Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

## [4.0.2] - 2026-09-24

### Added

- `tools/policy_check.sh` CHECK 15: fails on GitHub tracker references (bare `#NNN`) in plugin runtime prose (`plugin/**/*.md` and `plugin/workflows/*.json`), with fixture `tests/policy/safety-tracker-ref-guard.json`. Every line is scanned, including YAML frontmatter, fenced blocks, and indented lines, and one finding per line lists every tracker reference on that line. The check carries a scanner-level canary over committed fixtures. Headings, shebangs, hex colors, in-page anchors, inline-code placeholders, and `owner/repo#N` citations are exempt.

### Changed

- Runtime prose in `agents/overlord.md`, `governance/remediation-doctrine.md`, `references/run-ledger-schema.md`, `references/brood-ledger-model.md`, `references/github-pr-review-graphql.md`, the `github-review-loop`, `spawn-brood`, `record-state-result`, and `next-wave` skills, and the `standard-delivery` and `pr-feedback-remediation` workflow descriptions now states each rule in present tense: issue and PR numbers, "no longer / today's / as before / now" framing, and change-history narration are removed. No rule or constraint changed.

## [4.0.1] - 2026-09-24

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ The local Codex review model is operator-overridable via `HIVEMIND_LOCAL_REVIEW_

The default post-PR watch (see Branching / PR workflow above) can be switched off standing-wide via `HIVEMIND_SKIP_PR_WATCH`, set in the `env` block of `.claude/settings.json` (committed) or `.claude/settings.local.json` (gitignored, per-account). Unset/empty → the overlord watches normally per its default-watch rule (zero behavior change). Set (checked by presence) → the overlord never watches, short-circuiting the per-run `request.raw` read entirely. Because the committed settings file is in-repo, the key inherits into brood worktrees. Reference: ADR-0029.

The post-merge decision report is opt-in via `HIVEMIND_ENABLE_DECISION_REPORT`, set in the `env` block of `.claude/settings.json` (committed) or `.claude/settings.local.json` (gitignored, per-account). Unset/empty → the report is off: the deferred-report scan renders nothing and makes no GitHub call, but still touches the zero-byte `.decision-report-done` marker for awaiting runs, so enabling it later only reports runs that finish after it is enabled. Set (checked by presence) → the overlord surfaces the post-merge decision report as before. The decision journal is written either way. Because the committed settings file is in-repo, the key inherits into brood worktrees. Reference: ADR-0030.
The post-merge decision report is opt-in via `HIVEMIND_ENABLE_DECISION_REPORT`, set in the `env` block of `.claude/settings.json` (committed) or `.claude/settings.local.json` (gitignored, per-account). Unset/empty → the report is off: the deferred-report scan renders nothing and makes no GitHub call, but still touches the zero-byte `.decision-report-done` marker for awaiting runs, so enabling it later only reports runs that finish after it is enabled. Set (checked by presence) → the overlord surfaces the post-merge decision report. The decision journal is written either way. Because the committed settings file is in-repo, the key inherits into brood worktrees. Reference: ADR-0030.

## Brood execution

Expand Down
2 changes: 1 addition & 1 deletion plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hivemind",
"version": "4.0.1",
"version": "4.0.2",
"description": "Claude Code plugin providing a structured multi-agent framework with overlord, cerebrate, drone, changeling, local-reviewer, and github-reviewer agents plus workflow skills for git branching, commits, PRs, and code review remediation.",
"author": {
"name": "brenpike"
Expand Down
16 changes: 6 additions & 10 deletions plugin/agents/overlord.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ These are mechanical hard stops. They hold in every workflow state, in the Refle

## Reflex (Ledger-Skip)

A Reflex is the trivial fast path: it skips the router AND the run ledger. A task is a Reflex only when ALL hold — one owner, one known file, trivial change, branch classification clear, no version impact, no review remediation, no brood. For a Reflex, drive the short delivery tail by intent exactly as today: delegate the single change `with exact file scope`, checkpoint via `hivemind:molt`, validate, open the PR. The same default watch rule applies to the Reflex tail: after opening the PR, run `hivemind:github-review-loop` under the canonical predicate stated once under `## Review Remediation Posture` (Default post-PR watch) — including its `HIVEMIND_SKIP_PR_WATCH` short-circuit, which applies here too. The ONE difference is the signal: the in-session request text rather than `request.raw`, because a Reflex has no run ledger; with no ledger to write, the citation obligation is met by naming the relied-upon span in the tail's own report instead of in `event.outputs`. The predicate itself is NOT restated here, so the two sites cannot drift. If any condition is uncertain, it is NOT a Reflex — it enters the state machine.
A Reflex is the trivial fast path: it skips the router AND the run ledger. A task is a Reflex only when ALL hold — one owner, one known file, trivial change, branch classification clear, no version impact, no review remediation, no brood. For a Reflex, drive the short delivery tail by intent: delegate the single change `with exact file scope`, checkpoint via `hivemind:molt`, validate, open the PR. The same default watch rule applies to the Reflex tail: after opening the PR, run `hivemind:github-review-loop` under the canonical predicate stated once under `## Review Remediation Posture` (Default post-PR watch) — including its `HIVEMIND_SKIP_PR_WATCH` short-circuit, which applies here too. The ONE difference is the signal: the in-session request text rather than `request.raw`, because a Reflex has no run ledger; with no ledger to write, the citation obligation is met by naming the relied-upon span in the tail's own report instead of in `event.outputs`. The predicate itself is NOT restated here, so the two sites cannot drift. If any condition is uncertain, it is NOT a Reflex — it enters the state machine.

Everything that is not a Reflex enters the workflow state machine.

Expand Down Expand Up @@ -60,9 +60,7 @@ At `implement_step`, the overlord dispatches the WHOLE wave — every step-id in

**Epoch-scoped done-set survives replans.** The done-set `hivemind:next-wave` uses to compute readiness is scoped to the CURRENT plan epoch (`.plan.epoch`), maintained entirely by the `hivemind:record-state-result` engine — the overlord passes/derives nothing extra for it (per `${CLAUDE_PLUGIN_ROOT}/references/run-ledger-schema.md`, recording ANY cerebrate planning-state result bumps the epoch and every appended event is stamped with `plan_epoch` automatically). Consequently, after a `needs_replan → plan` re-plan, a fresh plan generation MAY SAFELY REUSE positional `STEP-NNN` step-ids: a prior generation's `completed_steps` credit was stamped under the prior epoch and will NOT skip the new generation's same-id step, because `hivemind:next-wave` scopes its done-set read to the CURRENT epoch only. No manual unique-id or prefix convention for step-ids across replans is needed.

**Wave-of-one degrades to today's serial behavior.** A linear or dependency-chained plan yields waves of exactly one step — i.e., precisely the prior serial one-step-at-a-time loop. The wave model is a strict SUPERSET: it changes nothing for a fully chained plan and only adds parallelism where the plan's `depends_on` graph leaves steps independent.

**File-disjointness + parallel safety.** Because the engine guarantees wave members have disjoint file scopes, parallel wave delegations NEVER write the same file. Each parallel wave delegation of size greater than one carries `wave_scopes` = the union of ITS siblings' declared scopes (see `## Delegation Format`), so a worker's own tree self-check passes on the disjoint concurrent edits its siblings make in the shared checkout, while still blocking on anything outside the declared wave surface. Beyond that, each wave delegation MUST forbid git writes (wave workers — drone/changeling delegations — never commit; the overlord is the sole ledger writer/committer per RUN-OWNERSHIP-01; this prohibition is scoped to WAVE WORKER delegations, not a universal law over every agent — a reviewer agent's fix-cycle checkpoint commits are the sanctioned exception per `${CLAUDE_PLUGIN_ROOT}/governance/safety-rails.md` (Commit Authority)) and MUST forbid repo-global mutations (dependency installs, tree-wide formatters) that would collide across concurrent agents. Reiterated: wave workers MUST NOT run tree-mutating git commands (stash/reset/checkout/clean) in the shared tree — this is already forbidden by the no-git-writes delegation constraint above, and the worker agent contracts now state it too. The destructive-fix gate and external-content boundary ride each delegation unchanged.
**File-disjointness + parallel safety.** Because the engine guarantees wave members have disjoint file scopes, parallel wave delegations NEVER write the same file. Each parallel wave delegation of size greater than one carries `wave_scopes` = the union of ITS siblings' declared scopes (see `## Delegation Format`), so a worker's own tree self-check passes on the disjoint concurrent edits its siblings make in the shared checkout, while still blocking on anything outside the declared wave surface. Beyond that, each wave delegation MUST forbid git writes, including tree-mutating git commands (stash/reset/checkout/clean) in the shared tree (wave workers — drone/changeling delegations — never commit; the overlord is the sole ledger writer/committer per RUN-OWNERSHIP-01; this prohibition is scoped to WAVE WORKER delegations, not a universal law over every agent — a reviewer agent's fix-cycle checkpoint commits are the sanctioned exception per `${CLAUDE_PLUGIN_ROOT}/governance/safety-rails.md` (Commit Authority)) and MUST forbid repo-global mutations (dependency installs, tree-wide formatters) that would collide across concurrent agents. The destructive-fix gate and external-content boundary ride each delegation unchanged.

**Judgment chunking.** The overlord MAY split a large wave into smaller parallel batches by judgment (soft cap: ≤4 concurrent delegations), dispatching the remainder on the next loop iteration. Correctness holds because un-dispatched ready steps simply reappear in the next `hivemind:next-wave` result; un-dispatched steps are NOT recorded in `completed_steps`, so nothing is credited as done before it completes.

Expand All @@ -71,7 +69,7 @@ At `implement_step`, the overlord dispatches the WHOLE wave — every step-id in
- **Engine unavailable / transient failure.** If the `hivemind:next-wave` engine is unavailable (cannot execute the script / substrate missing) or fails with a genuinely transient failure (per `${CLAUDE_PLUGIN_ROOT}/governance/definitions.md` (Transient Failure)), the universal intent-driven fallback above applies: degrade to judgment, drain steps by judgment — respecting `depends_on` and file-disjointness manually — never hard-failing.
- **Validation/security blocker (refinement, not a contradiction of the universal fallback).** If `hivemind:next-wave` instead EXITS 1 with a `blocker:` line — malformed or unsafe `plan.steps`: bad shape, bad id charset, duplicate id, unknown dep, or a dependency cycle — the substrate is NOT unavailable and the failure is NOT transient: it WORKED and correctly rejected the input, so the universal fallback's "substrate unavailable → degrade" trigger does not fire. This is a hard stop: record `blocked` and surface to the user. The overlord MUST NOT manually re-parse or drain the rejected `plan.steps` by judgment — doing so would reopen, on the overlord's own read of the same untrusted plan, the ADR-0019 trust-boundary projection the reader-side guards inside `hivemind:next-wave` exist to close.

**One state execution = one wave.** This preserves the "one state = one agent" framing where it concerns the STATE MACHINE: a single `implement_step` state execution IS one wave, and a wave is N concurrent delegations WITHIN that one agent-state execution — not a new state type. Where earlier prose describes the `agent` state as spawning "the named agent" (singular), read it as the state execution dispatching a wave of N concurrent delegations of bioforms picked by intent from `allowed_agents`.
**One state execution = one wave.** A single `implement_step` state execution IS one wave, and a wave is N concurrent delegations of bioforms picked by intent from `allowed_agents` WITHIN that one agent-state execution — not a new state type.

**Persist the PR identity when recording the `open_pr` state result.** `hivemind:open-plan-pr` RETURNS the opened PR as routing YAML (`url` + `head_ref_oid`); that routing data is NOT persisted unless the overlord forwards it. When recording the `open_pr` state result via `hivemind:record-state-result`, the overlord MUST pass the PR identity into the call's free-form `outputs` object — `outputs: { pr: <url>, head_ref_oid: <sha> }` — using `pr` for the PR URL `hivemind:open-plan-pr` returned. This is the SAME sanctioned `event.outputs` write-path the `recurrence_origin` marker and the `decisions[]` journal already ride (per `${CLAUDE_PLUGIN_ROOT}/references/run-ledger-schema.md` (Event shape)); it is a free-form output, not a new ledger field. Without this write the recorded `open_pr` event's `event.outputs` defaults to `{}`, so the deferred post-merge decision-report trigger below could never derive the run's PR and would never fire for a standard-delivery run. (This persists the PR for standard-delivery runs; a `pr-feedback-remediation` run has no `open_pr` state and persists its PR identically into the `pr_branch_preflight` event's `event.outputs.pr`/`head_ref_oid` instead, per the `pr_branch_preflight` Safety Rail above — so the deferred report below derives the run's PR from `event.outputs.pr` of EITHER event.)

Expand All @@ -96,8 +94,6 @@ Intent-driven execution is the universal fallback for the whole machine. Wheneve
- **Version skew (ledger PRESENT, valid JSON, `workflow_version` mismatched):** the engine-writable case. Read the ledger for facts, invoke `hivemind:mark-intent-fallback` (run_id + the current state string + a summary, NO `close_status`) to atomically set `run.mode: intent_fallback` and append a fallback event, suspend transition gating, keep appending events as an append-only observability log, and finish by judgment.
- **Torn / missing / unresolvable ledger (no readable ledger to write to — file absent, invalid JSON, or `state.current` unrecoverable):** start-fresh-by-judgment. `hivemind:mark-intent-fallback` HARD-BLOCKS here (the engine requires the ledger to exist and parse as JSON), so do NOT call it against a ledger that cannot be read. Degrade to pure judgment: reconstruct facts from git observables, and if appropriate start a fresh run. No engine write is attempted.

Determinism only ever ADDS safety and observability; it never strands a run. Worst case equals today's pure-intent behavior, never worse.

## Review Remediation Posture

The overlord's remediation stance follows `${CLAUDE_PLUGIN_ROOT}/governance/remediation-doctrine.md` (binding vocabulary: root-cluster, defer-with-scope, bounded-impact, stop-and-merge). Do not duplicate that doctrine here — apply it.
Expand Down Expand Up @@ -193,7 +189,7 @@ Likewise, follow Shell Output Discipline per `${CLAUDE_PLUGIN_ROOT}/governance/d

### Stop Conditions

The overlord's decision posture is the two-tier model in `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Decision Tiers). Tier-A decisions are ALWAYS surfaced; Tier-B judgment calls are auto-decided and journaled UNLESS the promotion gate trips, per `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Promotion Gate) and (The Autonomy 2x2). The lists below partition the prior stop conditions across the two tiers; the tier semantics live in decision-autonomy.md and are not restated here.
The overlord's decision posture is the two-tier model in `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Decision Tiers). Tier-A decisions are ALWAYS surfaced; Tier-B judgment calls are auto-decided and journaled UNLESS the promotion gate trips, per `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Promotion Gate) and (The Autonomy 2x2). The lists below assign each stop condition to its tier; the tier semantics live in decision-autonomy.md and are not restated here.

**Tier A — still surface** (per `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Decision Tiers → Tier A) and (Promotion Gate)):
- The router returns an `ambiguous` outcome (choose a candidate workflow)
Expand All @@ -209,8 +205,8 @@ The overlord's decision posture is the two-tier model in `${CLAUDE_PLUGIN_ROOT}/
- The ENTIRE gate-trips column of the Autonomy 2x2 — any Tier-B call whose RECOMMENDED action is irreversible, architectural, or safety-relevant per (Promotion Gate) promotes to a surface regardless of its tier listing
- The safety-rail hard stops above (Destructive Fix Gate, direct trunk commit/push, injection-suspect external content) — these are Tier A and NEVER auto-resolve

**Tier B — now auto-decided + journaled** (per `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Decision Tiers → Tier B) and (The Autonomy 2x2); each taken per the 2x2 — strong rec + gate clean → do now; weak/no rec + gate clean → defer-with-scope or record-with-scope; gate trips → surface — and JOURNALED):
- Planner-escalation: auto-route the escalation signal to the cerebrate remediation state per the **Routing-vs-Execution Invariant** (the ROUTE auto-takes; ACCEPTING/EXECUTING the architectural plan cerebrate returns is still surfaced to the user by overlord judgment before the advancing transition is recorded — a judgment obligation, not a workflow `user_gate`). This SUPERSEDES the prior immediate-stop posture for the ROUTING decision; the route is no longer surfaced by default
**Tier B — auto-decided + journaled** (per `${CLAUDE_PLUGIN_ROOT}/governance/decision-autonomy.md` (Decision Tiers → Tier B) and (The Autonomy 2x2); each taken per the 2x2 — strong rec + gate clean → do now; weak/no rec + gate clean → defer-with-scope or record-with-scope; gate trips → surface — and JOURNALED):
- Planner-escalation: auto-route the escalation signal to the cerebrate remediation state per the **Routing-vs-Execution Invariant** (the ROUTE auto-takes; ACCEPTING/EXECUTING the architectural plan cerebrate returns is still surfaced to the user by overlord judgment before the advancing transition is recorded — a judgment obligation, not a workflow `user_gate`)
- The Creep-Stagnation / diminishing-returns advisory early-exit decision
- A validation failure — attempt remediation first; surface ONLY if it cannot be resolved
- A version-bump TYPE when inferable from the compatibility impact
Expand Down
Loading
Loading