1054 Commits

Author SHA1 Message Date
Boden Fuller 0d366394cd fix(cli): restore trustworthy cmd/ao test floor + close the gate blindness that shipped it red
cmd/ao was deterministically RED under -shuffle (the order CI uses) from
process-global os.Chdir pollution. The local fast gate ran only *changed*
tests in -run isolation, so it structurally could not observe cross-test
pollution — red shipped to main across 281 commits. The membrane had a hole
in its own hull.

- migrate ~62 os.Chdir blocks in cli/cmd/ao + the internal/paths helper to
  t.Chdir (auto-restores, refuses t.Parallel); -302 net lines of boilerplate
- KEYSTONE: orchestrate_test.go did a non-restoring os.Chdir to the repo root
  — the actual deterministic shuffle leak the 62-block migration alone missed
- validate-go-fast.sh: force FULL-package + fixed -shuffle=1 for the
  isolation-sensitive cli/cmd/ao package (was -run-subset blind to pollution)
- promote go.test-isolation ratchet to Fast tier (ran Full-only, so it never
  fired pre-push) — aligns it with its home/test-home-isolation siblings
- lower BASELINE_CHDIR 137->7 (floor = intentional cwd-behavior tests)
- link behavior-first-planning.feature in its SKILL.md + mirror the codex twin
- fix(pawl gate): check-pawl-pre-push bead extraction swallowed a sentence-
  ending period (bead ids allow '.' for sub-ids), hunting for "<id>..json" and
  failing-closed on a normal commit message — strip trailing separators

cmd/ao now green under -race -shuffle=on. Closes age-cmd-ao-test-floor-hvb.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 19:58:43 -04:00
Boden Fuller 407d451b7c feat(codex): cross-runtime exemption + convert the remaining 6 twins (age-8wm)
The remaining 6 of the original 14 ref-dropping pointers legitimately document
NON-Codex runtimes, so the "0 Claude mentions" twin rule was wrong for them
(scrubbing "Claude" would gut the content). Adds a shared exemption list,
scripts/lint/codex-cross-runtime-skills.txt, honored by the generator AND the
gates:
- codex-sync: for listed skills, apply only the slash->$ rewrite; preserve
  runtime names/paths verbatim (Claude Code / ~/.claude stay accurate).
- validate-codex-runtime-sections: skip the no-Claude-mention scan for them.
- audit-codex-parity: skip CLAUDE_TOOL_NAMING for them.

Converts all 6 to self-contained (body + references now ship to Codex):
cass (parses Claude/Codex/Gemini logs), rch (Claude Code PreToolUse hook),
vibing-with-ntm (claude -p LAW-0 ban), agent-native (per-runtime paths),
cc-hooks (Claude Code hook system), agy-native (AGY/Gemini harness).

This completes age-8wm: all 14 pointer twins now self-contained. The 8 ordinary
ones convert clean (Codex-native); these 6 stay runtime-accurate via the
exemption. shellcheck clean; the 3 codex gates pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 19:01:01 -04:00
Boden Fuller 3d6eddf949 feat(codex): convert 8 ref-dropping pointer twins to self-contained (age-8wm)
Adds --force to codex-sync (scoped regenerate of existing twins; refuses
unscoped to protect the curated set) and fixes two transform bugs found in
review: the slash->$ regex was corrupting markdown PATHS (../foo/ -> ..$foo/),
and only references/scripts were copied (missing fixtures/ etc., breaking body
links). Now mirrors ALL source content except SKILL.md; catalog entries are
add-only so curated reasons aren't clobbered.

Converted 8 pointer twins to self-contained (body transformed runtime-native +
full references/scripts/fixtures mirrored) so Codex users get the real content
(installs ship skills-codex/ only): agent-mail, beads-br, beads-bv,
beads-workflow, dcg, ntm, reverse-engineer, toil-mining.

The other 6 of the original 14 are NOT auto-convertible — their docs legitimately
reference Claude tools/runtime, which the repo's own gates reject in a Codex doc:
cass + rch (Claude tool-naming "the Read tool"/"Bash tool" in references, fails
audit-codex-parity); cc-hooks, vibing-with-ntm, agy-native, agent-native (claude
-p / "the Claude path" etc., fails validate-codex-runtime-sections). They need a
manual Claude-term scrub (or bespoke classification) — tracked on age-8wm.

regen-all --check GREEN; acceptance test 15/15; shellcheck -S warning clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 17:46:58 -04:00
Boden Fuller 025b14c5a9 feat(codex): make codex-sync generate SELF-CONTAINED twins, not pointers (age-8wm)
Research (this session) established the runtime model: Codex installs ship
skills-codex/ ONLY (plugin.json "skills":"./skills-codex"; install-codex-plugin.sh
copies only skills-codex; install-codex.sh discards the source tarball). So a
pointer twin ("read skills/<name>/SKILL.md") dangles for real users — the twin
must be self-contained (AGENTS-CODEX.md).

codex-sync now generates a self-contained twin from source:
- SKILL.md = slim (name+description) frontmatter + source body transformed
  runtime-native: /<known-skill> -> $<known-skill>, ~/.claude -> ~/.codex,
  "Claude Code" -> "Codex".
- references/ + scripts/ copied byte-identical (lint scans only SKILL.md).
- Still missing-twin-only + idempotent; existing hand-tended twins untouched
  (converting all ~75 is a separate reviewed step; the 14 ref-dropping pointer
  twins tracked in age-8wm).

Acceptance test upgraded to assert self-containment: throwaway source skill WITH
a reference + transform cases -> twin carries body + reference, transforms
applied, content-divergence gate passes (15/15). shellcheck -S warning clean.
regen-all docs reconciled (pointer -> self-contained).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:55:45 -04:00
Boden Fuller b796d14ae6 feat(codex): generate parity_only twins from source — kill the hand-mirror whack-a-mole (age-codex-twin-generator-qlj)
scripts/codex-sync.sh authors the COMPLETE Codex twin for any source skill that
lacks one: a slim (name+description) frontmatter + a fixed pointer body naming
skills/<name>/SKILL.md as the source of truth, the prompt.md pointer template,
the per-skill marker, and all catalog surfaces, then fixes hashes. Because a
parity twin carries no source content beyond name+description, source body edits
never require a twin hand-edit — the divergence/parity/manifest/hash cascade that
made adding a skill cost ~5 serial codex-gate fixes is gone.

- Idempotent + append-only (no catalog re-sort → minimal diffs).
- bespoke twins are the opt-out: never generated or overwritten.
- Wired into regen-all.sh (generate step + --check drift step); stale
  "twins are MANUAL" note replaced.
- tests/scripts/test-codex-sync-generator.sh: self-cleaning L2 acceptance —
  throwaway source skill → generate → lint-clean, registered twin, gates pass,
  zero hand-edits (10/10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:27:32 -04:00
Boden Fuller e5d9fc8eca feat(skills): clear all 50 trigger-marker offenders + add skill.triggers gate
Every skill description now carries trigger markers (a Triggers: clause) so no skill
silently never-fires on the LLM router (rot had reached 68%). Hand-crafted triggers for
the 12 user-facing workflow skills (autodev, bootstrap, compile, crank, curate, discovery,
inject, orchestrate, release, rpi, using-atm, validate); description-derived for the long tail.

Add gate skill.triggers (scripts/validate-skill-triggers.sh -> scan_descriptions --strict;
blocking; Fast|Full; matches skills/**) so the rot cannot regrow. Closes defect 2 of
age-fix-skill-factory-mcc (defect 1 was a false alarm — the build-report schema exists).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:15:32 -04:00
Boden Fuller 88a4b80d54 feat(pawl): self-healing route — retry+engage sends, degraded-pane respawn+reroute, rate-limit handling (age-standing-pawl-service-ml8.3)
S3 of the standing pawl-service epic. route no longer dies on a flaky codex send (cod_send:
send + verify engagement via atm codex wait-goal-engaged, retry 3x, respawn on dead/usage-limit);
mid-route a degraded pane is respawned + re-routed ONCE so it cannot silently time out into a
false REFUTED. rotate_account opt-in (PAWL_AUTO_ROTATE; caam/claude-acct per TOOLS-TRUTH), guarded
with || true at call sites (it returns non-zero by design when not opted in; under set -e an
unprotected non-zero would abort the route).

Liveness (cod_dead) uses the DETERMINISTIC foreground-process signal (tmux pane_current_command:
shell => dead, codex binary => alive), NOT scraped scrollback text — text-scraping yielded a series
of false-alives (stale codex chrome above a shell prompt; a cwd path containing gpt-5) the pawl
refuter demonstrated across rounds. A source guard makes the helpers unit-testable;
tests/scripts/pawl-cod-dead.bats (7 cases) locks the classification + the rotate_account guard
contract. PROVEN LIVE: routes recovered from an injected shell-drop and a real usage-limit via
respawn+reroute. Timeout 200->320s. The pawl caught 3 real bugs here (false-dead, set-e abort,
text false-alive) — the gate working, not rubber-stamping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:05:05 -04:00
Boden Fuller 7a6aeea519 feat(pawl): deterministic single-push land — pawl-verdict.sh rebind + pawl-land.sh (age-standing-pawl-service-ml8.4)
S4 of the standing pawl-service epic. Removes the manual edge-commit dance behind a verdict-bound
push to main. Root cause (analysed, not assumed): the pre-push pawl gate checks ONLY
verdict.head_sha == the pushed head (stable local_sha); emit-verdict is idempotent and the ledger
edge need NOT be committed for the gate. A push fails iff the verdict points at a different commit
than HEAD — i.e. HEAD drifted since the review (a prior post-land-provenance-emit commit, or a
re-commit after routing). Committing the edge has NO fixed point (rebinding to the new head emits a
fresh edge → re-dirties forever), so the deterministic fix is to rebind the already-reviewed verdict
onto the exact pushed HEAD:
  - pawl-verdict.sh rebind <bead> <pr> --head SHA  — re-stamp head on a CONFIRMED verdict (refuters
    preserved, sensor re-fired); fail-closed on missing/non-CONFIRMED.
  - scripts/pawl-land.sh <bead> [pr]  — assert HEAD cites the bead, rebind verdict to HEAD, single push.
The ledger edge is left to post-land-provenance-emit (idempotent, trunk-bound); its working-tree churn
is absorbed by rebase.autoStash (age-uqj). Regression tests added (rebind re-stamps + preserves +
re-fires; refuses non-CONFIRMED/missing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 11:07:28 -04:00
Boden Fuller f79865e504 feat(pawl): standing cross-family pawl service — up/down/health/route (age-standing-pawl-service-ml8.2)
Encodes the manual opus+codex duel (dogfooded landing age-1vy + age-uqj) into a deterministic
lifecycle so the cross-family pawl is a SERVICE you route to, not a hand-spun codex-exec per bead:
  pawl up      spawn + readiness-gate the standing opus+codex session (idempotent; solves the boot race)
  pawl health  per-pane liveness/readiness probe
  pawl route   send a packet to BOTH panes via FILE REFERENCE (codex /goal 4000-char limit), poll for a
               per-route NONCE-tagged verdict, require BOTH CONFIRMED (fail-closed), record via pawl-verdict.sh
  pawl down    tear down, no orphan panes

Substantially delivers slices S1 (up/down) + S2 (route) + the health half of S3; ao pawl will wrap this
(CLI-for-deterministic). Self-validated: routed its OWN review through itself — opus + codex/gpt-5.5 both
CONFIRMED after the dogfood caught two real bugs first (stale-scrollback verdict capture -> per-route nonce;
set -euo pipefail aborting the poll on an empty grep -> verdict_of always returns 0).

Pawl: opus + codex both CONFIRMED via the standing pawl-service (self-review, multi-model).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 10:45:41 -04:00
Boden Fuller 4bb75bbcb7 fix(uqj): rebase.autoStash for dirty tracked runtime logs; document no-union rationale (age-uqj)
Tracked runtime audit logs (.agents/rpi/next-work.jsonl, .agents/findings/registry.jsonl,
docs/provenance/ledger.jsonl) get dirtied by tooling mid-session, so 'git pull --rebase'
repeatedly failed with 'unstaged changes' (and a stash-pop once left conflict markers in
the hash-chained ledger). Fix: install-pre-push-gate.sh (the fresh-clone setup) now sets
repo-local rebase.autoStash=true so rebase transparently stash+reapplies the dirty tree.
.gitattributes documents WHY these JSONL logs are deliberately NOT union-merged — next-work
is rewritten in place (markEntryConsumed/markItemConsumedOwned) and the ledger is a prev_hash
chain, so union would resurrect consumed work or break the chain; a real divergence must
surface as a conflict. Ledger emit/commit churn is tracked separately (age-standing-pawl-service-ml8.4).

Pawl: opus + codex/gpt-5.5 both CONFIRMED (v3) via the standing pawl-service. The pawl caught
two real defects across rounds — union-on-a-mutated-file (codex) and a stale union reference in
the installer comment (opus) — both fixed before CONFIRMED.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 10:29:02 -04:00
Boden Fuller e477c63548 test(dynamo-e2e): prove the attempt-ordering rework join, not just a phase label (age-vx0)
The rework dynamo-e2e demonstrated L>0 via an EXPLICIT phase=rework row — the
attempt-ordering rework join (the actual cleverness, where attempt-1 spend before
the accepting attempt is classified rework by usageAttempt) never fired. Worse,
the scenario's attempt-1 700-token spend was emitted AFTER its own REFUTE verdict,
so usageAttempt attributed it FORWARD to attempt-2 and it read Productive. The
e2e proved a phase label works, not the ordering mechanism.

- New `rework-order` scenario: attempt-1 production is emitted BEFORE its verdict
  (realistic order), so the 700-token spend maps to attempt-1 (< accepting
  attempt-2) and is classified rework SOLELY by the ordering join — no phase
  label anywhere. Verified live: L breakdown rework=700 productive=500, L=0.583.
- Tightened bats: asserts rework=700 / productive=500 (the ordering join fired).
- Fixed the existing `rework` scenario's comment to be honest — its loss is the
  phase=rework label (rework=500); its attempt-1 700 spend reads Productive
  (post-verdict emit order attributes it forward). Both paths now have coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 22:04:03 -04:00
Boden Fuller 395473e9f3 fix(pawl): multi-model mode enforces the fresh-context floor too (age-les)
Decision (age-les) + fix: multi-model is STRICTLY STRONGER than fresh-context,
not a swap. The fresh-context floor (≥1 refuter whose context_id !=
author_context_id) is the foundational independence property — it catches the
DOMINANT failure, a worker rubber-stamping its own work because it shares the
author's context. multi-model ADDS ≥2-family diversity ON TOP; it must not waive
the floor.

Before: scripts/pawl-verdict.sh checked ONLY ≥2 families in multi-model mode, so
a verdict with two distinct families whose refuters BOTH ran in the author's
context authorized the merge (exit 0) — a self-approval bypass (family-diverse,
zero context-independence). This is within the gate's own threat model (a sloppy
agent opting up to multi-model and self-approving with two in-context models).

This aligns the code with the contract's own intent: pawls.md already said
multi-model catches "the above PLUS a single model's blind spots" — "the above"
being the fresh-context catch. The "only the diversity requirement changes with
mode" line was the mismatch; corrected here.

- pawl-verdict.sh: fresh-context floor moved OUT of the mode case, enforced
  UNCONDITIONALLY; multi-model branch only adds the family check.
- reconcile-pr.bats: new case — multi-model, 2 families, both in author's context
  → HOLD exit 5. Existing multi-model-distinct-context case still merges.
- pawls.md: corrected the swap→strictly-stronger framing in 3 places.

Verified: shellcheck clean; reconcile-pr.bats 30/30; pawl suite 43/43.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 21:43:02 -04:00
Boden Fuller daf5c4fdd3 feat(orchestrate): Phase 1 instrument lane + profiles contract (age-ueu)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 16:48:21 -04:00
Boden Fuller bf70a89ff8 feat(yield): emit deterministic-tier gate-verdict on a blocked push (age-srl)
The in-situ catch-rate gauge (age-t3f) only counted the cross-family
refuter/merge tier (reconcile-pr.sh auto-emits); deterministic pre-push gate
FAILs — real false-done catches — were dropped, so the gauge UNDERCOUNTS.

- scripts/emit-deterministic-catch.sh: fail-open, skippable emit of a REFUTED
  gate-verdict (mode=deterministic, cross_family=false) mirroring the PASS-branch
  SENSOR feed (emit-landed-provenance.sh). One emit per blocked push attempt —
  the genuine claimed-done door — not per local `ao gate check` iteration.
- scripts/hooks/pre-push.local: FAIL-branch hook, symmetric to the PASS feed;
  never changes gate_status.
- yieldledger: ModeDeterministic as a first-class diversity mode so the tier is
  valid + queryable; it raises catch_rate WITHOUT touching catch_rate_cross_family.

L2 bats proves end-to-end: emit -> `ao yield gauge` counts catch_rate=1 for the
deterministic-pre-push run. Note: catch_rate is run-scoped; deterministic catches
land under run `deterministic-pre-push` (override via AO_YIELD_RUN_ID to attribute
to a session's run). Honest completion of the in-situ instrument; it grows the
real measurement window. Does NOT prove the self-improving loop (age-1gl, blocked
on a real escape).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:35:00 -04:00
Boden Fuller 32c2927cdb feat(gates): deterministic doc-invariant gate for the control-plane taxonomy (age-fey)
The membrane on the control-plane docs (hardening #6 of the 2026-06-17
--mixed pass). check-control-plane-taxonomy.sh asserts: (C1) no live doc
rebinds the etcd-analog to retired bd/Dolt; (C2) the agent two-altitude note
is present in both the-agent-factory.md and ports-and-adapters.md whenever the
agent is classified both ways; (C3) the adapter-taxonomy section exists and
the unifying-entry cross-links resolve bidirectionally. Registered as
docs.control-plane-taxonomy (Fast|Full, blocking). 7 bats cases incl. 4
negatives proving the gate bites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:23:18 -04:00
Boden Fuller 9e171c2023 feat(eval): verification-membrane eval — false-done catch rate, deterministic oracle + cross-family verifier (membrane-eval) 2026-06-17 11:11:54 -04:00
Boden Fuller 284376ff5e Merge task/age-6sg-claim-overlay (slice 1 claim overlay). 2026-06-17 10:48:54 -04:00
Boden Fuller d3ba2675ae feat(gates): age-6sg claim overlay and pmf warn-only
Curate claim-registry from AOP-CLAIM markers, register drift and non-blocking PMF evidence gates, and document CEP promotion policy for slice 1.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:45:33 -04:00
Boden Fuller cebc43e98e feat(eval): age-6sg scenario-ab control-only slice
Add --control-only for applied-OOD ceiling checks, CI validate headroom hook, and workflow coverage wiring so ceiling violations fail before live campaign spend.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:45:32 -04:00
Boden Fuller 7266052f39 docs(destale): wave 2 + ratchet — all live docs off retired tech (age-docs-staleness-remediation-cko)
Completes the staleness epic. 42 P2/P3 files converged to current truth
(bd→br, gascity/gt-sling/mayor→NTM+Agent Mail, daemon→substrate, hooks→hookless,
CI-authoritative→push-to-main local Go gate); GLOSSARY's 18 dead skills/* links
repaired to ../skills/<name>/SKILL.md (19 links, 0 broken); contracts/runbooks
that freeze retired-system nouns bannered RETIRED/HISTORICAL rather than rewritten.

Adds the Arc-7 ratchet — scripts/check-docs-no-retired-tech.sh — which scans all
live docs (260) for retired-subsystem commands/phrases and fails on regression.
A doc opts out by carrying a RETIRED/HISTORICAL/SUPERSEDED banner (or being an
ADR / migration / upgrade / index doc), and lines that describe a removal are not
flagged. Running it caught 12 stale refs the deep-read sweep missed — a
"CI is the authoritative gate" cluster (agentops-brief, primitive-chains,
INCIDENT-RUNBOOK, knowledge-flywheel, philosophy, software-factory), stale
hook-smoke in release-e2e-checklist, and GasCity descriptors in
contracts/index + SCHEMAS + strategic-direction — now fixed. Gate: PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 10:23:02 -04:00
Boden Fuller f3d99ca23f fix(provenance): trunk-bound merge_sha emit post-push (age-0tn)
Add --trunk-ref filter to emit-landed, post-land-provenance-emit.sh for
post-push sensor feed + verdict emit; disable pre-push emit by default;
add check-provenance-merge-sha mesh guard with bats.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 07:32:11 -04:00
Boden Fuller f62019050a fix(gates): wire pawl gate into pre-push cockpit (age-58o)
Run check-pawl-pre-push.sh after ao gate check on main pushes; allow pr=0
verdicts for push-to-main landings per goal-context default.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 00:09:23 -04:00
Boden Fuller 3941747d9a fix(scripts): repair pawl-verdict jq schema-fallback enum checks (age-anc)
Bind disposition/mode/verdict before index() so minimal hosts without
jsonschema still accept valid CONFIRMED verdicts; add bats with validators shadowed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 23:55:06 -04:00
Boden Fuller cf90ec392a feat(skills): consolidate beads 4->2 — retire beads umbrella, fold lifecycle doctrine into beads-br (ag-ez7y6 #beads-consolidate-4to2)
Salvaged the uncommitted work from wt-ag-ez7y6 and completed the 4->2 beads
skill consolidation the salvaged test asserts:

- Fold the "Issue-Lifecycle Discipline" doctrine (live-reads-authoritative,
  scoped-closure-proof, parent-reconciliation, narrow-the-umbrella-issue,
  normalize-stale-queue) from the retired `beads` umbrella into beads-br.
- Retire skills/beads --into beads-br via `ao skills retire` (trees removed,
  ledger row moved to historical: merged-into beads-br).
- Re-target every retired-skill reference: crank/implement/plan/post-mortem/
  refactor frontmatter+deps, SKILL-TIERS rows, docs/SKILLS.md, GLOSSARY link,
  sku_catalog LOOP_MOVES[2], image manifests (counts adjusted).
- Codex twin: mirror the doctrine into skills-codex/beads-br, prune `beads` from
  the codex catalog/manifest, regen hashes (parity gate age-yxl).
- Add cli/cmd/ao/beads_consolidation_test.go (L2 structural invariants). Uses a
  leak-proof repo-root finder (skills/+docs/contracts/) because the shared
  findRepoRoot keys on .agents/, which the cmd/ao suite leaks into the pkg dir.

Fixed an ao-skills-retire bug surfaced here: the historical row was appended at
the end of the `workflows:` section (between historical: and dispositions:)
instead of inside historical:. Corrected manually; full fix tracked separately.

Bounded-context: BC3-Loop
Evidence: cli/cmd/ao/beads_consolidation_test.go

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 23:42:28 -04:00
Boden Fuller 8e475387a8 feat(gates): add warn-only always.ledger-prefix-policy gate (age-7f6 #ledger-prefix-policy)
Salvaged uncommitted work from wt-ledger (fix/ag-ledger-cache-reconcile-uk3us)
that never landed. Adds a warn-first/non-blocking gate that warns when the
private _beads ledger contains bead ids outside the ag- prefix.

- seed.go: register always.ledger-prefix-policy (Fast|Full, Blocking:false,
  Backing check-ledger-prefix-policy.sh) — always-run with graceful local-only
  skip since _beads is gitignored/private.
- scripts/check-ledger-prefix-policy.sh: inspects _beads/issues.jsonl, exits 0
  on clean/contaminated-but-warned/absent; reports foreign ids + per-prefix counts.
- tests/scripts/check-ledger-prefix-policy.bats: warn/pass/skip cases (3/3 green).
- seed_test.go: TestLedgerPrefixPolicyGateIsWarnFirstLocalOnly asserts shape.

Closes-scenario: age-7f6#ledger-prefix-policy
Bounded-context: BC5-Governance
Evidence: tests/scripts/check-ledger-prefix-policy.bats

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 23:25:23 -04:00
Boden Fuller 0dcad9c35d feat(donetest): Directive-16 epic done-test — the unattended self-hosting loop closes end-to-end (age-d16-self-hosting-route-nkr #epic-donetest)
The terminal integration. scripts/epic-d16-donetest.sh composes the five landed
organs (M1 sensor, M2 recovery, M3 binding verdict, M4 ASSAY, M5 guard) into one
closed loop and asserts the mechanical done-test (plan §48-55):
  seed -> no-human boundary -> injected failure -> recovery branch fires ->
  accepted ONLY via a fresh-context verdict (self-approval refused) ->
  ASSAY mines a follow-up bead -> evidence artifact lists every path.

Runs over the REAL organs in an isolated, self-contained temp root (its own
docs/+schemas/+_beads), so it is repeatable and NEVER pollutes the real _beads /
provenance ledger (asserted byte-for-byte). A deterministic composition, not a
multi-hour live coding worker; the live codex worker is the production demo.

A proven run: seed ag-odq -> rescope recovery ag-cyt (seed not closed) ->
fresh-context verdict authorizes + lands in the isolated ledger; self-approval
(refuter==author) REFUSED -> ASSAY mines ag-k9p. result:PASS.

A fresh-context refuter CONFIRMED the PASS is genuine: step 4b refuses for
exactly the fresh-context-floor reason (the authorizing vs self-approval verdict
files differ only in refuter context_id), ledger isolation is MD5-identical
before/after, no step silently no-ops, deterministic across 3 runs.

Re-anchored on real interfaces: ao provenance emit-verdict resolves the ledger
by cwd (no env override) and pawl-verdict.sh write emits internally, so every
write/emit runs cwd=WORKDIR; pawl schema requires pr>=1; isolated store uses
prefix ag so the verdict bead id is mined by M4.

Closes-scenario: age-d16-self-hosting-route-nkr#epic-donetest
Bounded-context: BC3-Loop
Evidence: docs/evidence/age-d16-epic-donetest.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:22:19 -04:00
Boden Fuller d368f346c2 feat(governance): front-door admission guard — new skill/workflow/loop needs BC+role+acceptance (age-d16-self-hosting-route-nkr.6 #frontdoor-admission)
The M5 organ. A kind-unified, added-only, FAIL-CLOSED admission guard:
scripts/check-frontdoor-admission.sh blocks a newly-ADDED skill/workflow/loop
from merging unless its front-door evidence shows all three facts — bounded-
context found (BC1..6) + role assigned (hexagonal_role) + a runnable acceptance
(references/<name>.feature or a ## Scenarios block with steps). Evidence is read
from committed sources (domain map, SKILL.md frontmatter, the workflows ledger);
existing units are never re-judged (added-only), so routine edits aren't blocked.

Enforcement at TWO points (intake.sh stays the advisory early-warning):
- pre-push gate: new blocking gate governance.frontdoor-admission (seed.go),
  matching skills/** + .claude/workflows/** — fires when a unit is added.
- the named door: reconcile-pr.sh runs the guard after the pawl verdict and
  before merge; an under-governed unit yields ADMISSION-HOLD (no merge/close).

A fresh-context refuter caught THREE fail-OPEN holes (each would admit an
under-governed unit), all fixed + regression-locked: (1) the git fallback
silently degraded to HEAD~1 when origin/main was unresolvable -> now fail-closed
on an undetermined diff; (2) a non-BC workflow domain satisfied "BC found" ->
now requires BC[1-6]; (3) an empty .feature satisfied acceptance -> now requires
a runnable scenario. A 4th (inline-comment leak in the ledger parser, introduced
by fix #2) was caught on re-refute and fixed. 15 fail-closed bats green.

Closes-scenario: age-d16-self-hosting-route-nkr.6#frontdoor-admission
Bounded-context: BC4-Factory
Evidence: docs/evidence/age-d16-6-frontdoor-guard.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:05:30 -04:00
Boden Fuller 9d5c3df5df feat(cc-hooks): installed-skill-edit PreToolUse guard — route to repo skills/ (age-workflow-guardrail-hooks-j39.1 #installed-skill-edit-guard)
Keystone of the workflow-guardrail-hooks epic. A PreToolUse Edit|Write guard
that routes an edit of an installed skill copy (*/.claude/skills/**, .codex,
.gemini) back to the repo source of truth skills/<name>/. A true mistake-token:
editing an installed/symlinked copy has no legitimate form. Matches
tool_input.file_path only (zero false-positive surface); reversible -> ROUTE
(exit 2 + one-line redirect), not hard-block; SILENT on the happy path; fires
once per session. Ships INERT with an opt-in installer; AgentOps 3.0 hookless
default unchanged.

- skills/cc-hooks/hooks/installed-skill-edit-guard.sh — the guard
- scripts/install-installed-skill-edit-guard.sh — opt-in installer (idempotent jq merge)
- tests/scripts/installed-skill-edit-guard.bats — FIRE/SILENT/false-positive/once-per-session (round-trips real PreToolUse JSON)
- skills/cc-hooks/references/INSTALLED-SKILL-EDIT-GUARD.md + SKILL.md wiring

Closes-scenario: age-workflow-guardrail-hooks-j39.1#installed-skill-edit-guard
Bounded-context: BC6-Orchestration
Evidence: tests/scripts/installed-skill-edit-guard.bats

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:43:57 -04:00
Boden Fuller 3db013a440 feat(assay): self-improvement ASSAY tick — SENSOR→ASSAY→GATE closes the loop (age-d16-self-hosting-route-nkr.5 #assay-tick)
The M4 organ. A BOUNDED pure-shell tick that mines a completed run's evidence
from docs/provenance/ledger.jsonl (SENSOR), derives suggestions over EXISTING
miners (default: a built-in ledger assay; --mine-cmd swaps in ao harvest/curate
without rebuilding them) (ASSAY), and files each suggestion as a follow-up bead
through the front door via `br create` (GATE) — unattended.

Mirrors scripts/recovery-statemachine.sh (M2) discipline; crisp terminal
invariants asserted by failure-injection bats (15 cases, br + miner stubbed):
- NO daemon / NO spin: single pass over a bounded window; --window caps the
  SENSOR, --max-suggestions caps the GATE. One terminal JSON verdict per run.
- NO silent defer: every path emits a verdict; a non-zero --mine-cmd, default
  assay, or `br create` ESCALATES loudly (exit 4), never a set -e abort.
- NO mis-close: the tick NEVER closes a bead — close authority stays at the
  merge/pawl door (reconcile-pr.sh, M3).

Two degraded-path silent-failure holes were caught by a fresh-context refuter
(both the M2 fail-open class) and fixed + regression-locked: (1) an unguarded
default-assay substitution that aborted under set -e with no verdict when
reverse() failed on a tac-less / tail-r-less host — fixed with a portable
always-exit-0 reverser + an if-guard escalation; (2) a printf '%s' (no trailing
newline) reverse-glue that silently dropped a distinct bead at
--max-suggestions >=2 — fixed with printf '%s\n'.

Reuse, don't rebuild: no dream/harvest invention, no flywheel/gold/corpus-
PROMOTE (Mossy's lane), no unbounded/daemonized mining.

Closes-scenario: age-d16-self-hosting-route-nkr.5#assay-tick
Bounded-context: BC1-Corpus
Evidence: docs/evidence/age-d16-5-assay-tick.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:42:09 -04:00
Boden Fuller 8a35dbabda feat(recovery): Codex/local recovery state-machine — fix-forward | re-scope | andon (age-d16-self-hosting-route-nkr.3 #recovery-statemachine)
Port the Claude-only ship-beads.js fix-forward policy (poll -> flake-rerun
[budget 1] -> fix-forward -> terminal) into the bo-mac Codex/local runtime as a
pure-shell state machine, and add the two missing branches: re-scope-as-new-
acceptance and andon. Replaces the silent-defer (|| echo "failed") that
run-rpi-phases.sh does on failure today.

Crisp terminal invariants (asserted by failure-injection bats):
- no spin: fix-forward bounded by FIX_FORWARD_BUDGET=1, then forced escalation
- no silent defer: every path emits one terminal verdict + one bead mutation
- no mis-close: recovery NEVER closes the bead (the merge/pawl door's authority)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:19:47 -04:00
Boden Fuller 7670271539 fix(eval): corpus-delta propagates degraded + --timeout + elapsed + evidence_kind (age-t8n)
PILOT attempt 2 was a rate-limited burst (30 calls in 2.3min) yet recorded as an honest
off=0/3 on=0/3 null because the ContextDeltaScorecard read only .pass and discarded the
runner's degraded flag. Now:
- --timeout <secs> passes through to the default runner (drops the wrapper hack; live codex
  gets a real timeout instead of the 120s default)
- run_arm counts degraded seeds (runner .degraded) per arm
- scorecard carries degraded (bool), delta_valid (=!degraded), per-arm degraded_seeds +
  status="degraded", and elapsed_seconds (wall-time sanity — an impossibly-fast run is
  self-evident)
- evidence_kind = live_agent (default runner) vs harness_plumbing (stub) — folds age-jxq
- bats: degraded-seed-flags-run + clean-run-delta_valid (13/13)

A degraded/rate-limited/timed-out run can no longer masquerade as a null.

Bead: age-t8n (unblocks readable RULER PILOT age-d16-self-hosting-route-nkr.2)
Evidence: .agents/evals/runs/pilot2-20260616T203331Z/PILOT-VERDICT.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 16:49:02 -04:00
Boden Fuller 1b0ba1cdfb chore(docs): reconcile doc/ops debt waves A–F
Align br-first tracker truth, RPI terminology, stale architecture surfaces,
new drift gates, gate deferral drain (13→11), and audit artifacts so agents
and operators share one hookless map with mechanical acceptance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:38:48 -04:00
Boden Fuller 402ad42f18 fix(eval): carry ~/.codex auth into corpus-delta sandbox HOME (both arms) (age-94f)
The corpus-delta sandbox isolates HOME and copied only .claude; codex auth lives in
~/.codex, so codex failed 401 Unauthorized on every seed in BOTH arms — a DEGRADED run
(PILOT attempt 1: all 5 frozen tasks off=0/3 on=0/3). Carry codex CREDENTIALS
(auth.json + config.toml + config.json) into each sandbox HOME's .codex in BOTH arms
(auth is runtime, never corpus context; sessions/history NOT copied) via
CORPUS_DELTA_CODEX_HOME (default ~/.codex).

Verified: real codex via the fixed harness on cd-beads-1 → context_off 0/1 (fail),
context_on 1/1 (pass), delta +1 — first non-stub, non-degraded corpus-delta datapoint.
bats: codex-auth-carried-into-both-arms (11/11 green).

Bead: age-94f (blocks RULER age-d16-self-hosting-route-nkr.2)
Evidence: .agents/evals/runs/pilot-20260616T201843Z/PILOT-VERDICT.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 16:32:44 -04:00
Boden Fuller e81516c35b fix(eval): codex exec --skip-git-repo-check so the harness actually launches the agent (age-o9x)
The live eval harness never ran the agent. eval-agent-harness.sh runs each task in
a fresh non-git mktemp dir; modern `codex exec` refuses to launch there ("Not
inside a trusted directory and --skip-git-repo-check was not specified", exit 1)
and the harness swallowed it (`>/dev/null 2>&1 || true`). Net: codex never
executed, wrote nothing, and every cd-* task scored 0 in BOTH arms — the n=1 PILOT
"floor" was launch failure, not timeout/capability.

- add --skip-git-repo-check to both codex exec call sites
- stop swallowing the agent exit; surface a non-zero exit as degraded:true +
  agent_exit:N (distinguishes a launch/timeout failure from an honest grader-fail),
  happy path output unchanged
- bats: degraded-on-nonzero-exit + no-marker-on-clean-exit

Verified end-to-end: real codex via the fixed harness on cd-door9-1 →
{"score":3,"total":3,"pass":true}, deliverable written, EXIT=0.

Bead: age-o9x (blocks RULER age-d16-self-hosting-route-nkr.2)
Evidence: docs/evals/2026-06-16-eval-orchestration-decision.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 16:13:31 -04:00
Boden Fuller 2e7444b407 fix(gates): extend codex-twin content-divergence gate to SKILL.md body (age-j1g)
age-yxl gated source references/** divergence but left SKILL.md-body divergence
ungated (the residual it filed). Same silent-staleness: a source SKILL.md body
edit with a stale twin is masked by a regen hash bump.

validate-codex-generated-artifacts.sh now requires a real non-marker twin
content change when a source SKILL.md *body* changed — scoped to the BODY on
purpose: frontmatter-only edits (hex-wiring fields the twin never carries:
consumes/produces/hexagonal_role/context_rel) need no twin change and stay green,
so legit hex-wiring pushes don't red main. Body-vs-frontmatter is detected by
comparing the frontmatter-stripped body across the scope's base ref
(head: HEAD~1..HEAD; worktree: HEAD..working; staged/upstream handled);
conservative — any ambiguity (new file, unresolved base) requires the twin.

TEST: 3 new cases — body divergence FAILs under both worktree and head scopes,
frontmatter-only change PASSes. Verified both FAIL tests fail against the
unfixed gate (guard the regression). Real-skill smoke: frontmatter-strip yields
the correct body on discovery/rpi/skill-builder.

Closes-scenario: age-j1g#skillmd-body-gate
Bounded-context: BC2-Skills
Evidence: tests/scripts/test-codex-generated-artifacts.sh

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 15:03:36 -04:00
Boden Fuller 9e165bb65d fix(gates): block codex-twin content divergence on un-mirrored references edits (age-yxl)
PROBE (evidence, not inspection): built the post-mortem divergent state in a
worktree — edited skills/discovery/references/dag.md, ran regen-codex-hashes
(twin left stale), committed, ran both gates. check-codex-parity-drift.sh and
validate-codex-generated-artifacts.sh BOTH passed (exit 0). The audit is a
Claude-ism scanner that never reads source; the structural source->codex check
was satisfied by the regen marker bump alone (a counterfactual source-only
commit with zero codex files DID fail, proving the mechanism). Verdict: the
gate does NOT catch content divergence.

FIX (routed to the gate, per the verdict): validate-codex-generated-artifacts.sh
now requires a REAL twin content change to mirror a source references/** edit —
the generated .agentops-generated.json / .agentops-manifest.json bookkeeping no
longer satisfies the mirror requirement. Scoped to references/** (mirrored
near-verbatim) to avoid false-positiving the legit frontmatter-only/hex-wiring
flow that has no twin equivalent.

TEST: two new cases in test-codex-generated-artifacts.sh — divergence (regen
hash bump only) FAILs, mirrored edit PASSes. Verified the divergence test FAILs
against the unfixed gate (guards the regression) and PASSes against the fix.

DOCS: skill-builder/SKILL.md, AGENTS-CODEX.md, CLAUDE.md registry section now
state that editing an EXISTING skill needs a manual twin mirror (regen refreshes
hashes, not prose) — prior docs only warned about NEW skills. Dogfooded: this
commit's skill-builder edit is mirrored into its codex twin.

Closes-scenario: age-yxl#probe-and-gate-fix
Bounded-context: BC2-Skills
Evidence: .agents/learnings/2026-06-16-codex-twin-content-not-auto-mirrored.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:32:56 -04:00
Boden Fuller 49d2abdb43 fix(rpi): reject gc runtime mode
Bead: ag-968ok
2026-06-16 10:36:32 -04:00
Boden Fuller 41f1c17673 fix(skills): portable check-skill-isolation + wire it warn-first as skill.isolation (ag-skill-isolation-ci-gate-jxpbx #isolation-gate)
check-skill-isolation.sh used GNU-awk 3-arg match(line, /re/, m), which BSD/macOS
awk rejects — the awk errored but the script still printed PASS: a FALSE GREEN on
the dev platform (agents believed isolation was enforced when it wasn't).

- Rewrite the matcher to POSIX awk so it runs correctly on macOS (BSD awk) and
  Linux CI (gawk) alike; awk-dialect failure now hard-fails, never silent-PASS.
- Wire as gate `skill.isolation` (Fast|Full, Blocking: false — warn-first, so a
  future violation flood reports without walling the repo). Flywheel/gold/wiki/
  corpus stay out of scope (Mossy's lane).
- bats (tests/scripts/check-skill-isolation.bats): asserts no awk error, self-test
  passes, and a real compression pattern is caught.

Current skills/ tree: 0 violations (the gate now genuinely runs). Enforces the
strict-delegation contract that operating-loop principle 8 (single-agent-first)
relies on. gates + gates/checks Go suites green; shellcheck clean.

Closes-scenario: ag-skill-isolation-ci-gate-jxpbx#isolation-gate
Bounded-context: BC4-Factory
Evidence: tests/scripts/check-skill-isolation.bats

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 09:00:47 -04:00
Boden Fuller af45eefbc9 chore(cli): regen derived command-surface artifacts for ao wiki gold
Satisfies the derived.changed-scope pre-push gate: regenerates cli-surface
docs + the command-surface eval matrix/smoke fixture, and allowlists 'wiki
gold' as public-stateful-fixture-needed (siblings wiki inject/query use the
same category; compiler logic is covered by cli/internal/wiki/gold_test.go).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 07:14:01 -04:00
Boden Fuller fe1f937bd5 feat(intake): front-door fuse + generalize pawls to the blast-radius rule
Adds scripts/intake.sh — the minimal operating model's missing front-door
primitive: require a done-test (no destination, no start), trip the basement
alarm at >2 prerequisite layers, and triage blast-radius -> CHAOS (solo) vs
PAWL (summon the cross-family Navi). Advisory triage, not enforcement: the
doors (reconcile-pr.sh + dcg) are the un-leakable gates.

Generalizes docs/contracts/pawls.md from a static list to the blast-radius
rule (mutates shared state | changes enforcement logic | external effect |
hard rollback = pawl); the list becomes examples.

tests/scripts/intake.bats: 23 cases (fuses, both classes, omission +
false-positive guards, record uniqueness). shellcheck clean.

Gated cross-family: 3 Codex-Navi pawl rounds (each caught real defects the
green tests missed; all resolved), human-adjudicated the advisory-triage scope
at the circuit breaker, final merge receipt CONFIRMED.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:29:23 -04:00
Bo 3f4279d26f feat(propulsion): no-daemonized-wake guardrail (ag-cjruu)
Guard fails the build if the wake bridge is wired into any always-on launcher (systemd/launchd/cron/loop/watch/nohup/pm2/supervisor) until ag-egpu ratifies a watch surface; finite on-demand loops pass. Wired into CI via repo-root bats case. Cross-family gate PASS (codex gpt-5.5). 18 bats, shellcheck clean.

Closes: ag-cjruu
2026-06-15 15:59:32 -04:00
Boden Fuller 44f6540c29 fix(corpus): path-guard fail-closed on missing base — full-tree scan, not HEAD~1 (ag-ao0eo)
Navi review caught a fail-OPEN hole: when the authoritative base (origin/main) is
unavailable, the guard fell back to HEAD~1..HEAD — a narrow window that misses a
forbidden path introduced in an EARLIER unpushed commit still present in HEAD.
Fix: missing base now scans HEAD's FULL TREE (every path that would be pushed),
never HEAD~1. Regression bats added (missing base + earlier forbidden commit).

Closes-scenario: ag-ao0eo#fail-closed-missing-base
Bounded-context: BC5-Runtime
Evidence: tests/scripts/check-corpus-path-guard.bats

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:42:05 -04:00
Bo 0b22abfcb8 feat(propulsion): ntm-attention-tend single-shot wake bridge (#865)
Direction-D propulsion bridge (council-ratified): one bounded reconcile pass that wakes idle agents with action_required attention, then exits. No daemon, no loop. No-orphan guarantee via session-leader probe (setsid / python3 os.setsid) + guarded group reap + interrupt-safe cleanup + fail-closed fallback. Cross-family gate PASS (codex gpt-5.5, author!=reviewer); 15 bats incl. real no-orphan runtime proof; shellcheck clean. Provenance dry-run on the amended commit verified (Navi): emits ag-7hdg0 + ag-56cru only.

Closes: ag-7hdg0
Closes: ag-56cru
2026-06-15 15:41:43 -04:00
Boden Fuller 146118429f feat(corpus): fail-closed pre-push path guard for private artifacts (ag-ao0eo) 2026-06-15 15:36:19 -04:00
Boden Fuller da61f72641 feat(dynamo): dynamo-e2e --c-delta — self-excitation C readout, populated-or-pending (ag-1wv7s)
Dynamo e2e E2 (self-excitation readout). The e2e now wires C both ways: --c-delta
<float> (a PUBLISHED corpus delta from ag-8p8o/W1c) populates C in the gauge
readout; omitted -> C reports pending, NEVER a fabricated value. Asserts the
honesty (pending without, value with) + validates --c-delta is numeric. Completes
the self-excitation organ's readout wiring; the real VALUE stays gated on the W1c
run (ag-epgk + blockers). +1 bats = 4 total. shellcheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:17:26 -04:00
Boden Fuller 9ac0fa48c7 feat(pawl): second-poll.sh — the multi-model second poll as one operator command (ag-mg757)
B2 of the 2026-06-15 council judgment (operability lane). Bo's ask: 'additional
models as the second poll... works from codec-specific and cloud-specific.'

The default pawl poll is a single fresh-context refuter (model-agnostic). The
opt-in second poll adds a different model FAMILY — today a manual multi-step in
the pre-land-refuters skill. second-poll.sh collapses the cross-family half into
ONE command from any shell: runs the gpt-family (codex exec --sandbox read-only)
refuter, parses its verdict, captures real evidence, and emits a ready-to-run
'pawl-verdict.sh write --mode multi-model' with the Claude-family refuter left as
a clear placeholder for the in-session subagent.

DISJOINT by construction: CONSUMES the stable pawl-verdict.sh write CLI; does NOT
modify the pawl mechanism or any membrane file (no collision with mossylantern's
docs/schema/eval membrane work). Cross-runtime: it's a shell script.

Safety: a REFUTED second family is surfaced + exit 1 (never emits CONFIRMED);
codex-unavailable fails loud (exit 2) rather than silently degrading to a fake
single-family multi-model verdict; --write refuses a half-filled verdict.

Tests: 6 bats (confirmed/refuted/unknown/unavailable/half-write/evidence) green;
shellcheck clean. Smoked against LIVE codex exec (v0.139.0, gpt-5.5) end-to-end —
real refuter dispatched, verdict parsed, evidence written.

Discoverability pointer into pre-land-refuters = coordinated follow-up (seam-adjacent).

Closes-scenario: ag-mg757#second-poll-one-command
Bounded-context: BC5-runtime
Evidence: tests/scripts/second-poll.bats

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:16:06 -04:00
Boden Fuller 4e594576b4 feat(dynamo): dynamo-e2e --scenario=rework — prove the ratchet is honest (ag-7wrje)
Dynamo e2e E3 (reconcile-by-rejection). Adds --scenario=clean|rework to the e2e
harness. rework runs the defining dynamo dynamic: gate REFUTED attempt-1 ->
reconcile (rework) -> CONFIRMED attempt-2 -> accept bound to attempt-2. Asserts
the gauges PENALIZE it honestly: Q=0 (reworked bead is NOT a clean first pass,
0/1 clean) AND L>0 (rework spend = loss, e.g. 0.417). Proves reject->rework->
accept closes e2e and the ratchet is measured, not just asserted. Still no LLM,
isolated ledger. +1 bats (rework) = 3 total. shellcheck clean.

An agile reconcile-by-rejection demo; the full control-plane controller is ag-v1xk
(blocked on ag-egpu). This shows the reject/rework half of the loop runs today.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:08:57 -04:00
Boden Fuller 541fc86fe8 feat(dynamo): dynamo-e2e harness — one runnable thread proves the loop closes (ag-veotd)
Dynamo e2e E1 (epic ag-13osz). scripts/dynamo-e2e.sh runs ONE full cycle on a
synthetic bead with a deterministic stub worker (NO LLM, no compute, no network):
dispatch -> gate (cross-family CONFIRMED, author!=judge, fresh-context) -> accept
-> usage -> ao yield gauge (real A/Q/A-R/E/L) -> C status (pending, never faked) ->
shadow-tune readout. Wires the REAL yieldledger organs (emit+gauge); runs in an
isolated temp project dir (never touches the real ledger). Proves the loop CLOSED
by flowed values (A>=1, R>0 reached the sensor), not just label presence.
+2 bats (loop-closes + teeth: empty-emit fails). shellcheck clean.

Real-organ gaps tracked: controller ag-v1xk (blocked ag-egpu), C via ag-8p8o W1c,
auto-tune ag-qpg99. This is the integration thread they plug into.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:05:23 -04:00
Boden Fuller 394b3257f0 feat(spawn-gateway): roll the born-into-coordination gateway into using-atm + add coverage check (ag-xe6u5)
Slice 3 of ag-tixgy (the gateway was built+live but nothing passed the flags).
Re-anchored (council): only using-atm uses 'atm spawn' — crank/swarm spawn via
runtime-native subagents (different coord model), and ship-beads/SKILL.md does
not exist. So the honest rollout is using-atm + a coverage check, NOT a 3-skill
sweep, and it touches NO shared surfaces (spawn.go, yieldledger, SYSTEM.md).

- using-atm SKILL.md: the canonical spawn is now 'atm spawn --reserve <scope>'
  (born into coordination), with a note that bare spawn leaves workers
  uncoordinated and a pointer to the coverage check.
- scripts/check-spawn-reservation-coverage.sh: flags atm-registered workers that
  are recently-active but hold NO reservation (the uncoordinated-worker drift).
  Warn-only by default, --strict to fail, skips cleanly when AM/jq absent,
  recency-filtered so dead historical agents aren't flagged. Fixture-injectable
  (AGENTS_JSON/RESERVATIONS_JSON) for testing.

Tests: 6 bats cases (warn/strict/pass/all-uncoordinated/skip/stale) green;
shellcheck clean. Smoke against live AM correctly reports 'nothing live to check'
(the fleet is down) — confirming the recency filter + skip path on real data.

The deeper headless codex-exec prompt-injection gap (rpi runtime exec sites) is
a SEPARATE follow-up, not this bead.

Closes-scenario: ag-xe6u5#rollout
Bounded-context: BC5-runtime
Evidence: tests/scripts/check-spawn-reservation-coverage.bats

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:01:21 -04:00
Boden Fuller 93b1f64596 fix(eval-harness): honor CORPUS_DELTA_WORKSPACE + clean-only-what-we-create + abort-safe trap (ag-zzpy1)
W1c blocker (pre-mortem #3): the default runner did mktemp -d, ignoring the
harness-exported CORPUS_DELTA_WORKSPACE — so the agent ran OUTSIDE the per-arm
isolation sandbox (ag-5apc proof was stub-only). Now:
- use the caller's sandbox when provided (else mktemp);
- rm ONLY a runner-created workspace, never a caller-provided one;
- EXIT trap cleans the runner-created workspace even when setup.sh/score.sh
  fails under set -e (codex review: failure-path leak);
- WORKBENCH overridable via EVAL_WORKBENCH for testing.
3 bats (honor / fallback-cleanup / abort-cleanup, no LLM via fake codex + empty
TMPDIR) + harness 10/10, shellcheck clean.

NOTE: codex review also found CODEX_HOME / AGENTOPS_RPI_RUNTIME* are not isolated
in the arm env (a separate env-hygiene leak per docs/contracts/eval-environment.md)
— filed as ag-aekxj (auth-preserving fix), blocking ag-epgk so no metered run
proceeds until it lands. Out of scope for this workspace-isolation fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 08:50:19 -04:00