{"slug": "show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code", "title": "Show HN: Git worktrees and evidence gates for Codex and Claude Code", "summary": "Developer Alex Reysa released glueRun-go, an open-source orchestration engine that runs autonomous AI coding agents in parallel against software repositories using a three-tier scheduling model with git-worktree isolation. The tool supports Claude and Codex agents, implementing durable leases, state packets, and gate/audit pipelines to manage multi-agent coding workflows. It aims to improve developer productivity by enabling safe parallel AI-driven code generation and testing.", "body_md": "\n\n```\n      _          ___\n __ _| |_  _ ___| _ \\_  _ _ _ ___ __ _ ___\n/ _` | | || / -_)   / || | ' \\___/ _` / _ \\\n\\__, |_|\\_,_\\___|_|_\\\\_,_|_||_|  \\__, \\___/\n|___/                            |___/\n```\n\n**Autonomous multi-agent orchestration for software repos. One engine, many consumers.**\n\nglueRun-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.\n\n| Tier | Role |\n|---|---|\nL0 origin |\nThe single scheduler. Runs the reconcile cycle: import → recover → integrate → dispatch → snapshot. Holds the origin lock only during control work. |\nL1 area planners |\nOne 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. |\nL2 workers |\nExecute 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. |\n\nEach `gluerun reconcile --actuate`\n\nruns:\n\n**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.\n\nEvery in-flight task holds a **lease** (a JSON file in `.gluerun-state/leases/`\n\n) that records\nownership, retry count, and expiry. When a worker finishes it writes a **state packet**\n(`state-packet.v0.schema.json`\n\n) enumerating owned files, changed files, commands, tests, and\nevidence. The auditor validates the packet; the reaper attributes outcomes on later cycles.\n\nAfter each L2 worker run the host executes the configured **gate command** (e.g. `npm test`\n\n).\nA gate result (`gate-result.v0.schema.json`\n\n) feeds the **auditor** model, which returns an\naudit verdict (`audit-verdict.v0.schema.json`\n\n). The **decider** maps the\n`(failure-class, retries-left)`\n\npair to a recovery action — retry, amend-scope, escalate, or\npark — using a deterministic fast-path table before falling back to a model round-trip.\n\n**Detached dispatch is ON by default.** When `GLUERUN_DETACHED_DISPATCH=1`\n\n(the default),\n`reconcile`\n\npre-leases each frontier task and spawns the worker in its own session via\n`dispatch-wrap.sh`\n\n, then returns within seconds. The origin lock is held only for the cycle's\ncontrol work. A **reaper** (`gluerun_reap_dispatches`\n\n) runs at the top of every\napply/actuate cycle and attributes completions, failures, and crashes by checking dispatch\nrecords + worker exit files (pid liveness defeats pid reuse; crash detection drops from the\n60-min stale-lease window to ~one cycle).\n\nThis is what keeps import, integrate, recover, STATUS, and STOP responsive while long workers run in the background.\n\nSet `GLUERUN_DETACHED_DISPATCH=0`\n\nto restore the legacy synchronous batch path, where\n`reconcile`\n\nwaits for every worker before returning.\n\nPrerequisites:\n\n- Bash >= 4,\n`python3`\n\n, and`git`\n\n. - At least one supported runner CLI on\n`PATH`\n\n(`claude`\n\n,`codex`\n\n, or another configured runner). - macOS users may need\n`brew install bash`\n\nand a`PATH`\n\nentry that resolves`bash`\n\nto the Homebrew version before`/bin/bash`\n\n.\n\n```\n# Clone and install the engine to ~/.gluerun\ngit clone https://github.com/alex-reysa/glueRun-go /path/to/glueRun-go\ncd /path/to/glueRun-go\nbash install.sh\n# -> ~/.gluerun/versions/<ver>/  ~/.gluerun/current  ~/.gluerun/bin/gluerun\n\nexport PATH=\"$HOME/.gluerun/bin:$PATH\"\n```\n\nIn each consumer repo:\n\n```\ngluerun init      # scaffold gluerun.config.json, docs/orchestration/, .gluerun-version\ngluerun doctor    # check deps, engine resolution, repo config\n```\n\nEach repo pins its engine version in `.gluerun-version`\n\n(overrides `gluerun.config.json`\n\n`engineVersion`\n\n). The `gluerun`\n\nlauncher resolves that version from `~/.gluerun/versions/<ver>`\n\n,\nbinds `GLUERUN_ROOT`\n\nto the current repo, loads its config, and execs the engine. Run\n`gluerun update <ver>`\n\nto repin.\n\n```\n# Run one reconcile/actuate cycle (import → recover → integrate → dispatch → snapshot)\ngluerun reconcile --actuate\n\n# Drive a single task through L1 → L2 → audit\ngluerun drive TASK-0001\n\n# Self-driving autonomy loop (wall-clock budget: GLUERUN_MAX_HOURS)\ngluerun auto\n\n# Block until all detached workers finish (useful in CI or clean shutdown)\ngluerun reconcile --drain\n```\n\nAll per-repo variation lives in the consumer repo, never in engine files:\n\n— declarative:`gluerun.config.json`\n\n`targetBranch`\n\n,`gateCommand`\n\n,`runner`\n\n,`areas{}`\n\n,`areaPrefix`\n\n,`prewarm`\n\n,`modules[]`\n\n,`identity{}`\n\n,`env{}`\n\n,`provisionFiles[]`\n\n,`envAllowlist[]`\n\n.— optional shell extras (computed values, functions).`gluerun.config.sh`\n\n— gitignored operator overrides and secrets.`.gluerun-state/config.local.sh`\n\nThe starter config deliberately sets `gateCommand`\n\nto `false`\n\nso a newly\nscaffolded repo fails closed until you replace it with the command that proves\nthe repo is healthy.\n\n`provisionFiles`\n\nentries copy repo-local, gitignored files into each worker\nworktree after `git worktree add`\n\n: `{ \"source\": \".env.local\", \"target\": \".env.local\", \"required\": true }`\n\n. The source and target must both be ignored\nor provisioning fails closed. `envAllowlist`\n\naccepts exact env names or prefix\npatterns ending in `*`\n\n; allowed values are written to\n`worktree/.gluerun-state/worktree-env.sh`\n\nand sourced for prewarm/gate phases.\n\n| Env knob | Default | Effect |\n|---|---|---|\n`GLUERUN_MAX_CONCURRENT` |\n`5` |\nMaximum L2 workers running concurrently. |\n`GLUERUN_MAX_DISPATCH` |\n`5` |\nMaximum tasks dispatched per reconcile cycle. |\n`GLUERUN_DETACHED_DISPATCH` |\n`1` |\nDefault 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. |\n`GLUERUN_AUTO_INTEGRATE` |\n`1` |\nAutomatically integrate (merge) completed worker branches in direct `reconcile --actuate` , `gluerun auto` , launchd, and console-driven cycles. |\n`GLUERUN_PUSH` |\n`0` direct / `1` auto |\nPush integrated branches to the remote. Direct engine commands default local-only; `gluerun auto` /launchd set `1` unless overridden. |\n`GLUERUN_MAX_HOURS` |\n`12` |\nWall-clock budget for the autonomy loop (`gluerun auto` ). |\n`GLUERUN_MAX_RETRIES` |\n`3` |\nPer-task worker retries before the decider escalates. |\n`GLUERUN_STALE_MINUTES` |\n`60` |\nLease age (minutes) before a task without a live dispatch pid is reclaimed by the reaper. |\n`GLUERUN_TARGET_BRANCH` |\n(required) |\nIntegration target branch in the consumer repo. |\n`GLUERUN_SESSION_AFFINITY` |\n`1` |\nReuse a role's prior runtime session when all staleness gates pass; `0` always runs fresh. |\n`GLUERUN_FIX_PROMPT_STRUCTURED` |\n`1` |\nStructured fix prompt on retries (authoritative findings); `0` = legacy `fix_hints` tail. |\n`GLUERUN_DECIDER_FAST` |\n`1` |\nResolve clear-cut failure classes by host policy table; `0` routes every failure through the model decider. |\n`GLUERUN_WORKER_INFRA_MAX` |\n`1` |\nExtra worker re-runs on an infra failure before surfacing `worker-infra` . |\n`GLUERUN_AUDIT_INFRA_MAX` |\n`2` |\nExtra auditor re-runs on an infra failure before surfacing `audit-infra` . |\n`GLUERUN_CONTEXT_SECTION_MAX_CHARS` |\n`4000` |\nPer-section cap on continuity content appended to prompts. |\n`GLUERUN_PREFLIGHT_REQUIRE_ACCEPTANCE` |\n`1` |\nPreflight requires non-empty `acceptanceCriteria` on a task. |\n\nBetween retry attempts glueRun-go carries authoritative state forward rather than re-deriving it from a log tail:\n\n**Context capsules**— hash-stamped`implementer-capsule.json`\n\nand`reviewer-capsule.json`\n\nper attempt.**Findings ledger**—`findings-status.json`\n\nupserted from each audit verdict, with stable finding ids tracked open/resolved across retries.**Structured fix prompts**— the worker receives authoritative open findings on retry (set`GLUERUN_FIX_PROMPT_STRUCTURED=0`\n\nto 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) under`runs/<id>/attempts/<n>/`\n\nwith an`attempts/index.json`\n\n.\n\nOptional role-keyed runtime session resume (`codex exec resume`\n\n, `claude -r`\n\n) behind\n10 staleness gates, defaulting ON (`GLUERUN_SESSION_AFFINITY=1`\n\n). Any gate failure or\nrunner that refuses the resume degrades silently to a fresh run within the same attempt.\n\nInvariant:session resume is a token-cost optimization that never changes a task outcome.\n\nThe generic `engine/`\n\nreferences **zero** project-specific symbols — enforced by\n`tests/test-engine-clean.sh`\n\n(the abstraction gate test). All per-project logic lives in\nopt-in modules:\n\n```\ngluerun-ext/\n  storage-proof.sh    # example: durable-proof regime\n  promote-gate.sh     # example: gate promoter\n```\n\nModules are listed in `gluerun.config.json`\n\n→ `modules[]`\n\n. A repo that doesn't list them\nnever loads them. The `GLUERUN_MODULES`\n\nenv var is the runtime list (set by the JSON\nconfig loader).\n\nTwo versions move independently:\n\n**Engine pin**—`.gluerun-version`\n\nis the canonical per-repo pin (overrides`gluerun.config.json`\n\n`engineVersion`\n\n; if they disagree`.gluerun-version`\n\nwins and`gluerun doctor`\n\nwarns).`gluerun update <ver>`\n\nrewrites it.**Schema**—`SCHEMA_VERSION`\n\n(repo root) holds the data-contract version (`v1`\n\ntoday). A repo records the schema it was scaffolded against in`gluerun.config.json`\n\n→`schemaVersion`\n\n.`gluerun doctor`\n\nfails on a schema mismatch;`gluerun migrate`\n\nruns the shipped`migrations/<from>-to-<to>.sh`\n\nchain and rewrites`schemaVersion`\n\n. All runtime JSON schema identifiers follow the namespace`gluerun.orchestration.*.v0`\n\n.\n\n```\nbash tests/run.sh    # 23 regression tests\n```\n\nThe test suite uses no live state — all fixtures use a generic layer vocabulary. The\n`tests/test-engine-clean.sh`\n\ngate enforces the abstraction contract on `engine/`\n\n.\n\nRun `bash tests/run.sh`\n\nbefore opening a PR. Keep `engine/`\n\ngeneric: project-specific\nrules belong in opt-in modules under `gluerun-ext/`\n\nor in a consumer repo's config.\nDo not commit `.gluerun-state/`\n\n, `.worktrees/`\n\n, `.gluerun-evidence/`\n\n, local env\nfiles, or generated run artifacts.\n\nglueRun-go executes repo-configured shell commands and launches local coding\nagents in git worktrees. Review `gluerun.config.json`\n\n, `gluerun.config.sh`\n\n, and\ntask files before running it in an untrusted repo. Report vulnerabilities through\nGitHub's private vulnerability reporting for this repository; if that is\nunavailable, open a minimal public issue asking for a private channel and do not\ninclude exploit details.\n\nLicensed under GPL-3.0 — see [LICENSE](/alex-reysa/glueRun-go/blob/main/LICENSE).", "url": "https://wpnews.pro/news/show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code", "canonical_source": "https://github.com/alex-reysa/glueRun-go", "published_at": "2026-06-19 18:07:11+00:00", "updated_at": "2026-06-19 18:37:52.974330+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["Alex Reysa", "glueRun-go", "Claude", "Codex", "Git"], "alternates": {"html": "https://wpnews.pro/news/show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code", "markdown": "https://wpnews.pro/news/show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code.md", "text": "https://wpnews.pro/news/show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code.txt", "jsonld": "https://wpnews.pro/news/show-hn-git-worktrees-and-evidence-gates-for-codex-and-claude-code.jsonld"}}