mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
main
377 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7bbc6569c4 |
feat(liveness): enforce author-judge quorum gate (ag-xdrw) (#737)
## Summary Implements `ag-xdrw` independent-verification gates for claim-evidence and significant orchestration actions. - Adds `author_id` / `judge_id` metadata to claim-evidence bindings. - Rejects self-graded bindings at the ClaimEvidenceBinder port. - Requires non-empty, distinct author/judge metadata for high-assurance PG3/PG4 evidence while preserving legacy anonymous PG1/PG2 behavior. - Carries reviewer metadata through in-memory + production claim-evidence derive paths and durable JSONL binding records. - Adds `liveness.CheckSignificantAction` for orchestration-tier significant actions requiring two distinct non-actor ACKs across at least two model families. - Regenerates CLI docs/surface/registry after adding `ao claim bind --author-id/--judge-id` flags. ## Validation Current head: `e4456538d89660c954ca12d347a186bd1cf68edf` rebased over #740 (`853d781e`). Focused checks after rebase: - `go test ./internal/liveness ./internal/ports` - `go test ./cmd/ao -run 'TestProductionClaimEvidenceBinder|TestClaimBind|TestClaimList|TestProductionClaimEvidence|TestClaim'` Required regen after rebase: - `bash scripts/regen-all.sh` regenerated artifacts, then exited nonzero on the known CMDAO surface parity red: `wiki query` / 30 uncovered commands. Required pre-push after rebase: - `PRE_PUSH_FAIL_FAST=false bash scripts/pre-push-gate.sh` completed with 4 known non-diff failures: - test-fixture parity: `scripts/gc-stale-worktrees.sh` - worktree disposition: canonical root dirty/untracked operator state - corpus freshness: newest local snapshot older than threshold - contract canaries: known `agentops-core.pre-push-gate-governance` Bats failure Diff-relevant gates passed in the pre-push run, including changed-scope build/vet/race, command/test pairing, `goals validate`, registry drift, CLI docs parity, command-surface matrix canary, shellcheck, mkdocs, contract compatibility, CI policy parity, and context-map drift. ## Review Gate No self-grade: cross-model ACKs are recorded in Agent Mail. - WindyCastle re-confirmed ACK on `547eb36f` and then explicitly called to rebase once more over #740 and merge this keystone next (#134). - RubyMoose re-confirmed ACK on `547eb36f`; current `e4456538` is the same reviewed semantic diff rebased over #740 plus regenerated registry timestamp. Review attacks covered: - PG3/PG4 anonymous reviewer metadata rejects; PG1/PG2 anonymous legacy remains allowed. - `AuthorID == JudgeID` rejects. - Significant-action actor ACK does not count toward quorum. - Two same-family ACKs do not satisfy quorum. - Non-quorum path returns `NeedsAdmission`, never `Allowed`. Bead: `ag-xdrw` Evidence: TestProductionClaimEvidenceBinder_SelfGradeRejected Evidence: TestProductionClaimEvidenceBinder_HighAssuranceWithoutReviewersRejected Evidence: TestCheckSignificantActionTwoCrossModelACKsAllowed Evidence: TestCheckSignificantActionActorACKDoesNotCount |
||
|
|
8ad6747913 |
chore(ao): delete the ao evolve CLI surface (ag-llni slice 1) (#724)
**Slice 1 of ag-llni** — retire `ao rpi`/`ao evolve` (orchestration is no longer an in-CLI engine). This PR removes the **`ao evolve`** half; the `rpi*.go` + phased web is slice 2. **Architecture (operator-confirmed 2026-06-04):** orchestration is two-tier — *inner loop* (one session) = skills/CLIs/native-subagents + **Workflows** (`.claude/workflows/operating-loop.js` + `bead-crank.js` — the Claude encoding of inner-orchestration that was mis-shaped as `rpi`/`evolve`); *outer loop* (many sessions) = **NTM + mcp-agent-mail**. Codex inner-loop = NTM + agent-mail for now. Leaf CLIs (`corpus`/`goals`/flywheel/knowledge loops = BC1 corpus), NTM, and agent-mail all stay. ### Changes - Deleted `ao evolve` + 4 subcommands (`config`, `next-work`, `blocked`, `write-stop-marker`) — 10 files. - Relocated the one non-evolve coupling, `countCronHistoryRows`, into its sole consumer `cron_self_adjust.go`. - Removed `evolve` from the `cobra_commands_test.go` golden `expectedCmds` list (2 sites). - Regenerated `cli/docs/COMMANDS.md` (−125 lines) + `docs/cli-skills-map.md`. ### Verification - `go build ./...` green · `go vet ./cmd/ao` clean · **`go test ./cmd/ao` = 9251 pass**. - Net: 13 files, −2192 LOC. Bounded-context: BC5-Runtime Closes-scenario: ag-llni#delete-evolve-cli Evidence: cli/cmd/ao/cron_self_adjust.go Test-Removal-Reason: ao evolve CLI surface retired (ag-llni) — orchestration moved to .claude/workflows + NTM; the 5 deleted evolve_*_test.go covered now-deleted command code, not kept behavior. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
3d99d4bf69 |
fix(corpus): unify secret redaction + compile/CI git-safety (ag-sz3h ag-zi90 ag-y2xy #w1-git-safety) (#720)
Completes the **W1 git-safety arc** of epic ag-lhu0 (memory-system re-architecture) — three beads, one coherent surface, after #719 wired scrub-on-write into corpus_fs. - **ag-zi90 (dedup):** `redactContent` (`ao context assemble`) now runs canonical `llm.Redact` first — a single source of truth for credential patterns (AWS / GitHub / GitLab / Slack / GCP / PEM, previously uncovered in this path) — then keeps the supplements `llm.Redact` does *not* cover: 2-segment app JWTs, sensitive env-var assignments, high-entropy strings. - **ag-sz3h (compile chokepoint):** new `ao redact` (stdin→stdout canonical scrub) bridges the shell compile path; `compile.sh` pipes every rendered article through it before `os.WriteFile` (loud fallback if `ao` absent). - **ag-y2xy (CI backstop):** `check-corpus-secret-scan.sh` scans **git-tracked** (committed/allowlisted) `.agents` corpus + canon only — repo-root `.agents` is local-only by policy, so scrub-on-write (#719 + `ao redact`) is the primary defense and this is the backstop. Wired into `validate.yml`; bats covers clean / leak-with-file:line / untracked-not-scanned. Scrub-on-write is primary; CI is the backstop. Verified: go build/vet/test (incl. `TestRunRedact`, JWT-dedup regression test green), bats 3/3, shellcheck clean, conformance regenerated. Closes-scenario: ag-sz3h#compile-render-scrub Closes-scenario: ag-zi90#dedup-redactor Closes-scenario: ag-y2xy#ci-secret-scan Bounded-context: BC1-Corpus Evidence: scripts/check-corpus-secret-scan.sh --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
7bd90eab3b |
feat(canon): verify --council for independent cross-vendor verdicts (ag-mluj #council-verdict-independent) (#674)
## What gap#1 — the load-bearing **"earned by verification, not assertion"** gap. `ao canon verify --council` delegates the verdict to an **independent cross-vendor judge** instead of taking an operator-asserted one: - `CouncilVerifier` port + `CommandVerifier` adapter, configurable via `AGENTOPS_CANON_VERIFIER_CMD` (codex = the cross-vendor lane in this fleet) - Verdict is attributed to the **judge**, not whoever ran the command → counts toward promotion even when the author invokes it (independence by construction) - No judge configured → **loud error**, never fabricates a verdict - Judge output must carry `VERDICT: confirmed|refuted`; absence is an error (never defaults to confirmed) - The judge transcript is recorded as the verification **receipt** ## Honest scope This wires the cross-vendor **judgment** lane (council's P9 cross-vendor rule). How deeply the judge gathers its own evidence is bounded by what the judge command does — a codex judge has shell access and can read cited files; the receipt records what it examined. The full "gather-your-own-evidence" keystone (mo-qz3srw) remains a further step. ## Verification - 8 new unit tests (verdict parse, empty-cmd-fails-loud, confirmed/refuted exec, no-verdict-errors, council-is-independent); canon package green - e2e: no judge → loud error; fixture cross-vendor judge → independent `confirmed` attributed to `codex:gpt-5.3`; learning EARNED even when author-invoked - command-surface canary unchanged (flag, not a new heading) Closes-scenario: ag-mluj#council-verdict-independent Bounded-context: BC1-Corpus Evidence: cli/internal/canon/verifier.go |
||
|
|
3702761e75 |
feat(canon): earned-promotion team-knowledge tier (ag-bw5s #earned-promotion-gate) (#672)
## What A team-knowledge **canon**: learnings *earned* into a shared trusted set, not self-asserted. Adapts Doug Dan's warmind (#671) to the post-ACFS direction — moat = knowledge earned by verification, not self-certification. Promotion requires **two independent, self-guarded signals**: - **citation** — another engineer/agent USED it (proves useful) - **verification** — another engineer/agent CHECKED it (proves true; receipt-bearing) An independent refutation hard-blocks. The anti-self-certification guard is generalized to *all* promotion signals: the factory may not grade its own homework. ## Slices (3 commits, one coherent arc) 1. **Earned-promotion gate** — `internal/canon` (identity guard, citation + verification JSONL ledgers, gate); `ao canon cite/verify/status/promote`. 2. **Inject trusted tier** — `collectLearnings` surfaces `.agents/canon/learnings/` deduped + boosted 1.15× over equal-utility local; flagged `Canon`. 3. **IdentityResolver port** — `--as` > `AGENTOPS_ACTOR` env > git. Env tier is the seam to Agent Mail (`whois`) with **no MCP coupling** — `ao` stays portable. Makes the cross-actor guard hold for humans AND agents. ## Deliberately dropped from #671 Resurrected `hooks/` + session-end auto-sync (hookless regression), the "Gas City Dispatch (CRITICAL)" doctrine (contradicts prune-the-coordination-plane), the parallel scoring/maturity engine (duplicated inject primitives), and the "warmind" name. ## Verification - `go build`/`vet` clean, gofmt clean - 9,388 tests green (`cmd/ao` + `internal/canon` + `internal/search`) - e2e: apollo self-attesting excluded; witness (distinct agent via `AGENTOPS_ACTOR`) earns promotion; `ao inject` ranks canon first at equal utility ## Deferred (next) Wire `verify` → `ao verify`/council (currently operator-attested — the load-bearing gap); tier-aware gate (heuristics earn citation, not verification). Closes-scenario: ag-bw5s#earned-promotion-gate Closes-scenario: ag-bw5s#inject-trusted-tier Closes-scenario: ag-bw5s#agent-identity-resolver Bounded-context: BC1-Corpus Evidence: cli/internal/canon/promote.go |
||
|
|
a36abd3675 |
chore(provenance): align relation enum to W3C PROV-O vocabulary (ag-lmdx.7 #prov-o-vocabulary) (#660)
## What Rename the provenance ledger relation enum from AgentOps-local `subject_verb_object` names to the standard **W3C PROV-O / PROV-DM** verbs so an external auditor recognizes the term, and document the **columns-not-JSON-paths** guard-read principle in the schema. Schema changes are single-writer on `main`. Implements ag-lmdx.7. ### Relation mapping (atomic contract change) | Prior AgentOps-local | W3C PROV-O | |---|---| | `decision_produces_artifact` | `wasGeneratedBy` | | `decision_authorizes` | `wasAssociatedWith` | | `artifact_derived_from` | `wasDerivedFrom` | | `scenario_covers_artifact` | `wasInformedBy` | | `verdict_attests_artifact` | `wasAttributedTo` | | `bead_scopes_decision` | `wasInfluencedBy` | | `commit_implements_decision` | `wasRevisionOf` | | `learning_revises_decision` | `wasInvalidatedBy` | ## Scenarios - **Relations use PROV-O vocabulary** — the enum now contains only PROV-O verbs; an edge with the colloquial `derives_from` (or the prior `artifact_derived_from`) is REJECTED in favor of `wasDerivedFrom`. Enforced by two new bats cases (accept PROV-O, reject legacy vocabulary). - **Guard-read field is a column not a JSON path** — the schema description now states that guard-read/queryable fields (`from_id`, `to_id`, `relation`, `trust_tier`, the hash-chain anchors) are first-class top-level columns, never nested JSON payload paths, because Dolt JSON-path generated-column indexing is unreliable. The `judge_id` verdict guard already reads a first-class struct field in `evidencedturn`; **no Dolt migration is invented** (no Dolt projection schema exists in this repo — the principle is encoded in the contract). ## Ripple (every merged consumer, atomic) - `schemas/agentops-sdlc-provenance.v1.schema.json` (enum + description) - `cli/internal/provenancegraph/edge.go` (`Relations` + godoc) - schema-driven validator via `tests/scripts/validate-provenance-ledger.bats` (PROV-O accept + legacy reject) - consumers: `drrebuild`, `drwitness`, `evidencedturn`, `cmd/ao/provenance_*`, `cmd/ao/turn_verify` - all hash-chained fixtures **re-sealed via the canonical hasher** (`drrebuild` ledger + frozen `expected-graph-hash.txt`, `committed-witness.jsonl`); witness dolt-rows + provenance JSON fixtures updated - generated `cli/docs/COMMANDS.md` regenerated ## Verification - `cd cli && go build ./... && go vet ./...` clean; **`go test ./...` → 11942 passed in 72 packages** - `bats validate-provenance-ledger.bats witness-dolt-jsonl-crosscheck.bats` → 20/20 - `bats provenance-orphan-fixtures.bats check-provenance-orphans.bats` → 7/7 - `scripts/check-contracts-structural-floor.sh` → PASS (45 contracts) - `docs/provenance/ledger.jsonl` does not exist (no real entries to migrate); `.agents/ao/provenance/graph.jsonl` is a separate transcript-mining graph (no `relation` field) and out of scope. Closes-scenario: ag-lmdx.7#prov-o-vocabulary Bounded-context: BC4-Factory Evidence: schemas/agentops-sdlc-provenance.v1.schema.json |
||
|
|
554eb8c306 |
feat(turn): enforce author!=validator no-self-grading invariant (ag-lmdx.4 #author-validator-guard) (#658)
## What Enforce the no-self-grading invariant (`ag-lmdx.4`): a Turn graded by its own author is autocorrelated, so an Evidenced Turn is not done unless an independent judge context produced the acceptance verdict. - **`cli/internal/evidencedturn`** — new `author_neq_validator` predicate + `AuthorID`/`JudgeID`/`AllowSelf` fields on `Input`. The predicate FAILS when `judge_id == author_id` (self-graded) or when no judge identity was recorded (independence that was never recorded cannot be asserted); the documented, default-OFF `--allow-self` waives it for the inline fallback. This fills the `TODO(ag-lmdx.4)` extension point the #657 author left. - **`cli/cmd/ao/turn verify`** — `--allow-self` flag + `author_id`/`judge_id` on the turn-input file, wired into the DoD predicate so a self-graded verdict fails the `validated->closed` guard. - **`/pre-mortem` + `/vibe` SKILL.md** (and `skills-codex` twins) — refuse a self-graded PASS verdict; require the judge to be a blind, context-isolated sub-agent (`judge_id != author_id`); document `--allow-self` as the default-OFF escape and point at `ao turn verify` as the enforcement predicate. ## Tests (TDD-first) `evidencedturn`: self-graded refused / independent accepted / `--allow-self` waives / missing-judge refused. `cmd/ao`: `turn verify` self-graded exits non-zero, `--allow-self` passes. ## Gates `go build ./...` + `go vet` + `go test ./...` green (11845 pass). gosec: 0 new findings in touched files. Codex parity audit + generated-manifest/artifacts validators pass. `tests/skills/run-all.sh`: 87/87. COMMANDS.md regenerated (the one `--allow-self` line); codex manifest spliced to pre-mortem+vibe only (no drift-sweep). ## Dedup note (ag-9jle.5) This bead is the **invariant/guard** (data shape + predicate + skill refusal). The skill text states the blind-sub-agent requirement, but the actual blind-judge SPAWNING MECHANISM in `/vibe` + `/validation` (ag-9jle.5) is NOT implemented here. Partial overlap on the skill contract; the runtime mechanism remains for ag-9jle.5. Closes-scenario: ag-lmdx.4#author-validator-guard Bounded-context: BC2-Validation Evidence: cli/internal/evidencedturn/evidencedturn.go |
||
|
|
486cb99be5 |
feat(turn): ao turn verify Evidenced-Turn DoD predicate (ag-lmdx.5 #ao-turn-verify) (#657)
## What Adds `ao turn verify <bead>` — a legible Definition-of-Done predicate for an **Evidenced Turn** (ag-lmdx.5). Where the live AP#7 gate checks Evidence *presence*, this checks turn *sufficiency*: one verdict answering "can this bead legally transition validated->closed?" with a clear pass/fail per predicate and a reason for every gap (`--json` too). ## Definition of "Evidenced Turn" A turn is DONE iff all six predicates pass: | predicate | meaning | |---|---| | `chain_intact` | the bead's state_transition log hash-verifies and folds (turnstate `FoldVerified`) | | `terminal_state` | the folded lifecycle state is at the validated->closed boundary | | `scenarios_covered` | every Closes-scenario claim has a passing test | | `evidence_resolves` | every Evidence line resolves to a gate log that exercised THAT scenario (presence->sufficiency) | | `provenance_event` | a provenance edge in the ledger references the bead | | `no_orphan` | no artifact in the turn's trace-graph is a provenance orphan | ## How - New pure, in-memory predicate core `cli/internal/evidencedturn` (no Dolt / no shell-out) — the testable kernel that defines what "done" MEANS. - Builds directly on **#654** `cli/internal/turnstate` (`Seal/Append/Fold/FoldVerified/VerifyChain`) and `cli/internal/provenancegraph` (edges + `FindOrphans`). - `cli/cmd/ao/turn_verify.go` wires `--input` (turn-input JSON: state log + scenario coverage), `--ledger` (provenance EDGE ledger), and `--graph` (optional trace-graph for orphan audit). Non-zero exit on not-done makes it usable as a transition guard. ## Scope note (ag-lmdx.4) The author!=validator guard is a **separate** concern and is NOT implemented. It is left as a documented extension point (TODO on `Evaluate`); the verdict shape already accommodates an extra predicate row without a reshape. ## Tests `cli/internal/evidencedturn` (14 cases: complete-turn-done, each missing predicate fails with a legible reason, multi-gap, blank-bead error) + `cli/cmd/ao/turn_verify_test.go` (complete/incomplete/json/orphan/no-graph/missing-input/bead-mismatch). `go build ./...`, `go vet`, full `cmd/ao`+`evidencedturn` suites (9288) green. ## Derived surfaces regenerated COMMANDS.md, cobra `expectedCmds`, command-surface smoke (top=75 sub=188 all=263) + matrix.json, registry.json (cli_commands 72->73), cli-skills-map. Closes-scenario: ag-lmdx.5#ao-turn-verify Bounded-context: BC4-Factory Evidence: cli/internal/evidencedturn/evidencedturn.go |
||
|
|
a6336b7c34 |
feat(provenance): ao provenance trace --orphans --strict gate (ag-x31t.6 #provenance-orphan-gate) (#653)
## What Adds `ao provenance trace --orphans --strict`: detects provenance orphans — artifact nodes with **no inbound authored/inferred edge** — by generalizing the `goals_trace_orphans` no-inbound chain-gap detection onto the provenance graph. Wires it as a blocking CI gate. ## How - **`cli/internal/provenancegraph/orphans.go`** — `ReadGraphRecords` (parses the goalstrace `Node`/`Edge` JSONL contract that the seeded fixtures use) + `FindOrphans` (an artifact node is an orphan iff no edge's `to_id` targets it; it flips green the moment any inbound edge is added). - **`cli/cmd/ao/provenance_trace.go`** — the `trace --orphans [--strict] [--json] [--graph <path>]` subcommand. `--strict` exits non-zero when orphans exist; `--json` emits one finding per line. - **`scripts/check-provenance-orphans.sh`** + a new **blocking** step in `.github/workflows/validate.yml` (in the existing goals/spec-linkage job, right after the warn-only `ao goals trace --orphans`). The gate asserts the strict audit **catches** each seeded orphan fixture and **passes** once an inbound edge wires the artifact back to a directive — so it is deterministically green while proving the detector is wired. ## Tests (TDD-first) - `cli/cmd/ao/provenance_trace_test.go` (L2): drives the real `tests/fixtures/provenance/` fixtures against `expected-orphans.json` — `--strict` catches each of the 3 seeded orphans (`gate:scenario-hash-stability`, `artifact:scripts/pre-push-gate.sh`, `claim:65-jobs`), and a wired graph exits 0. Plus mode/flag-guard cases. - `cli/internal/provenancegraph/orphans_test.go` (L1): detection, non-artifact nodes never orphaned, deterministic sort, JSONL parsing + malformed/missing-file rejection. - `tests/scripts/check-provenance-orphans.bats`: gate-script behavior. ## Derived surfaces regenerated - `cli/docs/COMMANDS.md` (new `ao provenance trace` subcommand, cobra-conformance passes) - CLI surface smoke fixture + matrix (sub 186→187, all 260→261) - `registry.json` **unchanged** (provenance is already a top-level command; subcommands aren't counted) — timestamp-only churn reverted. ## Gates `go build ./... && go vet ./... && go test ./...` (11959 pass) · gosec clean on new files (one `#nosec G304` on the operator/CI-supplied graph path, with reason) · `scripts/validate-ci-policy-parity.sh` PASS. Closes-scenario: ag-x31t.6#provenance-orphan-gate Bounded-context: BC4-Factory Evidence: .github/workflows/validate.yml |
||
|
|
2fecf2b304 |
feat(provenance): ao provenance export deterministic hash-chained (ag-x31t.5 #provenance-export) (#651)
## What Adds `ao provenance export`: a deterministic, hash-chained rendering of the committed provenance ledger (`docs/provenance/ledger.jsonl`). - Reads the ledger, **canonically sorts** edges by `(ts, from_id, to_id, relation)` (with type/trust/evidence tie-breakers for a total order), then **re-seals** them into a fresh per-record hash chain. - Output is **byte-identical on re-run** regardless of the ledger's physical append order. Default = JSONL (one compact edge per line); `--json` = indented array; `--verify` = one-line OK summary, no varying body. - The re-chained export **verifies with no Dolt server** — the committed JSONL is the audit authority, and re-chaining uses only the in-process hashing in `cli/internal/provenancegraph` (same `prev_hash` discipline as the rpi ledger). No reinvented Edge/hash logic: new `CanonicalSort`/`ReChain` helpers reuse `Seal`/`VerifyChain`. ## Tests (TDD-first) - `chain_test.go`: canonical-sort ordering + stability + non-mutation, order-independent re-chain, byte-identical serialization, empty ledger, invalid-edge rejection, tamper detection. - `provenance_export_test.go`: deterministic bytes across runs, chain verifies, empty ledger (`[]` not `null`), `--verify` summary, tampered-ledger rejection. ## Derived surfaces regenerated - `cli/docs/COMMANDS.md` (cobra conformance) - `evals/agentops-core/fixtures/cli-command-surface-smoke.sh` + `cli-command-surface-matrix.json` (sub 185→186, all 259→260) - `registry.json` unchanged: it counts top-level commands only (subcommands not tracked; top-level count = 72). ## Gates `go build` / `go vet` / `go test ./...` green; gosec clean on the new files; CLI-skills-map, JSON-flag-consistency, and `generate-cli-reference.sh --check` all pass. Closes-scenario: ag-x31t.5#provenance-export Bounded-context: BC4-Factory Evidence: cli/cmd/ao/provenance_export.go |
||
|
|
427c25b248 |
feat(provenance): provenance_edges write-model + ao provenance add (ag-x31t.4 #provenance-write-model) (#649)
## What Builds the WRITE side of the SDLC provenance/intent graph (ag-x31t slice 1). Adds `ao provenance add` / `ao provenance list` plus a new `cli/internal/provenancegraph` package that seals typed, evidence-backed edges onto the per-record hash-chained ledger at `docs/provenance/ledger.jsonl`. Consumes the schema merged in #637 (`schemas/agentops-sdlc-provenance.v1.schema.json`). Does not touch the schema (.2), export (.5), or gate (.6). ## CQRS doctrine Per CLAUDE.md and the council architecture, the committed JSONL ledger is the **audit authority and source of truth**; any Dolt `provenance_edges` table is a rebuildable projection that loses on disagreement. So this command appends the JSONL ledger directly. Hashing reuses the `cli/internal/rpi/ledger.go` discipline: `payload_hash = sha256(canonical payload)`, `hash = sha256(payload_hash + "\n" + prev_hash)`, genesis `prev_hash=""`. ## Behavior - `ao provenance add <from-id> <to-id> --relation ... [--from-type --to-type --trust-tier --evidence --ts --json]` — seals + appends one schema-valid edge. **Idempotent** on edge identity (endpoints+relation+evidence+trust-tier), so a re-run with a different timestamp is a no-op. - `ao provenance list [--json --from-id --relation]` — reads edges back in chain order. ## Tests (TDD, table-driven, exact-value asserts) - `edge_test.go`: field/enum validation, deterministic hash chain, schema-version forcing, tamper + chain-link detection, identity stability, JSON field-name parity with the v1 schema. - `store_test.go`: append→read round-trip + persisted-chain verify, idempotency, reject-invalid-before-write (no file created), corrupt-line rejection, and **validation of emitted edges against the merged schema via `scripts/validate-provenance-ledger.sh`**. - `provenance_add_test.go`: add produces a schema-valid sealed edge + list reads it back, idempotent no-op, invalid-relation error, list filters. ## Gates - `cd cli && go build ./... && go vet ./... && go test ./...` — all green (11949 pass). - Command-surface bumped: regenerated `cli/docs/COMMANDS.md`, updated `cli-command-surface-smoke.sh` + `cli-command-surface-matrix.json` (top 73→74, sub 183→185, all 256→259), added `provenance` to cobra expectedCmds; `validate-cli-skills-map.sh` PASS. Closes-scenario: ag-x31t.4#provenance-write-model Bounded-context: BC4-Factory Evidence: cli/cmd/ao/provenance_add.go |
||
|
|
1307eb0e0a |
feat(skills): queryable skill catalog JSON + ao skills (soc-vuu6.4 #skill-catalog-json) (#640)
## What Slice 2 of the skill-catalog bead (soc-vuu6.4): the **queryable surface** over the generated `skills/catalog.json`. Slice 1 (the generator, schema, drift gate, and `catalog.json` itself) landed in PR #379; this adds the `ao skills` query commands the bead's acceptance criterion calls for. - New `cli/internal/skills/catalog.go` — loads `skills/catalog.json` and a **pure, table-tested** query engine (`List`/`Consumers`/`Producers`/`Mermaid`). No SKILL.md re-parsing; reads the committed, CI-synced catalog. - New `cli/cmd/ao/skills_query.go` — four cobra subcommands: - `ao skills list [--role --produces --consumes --practice --user-invocable] [--json]` - `ao skills consumers <skill> [--json]` - `ao skills producers <output> [--json]` - `ao skills graph [--format mermaid]` - Regenerated `cli/docs/COMMANDS.md`; bumped the cli-command-surface fixtures (`sub` 179→183, `all` 252→256) for the 4 new subcommands. ## Why `registry.json` and `catalog.json` existed but had no query API — agents grepping "which skill produces X?" had to scan markdown. This turns the catalog into a queryable surface (the bead blocks `ao skill new`, which needs sibling-skill defaults). ## Acceptance > `ao skills list ... --json` returns the matching skill set in <100ms. Verified: `ao skills list --produces result.json --json` → `[beads, discovery]`; `ao skills consumers rpi` → 5 skills; `ao skills graph` emits deterministic Mermaid. Latency well under 100ms. ## Scope notes - Did **not** regenerate `skills/catalog.json` — it carries pre-existing drift on `main` (the `check-skill-catalog-drift` gate is I0/advisory). This PR only *consumes* the catalog; regenerating would sweep in unrelated drift. - The bead's illustrative `--tier judge` example does not map to the real generated schema (which has no `tier` field — it uses `hexagonal_role`, `produces`, `consumes`, `practices`). Filters implemented against the actual catalog fields. ## Tests `cli/internal/skills/catalog_test.go` (engine, exact-value table tests + load round-trip) and `cli/cmd/ao/skills_query_test.go` (JSON shape, sort invariants, flag validation, mermaid header) — all green. `go build`/`go vet`/`go test ./...` pass; conformance + command-surface smoke pass. Closes-scenario: soc-vuu6.4#skill-catalog-json Bounded-context: BC1-Corpus Evidence: cli/internal/skills/catalog.go |
||
|
|
4131e7c720 |
feat(rpi): materialize harvested next-work into durable beads (ag-9jle.3 #lessons-to-beads) (#633)
## What
Closes the missing half of the BDD-Gherkin-wave loop — **lessons →
beads**. Harvested follow-ups landed in `.agents/rpi/next-work.jsonl` as
a queue but never became durable beads, so the flywheel executed without
compounding into the tracker.
New **`ao next-work materialize`**:
- Reads unmaterialized items from `next-work.jsonl` and `bd create`s one
durable bead each.
- Carries `source_epic` + `proof_ref` on **bd's native `--metadata`** —
*not* a forked provenance format. The real provenance graph edge is
deferred to `ag-x31t.4`'s future `ao provenance add`.
- **Idempotent** via the existing per-item `bead_id` back-reference.
Re-runs skip already-materialized / consumed / held-for-review items.
- Flags: `--file`, `--dry-run`, `--json`, `--source-epic`,
`--materialized-by`.
- `skills/post-mortem/references/harvest-next-work.md` now invokes it
after the queue-write (CLI owns the deterministic core; the skill just
calls it).
## First failing test (Gherkin contract)
> Given a completed wave with a harvested follow-up · When materialize
runs · Then a durable bead exists via `bd create` carrying
`source_epic`/`proof_ref`, not only a `next-work.jsonl` queue line.
`TestNextWorkMaterialize_CreatesDurableBeadWithProvenance` + 6 more
(idempotency, skips-consumed/held, dry-run-no-mutation, source-epic
filter, 2 mapping tables) — all green.
## Compass-not-maps pivots vs the locked plan
Verifying each premise before executing (the W1-reconciliation
overstated-scope lesson) caught two beats that were **already done**:
1. The schema fields `source_epic`/`proof_ref` already exist in
`next-work-{item,batch}.v1.schema.json` — dropped the "add fields" beat.
2. The idempotency anchor `NextWorkItem.BeadID` already exists — no new
field invented.
## Boundary
Zero `ag-x31t` files touched; `validate.yml` untouched (parked per
handoff). `ao next-work` is collision-free (distinct from the existing
`ao evolve next-work` ladder recommender).
## Validation
- `cli/cmd/ao` package: all tests green except pre-existing
`TestCronSelfAdjust_RoundTrip` (macOS-only `/tmp` vs `/private/tmp` path
bug — fails identically on clean `main`, passes on CI Linux).
- `TestCobraConformance` + `TestCobraExpectedCmdsMatchRegistration`
updated for the new command; `COMMANDS.md` regenerated.
- `go vet` + `gofmt` clean.
Closes-scenario: ag-9jle.3#lessons-to-beads
Bounded-context: BC3-Loop
Evidence: cli/cmd/ao/next_work_materialize_test.go
|
||
|
|
fb7ed11780 |
feat(eval): wire gate #3 holdout-burn enforcement into ao eval outcomes ingest (ag-vbwx) (#628)
## What Closes the **#1 caveat from the 2026-05-30 council post-mortem (WARN)**: `registerOutcomesBurn` (gate #3, shipped in #626) was a **correct-but-unwired primitive** — `runEvalOutcomesIngest` never called it, so `ao eval outcomes ingest` enforced **zero holdout quota at runtime**. This makes it a **live guard**. Adds a **`--burn-ledger <path>`** flag (opt-in, mirroring `--expect-judge-hash`). When set and the score is a holdout grade, ingest: 1. loads the persisted `HoldoutBurnLedger` JSON, 2. calls `registerOutcomesBurn` (which **refuses** on exhausted `(suite,gt)` quota), 3. persists the updated ledger **atomically** (temp+rename) across invocations. So a cloud/Codex Outcomes run can no longer re-observe a spent holdout split. **Managed Agents are NOT ZDR.** Empty path = no-op (dev/legacy flows preserved); dev-split scores never burn. ## Scope The **local-file persistence slice** of ag-vbwx. The global-Dolt transport (cross-host shared ledger) remains a follow-on slice tracked on ag-62g68. Two files + COMMANDS.md. ## Evidence (command-level, not just the primitive) - `TestApplyOutcomesBurn_RefusesAtCommandLevel_WhenQuotaExhausted` — `runEvalOutcomesIngest` refuses + leaves the ledger unmutated. - `TestApplyOutcomesBurn_PersistsAcrossInvocations` — two burns under budget 2 persist to disk, third refuses. - `TestApplyOutcomesBurn_EmptyPathNoOp` + `TestApplyOutcomesBurn_DevSplitNoBurn`. - `go build ./...` ✓ · `go test ./cmd/ao/` 9229 pass ✓ · `go vet` clean · gocyclo no findings · `generate-cli-reference.sh --check` up-to-date · `generate-registry.sh --check` OK (no new heading → surface-matrix canary unchanged; SKU `cmd:ao.eval` unchanged). Verdict that motivated this: `.agents/council/2026-05-30-evolve-624-627-postmortem/verdict.md` (local). Closes-scenario: ag-vbwx#gate3-runtime-wiring-local-ledger Bounded-context: BC4-Evaluation Evidence: cli/cmd/ao/eval_outcomes_ingest.go |
||
|
|
e2b4dcad2c |
feat(eval): gate #2 judge_content_hash parity on outcomes ingest (ag-62g68 #gate2-hash-parity) (#627)
## What `ao eval outcomes ingest` ignored the score's `judge_content_hash` entirely — so a score graded against a **drifted rubric** would still ingest into the council verdict and feed the Knowledge Flywheel. Gate #2 (SCHEMA rc2 drift key): a stale rubric must **self-invalidate**, exactly as a stale local judge does. Adds an optional **`--expect-judge-hash`** flag: when set, ingest **refuses** (emits no verdict) if the score's `judge_content_hash` differs from the active rubric's hash. Empty (default) = parity not configured → legacy/dev flows unaffected. ## Scope Second of **ag-62g68**'s gate scenarios (gate #3 write-side refuse landed in #626). Pure guard `requireJudgeHashParity` is unit-tested; the flag is exercised end-to-end through `runEvalOutcomesIngest`. **Remaining bead slices stay open:** the rc3 Run-manifest write into the eval-verdict-compiler pipeline, the `--score/--suite/--bead` interface, and global-Dolt ledger persistence (wiring `registerOutcomesBurn` into the command). **Flag-only CLI change** — `COMMANDS.md` regenerated; the flag adds **no new `###`/`####` heading**, so the `cli-command-surface-matrix` canary counts are unchanged and the registry SKU (`cmd:ao.eval`) is unchanged (verified `generate-registry.sh --check` green). ## Evidence - `TestRequireJudgeHashParity` (match / mismatch-refuses / empty-no-op / empty-score-vs-configured) + `TestRunEvalOutcomesIngest_RefusesOnHashMismatch` (command-level: mismatch refuses & emits no verdict, match ingests, unset = no check). - `go build ./...` ✓ · `go test ./cmd/ao/` 9225 pass ✓ · `go vet` clean · gocyclo no findings · `generate-cli-reference.sh --check` up-to-date · `generate-registry.sh --check` OK. Closes-scenario: ag-62g68#gate2-judge-hash-parity Bounded-context: BC4-Evaluation Evidence: cli/cmd/ao/eval_outcomes_ingest.go |
||
|
|
c4552483be |
feat(cli): ao mcp serve --print-tools — curated MCP tool-descriptor surface (ag-h1mk #mcp-print-tools) (#619)
## What New `ao mcp` noun + `serve` verb exposing **`--print-tools --json`** — the curated, read-mostly MCP tool surface a hosted/SDK Claude loop uses to orient and self-check. It's the descriptor `ao agent bundle --runtime managed` (#618) already references. **Claude-only** (Codex shells `ao` directly). **Slice 1 of ag-3ucpd** (split per the evolve scope filter — the full MCP server is genuinely oversized: a from-scratch JSON-RPC stdio transport + live integration test, no MCP library vendored). This ships the deterministic, high-value, fully-testable descriptor surface now; the live transport + transport-round-trip integration test is carved to the **ag-3ucpd** umbrella for a fresh context. - `mcpToolDescriptors()` — 6 curated tools (`session_bootstrap`, `inject`, `corpus_inject`, `standards`, `validate`, `goals_measure`) with name + description + input_schema + holdout-sensitive flag. - `mcpToolDenied()` — deterministic **NOT-ZDR holdout refusal**: a tool call whose args reference `holdout` / `ground_truth` / `.agents/evals` is denied (cloud MCP surface; eval substrate LOCKED; `AGENTOPS_HOLDOUT_EVALUATOR` does **not** unlock the cloud surface). - Bare `ao mcp serve` (no `--print-tools`) errors loudly pointing at the ag-3ucpd live-transport follow-up — never a silent no-op. ## Tests (TDD-first) `cli/cmd/ao/mcp_serve_test.go` — 6 cases: curated surface (6 tools, schemas present), holdout refusal (query + path-escape), clean-call allowed, `--print-tools` JSON shape, live-transport-not-yet error. `go vet` clean, gocyclo < 15, full `cmd/ao` suite **9210 pass**. ## New-`ao`-command surfaces (all 5 regenerated up-front) The corpus-encoded checklist from #618's three-round discovery — applied in one shot, expecting one-shot-green: 1. `expectedCmds` ×2 (`mcp` inserted alphabetically) · 2. `cli/docs/COMMANDS.md` (TestCobraConformance) · 3. `registry.json` (69→70 commands, 164→165 SKU) · 4. `cli-command-surface-matrix` eval fixtures (71/177/248 → 72/178/250; smoke PASS) · 5. `docs/cli-surface.md`+`.json` (`ao mcp serve` covered). Scope-only diff (10 files, all mcp-attributable; no unrelated drift). Closes-scenario: ag-h1mk#mcp-print-tools Bounded-context: BC5-Runtime Evidence: cli/cmd/ao/mcp_serve_test.go |
||
|
|
7fc46eb76e |
feat(cli): ao agent bundle — emit runtime-specific AgentOps-native Agent definitions (ag-eguw0 #agent-bundle) (#618)
## What New `ao agent` cobra noun + `bundle` verb — emits a **runtime-specific Agent definition** that stitches the AgentOps skill set + the `ao` tool surface so an out-of-session loop (Managed Agent / Codex-NTM swarm) runs under the same guardrails. Third child of epic **ag-7s9fo** (after ag-2wln skill #616, ag-mptr CI gate #617). - `--runtime managed` → Managed Agents JSON (model + stitched instructions + `skills[]` + `ao` MCP tool descriptor; self-hosted-sandbox block on `--sandbox self-hosted`). - `--runtime codex-ntm` → NTM bundle (skills-codex/agent-native ref + pane bootstrap running `ao session bootstrap` + `ao inject`); no MCP — Codex shells `ao` directly. - Default skills: `session-bootstrap, standards, validation, provenance`. Flags: `--skills`, `--sandbox`, `--out`, `--json`. ## Security — HARD REFUSAL (NOT-ZDR) Managed Agents are **not** ZDR. `buildAgentBundle` refuses (non-zero exit + explicit message) if any selected skill **names/paths a holdout/eval surface** or its `SKILL.md` body carries a holdout marker (`private_holdout` / `ground_truth` / `holdout target`). `AGENTOPS_HOLDOUT_EVALUATOR` does **not** authorize leaking holdout to a cloud agent. The eval substrate stays LOCKED (no relitigation of `~/.agents/evals/SCHEMA.md`). Fails closed. ## Tests (TDD-first) `cli/cmd/ao/agent_bundle_test.go` — 7 cases on the pure `buildAgentBundle` seam: managed defaults + `ao` MCP descriptor; self-hosted sandbox block; codex-ntm shape (bootstrap + reference, no MCP); **holdout refusal**; unknown runtime; default-skill set; managed JSON required-keys (= the schema contract). All funcs CC < 15 (budget 25). `go vet` clean; full `cmd/ao` suite 9204 pass. ## Gates handled - Added `agent` to **both** `expectedCmds` lists (TestCobraExpectedCmdsMatchRegistration). - Regenerated `cli/docs/COMMANDS.md` (TestCobraConformance) + `docs/cli-skills-map.md`. - `ao agent bundle` reads as `public-tested`/`covered`. `docs/cli-surface.md` left at its standing tolerated state (non-blocking inventory; reverted to avoid sweeping in unrelated #613 eval-outcomes drift). ## Notes for review - **Naming**: `ao agent` (singular, new) sits beside `ao agents` (plural, AGENTS.md doctor/lint) — different domains, but the singular/plural proximity is a UX smell. Proceeded per epic spec; trivial rename if you'd prefer (e.g. `ao agentdef bundle`). - **Schema follow-up**: the managed-output structural contract is test-enforced (required-keys); a formal `schemas/agent-definition.schema.json` + validator wiring can land later if a downstream consumer needs strict validation. Kept out to bound this PR. - Instructions are stitched as skill **names + preamble**, not full bodies — bounded payload + the agent loads full skills at runtime via the `ao` tool surface (also avoids over-inlining). Closes-scenario: ag-eguw0#agent-bundle Bounded-context: BC5-Runtime Evidence: cli/cmd/ao/agent_bundle_test.go |
||
|
|
4ad5ea40f2 |
feat(eval): ao eval outcomes ingest — Outcomes score → one verdict record (ag-hdqu0 #ingest-verdict) (#603)
## What Adds `ao eval outcomes ingest <score.json>` — the third slice of ag-hdqu0. Maps an Outcomes grader score (aggregate + per-criterion) onto the **one** council verdict record (`skills/council/schemas/verdict.json`: PASS/WARN/FAIL + `satisfaction_score` + `satisfaction_breakdown`), closing the **Outcomes → Knowledge Flywheel** loop without forking the verdict format. Pairs with `ao eval outcomes compile` (#601). Verdict bands: PASS ≥ threshold · FAIL < 70% of threshold · WARN between. ## One-shot surface landing (compounding from #601/ag-lkxx) `ingest` is a `#####` leaf, so heading counts are unchanged — only an allowlist entry was needed. Ran `scripts/test-agentops-contract-canaries.sh` locally **before pushing**: `cli-command-surface-matrix verdict=pass aggregate=1`. No CI canary round-trips. ## Tests (TDD) - `TestIngestOutcomesScore_ProducesVerdictRecord` — PASS verdict, satisfaction_score=aggregate, breakdown=criterion scores, schema_version 4, non-nil findings. - `TestIngestOutcomesScore_VerdictBands` — PASS/WARN/FAIL banding. - `go test ./cmd/ao` green, vet/build clean. Closes-scenario: ag-hdqu0.2#ingest-verdict Bounded-context: BC1-Corpus Evidence: cli/cmd/ao/eval_outcomes_ingest_test.go |
||
|
|
a3900ad0dc |
feat(eval): ao eval outcomes compile — holdout-safe rubric payload (ag-hdqu0 #compile-strip) (#601)
## What Adds `ao eval outcomes compile <input.json>` under `eval` — the second slice of ag-hdqu0, building directly on the merged `evalsubstrate.ProjectRubric` (#599). Projects a locked Task + criteria into an Outcomes rubric payload. ## Holdout isolation (Managed Agents are NOT ZDR) - Projection via `ProjectRubric` (strips ground truth by construction). - **Deny-by-default re-scan** (`ContainsAny`, guard layer 3): `compileOutcomesRubric` REFUSES to emit any rubric that would carry a holdout value (input `holdout_values` feeds the scan; never copied to output). - Carries `judge_content_hash` for stale-rubric self-invalidation. Outcomes is a derived projection of the locked SCHEMA.md — never an alternate authority. ## Tests (TDD) - `TestCompileOutcomesRubric_StripsHoldoutTarget` — criteria carried, zero holdout leak. - `TestCompileOutcomesRubric_RefusesLeak` — deny-by-default errors on a leaking criterion, names the value. - 9184 `cmd/ao` tests pass, `go vet`/`build` clean, `COMMANDS.md` regenerated for the new subcommand. ## Next in ag-hdqu0 `.2` ingest→verdict; `.4` re-parse/stale-hash; `.9` gate#3 burn ledger (remaining half); the future GT-loader slice wires `holdout_values` from the substrate automatically. Closes-scenario: ag-hdqu0.1#compile-strip Bounded-context: BC1-Corpus Evidence: cli/cmd/ao/eval_outcomes_test.go |
||
|
|
e4e32a3374 |
feat(orchestration): dual-runtime OrchestrationPort foundation (ag-nk67 #orchestration-foundation) (#598)
## What
The **dual-runtime OrchestrationPort foundation** — the seam that gates
the
`[EPIC] AgentOps × Claude Managed Agents integration (dual-runtime)`
application epics.
Implements the 3-category model (Claude Workflow / NTM swarm / plain
skill) behind a
single `OrchestrationPort` with safe degradation **NTM → Claude-native →
beads floor**
and a global `AGENTOPS_ORCHESTRATION=off` opt-out.
Derived from a live 3-legged spike (`~/dev/agentops-3cat-spike/`): safe
degradation is
solvable at the selection layer; parallel buys quality/independence not
wall-clock at
small N; NTM is a multi-vendor control plane that runs Claude/Codex as
panes.
## What's in it (10 slices, agent-team driven)
- **Port + adapters** — `cli/internal/ports/orchestration.go` (idiomatic
to existing ports pattern) + new `cli/internal/orchestration/` pkg:
`Selector`, `ntm_probe` (capability detection via `ntm
--robot-capabilities`, not `command -v`), `beads_floor` +
`OrchestrationResult` parity type, degradation-conformance test.
- **Live CLI** — `ao orchestrate select` (`--pin`/`--opt-out`/`--json`);
COMMANDS.md regenerated.
- **Contracts** — `schemas/orchestration-{backend,result}.v1` + paired
`docs/contracts/` docs (structural-floor gated: 41 contracts).
- **Prose** — swarm/shared/crank rewritten NTM>native>beads; **gc
demoted** (soc-2rtm0); `rpi_phased_stream.go` doc-comment fixed.
- **Skills** — `automation-shape-routing` (the 3-category router) +
`workflow-builder` + meta-skill authoring chain wired (`context_rel`);
skill counts synced.
- `lib/orchestrate-select.sh` selector seam.
## Verification (local)
`go build ./...` clean · `go vet` clean · **56 Go tests pass**
(orchestration 31, ports 10, cmd/ao orchestrate 15) · structural-floor
PASS (41) · `lib/orchestrate-select.sh --self-test` 6/6 · live command:
`--json`→claude (NTM absent), `--opt-out`→beads, `--pin claude`→claude.
## Notes
- Bundles the foundation + the routing/authoring skills as one coherent
dual-runtime arc.
- NTM/Claude executors are stubs (the parity contract is real); concrete
executors land in the application epics this gates.
- Two-ladders distinction preserved (spawn-backend ladder A vs CLI
phase-executor ladder B) — see `docs/contracts/orchestration-ports.md`.
Closes-scenario: ag-nk67#orchestration-foundation
Bounded-context: BC5-Runtime
Evidence: cli/internal/orchestration/conformance_test.go
|
||
|
|
bd4d97c292 |
feat(beads): ao beads scenarios extract --write — operator-confirmed write-back (ag-3gm #write-confirm) (#571)
## Summary Slice 2 of **ag-dwq** (the bead-acceptance → Gherkin extractor line). Adds `--write` to `ao beads scenarios extract <id>`: - After printing the candidate block and a `y/N` prompt, appends the rendered `## Scenarios` block to the bead's description via `bd update` — **only on confirmation**. - Declining (or EOF / empty input) leaves the bead unchanged (safe default). - The block is **appended**, not replacing the description, so the original acceptance prose is preserved (lossless). - `--write` short-circuits behind the existing already-has-block guard, so it won't duplicate an authored block unless `--force` is also passed. Read-only `extract` (dry-run) and `validate` behavior are untouched. Closes the `--write` slice of the extractor; the LLM-prose fallback remains a separate later slice of ag-dwq. ## Test plan - [x] Test-first: 2 new L2 tests map to the bead's single Given/When/Then — confirm → lossless write (`bd update` carries `## Scenarios` + preserves original prose); decline → no `bd update` (bead unchanged). - [x] `cd cli && go build ./... && go vet ./cmd/ao` clean. - [x] `cd cli && go test ./cmd/ao` green (full package). - [x] `scripts/generate-cli-reference.sh` regenerated `COMMANDS.md` (only the `--write` flag line added). Closes-scenario: ag-3gm#write-confirm Bounded-context: BC1-Corpus Evidence: cd cli && go test ./cmd/ao -run 'TestRunBeadsScenariosExtract_Write' |
||
|
|
2c5ac99e4d |
feat(beads): ao beads scenarios validate <id> — well-formedness check (ag-5cz #scenarios-validate) (#569)
## Summary Slice 4 of **ag-dwq** (child bead **ag-5cz**). Adds `ao beads scenarios validate <bead-id>`: a read-only, **dependency-free** validator for an authored `## Scenarios` Gherkin block. It is the inverse acceptance gate of the `extract` slice (#567) — extract turns acceptance into a candidate block; validate confirms an authored block is well-formed. - **`cli/internal/scenarios/validate.go`** (new, pure domain): `ParseBlock(text) ([]Scenario, error)` + `Validate(text) error`. A deterministic in-repo parser — **no `github.com/cucumber/gherkin-go` dependency** (the bead's open design question, resolved toward the repo's established dependency-free pattern). Each scenario must declare a name and a Given/When/Then step in that order with a non-empty body; `And`/`But` lines are accepted as continuations. Refactored into `groupScenarios`/`assemble`/`checkStepOrder` to stay under the cyclomatic-complexity budget (max 14 < 25). - **`cli/cmd/ao/beads_scenarios.go`**: `validate` subcommand under the existing `ao beads scenarios` surface. Agent-ergonomic (Directive 13): exits 0 when well-formed, non-zero **naming the parse error** otherwise; `--json` emits a verdict object (`{bead_id,valid,scenarios}` on success / `{bead_id,valid:false,error}` on failure) on **stdout** with diagnostics on **stderr**; `bd`-unavailable degrades gracefully (warn + exit 0). - **`cli/docs/COMMANDS.md`** regenerated. `capabilities` / `robot-docs` pick the command up automatically via the live command-tree walk. Surface heading counts are **unchanged** (validate is a `#####` leaf under the existing beads-scenarios group, so the `#{3,4}` command-surface canary is unaffected). ### Out of scope (remaining ag-dwq slices) `--write` / operator-confirmed bead update (**ag-3gm**) · LLM fallback for non-deterministic prose. Parent **ag-dwq** stays OPEN. ## Test plan - [x] `cd cli && go test ./internal/scenarios/...` — 14-case `TestParseBlock` table (well-formed single/multi, And/But continuations, block bounded by following heading, prose-prefixed block, no-block, no-Scenario, missing-name, missing Given/When/Then, out-of-order, empty-body, And-before-primary) + Validate nil/error + Render round-trip - [x] `cd cli && go test ./cmd/ao -run Scenarios` — L2 with stubbed `bd`: well-formed exit 0, malformed error, no-block error, `--json` success/failure verdicts, bd-unavailable graceful, read-only contract (no `bd update`) - [x] `cd cli && go build ./... && go vet ./... && go test ./...` — 11951 passed, 69 packages, 0 failures - [x] Real binary: `ao beads scenarios validate ag-3gm` → exit 0 (1 scenario well-formed); `ag-dwq` (free-text) → exit 1 naming the missing block; `--json` verdicts valid - [x] `gocyclo -over 15 internal/scenarios/` — clean; `scripts/generate-cli-reference.sh --check` — up to date; command-surface smoke — `top=69 sub=174 all=243`, exit 0 Closes-scenario: ag-5cz#scenarios-validate Bounded-context: BC1-Corpus Evidence: cd cli && go test ./internal/scenarios/... ./cmd/ao -run Scenarios |
||
|
|
70b6d638dc |
feat(beads): idempotent '## Scenarios' guard + --force for scenarios extract (ag-kyn #scenarios-guard) (#568)
## Summary Next slice of the open epic **ag-dwq** (Gherkin scenarios extractor). Slice 1 (`ag-ljd`, the dry-run `extract` command) merged in #567; this adds the **idempotent guard** (ag-dwq scenario 3): `ao beads scenarios extract <id>` now **refuses** when the bead already carries a `## Scenarios` block — prints a diagnostic to stderr naming `--force` as the corrective action, exits 0, emits nothing on stdout — **unless `--force`** is passed, in which case it re-extracts and prints normally. - New pure `scenarios.HasScenariosBlock(text)`: detects a markdown `## Scenarios` section heading (plural-only, case-insensitive). A bare `Scenario:` line or singular `## Scenario:` heading does **not** match. - Fetch now returns the bead's acceptance **and** description (`fetchedBead`) so the guard can inspect the description, where authored scenario blocks live. - Stays a **dry-run**; no bead mutation on any path. Out of scope (remain in parent ag-dwq): `--write`, `validate` subcommand + Gherkin parser dep, LLM fallback. > **Bead note:** the canonical follow-up bead for this work is **ag-kyn** (filed by a concurrent RPI cycle as a child of ag-dwq). A duplicate bead `ag-gam` was created before ag-kyn was visible; `ag-gam` is closed as duplicate-of `ag-kyn`. Branch name retains the `ag-gam` token but the work closes `ag-kyn`. ## Test plan - [x] `cd cli && go build ./... && go vet ./... && go test ./...` — clean (66 pkg ok, 0 fail) - [x] `go test ./internal/scenarios/ ./cmd/ao` — targeted, incl. new `TestHasScenariosBlock` (11 cases) + 2 new L2 guard tests - [x] Real binary: refuses on `ag-ljd` (has block), extracts on `ag-dwq` (free-text bullets) - [x] `cli/docs/COMMANDS.md` regenerated; `cli-command-surface-matrix` smoke passes (69/174/243 — flags aren't headings) Closes-scenario: ag-kyn#scenarios-guard Bounded-context: BC1-Corpus Evidence: cd cli && go test ./internal/scenarios/ ./cmd/ao |
||
|
|
a31999a061 |
feat(beads): ao beads scenarios extract → Gherkin to stdout (ag-ljd #scenarios-extract-stdout) (#567)
## Summary Slice 1 of **ag-dwq** (child bead **ag-ljd**). Adds `ao beads scenarios extract <bead-id>`: a deterministic, dependency-free, **dry-run** command that converts a bead's free-text acceptance criteria into a candidate Gherkin `## Scenarios` block printed to stdout. The bead is never modified. - **`cli/internal/scenarios`** (new, pure domain): `Extract(acceptance) ([]Scenario, error)` + `Render([]Scenario) string`. Word-boundary `given`/`when`/`then` matching so `forgiven`/`whenever` don't false-match; each clause must carry a letter so prose merely *mentioning* "Given/When/Then" isn't mistaken for a scenario. - **`cli/cmd/ao/beads_scenarios.go`** (new): subcommand under the existing `ao beads` surface, fetching via the `execBD show --json` seam. Agent-ergonomic (Directive 13): `--json` emits data on stdout / diagnostics on stderr; `bd`-unavailable degrades gracefully (warn + exit 0); errors name the corrective action (manual authoring). - **`cli/docs/COMMANDS.md`** regenerated. `capabilities` / `robot-docs` pick the command up automatically via the live command-tree walk. ### Out of scope (later slices of ag-dwq) `--write` / operator-confirmed update · idempotent `## Scenarios` guard + `--force` · `scenarios validate` + Gherkin-parser dep · LLM fallback for non-deterministic prose. ## Test plan - [x] `cd cli && go test ./internal/scenarios/...` — 12 cases (single/multi-bullet, sentence-form, mixed casing, skip-unparseable, empty→error, no-keywords→error, word-boundary, prose-mention→error, Render exactness, round-trip) - [x] `cd cli && go test ./cmd/ao -run BeadsScenarios` — L2 with stubbed `bd`: stdout Gherkin, `--json`, unparseable→error, bd-unavailable graceful, `parseAcceptanceFromBDJSON` (array/object/fallback/empty/malformed) - [x] `cd cli && go build ./... && go test ./...` — 11950 passed, 68 packages, 0 failures - [x] Real binary against `ag-dwq` → 5 clean scenarios; `--json` valid Closes-scenario: ag-ljd#scenarios-extract-stdout Bounded-context: BC1-Corpus Evidence: cd cli && go test ./internal/scenarios/... ./cmd/ao |
||
|
|
6c5a88694c |
feat(cli): ao skills find <intent> skill discovery (ag-a97 #find-ranks) (#563)
## Summary
Turns the 75-skill catalog from oral tradition into a queryable surface.
`ao skills find <intent>` scores every `skills/*/SKILL.md` against a
free-text
intent and returns the top matches (name, one-line description, score) —
so an
agent gets a discovery API instead of memorizing skill names.
- **Scoring engine** (`cli/internal/skills/find.go`) — pure,
deterministic
token-overlap. A query word hitting the skill **name** counts most, a
declared
**trigger** next, a **description** word least, with light plural/stem
tolerance (`loop` ↔ `loops`). Scores normalized to `[0,1]`; ties broken
by
name. No filesystem access, so it is fully table-testable.
- **Loader** (`cli/internal/skills/load.go`) — reads
`skills/*/SKILL.md`, parses
frontmatter (`name`, `description`, best-effort top-level / `metadata`
triggers). No static index file: a newly added skill is found on the
next run.
- **Command** (`cli/cmd/ao/skills_find.go`) — `--json` / `--limit`
(default 5),
stdout-as-data / stderr-as-diagnostics. An unmatched intent **exits 0**
with a
stderr note, not an error. Unknown-flag typo hints inherited from the
root
cobra config; `--limit < 1` returns a usage error naming the fix.
- Regenerated `cli/docs/COMMANDS.md`.
### Notes / corrections
- The bead's premise ("each SKILL.md has a populated `triggers:` array")
is
inaccurate — phase-1 discovery found **0/75** top-level `triggers:`
arrays;
intent lives as prose in `description`, with `metadata.triggers` in ~10
skills.
Scoring therefore treats name+description as the primary signal and
triggers as
an optional boost.
- Bounded context: the slice reads the **skills corpus** (SKILL.md
content), so
`BC1-Corpus` (the plan's draft `BC4-Practice` does not exist — BC4 is
Evidence).
- Deferred to follow-ups: `ao skills list --by-trigger` /
`--list-triggers`
(ag-0r0) and backfilling structured triggers across SKILL.md (ag-piv).
## Test plan
- [x] `cd cli && go test ./internal/skills/... ./cmd/ao` (green)
- [x] `cd cli && go build ./... && go vet ./internal/skills/...
./cmd/ao`
- [x] `scripts/generate-cli-reference.sh` (COMMANDS.md in conformance)
- [x] `bash skills/heal-skill/scripts/heal.sh --strict` (All clean)
- [x] `ao autodev validate --file PROGRAM.md --json` → `valid: true`
- [x] Manual smoke: `ao skills find "close the loop"`, `--json --limit
3`, unmatched intent
Closes-scenario: ag-a97#find-ranks-relevant-skills
Bounded-context: BC1-Corpus
Evidence: cli/internal/skills/find_test.go + go test
./internal/skills/... ./cmd/ao
|
||
|
|
3f4b67be49 |
feat(cli): add reconciliation report (#550)
## Summary - add `ao reconcile` for a read-only git/GitHub release/beads/.agents decision report - emit both human and `--json` output with ranked findings and next actions - anchor external checks at the git root and disable bd Dolt auto-start for this read-only scan - update generated CLI docs and JSON flag consistency coverage ## Validation - `cd cli && go test ./cmd/ao -run 'TestReconcile|TestCapabilities'`\n- `cd cli && make build`\n- `cd cli && bin/ao reconcile --json | jq ...` (live run detected green main Validate plus failed `v3.0.1` tag Validate)\n- `bash tests/cli/test-json-flag-consistency.sh`\n- `bash scripts/validate-ci-policy-parity.sh`\n- `./scripts/generate-cli-reference.sh --check`\n- `git diff --check`\n- `scripts/pre-push-gate.sh --fast` (passes; existing warn-only executable-spec warnings for `scenarios --lint` and `trace --orphans`)\n\nNote: a broad local `go test ./cmd/ao` run was stopped after it appeared hung with no child test process; the focused command tests and build passed, and CI should provide the full-package signal. |
||
|
|
010ade393c |
feat(rip)!: carve the daemon — delete internal/daemon + agentopsd, GC is the substrate (soc-2rtm0 #daemon-carve wave5) (#515)
Wave 5 of 5 (the finale) of the orchestration-substrate retirement (soc-2rtm0). AgentOps stops being the orchestration substrate; GC is the substrate. The always-on out-of-session supervisor (the daemon) is deleted; GC's controller replaces it. Features that ran AS daemon jobs (wiki build, llmwiki loop) keep their BUILDER CORE (in-process / GC-callable) but lose the daemon-job-executor wrapper. ## Deleted - `cli/internal/daemon/` — the whole package (71 .go files + testdata + AGENTS.md). - `cli/cmd/ao/`: `agentopsd.go`, `daemon_jobs.go`, `daemon_soak.go`, `daemon_fake_policy.go`, `rpi_phased_daemon.go` (+ their tests). - Daemon-only tests: `rpi_status_daemon_test.go`, `rpi_integration_test.go`, `doctor_product_runtime_test.go`. - `internal/doctor/fix_daemon.go` (+test) + the daemon runtime/ledger-health/telemetry/openclaw-consumer checks and the `--product-runtime` flag in `doctor.go` (the `ao doctor` command itself is KEPT). - The `ao daemon`/`agentopsd` command registration (went with `agentopsd.go`). - Daemon test scripts: `scripts/validate-daemon-product-e2e.sh`, `tests/scripts/test-daemon-product-e2e.sh`. No daemon CI gates existed in `validate.yml` / `ci-jobs.yaml` to remove (prior waves had already cleared them). ## Severed (KEEP features — builders stay, daemon-job-executor wrappers removed) - **wiki** (`internal/wiki/pipeline.go`): removed the `daemon.JobExecutor` impl (`JobTypes`/`RunJob`/`PipelineJobSpec`/`parsePipelineJobSpec`/`jobResultFromOutcome`) + the daemon import. The builder core — `WikiPipeline`, `RunStage`, `SelectStage`, the ingest/query/lint runners — is untouched; `ao wiki lint/query/promote` run in-process. - **llmwiki** (`internal/llmwiki/executor.go`): removed `LLMWikiLoopExecutor` + `LoopJobSpec` + the daemon import. KEPT the leaf builder core in the same file (`Stage`, stage constants, `StageHandler`, `StageResult`, `DefaultLintIntervalHours`, `SelectStage`, `rawHasNewerFiles`, `lintIsStale`) — `stages.go` (the real handlers) and `internal/scope` depend on these. No new package needed; the shared types already lived in this leaf file. - **rpi status** (`cmd/ao/rpi_status.go`): severed the `--daemon`/`--daemon-url`/`--daemon-fallback` read path. `ao rpi status` now reads only the local run registry (`.agents/rpi/runs/`) — a KEEP feature. Relocated the tiny `cobraContext` helper here (it lived in the deleted `agentopsd.go`, only consumer is this file). - **rpi phased** (`cmd/ao/rpi_phased.go`, `rpi_phased_context.go`): removed the `--daemon-submit` short-circuit + flags + the `DaemonSubmit/URL/Token/Fallback` opts fields (only consumer was the deleted submit path). ## Lost capabilities (intentional, daemon-only) - `ao rpi status --daemon` (read RPI job state from agentopsd) and `ao rpi phased --daemon-submit` (queue an RPI run to agentopsd). - llmwiki `LoopJobSpec.AllowPlaceholderOutputs` opt-in gating (the placeholder-output-disabled skip) — that gate lived in the removed daemon-job wrapper, not the stage handlers. - `ao doctor` daemon runtime/ledger-health/telemetry/openclaw-consumer checks + `--product-runtime`. ## Verification (all green) - `gofmt -l` clean (my files), `go build ./...`, `go vet ./...`, `go test ./...` → 11920 passed, 0 failed, 65 packages. - `scripts/release-smoke-test.sh` → 108 pass / 0 fail (EXPECTED_COMMANDS never listed daemon; no scrub needed). - `tests/windows/test-windows-smoke.ps1` → `Invoke-GoTest` list has no `./internal/daemon` ref (nothing to scrub). - `internal/quality/stale_refs.go` → no daemon/agentopsd deprecated-command entries (`TestDoctorStaleReplacementsExist` passes). - `tests/smoke-test.sh`, `tests/cli/test-json-flag-consistency.sh` (15/0), `scripts/test-agentops-contract-canaries.sh` (failures=0 after fixing the cli-command-surface heading-count fixture/eval 68/179/247 → 67/172/239 and the `ao daemon` refs in `skills/dream` + `skills-codex/dream`). - Regenerated `cli/docs/COMMANDS.md` + `registry.json`; `regen-codex-hashes.sh --check` clean; `validate-ci-policy-parity.sh` PASS; doc link/learning-ref checks pass; `heal.sh --strict` clean. Diff stat: 113 files changed, 95 insertions, 34,978 deletions. Closes-scenario: soc-2rtm0#cascade-rip Bounded-context: BC5-Runtime Evidence: .agents/discovery/2026-05-24-rip-caller-map.md |
||
|
|
d52144ed40 |
feat(cli): ao validate --gate — exit-code verdict for GC retry + CI (#ao-validate-gate) (#516)
## What
New top-level `ao validate` umbrella command with `--gate`
(exit-code-as-verdict) mode. This is the dependency the GC reference
City needs — GC's `check={max_attempts}` retry, CI steps, and `ao rpi`'s
internal validate phase can run one command and branch on the exit code.
Spec: `.agents/discovery/2026-05-24-gvkj6-finalize-runbook.md` ("`ao
validate --gate` — SPEC" section).
## Exit-code contract (`--gate`)
| Code | Meaning |
|---|---|
| `0` | PASS or WARN (gate passes) |
| `1` | FAIL (gate fails) |
| `2` | internal/setup error (distinct so a broken gate is never read as
a clean pass) |
- WARN exits `0` by default (advisory); `--strict` / `--warn-as-fail`
promotes WARN → exit `1`.
- Deterministic: **no network, no LLM**. Safe for GC
`check.max_attempts`, CI, and `ao rpi`.
- `--json` emits `{"verdict","issues","warnings","gate_exit"}` in both
modes.
## How (composed, not reinvented)
Reuses the existing `ratchet.Validator` (`ValidateWithOptions`) over the
resolved file set (`--changes`, `--bead`, or auto-located RPI outputs);
aggregates each result's `Valid`/`Issues`/`Warnings` into a single
PASS/WARN/FAIL verdict; maps verdict → exit code via a `gateExitError`
typed error caught in `Execute()` (same pattern as
`doctorExitError`/`AgentsLintError`). The existing `ao
ratchet/scenario/goals validate` sub-surfaces are untouched. New logic
is just the aggregation + mapping (well under the complexity budget).
## Residue handled (command-surface +1)
- Regenerated `cli/docs/COMMANDS.md`, `registry.json` (166 commands),
`docs/cli-skills-map.md`.
- Bumped `cli-command-surface` canary
(`cli-command-surface-matrix.json`) + smoke fixture heading counts: top
68→69, all 247→248 (sub unchanged — flat command).
- Added `validate` to release-smoke `EXPECTED_COMMANDS` + a `test_help
"ao validate --help"` line.
- Registered `validate` in `cobra_commands_test.go` `expectedCmds` (both
lists).
## Tests
L1 (`aggregateVerdict`, `gateExitForVerdict`, `gateExitError`) + L2
(full `runValidate` over real temp-dir artifacts) asserting exact exit
codes: PASS=0, WARN=0, WARN+`--strict`=1, FAIL=1, internal=2, and the
`--json` contract.
## Verified green
`gofmt` clean · `go build`/`go vet`/`go test ./cmd/ao
./internal/ratchet` · manual exit-code check (0/1/2) ·
`release-smoke-test.sh` (0 failed) · `test-json-flag-consistency.sh` (0
errors) · `validate-cli-skills-map.sh` (PASS) · `cli-command-surface`
canary (failures=0) · `regen-codex-hashes.sh --check` clean ·
`validate-ci-policy-parity.sh` PASS.
Closes-scenario: soc-ba1un#ao-validate-gate
Bounded-context: BC4-Evidence
Evidence: .agents/discovery/2026-05-24-gvkj6-finalize-runbook.md
|
||
|
|
1ba0ca8120 |
feat(rip)!: kill schedule/plans/watch/overnight commands+engines — GC owns scheduling (soc-2rtm0 #kill-schedule-overnight wave3-4) (#514)
Wave 3+4 of the soc-2rtm0 orchestration-substrate rip. Operator decision: **kill the schedule/plans/watch/overnight commands AND their engines entirely** — GC owns all scheduling/overnight/watch; AgentOps keeps only rpi/evolve/crank/swarm as loops. ## Killed (commands + engines) - `cli/cmd/ao/`: `overnight*.go` (overnight, council, curator, packets, setup, longhaul, daemon, tier1), `dream_subcycle.go`, `schedule.go`, `watch.go`, `plans*.go` (+ all tests). - `cli/internal/schedule/` — clean delete (only `schedule.go` + `agentopsd.go` imported it). - `cli/internal/overnight/` — the overnight engine, deleted whole. - Daemon refs severed (daemon stays, wave 5): removed `agentopsd.go` dream-executor + crash-recovery + `--schedule-file` loading; removed the `dream` soak scenario. - Removed `ao init --with-schedule` (seeded config for the now-dead daemon scheduler). - Retired the `dream` skill (claude + codex) to a GC-pointer stub. ## KEEP-feature severance (HARD CONSTRAINT) - **harvest** (KEEP): lock helpers (`LockIsStale`/`ReadLockPID`/`ProcessAlive`/`WriteLockPID`) **extracted** from `overnight/recovery.go` into new `cli/internal/lockfile` package; `harvest.go` repointed. Generic process-lock machinery, not overnight-specific. - **forge** (KEEP): `writeJSONAtomic` + `buildCuratorID` + curator-queue types **extracted** into `cli/cmd/ao/forge_curator_id.go`; forge curator-queue enqueue path preserved. - **evolve** (KEEP): the `--dream-first`/`--dream-only` Phase-1 dream sub-cycle was **severed** (capability genuinely overnight/dream-only). **LOST CAPABILITY** — flagged below. - `forge/runmine.go` + `wiki/artifact.go` only referenced overnight in comments (no real import) — untouched. ## CI gates / docs / fixtures reconciled - Removed `dream-end-user-coverage` GOALS gate + `scripts/check-schedule-example.sh` + `schedule.yaml.example` + `goals-affects-files.yaml` entry; updated GOALS Directive #8. - Fixed `cli-command-surface` canary: heading counts 72/194/266 → 68/179/247, dropped deleted `plans.go` artifact check. - Deleted `dream-software-factory-operator` eval; dropped deleted `plans.go` check from `session-continuity-context` eval. - Regenerated `COMMANDS.md`, `cli-skills-map.md`, `registry.json`; regenerated codex hashes. - No dedicated validate.yml/ci-jobs.yaml job existed for these surfaces (verified) — `validate-ci-policy-parity` stays PASS. ## Lost capability (flagged) - `ao evolve --dream-first` / `--dream-only` (run the knowledge-compounding dream loop before/instead of code cycles) is gone. Knowledge compounding now runs out-of-session via GC. The nightly-CI dream-cycle proof job (built on KEEP harvest/forge/inject/defrag primitives) is unaffected. ## Verification (all green) `cd cli && gofmt -l` clean · `go build ./...` · `go vet ./...` · `go test ./...` (zero FAIL) · `tests/smoke-test.sh` · `tests/cli/test-json-flag-consistency.sh` (0 errors) · `scripts/test-agentops-contract-canaries.sh` (**failures=0**) · doc-release gate · `heal --strict` clean · skill-lint · codex parity · ci-policy-parity. ## Follow-up (out of scope, build-green-safe to defer) Narrative docs (`docs/scheduling.md`, `docs/ARCHITECTURE.md`, comparisons, etc.) still mention the killed `ao overnight`/`ao schedule` commands in prose. No CI gate validates ao-subcommand existence in narrative docs, so these do not block; a doc-sweep is a separate follow-up. Closes-scenario: soc-2rtm0#cascade-rip Bounded-context: BC5-Runtime Evidence: .agents/discovery/2026-05-24-rip-caller-map.md |
||
|
|
cd6a7031ad |
feat(rip): sever + delete gc-bridge glue, phased engine keeps non-gc backends (soc-2rtm0 #gcglue-rip wave2) (#513)
Wave 2 of 5 of the orchestration-substrate retirement (soc-2rtm0). Severs the Gas City (gc) bridge glue from the phased RPI engine and deletes it. The phased engine keeps its non-gc backends (auto/direct/stream/tmux); the `gc` runtime mode is removed. Wave 1 (factory) merged as #512. ## What changed (Edge B sever, per recon map) **Typedef relocation:** Moved the injectable `gcExecFn`/`gcLookFn` func-typedefs out of the deleted `gc_bridge.go` into the KEEP file `rpi_phased_context.go`, renamed to `execFn`/`lookFn` (they are no longer gc-specific — used by `rpi_phased_setup.go`, `tracker_health.go`, `rpi_phased_stream.go`, `rpi_phased_context.go` for runtime/binary preflight). All callsites updated. **Phased selector patched (drop `gc` backend):** - `rpi_phased_stream.go` — removed the `case "gc":` executor + the auto-gc-preferred branch (auto now goes straight to stream) + the `gcExecutor` backendMode type-assertion. - `rpi_phased.go` — removed the `gc` preflight branch, the auto-gc branch, `preflightGCRuntimeAvailability`, and `gc` from the `--runtime` flag help + completion list. - `rpi_phased_context.go` — `validateRuntimeMode` drops `gc`; removed the `GasCityClient`/`GCCityPath`/`GCCityName` opts fields (their type died with `rpi_phased_gc.go`). - `doctor.go` — removed the GasCity Bridge + GasCity Product Runtime health checks (`checkGasCityBridge*`, `checkGasCityProductRuntime*`, `formatGasCityDiagnostic`); rest of doctor (daemon/ledger/openclaw checks) untouched. - `rpi_phased_domain_enforce.go` — emptied `opaqueRuntimeModes` (gc was the only opaque runtime); kept the `unavailable` enforcement schema path. **Files deleted:** `gc_bridge.go`, `gc_events.go`, `rpi_phased_gc.go` + their `_test.go` sidecars + `gc_test_helpers_test.go`. **Spillover fixes (both viral helpers defined in deleted files):** - `codex_runtime.go` re-pointed to `bridge.CompareSemver` (was using `compareSemver`, a thin wrapper that lived in `gc_bridge.go`). - `writeSSEFrame` test helper relocated into `rpi_integration_test.go` (the remaining daemon-gascity L3 smoke test that uses it). **Docs/generated:** scrubbed the CLAUDE.md "Gas City (gc) bridge" line and `cli/internal/gascity/AGENTS.md` cross-ref; regenerated `cli/docs/COMMANDS.md` + `registry.json`. ## Scope boundary The daemon's own GasCity client (`internal/gascity`, `internal/daemon` `GasCityClientAdapter`, `agentworker`) is a separate surface — left untouched (that's wave 5). No CI gate referenced the deleted glue (confirmed). ## Verification (all green) - `gofmt -l` clean (my files) · `go build ./...` · `go vet ./...` · `go test ./...` (11834 passed, 68 pkgs) - `tests/smoke-test.sh` · `tests/cli/test-json-flag-consistency.sh` (15 pass, 0 err) - `scripts/test-agentops-contract-canaries.sh` (failures=0) - `scripts/validate-ci-policy-parity.sh` (63 rows) · `scripts/generate-registry.sh --check` (up to date) - `tests/docs/validate-doc-release.sh` (CLI headings 72) · `check-docs-learning-references.sh` · `cli-docs-parity` stable · `check-test-staleness.sh` (0 stale) Diff stat: 23 files, +72 / -4099 (delete-heavy rip; insertions concentrated in deliberately-edited files). Closes-scenario: soc-2rtm0#cascade-rip Bounded-context: BC5-Runtime Evidence: .agents/discovery/2026-05-24-rip-caller-map.md |
||
|
|
ee748d580d |
feat(rip)!: retire factory command + contract corpus (soc-2rtm0 #cascade-rip) (#512)
**Wave 1 of the orchestration-substrate cascade rip** (soc-2rtm0). The
full cascade (daemon + dream/overnight + schedule/plans/watch + gc-glue
+ factory) is ~50K LOC across deeply-entangled packages — far past one
reviewable PR. Per the bead's slice directive and the recon map's
serial-by-wave verdict, this ships as sequential PRs by wave. **This is
the factory wave** (the only cleanly-disjoint slice — no KEEP-feature
entanglement).
## What this retires (operator-confirmed FULL factory retire)
**Go command surface** (no external non-test caller — clean delete):
- `cmd/ao/factory.go`, `factory_admit.go`, `factory_pilot.go`,
`factory_admission_adapter.go` (+ all tests)
- `internal/ports/factory_admission.go` +
`inmemory_factory_admission.go` (+ test) — the port was only wired to
the daemon by the deleted production adapter
- severed factory flag save/restore + command-tree assertions from
`cobra_commands_test.go` / `testutil_test.go`
**Contract corpus** (scripts, schemas, contract docs, runbooks,
fixtures, tests):
- `scripts/check-factory-{admission,claim-ledger,yield-ledger}.sh`
- `schemas/factory-{admission,work-order,yield}.v1.schema.json`
- `docs/contracts/factory-{admission,claim-ledger,yield-ledger}.*`
-
`docs/runbooks/{factory-manual-merge,daemon-factory-admission,cloud-frontier-pilot}.md`
- `tests/e2e/factory-operator-canary.sh`,
`tests/integration/test-factory-claim-ledger-ci-job.sh`,
`tests/scripts/test-factory-admission-contracts.py`,
`tests/fixtures/factory-*`
- orphaned `aggregate-observation-log` subsystem (script + integration
test + fixtures) — its only data source was the deleted
`factory-claim-ledger-strict` CI job
**CI / generated reconciliation:**
- removed 3 factory jobs from `validate.yml` (+ both `needs:` arrays +
verdict echoes); removed entries from `ci-jobs.yaml`; regenerated
`AGENTS-CI.md` (63 jobs)
- removed factory gate-ids from `GOALS.md`; trimmed
`contracts-structural-floor` factory references
- regenerated `registry.json` (177→174 CLI commands), `COMMANDS.md` (−70
lines), `cli-skills-map.md` (73→72 headings)
- updated `cli-command-surface-matrix` canary spec + fixture counts
(`top=72 sub=194 all=266`); scrubbed deleted-file links from
`documentation-index.md`, `SCHEMAS.md`, `contracts/index.md`,
`agentopsd-control-plane.md`, `insert-schema-practices.py`
## Deliberately left for the daemon-carve wave
Daemon-owned factory job types (`factory.admission`,
`factory.local-pilot`) and the `agentopsd` routing-policy schema remain
— they belong to `internal/daemon/` and retire when the daemon does.
## Gates verified green locally
`gofmt`/`go build`/`go vet`, full Go test (**11830 pass**),
`validate-ci-policy-parity`, `contract-compatibility`,
`contracts-structural-floor`, `registry --check`, `doc-release` (0
broken links), `smoke-test`, `json-flag-consistency` (0 errors),
**`contract-canaries` (failures=0)**, codex-hashes, `pre-push-gate.bats`
(55).
Diff: 66 files changed, ~16 insertions / ~5680 deletions.
Closes-scenario: soc-2rtm0#cascade-rip
Bounded-context: BC5-Runtime
Evidence: .agents/discovery/2026-05-24-rip-caller-map.md
|
||
|
|
e431339c40 |
feat(hookless)!: remove all hooks — skills + CLI only (soc-57b7f #remove-all-hooks) (#511)
## What AgentOps 3.0 goes **fully hookless**. This removes the entire hook product surface — the product is now skills + the `ao` CLI with **zero hooks**. CI is the authoritative gate. ## Deleted - `hooks/` — 46 hook scripts + `hooks.json` + examples (whole directory) - `cli/embedded/hooks/` + embedded `hooks.json` + `embedded/lib/hook-helpers.sh` - `lib/hook-helpers.sh` - `ao hooks` CLI command: `cli/cmd/ao/hooks.go`, `hooks_run.go` + 5 hook test files; `cli/internal/bridge/hooks.go`; `cli/internal/doctor/fix_hooks.go` + test - Codex hook manifest (`hooks/codex-hooks.json`) + handler/audit scripts (`scripts/audit-codex-hooks.sh`, `install-dev-hooks.sh`, `test-hooks-output.sh`, `test-codex-hookless-lifecycle.sh`, `test-hookless-rpi-phased.sh`) - Hook lease surface: `docs/contracts/hook-lease-*`, `schemas/hook-lease.v1.schema.json`, `scripts/check-hook-lease-inventory.sh`, `check-hook-port-replacements.sh`, `generate-hook-lease-inventory.py` - Hook docs: `docs/HOOKS.md`, `cli/docs/HOOKS.md`, `docs/architecture/hook-noise-audit.md`, `docs/contracts/hook-runtime-contract.md` - `tests/hooks/` (whole dir) + hook test scripts; 5 hook eval suites + fixtures ## CI gates removed `hook-preflight`, `validate-hooks-doc-parity`, `hook-output-schema-lint` (+ scripts/bats), the hook eval suites, the `test-runtime-codex-smoke` / `test-codex-native-install` / `test-codex-plugin-install` hook-handler assertions, the cli-integration hook-lifecycle steps, the bats `tests/hooks/*` glob + orphan-hooks audit, and the `--with-hooks` install path. `embedded-sync` now validates only lib/skills. Both summary `needs:` lists + the summary echo + `docs/contracts/ci-jobs.yaml` updated; `validate-ci-policy-parity` passes (66 rows). `.codex-plugin/plugin.json` drops the "Hooks" capability. ## Load-bearing PRESERVED (reported, not forced) - **`cli/cmd/ao/codex_runtime.go`** — the codex runtime *lifecycle profile* (`HookCapable`/`HookConfigured` detection) is a runtime-capability abstraction used by 6 `validate-codex-*` CI gates, distinct from the hook product. Deleting it is a separate refactor. - **`hooks-authoring` skill** + `schemas/hooks-manifest.v1.schema.json` — reframed as an opt-in "author your own hooks" guide. Deleting the skill cascades into catalog/domain-map/dispositions/context-map golden files (skill-count sync), out of scope for the hook-product removal. - **`scripts/pre-push-gate.sh`** — retired local gate (not in CI); self-skips deleted hook scripts via `[[ -x ]]` guards; its 55 bats tests still pass. - Domain-enforcement audit keeps the `enforced`-mode schema for backward-compatible JSON readers, but the hookless resolver only returns `audited`/`unavailable`. ## Verification `go build` / `go vet` clean; `go test ./...` = **11849 passed, 0 failed** (68 pkgs). gofmt clean on all touched files. Green: registry `--check` (0 hooks), `regen-codex-hashes --check`, `validate-ci-policy-parity`, `check-wiring-closure`, `validate-embedded-sync`, `validate-manifests`, `validate-agents-split`, `doc-release` (0 broken links), `generate-cli-reference --check`, `heal.sh --strict`, codex/claude/plugin smoke tests, baseline-audit (0 stale). Diff: 231 files, +354 / −39803. Closes-scenario: soc-57b7f#remove-all-hooks Bounded-context: BC5-Runtime Evidence: .github/workflows/validate.yml |
||
|
|
0759a740e6 |
feat(evolve): Phase 2 of /evolve --mode=loop — ladder + cron self-adjust + typed blocked events (soc-g2qd #phase-2) (#397)
## Why Phase 2 of soc-g2qd: ship the CLI enforcement primitives the skill's prompt-text alone can't guarantee. | Bead | What it gives the operator-loop | |---|---| | soc-mlbm | `ao evolve next-work` — 5-step programmatic ladder; agent stops guessing what to claim next | | soc-un0m | `ao cron self-adjust` — renders cron template + emits JSON spec; replaces manual CronList/Delete/Create per cycle | | soc-g34d | `ao evolve blocked` — typed blocked events at `.agents/evolve/blocked.jsonl`; agent logs rather than halts | ## What changed | Surface | Change | |---|---| | `cli/cmd/ao/evolve_next_work.go` + `_test.go` | New subcommand + L2 integration tests | | `cli/internal/evolve/ladder/` | 5-step ladder package (shape_filter, grep_siblings, primitive_test, cross_hop_pickup, bug_fallback) with table-driven unit tests | | `cli/cmd/ao/cron.go` | New top-level `ao cron` command | | `cli/cmd/ao/cron_self_adjust.go` + `_test.go` | New subcommand; calls `evolve.VerifyMarkers` + `evolve.Render` from #394; writes audit row to `.agents/evolve/cron-history.jsonl`; emits JSON spec to stdout (harness orchestrates CronCreate) | | `cli/cmd/ao/evolve_blocked.go` + `_test.go` | New subcommand: `--reason` (write), `--list [--tail N] [--json]` (read), `--clear <cycle>` (operator) | | Generated: `cli/docs/COMMANDS.md`, `registry.json`, `docs/cli-skills-map.md` | Regen for 3 new subcommands | | `evals/agentops-core/cli-command-surface-matrix.json` + smoke fixture | Counts bumped 73/199/272 → 74/202/276 | ## How tested - L2 integration: each new subcommand has L2 tests using fixture workspaces - L1 unit: 5-step ladder per-step table tests + JSONL schema validation on blocked records - Mechanical: `go test ./cli/...` 0 → 0 failures; cli-command-surface-smoke.sh `cli-help-matrix-ok`; check-no-tracked-agents.sh exits 0 ## Counts CLI heading counts: top 73 → 74, sub 199 → 202, all 272 → 276. Sibling pattern: `cron-history.jsonl` + `blocked.jsonl` follow the cycle-history.jsonl JSONL append-only shape from soc-5qit. Ladder structure mirrors the in-prompt cascade in `references/scout-mode.md` — making it programmatic per §A5. [no-sibling for cron-self-adjust] First-of-kind: no prior subcommand emits a cron-spec JSON for harness orchestration. The CLI does the safe work (template render + marker verify + audit row); the harness owns CronCreate. See: `docs/plans/2026-05-21-evolve-loop-epic-design.md` §A4, §A5, §A6 Closes-scenario: soc-mlbm#next-work-ladder Closes-scenario: soc-un0m#cron-self-adjust Closes-scenario: soc-g34d#typed-blocked-events Bounded-context: BC5-Runtime Evidence: cli/cmd/ao/evolve_next_work.go |
||
|
|
2ea3c12b7a |
feat(evolve): --mode=burst|loop flag + mechanical write-stop-marker refusal (soc-hwax #mode-loop-flag) (#395)
## Why
/evolve self-stops in operator-driven cron sessions because its defaults
assume agent-as-operator. `--mode=loop` flips the contract: operator
owns stop signals; CLI mechanically refuses self-written STOPs.
## What changed
| Surface | Change |
|---|---|
| `cli/cmd/ao/evolve.go` | New `--mode string` flag (burst\|loop,
default burst) + `validateEvolveMode` helper called from `runEvolve` |
| `cli/cmd/ao/evolve_write_stop_marker.go` | New subcommand; refuses
with exit 1 under `--mode=loop`, writes `.agents/evolve/<MARKER>` under
burst |
| `cli/cmd/ao/evolve_test.go` | L1: `--mode=invalid` rejected; mode flag
registered with burst default |
| `cli/cmd/ao/evolve_write_stop_marker_test.go` | L2 table tests: burst
writes (DORMANT body assertion), loop refuses {dormant,stop,kill}, no
file written under refusal |
| `skills/evolve/SKILL.md` | Mode-aware HTML comments in Steps 1/3/7 +
Flag table row (only edited Steps 1/3/7 + Flag table; verified via grep
`^### Step`) |
| `skills/evolve/references/loop-mode.md` | New reference doc with
invariants + CLI primitives |
| `docs/plans/2026-05-21-evolve-loop-epic-design.md` | Epic design memo
(consumed by all 6 sub-beads of soc-g2qd) |
| `cli/docs/COMMANDS.md` | Regenerated via
`scripts/generate-cli-reference.sh` |
|
`skills-codex/{.agentops-manifest.json,evolve/.agentops-generated.json}`
| Post-edit hook source-hash refresh; `check-codex-parity-drift.sh` PASS
|
## How tested
- `go test -count=1 ./cmd/ao/` — 10175 pass, 1 skip (full suite green
after CLI-docs regen; pre-regen `TestCobraConformance` correctly flagged
the doc drift)
- `go build ./... && go vet ./...` — green
- `grep '^### Step' skills/evolve/SKILL.md` confirms only Steps 1/3/7
edited (12 Step markers preserved at same positions)
- `bash scripts/check-codex-parity-drift.sh` — PASS
- Table tests assert exact marker filename (DORMANT/STOP/KILL) + body
content for burst; for loop they assert error substring AND that no
marker file was created.
## §A7 fallback decision
**Chose in-file HTML comments** (not two-file split). Each Step comment
is one line; no conditional sections needed. Two-file split would have
ballooned the surface for a single-line contract reminder. CLI
mechanical enforcement (`write-stop-marker` refusal) is the real
invariant; SKILL.md comments only document intent for human readers.
See: docs/plans/2026-05-21-evolve-loop-epic-design.md §A1 + §A7
## TODOs the worker leaves for the epic
- Wire `cli/internal/evolve.preferences.Load()` into
`detectEvolveWriteStopMarkerMode` once soc-6svt lands (currently
flag-only).
- `ao evolve operator-stop` (Wave 2) — separate code path explicit
operator override.
- `ao evolve blocked` (Wave 2) — typed blocked event instead of STOP.
Closes-scenario: soc-hwax#mode-loop-flag
Bounded-context: BC5-Runtime
Evidence: cli/cmd/ao/evolve_write_stop_marker.go
|
||
|
|
2d2b806ab8 |
feat(evolve): per-repo preferences.yaml schema + loader + ao evolve config --show (soc-6svt #preferences-yaml) (#396)
## Why Different repos have different /evolve physics. Hardcoded defaults force ADRs per-repo to override. Per-repo YAML separates skill-doctrine from repo-policy. ## What changed | Surface | Change | |---|---| | `schemas/evolve-preferences.v1.schema.json` | New JSON Schema draft-07 for the v1 preferences shape | | `cli/internal/evolve/preferences.go` | New loader: `Load(ctx) (*Prefs, error)` with file:line error context | | `cli/cmd/ao/evolve_config.go` | New `ao evolve config --show [--json]` subcommand | | `.agents/evolve/preferences.yaml.template` | New starter template | | `.gitignore` | Negation rules for the template path | ## Resolution order defaults < preferences.yaml < CLI flag (caller-applied) Invalid keys/types -> exit 1 with `preferences.yaml:line:col` context. Never silent fallback. ## How tested - L2: malformed YAML -> `ao evolve config --show` exits 1, stderr has file:line - L1: `preferences.Load()` table tests cover defaults, valid, invalid types, out-of-range, unknown keys - `go test ./cli/internal/evolve/ ./cli/cmd/ao/` green (299+ tests across both) See: docs/plans/2026-05-21-evolve-loop-epic-design.md §A2 (created by parallel worker W1a in soc-hwax PR) Closes-scenario: soc-6svt#preferences-yaml Bounded-context: BC5-Runtime Evidence: cli/internal/evolve/preferences.go |
||
|
|
1a7e2cb748 |
feat(ao session bootstrap): universal init prompt (soc-vuu6.25 #ao-session-bootstrap) (#390)
## Summary
`ao session bootstrap` — every agent spawned into an AgentOps repo runs
this first. Output shape is identical regardless of model (the
fungibility contract: swap Claude for Codex on any bead without
re-orienting).
## What
Four fail-open substeps emit fields in
`schemas/session-bootstrap.v1.schema.json`:
| Field | Source | Fallback |
|---|---|---|
| `agents_md_read` + `agents_siblings_read` | `AGENTS.md` +
post-soc-vuu6.3 siblings | `false` / empty array |
| `onboard_phase` | `onboard --auto` (soc-vuu6.9 future) |
`skipped:not-implemented` |
| `ready_beads_count` | `bd ready --json` | `null` |
| `mail_unread_count` | mcp-agent-mail | `null` (wiring is follow-up
bead) |
## Why
The fungibility philosophy mandates one init prompt for every agent
regardless of type. Today every operator hand-rolls orientation; two
agents spawned by two different operators don't share a starting frame.
`ao session bootstrap` is the operational primitive that closes the gap.
Tiny (~270 LOC including helpers), fail-open, deterministic.
## Files
- New: `cli/cmd/ao/session_bootstrap.go` + `_test.go` (8 cases)
- New: `schemas/session-bootstrap.v1.schema.json` (draft-07)
- New: `skills/session-bootstrap/SKILL.md` +
`skills-codex/session-bootstrap/SKILL.md` (mirrored)
- Catalog: `skills/SKILL-TIERS.md`, `skills/using-agentops/SKILL.md`,
`skills-codex/using-agentops/SKILL.md`
- Regenerated: `cli/docs/COMMANDS.md` (sub 196→197, all 269→270),
`registry.json` (cli_commands 173→174),
`PRODUCT.md`/`docs/ARCHITECTURE.md`/`docs/SKILLS.md` (count sync 79→80),
`evals/agentops-core/cli-command-surface-{matrix.json,fixtures/cli-command-surface-smoke.sh}`
(fixture bump)
## Verification
```
cd cli && go build ./... && go test ./cmd/ao/ -run TestSessionBootstrap -count=1
# 8 passed
bash evals/agentops-core/fixtures/cli-command-surface-smoke.sh
# cli-command-headings: top=73 sub=197 all=270 / cli-help-matrix-ok
bash tests/docs/validate-doc-release.sh
# PASS: doc-release gate succeeded
```
Closes-scenario: soc-vuu6.25#ao-session-bootstrap
Bounded-context: BC5-Runtime
Evidence: cli/cmd/ao/session_bootstrap.go
Evidence: cli/cmd/ao/session_bootstrap_test.go
Evidence: schemas/session-bootstrap.v1.schema.json
Evidence: skills/session-bootstrap/SKILL.md
|
||
|
|
f7cc505a7a |
fix(agentopsd): harden AI smell surfaces (soc-0l5z #ai-smell-hardening) (#389)
## Summary - Replace the plans manifest shape-only stub with projection-backed daemon state. - Gate llmwiki placeholder outputs behind explicit opt-in and make fake daemon execution test/demo-only. - Refresh stale Olympus-ported docs and tune README/PRODUCT claims to default-safe runtime behavior. - Repair strict docs-site and hook-lease inventory drift surfaced by the merge gate. ## Validation - `scripts/pre-push-gate.sh --fast` - `go test ./internal/daemon ./internal/llmwiki ./cmd/ao` - `bash tests/docs/validate-doc-release.sh` - `scripts/docs-build.sh --check` - `bash scripts/validate-sovereignty-proof-citations.sh` - `bash scripts/check-hook-lease-inventory.sh` Closes-scenario: soc-0l5z#ai-smell-hardening Bounded-context: BC5-Runtime Evidence: validate-sovereignty-proof-citations: scanned 3 pages, 16 citations |
||
|
|
3655c55356 |
feat(scripts): auto-resume-stale-claims driver (soc-vuu6.27 slice 4a #auto-resume-driver) (#385)
## Why Slice 4a of soc-vuu6.27 (fungible-swarm death recovery). The bead originally specified an "agentopsd job spec" but the operational essence is a periodic driver that calls slice 2 + slice 3 — that intent is met by a shell wrapper today, faster and with smaller surface than touching agentopsd internals. Slice 4b (`` filed) tracks the agentopsd-native variant for later. **Stacked on slice 3's branch** (which is stacked on slice 2). When the chain merges, this rebases onto main. ## What `scripts/auto-resume-stale-claims.sh` — one-shot driver suitable for cron, systemd timers, or future agentopsd job wrapping: 1. Calls `ao beads stale-claims --threshold=<N>h --json` (slice 2). 2. For each stale bead, calls `ao beads resume <id> --agent <recovery-agent>` (slice 3). 3. Per-bead OK/FAIL output + summary line. Exit code summarizes the run. Flags: `--threshold` `--agent` `--dry-run` `--max` (cap per-run transfers; default 25) `--quiet`. Exit 0 = success or no candidates; exit 1 = at least one failure; exit 2 = usage/env error. ## Test 9 bats tests, all passing. Stubs `ao` via PATH so the harness is deterministic. Covers: zero candidates, multi-candidate happy path, --dry-run, partial failure, --max cap, --threshold passthrough, --quiet suppression, unknown-flag error, missing-ao error. Self-dogfood: With slices 2 and 3 landed plus a stale-claim simulator, running this driver against the real bd backend transfers stale claims and emits one claim_transferred event per transfer (slice 3 contract). ## Follow-up - Slice 4b (``) — agentopsd-native job spec wrapping this driver. Closes-scenario: soc-vuu6.27#auto-resume-driver Bounded-context: BC2-Loop Evidence: scripts/auto-resume-stale-claims.sh Evidence: tests/scripts/auto-resume-stale-claims.bats --------- Co-authored-by: Codex <codex@example.invalid> |
||
|
|
57b2eabd7e |
feat(ao beads): stale-claims list command (soc-vuu6.27 slice 2 #stale-claims-list) (#383)
## Why
Slice 2 of soc-vuu6.27 (fungible-swarm death recovery). The fungibility
doctrine ("Dead agent? Start another.") needs an operational primitive.
This is the read-only listing half — surfacing stale claims so an
operator (or future slice-4 daemon job) can decide what to do. Slice 1
(PR #382) shipped the contract; this slice consumes it.
## What
`ao beads stale-claims [--threshold=4h] [--json]` — walks `bd list
--status in_progress --json`, applies a staleness heuristic (last
activity > threshold), emits a sorted listing (oldest first) or a JSON
array of records conforming to
`schemas/stale-claim-event.v1.schema.json` (event_type
`stale_detected`).
Files:
- `cli/cmd/ao/beads_stale.go` — cobra subcommand + pure
`computeStaleEvents` helper + exec seam for tests
- `cli/cmd/ao/beads_stale_test.go` — 5 test functions, 7 table sub-cases
+ L2 integration via the seam
- `cli/cmd/ao/beads.go` — one-line registration
(`beadsCmd.AddCommand(beadsStaleCmd)`)
Read-only: this command DOES NOT transfer claims. Slice 3 handles that.
Slice scope honors complexity budget — the orchestration function is two
short helpers (RunE wrapper + pure `computeStaleEvents`), each well
under the warn-at-15 threshold.
## Test
`cd cli && go test ./cmd/ao -run
'TestComputeStaleEvents|TestRunBeadsStale'`:
- TestComputeStaleEvents_TableDriven (7 sub-cases)
- TestComputeStaleEvents_AssigneeDefaultUnknown
- TestRunBeadsStale_JSON_OutputShape (L2 integration via seam)
- TestRunBeadsStale_HumanOutput_HasZeroMessage
- TestRunBeadsStale_BdMalformed
- TestComputeStaleEvents_ClaimAgeRounding
All passing. `gofmt -l` clean, `go vet ./...` clean, `go build ./...`
clean.
Self-dogfood (in this worktree, smoke):
```
$ ao beads stale-claims --threshold=4
ao beads stale-claims: 47 in_progress bead(s) stale (threshold 4.0h)
soc-t3z1 claim_age=21.5h last_touch=2026-05-19T22:30:00Z ...
```
## Follow-ups already filed
- Slice 3 — `ao beads resume <id>` atomic transfer (blocked on this PR)
- Slice 4 — agentopsd auto-resume daemon job (blocked on slice 3)
Closes-scenario: soc-vuu6.27#stale-claims-list
Bounded-context: BC5-Runtime
Evidence: cli/cmd/ao/beads_stale.go
Evidence: cli/cmd/ao/beads_stale_test.go
---------
Co-authored-by: Codex <codex@example.invalid>
|
||
|
|
c8edc80143 |
feat(wiki): wiki bounded context waves 1-4 (epic soc-behj) (#291)
## Summary Phased strangler consolidating `ao`'s `.agents/`-touching logic into one `cli/internal/wiki` bounded context. Waves 1-4 of epic **soc-behj** (8 beads, 5 waves). Strictly accretive — no `ao` command removed, legacy command surface untouched. Each wave boundary was gated on the 102 `cmd/ao` integration tests staying green. | Wave | Bead | Deliverable | |------|------|-------------| | W1 | soc-1lju | `FrontmatterCodec` — all 5 frontmatter parsers delegate to one codec | | W2 | soc-36lw | `CorpusLocator` — `agentsDirIn` moved, 17 call sites migrated | | W2 | soc-f4tr | `Artifact` + `Claim` domain types with subtype invariants | | W3 | soc-vot0 | persistent `WikiIndex` — JSONL, incremental by content-hash | | W3 | soc-r08p | `FreshnessPolicy` — claim-level, evidence-driven | | W4 | soc-ijp8 | `WikiPipeline` — subsumes the llmwiki loop, 3 stages wired | | W4 | soc-q50a | port conformance suite | Also anchors `.gitignore`'s bare `wiki/` pattern with a `!cli/internal/wiki/` negation — the new package was being silently ignored. Wave 5 (`ao wiki` command group) is **not** in this PR. ## Test plan - [x] `go build ./...` clean - [x] `go vet ./internal/wiki/` clean - [x] `go test ./internal/wiki/` — 96 pass - [x] `go test ./cmd/ao/ -run Integration` — 102 pass (regression net green) - [ ] CI `validate.yml` --------- Co-authored-by: Codex <codex@example.invalid> |
||
|
|
1f0e545a51 |
Executable spec layer (epic soc-58nt, F2–F5): GOALS as BDD acceptance criteria (#292)
* feat(goals): F2.0 scenario-result artifact contract + producer/writer
bead: soc-58nt.2.6
* docs(goals): F4.0 trace link convention ADR-0005
bead: soc-58nt.4.8
* docs(goals): F3.0 domain-slice manifest contract + ADR-0004
bead: soc-58nt.3.8
- schemas/domain-slice-manifest.v1.schema.json: JSON Schema (draft/2020-12,
additionalProperties:false) for domain-slice manifests. All required fields:
domain, version, bounded_context, directive_ids (d-<slug> pattern), scenario_ids,
context_roots, allowed_read_globs, denied_read_globs, validation_commands, owner.
- docs/adr/ADR-0004-domain-slice-manifest-contract.md: records four decisions:
(A) command shape is ao rpi phased --domain <name>; (B) manifest is durable
tracked artifact at docs/domains/<name>/manifest.yaml; (C) reconciles with the
domain skill (vocabulary), context-map.md (architecture view), and skill
frontmatter — no overlap; (D) Go model named domainSliceManifest, explicitly
distinct from rpi_phased_manifest.go's phaseManifest. Cross-references ADR-0003.
- docs/domains/README.md: explains the directory, field table, relationship to
the three pre-existing domain surfaces, and how to add a new slice.
- docs/domains/example/manifest.yaml: fully populated example; validated against
the schema via jsonschema (PASSED).
* feat(goals): F2.1 scenario-result aggregation reader
bead: soc-58nt.2.1
* feat(rpi): F3.1 domainSliceManifest model + loader
Implements the domainSliceManifest Go model and loader in
cli/internal/domainslice/ per the F3.0 contract (ADR-0004, Decision D).
Uses gopkg.in/yaml.v3 with KnownFields(true) to reject unknown fields,
mirrors the schema's additionalProperties:false. Validates all required
fields, directive_id pattern (^d-[a-z0-9][a-z0-9-]*$), context_roots
minItems:1, and validation_commands sub-fields with field-named errors.
Explicitly distinct from phaseManifest (rpi_phased_manifest.go).
28 tests pass (L1 unit + L2 fixture round-trip via docs/domains/example/manifest.yaml).
bead: soc-58nt.3.1
* feat(goals): F4.1 read-only executable-spec trace graph walker
bead: soc-58nt.4.1
* feat(goals): F2.2 per-directive scenario_satisfaction + threshold verdict
bead: soc-58nt.2.2
* feat(rpi): F3.2 ao rpi phased --domain scoping
bead: soc-58nt.3.2
* feat(goals): F4.2/F4.3 ao goals trace --from / --orphans
beads: soc-58nt.4.2 soc-58nt.4.3
* feat(goals): F4.4 ao goals render — GOALS.md to Gherkin
bead: soc-58nt.4.4
* feat(rpi): F3.3a domain-scope audit evidence
bead: soc-58nt.3.3
* feat(goals): F2.3 scenario_satisfaction JSON field + --scenarios-only
Per-directive scenario satisfaction added to ao goals measure: 0 -> 8
new JSON fields and a --scenarios-only mode that skips gate execution.
bead: soc-58nt.2.3
* feat(rpi): F3.4 ao rpi phased --scaffold-domain
bead: soc-58nt.3.4
* test(goals): commit missing goals-trace scenario-results fixture
The F4.1/F4.2 walker tests reference a scenario-results.json fixture under
a gitignored .agents/ subpath; it was never force-added and a clean
checkout (and CI) lacks it, failing 5 scenario_result tests. Force-add it.
bead: soc-58nt.4.1
* fix(goals): F4.1 tighten goalstrace scenario-claim heuristic
bead: soc-58nt.4.9
- Tighten scenarioTokenRe: auto- tokens now require at least two
hyphen-separated slug segments (auto-X-Y…), so single-word English
compounds like auto-merge and auto-update are no longer matched.
- Downgrade broken_bead_scenario_claim from error to warning when the
claim comes from a heuristic (ConfidenceLow) free-text match; per
ADR-0005 §4.1 only an explicit Scenarios: line constitutes a broken
explicit link and may produce an error.
- Add beads_test.go with table-driven tests covering: English auto-*
false-positive rejection, real multi-segment auto-* ID detection,
explicit missing scenario → error, heuristic missing → warning only,
resolvable scenario → no defect, end-to-end Walk with auto-merge bead
produces no error-severity finding.
* test(goals): F2.T1 regression-coverage audit + gap fill
bead: soc-58nt.2.4
* ci(goals): F1.6 wire executable-spec link lint + trace-orphans (warn-first)
bead: soc-58nt.1.9
* feat(rpi): F3.3b runtime hook enforcement of domain scope
bead: soc-58nt.3.9
* test(goals): F2.T2 e2e script for scenario-satisfaction gate
bead: soc-58nt.2.5
* docs(goals): F5.0 re-steer policy + mutation-safety contract (ADR-0006)
bead: soc-58nt.5.9
* docs(goals): fix streak-reset prose in ADR-0006 (cleanup)
bead: soc-58nt.5.9
[no-sibling] prose fixup only, no structural change
0 → 0 schema fields changed
* test(goals): F4.T1 regression-coverage audit + gap fill
bead: soc-58nt.4.6
* feat(wiki): land wiki bounded context waves 1-4 (epic soc-behj)
Phased strangler consolidating ao's .agents/-touching logic into one
cli/internal/wiki bounded context. Each wave gated by the 102 cmd/ao
integration tests staying green; legacy command surface untouched.
- W1 soc-1lju FrontmatterCodec — all 5 frontmatter parsers delegate
- W2 soc-36lw CorpusLocator — agentsDirIn moved, 17 call sites migrated
- W2 soc-f4tr Artifact + Claim domain types with subtype invariants
- W3 soc-vot0 persistent WikiIndex — JSONL, incremental by content-hash
- W3 soc-r08p FreshnessPolicy — claim-level evidence-driven freshness
- W4 soc-ijp8 WikiPipeline — subsumes llmwiki loop, 3 stages wired
- W4 soc-q50a port conformance suite
Also anchors .gitignore's bare wiki/ pattern with a !cli/internal/wiki/
negation — the new package was being silently ignored.
Wave 5 (ao wiki command group) is not included in this commit.
* test(goals): F4.T2 e2e script for trace chain
bead: soc-58nt.4.7
* test(rpi): F3.T1 regression-coverage audit + gap fill
bead: soc-58nt.3.6
* test(rpi): F3.T2 e2e script for domain-scoped RPI
bead: soc-58nt.3.7
* feat(goals): F5.1 verdict ledger schema + writer
bead: soc-58nt.5.1
* feat(goals): F5.2 re-steer policy engine + verdict-ledger producer hookup
bead: soc-58nt.5.2
* feat(goals): F5.4 feedback-to-learning compiler
Adds cli/internal/feedbackcompiler — scans the verdict ledger for
fail->pass directive transitions and drafts a learning entry in
docs/learnings/ for each transition found. Drafts carry status: draft
and directive_id frontmatter (ADR-0005 §2.6). Never auto-promotes.
Idempotent: skips existing drafts on re-run.
Also documents the auto-draft workflow in
skills/forge/references/feedback-compiler-drafts.md with a compact
reference-link in skills/forge/SKILL.md (under 248-line limit).
Synced to skills-codex/forge/ and regenerated codex hashes.
bead: soc-58nt.5.4
* docs(goals): F5.5 compound-engineering retro in /post-mortem
Extend the /post-mortem skill with a Compound-Engineering Retro section
that compares iteration N vs N-1 for a domain slice using the F5.1 verdict
ledger (.agents/goals/verdict-ledger.json). The mode emits a comparative
delta — directives that improved (fail→pass, satisfaction up), regressed
(pass→fail, satisfaction down), or held stable — plus learning yield since
N-1, written as a status:draft learning to .agents/learnings/.
Detailed step-by-step procedure (CE.0–CE.5) lives in
references/compound-engineering-retro.md; SKILL.md carries a compact
trigger/commands summary and links to it. Both files synced to
skills-codex/post-mortem/ with updated codex hashes.
bead: soc-58nt.5.5
* feat(goals): F5.3 ao goals steer --auto with human-gated confirmation
bead: soc-58nt.5.3
* test(goals): F5.T1 regression-coverage audit + gap fill
bead: soc-58nt.5.7
* test(goals): F5.T2 e2e script for auto re-steer
bead: soc-58nt.5.8
* docs(goals): F2.4 docs regen for scenario-satisfaction gate + epic CLI artifacts
Regenerate cli/docs/COMMANDS.md and registry.json from a clean worktree at
HEAD so the soc-58nt command surface is documented without leaking unrelated
peer WIP into the generated docs.
F2 (soc-58nt.2.7): document scenario_satisfaction JSON shape, --scenarios-only,
result-artifact resolution, and exit codes in skills/goals/SKILL.md +
references/executable-spec-chain.md; cross-ref ao goals measure/trace from
skills/scenario/SKILL.md.
Epic-wide artifacts also landed here because they regenerate atomically across
F2-F5: COMMANDS.md/registry.json (all new ao goals/rpi surface), cli-skills-map
heading count, skills-codex hashes, ADR-0004/0005/0006 documentation-index
links, and the F2-F5 e2e CI lanes in validate.yml.
ao capabilities and ao robot-docs need no manual edits — both build their
command/flag surface from the live cobra tree, so new commands register
automatically (Global Rule G5 satisfied by construction).
bead: soc-58nt.2.7
* docs(domain): F3.5 domain-as-loop docs for domain-scoped RPI
Document the domain-slice runtime in skills/domain/SKILL.md (a "Domain as a
scoped RPI loop" section connecting the Slice primitive to ao rpi phased
--domain / --scaffold-domain / --force) and add the Domain-Slice row to the
modes table in skills/scaffold/SKILL.md, mirroring the existing Project/
Component/CI mode-row shape. The scaffold skill's Domain-Slice Mode section
already covered the workflow; this lands the missing modes-table entry so the
mode count is 3 -> 4.
The COMMANDS.md/registry/CI-lane regen for F3 landed in soc-58nt.2.7.
skills-codex hashes for the two changed skills refreshed via
scripts/regen-codex-hashes.sh; codex-parity audit clean.
bead: soc-58nt.3.5
* docs(goals): F5.6 re-steer loop docs in /post-mortem
Cross-reference the auto re-steer loop from the Compound-Engineering Retro
section of skills/post-mortem/SKILL.md: when the compound retro names a
chronically regressing directive, ao goals steer recommend prints
policy-driven directive mutations from the same verdict ledger and ao goals
steer apply writes the mutation to GOALS.md, human-gated via the non-lossy
patcher (ADR-0006). Mirrors the existing "closing the loop" cross-ref shape
used elsewhere in the skill's See Also prose.
The ao goals steer recommend/apply COMMANDS.md surface, the F5 e2e CI lane,
and the ADR-0006 documentation-index link landed atomically in soc-58nt.2.7's
epic-wide regen; the re-steer contract detail lives in
skills/goals/references/executable-spec-chain.md (also in 2.7).
skills-codex/post-mortem hash refreshed; codex-parity audit clean.
bead: soc-58nt.5.6
* docs(goals): F4.5 docs regen for goals trace + render (epic-subsumed)
F4's docs deliverables — the `ao goals trace` and `ao goals render` entries in
cli/docs/COMMANDS.md, the F4 trace-chain e2e CI lane in validate.yml, the
ADR-0005 documentation-index link, and the Trace/Render mode sections plus the
trace contract in skills/goals/SKILL.md + references/executable-spec-chain.md —
all co-landed atomically in soc-58nt.2.7's epic-wide CLI-reference regen
(commit
|
||
|
|
a0b9b21145 |
docs(goals): document ao goals scenarios; regenerate CLI reference
F1.5 of epic soc-58nt (terminal docs bead for F1). - Regenerate cli/docs/COMMANDS.md and registry.json for the new 'ao goals scenarios' command surface (list / --create / --lint). - Document the directive↔scenario executable-spec link in skills/goals/ SKILL.md and cross-reference it from skills/scenario/SKILL.md. - 'ao goals scenarios' auto-registers in 'ao capabilities' and 'ao robot-docs' (both walk the cobra command tree). Codex parity audit passes for goals and scenario. Closes soc-58nt.1.5. |
||
|
|
dc14aeb439 |
feat(cli): add top-level capabilities and robot-docs agent surfaces
`ao doctor` already exposes `capabilities` and `robot-docs`, but an agent's first introspection guess is the top-level command. Elevate that pattern: `ao capabilities` emits the machine-readable CLI contract (command tree, global flags, exit codes, env vars, robot-surface pointers) as JSON, and `ao robot-docs` prints a paste-ready agent handbook. Both mirror the shape of the doctor surface in cmd/ao/doctor_surface.go. Top-level robot surfaces: 0 → 2. The command list and flags are walked from the live cobra tree so the contract never drifts from registration. |
||
|
|
54f1ba4568 |
feat(doctor): wire diagnose-and-repair subcommands into the ao CLI
Adds the doctor engine surface to the existing doctorCmd: subcommands fix, undo, explain, capabilities, health, robot-docs, gc, ls, diff, plus the additive flags --fix/--dry-run/--only/--skip/--since/--online/ --quick/--severity/--robot/--robot-triage/--explain. Exit codes route through a typed doctorExitError that Execute() maps to os.Exit via errors.As — mirrors the AgentsLintError pattern already in root.go, no parallel exit mechanism. Backward compatible: bare `ao doctor` and `ao doctor --json` keep the legacy 17-line check table and checks JSON array unchanged. With the empty registry the engine adds 0 findings, so the bare command's exit semantics (0 → 1 on required failure) are untouched. CLI reference docs regenerated for the 9 new subcommands. |
||
|
|
a4108a5503 |
fix: critical audit findings remediation (epic soc-ab5g) (#279)
* fix(session): sanitize init-step exec and correct BEADS_ACTOR
Two defects in `ao session spawn` runInitSteps, from the 2026-05-16
codebase audit (epic soc-ab5g):
- BEADS_ACTOR was exported as the expanded command string of the first
init step instead of the session actor identity, so beads attribution
for every init step was garbage. Thread tmpl.Identity.BeadsActorTemplate
through runInitSteps and export the var only when non-empty.
- Init steps ran via raw exec.Command("bash","-c",...) (SEC-C1). Route
init-step exec through shellutil.SanitizedBashCommand and add
sanitizeHostname() to strip shell metacharacters from {{hostname}}-class
template vars before substitution.
New regression tests: TestRunInitStepsSetsBeadsActor, TestSanitizeHostname.
Refs: soc-jhxr
* fix(autodev): replace vague 'validation failed' with a concrete summary
outputAutodevValidateResult returned fmt.Errorf("validation failed")
after already printing the detailed INVALID/ERROR lines -- a redundant,
content-free wrapper. Return a summary naming the file and the
validation-error count instead (COPY-C1, epic soc-ab5g).
Refs: soc-mpzu
* docs(eval): strip internal Day-N cadence jargon from user-facing text
eval_task.go exposed internal sprint labels ("Day-2 placeholder",
"Day-3 wires real launch", "Day-4 gate #4") in command Long
descriptions and flag help. Reword to describe current behavior
without the internal cadence (COPY-C2, epic soc-ab5g).
Refs: soc-iy7p
* fix(cli): reject unknown subcommands on group commands
Group-parent commands (daemon, beads, codex, constraint, factory,
goals, hooks, ratchet, rpi, session) had no Args validator, so an
unknown subcommand printed help to stdout and exited 0 -- breaking
`if ao rpi <bad>; then ...` scripting. Add Args: cobra.NoArgs to all
ten; unknown subcommands now exit 1 with the error on stderr
(CLI-C1, epic soc-ab5g).
Refs: soc-mlqe
* docs(cli): regenerate COMMANDS.md after eval-task help copy edit
* fix(daemon): contain dream output_dir against path traversal
DreamRunJobSpec/DreamStageJobSpec/DreamStageManifest Validate() only
TrimSpace-checked output_dir, leaving the operator-supplied job payload
free to redirect summary/log writes outside the intended tree.
validateOutputDir now rejects ".." traversal in all three Validate()
paths; outputDirContained rejects an absolute output_dir resolving
outside the daemon working tree, checked in DreamExecutor.RunJob before
MkdirAll. Containment checks: 1 (symlink only) → 3 (symlink + .. + abs).
Closes soc-ly33 (SEC-C2, epic soc-ab5g).
* fix(cli): wire ao --version flag and unify goals --json with -o
rootCmd had no Version field, so `ao --version` was unsupported even
though an `ao version` subcommand existed. Set rootCmd.Version = version
(the ldflags-injected build var) so the standard --version flag works.
goals registered its own local --json bool, disconnected from the
global -o/--output flag — `ao goals measure -o json` was ignored. Drop
goalsJSON; goalsJSONOutput() now reads GetOutput(), the sibling pattern
used by agentopsd.go, autodev.go, codex.go and ~40 other callsites. The
global --json persistent flag is inherited, so `ao goals --json` still
works; output paths honored by goals: 1 (local bool) → 2 (--json + -o).
Closes soc-nx1o (CLI-C2, epic soc-ab5g).
* perf(cli): collapse tmux probe storm in ao rpi status
checkTmuxSessionAlive forked `tmux has-session` up to 3 times per
non-terminal run, each with a 2s timeout — a status scan over N runs
issued 3N subprocesses and could stall ~6N seconds when tmux was slow
or absent.
probeTmuxSessions now runs one `tmux ls -F #{session_name}`, memoized
per process behind a mutex-guarded cache; tmuxSessionAlive filters the
snapshot in Go. resolveRPIToolchainDefaults collapses from per-run to
once. Subprocesses per status scan: 3N → 1.
Closes soc-d7v5 (PERF-C1, epic soc-ab5g). Mirrors the snapshot-then-
filter shape used elsewhere for batch probes.
* perf(cli): one-pass git capture + walk-once index in ao beads audit
ao beads audit re-shelled git per bead (one `git log --grep` per bead,
one `git log --since` per bead-path pair) and re-walked the worktree
per pattern (recordAuditStaleFinding probes up to 10 patterns/bead, so
up to 10N full-repo walks for N beads).
captureAuditCommits now runs a single `git log --all --name-only`,
parsed into auditCommit records; grepCommitsForID and
fileChangesSinceCommits filter that slice in Go. repoContentCache walks
the scoped roots once (lazily) and memoizes a path->content map shared
across every pattern probe. git subprocesses per audit: O(beads) → 1;
repo walks: O(10*beads) → 1. Mirrors the snapshot-then-filter shape
just applied to ao rpi status.
Closes soc-2grz (PERF-C2, epic soc-ab5g).
* fix(schemas): declare schema_version const in 15 unversioned schemas
15 of 34 schemas under schemas/ carried versioned filenames (or implied
a stable contract) without a machine-readable schema_version, so a
consumer could not detect the version from the payload alone.
Each now declares an optional schema_version integer const, mirroring
the shape in schemas/bead.v1.schema.json: const 1 for every schema
except skill-frontmatter.v2 (const 2). The field is intentionally left
out of "required" so existing documents without it still validate —
non-breaking. scenario.v1 keeps its legacy "version" field alongside.
Schemas declaring schema_version: 19/34 → 34/34.
Closes soc-wzgo (API-C2, epic soc-ab5g).
* docs(contracts): regenerate context-map after merging main
The merge of origin/main pulled a discovery SKILL.md description edit
without its companion context-map regeneration, so
validate-context-map-drift flagged 1 stale line. Regenerated via
scripts/generate-context-map.sh. Drifted lines: 1 → 0.
|
||
|
|
c85b27f439 |
feat(loop): expose HypothesisLedgerPort + ConvergenceCheckPort via ao loop
Follows the ao loop append/history wiring shape (loop_append.go): each
command pairs an options struct with an injectable *Fn seam and a
*ViaPort production path.
- ao loop hypothesis {list,append} — typed BC3 HypothesisLedgerPort
surface over .agents/evolve/hypotheses.jsonl (productionHypothesisLedger,
soc-y5vh.6). append rejects empty/duplicate IDs; list emits one JSON
HypothesisRecord per line.
- ao loop converged — pure BC3 ConvergenceCheckPort STOP predicate
(productionConvergenceCheck, soc-y5vh.7). Takes caller-supplied
evidence (green streak, unconsumed HIGH+MEDIUM, fitness-baseline),
emits {converged, ci_green_streak, ..., reasons}.
- evolve docs (SKILL.md + convergence-mechanics.md) reference the new
typed path instead of direct hypotheses/session-convergence reads.
- Cross-harness parity: ported convergence-mechanics.md into the codex
evolve skill (was 9/19 reference files, now 10/19), harness-adapted
(Step 7 while-loop STOP vs ScheduleWakeup). Broader evolve drift
tracked in soc-an3v.
- CLI docs regenerated; cd cli go build/vet/test ./... green
(11921 tests, 53 packages).
Tests: LoopConverged 5 cases (converged + each unmet reason + observed
streak), LoopHypothesis 4 cases (empty-id reject, stub mapping, JSONL
render, append->list round-trip).
Closes soc-y5vh.8
|
||
|
|
fefd1dd65e |
feat(loop): record XP/BDD/TDD trace in evolve cycles
Evolve cycle history/report now carries the Olympus continuous-evolution kernel as a structured `trace` object so a reviewer can reconstruct a cycle without the transcript: goal hypothesis -> selected gap -> Gherkin scenario (or explicit exemption) -> first failing proof -> red/green evidence -> refactor note -> validation evidence -> ratchet action -> goal reshape decision. - ports: CycleTrace struct + CycleEntry.Trace (json:"trace,omitempty"); TraceCompleteness pure helper reports exemption / missing fields. - adapters: rawCycleRecord + loopWriterRecord round-trip the trace; trace-less entries stay byte-identical. - ao loop append --trace-json <path|inline>; ao loop history emits it. - evolve-log-cycle.sh --trace-json <path|json|-> validates the object and records it; malformed/non-object payloads rejected. - Trivial one-shot cycles record trace.exemption_reason instead of false BDD/TDD ceremony. Completeness is advisory, never a gate. - docs: skills/evolve + skills-codex/evolve cycle-history.md + Step 6. Tests: TraceCompleteness table tests, adapter round-trip, loadCycleTrace, bats trace + exemption + malformed. go test ./... green; bats 10/10. Closes soc-y5vh.9 |
||
|
|
d17a5eec87 |
docs(cli): regenerate COMMANDS.md after --oscillation-sweep removal
Pure regen output. The cycle-181 dead-code sweep removed the --oscillation-sweep flag from `ao defrag` but did not regenerate the CLI reference, leaving cli/docs/COMMANDS.md listing a flag that no longer exists. This commit removes that single line. Caught by the new STEP 1.7.5 "Release-Readiness Gates" check added to the validation skill (this same session) — first validation that the new mechanical gate works on real drift. |
||
|
|
78ac885def |
feat(cli): ao loop verify — audit cycle-history integrity (uses cycle-161 widening)
Cycle 163. First NEW consumer of the cycle-161 CycleEntry widening
(soc-ckc4). NOT a template adapter wrap — adds new audit behavior
on top of the typed LoopReaderPort.
ao loop verify audits .agents/evolve/cycle-history.jsonl integrity:
- monotonic Number ordering
- no duplicate Number values
- non-empty StartedAt on every entry (uses the cycle-161 field)
- trailing IdleStreak < threshold (--max-idle, default 5)
Exit code 0 on clean ledger, non-zero with FAIL summary on any issue.
Useful as pre-commit gate or CI assertion against hand-edited ledgers.
Live smoke surfaced a REAL drift on first run: cycle 74 is duplicated
in the current ledger (lines 73-74, identical except unicode → vs
ASCII 'to'). Filed soc-(new) for operator-data cleanup; not fixed
in this cycle.
Implementation:
- cli/cmd/ao/loop.go: loopVerifyCmd + loopVerifyRun + checkLoopIntegrity
pure-Go audit fn + loopVerifyViaPort wiring. Injectable verifyFn
follows the cycle-147 CLI-wiring template testability pattern.
- cli/cmd/ao/loop_test.go: 7 new tests:
TestCheckLoopIntegrity_{CleanLedger, NonMonotonicNumber,
DuplicateNumber, MissingStartedAt, IdleStreakExceedsThreshold}
+ TestLoopVerifyRun_{StubPASS, StubFAIL}.
Distinguishing this from the cycle-155 banned pattern: the previous
adapter cycles wrapped a port method 1:1 in a CLI command. This
cycle composes Range + IdleStreak with NEW audit logic
(non-monotonicity check, duplicate detection, StartedAt presence)
that didn't exist anywhere before. It's a real consumer of the port,
not a trivial passthrough.
cli/docs/COMMANDS.md regenerated.
gofmt clean, go vet clean, full ./... PASS.
+143 LOC, 7 new tests, 1 real audit finding surfaced.
|
||
|
|
d5772d97f8 |
feat(cli): ao claim bind/list — 10th adapter CLI-exposed
Cycle 154 applies the cycle-147 template to a 10th adapter: productionClaimEvidenceBinder (cycle 116). Provides typed CLI for the claim→evidence promotion ledger. New surface: ao claim bind --claim AOP-CLAIM-X --path p.md --level PG2 [--anchor ...] ao claim list Wraps productionClaimEvidenceBinder — appends EvidenceBinding records to .agents/findings/evidence-bindings.jsonl with upgrade-only Level enforcement (per the port contract; downgrade attempts return an error surfaced through 'claim bind:' wrapping). Template adherence vs cycle-147 spec: ✓. Two new nuances: - Level validation (PG1-PG4) at the CLI layer via validateEvidenceLevelString helper. Catches typos before they reach the port. - Default --level=PG1 via cobra default flag, so 'ao claim bind --claim X --path Y' is valid for first-time bindings. New files: - cli/cmd/ao/claim_cmd.go (170 lines) — claimCmd parent + claimBindCmd + claimListCmd + level validator + path resolver. Both ops share claimOptions struct + injectable bindFn / listFn. - cli/cmd/ao/claim_cmd_test.go (115 lines) — 8 tests covering empty claim/path rejection, invalid level rejection, stub called with binding, default PG1 accepted, error wrapping, list returns bindings, empty list zero bytes. cli/docs/COMMANDS.md regenerated. 10 of 14 production adapters now CLI-exposed (~71%): loop history/append + ci latest/recent + corpus inject/capture + operator record/list + harness status + gate run + citation verify + claim bind/list. 4 remain (FactoryAdmission, ClaimEvidence, EventBus, FindingCompiler). Time: ~9 min. LOC: 285. Tests: 8. Within template band. Cycle 154 / template-applied CLI-wiring 7th application. |