Skip to main content

Gitmoot v0.6.0

A large orchestration release. The Orchestra delegation engine gains an engine-level verify rule, structured upstream-dependency context, a mid-run human ask gate, and actionable preflight errors. The daemon gains an off-by-default outbound event stream, a host-global memory-aware admission budget, and discoverable same-repo parallel jobs. Runtimes now self-heal dead Claude sessions and fail closed on implement-without-write. Plus event-stream and home-resolution fixes found by a live end-to-end test.

What's new since v0.5.2

Orchestration engine — the delegations DAG

  • feat(workflow): engine-level verify synthesis_rule + bounded verify→replan (#439) — a new verify synthesis rule lets the engine itself derive a pass/fail verdict from a verification leg's children and, on failure, enqueue a bounded verify→replan corrective continuation instead of dead-ending. Bounded by a new [orchestrate].max_verify_replan_attempts cap (default 2); on exhaustion it routes to the graceful finalize continuation. The verify→replan loop is now enforced by the engine, not left to the coordinator.
  • feat(workflow): structured upstream-dependency context manifest (#438) — deps[] dataflow now carries a structured manifest of upstream sibling results (decision, summary preview, changes count, PR link, artifact path, derived-from) into a child's prompt, instead of only inlined text — so a child can reference upstream outputs precisely. The manifest write is atomic (no torn reads under the parallel read-only fan-out).
  • feat(workflow): mid-run non-failure "ask" decision gate (#445) — a healthy job can return human_questions[] to pause the tree at awaiting_human without failing a leg; a human answers on the PR with /gitmoot resume <job> answer "<id>: ..." and the answer is injected into the coordinator continuation. It reuses the escalate_human pause + TTL machinery and is budget-neutral. (The answer resume verb sits alongside the existing retry/continue/abort.)
  • feat(workflow): actionable delegation preflight errors + corrective continuation (#451) — a fan-out that names a runtime instead of a registered agent no longer terminal-blocks the coordinator; it produces an actionable preflight error and a corrective continuation so the coordinator can fix and proceed. A delegation preflight failures: N line is surfaced in daemon status.

Daemon

  • feat(daemon): same-repo parallel jobs made discoverable (#444) — requesting multiple workers now actually delivers parallelism. --workers > 1 with an unset scheduler auto-selects --scheduler pool (a behavior change only when you asked for multiple workers; the single-worker default is unchanged, and explicit --scheduler barrier always forces the old per-tick behavior). A new --parallel N convenience flag sets workers + pool together. daemon status reports scheduler: <barrier|pool>, workers: <n>, and a preflight warning logs the exact relaunch command when ≥2 parallelizable jobs (distinct runtime sessions) meet a serializing config. A new "Run jobs in parallel on a repo" guide covers the two serialization layers (checkout lock + runtime:<runtime>:<ref> session lock).
  • feat(daemon): host-global, memory-aware admission budget (off by default) (#365) — an opt-in [admission] budget caps total in-flight agent sessions and the summed per-runtime RAM estimate across all repos in the daemon process, on top of --workers/scheduler and the per-repo locks. A job is admitted only if it fits both caps; one that doesn't is left queued and retried, never failed. Both caps default to 0 (disabled) — scheduling is byte-identical to no [admission] section.

Outbound events

  • feat(events): off-by-default outbound event stream + EventSink seam (#446) — a stable, versioned JSON event contract (job.finished / job.failed / job.blocked / job.needs_attention) emitted over a webhook when [events].webhook_url is set. Off by default, best-effort (a slow or dead consumer never blocks or fails a job), with secret + absolute-path redaction. Closes the "local-only, no remote control plane" gap — a Telegram/herdr bridge, dashboard, or future mobile monitor can subscribe without polling. (The ask-gate pause above rides this as a job.needs_attention event.)

Runtimes & sessions

  • feat(runtime): self-heal dead Claude --resume sessions (#443) — a background agent pinned to a Claude conversation UUID that died on a runtime restart used to fail instantly, before any work, with an opaque delivery failed error that read like broken auth. It now self-heals with a single bounded retry on a fresh session instead of dead-ending.
  • feat(cli,runtime): fail closed on implement without a write policy (#452) — an agent (or ephemeral worker) carrying the implement capability while its autonomy policy grants no headless write (auto/empty or read-only) is now refused early with actionable guidance instead of running a whole job and silently writing nothing. The check fires at agent start, agent subscribe, implement-job dispatch, and ephemeral delegation specs. The docs now carry the full policy → --permission-mode mapping.

Fixes

  • fix(events): the event stream now actually fires (#458) — the daemon double-resolved the [events] config home (reading a phantom .gitmoot/.gitmoot/config.toml), so the stream silently never emitted even when configured. Now resolved robustly for both daemon home shapes, side-effect-free. Found by a live end-to-end test (the unit tests had mocked the sink and missed it).
  • fix(daemon): no more phantom .gitmoot/.gitmoot (#459) — the registered-repo supervisor reused the resolved home for two raw---home helpers (resolveEscalationTTL and the supervisor worker's policy read), whose initialization created a doubled home directory. The home convention is normalized and resolveEscalationTTL is now side-effect-free (reads config, never initializes).

Upgrade notes

Two opt-in behavior changes, and only when you've asked for them:

  • --workers > 1 now auto-selects --scheduler pool (#444). If you run the daemon with multiple workers and rely on barrier semantics, add an explicit --scheduler barrier to keep the old behavior.
  • implement + a non-write policy is now refused (#452) with actionable guidance. Use --policy danger-full-access for a full headless implement (file writes plus go/git/gh via Bash) or --policy workspace-write for edits-only (note: workspace-write maps to Claude acceptEdits, which does not unblock Bash). read-only/ask/review agents are unaffected.

Install / upgrade

  • Existing install: gitmoot update
  • Fresh install: curl -fsSL https://gitmoot.io/install.sh | sh