_ ___
__ _| |_ _ ___| _ \_ _ _ _ ___ __ _ ___
/ _` | | || / -_) / || | ' \___/ _` / _ \
\__, |_|\_,_\___|_|_\\_,_|_||_| \__, \___/
|___/ |___/
Autonomous multi-agent orchestration for software repos. One engine, many consumers.
glueRun-go is a bash + Python orchestration engine that drives autonomous AI coding agents in parallel against a repository. It implements a three-tier scheduling model (L0 origin loop β L1 area planners β L2 worker agents) with durable leases, state packets, gate/audit pipelines, and git-worktree isolation. The engine is installed once per machine and pinned per consumer repo β improvements propagate by bumping a version pin, not by re-copying scripts.
| Tier | Role |
|---|---|
| L0 origin | |
| The single scheduler. Runs the reconcile cycle: import β recover β integrate β dispatch β snapshot. Holds the origin lock only during control work. | |
| L1 area planners | |
| One planner per DAG node (area). Reads the node's context, plans a batch of L2 tasks, and stages them as proposals for L0 to import. | |
| L2 workers | |
| Execute a single task in an isolated git worktree on a per-task branch. Produce a state packet (owned files, changes, evidence). An auditor reviews the packet; the decider routes the outcome. |
Each gluerun reconcile --actuate
runs:
Importβ pull staged L1 task proposals into the DAG under the origin lock.** Recover**β reclaim stale leases whose workers have exited or timed out.** Integrate**β merge completed worker branches into the target branch under the git-op lock.** Dispatch**β pre-lease frontier tasks and spawn L2 workers.** Snapshot**β write a human-readable project state snapshot.
Every in-flight task holds a lease (a JSON file in .gluerun-state/leases/
) that records
ownership, retry count, and expiry. When a worker finishes it writes a state packet
(state-packet.v0.schema.json
) enumerating owned files, changed files, commands, tests, and evidence. The auditor validates the packet; the reaper attributes outcomes on later cycles.
After each L2 worker run the host executes the configured gate command (e.g. npm test
).
A gate result (gate-result.v0.schema.json
) feeds the auditor model, which returns an
audit verdict (audit-verdict.v0.schema.json
). The decider maps the
(failure-class, retries-left)
pair to a recovery action β retry, amend-scope, escalate, or park β using a deterministic fast-path table before falling back to a model round-trip.
Detached dispatch is ON by default. When GLUERUN_DETACHED_DISPATCH=1
(the default),
reconcile
pre-leases each frontier task and spawns the worker in its own session via
dispatch-wrap.sh
, then returns within seconds. The origin lock is held only for the cycle's
control work. A reaper (gluerun_reap_dispatches
) runs at the top of every apply/actuate cycle and attributes completions, failures, and crashes by checking dispatch records + worker exit files (pid liveness defeats pid reuse; crash detection drops from the 60-min stale-lease window to ~one cycle).
This is what keeps import, integrate, recover, STATUS, and STOP responsive while long workers run in the background.
Set GLUERUN_DETACHED_DISPATCH=0
to restore the legacy synchronous batch path, where
reconcile
waits for every worker before returning.
Prerequisites:
- Bash >= 4,
python3
, andgit
. - At least one supported runner CLI on
PATH
(claude
,codex
, or another configured runner). - macOS users may need
brew install bash
and aPATH
entry that resolvesbash
to the Homebrew version before/bin/bash
.
git clone https://github.com/alex-reysa/glueRun-go /path/to/glueRun-go
cd /path/to/glueRun-go
bash install.sh
export PATH="$HOME/.gluerun/bin:$PATH"
In each consumer repo:
gluerun init # scaffold gluerun.config.json, docs/orchestration/, .gluerun-version
gluerun doctor # check deps, engine resolution, repo config
Each repo pins its engine version in .gluerun-version
(overrides gluerun.config.json
engineVersion
). The gluerun
launcher resolves that version from ~/.gluerun/versions/<ver>
,
binds GLUERUN_ROOT
to the current repo, loads its config, and execs the engine. Run
gluerun update <ver>
to repin.
gluerun reconcile --actuate
gluerun drive TASK-0001
gluerun auto
gluerun reconcile --drain
All per-repo variation lives in the consumer repo, never in engine files:
β declarative:gluerun.config.json
targetBranch
,gateCommand
,runner
,areas{}
,areaPrefix
,prewarm
,modules[]
,identity{}
,env{}
,provisionFiles[]
,envAllowlist[]
.β optional shell extras (computed values, functions).gluerun.config.sh
β gitignored operator overrides and secrets..gluerun-state/config.local.sh
The starter config deliberately sets gateCommand
to false
so a newly scaffolded repo fails closed until you replace it with the command that proves the repo is healthy.
provisionFiles
entries copy repo-local, gitignored files into each worker
worktree after git worktree add
: { "source": ".env.local", "target": ".env.local", "required": true }
. The source and target must both be ignored
or provisioning fails closed. envAllowlist
accepts exact env names or prefix
patterns ending in *
; allowed values are written to
worktree/.gluerun-state/worktree-env.sh
and sourced for prewarm/gate phases.
| Env knob | Default | Effect |
|---|---|---|
GLUERUN_MAX_CONCURRENT |
||
5 |
||
| Maximum L2 workers running concurrently. | ||
GLUERUN_MAX_DISPATCH |
||
5 |
||
| Maximum tasks dispatched per reconcile cycle. | ||
GLUERUN_DETACHED_DISPATCH |
||
1 |
||
Default ON. Reconcile spawns workers in their own session and returns in seconds; the reaper attributes outcomes on later cycles. Set 0 for the legacy synchronous batch wait. |
||
GLUERUN_AUTO_INTEGRATE |
||
1 |
||
Automatically integrate (merge) completed worker branches in direct reconcile --actuate , gluerun auto , launchd, and console-driven cycles. |
||
GLUERUN_PUSH |
||
0 direct / 1 auto |
||
Push integrated branches to the remote. Direct engine commands default local-only; gluerun auto /launchd set 1 unless overridden. |
||
GLUERUN_MAX_HOURS |
||
12 |
||
Wall-clock budget for the autonomy loop (gluerun auto ). |
||
GLUERUN_MAX_RETRIES |
||
3 |
||
| Per-task worker retries before the decider escalates. | ||
GLUERUN_STALE_MINUTES |
||
60 |
||
| Lease age (minutes) before a task without a live dispatch pid is reclaimed by the reaper. | ||
GLUERUN_TARGET_BRANCH |
||
| (required) | ||
| Integration target branch in the consumer repo. | ||
GLUERUN_SESSION_AFFINITY |
||
1 |
||
Reuse a role's prior runtime session when all staleness gates pass; 0 always runs fresh. |
||
GLUERUN_FIX_PROMPT_STRUCTURED |
||
1 |
||
Structured fix prompt on retries (authoritative findings); 0 = legacy fix_hints tail. |
||
GLUERUN_DECIDER_FAST |
||
1 |
||
Resolve clear-cut failure classes by host policy table; 0 routes every failure through the model decider. |
||
GLUERUN_WORKER_INFRA_MAX |
||
1 |
||
Extra worker re-runs on an infra failure before surfacing worker-infra . |
||
GLUERUN_AUDIT_INFRA_MAX |
||
2 |
||
Extra auditor re-runs on an infra failure before surfacing audit-infra . |
||
GLUERUN_CONTEXT_SECTION_MAX_CHARS |
||
4000 |
||
| Per-section cap on continuity content appended to prompts. | ||
GLUERUN_PREFLIGHT_REQUIRE_ACCEPTANCE |
||
1 |
||
Preflight requires non-empty acceptanceCriteria on a task. |
Between retry attempts glueRun-go carries authoritative state forward rather than re-deriving it from a log tail:
Context capsulesβ hash-stampedimplementer-capsule.json
andreviewer-capsule.json
per attempt.Findings ledgerβfindings-status.json
upserted from each audit verdict, with stable finding ids tracked open/resolved across retries.Structured fix promptsβ the worker receives authoritative open findings on retry (setGLUERUN_FIX_PROMPT_STRUCTURED=0
to revert to the legacy byte-tail).Re-audit delta promptsβ the auditor receives prior findings + fix diff + per-id verification targets.** Attempt archive**β each attempt's artifacts are copied (never moved) underruns/<id>/attempts/<n>/
with anattempts/index.json
.
Optional role-keyed runtime session resume (codex exec resume
, claude -r
) behind
10 staleness gates, defaulting ON (GLUERUN_SESSION_AFFINITY=1
). Any gate failure or runner that refuses the resume degrades silently to a fresh run within the same attempt.
Invariant:session resume is a token-cost optimization that never changes a task outcome.
The generic engine/
references zero project-specific symbols β enforced by
tests/test-engine-clean.sh
(the abstraction gate test). All per-project logic lives in opt-in modules:
gluerun-ext/
storage-proof.sh # example: durable-proof regime
promote-gate.sh # example: gate promoter
Modules are listed in gluerun.config.json
β modules[]
. A repo that doesn't list them
never loads them. The GLUERUN_MODULES
env var is the runtime list (set by the JSON config ).
Two versions move independently:
Engine pinβ.gluerun-version
is the canonical per-repo pin (overridesgluerun.config.json
engineVersion
; if they disagree.gluerun-version
wins andgluerun doctor
warns).gluerun update <ver>
rewrites it.SchemaβSCHEMA_VERSION
(repo root) holds the data-contract version (v1
today). A repo records the schema it was scaffolded against ingluerun.config.json
βschemaVersion
.gluerun doctor
fails on a schema mismatch;gluerun migrate
runs the shippedmigrations/<from>-to-<to>.sh
chain and rewritesschemaVersion
. All runtime JSON schema identifiers follow the namespacegluerun.orchestration.*.v0
.
bash tests/run.sh # 23 regression tests
The test suite uses no live state β all fixtures use a generic layer vocabulary. The
tests/test-engine-clean.sh
gate enforces the abstraction contract on engine/
.
Run bash tests/run.sh
before opening a PR. Keep engine/
generic: project-specific
rules belong in opt-in modules under gluerun-ext/
or in a consumer repo's config.
Do not commit .gluerun-state/
, .worktrees/
, .gluerun-evidence/
, local env files, or generated run artifacts.
glueRun-go executes repo-configured shell commands and launches local coding
agents in git worktrees. Review gluerun.config.json
, gluerun.config.sh
, and task files before running it in an untrusted repo. Report vulnerabilities through GitHub's private vulnerability reporting for this repository; if that is unavailable, open a minimal public issue asking for a private channel and do not include exploit details.
Licensed under GPL-3.0 β see LICENSE.