Commit Graph

18 Commits

Author SHA1 Message Date
Bo 62cc3b6ee0 Clear the operations-layer alignment residuals (#1054)
Closes out the six residual items #1051 disclosed: terminology residue
on non-authority surfaces, the eval command-surface fixture that failed
when executed (#{3,4} -> #{3,5}), the vacuous retrieval-quality canary
and the nightly job that ran it, the consumer-free dream config block
and its exclusive helpers, the remaining knowledge-shaped writers moved
to the scratch tier, and the MEMORY.md consumer audit.

bin/ralph still resumes legacy .agents/ralph/ checkpoints so the
documented backwards-compat contract holds without a migration; both
paths and the outside-both refusal are now tested.

Fresh author-distinct validation returned PASS with empty not_checked,
after an earlier revision failed on a dangling nightly invoker and a
back-compat test regression that were fixed and independently
re-verified.

Test-Removal-Reason: the dream config subsystem was deleted with its tests (operations-layer residuals)
2026-08-08 14:34:14 -04:00
Bo 7265fda1b1 chore(test): migrate redundant os.Setenv to t.Setenv; lower isolation ratchet 22->12 (ag-k38x #bulk-migration-setenv) (#772)
## What

Advances the test-isolation ratchet (`scripts/check-test-isolation.sh`,
shipped in #699) by driving the `os.Setenv` baseline from **22 → 12**.
Pure test-hygiene; no production-code change.

`t.Setenv` auto-restores on cleanup **and** fails fast under
`t.Parallel` — the raw `os.Setenv` form is the latent-flake landmine the
ratchet exists to retire (cf. ag-jfzs).

## Sites migrated (10 eliminated)

| File | Δ | How |
|---|---|---|
| `internal/config/config_test.go` | -6 | Collapse the `origX :=
os.Getenv(...)` + `defer os.Setenv(... restore)` block into 3×
`t.Setenv` |
| `internal/goals/measure_test.go` | -1 | Delete the redundant
`origPath`/`defer os.Setenv` — the existing `t.Setenv("PATH","")`
already auto-restores |
| `cmd/ao/rpi_reliability_test.go` | -3 | Delete 3 redundant
restore-defers wrapped around existing `t.Setenv` calls |

## The remaining 12 are intentional (not migratable)

Documented inline in the ratchet script. They cannot use `t.Setenv`:
- **TestMain** (`cmd/ao/main_test.go`,
`internal/doctor/doctor_testmain_test.go`) — no `*testing.T` in scope
(4)
- **String-literal fixtures** (`internal/doctor/fix_cliconfig_test.go`)
— `os.Setenv` appears inside generated test-program source, not a real
call (2)
- **Unset-semantics helpers** (`cmd/ao/handoff_test.go`,
`internal/lifecycle/repo_readiness_test.go`,
`internal/wiki/locator_test.go`) — these `os.Unsetenv`+restore vars;
`t.Setenv` has no unset form (6)

## Verification

- `bash scripts/check-test-isolation.sh` → `PASS … os.Setenv=12/12`
- `go build ./...` ✓ · `go vet` (touched pkgs) ✓
- `go test ./internal/config/ ./internal/goals/` → 526 passed; touched
cmd/ao tests → 3 passed

Closes-scenario: ag-k38x#bulk-migration-setenv
Bounded-context: BC5-Runtime
Evidence: scripts/check-test-isolation.sh PASS 12/12
2026-06-06 10:17:21 -04:00
Bo 6bd788d8af chore(cli): gofmt sweep — 14 unformatted files (ag-ozac #gofmt-sweep) (#717)
Mechanical `gofmt -w` across `cli/` — fixes the 14 unformatted files
surfaced by the **ag-tcf0** Go-cohesion audit. No logic change (diff is
whitespace/grouping only; `git diff -w` is ~empty).

## Verification
- `gofmt -l cli/` → empty
- `go build ./...` → passes
- Rebased onto current `origin/main`

Closes-scenario: ag-ozac#gofmt-sweep
Bounded-context: BC5-Runtime
Evidence: cli/internal/eval/types.go
2026-06-04 09:11:11 -04:00
Claude 1ab6bbb291 feat(goals): split summary into code-driven vs runtime-artifact slices
Closes the second half of ONE-TIME REPO FIX #3 from the nightly
improvement routine. The `runtime-artifact` tag was already declared
on `compile-freshness` and `compile-no-oscillation` in GOALS.md, but
the goals runner ignored the tag — both gates fed straight into the
headline `score`. Eight nightly digests in a row noted that this
inflated morning summaries by ~+8 points whenever Dream had populated
.agents/defrag/latest.json (a gitignored artifact that re-flips every
run, so its pass propagates to nothing downstream).

This change:

1. Extends `SnapshotSummary` with three lanes:
   - `score` (raw, headline) — unchanged for backward compat
   - `code_driven_*` — the same calculation restricted to goals
     without the `runtime-artifact` tag; this is the comparison
     number the nightly routine uses for fitness deltas
   - `runtime_artifact_*` — the slice tabulated separately so
     digests can still surface "RA was 0/8, now 8/8" without it
     contributing to a code-driven flip

2. Updates `computeSummary` to walk each measurement once and tally
   into both lanes simultaneously (no extra pass over the slice).

3. Adds a small `isRuntimeArtifact(tags)` predicate, case-insensitive
   and whitespace-tolerant, anchored to the canonical
   `runtime-artifact` tag string.

4. Tests cover: mixed corpus produces both Score and CodeDrivenScore
   correctly; all-runtime-artifact corpus keeps CodeDrivenScore at 0
   without dividing-by-zero; the predicate handles nil/empty/Case-
   sensitivity/whitespace/multi-tag inputs.

End-to-end: today's measurement now reports `code_driven_score:
91.43` alongside `score: 92.04`. Going forward the headline
comparison goes off the code-driven number and runtime-artifact
flips are reported in their own column.

Backward-compatible JSON: existing readers that only consume
`summary.score` keep working; new fields are additive.
2026-05-05 06:57:23 +00:00
Claude 1ed5471576 feat(goals): SKIP exit code 77 + flywheel-compounding dormant precondition
Closes ONE-TIME REPO FIX #2 from the nightly improvement routine. Goes
back to finding f-2026-04-30-002, which the flywheel-compounding gate
itself has been pointing at in its FAIL output for the last six runs:
"corpus dormant; flywheel-compounding has no signal to evaluate."

Two coordinated changes:

1) Goals runner accepts skip-by-exit-code (`cli/internal/goals/measure.go`).
   Adds the SkipExitCode constant (77, autotools convention) plus an
   `isSkipExit` predicate. classifyResult is restructured around the
   ExitError shape so:
   - exit 0 → pass
   - context deadline / canceled → skip
   - exit 77 → skip
   - any other non-zero → fail
   Tests cover all three paths plus a parameterized non-77 fail check
   over exit codes 1, 2, 7, 76, 78, 99 to lock in that SKIP stays
   opt-in (no accidental skips from generic `set -e` killers).

2) flywheel-compounding gate (`scripts/check-flywheel-compounding.sh`)
   uses the new contract for the dormant-corpus precondition. When σ=0
   AND ρ=0 AND citations_this_period=0 — the *fully dormant* state,
   distinct from σ=0 with citations elsewhere or ρ=0 with σ>0 — the
   gate now exits 77 with a SKIP message. The goals runner records
   that as `skip`, not `fail`, so the gate stops dragging the headline
   fitness number every nightly. The flywheel-compounding goal flipped
   from fail (-3 weight) to skip (excluded from numerator + denominator)
   on this branch's measurement, taking the headline from 89.66% to
   92.04% (+2.38 pp) without any contract change.

   Falls back to the old FAIL diagnostics — including the multi-session
   verdict surface — once the corpus has any signal at all. The moment
   any session runs `ao lookup --cite`, the precondition stops firing
   and the gate measures real flywheel health again. Override available
   via FLYWHEEL_SKIP_DORMANT=0 for dev iteration.

This is the *quarantine-by-precondition* path, preferred over a static
`quarantined: true` flag in goals.yaml. Real regressions still surface
the moment the corpus has signal; only "no signal at all" returns SKIP.

End-to-end verification:
- `cli/bin/ao goals measure --goal flywheel-compounding --json` →
  result="skip", output starts with "SKIP: σ=0 ρ=0 — corpus dormant…"
- Full measure: failing=2 (was 3), skipped=1 (was 0), score 92.04%
  (was 89.66%).
2026-05-05 06:50:20 +00:00
Boden Fuller 1a2ba1d56a fix: bound goals measurement runtime 2026-05-02 12:15:11 -04:00
Bo 5363a6384f Nightly 2026-04-30 — 10 productive cycles, 0 goal flips, +2 findings (#187)
* chore(triage): mark 4 stale items + 0 stale packets consumed 2026-04-30

https://claude.ai/code/session_01SoXsYqmcbntjCoLdiET8P9

* chore(evolve): stale-audit + dream-curator-degraded finding (2026-04-30)

Probe-stale rate this run = 66% (2/3 Dream packets), above the 30% MUST-spend
trigger and the 50% finding threshold. One stale-audit cycle spent here.

Marks 2 stale Dream packets consumed in next-work.jsonl:
- dream-df960e173c38bb56 — "Decompose skills/crank/SKILL.md to under 248-line
  limit": claim is fictional; check-skill-size.sh thresholds are warn>500
  fail>800; crank=660 → WARN, not FAIL. Same packet was probed stale on
  nightly/2026-04-29 (see PR #177 digest).
- dream-476e66319e8d18d3 — "Investigate GitHub-only agentops-eval-advisory
  failures": already addressed by merged PR #172 (commit 67a783ac); also
  marked consumed in still-open triage PR #176. Curator re-emitted as fresh.

Files f-2026-04-30-001.md (dream-curator-degraded) under .agents/findings/
escalating from per-packet noise to curator-level. Recommends extending
probeDreamPacketStaleness (cli/cmd/ao/overnight_packets.go:195) to detect
skills/<name>/SKILL.md and schemas/<x>.json tokens analogously to the existing
scripts/<x>.sh extractor, and to cross-check item.ID against open triage PRs'
consumed marks before emit.

This cycle is bookkeeping (1-stale-audit cap fires); productive cycles follow.

* fix(dream-curator): extend probe-staleness to skills/SKILL.md, schemas/, line-limit claims

Closes f-2026-04-30-001 (dream-curator-degraded). The curator's
probeDreamPacketStaleness was emitting packets the nightly's 5-second
inline probe rejected as stale on consecutive nightlies (e.g. "Decompose
skills/crank/SKILL.md to under 248-line limit" — claim is fictional vs
scripts/check-skill-size.sh thresholds warn>500 fail>800). The probe was
too narrow: only scripts/<x>.sh tokens were extracted from title/command.

Changes:

- extractScriptsRef → thin wrapper over generalized extractRepoRef
  (prefix, suffix). Same termination chars (whitespace, quote, paren,
  backtick, newline) so existing scripts/<x>.sh detection is byte-
  equivalent.
- probeRepoRefTokens — new helper that scans title + morning_command
  for scripts/*.sh AND schemas/*.json tokens.
- probeSkillLineLimitClaim — new helper that detects "skills/<name>/
  SKILL.md" + numeric "<N>-line" pattern and treats the packet as stale
  when the file is below the canonical 800-line FAIL threshold (lines
  vary; warn=500, fail=800 per scripts/check-skill-size.sh).
- extractSkillLineLimitClaim — extracts the (path, ok) tuple, requires
  both a skills/<name>/SKILL.md token AND a "<digit>-line" phrase so
  legitimate "Add a section to skills/foo/SKILL.md" packets are not
  flagged.
- countFileLines reuses the existing helper in doctor.go (delegates to
  quality.CountFileLines).
- probeDreamPacketStaleness orchestrates the three new helpers; CC drops
  back below the 14-line gocyclo warn threshold.

Tests:

- TestProbeDreamPacketStaleness_SchemaRef — schemas/*.json detection.
- TestProbeDreamPacketStaleness_SkillLineLimitClaim — fictional-limit
  pattern (this run's 248-line claim) is suppressed when actual file
  is <800 lines.
- TestProbeDreamPacketStaleness_SkillRefWithoutLineLimit — packets
  that mention skills/<name>/SKILL.md without a numeric line-limit
  claim are NOT flagged ("Add a section to ..." passes through).
- TestExtractRepoRef_TerminationCharacters — table-driven coverage of
  the generalized extractor's termination behavior.

End-to-end verification: rebuilt binary + reran `ao overnight start
--max-iterations 1 --warn-only`. Curator now selects 3 different
packets (the stale ones marked consumed in cycle 1 stayed out of the
candidate pool), and no new packets trigger the extended extractors —
behavior is observable and conservative.

* fix(goals/flywheel-compounding): surface multi-session corpus diagnostic + propose corpus-active precondition

Heavy-goal observability cycle for `flywheel-compounding` (W=8). Per the
4-attempt history (PR #165 observability, PR #174 rich diagnostic, PR #177
quarantine W=8→3, this run today's observability strengthening), the gate
genuinely cannot be moved by single-session work because total citations
in the 7-day measurement window remain 0.

Defensible heavy-goal cycle per run-brief definition (b): documented
investigation proving corpus-state binding paired with an observability
improvement.

Changes:

- `scripts/check-flywheel-compounding.sh`: when σ=0 ρ=0, in addition to
  the existing dormant-corpus hint, surface
  `golden_signals.{trend_verdict,concentration_verdict,overall_verdict}`,
  `metrics.{citations_this_period,total_artifacts,learnings_created}`,
  and the period range. Adds a labelled "multi-session-bound:" line so
  operators see at a glance the gate is corpus-state bound without
  running `jq` against the JSON manually. Diagnostic only fires on the
  σ=0 ρ=0 branch — ρ=0-only and generic-fail branches are unchanged
  (existing tests cover that boundary).

- `tests/scripts/check-flywheel-compounding.bats`:
  * existing σ=0 ρ=0 test gains a "multi-session-bound" assertion;
  * new test "FAIL with σ=0 AND ρ=0 surfaces verdict + period block when
    payload provides them" exercises the full diagnostic against a
    realistic payload and asserts each emitted field by name + the
    finding citation.

- `.agents/findings/f-2026-04-30-002.md` (force-tracked): new finding
  building on `f-2026-04-29-001.md` (PR #177). Documents that this
  run is the 4th consecutive failed heavy-goal attempt and proposes
  a corpus-active precondition (`if total citations == 0 in window AND
  total_artifacts > 0: skip with reason='corpus-dormant'`) as the
  durable remediation. Also records the run-brief stop clause:
  attempt 4 binds "stop attempting heavy-goal cycles on this goal for
  the rest of this run" — subsequent cycles pivot to disjoint work.

The goal still fails (the metric does not move from this commit alone —
moving it requires sustained citation activity across many sessions, OR
the corpus-active precondition's implementation). This cycle improves the
diagnostic so operators stop re-attempting the same goal across nightlies.

* test(cmd/ao): replace defer/t.Cleanup os.Chdir with t.Chdir (6 sites, 3 files)

Generator-layer test hygiene cycle. Continues the t.Chdir migration started
in PR #177 (which covered 5 cmd/ao test files: plans, dedup, config,
metrics_flywheel, metrics_health). This cycle picks up disjoint files so
PR #177 and this nightly do not conflict on the same _test.go.

Files migrated (6 sites):
- batch_forge_test.go (3 sites): TestRunForgeBatch_NoPendingTranscripts,
  TestRunForgeBatch_DryRunAppliesMaxLimit, TestRunForgeBatch_ProcessesTranscript.
  In each, replaces the 4-line block `origDir, err := os.Getwd(); ...
  os.Chdir(tmpDir); ...; t.Cleanup(func() { _ = os.Chdir(origDir) })`
  with `t.Chdir(tmpDir)`. Subsequent `err = runForgeBatch(...)` becomes
  `err := runForgeBatch(...)` (the prior implicit declaration came from
  the os.Getwd line).
- batch_promote_test.go (1 site): TestRunBatchPromote_NoPendingCandidates,
  same pattern.
- cobra_commands_test.go (2 sites): TestCobraStatusCommand/json_not_initialized
  and TestCobraSeedCommand. Pattern is the simpler `defer func() { _ =
  os.Chdir(orig) }()` form; collapses to `t.Chdir(...)`.

Net: -32 lines, +0 logic change. `go test -count=1 ./cmd/ao/...` passes;
`go vet ./...` clean; pre-push fast gate passes; full goals measure
unchanged (17 pass / 2 fail — the two open-state failures are
flywheel-compounding W=8 corpus-bound and go-complexity-ceiling W=6
in-flight via PR #177).

* test(goals,doctor): replace defer/cleanup os.Chdir with t.Chdir (20 sites, 3 files)

Generator-layer test hygiene cycle, continues PR #177's t.Chdir migration
on disjoint files (PR #177 covered cmd/ao tests; this cycle covers
internal/goals tests + the remaining doctor_test sites).

Files migrated (20 sites):

- cli/internal/goals/commands_test.go (17 sites): the per-package
  `chdir(t, dir) func()` helper is gone — every call site was the same
  exact two-line `cleanup := chdir(t, tmp); defer cleanup()` pattern,
  collapsed to `t.Chdir(tmp)`. Helper definition removed.
- cli/internal/goals/measure_test.go (1 site):
  TestGitSHA_OutsideGitRepo — the four-line origDir/Chdir/defer block
  collapsed to one line.
- cli/cmd/ao/doctor_test.go (2 sites): TestCheckHookCoverage and
  TestFallbackReasonSurfaced — both used the seven-line
  `oldWD, err := os.Getwd(); ... t.Cleanup(...)` pattern; collapsed to
  one line each.

Net: +20 lines, -74 lines. All package tests pass (`go test ./...`),
`go vet ./...` clean, fast pre-push gate passes, fitness still 17 pass
/ 2 fail (W=8 flywheel-compounding corpus-bound + W=6 go-complexity-
ceiling in-flight via PR #177).

* test(cmd/ao/index): replace 4 chdir blocks with t.Chdir

Generator-layer test hygiene. Continues t.Chdir migration on the
disjoint cli/cmd/ao/index_test.go (PR #177 covered different test files;
this file is independent so the migration does not conflict).

4 sites migrated (TestRunIndex_WriteMode/CheckMode_Stale/JSONOutput/
SingleDir): each had the 8-line `prevWD, err := os.Getwd(); ... ;
t.Cleanup(func() { _ = os.Chdir(prevWD) })` block, collapsed to a
single `t.Chdir(tmp)` call. The trailing bare `err = runIndex(...)`
that previously reused the `err` declared by `os.Getwd` is now
`err := runIndex(...)` (the test's `err` is now scoped to that
single assignment, which is fine since each subsequent use is a
read, not a reassignment).

Net: -36 lines, +8 lines. All cmd/ao tests pass; vet clean; goals
measure unchanged (17 pass / 2 fail).

* test(agents): fixture-lock parity between Go + shell allowlist parsers

Resolves the L58 next-work item from epic ag-0af ("Centralize or
fixture-lock agents write-surface scanner parity"). The two parsers —
parseAgentsAllowlist in cli/cmd/ao/agents.go and the awk|sed|sort -u
pipeline in scripts/check-agents-write-surfaces.sh — were independently
maintained with no test that exercises them on the same input. Drift in
either side could let the CI gate (shell) and `ao agents inspect` (Go)
disagree about the catalogued allowlist.

Adds TestParseAgentsAllowlist_ShellParity in cli/cmd/ao/agents_test.go.
The test:

1. Defines a fixture covering every meaningful boundary the parsers
   must agree on:
   - BEGIN/END marker lines.
   - Blank lines inside the block.
   - Inline `   # comment` suffixes (whitespace before `#`).
   - Full-line `# comment` lines.
   - Duplicate entries.
   - Sort order.

2. Runs parseAgentsAllowlist on the fixture (Go side).

3. Runs the canonical 9-line shell pipeline from
   check-agents-write-surfaces.sh (lines 62-70) on the same fixture
   via `bash -c <pipeline>` with the fixture on stdin.

4. Asserts both outputs are identical AND match a hand-checked
   ground-truth list.

Skips on systems missing bash/awk (defensive). The fixture-lock means
any future change to either parser must keep both in step or fail this
test.

Build clean; vet clean; full cmd/ao test suite passes; pre-push fast
gate passes; goals measure unchanged (17 pass / 2 fail).

* docs(skill/plan): default-include skills-codex mirror in plan template

Resolves L57 next-work item from epic 2026-04-19-rpi-dag-hardening
("Plan template: default-include skills-codex mirrors"). The plan
template's "Files to Modify" section had no guidance about the
skills-codex mirror, so plans that touched skills/<name>/SKILL.md often
silently skipped skills-codex/<name>/SKILL.md, producing parity drift
that scripts/audit-codex-parity.sh would later flag.

Adds a "Skills-codex parity" callout under the "Files to Modify" section
in both:
- skills/plan/references/plan-document-template.md (canonical agentops
  plan template)
- skills/plan/references/templates.md (generic service plan template)

The callout is brief (5 lines), cites the audit script, and is placed
directly under the "Files to Modify" table where authors will see it
when filling the section in.

Marks the next-work item consumed in .agents/rpi/next-work.jsonl with
triage_evidence pointing to the two edited templates. Schema validates.

No code changes; doc-only. Goals measure unchanged.

* test(internal): replace os.Chdir/Getwd helpers with t.Chdir (19 sites, 2 files)

Generator-layer test hygiene cycle. Continues t.Chdir migration on
disjoint internal/ packages. PR #177 covered cmd/ao test files; this
cycle handles internal/search and internal/ratchet.

- cli/internal/search/constraint_test.go (18 sites): every usage of the
  three-line `prev, _ := os.Getwd(); defer func(){_ = os.Chdir(prev)}();
  _ = os.Chdir(tmp)` pattern collapses to `t.Chdir(tmp)`. Pattern was
  identical at every call site so a single replace_all captured them.
  No err shadowing or downstream `prev` references — the `_` discards
  in the original pattern proved the variable wasn't observed elsewhere.

- cli/internal/ratchet/gate_test.go (1 helper, 2 call sites): the
  package's `chdirTemp(t, dir)` helper had a 14-line manual save/restore
  using `os.Getwd` + `t.Cleanup`. Replaced the helper body with a single
  `t.Chdir(dir)` call. The two callers (line 646, 967) keep using the
  helper unchanged, so the migration is internal to the helper.

Net: -24 lines, +7 lines. Build clean, vet clean, both packages' tests
pass, fitness 17 pass / 2 fail (W=8 flywheel-compounding corpus,
W=6 go-complexity-ceiling in-flight via PR #177).

The rpi/worktree_test.go remaining os.Chdir sites are intentional
subprocess-helper code (not test cleanup) and were left unchanged.

* test(cmd/ao/extract): replace defer+os.Chdir blocks with t.Chdir (7 sites)

Generator-layer test hygiene. Continues t.Chdir migration on disjoint
files (PR #177 covered different cmd/ao tests). The 7 sites in
extract_test.go all used the same identical 5-line pattern:

    origDir, _ := os.Getwd()
    defer func() { _ = os.Chdir(origDir) }()
    if err := os.Chdir(tempDir); err != nil {
        t.Fatal(err)
    }

The `_` discards err from os.Getwd and the `if err := ...` block has
its own scope, so no err-shadowing risk; a single replace_all swept
all sites cleanly.

Net: -28 lines, +7 lines. Build clean, vet clean, full cmd/ao test
suite passes (29.7s), fitness 17 pass / 2 fail.

* test(cmd/ao/goals): replace defer+os.Chdir with t.Chdir (4 sites)

Generator-layer test hygiene. Continues t.Chdir migration on disjoint
test files. Both goals_test.go and goals_validate_test.go used the
identical 5-line `origDir, _ := os.Getwd(); defer func()...; if err :=
os.Chdir(...)` pattern that the previous migrations targeted; replace_all
caught all 4 sites cleanly.

- cli/cmd/ao/goals_test.go (3 sites)
- cli/cmd/ao/goals_validate_test.go (1 site)

Net: -20 lines, +4 lines. Build/vet/test all pass; fitness 17/2
unchanged.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-30 16:02:43 -04:00
Bo 0f8dbee992 fix(nightly): ship 5 retrospective code fixes (truncate, standards gate, probed_stale_at, dream-probe, bd-install) (#156)
* fix(goals): preserve diagnostic tail in truncateOutput

Head-only truncation at 500 runes cut the operator hint off the end of
gate output. The 2026-04-26 nightly retrospective showed flywheel-
compounding's "sessions must use 'ao lookup --cite ...'" tail being lost
mid-word for verbose runs.

New shape: when input exceeds 500 runes, keep first 200 + truncation
marker + last 200 runes. Short inputs untouched. Verified against live
ao goals measure --json — six long-output gates (flywheel-proof,
hook-preflight, go-cli-tests, contract-compatibility, install-smoke,
flywheel-lifecycle) now expose both their failure label and their
trailing fix-it.

Source: 2026-04-26 nightly retro task 1.

* feat(ci): add standards-injector reference completeness gate

hooks/standards-injector.sh fails open when a mapped <lang> is missing
its reference file. That's how `.js` lost standards inject for weeks
until the 2026-04-26 nightly caught it. New gate parses the case
statement, asserts every mapped lang has skills/standards/references/
<lang>.md, and runs in pre-push and CI.

Wires:
- scripts/check-standards-injector-completeness.sh (new)
- scripts/pre-push-gate.sh (slot 27b under hook category)
- .github/workflows/validate.yml (parallel job + summary deps)
- tests/scripts/check-standards-injector-completeness.bats (6 cases:
  happy path, missing-named, |-alternation, parser-empty, real-repo)

Removing skills/standards/references/javascript.md temporarily makes
the gate FAIL with a clear message; restoring makes it PASS.

Source: 2026-04-26 nightly retro task 2.

* feat(rpi): add probed_stale_at + probed_by + ao rpi mark-probed

When a nightly probes a queue item and finds it stale, the knowledge
dies in the digest — tomorrow's run re-probes the same item. Adds
optional probed_stale_at (RFC3339) and probed_by fields to the v1.3
item schema, the Go round-trip type, the schema-rows acceptance test,
and a new `ao rpi mark-probed --id=... --by=...` subcommand for future
nightlies to write these without hand-editing JSON.

- docs/contracts/next-work.schema.md (Item table)
- cli/internal/rpi/types.go (NextWorkItem fields, omitempty)
- cli/internal/rpi/types_test.go (round-trip + omitempty)
- cli/cmd/ao/rpi_mark_probed.go (new subcommand)
- cli/cmd/ao/rpi_mark_probed_test.go (4 cases)
- cli/docs/COMMANDS.md (regenerated)
- tests/scripts/check-next-work-schema-rows.bats (acceptance case)

validate-next-work-contract-parity.sh stays green.

Source: 2026-04-26 nightly retro task 3.

* fix(overnight): probe Dream packets for staleness before emit

Three nightlies in a row emitted the same two stale packets ("philosophy
doc", "next-work schema v1.3") because no gate verified the cited
surface wasn't already shipped. Curator now runs a 5-second tractability
probe against each candidate's TargetFiles + scripts/ refs in the
morning command before writing it. Conclusively-stale packets are
suppressed; the suppression is recorded as a dream-curator-suppressed
entry on the run summary so operators see what was skipped instead of a
silent gap.

- cli/cmd/ao/overnight.go (overnightSummary.CuratorSuppressed)
- cli/cmd/ao/overnight_packets.go (probeDreamPacketStaleness,
  extractScriptsRef, suppression plumbed through
  buildDreamMorningPacketPlans return)
- cli/cmd/ao/overnight_packets_test.go (suppression-on-existing-target +
  emits-when-inconclusive integration tests)

Source: 2026-04-26 nightly retro task 4.

* chore(scripts): add install-bd.sh installer

bd has been "unavailable" in three consecutive nightly runs. Upstream
(steveyegge/beads) publishes signed cross-platform binaries for
darwin/linux on amd64/arm64. New installer detects the platform,
downloads the matching tarball, installs to ~/.local/bin/bd, and
verifies via `bd version`. Idempotent: short-circuits when the
requested version is already present (use --force to override).

- scripts/install-bd.sh (new, executable)
- tests/scripts/install-bd.bats (4 offline-safe cases)

Verified end-to-end on darwin/arm64: download + extract + verify all
green.

Source: 2026-04-26 nightly retro task 5.

* fix(ci): align bats stub and AGENTS table with new standards-injector gate

PR #156 introduced scripts/check-standards-injector-completeness.sh
without:
- adding a make_stub for it in tests/scripts/pre-push-gate.bats setup;
  three pre-push-gate bats tests (404, 414, 415) used a FAKE_REPO that
  lacked the new script and the gate fired "missing executable", so
  status came back non-zero
- listing it in the AGENTS.md CI table; validate-ci-policy-parity.sh
  diffs the table against validate.yml summary.needs and flagged 2
  drift groups

Both gates pass locally now.
2026-04-26 19:26:04 -04:00
Boden Fuller ee2af059c9 test(goals): stabilize skipped timeout cases 2026-04-12 03:21:31 -04:00
Boshu2 e442a414a8 fix(tests): push internal packages to 100% coverage with error-path tests
Add comprehensive error-path tests across all internal packages and cmd/ao.
14 packages now at 100% statement coverage; 4 remaining packages at
98-99% ceiling (provably unreachable defensive code).

Key changes:
- Add injectable test hooks (getwdFunc, marshalJSON, openFileFunc, etc.)
  to cover OS-level error branches unreachable on macOS
- Cover deferred f.Close() errors, json.Marshal failures on typed structs,
  filepath.Walk errors, and crypto/rand.Read fallbacks
- Add Linux-only build-constrained tests for filepath.Abs double-failure
- Fix flaky TestMergeWorktree_UntrackedFileDirtyRepo (100ms -> 5s timeout)
- Split ratchet_extra_test.go into per-source test files per convention
- Remove duplicate test declarations from prior agent merges
2026-03-11 12:33:52 -04:00
Boshu2 f2ddcfd900 fix(release): restore coverage and learning coherence gates 2026-03-10 07:45:41 -04:00
Test 51cc112b15 fix(cli): fix 23 bugs from comprehensive CLI audit
Address 7 HIGH, 11 MEDIUM, and 5 LOW severity bugs found during
systematic audit of the ao CLI. All fixes use TDD — failing tests
written first, then fixes applied.

HIGH fixes:
- Signal handler goroutine leak in goals/measure.go (done channel pattern)
- Child process map lazy init race in goals/measure.go (eager init)
- Windows filelock unguarded type assertion panic (2 files, safe assertion)
- Pool chain event records wrong FromStatus (capture before mutation)
- Scanner error swallowed in storage/file.go (check scanner.Err())
- Stream parser 64KB alloc per read (reuse buffer)
- Context state race in classifyStreamResult (cache Err() result)

MEDIUM fixes:
- Unbounded stream buffer growth (1MB max line guard)
- Pipe close error silently discarded (log via VerbosePrintf)
- No-op cancel function on zero timeout (use context.WithCancel)
- Pool recordEvent missing Sync (add f.Sync())
- paginate nil vs empty slice inconsistency (always return empty slice)
- Worker pool panic causes deadlock (wrap fn in recover)
- Nil Source pointer in writeArtifact (nil guard)
- Negative/oversized weight parsing (clamp 1-10)
- Worktree context not deferred (use defer cancel())
- Merge conflict error silently discarded (acknowledge explicitly)
- Sandbox nil meta guard in team lifecycle validation

LOW fixes:
- Empty steer field accepted (skip if empty after trim)
- Dead runID parameter (use blank identifier)
- Nil file guard in writeStreamEvent
- Env var precedence documented in toolchain.go
- Windows filelock duplicate assertion (same fix as HIGH #2)

Epic: ag-6bc (8 issues, 1 wave, 8 parallel workers)
2026-03-09 16:50:48 -04:00
Boden Fuller d6c4a04389 evolve: cycle 35 -- go-cli-tests improved 2026-03-06 22:53:21 -05:00
Boden Fuller 64afb4e98f fix: bound curate verify smoke path 2026-03-05 21:10:18 -05:00
Boden Fuller 273e0bd9c3 fix: address all 6 post-mortem findings from TDD hardening
Post-mortem council flagged 6 items. All resolved:

1. Clean dead code in measure_test.go — removed longOutput variable,
   order variable, fixed byte-vs-rune assertion to use len([]rune())
2. Add goleak for goroutine leak detection — replaces fragile
   runtime.NumGoroutine + sleep heuristic with deterministic check
3. Assert AntiStars values in goals_init_test.go — not just count
4. Fix ci-local-release.sh invocation: ./scripts/ not bash scripts/
5. Add MigrateV1ToV2 and killAllChildren package-level tests —
   previously at 0% coverage in internal/goals
6. Fix goroutine leak in rpi_status.go — same signal.Stop-without-close
   pattern found by audit of all signal.Notify sites (1/3 leaking)
2026-02-24 11:46:47 -05:00
Boden Fuller 03c4849795 fix(goals): goroutine leak, nil Process guard, and TDD coverage expansion
TDD approach: wrote tests first proving 2 bugs (goroutine leak in
runGoals signal handler, nil pointer panic in configureProcGroup Cancel
closure), then fixed them. Added 15 new test cases covering detectGates,
buildInteractiveGoalFile, directivesFromPillars, and multi-byte rune
truncation. Wired check-skill-flag-refs.sh into release gate. Deleted
untracked cli/AGENTS.md (redundant with ~/gt/AGENTS.md).
2026-02-24 11:20:53 -05:00
Boden Fuller 9178f2b052 evolve: cycle 32 -- boost goals 97.8%->98.9%, search 95.9%->96.7%
goals: Add LoadHistory scanner error test (line >64KB),
add gitSHA error path test (run outside git repo).

search: Add BuildIndex deduplicate-terms-per-file test
exercising the seen[term] continue path in indexFile.
2026-02-22 01:44:27 -05:00
Boden Fuller bed4d5ffcf test(rpi): add integration tests for RPI orchestrator, goals, and cmd/ao
Coverage improvements across the three most critical CLI subsystems:
- cli/internal/goals/: 15.2% → 94.4% (target 50%, exceeded)
- cli/internal/rpi/: 35.0% → 69.1% (target 65%, met)
- cli/cmd/ao/: 46.9% → 48.8% (target 65%, partial — entry points
  need integration harness for further coverage)

14 new test files covering: goals validation/measure/drift/history/
snapshot, RPI worktree lifecycle, supervisor loop, phased engine
phase runner, RPI status/cancel/cleanup commands. All existing tests
pass, zero regressions.
2026-02-21 22:10:56 -05:00