mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
ao-pre-reduction@5b334a13f
1492 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bb8d747d3a |
feat(ao): add harness-neutral bead ports (#810)
## Summary - add harness-neutral BR/git ports: `ao ready`, `ao close ...`, and bare `ao claim <id>` while preserving `ao claim bind/list` - keep top-level gate commands from #809 as the shared gate surface; `ao close` reuses the typed commit-persist close path and returns success when the ledger already proves the bead is closed - regenerate command docs, command surface inventory, matrix counts, and registry metadata ## Validation - `go test ./cmd/ao -run TestTick -count=1` - `bash scripts/regen-all.sh && bash scripts/regen-all.sh --check` - `go test ./cmd/ao -count=1` - `go vet ./...` - `go test ./... -count=1 -short` - `git diff --check` - `/tmp/ao-cp-ljp ready` from `/Users/bo/dev/control-plane` returned `state_source=br`, `ready_count=20`, and counts `{ready:20, open:30, in_progress:1, closed:19}` - `/tmp/ao-cp-ljp claim cp-ljp` from `/Users/bo/dev/control-plane` succeeded and did not dirty the Git ledger - `PRE_PUSH_SKIP_MKDOCS=1 bash scripts/pre-push-gate.sh --fast` passed; warning-only executable-spec drift remains pre-existing (`scenarios --lint`, `trace --orphans`) BR: cp-ljp |
||
|
|
a617df3028 |
feat(ao): expose membrane gate aliases (#809)
## Summary - expose the membrane gate surfaces as top-level `ao` aliases: `verdict-gate`, `council-gate`, `install-guards`, `guard-status`, and `chaos-test` - keep the existing `ao tick ...` implementation as the shared backend, so the shell-oracle port and public aliases cannot drift - regenerate CLI command docs, surface inventory, matrix counts, and registry metadata ## Validation - `go test ./cmd/ao -run TestTick -count=1` - `bash scripts/check-cmdao-surface-parity.sh --write-surface` - `bash scripts/regen-all.sh --check` - `go test ./cmd/ao -count=1` - `go vet ./...` - `go test ./... -count=1 -short` - `/tmp/ao-cp-ltj chaos-test` from `/Users/bo/dev/control-plane` => `SMOKE PASS` - `./tick.sh smoke` from `/Users/bo/dev/control-plane` => `SMOKE PASS` - top-level alias exit matrix from `/Users/bo/dev/control-plane`: `council-gate` mixed => 8, unverified => 6 - `PRE_PUSH_SKIP_MKDOCS=1 bash scripts/pre-push-gate.sh --fast` passed; warning-only executable-spec drift remains pre-existing (`scenarios --lint`, `trace --orphans`) BR: cp-ltj |
||
|
|
9ddffab410 |
feat(ao): add typed tick oracle port (#808)
## Summary - add `ao tick` as a typed Go port of the control-plane tick oracle - preserve BR/git boundaries for next/status/claim/reopen/close and port verdict/council/guard/smoke behavior - update generated command inventory, registry, CLI docs, and command-surface fixtures ## Validation - cd cli && go test ./cmd/ao -run TestTick -count=1 - cd cli && go test ./cmd/ao -count=1 - cd cli && go vet ./... - cd cli && go test ./... -count=1 -short - bash scripts/check-cmdao-surface-parity.sh - bash scripts/regen-all.sh --check - git diff --check - PRE_PUSH_SKIP_MKDOCS=1 bash scripts/pre-push-gate.sh --fast - built /tmp/ao-cp7k6 and compared against /Users/bo/dev/control-plane/tick.sh for verdict-gate, council-gate, next; `ao tick smoke` returned SMOKE PASS Note: fast pre-push gate still reports existing warn-only executable-spec drift for scenarios --lint and trace --orphans. |
||
|
|
f4162649b8 |
fix(agentops): remove api-print worker paths (#804)
## Summary - replace AgentOps headless Claude print worker paths with Codex exec or non-CLI providers - switch compile auto-detect/default headless CLI runtime from claude-cli to codex-cli - fix two shellcheck blockers from the merged skill corpus and refresh generated docs/hash metadata ## Validation - bash /Users/bo/acfs/skill-pipeline/scripts/no-api-print-scan.sh /Users/bo/dev/agentops/skills /Users/bo/dev/agentops/scripts /Users/bo/dev/agentops/hooks - shellcheck --severity=error skills/compile/scripts/compile.sh scripts/eval-agent-harness.sh scripts/run-rpi-phases.sh skills/agy-rules-workflows/scripts/close-guard.sh skills/rch/scripts/mine_rch_history.sh - cd cli && go test ./cmd/ao -run 'TestResolveCompileRuntime|TestPreflightCompileRuntime|TestCompileScriptOptionsPassesBatchFlags|TestRunCompile_EndToEnd_FixtureCorpus' -count=1 - bash scripts/regen-all.sh --check - PRE_PUSH_SKIP_MKDOCS=1 bash scripts/pre-push-gate.sh --fast Note: unscoped /Users/bo/acfs/skill-pipeline/scripts/no-api-print-scan.sh still flags ACFS conformance-selftest fixture strings outside this repo; AgentOps scoped roots are clean. |
||
|
|
6d5d111faf |
feat(skills): land four-vendor skill corpus (#803)
## Summary - Lands the AgentOps skill corpus across source and Codex wrappers, including Gemini image targets. - Integrates the skill branch onto current origin/main and refreshes generated manifests/catalogs. - Normalizes local next-work queue enum drift and fixes shellcheck in alias-collision validation. ## Validation - bash scripts/regen-all.sh --check - bash scripts/validate-skill-schema.sh - bash tests/skills/test-token-budgets.sh - bash tests/skills/run-all.sh - bash scripts/audit-codex-parity.sh && bash scripts/validate-codex-override-coverage.sh && bash scripts/validate-codex-generated-artifacts.sh --scope worktree && bash scripts/validate-codex-api-conformance.sh && bash scripts/validate-codex-runtime-sections.sh && bash scripts/lint-codex-native.sh - bash skills/heal-skill/scripts/heal.sh --strict - PRE_PUSH_SKIP_MKDOCS=1 bash scripts/pre-push-gate.sh --fast MkDocs strict remains skipped locally via the documented PRE_PUSH_SKIP_MKDOCS=1 override because the repo currently emits repo-wide strict-link warnings unrelated to this landing; CI remains authoritative. |
||
|
|
b84dcf3ca2 |
docs(hookless): close cold-start orientation drift (soc-qh2g1 #cold-start-orientation-coherence) (#795)
## Summary Close the hookless cold-start orientation gap for `soc-qh2g1` by making the live startup docs and skills point at explicit `ao session bootstrap` plus pulled context (`ao inject` / `ao lookup`) instead of hidden SessionStart behavior. ## Changes - Reframes live docs that still implied automatic startup/handoff injection to the hookless explicit-command path. - Updates source and Codex skill mirrors for `quickstart`, `inject`, `using-agentops`, `recover`, `bug-hunt`, and `session-bootstrap`. - Expands the cold-start and docs drift gates so `SessionStart hook`, `startup hooks`, and `auto-inject ... hook` promises fail unless explicitly hedged as opt-in, removed, or historical. - Refreshes scoped Codex skill hashes for the touched mirrors. ## Test plan - [x] `bash scripts/check-hookless-cold-start.sh` - [x] `bash scripts/check-doc-hooks-drift.sh` - [x] `bats tests/scripts/check-hookless-cold-start.bats tests/scripts/check-doc-hooks-drift.bats` - [x] `shellcheck scripts/check-hookless-cold-start.sh scripts/check-doc-hooks-drift.sh` - [x] `bash scripts/regen-codex-hashes.sh --check --only session-bootstrap,quickstart,inject,using-agentops,recover,bug-hunt` - [x] `bash scripts/validate-codex-generated-artifacts.sh` - [x] `bash scripts/validate-codex-lifecycle-guards.sh` - [x] `bash scripts/validate-agents-split.sh` - [x] `git diff --check` - [x] `bash scripts/validate-skill-runtime-parity.sh` - [x] `bash scripts/lint-codex-native.sh` Closes-scenario: soc-qh2g1#cold-start-orientation-coherence Bounded-context: BC1-Corpus Evidence: scripts/check-hookless-cold-start.sh |
||
|
|
3bab897009 |
test(cli): migrate dedup_test.go to t.Chdir + lock isolation ratchet 163->151 (ag-4nif #dedup-tchdir) (#773)
## What Migrate `dedup_test.go`'s 6 manual `origDir, _ := os.Getwd(); os.Chdir(tmp); defer os.Chdir(origDir)` blocks to Go 1.20+ `t.Chdir(tmp)` — auto-restores cwd **and** refuses `t.Parallel`, pre-empting the latent flake class flagged by **ag-4nif** / **ag-k38x** (raw forms mutate process-global cwd). No `t.Parallel` in the file; behavior-preserving. Each block held two `os.Chdir(` references (the call + the defer restore), so 6 blocks drop the repo-wide test-isolation count by **12 (163→151)**. I lowered `BASELINE_CHDIR` in `scripts/check-test-isolation.sh` to **lock the gain** (the ratchet is only-goes-down). ## Scope / no-collision note `os.Chdir` only. The 3 redundant `os.Setenv` restores in `rpi_reliability_test.go` are **already handled by the open PR #772 (ag-k38x)** — I deliberately do **not** touch that file here, to avoid a merge collision (an earlier draft of this branch did; it was reverted). **ag-k38x is the canonical tracker; ag-4nif/ag-y4ac are duplicates** — worth closing as dup-of-ag-k38x during triage. ## Evidence ``` bash scripts/check-test-isolation.sh # PASS (os.Chdir=151/151, os.Setenv=22/22) cd cli go build ./... # OK go vet ./cmd/ao/ # No issues found go test ./cmd/ao/ -run 'TestRunDedup|TestMergeDedupGroups' -count=1 # 17 pass gofmt -l # clean ``` Net: −19 / +8 across `dedup_test.go` + the ratchet baseline. Closes-scenario: ag-4nif#dedup-tchdir Bounded-context: BC5-Runtime Evidence: ratchet PASS + go build/vet/test (17 pass) + gofmt clean |
||
|
|
69b8ba0a4f |
feat(liveness): add inbound admission core (ag-c3c7) (#757)
## Summary - Add a substrate-neutral inbound admission primitive in `cli/internal/liveness`. - Gate inbound work messages by source class and intent: authenticated operator directives may execute; peer/other-host/tmux directives are downgraded to proposals and cannot execute reflexively. - Require ratified quorum authority for quorum-sourced directives, with cross-model ACK verification for significant actions. - Extend the liveness composition test so the inbound admission path composes with role, quorum, judge, and lease primitives. ## Validation - `go test ./internal/liveness -count=1` - `go test ./...` from `cli/` - `PRE_PUSH_FAIL_FAST=false bash scripts/pre-push-gate.sh` ran and blocked on existing repo/environment gates: - `test-fixture parity break`: missing pre-push helper Bats stubs for `scripts/check-author-judge-convergence.sh` and `scripts/gc-stale-worktrees.sh` - `worktree disposition`: canonical root `/home/boful/dev/agentops` has pre-existing dirty/untracked operator state - `goals validate`: reported `open GOALS.md: no such file or directory` despite `GOALS.md` existing in this worktree - `corpus freshness`: newest corpus snapshot is 8d old, over the 7d threshold - `contract canaries`: distribution README install-line drift and pre-push governance Bats failure Branch-specific gate sections passed, including `go build`, `go vet`, changed-scope `go test -race`, command/test pairing, mutation-route guard, author!=judge convergence, and the full `cli` Go test suite above. ## Review Cross-model review required before merge. This is not self-graded. Refs: `ag-c3c7` |
||
|
|
2dbc575ea3 |
docs(agent-native): add Claude + Codex/NTM runtime reference recipes (ag-ok755 #agent-native-runtime-refs) (#789)
## What Completes ag-ok755's remaining acceptance: the `agent-native` skill shipped doctrine-only, missing the two runtime how-to references the bead requires (linked from SKILL.md per the heal `--strict` rule). - `references/managed-agents-runtime.md` — **Claude path**: Anthropic Managed Agents + Agent SDK + self-hosted sandbox. Carries the three-phase recipe (bundle → expose `ao` → CI-gate), the planned-mechanism status for `ao agent bundle` (ag-jspr) / `ao mcp serve` (ag-higd), and the ZDR / no-fork / CI-is-the-gate boundaries. - `references/codex-ntm-runtime.md` — **Codex/NTM path**: tmux pane swarms + agent-mail + direct `ao` shell calls (no Managed Agents API), with the Claude→Codex primitive substitution table. - Both linked from `SKILL.md` (runtime-recipes pointer + See Also). - Regenerated derived artifacts: skills-codex source-hash manifest/marker (source tree changed) and `registry.json` reference_count (1→3). ## Scope decision Catalog treatment for `agent-native` stays **`parity_only`** — the codex artifact is manual-maintained and already tailored (it has a dedicated Codex/NTM section), and the bespoke override-dir flip is a deliberate operator TODO in `skills-codex-overrides/catalog.json`. Not auto-flipping that here (operator judgment). ## Gates run (all green, in-worktree) - `heal.sh --strict skills/agent-native` — all references linked - All 7 codex-parity checks: parity audit, generated-artifacts (`--scope head`), backbone-prompts, override-coverage, runtime-sections, lifecycle-guards, parity-drift - `generate-registry.sh --check` — up to date - `markdownlint-cli2` on all changed/new files — 0 errors Closes-scenario: ag-ok755#agent-native-runtime-refs Bounded-context: BC5-Runtime Evidence: skills/agent-native/SKILL.md |
||
|
|
def8fc9bd4 |
chore(doctor): drop dead ao agentopsd/GasCity strings (ag-9hhm #dead-text-removed-surfaces) (#793)
## What Two dead-text remnants pointed operators at **retired surfaces** (discovered in the 2026-06-03 feature-map analysis). Pure string hygiene — no behavior change. 1. **`cli/internal/doctor/fix_bridges.go`** — `openclawHealthReport` and `snapshotStaleReport` instructed `ao agentopsd start/status/restart` and `ao agentopsd projection rebuild --consumer openclaw`. The in-repo daemon was **removed (ADR-0009)** and no such command exists. Reworded to: bring the OpenClaw daemon up out-of-band / regenerate the projection from the out-of-session substrate, naming the daemon removal instead of a dead command. (Also fixed two stale code comments naming `agentopsd`.) 2. **`cli/cmd/ao/forge.go:43`** — the `--legacy-local-llm` deprecation warning named *"AgentWorker/GasCity-backed Codex or Claude workers"*. Gas City was pruned (ag-124p) and the GasCity worker adapter removed. Reworded to point at a **Dream worker queue** (consistent with the existing language elsewhere in `forge.go`). ## Why These strings mislead operators toward commands/substrates that no longer exist; the `gc`/`agentopsd` prune was code-clean but the user-facing strings survived. ## Verification - `gofmt` clean; `go build ./...`; `go vet ./internal/doctor/ ./cmd/ao/` - `go test ./internal/doctor/` → 76 passed; `go test ./cmd/ao/ -run Forge` → 379 passed - `git grep "ao agentopsd"` / `GasCity` over live (non-test) code in touched files → empty - Updated the two doctor tests that asserted the old substrings. Closes-scenario: ag-9hhm#dead-text-removed-surfaces Bounded-context: BC5-Runtime Evidence: cli/internal/doctor/fix_bridges_test.go |
||
|
|
3df599df75 |
fix(ao): case-insensitive dedup in pool_ingest candidate IDs (soc-xn5s #dedup-case-insensitive) (#792)
## What
`buildCandidateFromLearningBlock` (cli/cmd/ao/pool_ingest.go) dedups the
three ID
components (`base`, `sessionHint`, `learningID`). `learningID` is
lowercased before
the check, but `base`/`sessionHint` keep their source-filename case. So
any source
filename with an uppercase character (e.g.
`2026-04-30-fix20260430T090800-1.md`)
**skipped** the `strings.Contains` dedup branch and produced a
**doubled** candidate ID:
```
pend-2026-04-30-fix20260430t090800-1-ag-test-fix20260430t090800-1 (id appears twice)
```
The final ID is lowercased by `Slugify` anyway, so the comparisons
should be
case-insensitive. Fix normalizes both sides of the equality/`Contains`
checks for
`base`↔`sessionHint` and `joined`↔`learningID`.
## Why it mattered
Verified live 2026-04-30 (soc-xn5s): a mixed-case source filename
re-amplified its
ID on each close-loop pass. Production residue was all-lowercase so
unaffected, but
the edge case remained uncovered.
## Test
Two regression subtests in
`TestPoolIngest_buildCandidateFromLearningBlock` reproduce
the exact doubled ID and the mixed-case session-hint duplication. Both
fail against the
old code, pass with the fix:
```
--- FAIL .../mixed-case_filename_does_not_double_the_learning_id
learning id token "fix20260430t090800-1" appears 2 times ... want exactly 1
--- FAIL .../mixed-case_session_hint_matching_base_is_not_appended
session hint token appears 2 times ... want exactly 1
```
`go build ./...`, `go vet ./cmd/ao/`, `gofmt -l` all clean.
Closes-scenario: soc-xn5s#dedup-case-insensitive
Bounded-context: BC1-Corpus
Evidence:
cli/cmd/ao/pool_metrics_test.go::TestPoolIngest_buildCandidateFromLearningBlock
🤖 Autonomous factory tick.
|
||
|
|
93bc54d401 |
fix(goals): drop unresolved heuristic scenario claims to kill prose false positives (soc-artx7 #orphans-prose-false-positive) (#779)
## What
`ao goals trace --orphans` reported **7 `broken_bead_scenario_claim`
warnings that were false positives** — bead-description prose mis-read
as scenario references. All 7 were multi-segment `auto-` slugs
(`auto-merge-update-branch`, `auto-safe-pull`, `auto-picks-up`,
`auto-regen-on-skill-change`, …) that match the heuristic free-text
token grammar but are lexically **indistinguishable** from genuine
auto-generated scenario IDs like `auto-nightly-evolution-dry-run`. No
regex can separate them — the only real discriminator is **resolution**
(does the token name an actual `spec/scenarios/<id>.json` or
`.agents/holdout/<id>.json` file?).
## Fix
`emitBeadClaimEdges` now drops heuristic (free-text) claims that resolve
to no scenario file *before* emitting an edge: a token matching the slug
grammar but naming no real scenario is prose, not a claim. This aligns
with ADR-0005 §4.1 — **only explicit `Scenarios:`-line claims are
defects.** Explicit claims are untouched: a broken explicit link stays
an **error**.
## Evidence (live repo, before → after)
| class | old | fixed |
|---|---|---|
| `broken_bead_scenario_claim` | **7** | **0** |
| `no_learning_yield` | 15 | 15 |
| `scenario_no_bead_claim` | 14 | 14 |
Surgical: only the 7 prose false positives drop; every other warning
class is unchanged. Acceptance ("`ao goals trace --orphans` returns 0
`broken_bead_scenario_claim` on current main, no false positives from
bead prose") met. This unblocks promoting `trace --orphans` to a
required gate.
## Tests
- `go test ./internal/goalstrace/...` — 78 pass (incl. new
`TestWalk_MultiSegmentProseAutoSlugProducesNoClaim` regression).
- Existing heuristic/explicit contract tests stay green; `gofmt`/`go
vet` clean.
Closes-scenario: soc-artx7#orphans-prose-false-positive
Bounded-context: BC5-Runtime
Evidence: cli/internal/goalstrace/beads_test.go
|
||
|
|
9af54d589a |
feat(corpus): per-session corpus-reuse receipt at session close (ag-469h #corpus-reuse-receipt) (#778)
## What
Makes the knowledge-flywheel moat **felt**. `ao session close` now
renders a per-session **corpus-reuse receipt**: a `Reused: N` table line
plus a loud `♻ Compounding: reused N prior learnings (titles…); corpus
now X entries` line. Closes the perception gap behind bead **ag-469h** —
users perceive the WRITE tax every session but never the READ payoff, so
they churn before the aha.
## How
- `computeReuseReceipt(cwd, sessionID)` reads
`.agents/ao/citations.jsonl` (via `ratchet.LoadCitations`), filters to
the closing session, dedupes by canonical artifact path, and excludes
`reference` (manual-pointer) citations — counting only
`retrieved`/`applied` read-payoffs.
- Corpus size counts durable `.md` under `.agents/{learnings,patterns}`.
- New `SessionCloseResult` fields
`Reused`/`ReusedTitles`/`CorpusEntries` (all `omitempty`, so JSON output
is backward-compatible).
- Best-effort: a missing ledger or corpus yields a zero receipt and
never fails the close. Cold runs print nothing.
- No new CLI command (avoids the surface-matrix canary churn documented
in ag-lkxx) — purely additive output on an existing command.
## Test
`cli/cmd/ao/session_close_receipt_test.go` — dedup, cross-session
isolation, reference-exclusion, empty/no-ledger zero-receipt,
singular-noun, cold-run silence, date-prefix title stripping, and
`printCloseTable` integration. Full `cmd/ao` suite green (`go test`/`go
vet`/`gofmt` clean).
Closes-scenario: ag-469h#corpus-reuse-receipt
Bounded-context: BC1-Corpus
Evidence: cli/cmd/ao/session_close_receipt_test.go
|
||
|
|
bc9a846dbd |
feat(eval): ao eval outcomes ingest --manifest-out emits eval-run.v1 manifest (ag-fy6e #manifest-out-eval-run) (#774)
## What
Adds `--manifest-out <dir>` (+ `--run-id`) to `ao eval outcomes ingest`.
When set, ingest **also** writes `<dir>/<run-id>/manifest.json`
conforming to `schemas/eval-run.v1.schema.json`, so the existing verdict
pipeline (`docs/contracts/eval-verdict-pipeline.md`) can pick it up and
feed the Knowledge Flywheel — closing the **Outcomes→Flywheel loop** for
the eval-run.v1 surface. Bead: **ag-fy6e**.
## How
- New file `cli/cmd/ao/eval_outcomes_manifest.go` (diversifies off
`eval_outcomes_ingest.go`); ingest.go only wires the thin flag.
- Reuses the existing `eval.RunRecord` struct rather than hand-rolling
the schema shape.
- Band mapping: `PASS→{status:pass, verdict:pass}`, `FAIL→{fail, fail}`,
`WARN→{inconclusive, advisory}`.
- `dimension_scores` filtered to the 7 schema-permitted keys (foreign
criterion dropped; `minProperties:1` guarded by synthesizing
`correctness=aggregate`).
- Out-of-process grade → honest schema-valid stubs for
`git`/`runtime`/`environment` + a `notes` provenance entry.
## Deviation from bead text (source-of-truth precedence)
The bead said `status=complete`, but that value belongs to the **other**
SCHEMA.md run-manifest. eval-run.v1's `status` enum is
`pass/fail/error/skipped/inconclusive` — no `complete` member — so this
follows the schema (per CLAUDE.md precedence: executable contracts >
narrative).
## Scope boundary (honest)
This delivers **only** the eval-run.v1 emission named in the bead's
ACCEPTANCE CRITERIA. The downstream `eval-verdict-compiler.sh` /
SCHEMA.md run-manifest path (rc3 struct verdict + holdout-sensitive
`ground_truth_ref/hash`) remains **BLOCKED** on the external compiler
contract + a holdout-safety decision, per the bead's own 2026-05-30
SCOUT CORRECTION. eval-run.v1 carries no holdout-sensitive fields, so
that blocker does not apply to this slice. Bead left open for the
compiler-path follow-up.
## Verification
- `go build ./... && go vet ./cmd/ao/` clean
- 77 eval/outcomes tests pass (`go test ./cmd/ao/ -run 'Eval|Outcomes'`)
- Real CLI run writes a manifest that validates against
`eval-run.v1.schema.json` via python `jsonschema`
- `cli/docs/COMMANDS.md` regenerated for the two new flags
Closes-scenario: ag-fy6e#manifest-out-eval-run
Bounded-context: BC2-Validation
Evidence: cli/cmd/ao/eval_outcomes_manifest_test.go
|
||
|
|
7265fda1b1 |
chore(test): migrate redundant os.Setenv to t.Setenv; lower isolation ratchet 22->12 (ag-k38x #bulk-migration-setenv) (#772)
## What Advances the test-isolation ratchet (`scripts/check-test-isolation.sh`, shipped in #699) by driving the `os.Setenv` baseline from **22 → 12**. Pure test-hygiene; no production-code change. `t.Setenv` auto-restores on cleanup **and** fails fast under `t.Parallel` — the raw `os.Setenv` form is the latent-flake landmine the ratchet exists to retire (cf. ag-jfzs). ## Sites migrated (10 eliminated) | File | Δ | How | |---|---|---| | `internal/config/config_test.go` | -6 | Collapse the `origX := os.Getenv(...)` + `defer os.Setenv(... restore)` block into 3× `t.Setenv` | | `internal/goals/measure_test.go` | -1 | Delete the redundant `origPath`/`defer os.Setenv` — the existing `t.Setenv("PATH","")` already auto-restores | | `cmd/ao/rpi_reliability_test.go` | -3 | Delete 3 redundant restore-defers wrapped around existing `t.Setenv` calls | ## The remaining 12 are intentional (not migratable) Documented inline in the ratchet script. They cannot use `t.Setenv`: - **TestMain** (`cmd/ao/main_test.go`, `internal/doctor/doctor_testmain_test.go`) — no `*testing.T` in scope (4) - **String-literal fixtures** (`internal/doctor/fix_cliconfig_test.go`) — `os.Setenv` appears inside generated test-program source, not a real call (2) - **Unset-semantics helpers** (`cmd/ao/handoff_test.go`, `internal/lifecycle/repo_readiness_test.go`, `internal/wiki/locator_test.go`) — these `os.Unsetenv`+restore vars; `t.Setenv` has no unset form (6) ## Verification - `bash scripts/check-test-isolation.sh` → `PASS … os.Setenv=12/12` - `go build ./...` ✓ · `go vet` (touched pkgs) ✓ - `go test ./internal/config/ ./internal/goals/` → 526 passed; touched cmd/ao tests → 3 passed Closes-scenario: ag-k38x#bulk-migration-setenv Bounded-context: BC5-Runtime Evidence: scripts/check-test-isolation.sh PASS 12/12 |
||
|
|
ba2d0380b2 |
feat(eval): holdout-leak key-name backstop for outcomes compile (ag-uux93 #holdout-key-guard) (#770)
## What Adds the key-name leak backstop that **ag-uux93** explicitly calls for on `ao eval outcomes compile`: re-parse the emitted Outcomes rubric payload and refuse any object key (at any depth) matching `/target|ground_truth|expected_output|answer/i`. ## Why The compile command itself already shipped (under sibling **ag-hdqu0** / #601) with a value-based guard (`ContainsAny` scans for known holdout *values* — layer 3). ag-uux93 additionally requires a **structural key-name** backstop: "re-parse the emitted payload and assert no key matches `/target |ground_truth|expected_output|answer/i`; abort + non-zero exit if found." This is **additive defense-in-depth** at a load-bearing boundary — Managed Agents are not ZDR, so a holdout leak across the cloud boundary is permanent. The allowlisted `Rubric` struct can't carry such a key today; the guard *pins that invariant* so a future field that smuggles ground truth fails closed instead of leaking silently. ## Changes - `evalsubstrate.ScanForbiddenKeys(payload []byte)` — walks decoded JSON for leak keys at any nesting depth - `Rubric.HasForbiddenKey()` — marshals + scans (mirrors the existing `ContainsAny`) - Wired into `compileOutcomesRubric` after the value-scan, before return (structured non-zero error on hit) - Unit tests: positive (nested / case-insensitive / substring), clean rubric, unparseable input, allowlist-by-construction invariant ## Verification `cd cli && go build ./... && go vet ./... && go test` — build + vet clean; evalsubstrate 92 pass, cmd/ao outcomes/rubric 30 pass; gofmt clean. ## Scope note for maintainer ag-uux93's spec also describes a `--suite/--split/--out` **flag interface** reading locked YAML from `~/.agents/evals/`. The shipped #601 command deliberately took a **JSON-input** design (`ao eval outcomes compile <input.json>`) instead. I did **not** unilaterally rewrite that working interface in an unattended tick — that's an intentional design fork needing your call. Queued to `bo-queue`. This PR closes only the `#holdout-key-guard` scenario. Closes-scenario: ag-uux93#holdout-key-guard Bounded-context: BC4-Evals Evidence: cli/internal/evalsubstrate/holdout_guard_test.go |
||
|
|
22543558a4 |
refactor(cli): convert beads verdict os.Exit calls to typed exit-error (ag-x22j #beads-exit-as-typed-error) (#769)
## What
`ao beads verify|lint|audit` used exit-code-as-verdict but signalled it
by calling `os.Exit(1)` **inside** RunE. `os.Exit` skips deferred
cleanup (temp files, lock release) and kills the test binary, so the
verdict branches were untestable.
This converts the 3 sites to return a typed `*beadsExitError`, which
`Execute()` maps to the process exit code at the single root exit point
— the established CLI idiom (mirrors `gateExitError` in `validate.go`
and `doctorExitError` in `doctor_surface.go`).
## Sites converted
- `runBeadsVerify` (`beads.go`) — stale citations → exit 1
- `runBeadsLint` (`beads.go`) — stale beads → exit 1
- `runBeadsAudit` (`beads_audit_cluster.go`) — `--strict` + flagged →
exit 1
## How
- New `beadsExitError{code}` type (`Error()` empty, `ExitCode()`), since
the verdict text already went to stdout.
- The returning RunE sets `cmd.SilenceErrors` (nil-guarded) so cobra
prints no spurious `Error:` line; **genuine** errors returned elsewhere
in those commands still print normally.
- `Execute()` gains a `beadsExitError` branch before the generic
fallback.
## Evidence
- `cli/cmd/ao/beads_exit_test.go` — pins the verdict contract: verify +
lint stale → `*beadsExitError` exit 1 + `SilenceErrors`; clean → nil;
nil-cmd no panic.
- `cd cli && go build ./... && go vet ./cmd/ao/` clean; `gofmt -l`
clean.
- Full `go test ./cmd/ao/` → **9314 passed**.
## Bead
`ag-x22j` (P3, child of the Go idiomatic audit `ag-tcf0`). No more
`os.Exit` outside `main`/root in the beads command paths.
Closes-scenario: ag-x22j#beads-exit-as-typed-error
Bounded-context: BC5-Runtime
Evidence: cli/cmd/ao/beads_exit_test.go
|
||
|
|
5f69150169 |
test(cli): migrate curate_test.go os.Chdir to t.Chdir (ag-y4ac #curate-tchdir-w2) (#786)
## What Collapse 7 identical `os.Getwd()` + `os.Chdir(tmpDir)` + `t.Cleanup(restore)` blocks in `cli/cmd/ao/curate_test.go` to `t.Chdir(tmpDir)`. Bare downstream `err =` first-uses promoted to `err :=` (the removed block held the only function-scope `err`). ## Why `t.Chdir` auto-restores cwd on cleanup **and** refuses to run under `t.Parallel` — pre-empting the process-global-cwd flake class (cf. ag-jfzs). This is one wave of the ag-k38x / ag-y4ac test-isolation sweep (`finish-the-job`: ~133 sites already use the safe idiom). ## Scope / collision-safety - `os.Chdir` in `_test.go`: **163 → 149 (-14)**. `os.Setenv` untouched (owned by in-flight setenv ratchet **PR #772**). - **`BASELINE_CHDIR` intentionally NOT lowered** — that single line is the contention point with in-flight **PR #772/#773**; the ratchet stays green because count-below-baseline is a NOTE, not a failure (`149 <= 163`). A later wave locks the baseline once those settle. - Non-overlapping with PR #772 (rpi setenv) and PR #773 (dedup_test.go os.Chdir). ## Verification - `gofmt -l` clean · `go build ./...` · `go vet ./cmd/ao` clean - `go test ./cmd/ao -run TestCurate` → 14 pass - `scripts/check-test-isolation.sh` → PASS (os.Chdir=149/163, os.Setenv=22/22) - `scripts/pre-push-gate.sh --fast` → passed Closes-scenario: ag-y4ac#curate-tchdir-w2 Bounded-context: BC5-Runtime Evidence: .ntm/bo-queue/2026-06-06-ag-y4ac-pr-curate-tchdir.md |
||
|
|
f56f5b1521 |
chore(lint): clear 13 golangci-lint findings (ag-tcf0.1 #golangci-lint-clear) (#777)
## What
Clears all outstanding `golangci-lint run` findings in `cli/` — **13
issues** across 8 files. Pure mechanical lint cleanup, no behavior
change. (Several were hidden behind golangci-lint's default
`max-same-issues=3` display cap; running with caps disabled surfaced the
full set.)
| Linter | Count | Fix |
|---|---|---|
| errcheck | 7 | unchecked `f.Close()` → `defer func() { _ = f.Close()
}()` / `_ = f.Close()` |
| staticcheck S1016 | 2 | struct-literal copy → type conversion
(`reconcileCIRun(run)`, `reconcileBeadSummary(issue)`) |
| staticcheck QF1012 | 2 | `b.WriteString(fmt.Sprintf(...))` →
`fmt.Fprintf(&b, ...)` |
| staticcheck QF1001 | 1 | De Morgan: `!(a && b)` → `a' || b'` |
| copyloopvar | 1 | drop redundant `fx := fx` (Go 1.22+ per-iteration
loop var; go.mod is 1.26) |
Files: `loop_blocked.go`, `loop_next_work.go`, `cron_self_adjust.go`,
`reconcile.go`, `provenance_trace_test.go`, `internal/canon/ledger.go`,
`internal/scenarios/validate.go`, `internal/skills/catalog.go`.
## Verification
- `go build ./...` ✅ · `go vet ./...` ✅
- `golangci-lint run --max-same-issues 0 --max-issues-per-linter 0` →
**0 issues** ✅
- `go test ./internal/canon/... ./internal/scenarios/...
./internal/skills/...` → 116 passed ✅
- targeted `cmd/ao` tests (provenance/reconcile/cron/blocked/next-work)
→ ok ✅
- `scripts/pre-push-gate.sh --fast` → passed ✅
Closes-scenario: ag-tcf0.1#golangci-lint-clear
Bounded-context: BC5-Runtime
Evidence: golangci-lint run --max-same-issues 0 → 0 issues (verified
locally; CI re-runs the omnibus gate)
|
||
|
|
1601467387 |
chore(docs): gut dead-mechanism context poison from agent-facing docs (ag-sjz8 #gut-poison) (#764)
## What Gut **context poison** — agent-facing docs that route a working agent at DEAD mechanisms. This poisoned a live fleet-operating session (the bo driver building the go-dark supervisor) into proposing `ao rpi` as a continuity-loop worker. Found via a 5-way parallel poison fan-out. **Scope: operational-surgical** (Bo's explicit call). Gut the agent-facing *operational* guidance + *factual* errors; **LEAVE** the README/`docs/3.0.md` product narrative (Gas-City-as-reference-substrate is coherent, ADR-backed product design — a different altitude from Bo's live fleet). ## Changes (10 files, surgical) **Tier A — operational guidance (the poison that bit me):** - `CLAUDE.md` Session Constraints: "route multi-phase work through `ao rpi`" → the live substrate (NTM + MCP Agent Mail + `continuity-loop`); `gc` reframed as optional-out-of-session, **not** the live substrate. Kept the accurate "bridge REMOVED" + "load-bearing legacy" lines. - `AGENTS.md`: dropped the deleted "scheduling daemon" (ADR-0009). - `AGENTS-RUNTIME.md`: `ao rpi serve --help` → the real `ao` command surface. **Tier B — hookless-factual** (3.0 installs no hooks by default): hookless banners on `ARCHITECTURE.md` + `reference.md` (surgical vs. rewriting diagram internals); corrected SessionStart-hook prose in `context-packet.md` + `vs-claude-flow.md`. **Tier C — retired `/dream` shown as live:** marked retired in `evolve`/`harvest`/`using-agentops` (compounding moved to Gas City). `curate` **intentionally left** — its `--mode=dream` is the forward replacement, not poison. ## Guardrails - Does **not** claim `ao rpi` was deleted — the command still compiles (`loop`/`phased`/`serve` exist); only its role as the *live workflow* is corrected. - registry.json unaffected (skill **bodies** only; `generate-registry.sh --check` = OK). ## Evidence `bash scripts/generate-registry.sh --check` → OK. Diff is 20 insertions / 16 deletions across 10 files. Bounded-context: BC1-Corpus (agent-facing context docs) Evidence: this PR diff + the parallel fan-out inventory Closes: ag-sjz8 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
8611b71f0f |
feat(corpus): auto-snapshot before destructive defrag prune (ag-32xk #defrag-autosnapshot) (#771)
## What `ao defrag` now takes an **automatic, recoverable corpus snapshot** before it applies a destructive `--prune` (anything that deletes from `.agents/`). It reuses the same tar.gz machinery as `ao corpus snapshot`, so an over-aggressive cleanup is always rehydratable via `ao corpus restore`. ## Why (ag-32xk — moat durability) The corpus moat is switching-cost / data-gravity, not tech — and it is one accidental delete away from losing its receipts. Directive #11 history: routine maintenance wiped `.agents/` subdirs, counts went to ~0. A moat you can lose to routine cleanup doesn't feel like a moat. This closes the most common loss path (the destructive defrag) first. ## Behavior - **Apply-mode prune** → snapshot first, then prune. - **Safe-by-default**: a snapshot failure *aborts* the prune — we refuse to delete files we couldn't first back up. - **No-op** for: dry-runs (nothing deleted), dedup-only runs (flags, never deletes), and `--no-snapshot` (new escape hatch). ## Changes - `corpus_snapshot.go`: extract `createCorpusSnapshot()` as the shared engine behind both the `ao corpus snapshot` command and the defrag auto-snapshot (no behavior change to the command). - `defrag.go`: `autoSnapshotBeforeDefrag()` + `--no-snapshot` flag + help text. - `defrag_autosnapshot_test.go`: 6 tests (apply-prune snapshots; dry-run/no-snapshot/dedup-only skip; missing-corpus aborts; L2 `runDefrag` leaves a recoverable tarball). - `cli/docs/COMMANDS.md`: regenerated for the new flag (passes `generate-cli-reference.sh --check`). ## Scope Slice of ag-32xk. **Remaining (bead stays open):** `ao curate` auto-snapshot + a canon/promoted-entry delete guard. ## Verification - `cd cli && go build ./... && go vet ./cmd/ao/` — clean - `go test ./cmd/ao/` — 9315 pass - `scripts/pre-push-gate.sh --fast` — passed (CLI docs parity green) Closes-scenario: ag-32xk#defrag-autosnapshot Bounded-context: BC1-Corpus Evidence: cli/cmd/ao/defrag_autosnapshot_test.go |
||
|
|
784fcfca4e |
fix(test): convert goals integration lifecycle to subprocess isolation (ag-x2gv #flaky-goals-integration) (#762)
## Summary - Convert `TestGoals_Integration_FullLifecycle` from in-process `rootCmd.Execute()` + `captureStdout` + `chdirTemp` to subprocess `exec.Command(bin, ...)` with isolated `t.TempDir()` - Eliminates process-global state sharing (`os.Chdir`, `os.Stdout`, cobra `rootCmd`) that caused intermittent empty-stdout failures under `-race -shuffle=on` - Same fix pattern as ag-z8c4 (PR #761) which fixed the analogous `TestFlagMatrix_QuietMode` flake ## Test plan - [x] 20/20 passes in isolation (`-run TestGoals_Integration_FullLifecycle -race -shuffle=on -count=20`) - [x] Full package suite green (`go test -race -shuffle=on -count=1 ./cmd/ao/`) - [x] `go vet ./cmd/ao/` clean - [x] `go build ./cmd/ao/` clean Closes-scenario: ag-x2gv#flaky-goals-integration Bounded-context: BC5-Runtime Evidence: 20/20 pass with -race -shuffle=on -count=20 |
||
|
|
6489da8fab |
chore(cli): gofmt agent_bundle.go struct-literal indentation (ag-tcf0.2 #gofmt-agent-bundle) (#783)
Fixes a gofmt drift that landed on `main`: `cmd/ao/agent_bundle.go` had
an extra-tab indent on the `Bootstrap` field of the codex-ntm bundle
struct literal (unformatted since
|
||
|
|
a3457c001d |
test(posture): restore stance-claim enforcement lost when internal/gascity removed (ag-ddrb #posture-tests) (#791)
## What
Adds `cli/internal/posture/posture_test.go` — the package had **zero**
tests.
## Why
`internal/posture/posture.go` is pure and deterministic but its doc
comment promises:
> the AgentOps stance claim "must either update this value or fail the
integration test in `cli/internal/gascity/bridge_test.go`"
`internal/gascity` was **deleted** (ag-hfc, 3.1 teardown — confirmed in
CLAUDE.md), so that enforcing test no longer exists. The `AgentOps`
stance declaration has been **unguarded** since. `TestAgentOpsStance`
here is the replacement regression guard: a silent edit to the stance
now fails CI.
## Coverage
Behavioral, table-driven, **100.0% statement coverage** (10 tests):
- `Layer.String()` — all six + sentinel/out-of-range
- Layer bit-position values (the shift-amount contract `LayerSet`
depends on)
- `LayerSet` `NewLayerSet`/`Has`/`Union` — idempotence, commutativity,
empty-set identity
- `AllLayers` / `ExternalLayers` exact membership ("Bead is universal")
- `Kind.String()` — all families + out-of-range
- `AgentOps` stance invariant: `Kind=Distribution`, owns exactly
`{Role,Skill,Ledger,Distribution}`, does **not** own `Loop`, `Bead` is
external
- owned ⊆ `AllLayers` structural invariant
No coverage-padding: every assertion checks exact behavior or a
documented invariant.
## Verification
```
go test ./internal/posture/ -cover → ok 100.0% of statements (10 pass)
go vet ./internal/posture/ → clean
golangci-lint run ./internal/posture/ → 0 issues
gofmt -l → clean
```
Closes-scenario: ag-ddrb#posture-tests
Bounded-context: BC5-Runtime
Evidence: go test ./internal/posture/ -cover → 100.0%
|
||
|
|
a6958e6ff0 |
feat(memory): enforce reach always error budget (#752)
## Summary - enforce a computed `reach=always` error budget over established canon learnings during maturity reconciliation - immediately demote independently refuted canon entries to `pull` while preserving budget and archiving the demoted artifact - spend budget on independent harmful outcomes and 45-day citation droughts, reset budget on fresh cross-engineer positive citations, and carve out foundation contracts from blind drought spends - append provenance ledger evidence for runtime demotions ## Validation - PASS: `cd cli && go test ./cmd/ao -run 'TestMaturity_reachAlwaysBudget|TestMaturity_runMaturityScanAll_reconcilesHelpfulCitationBeforeApply|TestMaturity_runMaturityScanAll_retrievedCitationDoesNotChangeUtility' -count=1`\n- PASS: `cd cli && go test ./cmd/ao -run 'TestMaturity_reachAlwaysBudget' -count=1`\n- PASS: `cd cli && go test ./cmd/ao -count=1`\n- PASS: `cd cli && go test ./internal/lifecycle ./internal/provenancegraph ./internal/search ./internal/ratchet -count=1`\n- PASS: `git diff --check`\n- RAN: `bash scripts/regen-all.sh` (known CMDAO `wiki query` red only; restored timestamp-only registry drift)\n- RAN: `PRE_PUSH_FAIL_FAST=false bash scripts/pre-push-gate.sh` (blocked on known main-red set: fixture parity, goals validate, corpus freshness, contract-canaries/pre-push-bats governance, dirty canonical root/worktree disposition)\n\n## Coordination\n- Bead: ag-v81n\n- Cross-model review required before merge; no self-grade.\n |
||
|
|
df3cc9803b |
fix(memory): reconcile W6 cutover commands
Reconcile W6 memory cutover surfaces so runnable/doc commands match the real CLI. Cross-model ACKs: WindyCastle Agent Mail #225, RubyMoose Agent Mail #226. Required checks green; Cursor Bugbot non-required pending under recorded exception. |
||
|
|
ec11c9a7f5 |
fix(memory): relabel negative citation feedback
Relabel harmful/refuted citation feedback decisions as penalized while preserving the reward=0 soft-penalty behavior. Cross-model ACKs: WindyCastle Agent Mail #220, RubyMoose Agent Mail #221. Required checks green; Cursor Bugbot non-required pending under recorded exception. |
||
|
|
57ec8f3290 |
docs(memory): remove legacy bd-memory guidance
Implements ag-i788 W4.3. Cross-model ACKs recorded in Agent Mail: RubyMoose #214 and WindyCastle #213. Required checks green; merge proceeds under the recorded Cursor Bugbot non-required instability exception. |
||
|
|
d135c56f5c |
feat(memory): reconcile citation outcomes before maturity
Implements ag-sx9c W3.2. Cross-model ACKs recorded in Agent Mail: WindyCastle #208 and RubyMoose #209. Required checks green; merge proceeds under the recorded Cursor Bugbot non-required instability exception. |
||
|
|
f735779124 |
docs(memory): re-source lesson recall contract
Resolve ag-qa01 by re-sourcing lesson recall contracts to markdown-as-source while preserving legacy bd memory lineage during W4 transition.\n\nQuorum: WindyCastle ACK #202 and RubyMoose ACK #203 at
|
||
|
|
466842d9bd |
feat(memory): add citation outcome taxonomy (#741)
## Summary Implements `ag-rbx8` W3.1 citation outcome taxonomy and reviewer identity plumbing for memory feedback. - Adds canonical citation types: `retrieved`, `used-in-final-artifact`, `helpful`, `harmful`, `refuted`, while preserving legacy `applied`, `reference`, and `skill_loaded`. - Extends citation events with `artifact_author_id`, `cited_by_agent_id`, and `cited_by_model_family`. - Parses legacy identity aliases in citation JSONL (`author_id`, `reviewer_id`, `judge_id`, `model_family`). - Updates `ao metrics cite` with non-author identity flags and rejects self-authored outcome judgments. - Teaches citation pipeline and feedback-loop logic that retrieved-only is exposure, helpful/final-artifact/applied are rewardable, and harmful/refuted are explicit non-reward outcomes. - Regenerates CLI command docs and `registry.json`. ## Validation Focused tests after rebase over #737 (`origin/main` @ `7bbc6569`): - `go test ./internal/types ./internal/ratchet ./internal/quality ./internal/lifecycle` - `go test ./cmd/ao -run 'TestMetricsCite|TestProcessCitationFeedback|TestCitationConfidenceBuckets|TestValidateFeedbackCitationType|TestFlagCompletions_Registered|TestComputeCitationPipeline|TestCanonicalCitationType'` - `go test ./cmd/ao` - `git diff --check` Required regen/gate: - `bash scripts/regen-all.sh` completed generated artifact updates, then exited on known CMDAO surface parity red (`wiki query`; 30 uncovered commands). - `PRE_PUSH_FAIL_FAST=false bash scripts/pre-push-gate.sh` completed with 5 known non-diff failures: - test-fixture parity: `scripts/gc-stale-worktrees.sh` - worktree disposition: canonical root dirty/untracked operator state - goals validate: local `GOALS.md` lookup red - corpus freshness: newest local snapshot over threshold - contract canaries: known `agentops-core.pre-push-gate-governance` failure Diff-owned checks passed in the gate, including go build, go vet, changed-scope race tests, command/test pairing, registry drift, CLI docs parity, mkdocs strict build, contract compatibility, CI policy parity, context-map drift, shellcheck, skill citation parity, and executable-spec link integrity. ## Review Gate No self-grade: requesting cross-model review from WindyCastle and RubyMoose before merge. Bead: `ag-rbx8` |
||
|
|
76af462b45 |
refactor(evidencedturn): converge author≠judge onto liveness.Disjoint (DRIFT fix, impl #2) (#744)
## What WindyCastle's vibe-check (Agent Mail #149) found the **no-self-grade / author≠judge invariant fragmented across 3 divergent implementations** on main: 1. `liveness.Disjoint` (ag-xdrw/#737) — the canonical one. 2. `evidencedturn`'s `evalAuthorNeqValidator` (ag-lmdx.4) — **this PR**. 3. #741's inline `EqualFold` — SageHarbor converges in parallel. That divergence (empty-handling / case / waiver) is **why the empty-ID self-grade bypass recurred** (#737 PG3/PG4 → #741 citation reward). This PR converges **impl #2**: `evalAuthorNeqValidator` now routes its core author≠judge decision through `liveness.Disjoint`. ## Behavior-preserving `Disjoint` denies on `empty-author OR empty-judge OR author==judge` — **identical** to the prior inline checks. Verified: all existing `evidencedturn` tests pass unchanged. Preserved: the `--allow-self` waiver (explicit pre-check) + the specific legible reason strings. ## Anti-recurrence lock Adds `TestAuthorNeqValidator_AgreesWithDisjoint` — asserts the validator's decision matches `liveness.Disjoint` across every identity case (distinct / self-graded / empty-author / empty-judge / both-empty) + the waiver. **A future re-divergence fails CI** — the structural fix WindyCastle's finding asks for. ## Scope 2 files (`evidencedturn.go` +28/−10, `evidencedturn_test.go` +37). `evidencedturn`→`liveness` import, **no cycle** (liveness doesn't import evidencedturn). No overlap with #741 (different package — SageHarbor owns impl #3). `go build ./...` + vet + race + package tests green; 4 reds are the known non-diff set. > Provenance: bead pending Dolt write recovery (down per #149); vibe-check #149 + Agent Mail #151 carry the claim. File the p1 DRIFT bead when Dolt's back. Bounded-context: BC5-Runtime Evidence: TestAuthorNeqValidator_AgreesWithDisjoint |
||
|
|
0c5554f1bc |
build(factory): one-shot regenerator for ao-command-landing surfaces (ag-jy12 #command-regen) (#742)
## What A ONE-SHOT regenerator (`scripts/regen-command-surfaces.sh`) for the `ao`-command-landing derived surfaces. When an `ao` command is added/removed/renamed, these surfaces must update in lockstep — the multi-surface tax that bit #720 (ag-sz3h, ~4 extra CI rounds): - the two cobra `expectedCmds` literals in `cli/cmd/ao/cobra_commands_test.go` - the `cli-command-surface` heading counts: `evals/agentops-core/fixtures/cli-command-surface-smoke.sh` + `evals/agentops-core/cli-command-surface-matrix.json` ## How - **Single source of truth for the command set**: the LIVE cobra tree, dumped by the new `TestDumpRegisteredTopLevelCommands` (set `AO_DUMP_REGISTERED_CMDS=1`). It walks `rootCmd.Commands()` (sorted, `help` excluded) — exactly the membership the two `expectedCmds` literals must match. A *test*, not a subcommand, so emitting the list does not itself add a registered command (which would be circular). - **Single source of truth for the counts**: `cli/docs/COMMANDS.md` (itself generated from the cobra tree). `top = ### \`ao `, `sub = #### \`ao `, `all = #{3,4} \`ao `. - Rewrites all three derived surfaces deterministically. The `expectedCmds` literals are reformatted one-element-per-line (gofmt-stable) so output is canonical forever — **membership is identical to before (pure reformat)**. - **Idempotent**: a no-change tree is a no-op; `--check` fails on drift without writing. - Wired into `regen-all.sh` (both regen + `--check`) right after the COMMANDS.md step. ## Deletion ⊃ Addition (completeness note) Removing/renaming a command is a SUPERSET of adding one. This regenerator covers the ADD surfaces. A delete/rename ALSO disturbs surfaces it does NOT auto-regenerate — these need manual/quorum attention: - (a) codex-contract gates that hardcode command literals (`validate-codex-rpi-contract.sh`) - (b) skills-codex twins/overrides (`export-claude-skills-to-codex` + `regen-codex-hashes`) - (c) VERBATIM-PRESERVE template SHAs (`cron-loop-mode.md` frontmatter) A "deletion ⊃ addition" note is present in the regenerator header comment AND the `regen-all.sh` operator reminder. ## Verification - `scripts/regen-command-surfaces.sh` → no-op on clean tree; `--check` green. - `go build ./cmd/ao`, `go vet ./cmd/ao`, `go test ./cmd/ao` (full package) all pass; `gofmt -l` clean. - `cli-command-surface-matrix` canary: pass. Smoke fixture: pass. - Pre-push gate's only reds are pre-existing, unrelated canaries (`context-packet-ab-wave0`, `agentops-core.pre-push-gate-governance` bats) — not touched by this diff. Closes-scenario: ag-jy12#command-regen Bounded-context: BC4-Factory Evidence: scripts/regen-command-surfaces.sh |
||
|
|
9c6b4036bf |
test(liveness): end-to-end kernel composition test (ag-c3c7 #compose) (#743)
## What An **L2 integration test** proving the 5 liveness files — built across separate PRs by separate contexts (#733 roles, #737 quorum/guards, #739 work_lease) — compose into **one admission lifecycle on one vocabulary**, not five parallel ones. `TestKernelComposition_FullAdmissionFlow` walks the full flow: 1. **Role-matrix SoD** (`roles`) — worker edits, worker can't self-vote, orchestrator can't edit (injection defense). 2. **External role source** (`request`+`guards`) — leased role passes `Check`; self-asserted (source==actor) → `Denied`. 3. **Work-lease** (`work_lease`) — the just-authorized identity takes a lease. 4. **Author≠judge** (`guards.Disjoint` via `Check` `VerbJudge`) — self-judge `Denied`, distinct verifier `Allowed`; high-level `Check` and low-level `Disjoint` must **agree**. 5. **Cross-model quorum** (`quorum`) — solo→NeedsAdmission, actor self-ACK doesn't count, two same-family ACKs don't clear (collusion guard), two distinct families clear. 6. **Hard expiry + takeover** (`work_lease`) — late renewal `ErrLeaseExpired`, deadman sweep surfaces it, distinct owner takes over via `Create`. ## Why WindyCastle's vibe-checks *assert* the kernel composes; this *proves* it mechanically and **locks it against regression** — if a future change breaks the composition (e.g. `Check VerbJudge` stops routing through `Disjoint`, or quorum drops family-diversity), this fails where the per-file unit tests wouldn't. ## Scope New test file ONLY (`cli/internal/liveness/kernel_composition_test.go`). **Zero production code touched.** Exercises only public APIs already on main. `go build ./...` + `go vet` + full liveness package green; the 4 local reds are the known pre-existing non-diff set. Closes-scenario: ag-c3c7#compose Bounded-context: BC5-Runtime Evidence: TestKernelComposition_FullAdmissionFlow |
||
|
|
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 |
||
|
|
853d781e66 |
feat(memory): inject canon memory during session bootstrap (#740)
## Summary Implements ag-11bi W2.3 canon-gated T2 bootstrap memory for `ao session bootstrap`. - Selects only canon-promoted established learnings plus high/critical severity canon anti-patterns from `.agents/canon/learnings`. - Ranks by `utility * confidence * freshness`, caps selection at 1200 estimated tokens, and warns on stderr when eligible canon memory exceeds the cap. - Computes reach through the existing search reach helper, so established canon memory surfaces as `reach=always` without author-set reach. - Emits the memory payload in JSON/robot output and prints selected memory in the default human bootstrap output. - Extends `schemas/session-bootstrap.v1.schema.json` and tests the filter, budget, warning, and human-output paths. ## Validation Focused checks: - `go test ./cmd/ao -run 'TestSessionBootstrap'` - `go test ./internal/search ./internal/types` - `git diff --check` - `python3 -m json.tool schemas/session-bootstrap.v1.schema.json` Required regen: - `bash scripts/regen-all.sh` regenerated artifacts but exited on the known CMDAO `wiki query` parity red. 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 Go race tests, command/test pairing, goals validate, registry drift, CLI docs parity, command-surface matrix canary, schema checks, CI policy parity, and shellcheck. ## Review Ask Requesting cross-model ACK/AMEND/BLOCK before merge. Primary attacks to run: - Does any non-canon or candidate/provisional learning enter bootstrap memory? - Can the 1200-token cap be bypassed or hidden from callers? - Does the default human path actually expose the selected memory, not just JSON? - Is the generated CLI-surface drift acceptable as regen output on this branch? No self-grade for merge. |
||
|
|
6f3b0aac04 |
feat(liveness): typed work-lease tracking (ag-c3c7.2 #work-lease) (#739)
## What
A deterministic liveness-domain **work-lease tracker** — the substrate
record of who owns an active work arc and when the claim lapses.
deadman/fallback (later slice) consumes expired leases to know which
work is abandoned and eligible for quorum takeover. Makes no admission
decision itself.
`cli/internal/liveness/work_lease.go` (+ test):
- `WorkLease{BeadID, Branch, OwnerAgentID, ModelFamily, LeaseReason,
IssuedAt, ExpiresAt, RenewedAt, EvidenceRef}` + `Status(now)`.
- `LeaseTracker` (injected `Clock`): `Create / Renew / Expire / Get /
List / Expired`.
## Invariants (the kernel's principles, mechanical)
- **No-self-grade on liveness:** `Renew` requires a **non-empty
`evidence_ref`** → `ErrEvidenceRequired`. Alive = externally-visible
evidence, not self-report.
- **Quorum takeover:** `Create` rejects an *active* duplicate
(`ErrLeaseActive`) but **re-leases an expired bead** (new owner takes
over abandoned work).
- **Deterministic:** every time decision routes through the injected
`Clock` — reproducible, testable; tests use a fixed clock.
## Scope (per SageHarbor's carve, Agent Mail #115)
New `work_lease{,_test}.go` ONLY. **Not** admission classification,
pulse/quorum schema, deadman escalation, or the #737 author/judge gate.
Untouched: `ports/claim_evidence_binder.go`, `session_bootstrap.go`,
`search/*`, `registry.json`, generated CLI docs.
## Validation
- 6 tests pass (create/takeover, evidence-gated renewal, status/expired,
force-expire) with exact-value assertions + fake clock.
- Local gate: `go build` / `go vet` / `go test -race (changed scope)` /
command-test pairing / HOME-isolation all **green**. The 4 remaining
local reds (gc-stale-worktrees fixture, canonical-root-dirty [shared
checkout], goals-validate, corpus-freshness) are the **pre-existing
non-diff** set (same as #730/#736/#737).
Requesting **≥2-of-3 cross-model review** — this is liveness-kernel
code, review hard.
Closes-scenario: ag-c3c7.2#work-lease
Bounded-context: BC5-Runtime
Evidence: cli/internal/liveness/work_lease.go
|
||
|
|
cd5b8acc1e |
feat(liveness): role-capability matrix — deny-and-escalate RBAC (ag-c3c7.1 #role-matrix) (#733)
Role-capability matrix for the liveness-kernel (ag-c3c7.1, assigned by SageHarbor as sequencing lead). `cli/internal/liveness/roles.go` defines each role's allowed verbs — orchestrator: route/vote/shepherd/synthesize · worker: edit · verifier: judge · scribe: record · heartbeat: nudge. Every out-of-capability action resolves to `needs-admission` — **deny-and-escalate by default, never allow**. Key separation semantics (all tested): - **orchestrator CANNOT edit** — the prompt-injection defense; an orchestrator can't perform a worker's edit - **verifier CANNOT edit what it judges** — no-self-grade - worker / scribe CANNOT vote (execute/record, don't decide) - heartbeat does nothing but nudge - unknown role/verb → needs-admission New isolated package. No-touch list respected: validate.yml, registry.json, pre-push-gate.sh, skill-eval.sh, .agents/design/*, cli/internal/search/*, cli/cmd/ao/* all untouched. 24 tests pass; full `go build ./...` + vet clean. Closes-scenario: ag-c3c7.1#role-matrix Bounded-context: BC2-Validation Evidence: cli/internal/liveness/roles.go |
||
|
|
01dc1568cf |
feat(memory): compute always reach from canon maturity
Implements ag-oqha W2.2. Authored reach=always is sanitized to pull; effective always is computed only from canon-collected maturity=established learnings. Cross-model ACKs recorded in Agent Mail messages #70 and #71. |
||
|
|
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> |
||
|
|
6c8cb223ea |
feat(corpus): add reach blast-radius tier {bead|pull|always} (ag-bsf6 #reach-field) (#721)
W2.1 of epic ag-lhu0 (memory-system re-architecture). Adds the **reach**
blast-radius axis, orthogonal to maturity, per the locked duel
architecture.
- `reach {bead|pull|always}` on FrontMatter + Learning; `reach:`
frontmatter round-trips.
- `SanitizeReach` normalizes + defaults absent/invalid → `pull`, and
**never** promotes to `always` (the computed-not-authored invariant —
`always` is derived from maturity==established ∩ canon in ag-oqha).
- `learning.v1.schema.json`: reach enum + default pull; domain vocab
`skills/domain/references/reach.md`.
- Tests: SanitizeReach + frontmatter round-trip/default (88 search-pkg
tests green).
Closes-scenario: ag-bsf6#reach-field
Bounded-context: BC1-Corpus
Evidence: cli/internal/search/learnings.go
|
||
|
|
092b99dad9 |
feat(skills): add skill-eval.sh ms-backed quality gate (ag-yzoz #skill-eval) (#726)
## What
Adds `scripts/skill-eval.sh` — a thin gate that runs one skill's
`SKILL.md` through Jeff Emanuel's `ms` (meta_skill) `lint` + `validate`.
The wrapper decides the gate purely on whether a **blocking** `rule_id`
appears (ms's own severity/exit is not trusted):
- Blocking: `no-secrets`, `no-injection`, `safe-paths`,
`required-metadata`, `no-cycle`, `valid-version` → non-zero exit.
- Everything else → annotated only (`::warning::`), never fails.
- `ms` not on PATH (or `MS_BIN` missing) → **loud `::error::` hard-fail
(exit 3)**, never skip-and-pass — a silent skip would recreate the
no-evaluation gap this gate closes.
Planted `skills/_fixtures/{bad,good}-skill/SKILL.md` fixtures +
`tests/scripts/skill-eval.bats` (10 tests) exercise the
bad/good/ms-absent contracts.
## Fixture scoping
`skills/_fixtures/` is non-skill scaffolding (planted fixtures). The
skill-enumerating gates/generators are taught to skip `skills/_*` so the
fixtures never inflate the skill count (stays 82) or fail registry /
schema / wiring / runtime / count gates. Touched enumerators:
`generate-registry`, `validate-skill-schema`, `sync-skill-counts`,
`validate-skill-count`, `generate-skill-catalog`,
`generate-context-map`, `validate-manifests`, `check-wiring-closure`,
`validate-headless-runtime-skills`, `lib/sku_catalog.py`,
`check-alias-collisions`, `run-all`, `test-runtime-opencode-smoke`,
`release-smoke-test`, `smoke-test`, `validate-skill`.
Does **not** touch `validate.yml` — wiring skill-eval.sh into CI is a
separate bead.
Epic: ag-czzf
## Verification
- `bats tests/scripts/skill-eval.bats` → 10/10 pass (ms 0.1.2 on PATH)
- `shellcheck scripts/skill-eval.sh` → clean
- `check-registry-drift`, `validate-skill-schema`, `sync-skill-counts`,
`run-all`, opencode-smoke → all PASS with fixtures present, skill count
= 82 (fixtures excluded)
Closes-scenario: ag-yzoz#skill-eval
Bounded-context: BC2-Validation
Evidence: scripts/skill-eval.sh
---------
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> |
||
|
|
dd6cff74d8 |
fix(corpus): scrub secrets on corpus write (ag-6vlm #scrub-on-write) (#719)
Wire `llm.RedactBytes` into `corpus_fs.Writer.Capture` so every byte that lands in the `.agents/` corpus (frontmatter + body) is scrubbed before `os.WriteFile`. Activates the previously-dead redactor on the load-bearing local corpus-write path — the W1 git-safety scrub-on-write chokepoint (primary defense; CI scan is the backstop). **Scenario (Gherkin):** Given a learning body with an sk-ant- token / AWS key / PEM block, When `corpus_fs.Writer.Capture` writes it, Then the persisted file has the secret scrubbed to `[REDACTED]` and non-sensitive content preserved. Proven by `TestWriter_CaptureScrubsSecrets` (L2). Epic ag-lhu0 (memory-system re-architecture), Wave 1. Closes-scenario: ag-6vlm#scrub-on-write Bounded-context: BC1-Corpus Evidence: cli/internal/adapters/corpus_fs/corpus_fs.go |
||
|
|
288943ad49 |
refactor(cli): decouple mine.go + handoff.go from rpi symbols (ag-362v #decouple) (#718)
**Prerequisite for removing `ao rpi` / `ao evolve`** (epic ag-llni / soc-1gbpz). Operator directive: out-of-session orchestration moves to the substrate (NTM + background agents + `/discovery`); the in-CLI loop engines are removed. A full-repo map confirmed the **only 2 non-rpi/evolve production callers** of rpi symbols: - `mine.go` → `RPIC2Event` + `loadRPIC2Events` - `handoff.go` → `shellQuote` This PR relocates both into files that survive the `rpi*.go` deletion glob, **zero behavior change**: - **`shell_quote.go`** — POSIX single-quote helper moved out of `rpi_parallel.go` (body inlined, drops the `internal/rpi.ShellQuote` hop). Both `handoff.go` and `rpi_parallel.go` keep using it. - **`c2_event_reader.go`** — `RPIC2Event` type + `loadRPIC2Events` reader moved out of `rpi_c2_events.go` (events.jsonl path inlined to mirror `internal/rpi.RPIRunRegistryDir`). `mine.go` unchanged; the rpi-internal **writer** `appendRPIC2Event` stays and is deleted with the engine. After this, **nothing outside `rpi*.go`/`evolve*.go` references any rpi-internal symbol** — the engine deletion (next PR) is unblocked. ## Verification - `go build ./...` + `go vet` clean - 3 new reader tests + 21 existing handoff/mine/c2/shellQuote tests pass - `rg` confirms `mine.go`/`handoff.go` carry no rpi-internal symbol refs Closes-scenario: ag-362v#decouple Bounded-context: BC5-Runtime Evidence: cli/cmd/ao/c2_event_reader.go --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
6bd788d8af |
chore(cli): gofmt sweep — 14 unformatted files (ag-ozac #gofmt-sweep) (#717)
Mechanical `gofmt -w` across `cli/` — fixes the 14 unformatted files surfaced by the **ag-tcf0** Go-cohesion audit. No logic change (diff is whitespace/grouping only; `git diff -w` is ~empty). ## Verification - `gofmt -l cli/` → empty - `go build ./...` → passes - Rebased onto current `origin/main` Closes-scenario: ag-ozac#gofmt-sweep Bounded-context: BC5-Runtime Evidence: cli/internal/eval/types.go |
||
|
|
8be8d678f2 |
fix(corpus): relevance-rank ao inject — strip stopwords from query tokens (ag-32gx #stopword-relevance) (#704)
## What Fixes the retrieval-relevance gap the corpus-delta **W1c first signal** located: `ao inject --context "<verbose query>"` returned generic recency-ranked learnings, not the task-relevant one. **Root cause:** `QueryTokens` did no stopword filtering — a long query became ~80 tokens (incl. the/if/any/that), so `MatchRatio` (matched ÷ total) collapsed for every learning and ranking fell back to freshness. **Fix** (mirrors the proven `skills/find.go` tokenizer): `QueryTokens` now splits on any non-alphanumeric rune (`continue-on-error:true` → continue/error/true), drops a ~80-word English stopword set + sub-2-char tokens, and dedups. Domain words (gate/job/exit/ci/run/check) are deliberately kept. ## Validation - **Empirical, against the real corpus:** a focused query's hits on the target learning rose (2 → 4); the learning is NOT quality-gate-filtered (it surfaces with a salient query). - **Tests:** QueryTokens strips stopwords/punctuation + dedups; a verbose query ranks a salient-matching learning above a generic one; all-stopword query degrades safely (→ no relevance signal → freshness, preserving prior behavior). 86 search + 580 cmd/ao pass; build + vet clean. ## Honest residual (separate, NOT an inject defect) A raw whole-prompt query still dilutes via `MatchRatio` length-normalization. inject's job is to rank *given* a query; it now does. The **caller** should pass a focused query — noted on **ag-epgk**: the W1c runner should derive a focused retrieval query (task title/salient line), not pass `prompt.md` verbatim. That, plus this fix, unblocks a clean W1c re-run. Closes-scenario: ag-32gx#stopword-relevance Bounded-context: BC1-Corpus Evidence: cli/internal/search/learnings.go |
||
|
|
81aec49b1c |
chore(tests): test-isolation ratchet + migrate testutil chdir helpers to t.Chdir (ag-k38x #lint-ratchet) (#699)
## What
Lands the durable mechanism for ag-k38x (codebase-audit P2-1/P2-2): raw
`os.Chdir`/`os.Setenv` in tests mutate process-global cwd/env — a latent
flake landmine once any test opts into `t.Parallel` (cf. **ag-jfzs**,
the memory-sync flake of exactly this class).
The repo has ~163 `os.Chdir` + 22 `os.Setenv` inline sites across 34
files in **non-uniform patterns** (`defer` / `t.Cleanup` / `defer
func(){}()` with reversed order) — a blind sweep would break the suite.
So this ships the **durable gate + the canonical lever**, not a risky
80-site mass-edit:
- **`scripts/check-test-isolation.sh`** — a baseline ratchet (163/22)
wired into the **process-hygiene** job: raw `os.Chdir`/`os.Setenv` in
`*_test.go` may not **grow**; new code must use `t.Chdir`/`t.Setenv` or
the testutil helpers. This pre-empts the flake class from spreading.
- **`testutil_test.go`** — `chdirTemp`/`chdirTo` migrated from
`os.Chdir`+`t.Cleanup` to `t.Chdir` (the shared helpers most tests
delegate to; canonical example).
## Follow-up
The bulk inline-site migration drives the baseline toward zero
incrementally — **ag-k38x stays open** for it (scenario
`#bulk-migration`). Decomposing an ~80-site, non-uniform migration into
*gate-the-growth now + reduce-incrementally* is the responsible path; a
one-shot sed would be the reckless one.
## Verification
Ratchet PASSes at baseline AND catches a synthetic increase; shellcheck
+ `validate-ci-policy-parity` green; `go vet` clean; chdir-helper-caller
tests pass under `-race`.
Closes-scenario: ag-k38x#lint-ratchet
Bounded-context: BC2-Validation
Evidence: scripts/check-test-isolation.sh
|
||
|
|
28b18a8523 |
fix(corpus): handle silent G104 parse/write swallows (ag-chvc #silent-error-handling) (#697)
## What Fixes the behavioral `#nosec G104` silent-error swallows surfaced by the codebase-audit (ag-chvc). - **Sscanf** (`lifecycle/temper.go` ×3, `cmd/ao/temper.go` ×4, `storage/searchindex.go`): a *malformed* Utility/Confidence/SchemaVersion silently parsed to **zero**, corrupting decay-rank inputs. Now parse into a local and assign only on a clean parse → malformed value keeps the prior default. The error is handled, so the `#nosec G104` is gone. - **WriteFile/MkdirAll** (`cmd/ao/quickstart.go`, `cmd/ao/demo.go` ×6): silently dropped write failures while still printing ✓. Now warn to stderr on failure, print ✓ only after the write lands. - **Left untouched** (legitimate best-effort): `rpi_phased_processing` `os.Remove` cleanup, demo interactive `Scanln`. ## Verification `go build` + `go vet` clean; 276 lifecycle/storage tests pass under `-race`; 3 new regression tests (malformed → keeps default; valid → parses). Zero G104 left in the 5 touched files. Closes-scenario: ag-chvc#silent-error-handling Bounded-context: BC1-Corpus Evidence: cli/internal/lifecycle/temper.go |
||
|
|
6072dceac5 |
docs(substrate): reconcile doctrine — skill-dispatch + drop Gas City reference (ag-88y5 #docs-skills-dispatch-reframe) (#696)
## What Two bounded doctrine-reconciliation slices (one coherent arc): **ag-88y5** — the out-of-session dispatch unit is the `/rpi`·`/evolve` **skill**, not the `ao rpi`/`ao evolve` CLI. Per the 3.0 skills-are-the-runtime thesis (using-ntm #693 already frames it this way), re-narrate the **live** doctrine surfaces so the substrate spawns an agent that *runs the /rpi skill* over a bead: - docs/3.0.md, docs/architecture/canonical-loop-model.md, docs/runbooks/nightly-evolution.md - skills/using-agentops, skills/agent-native, skills/domain/references/factory.md Historical surfaces (MIGRATION-3.0, ADR-0009, release notes) + CLI-reference left as-is; the actual `ao rpi`/`ao evolve` CLI removal is the **ag-iowf** epic (live automation callers — overnight-evolve, release-smoke — must migrate first). **ag-ogp5** — drop the 4 docs still asserting Gas City as THE reference substrate → NTM+MCP+managed-agents: - docs/ARCHITECTURE.md, docs/SCHEMAS.md, docs/contracts/agents-write-surfaces.md, docs/patterns/completion-notifications.md (Pattern C) The ~37 historical/illustrative GC refs are intentionally retained (per ag-ogp5 scope). ## Verification regen-all --check, embedded-sync, heal --strict, registry-drift, codex-rpi-contract, codex-artifacts --scope head — all green. Closes-scenario: ag-88y5#docs-skills-dispatch-reframe Bounded-context: BC4-Factory Evidence: docs/3.0.md |