Cycle 153 applies the cycle-147 template to a 9th adapter:
productionCitationAdapter (cycle 83 — the original first wire-up
adapter from the BC ports arc). Verifies file/function/symbol
citations against HEAD.
New surface:
ao citation verify --kind <file|function|symbol> --raw <text>
Wraps productionCitationAdapter — which in turn wraps the existing
verifyFileCitation / verifyFunctionCitation / verifySymbolCitation
helpers in beads.go. Output is JSON CitationVerdict (Status, Reason,
optional Resolved).
Live smoke verified both directions:
$ ao citation verify --kind file --raw "cli/cmd/ao/beads.go"
{"Status":"FRESH","Reason":"file exists at HEAD","Resolved":""}
$ ao citation verify --kind file --raw "this/file/does/not/exist.go"
{"Status":"STALE","Reason":"file this/file/does/not/exist.go not found at HEAD","Resolved":""}
Template adherence vs cycle-147 spec: ✓. 6 tests covering:
empty kind/raw rejected, FRESH/STALE/UNKNOWN status passthrough,
error wrapping.
New files:
- cli/cmd/ao/citation_cmd.go (107 lines) — citationCmd parent +
citationVerifyCmd. Resolves cwd via resolveProjectDir; passes
to the port as Cwd field.
- cli/cmd/ao/citation_cmd_test.go (104 lines) — 6 tests using
injectable verifyFn.
cli/docs/COMMANDS.md regenerated.
9 of 14 production adapters now CLI-exposed (~64%):
loop history/append + ci latest/recent + corpus inject/capture +
operator record/list + harness status + gate run + citation verify.
5 remain (ClaimEvidenceBinder, FactoryAdmission, ClaimEvidence,
EventBus, FindingCompiler).
Time: ~8 min. LOC: 211. Tests: 6. Within template band.
Symbolic milestone: this exposes the FIRST production adapter that
shipped in the wire-up arc (cycle 83 productionCitationAdapter).
The cycle-122 wire-up-arc learning's named gap is now fully closed
for that pioneer adapter — typed verification reachable from the
CLI 70 cycles after the adapter shipped.
Cycle 153 / template-applied CLI-wiring 6th application.
Cycle 151 applies the cycle-147 template to a 7th adapter:
productionCorpusWriter (cycle 113). Closes the BC1 CorpusReader+
Writer pair on the CLI side (cycle 146 already shipped 'ao corpus
inject' for the reader).
New surface:
ao corpus capture --path <relpath> --body "..." [--meta k=v ...]
ao corpus capture --path x --body-file f.md
echo "..." | ao corpus capture --path x --body-stdin
Wraps productionCorpusWriter. Three body-source options
(--body, --body-file, --body-stdin) are mutually exclusive — the
helper rejects multiple sources to force one explicit choice.
Metadata via --meta key=value (repeatable). Path safety inherited
from the production adapter (rejects absolute paths and parent
traversal).
Live smoke (round-trip):
$ ao corpus capture --root /tmp --path smoke.md --body "hello"
created /tmp/smoke.md
$ cat /tmp/smoke.md
hello from cycle 151
New nuance from this cycle: 'body source' validation. The template
previously didn't model "one of N alternatives required" inputs.
Solved with a small corpusCaptureResolveBody helper that counts
sources and errors clearly. Future cycles applying the template to
adapters with mutually-exclusive input modes can copy this pattern.
New files:
- cli/cmd/ao/corpus_capture.go (172 lines) — corpusCaptureCmd
added under existing corpusCmd. Three body sources + metadata +
injectable captureFn. Compile-time port wiring via
productionCorpusWriter.
- cli/cmd/ao/corpus_capture_test.go (165 lines) — 8 tests:
empty path rejected, body required, multiple-sources rejected,
inline body to stub, stdin body, meta parsed, malformed meta
rejected, --body-file reads content, stub error wrapped.
cli/docs/COMMANDS.md regenerated.
7 of 14 production adapters now CLI-exposed (50%!):
loop history + ci latest/recent + corpus inject + corpus capture
+ operator record/list + harness status + gate run.
7 adapters remain unexposed. Exposing all 14 is now a deterministic
path; expose ad-hoc as needs surface.
Time: ~10 min. LOC: 337. Tests: 8. Slightly above template band
because of the body-source-resolution helper — accounted for in
the new nuance documented above.
Cycle 151 / template-applied CLI-wiring 4th application.
BC1 R/W pair now complete on the CLI side.
Cycle 150 applies the cycle-147 CLI-wiring template to a 6th
adapter: productionGateRunner (cycle 115). The 3rd consecutive
application of the template (148-149-150) — pattern is now
demonstrably routine.
New surface:
ao gate run <name>
Wraps productionGateRunner — invokes scripts/check-<name>.sh and
emits a structured GateVerdict (Status, Reason, LogTail) as JSON.
Useful as a typed alternative to 'bash scripts/check-X.sh; echo $?'
for scripts wanting structured output.
Live smoke (from project root):
$ ao gate run compile-health
{"Status":"PASS","Reason":"exit 0","LogTail":"PASS: Compile
health OK (defrag 14h ago, stale=0/5)\n"}
Implementation note: `gate` parent command already existed (human
review gates from a different surface). cobra accepts adding a
'run' subcommand to it without conflict. The BC2 surface lives at
'ao gate run'; the prior 'ao gate ...' subcommands are unaffected.
Template adherence vs cycle-147 spec: ✓ on all 5 principles. New
nuance from this cycle: composing into a pre-existing parent
command works as long as the verb subcommand doesn't conflict with
existing subcommands under the parent.
New files:
- cli/cmd/ao/gate_cmd.go (96 lines) — gateRunCmd added under
existing gateCmd. Standard injectable runFn for tests.
- cli/cmd/ao/gate_cmd_test.go (90 lines) — 5 tests: stub returns
verdict, empty name rejected, failure wrapped, UNKNOWN status
for missing gate, LogTail surfaced.
cli/docs/COMMANDS.md regenerated.
Time: ~9 min. LOC: 191. Tests: 5. Within template band.
6 of 14 production adapters now CLI-exposed:
loop history + ci latest/recent + corpus inject + operator
record/list + harness status + gate run.
8 adapters remain unexposed; expose ad-hoc.
Cycle 150 / template-applied CLI-wiring mode — 3rd consecutive
template application. Compounding rate is steady: ~1 adapter per
~8-10 min cycle.
Cycle 149 applies the cycle-147 template to a 5th adapter:
productionHarness (cycle 111). Mirrors cycle 148's operator surface
exactly — second consecutive validation of the template's
predictive value.
New surface:
ao harness status [--skill <name>] [--out-of-sync-only]
Wraps productionHarness — emits one HarnessSkillSync per
(skill, harness) pair (claude vs codex), each with SHA-256 content
hash and OutOfSync flag. Typed alternative to parsing
scripts/audit-codex-parity.sh output.
Live smoke verified: 'ao harness status --out-of-sync-only' returns
empty against the repo's current state (all skills in sync), and
'ao harness status --skill evolve' returns both claude+codex entries
for the evolve skill.
Template adherence vs cycle-147 spec: ✓ on all 5 principles + the
post-filter pattern proven (--out-of-sync-only filters AFTER the
port call, not as a port arg — keeps the port narrow).
New files:
- cli/cmd/ao/harness_cmd.go (108 lines) — harnessCmd + status
subcommand + 2 flags + injectable statusFn.
- cli/cmd/ao/harness_cmd_test.go (107 lines) — 5 tests: emits all,
--out-of-sync-only filters, empty results → 0 bytes, all-in-sync
with filter → 0 bytes, error wrapping.
cli/docs/COMMANDS.md regenerated.
5 of 14 production adapters now CLI-exposed (loop history + ci
latest/recent + corpus inject + operator record/list + harness
status). 9 adapters remain unexposed — expose ad-hoc as needs
arise.
Time: ~8 min. LOC: 215. Tests: 5. Squarely within template band.
Cycle 149 / template-applied CLI-wiring mode (cycle 148 + 149 are
the 2-cycle proof that the template works for arbitrary adapters).
Cycle 148 ships the 4th CLI surface using the cycle-147 template
captured immediately after the 3-cycle slice arc (144-146). First
test of the template's predictive value: a new adapter exposure in
~10 min using the documented pattern without re-deriving the shape.
New surface:
ao operator record --kind <kind> [--subject S] [--note N]
ao operator list
Wraps productionOperator (cycle 110) — writes/reads OperatorIntent
records to .agents/operator/intents.jsonl. Useful as a durable
operator-decision ledger: halt, rescope, handoff records survive
session boundaries.
Template adherence (vs cycle-147 spec):
- ✓ Parent noun (operator) + verb subcommands (record, list)
- ✓ Injectable function fields (recordFn + listFn) on options bag
- ✓ Line-delimited JSON output for list
- ✓ Error wrapping with command name
- ✓ Build + smoke verification (ao operator --help renders)
- New nuance: --kind marked required via cobra's MarkFlagRequired
(per port contract that rejects empty Kind)
- New nuance: operatorIntentsPath helper centralizes the
.agents/operator/intents.jsonl path resolution + mkdir-parent
New files:
- cli/cmd/ao/operator_cmd.go (149 lines) — operatorCmd parent +
operatorRecordCmd + operatorListCmd + 4 helper functions.
- cli/cmd/ao/operator_cmd_test.go (107 lines) — 6 tests covering
empty-kind rejection, stub-called, error-wrapped, list emits
intents, empty list, error wrap on list.
Total: 256 LOC + 6 tests — within the cycle-147 spec's 250-335 LOC
band. Time: ~9 min. Template predicts costs accurately.
cli/docs/COMMANDS.md regenerated.
soc-y5vh-style follow-up: this exposes the 4th of 14 production
adapters via CLI. 10 remain (Citation, Harness, ClaimEvidenceBinder,
GateRunner, FactoryAdmission, ClaimEvidence, EventBus,
CorpusWriter, LoopWriter, FindingCompiler). None are blocking any
queued bd; expose them as ad-hoc needs arise.
Cycle 148 / template-applied CLI-wiring mode (cycle-147 spec
validated on first real use).
Cycle 146 ships slice 3 of soc-y5vh.5. The 3-slice prerequisite work
(cycles 144 + 145 + this) is now complete — 3 production adapters
exposed via the operator-facing CLI:
ao loop history — productionLoopReader (cycle 108)
ao ci latest — productionCIStatus (cycle 117)
ao corpus inject — productionCorpusReader (cycle 112) ← THIS
This unblocks soc-y5vh.1 (Step 0 prior-failure injection),
soc-y5vh.2 (Step 1.5 healing classifier), and soc-y5vh.4 (script
wrapper) — each can now consume the typed adapter without
re-implementing the file walk / gh shellout / jsonl scan.
New files:
- cli/cmd/ao/corpus_inject.go (114 lines) — corpusInjectCmd added
as subcommand under existing 'ao corpus'. Flags: --query, --root
(default .agents/learnings/), --limit (default 10).
corpusInjectOptions struct with injectable injectFn (mirrors
cycle 144 historyFn + cycle 145 statusFn patterns).
- cli/cmd/ao/corpus_inject_test.go (5 tests) — stub-based +
live-root walk + limit-respected + empty-results + error-wrap.
cli/docs/COMMANDS.md regenerated.
End-to-end smoke verified:
$ ao corpus inject --root docs/learnings --query "wire-up" --limit 2
{"Path":"docs/learnings/2026-05-13-bc-ports-wire-up-arc.md",...}
The cycle-122 wire-up-arc learning IS the top match for "wire-up",
which is the right ranking outcome.
soc-y5vh.5 epic prerequisite COMPLETE. Tree status:
✓ soc-y5vh.5 (this commit closes)
○ soc-y5vh.1/.2/.4 (now unblocked)
○ soc-y5vh.3 (separate scope — Hypothesis + Convergence ports)
3-cycle slice arc summary:
Cycle 144: ao loop history (~10 min / 335 LOC / 6 tests)
Cycle 145: ao ci latest+recent (~ 8 min / 258 LOC / 4 tests)
Cycle 146: ao corpus inject (~ 8 min / ~230 LOC / 5 tests)
The repeated cycle-shape across 3 unrelated adapters proves the
CLI-wiring pattern is broadly applicable. Future production
adapters just need to follow the same parent-noun + verb-subcommand +
injectable-fn shape.
Cycle 146 / soc-y5vh.5 slice-3-of-3 + EPIC-CLOSE mode.
Cycle 145 ships the second slice of soc-y5vh.5: 'ao ci' command
group with two subcommands wired through productionCIStatus
(cycle 117 adapter). Mirrors cycle 144's 'ao loop history' shape.
New subcommands:
- ao ci latest <sha> — most recent CI run for the given commit;
emits empty when no run exists
- ao ci recent --limit N — last N runs (any sha; default 10, cap 50)
Wraps the cycle-117 adapter which itself wraps 'gh run list --json
...'. Output is line-delimited JSON, one CIRun per line — composable
with jq, awk, grep.
New files:
- cli/cmd/ao/ci.go (138 lines) — ciCmd parent + ciLatestCmd +
ciRecentCmd; ciStatusOptions struct with injectable statusFn
for tests (mirrors cycle 117's runGH pattern and cycle 144's
historyFn).
- cli/cmd/ao/ci_test.go (4 tests) — stub-based: latest emits 1
run, latest empty emits 0 lines, recent emits multiple, errors
wrapped with "ci status:" prefix.
cli/docs/COMMANDS.md regenerated.
Pattern reused from cycle 144:
- Parent cmd as a noun (loop, ci); subcommands as verbs (history,
latest/recent)
- Injectable function field for test stubs (so tests don't need
real gh or temp dirs)
- Line-delimited JSON output for shell-script composability
soc-y5vh.5 progress: 2 of 3 slices shipped (LoopReader + CIStatus).
Remaining: ao corpus inject via productionCorpusReader (cycle 112).
After slice 3 closes, soc-y5vh.1/.2/.4 unblock.
Cycle 145 / soc-y5vh.5 slice-2-of-3 mode.
Cycle 144 ships the first slice of soc-y5vh.5: the new 'ao loop'
command group with 'ao loop history' as its first subcommand. This
is the first cobra command that exposes a production port adapter
(productionLoopReader, cycle 108) to the operator surface.
Why this matters: cycle 143 audit found that all 14 production
adapters were internal-only — no CLI surface invoked them outside
tests. This was the latent-value problem from cycle 122's wire-up
learning. soc-y5vh.5 (cycle 143 filed) was the operator surface
that closes that loop. This commit ships the first 1 of 3 planned
subcommands.
New files:
- cli/cmd/ao/loop.go (130 lines) — loopCmd + loopHistoryCmd. Three
ways to query the history:
--latest emit only the most recent entry
--limit N emit at most N most-recent
--start S --end E emit cycles S..E inclusive
Output is line-delimited JSON (one CycleEntry per line). Wired
through productionLoopReader (cycle 108) reading
.agents/evolve/cycle-history.jsonl.
- cli/cmd/ao/loop_test.go (6 tests) — temp-dir fixtures, latest +
limit + range slicing, missing-file empty output, injectable
historyFn for test stubs, error wrapping.
Verified end-to-end against this session's actual cycle-history.jsonl:
$ cli/bin/ao loop history --latest
{"Number":143,"Mode":"prerequisite-audit-and-bd-decomposition",
"Result":"improved",...}
cli/docs/COMMANDS.md regenerated via scripts/generate-cli-reference.sh.
Anti-pattern caught (cycle-126 lesson, applied to a name collision):
- Initial helper named `loadCycleHistory` collided with an existing
function of the same name in cli/cmd/ao/metrics_health.go. go vet
caught it; renamed mine to `loadCycleHistoryViaPort`. Grep BEFORE
naming helpers in cli/cmd/ao/ — the package is large and
collisions are easy.
Future slices of soc-y5vh.5:
- ao corpus inject (productionCorpusReader, cycle 112)
- ao ci latest <sha> (productionCIStatus, cycle 117)
- Each is a separate cycle; same shape as this one (cobra add +
thin wrapper + tests + COMMANDS.md regen).
Cycle 144 / soc-y5vh.5 slice-1-of-3 mode.
Closes soc-ymph.11 — Directive D11 (Corpus durability snapshot/restore).
Why
- Routine cleanup periodically wipes most of .agents/. Without a
durable copy, the corpus moat claim becomes fragile every time the
operator runs maintenance. soc-rv5p documented the 2026-05-07
incident that motivated this work.
What
- cli/cmd/ao/corpus_snapshot.go: two new subcommands.
* ao corpus snapshot — tar.gz the .agents/ tree into
$AGENTOPS_CORPUS_SNAPSHOT_DIR (default ~/.agentops/corpus-snapshots),
write a sidecar .manifest.json with file_count, total_bytes,
sha256, RFC3339 created_at. Atomic via tmp+rename.
* ao corpus restore — extract a snapshot tarball, with path-
traversal defense, --from/--latest source resolution, --into
destination (default .agents), --overwrite gate that moves the
existing tree to .agents.bak-<ts>/ before extracting and only
removes the backup after a successful extract.
- scripts/check-corpus-freshness.sh: structural freshness gate.
Fails when the newest tarball in the snapshot dir is older than
AGENTOPS_CORPUS_FRESHNESS_DAYS (default 7). Skips cleanly when
no snapshot dir or no tarballs (greenfield boxes); honors
AGENTOPS_CORPUS_FRESHNESS_SKIP=1.
- GOALS.md: new gate row corpus-freshness, weight 4.
- .github/workflows/validate.yml: new validate-corpus-freshness job
(always-on; sets the SKIP env on CI runners since they don't carry
a snapshot dir). Registered in summary.needs[] and summary echo
per validate-ci-policy-parity contract.
- scripts/pre-push-gate.sh: new always-on check 22g. Fast (<100ms)
in the SKIP path; real teeth on operator boxes with a snapshot
dir.
- AGENTS.md: CI Jobs row for validate-corpus-freshness.
- tests/scripts/pre-push-gate.bats: stub for the new gate script.
- cli/docs/COMMANDS.md: regenerated to include corpus snapshot/restore
(cobra-conformance test would fail otherwise).
Round-trip smoke
- Snapshot of a 2-file .agents/ tree round-trips byte-identical
through tar.gz + sha256 manifest.
- check-corpus-freshness.sh: SKIP (no dir) → SKIP (env) → PASS
(fresh) → FAIL (10d old > 7d threshold). All four paths.
- bats: 51/51 ok.
- go test ./cmd/ao/... -run "TestCorpus |TestCobra" : 165 pass.
- validate-ci-policy-parity: PASS (53 jobs, 7 non-blocking).
- pre-push --fast (PRE_PUSH_SKIP_EVAL=1 for the soc-l4yt canary flake):
both passes green with "ok corpus freshness".
Companion bead: soc-rv5p (closed) — original incident.
Propagate the council-consolidated positioning thesis across the doc tree.
8/8 cross-vendor council verdict (.agents/council/2026-05-07-validate-positioning-thesis-report.md)
identified the substrate-leads framing as the durable 24-month thesis;
plugin-not-API was a 12-month wedge that contradicted the existing strategic
bet ("Knowledge is the moat. AgentOps isn't.").
Canonical thesis (now propagated):
AgentOps is a context compiler — the substrate the supermodel plugs into.
It encodes the DevOps SDLC as the CDLC, plus the operating practices of
multi-agent work: isolated context, stigmergic coordination, planner/
implementer/validator separation. Validation gates, the knowledge flywheel,
and the schedulable dream daemon are outputs of the compiler, not peer
products. The bet is sovereignty, not features.
Surface changes:
- PRODUCT.md: Mission section (substrate-leads thesis); "What the Product
Actually Is" reframed as "one substrate, three surfaces / three outputs";
Strategic Bet expanded with sovereignty answer (cross-runtime corpus,
local sovereignty, operator workflow encoding); new dedicated Lineage
section (Knowledge OS → Olympus → AgentOps → Mt. Olympus); compound-
engineering / software-factories / Greenfield 2003 named lineage; 12-factor
parallel-not-derived callout; Meadows promoted from footnote.
- README.md: hero replaced with substrate-leads framing; scheduling
reference link surfaced.
- AGENTS.md: top-level positioning blurb updated.
- CLAUDE.md: new "What this is" preamble with one-sentence thesis.
- cli/docs/HOOKS.md: CASS clarified as AgentOps-internal terminology
(not external prior art); inspired by Olympus.
- docs/strategic-direction.md: lineage hierarchy spine added under the
consolidation decision; industry parallels named as convergent.
- docs/cdlc.md: Meadows leverage-point hierarchy was already integrated;
no edit needed (worker verified existing prose covers it).
Constraints honored (per pre-mortem R1, R2, council verdict):
- No new docs/comparisons/ files created (existing vs-compound-engineer.md
referenced by link only).
- Factory's Missions / Luke / Factory AI not cited explicitly (operator
decision: internalize the planner/implementer/validator framing, don't
attribute).
- No fabricated corpus stats (sx99.9 owns that slice).
Closes soc-sx99.3.
Audit found 128/136 patterns (94%) on disk with malformed recursive-doubled
filenames like 2026-04-29-pend-2026-04-19-6a97752-19-2026-04-19-6a97752-19-…md.
Root cause: cli/internal/harvest/catalog.go promotionDestinationName
unconditionally re-prepended <rig>- on every promotion pass, even when the
source filename already started with <rig>-.
- Fix: strip pre-existing <rig>- prefixes (in a loop) before re-prefixing,
making promotion idempotent for both already-canonical and pre-corrupted
inputs.
- Regression tests: TestPromote_DoesNotDoubleRigPrefix, …TripleRigPrefix,
…RepeatedPromotionIsIdempotent. Each FAILS pre-fix, PASSES post-fix.
- New: ao patterns repair-filenames — one-shot migration. Default dry-run
(lists proposals, exits 0). --apply performs renames idempotently
(running twice = no-op). Frontmatter name field updated. Collisions
resolved by appending a suffix.
- Real-corpus dry-run on this repo: 82 of 136 patterns flagged for repair.
--apply NOT run by the agent; left for operator review.
- All 9 added tests PASS; cli build/vet/test green.
Why it matters: without clean filenames, pattern→rule promotion can never
run reliably (the 0-rules corpus is partially explained by this upstream
break).
Closes soc-sx99.7.
Add JobTypePlansProjection, JobTypeLLMWikiLoop, JobTypeEvalSuite, and
JobTypeEvalSkillDelta to the known daemon job types. Regenerate
COMMANDS.md to match. Extend TestValidateSubmitJobTypeAcceptsKnown to
cover the new types.
Phase 1: scripts/eval-agent-harness.sh wraps setup → agent CLI → score
for any workbench task. Supports --dry-run, --hooks-disabled for A/B,
--timeout, and agent-not-found graceful handling.
Phase 2: extend parseEvalRuntime() to accept claude/codex alongside
static/mock/shell. Update flag help and shell completion. Add table-
driven test covering all 5 runtime values plus empty and unknown.
Closes soc-egdg, soc-eiy4.
* feat(eval): plumb DisableHooks toggle for LID baseline-A/B (W1.1)
Wire SuiteEnvironment.DisableHooks (suite-declared) and
LiveRuntimeOptions.OverrideDisableHooks (caller-toggled) through
liveEnvironmentRecord, liveRuntimeEnv, and liveRuntimePrompt via the
new effectiveDisableHooks helper. When effective:
- liveEnvironmentRecord populates the existing HooksDisabled placeholder
- liveRuntimeEnv appends AGENTOPS_HOOKS_DISABLED=1 (already honored at
hooks/session-start.sh:7)
- liveRuntimePrompt appends a "do not load skills" constraint sentence
Round-trip JSON snapshot tests for SuiteEnvironment + EnvironmentRecord
per f-2026-04-26-001. Internal helpers for the prompt/env wiring.
Issue: soc-x5yz / W1.1
Plan: .agents/plans/2026-05-02-lid-primitives-eval-integration.md
* feat(eval): --baseline-mode flag + DeltaScorecard runner (W1.2)
Add `ao eval run --baseline-mode={skill-on,skill-off,both}`. When `both`,
runs the suite twice (skill-on, then skill-off via OverrideDisableHooks)
and synthesises a DeltaScorecard with per-case pass/fail delta + aggregate
score delta. cobra ValidArgs reject invalid mode values. New `--delta-out`
writes the scorecard JSON. Per-leg run records get `-skill-on`/`-skill-off`
suffixed paths and run-ids when caller supplies --out / --run-id, so the
two leg artifacts are preserved alongside the scorecard.
Wires OverrideDisableHooks through RunOptions → environmentRecord so the
deterministic SIL path mirrors the live path's HooksDisabled provenance
(W1.1 wired the live path; this commit completes the deterministic side).
Tests: AllBaselineModes/IsValidBaselineMode, deltaSign triad, computeDelta
with mixed pass/fail/missing cases, appendBaselineSuffix path-mangling.
Issue: soc-x5yz / W1.2
Plan: .agents/plans/2026-05-02-lid-primitives-eval-integration.md
* feat(eval): wire DisableHooks into deterministic engine + LID demo fixture (W1.3)
Engine: when OverrideDisableHooks is set, mutate the local suite copy so
runtimeRecord, environmentRecord, and the case command env all see the same
effective DisableHooks state. Inject AGENTOPS_HOOKS_DISABLED=1 into the case
command env (parallels the live-runtime path from W1.1) so SIL fixtures can
gate behavior on the kill-switch.
Demo fixture: evals/agentops-core/lid-primitives-demo.json — two shell cases
that produce the smallest measurable delta proving the baseline-A/B wiring
works end-to-end. Smoke run reports +0.5 aggregate delta:
ao eval run evals/agentops-core/lid-primitives-demo.json --baseline-mode=both
→ skill-on=1.0000 (pass) skill-off=0.5000 (fail) delta=+0.5000 cases=2
Issue: soc-x5yz / W1.3
Plan: .agents/plans/2026-05-02-lid-primitives-eval-integration.md
* docs(eval): contract + code-map for LID baseline-A/B (W1.4)
- docs/contracts/eval-baseline-ab.md: --baseline-mode semantics, what
skill suppression actually disables (and what it doesn't), DeltaScorecard
schema, when to use which mode, SIL vs HIL/VIL scope (HIL/VIL deferred),
backward-compat guarantees, regression guards.
- docs/code-map/eval-lid-primitives.md: file inventory of every Wave 1
surface, test coverage map, live smoke recipe, recipe for adding new
baseline-A/B-eligible suites, open follow-ups (Wave 2 anchor namespace,
HIL/VIL extension, release-readiness gate promotion).
Hook audit confirmed only hooks/session-start.sh:7 auto-honors
AGENTOPS_HOOKS_DISABLED today; future skill-loading hooks must honor it
or future baseline-A/B measurements will under-report.
Issue: soc-x5yz / W1.4
Plan: .agents/plans/2026-05-02-lid-primitives-eval-integration.md
* fix(daemon): Wave A durability — fsync prop, orphan-tmp sweep, snapshot dir-fsync
Three audit follow-ups from .agents/research/2026-05-02-bug-daemon-audit-and-chaos.md:
- W-A-04 (soc-58q5.1): AppendLedgerEvent fsync error propagation. Audit was
STALE — code already returned wrapped Sync error at store.go:211. Added
L2 regression test TestAppendLedgerEvent_SyncErrorPropagates via a
test-only ledgerSyncFn function-variable seam. Caught by reverting line
211 and observing the new test fail.
- W-A-09 (soc-58q5.2): rotateLedger orphan-tmp cleanup. Sweeps
ledger.*.jsonl.gz.tmp files older than 5 min at rotation start (grace
prevents racing concurrent in-flight gzip work). Cleanup failures log at
warn and do not fail rotation. L2 test TestRotation_CleansOrphanedGzTmp
pre-seeds stale + fresh tmps via os.Chtimes, asserts only stale removed.
- W-A-21 (soc-58q5.3): WriteProjectionSnapshot syncDir after rename.
Adds private syncDir helper; calls it after os.Rename(tmp, dst).
syncDir failure DOES fail the function (durability contract). L2 test
TestWriteProjectionSnapshot_SyncsParentDir confirms happy-path remains
green; injection-based negative test deferred (would require interface
threading that costs more than defense-in-depth value).
go test -race -count=1 ./internal/daemon/... green (26.7s).
* fix(ci): close out PR #212 CI failures (W1.x parity + pre-mortem ref link)
- skills/pre-mortem/SKILL.md: add the missing scope-predicate-positive-
negative-cases.md to References (fixes go-build TestSkillContract_
ReferencesLinkedInSKILLMD failure that's been carrying forward from
commit 12fa13b4).
- docs/documentation-index.md: register docs/contracts/eval-baseline-ab.md
(fixes contract-compatibility-gate orphan-contract failure).
- cli/docs/COMMANDS.md: regenerate to capture --baseline-mode and
--delta-out flags added in W1.2 (fixes cli-docs-parity diff failure).
- AGENTS.md: add the hook-output-schema-lint job introduced by 12fa13b4
to the CI jobs table (fixes validate-ci-policy-parity drift).
Local: 11899 tests pass. heal-skill --strict clean. validate-ci-policy-
parity PASS.
Issue: soc-x5yz / W1 CI closure
Upstream commits f2053294, 3597ff77, c954643f added `ao eval cleanup`,
`ao eval suite`, `ao eval task` (+ subcommands) but didn't regen the docs.
TestCobraConformance now passes again with the regenerated reference.
Orchestrator post-wave step. Mechanical updates triggered by Wave 1
landings (soc-irg1.1 through .3):
- cli/cmd/ao/cobra_commands_test.go: add 'scope' and 'skills' to both
expectedCmds lists (TestCobraCommandTreeRegistration +
TestCobraExpectedCmdsMatchRegistration), so the cobra registration
conformance test passes with the new ao subcommands.
- cli/docs/COMMANDS.md: regenerated by scripts/generate-cli-reference.sh
to include ao scope and ao skills subcommands.
- cli/embedded/hooks/{hooks.json,edit-scope-guard.sh}: re-synced via
cd cli && make sync-hooks (per CLAUDE.md sync-hooks rule). Wave 2 (I5)
pre-mortem amendment will re-verify embedded copies after the mass
refactor.
- skills/SKILL-TIERS.md: add /scope row under Primitives table.
- docs/SKILLS.md, docs/ARCHITECTURE.md, PRODUCT.md: skill counts synced
by scripts/sync-skill-counts.sh from 69 → 70 (and user-facing 60 → 61).
All Wave 1 issues now closeable. Codex parity audit passes. Full
go test ./... green.
Mac, phone, and any future non-CLI client of agentopsd previously had to
hand-roll curl POSTs to /v1/jobs. The runbooks documenting that path were
correct (X-AgentOps-Daemon-Token header, AllowedPaths /v1/jobs) but every
operator hit the same papercuts: header-name typos, non-JSON payloads, and
silently mistyped job_type strings that the daemon would queue without an
executor.
This adds `ao daemon jobs submit --type <known-type> --payload <inline|@file|@->`
sibling to the existing show/list/wait/cancel commands. Behavior:
- POSTs SubmitJobRequest{job_type, payload} to <url>/v1/jobs with the
canonical X-AgentOps-Daemon-Token header (DefaultMutationTokenHeader from
cli/internal/daemon/auth.go).
- Validates --type against the JobType enum (cli/internal/daemon/types.go).
Unknown types exit 2 with the full known-type list — scripts and the
/evolve loop can branch on the exit code without parsing stderr.
- Reads --payload as inline JSON, '@-' for stdin, or '@path' for a file.
- Outputs submitDaemonJobResponse (Accepted/JobID/JobType/Status/RequestID/
LastEventID/ProjectionStatus) in table or json format, suitable for
shell pipelining via `--json | jq -r .job_id`.
Tests in cli/cmd/ao/daemon_jobs_test.go cover:
- Happy path: real httptest fixture submits openclaw.snapshot, asserts
daemon queue contains the returned job_id (L2 integration via the same
fixture as cancel/wait tests).
- Enum validation: known/unknown/error-message coverage (L1 unit).
- Payload reading: inline, @file, empty/whitespace, and non-JSON rejection.
CLI docs regenerated via scripts/generate-cli-reference.sh; TestCobraConformance
passes.
Closes-after-validation: soc-5of.11