--reset: delete .agents/compiled/ and .hashes.json before compiling.
Use to force a full rebuild or clean up stale output from a prior
broken compile run. Safe on missing dirs (idempotent).
--repair: scan .agents/compiled/ and remove article .md files with
zero inbound [[wikilinks]]. Infrastructure files (index.md, log.md,
lint-report.md) are always preserved. Addresses the 2026-04-15
scenario where a failed compile run left fallback stubs that later
had no natural way to be cleaned up.
Both flags are standalone-capable (no LLM runtime required) and
compose with --full / --compile-only.
Tests:
- TestResetCompileOutput_RemovesDirectory
- TestResetCompileOutput_IdempotentOnMissingDir
- TestRepairCompileOutput_RemovesOrphansOnly
Regenerated COMMANDS.md for the new flag entries.
Closes na-pmx1.8.
Fixes three onboarding defects that surfaced on 2026-04-15 when running
against a global ~/.agents corpus from a non-git home directory:
1. `ao compile --full` failed in the installed bundle with
"open skills/compile/scripts/compile.sh: file does not exist". The
Makefile's sync-hooks target never copied compile.sh into
cli/embedded/skills/, so the //go:embed all:skills fallback had
nothing to fall back to. Fix: sync-hooks now seeds the script and a
regression test (TestMaterializeCompileScriptFallsBackToEmbedded)
asserts the embedded copy resolves when no local skills/ exists.
2. Headless compile implicitly required OLLAMA_HOST / OPENAI_API_KEY /
ANTHROPIC_API_KEY with no actionable error when none were set, and
ignored a locally installed `claude` CLI. Fix: resolveCompileRuntime
auto-detects the `claude` binary and selects claude-cli runtime (no
API key needed — inherits Claude Code auth). preflightCompileRuntime
fails fast with an actionable error naming the exact env var to set.
compile.sh gains a matching claude-cli backend and a --preflight flag.
3. The headless compiler concatenated all changed files into one LLM
prompt, which is unworkable on 2000+ file corpora. Fix: compile.sh
batches by --batch-size (default 25) and --max-batches (default
unlimited); ao compile propagates both flags.
Onboarding gaps:
- $quickstart now detects a global ~/.agents corpus (GLOBAL_AGENTS=true)
and, when GIT=false + AO=true, surfaces a harvest → compile →
knowledge-activation path instead of only suggesting `git init`.
- Harvest SKILL.md clarifies that promotion writes to ~/.agents/learnings/
(not ~/.agents) and adds a "which skill do I need?" decision table.
- Compile SKILL.md documents the claude-cli runtime and batching flags.
- skills-codex/compile/scripts/compile.sh wrapper now falls back through
multiple candidate paths and finally delegates to `ao compile`, so an
installed bundle without a sibling skills/ checkout still works.
Tests added:
- TestMaterializeCompileScriptFallsBackToEmbedded
- TestResolveCompileRuntime
- TestPreflightCompileRuntimeErrors (5 subtests)
- TestPreflightCompileRuntimeSuccess
- TestCompileScriptOptionsPassesBatchFlags
- TestQuickstartSkillCoversGlobalCorpus (both parity surfaces)
Verification:
cd cli && go vet ./... && go test ./... # all green
bash skills/heal-skill/scripts/heal.sh --strict # clean
bash tests/docs/validate-doc-release.sh # PASS
bash scripts/check-contract-compatibility.sh # 0 failures
bash scripts/regen-codex-hashes.sh # 3 skills rehashed
bash scripts/generate-cli-reference.sh # COMMANDS.md regenerated
Three subcommands under a new 'ao beads' command group that complement
the bd CLI without replacing it. All commands degrade gracefully when
bd is not on PATH (warn + exit 0).
## Commands
### ao beads verify <bead-id>
Reads 'bd show <id>', extracts file paths, function references, and
backticked symbols from the description (or close reason for closed
beads), and checks each citation against HEAD. Reports FRESH / STALE /
UNKNOWN status per citation.
Bare filenames (e.g. 'loop.go' with no path) are treated specially:
the verifier walks cli/, skills/, docs/, scripts/, .agents/ to find
matches and reports FRESH if unique, UNKNOWN if ambiguous (with the
resolved path suggestions), STALE if zero matches.
Exit codes: 0 clean, 1 stale found, 2 bd error.
### ao beads lint [--status=open]
Batch-runs verify across every bead matching a status filter and
aggregates results. Exit code signals overall staleness — suitable
as a weekly audit or pre-release gate.
### ao beads harvest <bead-id>
Materialises a closed bead's close reason as a learning file at
.agents/learnings/YYYY-MM-DD-<id>-<slug>.md with frontmatter. Only
operates on closed beads. --dry-run prints to stdout instead of writing.
Compresses the bd-close → learnings pipeline into one command, so
operators running 'bd close <id> --reason "..."' can immediately
promote the reason into the knowledge flywheel.
## Design
* execBD / bdAvailable are package-level function vars so tests can
inject fakes without touching PATH (pattern consistent with existing
cmd/ao test hooks).
* parseBDShow is tolerant of both open and closed bead formats. Closed
beads hide their original description and surface a 'Close reason:'
line instead; the parser captures both and Body() prefers CloseReason.
* listBeadIDs uses a permissive <rig>-<ident> grammar so it handles
flat rows, hierarchy rows (├──/└── tree chars), and future bd shape
tweaks without breaking.
* No hard dependency on bd for tests — all L2 tests mock execBD and
drive the parse/verify/render logic directly.
## Tests
cli/cmd/ao/beads_test.go (L2, 23 tests):
* beadSlugify: basic, punctuation, truncation, empty, punct-only
* parseBDShow: canonical open, closed with Close reason, empty errors
* bdShowParsed.Body: prefers CloseReason, falls back to Description
* extractCitations: file+line, function refs, backticked symbols, dedup
* verifyFileCitation: fresh, stale, line-suffix handling
* isClosedStatus: substring matching across bd status-field shapes
* listBeadIDs: flat + tree output, non-bead lines skipped
* verifyBead: bd-absent graceful degradation + end-to-end with fake
* renderLearningBody: frontmatter + body composition
cli/cmd/ao/cobra_commands_test.go:
* beads added to expectedCmds + parentExpectations (verify|lint|harvest)
## Smoke test
Ran against na-h61 (the bead closed earlier today). Found:
- 4 FRESH, 0 STALE, 1 UNKNOWN (ambiguous bare 'types.go' — resolved
to 6 candidates, correctly suggested full paths)
- harvest --dry-run produced a clean learning file with frontmatter
- lint --status=closed found 49 clean / 1 genuinely stale (na-63f.8
references summary.json/summary.md which doesn't exist anywhere)
## Files
cli/cmd/ao/beads.go (new, ~550 LOC)
cli/cmd/ao/beads_test.go (new, ~280 LOC)
cli/cmd/ao/cobra_commands_test.go (+3 lines — beads in registry)
cli/docs/COMMANDS.md (regenerated)
## Why
Closes the last 3 items of the 7-item summary table from today's
retrospective. The first 4 items (--evidence, --commit-ready,
--discovery-artifact, stale-scope planning rule) landed in 63c8b81a.
The na-h61 session earlier today showed that bead descriptions drift
from HEAD within hours of being filed. Two of the five beads I closed
today had factually wrong descriptions (na-h61 cited a nonexistent
cli/cmd/ao/fitness.go; na-khk cited a non-reproducible env leak).
'ao beads verify' catches exactly this pattern before a new session
commits to the wrong mental model.
Introduces the C3 warn-only ratchet from the Dream RunLoop Correctness
series. Warn-only mode now consumes a bounded rescue budget and falls back
to strict halting behaviour once exhausted, preventing the "warn-only
protects me forever" anti-pattern that enabled the 2026-02-22 evolve
overnight 115-cycle runaway.
New package-local primitives in cli/internal/overnight/warn_only_budget.go:
- WarnOnlyBudgetState on-disk schema v1
- ReadBudget with rescue matrix (missing → default, corrupt → default,
out-of-range → clamp)
- WriteBudget atomic (CreateTemp → Sync → Rename)
- ResetBudget / DecrementBudget helpers
- Default rescue ceiling = 3
Loop integration via RunLoopOptions.WarnOnlyBudget (*WarnOnlyRatchet).
Pointer-based opt-in preserves legacy infinite-warn-only behaviour for
the existing L1/L2 test suites that pass WarnOnly=true without a ratchet.
At most one rescue is consumed per iteration even when both regression
and plateau fire on the same pass. Halt reasons are annotated
"(warn-only budget exhausted)" when the ratchet was the reason strict
mode kicked in.
Cmd-layer wiring in cli/cmd/ao/overnight.go reads .agents/overnight/
warn-only-budget.json at run start, passes a live ratchet with a
persistence callback, and stamps WarnOnlyBudgetInitial/WarnOnlyRemaining
into overnightSummary for the morning report.
New subcommand `ao overnight warn-only reset [--initial N] [--json]`
restores the budget file to a fresh state after an operator investigates
a burned-through budget.
Tests:
- L1 warn_only_budget_test.go covers all 4 rescue-matrix paths, atomic
write round-trip, Reset semantics, and Decrement countdown.
- L1 overnight_test.go additions cover the reset subcommand (default +
--initial override + --json emission) and the ratchet literal wire-in
to RunLoopOptions, mirroring Micro-epic 2's RunID regression guard.
CLI docs regenerated via scripts/generate-cli-reference.sh. Pre-existing
failures in internal/rpi toolchain_test.go (unrelated "bushido" env var
leak on main HEAD) are out of scope.
Refs: .agents/handoff/2026-04-10-dream-runloop-correctness.md §Micro-epic 4
Rename the athena skill to compile — a descriptive name that communicates
what it actually does. Extend with Karpathy's LLM Knowledge Bases architecture:
- New compile phase: LLM reads raw .agents/ artifacts and produces interlinked
markdown wiki at .agents/compiled/ with index.md, log.md, backlinks
- New lint phase: detects contradictions, orphan pages, stale claims, coverage gaps
- Pluggable compute backend via AGENTOPS_COMPILE_RUNTIME (ollama|claude|openai)
- Hash-based incremental compilation (only recompile changed sources)
- compile.sh engine with security fixes (no shell injection, path traversal guard)
- Full rename across 93 files: skills, docs, CLI, tests, hooks, scripts, codex
Existing Mine → Grow → Defrag cycle preserved as phases within the larger
compile workflow. No vector DB — compiled wiki IS the retrieval layer.
Add --mixed CLI flag to ao rpi phased. Extend executionPacket and
phaseHandoff structs with mixed_mode_requested, mixed_mode_effective,
planner_vendor, reviewer_vendor, and mixed_mode_degraded_reason fields.
Provenance is carried across phase boundaries via handoff and persisted
in the execution packet. Downstream phases (MR-2..MR-5) will populate
effective/vendor fields. Regenerated CLI docs.
- harvest.go: use empty defaults with ~/ descriptions instead of baking $HOME
into flag defaults, resolving cli-docs-parity failures across environments
- athena-session-defrag.sh: swap stat order to try Linux stat -c first, fixing
integer expression error when macOS stat -f succeeds but returns mount path
- skills-codex/validation: replace ao codex stop with ao codex ensure-stop to
pass codex lifecycle guard validation