mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
ao-pre-reduction@5b334a13f
301 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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. |
||
|
|
65a986c691 |
fix(skill-eval): constrain backtick safe-paths exemption to known file extensions (ag-eatf follow-up) (#801)
## Why (quorum remediation) #767 (via an autonomous resolver, **merged without quorum**) broadened the ag-eatf safe-paths false-positive filter to strip **any** backtick-wrapped `../path`. Side effect: a backtick-wrapped `../../../../etc/passwd` in a SKILL.md would be treated as a safe doc-reference and **bypass the safe-paths gate**. Cross-model quorum on the as-merged change: **Codex = REVISE** ("unacceptable bypass… constrain to repo-internal + approved extensions, else revert"). (agy/Gemini was unreachable this round — timeouts.) Tightening a gate back toward its documented intent is the safe direction, so this lands the constrained version. ## Fix Backtick strip now requires a **known repo-file extension**: `md|markdown|mdx|txt|rst|json|yaml|toml|sh|go|py|ts|rs`. Legit inline-code refs (``../../schemas/x.json``, ``../scripts/y.sh``) stay exempt; an extension-less traversal (``../../../../etc/passwd``) no longer matches → still **BLOCKS**. ## Evidence `bats tests/scripts/skill-eval.bats` → 14/14 (2 new: backtick-`/etc/passwd` blocks; backtick-`.json` ref passes; the bare-traversal-blocks test still green). Closes-scenario: ag-eatf#constrain-backtick-exemption Bounded-context: BC2-Validation Evidence: scripts/skill-eval.sh |
||
|
|
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 |
||
|
|
cfcca74773 |
fix(scripts): port skill-catalog generator off gawk-only awk -v (ag-mm6q #bsd-awk-portability) (#784)
## What
`scripts/generate-skill-catalog.sh` passed the YAML frontmatter into awk
via `awk -v fm="$fm"`. A literal newline inside a `-v var=value`
assignment is accepted **only by GNU awk**; BSD/POSIX awk (macOS without
gawk) errors with `awk: newline in string ...` and emits no catalog — so
the catalog (and its drift gate `check-skill-catalog-drift.sh`) could
only run inside Linux CI.
## Fix
Feed the frontmatter on **stdin** and accumulate input lines into
`lines[]` (processed in `END` exactly as before) instead of `-v` +
`split()`. Pure input-mechanism change — the parse logic is untouched.
## Evidence (macOS BSD awk, version 20200816)
- **Before:** `bash scripts/generate-skill-catalog.sh --stdout` → `awk:
newline in string name: agent-native` (no output).
- **After:** valid JSON for all 81 skills; lists, `context_rel`, and
quoted descriptions parse correctly (e.g. `deps` → `context_rel: [{kind:
supplier-to, with: vibe}]`, matching the source SKILL.md).
- Added an explicit BSD/POSIX-awk regression test (`multi-line
frontmatter parses ... without 'newline in string'`). Full bats suite
**15/15 green** on macOS.
- `shellcheck` clean.
## Scope note
The committed `skills/catalog.json` is **independently stale** (75 vs 81
skills — drift predates this change, since the generator never ran
off-Linux). Regenerating it is deliberately left to the Linux-CI drift
path (the `check skill catalog drift` job is **I0 advisory /
non-blocking**) to avoid committing a glob-order-sensitive artifact
generated off-CI.
Closes-scenario: ag-mm6q#bsd-awk-portability
Bounded-context: BC2-Validation
Evidence: tests/scripts/generate-skill-catalog.bats
|
||
|
|
cb8161c806 |
feat(ratchet): enforce R3 'no learning without a constraint' as a script gate (ag-maaa #r3-constraint-gate) (#768)
## What Makes the Brownian-Ratchet rule **R3 — "no learning without a constraint"** self-enforcing. Previously it was prose only (`docs/architecture/operating-loop.md` promotion table: *"Must never regress → add a validation gate"*): a learning could be promoted to a durable maturity tier without ever compiling into a gate/test/rule. The mechanism existed (`cli/internal/ratchet/`) but R3 was a manual operator decision with no check. ## How `scripts/check-ratchet-r3-constraint.sh` scans the learnings corpus and flags any **durable-tier** learning (`candidate`/`established`/`canonical`/`stable`/`promoted`) that cites **no constraint** — a `scripts/`/`.github/workflows/` gate, a `_test.go`/`tests/` reference, a `skills/**/SKILL.md` step, or a `constraint:`/`enforced_by:` frontmatter field. Provisional learnings are exempt (still forming). - **Warn-first → blocking**, mirroring the ratchet's own warn-then-fail ladder: warn-only by default (exit 0); `--strict` or `RATCHET_R3_BLOCKING=true` makes the same gaps blocking (exit 1). ## Why a script, not a CI path-filter gate `.agents/learnings/**` is **gitignored** (0 tracked). A CI path-filter gate on it would be dead-by-design — the exact reason the `learning-coherence` CI job was retired (2026-05-19). So R3 runs at ratchet/flywheel time against the **live local corpus**; the script's own correctness is gated in CI by the committed bats test (`tests/scripts/*.bats` runs in `validate.yml`). ## Verification - `tests/scripts/check-ratchet-r3-constraint.bats` — 11 hermetic tests on a synthetic fixture (warn-first, --strict, env-var parity, provisional exemption, empty-field rejection, gate/test/SKILL citation forms, count accuracy). All pass. - `shellcheck` clean. - Dry-run against the real local corpus: 639 scanned, 7 durable-tier, 5 flagged — warn-only, exit 0 (honest; does not break on existing corpus). Closes-scenario: ag-maaa#r3-constraint-gate Bounded-context: BC1-Corpus Evidence: tests/scripts/check-ratchet-r3-constraint.bats |
||
|
|
fec947be0d |
fix(skill-eval): filter safe-paths false-positives on markdown doc-link ../ (ag-eatf #safe-paths-doclink-filter) (#796)
## What `scripts/skill-eval.sh` treated ms's `safe-paths` rule as blocking on **every** `../`. That rule is a blunt regex, and `../` relative markdown doc-links are the repo-wide SKILL.md convention (47+ skills, e.g. `[x](../other/SKILL.md)`, `../../docs/...md`). SKILL.md is documentation, not executed code, so those are false positives — they redded `skill-eval` → `summary` on **every skills-touching PR** (blocked #776; gated #759/#764/#767 in this session's drain). ## Fix Added a file-level filter: `safe-paths` stays **blocking only when a `../` survives stripping (1) markdown inline-link targets `](...)` and (2) relative doc-path tokens (`*.md/.markdown/.mdx/.txt/.rst`)** — i.e. a real, non-doc `../`. Otherwise the findings downgrade to advisory annotations (announced, not silenced). Net effect: **purely removes false positives; real protection is preserved.** A genuine traversal (e.g. `../../../../etc/passwd` in a description) still blocks — verified. No regression to the other blocking rules. ## Evidence - `bats tests/scripts/skill-eval.bats` → 12/12 pass (10 prior + 2 new ag-eatf cases: doc-links downgrade→PASS; real non-doc `../`→BLOCK). - Manual: `agent-native` and `domain` skills (previously red on safe-paths) now PASS; a mixed real-threat fixture BLOCKs. Closes-scenario: ag-eatf#safe-paths-doclink-filter Bounded-context: BC2-Validation Evidence: scripts/skill-eval.sh |
||
|
|
b008e22f9b |
feat(domain): name silent-contract-violation + verdict.v1 finding taxonomy (ag-twl8 #verdict-category-taxonomy) (#759)
## What First slice of the RubricRefine integration epic (**ag-5elx**). Moves the paper's sharpest idea into the verification membrane — and it's the dependency that **blocks the flagship** pre-execution gate (ag-rjvf). - **`skills/domain/references/silent-contract-violation.md`** — new draft anti-pattern entry. Names the failure class the whole membrane exists to catch: tool-use code that **runs clean, raises no exception, and is still wrong** (wrong routing, mismatched output shape, broken argument provenance). Full Signature / Cost / Cause / Refusal + `bd` incident citation, indexed in `INDEX.md` under a new "Verification membrane concepts" section. - **`schemas/verdict.v1.schema.json`** — adds RubricRefine's 4-category contract-check taxonomy as an **optional** `category` enum on findings: `tool-choice | output-contract | call-signature | data-provenance`. Backward compatible — existing uncategorized findings stay valid (`additionalProperties:false` preserved), an unknown category is rejected so the taxonomy can't drift. - **`tests/scripts/check-verdict-category-taxonomy.bats`** — behavioral schema tests via python `jsonschema` (valid accepted · all four accepted · omit valid · unknown rejected · enum exact). Written test-first: confirmed failing against the unmodified schema, then green. - **`registry.json`** — regenerated (domain `reference_count` 18→19; scope-only diff). ## Why RubricRefine (Anduril, arxiv 2605.09730v3) formalizes the failure AgentOps' no-self-grade membrane targets, but AgentOps had no name for it and no shared bucket vocabulary for findings. This slice supplies both, so every downstream gate (and the pre-execution gate ag-rjvf) can categorize and ablate contract violations. ## Verification - `bats tests/scripts/check-verdict-category-taxonomy.bats` → 5/5 (CI runs it via the bats job; surfaces changed: schemas/skills/docs/bats). - `scripts/generate-registry.sh --check` → up to date. - `scripts/check-bead-scenario-coverage.sh --run` → PASS (1/1 scenario covered & passing). - Full `pre-push-gate.sh --fast`: green except `corpus-freshness` (env-local snapshot 8d old; CI sets `AGENTOPS_CORPUS_FRESHNESS_SKIP=1` — not a PR blocker). Closes-scenario: ag-twl8#verdict-category-taxonomy Bounded-context: BC1-Corpus Evidence: schemas/verdict.v1.schema.json |
||
|
|
463a6b31b1 |
chore(ci): guard author≠judge convergence on liveness.Disjoint (DRIFT #149 gate) (#746)
## What The empty-ID self-grade bypass **recurred** — #737 (PG3/PG4) → #741 (citation reward) — because the author≠judge invariant had been reimplemented in divergent places. #744 + #741 converged the 3 sites onto `liveness.Disjoint`. This is the **2nd-occurrence gate** that keeps them converged. `scripts/check-author-judge-convergence.sh` flags any Go site doing its own `author == judge` / `EqualFold(author, judge)` / `judge_id == author_id` equality **outside** `liveness.Disjoint` (`cli/internal/liveness/guards.go`). Comments and `*_test.go` are excluded. ## Why This completes the no-self-grade invariant to its full form — **converged + locked + gated**: - **Converged** — #744 (`evidencedturn`) + #741 (`citation`) collapse the 3 impls onto one `Disjoint`. - **Locked** — #744's `TestAuthorNeqValidator_AgreesWithDisjoint` fails CI if impl-#2 re-diverges. - **Gated (this PR)** — catches a *new* 4th divergent impl **anywhere**, in the gate every cluster agent runs pre-push. Catch → encode → never-again. A failure that recurred twice mandates a durable gate, not a third per-site patch. ## Validation - Passes clean on current `main` (post-convergence: **zero** divergent sites). - 5 bats specs: pass-on-converged, flag-equality, flag-`EqualFold`, skip-comment, skip-`_test.go`. - Wired into `pre-push-gate.sh` always-on (fast grep, ~ms) — verified `ok author!=judge convergence` in a full gate run. shellcheck clean (the 2 SC2317 infos are pre-existing in pre-push-gate.sh, not this change). - Scope: 3 files, +96/−0 (guard script + bats + gate wiring). No production code. > Follow-up: mirror as a `validate.yml` CI step once the validate.yml merge-churn settles (low-collision now via the pre-push gate). DRIFT bead pending Dolt-write recovery (#149); Agent Mail #151/#166 carry provenance. Bounded-context: BC5-Runtime Evidence: author!=judge convergence |
||
|
|
419bda7532 |
feat(memory): classify bd remember notes (ag-u1zi) (#745)
## Summary Implements ag-u1zi W4.1: a deterministic classifier for migrating `bd remember` notes into the memory architecture without promoting bead-local operational chatter into pull-learning memory. Changes: - adds `scripts/classify-bd-remember.py` with JSON/markdown output, `--input`, `--expected-count`, and `--generated-at` options - adds fixture and Bats coverage for classification coverage, lineage preservation, markdown manifest, and expected-count mismatch - adds `docs/contracts/bd-remember-migration-manifest.md` plus documentation-index entry Classification policy: - `bead`: bead-linked, session-local, one-off, or tracker-operational notes - `pull-learning`: reusable project learning candidates, emitted as `reach=pull`, `maturity=provisional`, `source=migrated-bd-remember` - `discard`: empty/stale/deprecated/obsolete notes Dolt/bd caveat: `bd update ag-u1zi --claim` and `bd ready` are failing via the known Dolt/MySQL write/read path (`context canceled` / invalid connection), so claim/provenance is recorded in Agent Mail rather than bd state. ## Validation Focused: - `bats tests/scripts/bd-remember-classifier.bats` PASS - `python3 -m py_compile scripts/classify-bd-remember.py` PASS - `bash scripts/check-contracts-structural-floor.sh` PASS after indexing the new contract doc - `git diff --check` PASS Required push path: - `bash scripts/regen-all.sh` ran; failed only known CMDAO surface parity red, timestamp-only `registry.json` drift reverted - `PRE_PUSH_FAIL_FAST=false bash scripts/pre-push-gate.sh` completed with the known red set: 4 failures (`test-fixture parity`, canonical-root worktree disposition, corpus freshness, contract canary pre-push-governance); no observed diff-caused failure ## Review Request Requesting cross-model ACK before merge. Do not merge unless PR checks reach CLEAN and quorum is satisfied. Closes-scenario: ag-u1zi Bounded-context: BC1-Corpus Validation-evidence: classifier script + Bats coverage; see Validation section above. |
||
|
|
015bb52286 |
ci(ci): wire scan_descriptions --probe as I0-informational receipt lane (ag-iyu4 #probe-i0) (#738)
Wires `scripts/skill-probe-i0.sh` — the deterministic lexical trigger ranker (`scan_descriptions.py --probe`, ag-7led) — as an **I0-INFORMATIONAL** step inside the `skill-eval` job. ## What it does - Runs the probe over every `trigger_probes:` phrase in the corpus, writes a per-skill JSON receipt to `.agents/ao/skill-eval/<id>.json`, and uploads it as the `skill-retrieval-probe-receipts` workflow artifact. - Asserts byte-stable **determinism** across two runs; a non-deterministic probe is surfaced as a `::warning::` only. - **Not a PR check:** `continue-on-error: true` lives INSIDE the existing `skill-eval` job, so no new GitHub check is created and the step can never block (or even advisory-fail) a merge. I0 = informational. - No-ops cleanly (exit 0, no receipts) until a skill opts in with `trigger_probes:`. ## Acceptance - Probe emits the JSON-receipt artifact AND no new PR check appears (verify absent from `gh pr checks`). - A deliberately non-deterministic probe input is caught by the determinism assertion before it could become a gate — `tests/scripts/skill-probe-i0.bats` (3 specs, all green). ## 2-week stability baseline Documented in three places (validate.yml comment, `docs/contracts/ci-jobs.yaml` skill-eval entry, `skills/skill-builder/SKILL.md` trigger_probes note): keep `--probe` I0-only until the receipt lane runs green + byte-stable across the corpus for a 2-week baseline of merges before any blocking-gate promotion. Closes-scenario: ag-iyu4#probe-i0 Bounded-context: BC1-Corpus Evidence: scripts/skill-probe-i0.sh |
||
|
|
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> |
||
|
|
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>
|
||
|
|
7e8197ba93 |
ci(skills): consolidate live skill gates into one required skill-gates job (ag-87sv #skill-gates-job) (#723)
Consolidates the live skill-authoring CI gates into one named, required `skill-gates` job (pure regroup of already-live gates — no behavior change). Replaces the phantom `scenario-hash-stability` reference in `CLAUDE.md` with the real `check-scenario-test-linkage` gate now grouped under `skill-gates`. Adds the `skill-gates` row to the CI-policy-parity manifest (`docs/contracts/ci-jobs.yaml` + `AGENTS-CI.md`) and the `gate:skill-gates` SKU to `registry.json` (11→12 gates). New `tests/scripts/skill-gates.bats` (12 tests) locks the job's structure, required-check wiring, and drift-sweep behavior. Part of epic ag-czzf. Closes-scenario: ag-87sv#skill-gates-job Bounded-context: BC2-Validation Evidence: .github/workflows/validate.yml --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
ab138a5418 |
feat(skills): add scan_descriptions --probe deterministic trigger ranker (ag-7led #trigger-probe) (#722)
## Summary Adds a `--probe "<phrase>"` mode to `skills/skill-builder/scripts/scan_descriptions.py` that ranks every skill against a lexical trigger phrase **deterministically** (no live model, byte-stable output). Introduces an optional `trigger_probes:` skill-frontmatter field so a skill can self-declare phrases it must rank #1 for; the probe asserts the declaring skill wins its own phrases against the corpus. Epic: ag-czzf. **INFORMATIONAL-only tooling — not a blocking gate.** The probe is a self-check authors can run; no CI gate is wired to it. ## Changes - `skills/skill-builder/scripts/scan_descriptions.py` — `--probe` ranker + `trigger_probes` parser (flow + block YAML forms). - `schemas/skill-frontmatter.v2.schema.json` — optional `trigger_probes` array field. - `tests/scripts/scan-descriptions-probe.bats` — 4 scenarios (rank-#1, determinism, demotion-on-mutation, usage-error exit codes). ## Validation - New bats suite: 4/4 pass. - `scripts/pre-push-gate.sh` reds are pre-existing main-red (context-packet-ab canary + its downstream pre-push-gate-governance nested bats), not caused by this diff; CI is changed-files-scoped. Closes-scenario: ag-7led#trigger-probe Bounded-context: BC2-Validation Evidence: skills/skill-builder/scripts/scan_descriptions.py --------- 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> |
||
|
|
e74d8899fd |
feat(ci): gate live-hooks reintroduction in docs/ (ag-rryf #doc-hooks-drift-gate) (#713)
## What
Adds `scripts/check-doc-hooks-drift.sh` — a CI regression guard that
fails when a **live-facing** doc reintroduces a live hooks runtime after
the 3.0 hookless teardown:
- `hooks/hooks.json` (retired manifest), a `hooks/<name>.sh` runtime
path,
- `ao hooks` (not a registered command — verified absent from
`cli/cmd/ao/`),
- a bare `session-{start,end,autostart}*.sh` hook-file ref
…unless the **same line** hedges it as hookless / opt-in / historical /
removed / a git-hook. Companion to `sync-skill-counts.sh` (skill-count
drift) and `check-hookless-cold-start.sh` (fixed-list cold-start gate).
## Scope (and why the exclusions)
`docs/` **minus** surfaces that legitimately/archivally name hooks:
- **archival history** — `CHANGELOG.md`, `releases/`, `learnings/`,
`plans/`, `adr/`, `convergence/`, `sovereignty-proof/` (document the
past / the removal itself)
- **opt-in subsystem** — `contracts/` (hooks-authoring opt-in specs),
`runbooks/` (diagnostic enumeration), `code-map/` (point-in-time audits)
The gate keeps the onboarding / operator / architecture narrative
hookless.
## Also: finishes the ag-t1ca residue the gate flags
The ag-t1ca de-hooking missed 8 live-facing lines (gate caught them);
each is reframed:
- stale `ao hooks` command/smoke refs → removed / `ao doctor`
(`cli-skills-map`, `UPGRADING`, `release-e2e-checklist`,
`contracts/release-readiness`)
- present-tense hooks-as-rules → CI gates (`strategic-direction`)
- hook-runtime mentions → `ao curate constrain` / opt-in framing
(`curation-pipeline`, `leverage-points`, `SCHEMAS` legacy-manifest
label, `workflows/session-lifecycle`)
## Verification
- `scripts/check-doc-hooks-drift.sh` → PASS on this branch (FAILed on
all 8 before the reframes)
- `tests/scripts/check-doc-hooks-drift.bats` → 8/8 (positive /
negative×3 / hedge×2 / exclusion / no-docs error)
- `shellcheck` clean · `markdownlint` 0 errors (9 docs) ·
`validate-cli-skills-map.sh` PASS · `generate-ci-jobs-table.sh --check`
PASS · existing `check-hookless-cold-start.sh` still green
- Wired into `validate.yml` lint/contracts (gated on docs/ci/shell
changes) + auto-run via the bats suite
Closes-scenario: ag-rryf#doc-hooks-drift-gate
Bounded-context: BC2-Validation
Evidence: scripts/check-doc-hooks-drift.sh
|
||
|
|
215fcef720 |
feat(eval): held corpus-delta tasks cd-ci-1 + cd-ci-4 (ag-nfux #approved-tasks-ci1-ci4) (#703)
## What Materializes the **two operator-vetted** W1b tasks (the only 2 the adversarial audit passed as clean: `.agents/`-grounded, principle-not-answer, deterministically gradeable). - **cd-ci-1** — author an advisory-tier guard gate. Grounds in `.agents/learnings/2026-05-17-ci-advisory-killed.md`; the agent must build `check-no-advisory-tier.sh`. - **cd-ci-4** — author a removed-job assertion pre-flight gate. Grounds in `.agents/learnings/2026-05-17-delete-grep-asserts.md`; the agent must build `check-removed-job-assertions.sh`. Each task ships `prompt.md` + `setup.sh` + `score.sh` (deterministic, no-LLM grader) + a `golden-solution.sh` reference (**not** given to the agent). The grounding learning lives in `.agents/`, so the W1a sandbox (ag-5apc) surfaces it in `context_on` and strips it in `context_off` → a real delta. ## Grader-discrimination test The task fixtures' own validity: each grader scores the **golden solution PASS** and an **empty workspace FAIL** — a grader that can't tell the difference would make the A/B meaningless. 5/5 bats pass; shellcheck clean on all 6 task scripts. ## N note This is the honest **N=2** starting set. The adversarial audit showed N≥10 isn't reachable from the first drafting slate without a second `.agents/`-only pass; a rigorous small-N beats a large rigged one (per the product panel). **ag-nfux stays open** for N expansion. Closes-scenario: ag-nfux#approved-tasks-ci1-ci4 Bounded-context: BC2-Validation Evidence: evals/workbench/tasks/cd-ci-1/score.sh --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
e6ec5561df |
fix(eval): strip always-loaded roots in context_off (ag-5apc #strip-always-loaded) (#702)
## What Fixes the contamination flaw the W1b adversarial audit surfaced: isolating `AO_AGENTS_DIR` alone is **insufficient** — the agent also auto-loads knowledge from **always-loaded roots** (repo-root `CLAUDE.md`, `.claude/rules/*`, user-global `~/.claude/CLAUDE.md`, auto-memory `MEMORY.md`), read in **both** arms → no delta to measure (6 of 12 W1b candidates were invalidated by this). Each arm now runs in an isolated **sandbox** (HOME + workspace). Those surfaces are treated as **corpus** — populated in `context_on`, absent from `context_off`: - `build_arm_sandbox()` — ON copies project CLAUDE.md + .claude/rules + user CLAUDE.md + auto-memory + the .agents corpus; OFF leaves them out (and strips any base-carried context). - `CORPUS_DELTA_HOME_BASE` seeds auth/settings into both arms **before** context, so a real agent keeps credentials while OFF stays context-clean (off = base − context, on = base + context). - Runner now gets `HOME` + `AO_AGENTS_DIR` + `CORPUS_DELTA_WORKSPACE`; a real agent MUST run with that HOME + cwd=workspace. ## Contamination self-test (the bead's success criterion) A marker seeded into **every** always-loaded root reaches `context_on` but **NOT** `context_off` (delta=1); a separate test proves auth (`HOME_BASE`) survives both arms while base-carried context is stripped from off. ## Verification 7/7 bats pass; shellcheck clean. No `ao` surface; no derived-surface regen. Unblocks honest W1b/W1c. Closes-scenario: ag-5apc#strip-always-loaded Bounded-context: BC2-Validation Evidence: scripts/corpus-delta-harness.sh --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
8ad336122f |
feat(eval): corpus-delta A/B side-harness (ag-u6jh #harness) (#701)
## What
Wave-1a of the corpus-delta proof (ag-8p8o) — the runnable arm.
The deterministic eval runner rejects non-shell runtimes ("out of
deterministic scope", `cli/internal/eval/io.go`) and is CI-locked, so
this is a **side harness** — *not* an extension of that runner, and
**not a new `ao` subcommand** (no CLI surface growth, per the
minimalist/competitive lenses).
- **`scripts/corpus-delta-harness.sh`** — runs one task in two context
arms: `context_off` (isolated **empty** `AO_AGENTS_DIR`) vs `context_on`
(organic `--corpus` root), K seeds each → a
`ContextDeltaScorecard`-shaped JSON (matches the Go struct fields). The
agent runner is **injectable** (`CORPUS_DELTA_RUNNER`, default
`eval-agent-harness.sh --agent claude|codex`) so it's testable **without
LLM calls**.
- **`tests/scripts/corpus-delta-harness.bats`** — 5 cases via a stub
runner: off(empty)→fail, on(corpus)→pass, delta=1.0; no-delta when arms
match; scorecard shape; `--out`; arg validation.
## Honesty guard (baked in)
The script header, test comments, and `evidence_kind:
"harness_plumbing"` all state: **a stub/plumbing run is NOT evidence of
the corpus delta.** The real claim needs a real agent + held
non-engineered tasks + K seeds (ag-nfux W1b, ag-epgk W1c). This
explicitly avoids repeating the wave0 confusion of citing plumbing as
proof.
## Verification
5/5 bats pass; shellcheck clean. No ao is the CLI for AgentOps, a
software-factory control plane for repo-native agent work.
"Problem in. Value out. Intelligence compounds."
Software Factory Lane:
ao factory start --goal "fix auth startup"
/rpi "fix auth startup" or ao rpi phased "fix auth startup"
ao codex stop
The Knowledge Flywheel underneath it:
Sessions compound via .agents/ + Smart Connections.
Others start fresh. You get smarter every session.
For AI agents:
ao capabilities Machine-readable CLI contract (JSON) — run this first.
ao robot-docs Paste-ready agent handbook.
Append --json to any read-side command for structured output.
Use "ao <command> --help" for more information about a command.
Usage:
ao [command]
Getting Started:
demo Show the council-first AgentOps 3.0 value path
init Initialize AgentOps in the current repository
quick-start Set up AgentOps in your project (5 minutes)
seed Plant the seed in any repository
Core Commands:
anti-patterns List learnings marked as anti-patterns
badge Display knowledge flywheel health badge
canon Team-knowledge canon: learnings earned by independent attestation
capabilities Print the machine-readable CLI contract (JSON)
ci BC2 CI status operations (latest run by SHA, recent runs)
citation BC1 CitationPort operations (verify file/function/symbol
citations)
claim BC2 ClaimEvidenceBinderPort operations (bind/list claim-evidence)
constraint Manage compiled constraints
contradict Detect potentially contradictory learnings
curate Curation pipeline operations
dedup Detect near-duplicate learnings
doctor Check AgentOps health
flywheel Knowledge flywheel operations
gate Human review gates
harness BC5 HarnessPort operations (sync state across skill harnesses)
loop BC3 Loop operations (cycle history, etc.)
maturity Check and manage learning maturity levels
metrics Knowledge flywheel metrics
operator BC4 OperatorPort operations (record/list operator intents)
pool Manage quality pools
reconcile Join git, CI, release, beads, and .agents truth into one
report
robot-docs Print the paste-ready agent handbook for the ao CLI
(Markdown)
status Show AgentOps status
version Show version information
vibe-check Analyze codebase health and vibe
Workflow:
autodev Manage the PROGRAM.md operational contract for autonomous
development
codex Codex lifecycle commands (fallback for pre-v0.115.0; native hooks
preferred)
cron Cron-fire loop helpers (used by /evolve --mode=loop)
eval Run deterministic local evaluation suites
evolve Run the autonomous code-improvement loop
feedback-loop Close the MemRL feedback loop for a session
goals Fitness goal measurement and validation
handoff Write a structured handoff artifact for session boundary
isolation
orchestrate Resolve and inspect the orchestration backend ladder
ratchet Brownian Ratchet workflow tracking
rpi RPI lifecycle automation
session Session lifecycle operations
validate Umbrella validation gate (exit-code-as-verdict with --gate)
Configuration:
completion Generate shell completion scripts
config Manage configuration
memory Manage repo-root MEMORY.md for cross-runtime access
notebook Manage the session notebook (MEMORY.md)
Communication:
Knowledge:
beads Complementary tooling for the bd (beads) issue tracker
compile Compile .agents knowledge into an interlinked wiki
corpus Corpus-quality probes for Dream and the knowledge flywheel
defrag Prune and deduplicate .agents/ learning artifacts
findings Manage promoted findings
forge Extract knowledge from sources
harvest Sweep all rigs, extract and deduplicate cross-rig knowledge
inject Output relevant knowledge for explicit or JIT injection
knowledge Operationalize a mature .agents corpus into reusable operator
surfaces
lookup Retrieve specific knowledge artifacts by ID or query
mind Knowledge graph operations
mine Extract knowledge signal from git, .agents/, and code
patterns Inspect and repair .agents/patterns/ artifacts
retrieval-bench Run retrieval quality benchmarks
search Search workspace session history and repo-local knowledge
sessions Manage indexed session pages
trace Track artifact provenance
wiki Unified wiki knowledge surface (experimental)
Additional Commands:
agent Produce AgentOps-native session profiles for background agents
agents Inspect and manage .agents/ contracts and surfaces
extract Process pending learning extractions
help Help about any command
mcp Expose the ao tool surface over MCP for hosted/SDK Claude loops
next-work Operate on the harvested next-work queue
(.agents/rpi/next-work.jsonl)
provenance Write and read the SDLC provenance edge ledger
registry Query the unified registry
scenario Manage holdout scenarios for behavioral validation
scope Manage edit-scope guard (freeze, unfreeze, status)
skills Inspect and validate the skills/ tree
turn Evidenced-Turn operations (the enforced unit-of-work
definition-of-done)
Flags:
--config string Config file (default: ~/.agentops/config.yaml)
--dry-run Show what would happen without executing
-h, --help help for ao
--json Output as JSON (shorthand for -o json)
-o, --output string Output format (json, table, yaml) (default "table")
-v, --verbose Enable verbose output
--version version for ao
Use "ao [command] --help" for more information about a command. command
surface; doesn't touch the locked deterministic eval runner; no
derived-surface regen needed.
Closes-scenario: ag-u6jh#harness
Bounded-context: BC2-Validation
Evidence: scripts/corpus-delta-harness.sh
|
||
|
|
7455382416 |
refactor(gc): strip Gas City coupling; adopt NTM+MCP+managed-agents (ag-124p) (#679)
## What Operator-authorized (Bo, 2026-06-02). Strips the remaining **Gas City** (`gastown`) coupling from AgentOps and reconciles the **split-doctrine state** on `main` that the #672–#676 post-mortem flagged: canonical docs (#676) said NTM+MCP+managed-agents while user-facing docs still described Gas City as the reference substrate. The out-of-session substrate is now uniformly **NTM** (local tmux swarm) + **MCP** (`ao mcp serve`, shipped) + **managed-agents** (`ao agent`). AgentOps adopts a substrate; it owns none. Closes **ag-124p** (and resolves **ag-h93p** — the claude.json gc-hook decouple). ## Deleted (load-bearing surfaces, per the bead's verified scope) - `packs/agentops/` (the reference City) + root `city.toml` - `skills/using-gc` + `skills-codex/using-gc` (+ `tests/scripts/using-gc-skill.bats`) - `gc prime/nudge/mail/hook` wiring in `cli/hooks/claude.json` → now hookless, matching 3.0 doctrine ## Doc sweep (the split-doctrine fix the post-mortem required) - **README.md, docs/MIGRATION-3.0.md, docs/dependencies.md, docs/activation-profiles.md** re-narrated to the substrate trio (the four files the verdict named) - AGENTS.md / CLAUDE.md substrate bullets; `dream` skill (+codex twin) retirement pointer; `shared` / `agent-native` / `using-agentops` cross-refs; skill-dispositions, context-map, sku-catalog, google-sre convergence map ## Regenerated derived surfaces Skill counts (81→80), `registry.json`, `skills/catalog.json`, context-map, skill-domain-map, codex hashes (14) + manifest, SKILL-TIERS — all via the generators, validated drift-free. ## Scope boundaries / follow-ups - **`cli/internal/doctor/fix_bridges.go`** still carries a gc-bridge detector/fixer subsystem. Out of the bead's verified scope; degrades gracefully (stat-checks, returns empty when `gc`/`city.toml` absent); removing it is a test-backed Go change → **follow-up bead**. - **CLAUDE.md "Gas City bridge — REMOVED"** note kept intentionally: it's an anti-re-coupling record, not substrate-framing. - The local-only **bd-closeout** pre-push check (not in CI) is a pre-existing gap on `main` (its AGENTS.md has no `bd dolt push` line) — untouched here. - `thesis-stability` gate FAIL, if present, is the pre-existing README/PRODUCT/GOALS tagline drift, unrelated to this PR (my README/PRODUCT edits are the dependency table + skill-count numbers, not the tagline). ## Verification `go build ./...` + `go vet` green · skill schema (80/80) + integrity (heal --strict clean) + lint suite (0 fail) + codex parity green · sku-catalog & context-map drift gates green · zero broken markdown links to deleted paths. Closes-scenario: ag-124p#gc-coupling-strip Bounded-context: BC5-Runtime Evidence: docs/MIGRATION-3.0.md |
||
|
|
37c86dc282 |
docs(doctrine): re-narrate out-of-session substrate Gas City → NTM+MCP+managed-agents (ag-vg40 #substrate-renarration) (#676)
## What The **doctrine slice** of the ACFS-prune (operator-authorized 2026-06-02). Re-narrates AgentOps's out-of-session story. **Kept (the sovereignty floor — unchanged):** AgentOps = the in-session loop + compounding context; ships no daemon/scheduler/overnight-runner; delegates out-of-session execution to a *swappable substrate*. The in-session/out-of-session boundary and the "substrate owns when/where/who-supervises/coordination" split stay. **Changed (the reference substrate):** Gas City → the adopted ACFS trio — **NTM** (local tmux swarm) + **MCP** (`ao mcp serve`, shipped) + **managed-agents** (`ao agent`). "AgentOps IS a Gas City reference config" → "AgentOps adopts NTM+MCP+managed-agents; it still owns no core, it just doesn't own or reference Gas City." This is the deep-dive's "adopt the substrate, don't own it." ## Changes (7 files, +25 / −120) - `docs/3.0.md` — substrate table row; replaced the "Gas City reference City" section with "Running the loop out of session" (the three substrate options); Olympus comparison rows; sovereignty-floor line - `docs/architecture/canonical-loop-model.md` — Factory-driver framing, ASCII diagram, boundary table, dispatch paragraph - `docs/cdlc.md`, `docs/architecture/fungibility-charter.md` — substrate one-liners - **deleted** `docs/architecture/gc-posture.md` + reconciled its 4 inbound links (both index files, documentation-index, fungibility-charter) ## Scope boundaries - **ADR-0009 left historical** — decision records are immutable; it records the *then*-rationale. - **`thesis-stability` not tripped** — that gate guards the product thesis (README/PRODUCT/GOALS), not the substrate detail. (Its current FAIL is pre-existing README/PRODUCT/GOALS tagline drift, unrelated to this PR.) - **Follow-up `ag-124p`** (separate PR): the code/config strip — `packs/agentops` + `city.toml` + `skills/using-gc` + `cli/hooks/claude.json` gc-wiring. ## Note This is outward-facing doctrine — opened for your review rather than auto-merged. PR #5 this session; you authorized continuing past the scope ceiling for the prune. Closes-scenario: ag-vg40#substrate-renarration Bounded-context: BC1-Corpus Evidence: docs/3.0.md |
||
|
|
eba83ad11b |
feat(ci): committed reconcile-pr + no-epic-close-with-open-child gate (ag-9gac #reconcile-helper-epic-gate) (#669)
Promotes the ephemeral `/tmp` bead-crank reconcile engine (ran ~20x this
session) to committed, **tested, enforced** scripts. Turns S3's advisory
prose into executable gates.
## What lands
- **`scripts/reconcile-pr.sh <pr> <bead> [--epic <epic>]`** — polls
checks until terminal, reruns the lone `correctness (ubuntu-latest)`
tar-cache flake **once**, treats only substantive non-`claude-review`
fails as blocking, `gh pr merge --squash --admin` when clean, confirms
`gh pr view --json state == MERGED`, then `bd update <bead> --status
closed` (bd close has a dolt blocker-query glitch). `--epic` mode calls
the gate before closing the epic.
- **`scripts/check-epic-children-closed.sh <epic>`** — the
**no-epic-close-with-open-child** gate: exit 1 naming any
open/in_progress child, exit 0 when all closed.
- **15 hermetic bats** (`gh`+`bd` stubbed via PATH shims) — prove
merge+close on green, BLOCK (exit 2) on a substantive fail,
rerun-once-then-merge on the lone flake, no-close when state != MERGED,
gate rejects+names an open child, passes when all closed. shellcheck -S
warning clean.
- **crank/evolve SKILL.md** prose now points to the committed scripts
(tiny edits).
## Exit-code contract (asserted in tests)
`0` merged+closed · `1` epic-gate fail (open child) · `2` blocked
(substantive fail) · `3` merge attempted but state != MERGED · `4`
usage/dep error.
## Gates
- shellcheck -S warning: CLEAN (both scripts)
- `bats tests/scripts/{reconcile-pr,check-epic-children-closed}.bats`:
15/15 pass
- `scripts/regen-all.sh --check --skills crank,evolve`: ALL GATES GREEN
- Diff scope-only: 2 scripts + 2 bats + 2 skill pointers + 3 codex hash
files (source_hash bumps). Pre-existing `docs/cli-surface.*` main drift
reverted, not swept in.
Orchestrator helpers (not necessarily CI jobs) — wired as enforcement
for the crank/evolve close discipline.
Closes-scenario: ag-9gac#reconcile-helper-epic-gate
Bounded-context: BC3-Loop
Evidence: scripts/check-epic-children-closed.sh
|
||
|
|
efb7fd66e9 |
feat(ci): repo-wide path-filter/gate-target coverage audit + gap fixes (ag-g9ex #pathfilter-audit) (#666)
## What Repo-wide audit of every file-reading CI gate in `.github/workflows/validate.yml` against the invariant the #634/#638 trunk-heal proved: **a gate that READS a file must be TRIGGERED by a path-filter covering that file.** A docs-thinning commit (`bbfd278e`) silently disabled the security redteam canary because the `contracts` filter didn't cover `AGENTS.md`, and it surfaced only on a later unrelated PR. Closes **ag-g9ex** (Slice5[GOVERNANCE]). Derived from `.agents/retro/2026-05-31-bead-crank-postmortem.md` §4(#2) + §7(#5). ## Audit `docs/contracts/ci-pathfilter-coverage-audit.md` enumerates every gate that reads specific files, the files it reads, the filter(s) that trigger it, and a COVERED/GAP verdict. 13 gates audited + verified non-findings. ## Gaps found and fixed (2) 1. **AGENTS tiered-split siblings uncovered (direct #634 class).** `scripts/validate-agents-split.sh` validates `AGENTS.md` + `AGENTS-{WORKFLOW,CI,CODEX,RUNTIME}.md`, but the gate triggered on `docs/ci/shell` and the four siblings were covered by **no** consumed filter. A sibling-only edit would skip the split gate. **Fix:** added the siblings to the `contracts` filter + `contracts` to the gate trigger (mirrors #638). 2. **wiring-closure not re-triggered by GOALS.md de-wire.** `scripts/check-wiring-closure.sh` greps `GOALS.md`/`GOALS.yaml` to confirm every `check-*.sh` is referenced, but triggered on `go/hooks/shell/ci` — not `goals`. A GOALS.md-only de-wire would skip it. **Fix:** added `goals` to the gate trigger. ## Governance (--admin self-merge, §7 #4) Documented as policy in the audit doc rather than shipped as a half-working CI gate (GitHub Actions cannot observe `--admin` from inside a `pull_request` workflow; building a fake gate would be over-engineering against the bead's explicit guidance). Mechanical enforcement filed as a follow-up. ## Guard test Extended `tests/scripts/test-pathfilter-gate-coverage.bats` (the #638 guard) with 3 new assertions: AGENTS-split targets ⊂ `contracts`, split gate triggers on `contracts`, wiring-closure triggers on `goals`. All 10 tests pass. ## Gates run (local) - `python3 yaml.safe_load(validate.yml)` → VALID - `bats test-pathfilter-gate-coverage.bats` → 10/10 ok - `scripts/check-contracts-structural-floor.sh` → PASS (46 contracts) - `scripts/validate-ci-policy-parity.sh` → PASS (11 rows) - `git diff origin/main --stat` → scope-only (4 files) Closes-scenario: ag-g9ex#pathfilter-audit Bounded-context: BC2-Validation Evidence: docs/contracts/ci-pathfilter-coverage-audit.md |
||
|
|
7c10303184 |
chore(ci): regen-codex-hashes --only scoping + regen-all passthrough (ag-fbe9 #regen-scoping) (#664)
## What Adds `--only <skill[,skill,...]>` to `scripts/regen-codex-hashes.sh` and threads it through `scripts/regen-all.sh` (`--skills` arg / `REGEN_SKILLS` env), so an agent can regenerate codex hashes for **only the skills it touched**. ## Why From `.agents/retro/2026-05-31-bead-crank-postmortem.md` §5 (#1-2): the codex hash regen rewrites every drifted manifest entry, sweeping ~8-9 pre-existing drifts into every skill PR and forcing a manual `jq`-splice. Scoping the loop kills that toil. ## Changes - **`regen-codex-hashes.sh`**: `--only` parses a skill set; the per-skill loop `continue`s when a skill isn't in the set. `--check` honors the same scope. Default (no flag) = all skills, unchanged. `SKILLS_ROOT` is now env-overridable (enables hermetic testing). - **`regen-all.sh`**: `--skills a,b` / `REGEN_SKILLS=a,b` threads `--only` into the codex-hash step in both regen and `--check` modes; trailing NOTE instructs passing scope when only some skills changed. - **`tests/scripts/regen-codex-hashes-only.bats`**: hermetic — `--only foo` regenerates only foo and leaves a simulated pre-existing-drift sibling untouched; no-`--only` regenerates all; `--check` scoping; comma-list; arg-required. ## Verification - `bats tests/scripts/regen-codex-hashes-only.bats` — 5/5 pass - `shellcheck -S warning` clean on both scripts - `git diff origin/main --stat` scope-only (2 scripts + 1 bats) - The 9 manifest drifts on `main` (deps, post-mortem, provenance, red-team, release, scenario, ship-loop, skill-builder, trace) are **pre-existing**; this PR touches zero `skills-codex/` files. Closes-scenario: ag-fbe9#regen-scoping Bounded-context: BC2-Validation Evidence: scripts/regen-codex-hashes.sh |
||
|
|
0dcbae450c |
fix(loop): re-enforce session-PR-scope hooklessly + fix stale hook refs (ag-o5xp #session-pr-scope) (#661)
## Problem The session-PR-scope guardrail shipped as a PreToolUse hook (`hooks/session-pr-counter.sh`, PR #362), but **PR #511 (the 3.0 hookless teardown) deleted all hooks**. Six workflow-discipline surfaces were never updated — they still advertise the hook as a live, shipping mechanism. That's a **stale active-surface promise + a lost reliability guardrail** (surfaced by the ag-4hf7 Google-SRE audit: "explainability/trust" turned inward). ## Hookless re-enforcement (the decision) - **The mandatory layer already survives**: the `/evolve` post-mortem checkpoint #6 (council-gated, cannot be bypassed) enforces session-scope for autonomous loops — the actual failure mode. It only lacked a canonical count source. - **New `scripts/session-pr-scope.sh`** — the reusable hookless count + verdict (`OK`/`WARN`/`BLOCK`), fail-open, robot-friendly (`--json`/`--count`). It is now: - the checkpoint's `$session_pr_count` source, and - the one-liner an **opt-in** hook wraps (re-author via the hooks-authoring skill — AgentOps ships none). - 8 bats cases (thresholds, block-mode exit code, fail-open); shellcheck clean. ## Stale-doc truth (6 surfaces, all hedged) CLAUDE.md · AGENTS-WORKFLOW.md · skills/ship-loop/SKILL.md · the evolve postmortem-checkpoint (skills/, skills-codex/, packs overlay — kept in parity; codex hashes regenerated for **evolve + ship-loop only**, the 7 pre-existing drifts left untouched). ## Ratchet (knowledge → a constraint) Extend `check-hookless-cold-start.sh` to cover these workflow-discipline surfaces — reversing the now-stale CLAUDE.md carve-out — so this exact drift class **cannot recur**. Gate scope 5 → 10 surfaces; its bats test stays green. (This is the "knowledge becomes a constraint" invariant the whole ag-4hf7 thread identified as our edge — applied to the very gap that thread surfaced.) ## Verification - `bats tests/scripts/session-pr-scope.bats` → 8/8 - `bash scripts/check-hookless-cold-start.sh` → PASS (10 surfaces) - `check-hookless-cold-start.bats` → 5/5 · `validate-codex-generated-artifacts.sh --scope head` → pass · wiring-closure → pass · shellcheck clean · overlay ≡ source Closes-scenario: ag-o5xp#session-pr-scope Bounded-context: BC3-Loop Evidence: scripts/session-pr-scope.sh |
||
|
|
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 |
||
|
|
81c9f305ac |
feat(ci): witness Dolt->JSONL re-derive + hash-compare (ag-lmdx.3 #witness-crosscheck) (#656)
## What The **watcher that watches the watcher** (ag-lmdx.3). A blocking CI gate that re-derives the hash-chained JSONL witness **from the Dolt projection** and hash-compares it against the git-committed witness ledger — proving Dolt is a *faithful projection* of the canonical event log. This is the **inverse** of drrebuild (#646): drrebuild rebuilds the Dolt context graph FROM the witness (JSONL + git blobs); this rebuilds the witness FROM Dolt rows. Together they pin both ends of the projection. Dolt history is rewritable (reset/--force/root) so it is NOT tamper-evidence; the git-anchored JSONL witness is. A Dolt rewrite that did not also rewrite the committed witness is caught here, and nowhere else. ## How - `cli/internal/drwitness/` — re-derive + cross-check core. Reuses drrebuild's exact hash discipline (`ComputeEventHashes`: payload_hash = sha256(canonical-JSON), hash = sha256(payload_hash + "\n" + prev_hash)) and canonical edge ordering. Re-derivation is order-independent (canonical sort then re-seal), which is what makes the hash-compare meaningful. - `cli/cmd/witness-crosscheck/` — standalone helper main (like `cmd/skill-frontmatter-json`), **NOT** an `ao` subcommand (no CLI surface added). - `scripts/witness-dolt-jsonl-crosscheck.sh` — hermetic CI gate. CI has no live Dolt, so it drives committed fixtures through the helper and asserts the gate fires correctly. - `tests/scripts/` + `tests/fixtures/witness/` — bats behavioral proof. ## Scenarios (acceptance) - **Clean state passes** — the faithful Dolt projection re-derives to the committed witness; gate exits 0. - **Tampered Dolt fails** — a rewritten Dolt row no longer matches the committed witness head; helper reports `DIVERGED`, gate exits non-zero. ## Verification - `go build ./... && go vet ./... && go test ./...` (full suite: 11948 passed / 71 pkgs; drwitness: 7/7) - `bats tests/scripts/witness-dolt-jsonl-crosscheck.bats` — 6/6 - `shellcheck -S warning` — clean - `scripts/validate-ci-policy-parity.sh` — PASS - diff is scope-only (10 files, additions); the sibling wave-pregate (#655) is present and untouched. Closes-scenario: ag-lmdx.3#witness-crosscheck Bounded-context: BC4-Factory Evidence: scripts/witness-dolt-jsonl-crosscheck.sh |
||
|
|
46f0768ed8 |
feat(swarm): wave pre-gate node-state ownership disjoint (ag-lmdx.6 #wave-ownership-disjoint) (#655)
## What
Adds `scripts/check-wave-ownership-disjoint.sh` — a wave **pre-gate**
that, before spawning a parallel wave of agents, asserts each slice's
owned **node-state** set is pairwise-disjoint. Overlap means two agents
would concurrently transition the same artifact's state — a genuine Dolt
cell conflict on the `context_artifact` state projection / append-only
`state_transition` log (the real convergence invariant from the ag-lmdx
Dolt-expert review). File-disjointness
(`check-file-manifest-overlap.sh`) is only the weak textual shadow of
this.
## Behavior
Input: JSON array of `{id, subject, owns[]}` slices (file arg or stdin).
- **Overlap** → exit 1, names the contended node-state and the
conflicting slice pair, "wave NOT spawned" (Scenario: *Overlapping node
ownership blocks the wave*).
- **Disjoint** → exit 0, "wave may spawn" (Scenario: *Disjoint ownership
proceeds*).
- Slice with no declared ownership → blocked (cannot prove
disjointness).
- Bad usage/input → exit 2. Missing `jq`/old bash → soft skip.
## Tests / gates
- `tests/scripts/check-wave-ownership-disjoint.bats` — 11 hermetic tests
(both scenarios + exact exit codes 0/1/2, stdin, empty, undeclared,
duplicate-within-slice, three-slice).
- `shellcheck -S warning` clean; `bash -n` clean.
Scope is two new files; no `validate.yml`/skill wiring (follow-up).
Closes-scenario: ag-lmdx.6#wave-ownership-disjoint
Bounded-context: BC5-Runtime
Evidence: scripts/check-wave-ownership-disjoint.sh
|
||
|
|
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 |
||
|
|
03e365bb92 |
feat(validate): generate+check tests-from-scenarios coverage (ag-9jle.4 #tests-from-scenarios) (#648)
## What Adds the C2 "tests-from-scenarios" leaf gate (ag-9jle.4): a per-bead, forward-from-Gherkin scenario→test coverage check, plus wiring into the leaf validators `/vibe` and `/test`. `scripts/check-bead-scenario-coverage.sh` parses a bead's `## Scenarios` block (via `--bead <id>`), a `.feature` file, or stdin, and **FAILS if any scenario lacks a `@covered-by:<test-path>` link**. With `--run` it also executes each covering test and requires it to PASS — not merely exist. This is the distinction the bead calls out: "tests exist" or a coverage percentage is not sufficient. This is the **per-slice sibling** of the existing corpus-wide `scripts/check-scenario-test-linkage.sh` (which sweeps every `.feature` under `skills/*/references/` in CI). They share the `@covered-by:` convention so a scenario authored once carries linkage to both. No new `ao` subcommand (avoids cli-command-surface churn); no symlinks (codex twins copied). ## Why Audit ag-9jle.1 found C2 weak: vibe/validate check test-pyramid *presence*, `test` checks coverage %, review uses a checkbox; only `/validation` enforced scenario→passing-test mapping and only at the bypassable roll-up. This makes the check mechanical and moves it to the leaf (vibe Step 2g.1, test Step 0a), working forward from behavior. ## How it's tested `tests/scripts/check-bead-scenario-coverage.bats` — 19 hermetic cases: M>=N gate, bead-body + `.feature` inputs, `--run` pass vs fail, dangling `@covered-by`, `::Name` resolution, threshold override, `--json`, stdin, `## Scenarios`-block scoping, misuse exits. The gate is dogfooded: it passes on its own bead ag-9jle.4 (`--run` executes this very bats file). ## Gates - `bats tests/scripts/check-bead-scenario-coverage.bats` — 19/19 pass - `shellcheck scripts/check-bead-scenario-coverage.sh` — clean - `bash scripts/check-codex-parity-drift.sh` — no drift (codex twins mirrored) - `bash tests/skills/run-all.sh` — 87/0 pass Closes-scenario: ag-9jle.4#tests-from-scenarios Bounded-context: BC2-Validation Evidence: scripts/check-bead-scenario-coverage.sh |
||
|
|
2c5d93e16b |
feat(ci): scripts/check-proof-coherence.sh (soc-57hbj #proof-coherence) (#647)
## What
Proof-coherence gate for the reconciliation engine (Wave 3C). Two axes
(plan: `.agents/plans/2026-05-07-reconciliation-engine-full-arc.md`):
claim coherence (advisory) and **proof coherence** (claim-ledger row →
daemon criterion-verdict event, **blocking for L2/L3 claims**). This PR
ships proof coherence.
## Coherence predicate
For every L2/L3 claim-ledger row, each `evidence_event_refs[]` entry
must:
1. resolve to a daemon event matching `event_type`+`run_id`
(+`criterion_id` if named) — else **DANGLING**;
2. carry `verdict: pass` — else **FAILED** (demote).
An L2/L3 row with zero refs is **UNBACKED**. L0/L1 rows are not gated.
## Forward-compatible
Wave 1's claim ledger and Wave 3B's `evidence_event_refs` schema haven't
landed, so with no ledger present the gate is a **PASS no-op** — it
lands as blocking CI surface now and becomes load-bearing automatically
once L2/L3 rows appear. Inputs auto-discover
(`docs/contracts/factory-claim-ledger{,.example}.json`,
`cli/.agents/daemon/ledger.jsonl`), overridable via
`--ledger`/`--events`.
## Output / exit codes
Text (default) + `--json`. Exit `0` coherent / no ledger · `1`
incoherent · `2` usage|env.
## Tests
`tests/scripts/check-proof-coherence.bats` — 13 hermetic cases, exact
exit codes + messages, both drift directions (missing event + failed
verdict), unbacked L2/L3, L0/L1 ungated, no-ledger no-op, JSON
pass/fail, malformed-ledger + bad-flag env errors.
## Gates
- `shellcheck -S warning scripts/check-proof-coherence.sh` — clean.
- `bats tests/scripts/check-proof-coherence.bats` — 13/13 pass.
- `git diff origin/main --stat` — scope-only (the two intended files).
## Scope note
validate.yml wiring deferred: a no-op until the ledger ships (Wave 1/3B
precondition); wiring lands with the first L2/L3 ledger row.
Closes-scenario: soc-57hbj#proof-coherence
Bounded-context: BC2-Validation
Evidence: scripts/check-proof-coherence.sh
|
||
|
|
5448142268 |
test(provenance): seed 3 failing orphan fixtures (ag-x31t.7 #orphan-fixtures) (#645)
## What
Seeds 3 **inert, failing-by-design** orphan fixtures for the no-orphan
provenance gate built in **ag-x31t.6** (`ao provenance trace --orphans
--strict`, generalizing `goals_trace_orphans`). Each fixture is a small
goalstrace-shaped graph JSONL (`node`/`edge` records per
`cli/internal/goalstrace/graph.go`) seeding **one engineered artifact
node with no inbound authored/inferred edge** — the orphan condition the
future gate detects.
The three fixtures reproduce the three audit gaps epic **ag-x31t**
closes:
| Fixture | Orphan artifact | Audit gap |
|---|---|---|
| `orphan-scenario-hash-stability.jsonl` |
`gate:scenario-hash-stability` | phantom CI gate with no authoring
directive |
| `orphan-retired-pre-push-gate.jsonl` |
`artifact:scripts/pre-push-gate.sh` | retired-but-present script
reference |
| `orphan-stale-65-jobs.jsonl` | `claim:65-jobs` | stale doctrine claim
("65 jobs") |
`expected-orphans.json` is the contract the **ag-x31t.6** gate will
assert against.
## Verification
Since the consuming gate (ag-x31t.6) isn't built yet,
`tests/scripts/provenance-orphan-fixtures.bats` only verifies the
fixtures are well-formed JSONL and internally consistent with the
manifest (orphan node present, no inbound edge). All 4 checks pass
locally.
## Scope
Fixtures + one format-check bats only. **Out of scope** (sibling beads):
the orphan gate (ag-x31t.6), the ledger schema (ag-x31t.2), any `ao`
subcommand. No symlinks, no holdout data.
Closes-scenario: ag-x31t.7#orphan-fixtures
Bounded-context: BC4-Factory
Evidence: tests/fixtures/provenance/orphan-scenario-hash-stability.jsonl
|
||
|
|
0bc1b5a7ee |
chore(ci): enforce worktree-disposition discipline + prune gate (ag-4oj9.2 #worktree-disposition) (#642)
## What
Closes the CI-gate gap in the worktree-disposition discipline
(ag-4oj9.2). The repo's `bd worktree create` flow accumulates abandoned
tmp worktrees; detection + prune already existed (`gc-stale-worktrees.sh
--apply`, live `check-worktree-disposition.sh`), but nothing **gated**
against an undisposed worktree that gets *committed* into the tree.
- **New `--check-committed` mode** on `scripts/gc-stale-worktrees.sh`:
scans tracked paths (`git ls-files`) for committed tmp-worktree
artifacts — `agentops-*-{merge,rpi*,wt}`, `*-wt/`, `.codex/worktrees/` —
and fails non-zero. Read-only: never touches the working tree, never
removes anything. Uses the existing `--git-common-dir` parent (never
`--show-toplevel`) for main-checkout safety.
- **Wired into `scripts/pre-push-gate.sh`** (step 7a), unconditionally —
it inspects only tracked paths so it is cheap and CI-safe (the live
worktree list is empty on a fresh CI checkout; this catches what CI
*can* see). Auto-runs in CI via the existing `bats tests/scripts/*.bats`
step.
- **Bats coverage**: pass-on-clean, fail-on-committed-tmp-tree (two
naming families), no-false-positive on ordinary source, and a
read-only/no-mutation assertion against the main checkout.
## Why
Undisposed worktrees are statelessness entropy — branch state no agent
owns. The disposition contract (AGENTS-RUNTIME.md) was documented but
not gated against the committed-artifact case. This makes it impossible
for a tmp worktree to land on `main`.
## Gates
- `shellcheck -S warning` — PASS (both scripts)
- `bats tests/scripts/gc-stale-worktrees.bats` — 18/18 PASS
- `scripts/validate-ci-policy-parity.sh` — PASS (no
validate.yml/manifest change; new bats picked up by existing step)
- `git diff origin/main --stat` — scope-only (3 files)
Closes-scenario: ag-4oj9.2#worktree-disposition
Bounded-context: BC5-Runtime
Evidence: scripts/gc-stale-worktrees.sh
|
||
|
|
2907503176 |
fix(ci): cover gate-target files in path filters (ag-nl1u #pathfilter-coverage) (#638)
## What Closes both **ag-nl1u** and **ag-n4m7** — same class of bug (CI path-filter gap) on the same surface (`.github/workflows/validate.yml`), folded into one coherent-arc PR so they don't collide. A gate that reads a specific set of files must be triggered by a change-filter covering those files. When it isn't, an edit to a guarded file SKIPS the gate that guards it, and the required `summary` branch-protection check goes green-but-incomplete — the regression reaches `main` and surfaces only on a later unrelated PR. ### ag-nl1u — contracts filter omits redteam-pack targets (#634) The security-suite redteam pack (`skills/security-suite/references/agentops-redteam-pack.json`) asserts behavioral contracts against `AGENTS.md`, `docs/ARCHITECTURE.md`, `docs/CI-CD.md`, `docs/strategic-direction.md`, `docs/standards/shell-script-standards.md`, `skills/security/SKILL.md`, `skills/security-suite/SKILL.md`. The `contracts` filter only matched `schemas/**` + `docs/contracts/**`, so editing any guarded file skipped the contracts-sync canaries that guard it (the #634 break, fixed reactively). **Fix:** extend `contracts` to a superset of every redteam-pack target glob. ### ag-n4m7 — correctness gates skip on GOALS.md/scenarios (#591/#593) The directive-to-scenario correctness gates police `GOALS.md` + `spec/scenarios/**` but ran only on `go || docs || ci`. A GOALS.md-only edit citing a phantom scenario merged with the gate skipped. **Fix:** add a `goals` filter (`GOALS.md`, `spec/scenarios/**`, `docs/adr/ADR-0003*`) and wire `|| needs.changes.outputs.goals` into goals-validate, F1/F2 spec-link e2e, directive-to-scenario lint, trace-orphans, scenario-to-test linkage (and the Go setup/build steps those depend on, since they invoke `cli/bin/ao`). ## Guard test `tests/scripts/test-pathfilter-gate-coverage.bats` (7 tests) parses the pack JSON + the validate.yml filters and asserts the `contracts` filter is a superset of the pack targets and the `goals` filter + gate wiring stay in place. Prevents this class from regressing. ## Verification - `python3 + PyYAML` parse of validate.yml: valid; both filters present. - `bats tests/scripts/test-pathfilter-gate-coverage.bats` -> 7/7 pass. - `scripts/validate-ci-policy-parity.sh` -> PASS (job blocking classification unchanged). - Sibling `test-bats-path-filter-wiring.bats` + `test-strict-coverage-ci-wiring.bats` -> 8/8 pass (no regression). ## Scope Only `.github/workflows/validate.yml` + one new guard test under `tests/`. No other surface touched. Closes-scenario: ag-nl1u#pathfilter-coverage Bounded-context: BC2-Validation Evidence: .github/workflows/validate.yml |
||
|
|
004fcbc249 |
feat(provenance): agentops-sdlc-provenance.v1 ledger-event schema (ag-x31t.2 #provenance-schema) (#637)
## What
Adds `schemas/agentops-sdlc-provenance.v1.schema.json` — the JSON Schema
(draft-07) that formally defines one event of the committed, per-record
hash-chained provenance ledger at `docs/provenance/ledger.jsonl` (schema
id `agentops-sdlc-provenance.v1`, referenced by CLAUDE.md and the
ag-x31t council architecture).
Each event = one typed provenance edge `{from_id, from_type, to_id,
to_type, relation, evidence_ref, trust_tier(authored|inferred|mined),
ts}` plus export-time hash-chain fields `{prev_hash, payload_hash,
hash}` mirroring `cli/internal/rpi/ledger.go` chaining semantics
(`payload_hash` = sha256 over the edge payload; `hash` =
sha256(payload_hash + "\n" + prev_hash)).
## Acceptance (ag-x31t.2)
> First failing test: validates a `decision_produces_artifact` edge,
rejects one missing `trust_tier`.
- `scripts/validate-provenance-ledger.sh` — python `jsonschema` (Draft7)
validator with `--selftest` and `--jsonl` modes, mirroring
`validate-outcomes-rubric.sh`; SKIPs gracefully when jsonschema is
unavailable.
- `tests/scripts/validate-provenance-ledger.bats` — 12 checks. A
`decision_produces_artifact` edge VALIDATES; an otherwise-identical edge
missing `trust_tier` is REJECTED. Structural-JSON checks are the
always-on guard (run without jsonschema).
-
`tests/fixtures/provenance/{valid-decision-produces-artifact,invalid-missing-trust-tier}.json`
— fixtures with real sha256 chain hashes.
TDD verified: the selftest FAILS when the schema is edited to drop the
`trust_tier` requirement, PASSES when restored.
## Scope
Schema + validator + test only. Does **not** create/edit
`docs/provenance/ledger.jsonl`, the write-model (ag-x31t.4), export
(ag-x31t.5), or gate (ag-x31t.6). No symlinks. No holdout data.
```
gates: validator --selftest pass · bats 12/12 pass
```
Closes-scenario: ag-x31t.2#provenance-schema
Bounded-context: BC4-Factory
Evidence: schemas/agentops-sdlc-provenance.v1.schema.json
|
||
|
|
d82adc3717 |
fix(evolve): sync local main to origin/main before discovery (ag-6jt #discovery-origin-main) (#636)
## What The evolve-cron-rpi loop's phase-1 discovery diffed candidate slices against a **stale local `main`** (the rpi worktree's local main lags `origin/main`), so work already merged to `origin/main` read as "open" and got re-seeded as duplicate beads/PRs (ag-b8m≈ag-jov, ag-6kw≈ag-c2i — 4th recurrence). The `work-selection-ladder` reference *claimed* "the cron syncs local main to origin/main before discovery" but no code actually did it. ## Change - **`skills/evolve/scripts/sync-main-to-origin.sh`** (new): `git fetch origin`, then fast-forward local `main` to `origin/main` (never forced), emitting `DIFF_BASE: origin/main <sha>` as the authoritative diff base. A divergence is refused, never force-moved. - **`scripts/overnight-evolve.sh`**: runs the sync before the loop's discovery phase. Non-fatal on warning (loop proceeds with origin/main as the base). - **`skills/evolve/references/work-selection-ladder.md`**: the claimed sync now points at the real, runnable script. - **`tests/scripts/sync-main-to-origin.bats`** (new): hermetic bare-repo tests pin the diff base = origin/main after fetch (not stale local main), local main fast-forwards, divergence is refused, and a custom remote is respected. Pairs with the grep-existing-beads guard (`duplicate-work-guard.sh`, #582) to cover both halves of the bead. ## Gates - `shellcheck --severity=error` clean on both modified scripts. - `bats tests/scripts/sync-main-to-origin.bats` — 5/5 pass. - `git diff origin/main --stat` — scope-only (4 files, evolve/rpi-discovery surface). Closes-scenario: ag-6jt#discovery-origin-main Bounded-context: BC3-Loop Evidence: skills/evolve/scripts/sync-main-to-origin.sh |
||
|
|
0f16a574bc |
feat(eval): outcomes-rubric projection contract + schema (ag-hguuf #outcomes-rubric) (#624)
## What
Defines the machine-checkable contract for projecting the **locked eval
substrate** into an **Outcomes-style grading payload** (Anthropic
Managed Agents Outcomes analog) — holdout-safe by construction *and* by
schema.
The schema validates the **actual** output of `ao eval outcomes compile`
(`evalsubstrate.Rubric`), not the bead's pre-implementation prose sketch
(which imagined `suite_id`/`metric`/`decision_rule`/`split`). Per
source-of-truth precedence (executable > narrative), the shipped
projection deliberately emits *fewer* fields — a smaller cloud boundary
is a smaller leak surface. The "deliberately NOT projected" rationale is
documented in the contract.
## The load-bearing invariant
**Managed Agents are not ZDR** — a rubric crossing the cloud boundary
must never carry a ground-truth answer / holdout value / `target` /
`expected_output`. Enforced three ways:
1. **By construction** — `ProjectRubric` can't copy ground truth
(existing).
2. **By re-scan** — `Rubric.ContainsAny` guard (existing).
3. **By schema (this PR)** — `additionalProperties:false` at **every
nesting level** → a malformed compiler emission that smuggles a leak
field **fails schema validation**, not merely a code check.
## Files
- `schemas/outcomes-rubric.v1.schema.json` — the contract schema
-
`tests/fixtures/outcomes-rubric/{valid-dev,valid-holdout-criteria-only,invalid-contains-target}.json`
- `scripts/validate-outcomes-rubric.sh` — standalone validator (python
`jsonschema`, mirrors `validate-next-work.sh`); `--selftest` asserts
pass/pass/fail
- `tests/scripts/validate-outcomes-rubric.bats` — 9 acceptance tests
- `cli/internal/evalsubstrate/rubric_schema_test.go` — Go schema↔struct
drift guard (reflection)
- `docs/contracts/outcomes-rubric-projection.md` —
SCHEMA-field→Outcomes-field mapping; catalogued in doc index;
cross-linked from `eval-verdict-pipeline.md`
The contract **references** the LOCKED `~/.agents/evals/SCHEMA.md`
§rc2/§4 — it never edits it. Substrate EXTENDED, never relitigated.
## Evidence
- `scripts/validate-outcomes-rubric.sh --selftest` → PASS/PASS/FAIL
(exit 0)
- `bats tests/scripts/validate-outcomes-rubric.bats` → 9/9 ok
- `go test ./internal/evalsubstrate/` → 82 passed; `go vet` clean; `go
build ./...` success
- `check-contract-compatibility.sh` → contract catalogued + schema
reference OK
- `shellcheck scripts/validate-outcomes-rubric.sh` → clean
Closes-scenario: ag-hguuf#outcomes-rubric-projection-contract
Bounded-context: BC4-Evaluation
Evidence: schemas/outcomes-rubric.v1.schema.json
|
||
|
|
9e311c7e61 |
fix(ci): pre-push-gate skips intentionally-removed hookless-3.0 scripts (ag-nrn7 #hookless-gate-skips) (#622)
## What The full (non-fast) `scripts/pre-push-gate.sh` exits BLOCKED on pristine origin/main, partly because 3 hook-validation scripts it references were **intentionally deleted in the hookless-first migration** (#511): `audit-codex-hooks.sh`, `validate-hook-preflight.sh`, `validate-hooks-doc-parity.sh`. Their gate branches still ran `fail "missing executable"` when a hook diff triggered `needs_check hook` — 3 of the 8 failures in the release-readiness gate (ag-nrn7 triage). ## Fix Convert each `else fail` → `skip` with a hookless-3.0 rationale. **Forward-compatible** (if a script is ever restored, the `[[ -x ]]` branch still runs it) and **honest** (intentionally-absent ≠ broken). 3 lines changed. ## Test Added a regression test: the bats setup stubs every helper script present (per f-2026-04-27-002), masking the absent-script path. The new `ag-nrn7` case removes the 3 stubs, triggers a hook diff, and asserts the gate **skips** (no `missing executable`) rather than fails. - `bats tests/scripts/pre-push-gate.bats` → 56/56 ok (new case green; red before the fix on the `audit-codex-hooks.sh` assertion). - `shellcheck -S error scripts/pre-push-gate.sh` → clean. Removes 3 of the 8 `pre-push-gate.sh` failures triaged in ag-nrn7; advances soc-z3jft 3.0 release readiness. Closes-scenario: ag-nrn7#hookless-gate-skips Bounded-context: BC5-Runtime Evidence: tests/scripts/pre-push-gate.bats |
||
|
|
0c42512fdd |
feat(ci): agent-output-validate.yml — reusable authoritative gate on agent output (ag-mptr #agent-output-validate) (#617)
## What Reusable, authoritative CI gate over **agent-produced output** — the hookless guardrail for out-of-session agents (Claude Managed Agent, Agent SDK loop, or NTM/Codex swarm). A `workflow_call` job runs `ao validate --gate` (the umbrella composing ratchet/standards/scenario) against an agent's PR/artifact and propagates PASS/WARN/FAIL to the job exit code. **CI is the gate, not a ported hook** (AgentOps 3.0 is hookless). Second child of epic **ag-7s9fo** (Make Managed/SDK agents AgentOps-native), after ag-2wln `/agent-native` (#616). Inherits the richer spec absorbed from superseded ag-toat4; the optional SDK hook adapter was split out to ag-50m3. ## Files (3, +184/−0) - `scripts/agent-output-validate.sh` — testable gate logic. Resolves `ao` (`AO_BIN` override), runs `ao validate --gate "$@"`, propagates exit (0 pass/warn, 1 fail, 2 error). **Fails loudly if `ao` is missing** — a missing gate never reads as a clean pass. - `.github/workflows/agent-output-validate.yml` — `workflow_call` wrapper (inputs: `changes`, `strict`); builds `ao`, runs the script. Runtime-agnostic (serves Managed-Agent + NTM-swarm PRs). `workflow_call`-only **by design** — it's adopted by a caller, not triggered standalone, so it does not run on this PR. - `tests/scripts/agent-output-validate.bats` — 7 cases. The **passing+failing fixture evidence** the bead requires, exercised deterministically via an injectable fake `ao` (exit 0/1/2), plus scope-flag forwarding, missing-binary, strict-mode, and workflow-wiring assertions. ## Evidence - `bats tests/scripts/agent-output-validate.bats` → **7/7 green** - `shellcheck scripts/agent-output-validate.sh` → clean (severity=error) - Real-`ao` smoke: against the live binary the script faithfully propagates the gate verdict (an empty dir yields ao's exit-2 "no artifacts" → ERROR, proving no silent pass) - yaml parses valid ## Note for review The workflow is `workflow_call`-only, so CI here can't execute it (nothing `uses:` it yet). The **bats suite is the regression proof** for the gate logic; the yaml is the thin Actions wrapper a caller adopts. Bare invocation (no `changes`/`bead`) intentionally surfaces ao's exit-2 — callers scope the gate via the `changes` input. Closes-scenario: ag-mptr#agent-output-validate Bounded-context: BC5-Runtime Evidence: tests/scripts/agent-output-validate.bats |
||
|
|
8a4e78f01c |
docs(evolve): bake fix-and-repush discipline into the /evolve skill (ag-j4l1 #evolve-discipline-references) (#615)
## What Promotes this session's hard-won fix-and-repush discipline — which lived only in the **session-only cron prompt** (expires in 7 days) — into the **durable `/evolve` skill**, so every future autonomous run inherits it. ## How - **NEW** `skills/evolve/references/new-skill-landing.md` — the **six derived surfaces** a new/modified skill must regenerate in one shot (registry.json being the most-missed; it trips `contracts-sync` + `correctness(ubuntu)` together), with the `regen-all.sh` shortcut and the manual codex-twin / `SKILL-TIERS.md` steps. - `gate-hygiene.md` **+2 subsections**: pre-push **diff-scope check** (catches half-staged commits like #612 + conflict-resolution collateral deletions like #600) and **pre-existing-vs-mine red triage** (mkdocs-strict + the 7 codex `.agentops-generated.json` drifts). - `SKILL.md` links both from Step 4.5 + the References list. ## Dog-fooding Built one-shot through its own documented discipline: codex twin hash refreshed for `evolve`, the 7 pre-existing codex drifts reverted, manifest surgically rebuilt to the `evolve` delta only. No inventory/count files touched (correct — adds references, not a skill). ## Evidence - `tests/scripts/evolve-discipline-references.bats` → **4/4** (locks both reference links + the two new gate-hygiene subsections) - `heal.sh --strict skills/evolve` → clean - `validate-codex-generated-artifacts.sh --scope worktree` → pass (Companion: ag-cw2y wired the skill-builder *scaffold*; ag-ekyq added the registry surface; this bakes the operator-side *runtime guidance* into /evolve.) Closes-scenario: ag-j4l1#evolve-discipline-references Bounded-context: BC2-Validation Evidence: skills/evolve/references/new-skill-landing.md |
||
|
|
b0a7f4e958 |
fix(skill-builder): scaffold regenerates registry.json — the 5th one-shot-green surface (ag-ekyq #scaffold-registry-regen) (#614)
## What
skill-builder's `init.sh` new-skill plumbing (ag-cw2y) wired **4 of 5**
derived surfaces — dispositions, narrative counts, codex
override-catalog — but **not** the `registry.json` SKU catalog. A stale
`registry.json` trips `contracts-sync` ("registry.json is stale") AND
`correctness(ubuntu)` ("SKU_CATALOG: DRIFT") together.
This was the **most-missed surface** this session: it cost `/burndown`
#600 a 2nd fix-and-repush (`22a0af2f`) and was a manual
`generate-registry.sh` step for `/eval-outcomes` (#613).
## How
Adds `generate-registry.sh` as plumbing **step 4** in `init.sh`,
positioned **last** (it scans the whole `skills/` tree, so the skeleton
+ the other 3 surfaces must exist on disk first), guarded with a `WARN`
fallback like its siblings. A new skill is now one-shot-green across all
5 surfaces with zero manual regen.
## TDD
`tests/scripts/scaffold-registry-regen.bats` (4/4 green) locks the
wiring + ordering contract: init.sh invokes the canonical generator,
guarded, after the override-catalog step and before the final skeleton
echo. `generate-registry.sh` is not repo-root-injectable (it reads
hooks/types.go/schedule across the tree), so the contract is the
wiring+ordering; the end-to-end behavior was empirically validated this
session running `generate-registry.sh` on the freshly-scaffolded
`/eval-outcomes` (#613, registry included the new skill).
## Scope
Reverted the 7 pre-existing-main codex `.agentops-generated.json` drifts
that `regen-codex-hashes` swept in; surgically rebuilt the manifest to
skill-builder's hash delta only (changing init.sh refreshes
skill-builder's codex twin hash — a real consequence of this diff).
Closes-scenario: ag-ekyq#scaffold-registry-regen
Bounded-context: BC4-Factory
Evidence: tests/scripts/scaffold-registry-regen.bats
|
||
|
|
4d18300790 |
chore(tests): codex-desc budget is per-skill-average, not a hard aggregate (ag-vzbt) (#612)
## What **ag-vzbt** — the last `ag-cw2y` item. The skills-codex description catalog budget was a **hard aggregate** (2800 chars, bumped 2600→2700→2800 as skills landed) with ~17 chars headroom. Adding the Nth+ skill walls out — `/burndown` #600 was forced into a 17-char stub ("Bounded epic loop") to fit. ## How Replace the hard aggregate with a **per-skill average** cap (`CODEX_DESC_AVG_FAIL_CHARS=45`) that scales with the catalog: - Each terse description keeps the average low; the gate fails only if descriptions are **bloated on average** — not because the catalog grew. - Current state: avg **35** chars/skill (77% of 45) — real headroom, and it never becomes a wall again. - The per-skill hard cap (`DESC_FAIL_CHARS=180`) still bounds any single bloated description. - `BUDGET_REPO_ROOT` override added so the rule is fixture-testable. ## Tests (TDD, red→green) `tests/scripts/codex-desc-avg-budget.bats` — PASS under budget / FAIL over budget / **100 skills (total ~3800 > old 2800 wall) still pass** because avg stays low. 3/3 green; shellcheck clean; real-repo gate passes (avg 35/45). ## ⚠️ Pre-existing unrelated red The local fast gate also surfaces a **pre-existing** `mkdocs strict` failure on `rfcs/0001-finding-generator-parallelism.md` — reproduces on clean `origin/main` with my changes stashed; my diff touches only the test script + bats (zero docs). Flagging separately; not in scope here. ## ag-cw2y status **All four items now done** (items 1,2,4 merged #609/#610/#611; item 3 here). A brand-new skill is now **one-shot-green** → this unblocks **`ag-hdqu0.8`** (last Outcomes bead) and **`/burndown` #600**. Closes-scenario: ag-vzbt#per-skill-average-budget Bounded-context: BC2-validation Evidence: tests/scripts/codex-desc-avg-budget.bats |
||
|
|
0023aa5acf |
feat(skills): skill-builder scaffolds codex override-catalog entry (ag-cw2y item 4) (#611)
## What **ag-cw2y item 4** — the 4th and last new-skill gate that cost `/burndown` #600 a CI round. A new skill previously tripped `validate-codex-override-coverage` ("source skill missing from Codex catalog"). skill-builder now adds the catalog entry automatically. ## How - **`scripts/append-codex-override-entry.sh`** — idempotent, JSON-aware: appends a `parity_only` entry (`name`/`treatment`/`wave=catalog-parity`/`reason`) to `skills-codex-overrides/catalog.json` if the skill is absent. `parity_only` is correct for skill-builder's canonical-derived codex form; author flips to `bespoke` + scaffolds the override dir only if a Codex-only divergence is needed. Repo-root-injectable. - **`init.sh`** — calls it in the new-skill plumbing block alongside the dispositions row (#609/#610) and `--fix-counts` (#610). All three gates now pre-empted at scaffold time. ## Tests (TDD, red→green) `tests/scripts/append-codex-override-entry.bats` — appends parity_only / stays valid JSON / idempotent / no-dup-on-existing. 4/4 green. shellcheck clean. ## Codex artifact Refreshed **only skill-builder's** hash (6 unrelated pre-existing `main` drifts untouched). PR-scope codex validation passes. ## ag-cw2y status after this Item 1 (#609 check + #610 scaffold) ✅ · Item 2 (#610) ✅ · **Item 4 (here)** ✅ · **Item 3** (codex desc token budget / `ag-vzbt`) is the only remaining piece. Once item 3 lands, a new skill — and therefore `ag-hdqu0.8` + `/burndown` #600 — is fully one-shot-green. Closes-scenario: ag-cw2y#override-catalog-scaffold Bounded-context: BC4-factory Evidence: tests/scripts/append-codex-override-entry.bats |
||
|
|
5918fd559f |
feat(skills): skill-builder scaffolds dispositions row + narrative counts (ag-cw2y items 1-scaffold + 2) (#610)
## What Completes **ag-cw2y item 1's scaffold-half + item 2**. A newly-scaffolded skill is now one-shot-green against the two gates that silently tripped `/burndown` #600: 1. missing `skill-dispositions.yaml` row → `heal.sh` Check 12 (`MISSING_DISPOSITION`, shipped #609) 2. stale `"N checked-in skills"` narrative counts → `check-registry-drift` ## How - **`scripts/append-skill-disposition.sh`** — idempotent helper that appends a dispositions row (valid `BC4 Factory` placeholder + TODO rationale, so `check-bounded-contexts-drift` passes; author refines during content fill). Repo-root-injectable → fixture-testable. - **`init.sh`** — after scaffolding, calls the helper *and* runs `check-registry-drift.sh --fix-counts` to bump the narrative skill-count tokens. Both calls are guarded + WARN-on-failure so they never break the scaffold. ## Discovery (scope-narrowing) Item 2's **check + `--fix-counts` already existed** and were wired into both the fast pre-push gate (line 1330) and CI (line 803). The only gap was that **skill-builder never invoked them** — so the fix is wiring, not a new check. ## Tests (TDD, red→green) `tests/scripts/append-skill-disposition.bats` — appends row / valid BC + TODO / idempotent / no-dup-on-existing. 4/4 green. shellcheck clean. ## Codex artifact Refreshed **only skill-builder's** source/generated hash (6 unrelated pre-existing `main` drifts left untouched). PR-scope `validate-codex-generated-artifacts --scope head` passes. ## ag-cw2y remaining Item 1 (check #609 + scaffold here) ✅ · Item 2 (here) ✅ · **Item 3** (codex desc budget / `ag-vzbt`) and **Item 4** (override-catalog scaffold + `test-codex-override-coverage`) remain — then `ag-hdqu0.8` and `/burndown` #600 are fully one-shot-green. Closes-scenario: ag-cw2y#skillbuilder-scaffold-dispositions-counts Bounded-context: BC4-factory Evidence: tests/scripts/append-skill-disposition.bats |
||
|
|
3711106671 |
feat(skills): heal --strict checks skill-dispositions coverage (ag-cw2y item 1) (#609)
## What First slice of **`ag-cw2y`** (make adding a skill one-shot-green). Adding `/burndown` (ag-3yl8 #600) cost a CI round because a new user-invocable skill with **no row in `docs/contracts/skill-dispositions.yaml`** passed every local check (`audit-codex-parity --skill`, `heal --strict`, `sync-skill-counts`) silently — the miss only surfaced in CI. This adds the local catch: **`heal.sh` Check 12 — dispositions coverage.** Every user-invocable `skills/<n>` must have a dispositions row, else `MISSING_DISPOSITION` (exit 1 under `--strict`). Same internal/non-invocable exemptions as the existing catalog check (Check 10). ## How - `heal.sh`: new Check 12 (global), plus a `HEAL_REPO_ROOT` env override so the check is fixture-testable; production still derives `REPO_ROOT` from script location. - Verified **no `MISSING_DISPOSITION` on the real repo** — all current skills are covered, so this is a pure tightening with zero false positives. ## Tests (TDD, red→green) `tests/scripts/heal-dispositions.bats` — fixture skill missing a row → flagged; with a row → clean; `--strict` exits 1 and names the miss. All 3 green. ## Codex artifact note Editing `skills/heal-skill/` requires a paired `skills-codex/heal-skill/` update (the source-hash). I refreshed **only heal-skill's** `.agentops-generated.json` + its manifest entry. The 6 unrelated pre-existing codex-hash drifts on `main` (deps/trace/scenario/provenance/red-team/release) are **left untouched** — out of this PR's scope. PR-diff-scoped `validate-codex-generated-artifacts.sh --scope head` passes. ## Remaining ag-cw2y items (follow-on) Item 1 (dispositions) is the check half done here. Items 2 (domain-map narrative counts), 3 (codex desc budget / ag-vzbt), 4 (codex override-catalog scaffold) + the skill-builder *scaffold* halves remain — they fully unblock `ag-hdqu0.8` and `/burndown` #600 one-shot-green. Closes-scenario: ag-cw2y#dispositions-coverage-check Bounded-context: BC2-validation Evidence: tests/scripts/heal-dispositions.bats |
||
|
|
fe731d12b9 |
feat(skills): skill-flow connectivity gate + closed consumes vocabulary (#597)
## Do all skills flow together? **No — not until this PR.** Investigating the question surfaced a structural gap: skill dependencies are declared across **three overlapping frontmatter fields that drifted apart and were never reconciled**, and nothing enforced connectivity or constrained the `consumes` vocabulary. | Field | Meaning | Read by context-map? | |-------|---------|----------------------| | `consumes` | upstream inputs | yes (data-flow table) | | `context_rel` | DDD relationship | yes (mermaid) | | `metadata.dependencies` | upstream skill slugs | **no** | Findings (76 skills): - **33 skills** where `consumes` (skills) ≠ `metadata.dependencies` — the two skill-slug fields disagree. - The generated `context-map.md` **ignored `metadata.dependencies` entirely** (34 skills, the richest layer). - Counting all three layers, **16 true orphans** (incl. core skills like `push`, `session-bootstrap`) with zero skill-to-skill edges — silently. - `consumes` was an **open free-text field**: no check that a token resolves to anything. `scripts/audit-skill-metadata.sh` already flagged the `consumes`-vocabulary and connectivity checks as *"discovered follow-ups, not enforced."* This is that follow-up. ## What this PR does **1. Connectivity gate** — `scripts/validate-skill-flow.sh` (+ `validate-skill-flow` CI job): - **Closed `consumes` vocabulary**: every token must resolve to a skill slug, a whitelisted external input (`repo-context`, `external-api`, `bd`, `github-pr`, `onboard`), or an artifact some skill produces. Catches typos/undeclared deps. - **`metadata.dependencies` resolution**: every entry must name a real skill. - **Orphan detection** across all three edge layers; un-allowlisted orphans fail. - Reports (non-fatal): cross-layer disagreement + dead-end artifacts, so they can be reconciled later. **2. Wire the genuine-gap edges** — added `context_rel` for 6 disconnected skills and regenerated `context-map.md`: - `deps` → `vibe`, `red-team` → `vibe` (mirrors `security`/`security-suite`) - `provenance` ↔ `trace` - `scenario` → `validation` - `release` → `ship-loop` **3. Close the vocabulary** — the closed `consumes` namespace is enforced by the gate and documented in `docs/contracts/skill-flow.md` (linked in `documentation-index.md`). 14 intentionally-standalone leaves are allowlisted in `scripts/skill-flow-standalone.txt` with a rationale per entry. ## Verification ``` $ bash scripts/validate-skill-flow.sh validate-skill-flow: 76 skill(s), 121 skill-to-skill edge(s) orphans: 14 (allowlisted standalone: 14) OK: skill flow is connected and the consumes vocabulary is closed. ``` - `validate-skill-flow.sh`: exit 0 ✅ - `validate-context-map-drift.sh`: exit 0 ✅ - `check-contracts-structural-floor.sh`: PASS (contract cataloged) ✅ - 11 acceptance tests in `tests/scripts/validate-skill-flow.bats` (bats not installed locally; exercised via manual smoke + will run in CI `bats-tests`). Bounded-context: BC1-Corpus Evidence: OK: skill flow is connected and the consumes vocabulary is closed. --- _Generated by [Claude Code](https://claude.ai/code/session_01WLdHEva31cixBjxo8z9TXK)_ Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
e33fa8c5e2 |
feat(eval): deny-by-default holdout-leak CI gate for Outcomes payloads (ag-hdqu0 #leak-gate) (#605)
## What Adds the **fourth holdout-leak guard** for ag-hdqu0: `scripts/check-outcomes-holdout-leak.sh` — the authoritative CI check (a script, not a hook) that refuses any Outcomes rubric/score payload carrying a `target`/`ground_truth` **key**. Managed Agents are not ZDR, so a leak is permanent; this backs the by-construction (`ProjectRubric`) + re-scan (`ContainsAny`) + drift (`FreshAgainst`) guards with a deny-by-default gate. - Deny-by-default: unreadable file → fail; no args → usage error. - Wired as a **step in the existing `contracts-sync` job** (scans committed Outcomes payload fixtures; empty set passes, gate armed for future fixtures). **No new job** → jobs-table unchanged (11 rows), `ci-policy-parity` green (verified locally pre-push). ## Tests (TDD) - `tests/scripts/check-outcomes-holdout-leak.bats` — 6 cases: clean→0 · target→1 · ground_truth→1 · mixed→1 · unreadable→1 (deny-by-default) · no-args→usage. All pass; `shellcheck --severity=error` clean. Closes-scenario: ag-hdqu0.6#leak-gate Bounded-context: BC1-Corpus Evidence: tests/scripts/check-outcomes-holdout-leak.bats |
||
|
|
4107bbed1c |
refactor(ci): rebuild validate.yml — 67 jobs → 10 purpose-grouped (ag-877 #gate-rebuild) (#592)
## What
First-principles rebuild of `.github/workflows/validate.yml` (ag-877 /
epic ag-5ck, no strangler). Collapses the **67-job** orchestration into
**9 purpose-grouped jobs** (+ `changes` + `summary` = 12 total). All
**59** `scripts/{check,validate}-*` are preserved verbatim — the checks
are the safety logic; the 67-way job fan-out was accretion slop.
Design: `spec/teardown-2026-05-28/gate-rebuild-first-principles.md`
## How
Each purpose job runs its script family as **path-gated steps**
(per-step `if: needs.changes.outputs.X`), with advisory checks marked
`continue-on-error: true` at the **step** level (no whole-job
non-blocking). Notable structural moves:
- **correctness** = matrix `[ubuntu, windows]` — folds `windows-smoke`
in as a Windows leg (it runs `tests/windows/*.ps1`, no `scripts/`
family) instead of a standalone job.
- **doctrine-proof** = the doctrine/GOALS proofs **+ spec-linkage**
(executable-spec link, scenario↔test linkage, AGENTS split,
docs↔learning) — both prove the GOALS/spec apparatus is consistent and
share the Go+ao+Python setup (10→9).
- **summary** absorbs **AP#7** Evidence verification (was
`validate-pr-evidence-claims`) — it needs every sibling job's logs, so
it must run last, not in a parallel group.
## Acceptance (ag-877)
- **ac-gr.1 coverage-proof empty** — `comm -23` of old-vs-new
`scripts/*` invocations is empty (no script dropped). ✅
- **ac-gr.2 job count ≤12** — `grep -cE '^ [a-z][a-z0-9-]+:$'` = 12. ✅
- **ac-gr.3 self-CI green** — this PR runs the new `validate.yml`
against itself (changes `.github/**` → all paths trigger). ⏳ this run.
Coupled job-name contract projections updated in lockstep:
`docs/contracts/ci-jobs.yaml` manifest (64→9), regenerated
`AGENTS-CI.md` table + `registry.json` (gate SKUs 66→11; skills/cli/ref
untouched), and 3 structural bats tests re-anchored to the grouped jobs.
Local: `validate-ci-policy-parity`, `registry-check`,
`validate-sku-catalog-drift`, `check-wiring-closure` all PASS; full bats
suite **740 tests, 0 failures**.
## ⚠️ Operator-gated cutover (do NOT auto-merge)
Branch protection still lists the **64 old** required-check names. This
PR **cannot auto-merge** until an admin swaps them for the new ~10
(**ag-7hpl**), then verifies a no-op PR is gated by exactly the new set
(**ag-1eqi**). Both are repo-admin, repo-wide blast radius →
operator-coordinated.
Closes-scenario: ag-877#uniform-gates-consolidated
Closes-scenario: ag-877#heterogeneous-setup-ported
Closes-scenario: ag-877#changes-preserved-summary-rewired
Closes-scenario: ag-877#coverage-proof-empty-ci-green
Bounded-context: BC2-Validation
Evidence: CI_JOBS_TABLE: PASS
|
||
|
|
4e4842865d |
feat(goals): anti-regeneration fitness goal — teardown-removed apparatus stays removed (ag-8ok #anti-regen) (#591)
3.1 teardown **keystone** (ag-8ok), discovered-from ag-097. Makes
subtraction a *measured* fitness outcome so the `/evolve` loop can't
quietly rebuild what the teardown removed.
### The design (NOT a size metric — that's a GOALS.md Anti-Star)
GOALS.md "## Anti Stars" forbids "Goals that measure code metrics
instead of user outcomes." So this is a **stay-removed guard**, not a
"fewer lines/files/jobs is better" ratchet: it fails *only* when a
surface the teardown explicitly removed comes **back**. Legitimate new
growth is fine; only regrowth of specifically-removed apparatus fails.
That's a real outcome ("the slop we removed stays removed"), not a size
metric.
This session is the live evidence ag-8ok predicts: planning regenerated
duplicate P1 beads (ag-cbt/ag-2oi) faster than the system pruned.
Without an anti-regeneration signal, the loop's merge=reward incentive
re-grows apparatus.
### What changed (additive only)
- `scripts/check-no-apparatus-regrowth.sh` — reads a manifest of removed
paths; exit 0 if all stay gone, exit 1 (per-path message) on regrowth.
`--json`/`--manifest`/`--root` flags.
- `scripts/removed-apparatus.txt` — the data-driven manifest (5
surfaces: wikiworker #589, plans/worker #581, gascity + bridge/gc.go
#590). Future teardown waves append here in the same change that lands
the deletion.
- `GOALS.md` — one measurable goal (`no-apparatus-regrowth`, weight 5)
wired to the script + one strategic Directive (D15,
`d-teardown-removed-apparatus-stays-removed`), framed as an outcome. No
North/Anti-Star edits.
- `tests/scripts/check-no-apparatus-regrowth.bats` — 8 tests
(PASS-when-absent, FAIL-when-regrown, json, missing-manifest, and a
guard that the real committed manifest passes on the real tree).
### Verification
- `bash scripts/check-no-apparatus-regrowth.sh` → PASS, all 5 stay
removed, exit 0
- `bats` 8/8 · `shellcheck` clean
- `ao goals measure` (built from source) surfaces
`no-apparatus-regrowth: PASS`; `--directives` lists D15; `goals
validate` valid
Closes-scenario: ag-8ok#anti-regen
Bounded-context: BC1-Corpus
Evidence: spec/teardown-2026-05-28/
|
||
|
|
10db732740 |
fix(evolve): guard jq|wc pipefail so a malformed line cannot abort the script (ag-1j1 #jq-wc-guards) (#584)
## What Under `set -euo pipefail`, a `jq ... 2>/dev/null | wc -l` substitution aborts the entire script when `jq` hits a malformed JSON line: `2>/dev/null` suppresses jq's stderr but not its non-zero exit code, `pipefail` propagates that through the pipeline, and `set -e` then kills the script mid-run (leaving partial state). ## Fix Append `|| echo 0` to the unguarded substitutions: - **`scripts/bootstrap-maturity.sh` line 65** — reads the raw `.jsonl` file directly, so a malformed line genuinely aborts the migration before the summary prints. Verified empirically and caught by the regression test (test fails against the unguarded copy with `status != 0`). - **`scripts/evolve-capture-daily-learning.sh` lines 59-62 (4x)** — matches the already-guarded `grep -c` on line 58. Verification note: in normal operation `TODAY_CYCLES` is pre-sanitized by the line-55 `jq ... || true` filter, so these lines don't see malformed input in practice. The guard is defense-in-depth that pins abort-proof behavior if malformed content ever reaches them (e.g., a future refactor drops the line-55 sanitization). `halt-check.sh` is intentionally out of scope (`set -uo`, no `-e` — degrades, doesn't abort). ## Test `tests/scripts/jq-wc-pipefail-guards.bats` (5 tests): - Malformed-input fixtures for both scripts prove neither aborts and the consolidated artifacts still get written. - A guarded/unguarded expression pair (positive + negative control) pins the `|| echo 0` mechanism so a future edit can't silently drop it. ## Local validation - `bats tests/scripts/jq-wc-pipefail-guards.bats` — 5/5 green - `shellcheck scripts/evolve-capture-daily-learning.sh scripts/bootstrap-maturity.sh` — clean - Existing `tests/scripts/bootstrap-maturity.bats` — still 4/4 green Closes-scenario: ag-1j1#jq-wc-guards Bounded-context: BC5-Runtime Evidence: bats tests/scripts/jq-wc-pipefail-guards.bats |