Cycle 178 of the v2.41-evolve-run loop. `ao goals measure` surfaced a
failing `three-gap-supergate` directive — the `goals-validate`
sub-gate's `go build -o /tmp/ao-sg ./cmd/ao` was tripping with "build
output /tmp/ao-sg already exists and is not an object file".
Root cause: cycle 174 (soc-wxh5.3) added bats tests whose shim `go`
binary writes a shell-script `/tmp/ao-sg`. The bats teardown cleaned
`$TMP_HOME` but not the literal `/tmp/ao-sg` the shim left behind, so
subsequent real-goals runs found the stale shell script and refused to
overwrite it.
Two-sided fix:
- scripts/check-three-gap-supergate.sh — `rm -f /tmp/ao-sg` before the
`go build`. This is a real production guard, not just a test concern:
any prior process leaving a non-binary at /tmp/ao-sg would wedge the
gate.
- tests/scripts/check-three-gap-supergate.bats — `rm -f /tmp/ao-sg` in
teardown so subsequent runs in the same shell don't carry the
pollution.
After fix: `ao goals measure` reports 0 failing directives (was 1),
satisfying the v2.41 done-criterion "GOALS green". All 18 bats tests
still pass.
This is a clean self-correction loop: cycle 174 introduced a latent
hazard, cycle 178's goals-measurement caught it, fix lands in the
same session.
soc-w6vh.6 acceptance: TG1 council-coverage maps changed PR commits or
cycle outputs to a required council artifact, pre-mortem, or vibe
verdict. Greenfield CI behavior remains explicit and non-misleading.
The gate report distinguishes structural availability from real
coverage.
Changes:
1. scripts/check-three-gap-supergate.sh — add --strict-coverage flag
(default off, backwards compatible). On opt-in, the new
strict_council_coverage() function:
- resolves base ref via $PR_BASE_REF || $GITHUB_BASE_REF || "main"
- lists commits via `git log --format=%H base..HEAD`
- SKIPs when commits is empty (single-commit PR, missing base, or
non-git invocation — matches existing greenfield SKIP shape)
- for each commit, counts as "covered" if:
a) any .agents/council/*.md mentions the commit's 7-char SHA, OR
b) the commit message begins with a `Council|Pre-mortem|Vibe verdict:`
header (case-insensitive)
- PASSes when covered=total; FAILs (exit 1) when any commit is
missing, with the missing-SHAs list in the report
- Default mode unchanged in semantics: emits an INFO line pointing
to --strict-coverage instead of acting on it
2. Existing PASS report gains a `[structural]` suffix so the gate
report explicitly distinguishes structural availability from real
coverage (AC #3). Default backwards-compatible.
Drift-blocking tests: tests/scripts/check-three-gap-supergate.bats
extended from 9 to 14 tests. New tests (10-14) cover:
- Default emits INFO line about --strict-coverage opt-in
- --strict-coverage SKIPs when no commits past base
- --strict-coverage PASSes when commits have council reference
- --strict-coverage FAILs when commits lack reference (with diagnostic)
- --strict-coverage covers by short-SHA mention in council artifact
The new tests use a minimal git init inside SHIM_ROOT — same pattern
as cycle 63's bats extension (commit 383a0942) but with git fixtures
on top.
Sibling pattern: cycle 63 commit 383a0942 (Gap 1 council-coverage
structural bats extension) — same shape: extend the existing
SHIM_ROOT setup with one new helper (`init_shim_git`), add tests that
exercise both PASS and FAIL paths for the new flag, preserve the
backwards-compatible default. All 9 existing bats still pass.
Code-driven fitness:
- bats coverage for gap_council_coverage: 9 → 14 (5 new tests cover
both --strict-coverage paths + the INFO line)
- backwards-compatible default behavior: unchanged
- pre-push --fast: 0 blocking; check-three-gap-supergate
council-coverage gate PASS (structural) and SKIP (--strict-coverage,
on-main, no commits past base) on operator box
Follow-up (next cycle): wire --strict-coverage into CI (probably
advisory mode first, then required after one round of operator
calibration). Filed as soc-w6vh.6.1 follow-up child.
Closes the implementation surface of soc-w6vh.6 (the gate logic +
bats). Parent soc-w6vh.6 stays open for the CI-wiring follow-up.
Cycle 72 / soc-w6vh.6 implementation mode.
The Gap 2 (durable learning) sub-gate hard-failed when neither
.agents/defrag/latest.json nor an overnight Dream preview existed,
making three-gap-supergate the sole code-driven failing goal on
fresh CI runners. The same artifact dependency is already classified
runtime-artifact for compile-freshness and compile-no-oscillation;
those goals still surface the underlying signal on operator boxes.
Match the existing Gap 1 council-coverage SKIP shape: when the
artifact is absent the gate emits SKIP rather than FAIL, because the
absence is a structural property of greenfield CI, not a durable-
learning health regression. Add bats coverage for the SKIP path,
the canonical-artifact path, the overnight-preview path, and the
empty-overnight-tree edge case.
Code-driven fitness: 134/139 -> 139/139.
https://claude.ai/code/session_01Pf3WB9DEzfZUjqhmTssHPR
Three required-job failures caught by `gh run list` per the cycle-48
tightened quality protocol (operator-asked, "how are you going to
enforce quality"):
1. **markdownlint** (cycle 46+) — MD004 ul-style violation in
docs/releases/v2.39.0-claims/all-claims-evidence-map.md:52. A `+`
bullet at column 3 was being interpreted as a nested list using
plus-style; rewrote prose to use "with" instead.
2. **validate-three-gap-supergate** (cycle 42+) — compile-health child
failed every CI run since the supergate landed because it requires
.agents/defrag/latest.json which doesn't exist on greenfield CI
runners (the nightly workflow generates it via `ao defrag` into a
tmpdir + COMPILE_OUTPUT_DIR env). Sibling gates (council-coverage,
flywheel-proof) already SKIP under similar conditions; compile-
health now does too: if neither AGENTS_DIR/defrag/latest.json nor
AGENTS_DIR/overnight/*/defrag/latest.json exists AND
COMPILE_OUTPUT_DIR is unset, SKIP with "enforced by nightly
workflow" message. The nightly workflow remains the canonical
enforcer.
3. **registry-check** (cycle 45) — registry.json stale because cycle
45 added 4 new skills/evolve/references/*.md files without
regenerating. `bash scripts/generate-registry.sh` regenerated;
counts now reflect current state (77 skills, 43 hooks, 4 stores,
14 job types, 63 evals, 148 CLI commands).
Verification:
- markdownlint docs/releases/v2.39.0-claims/*.md — clean.
- bash scripts/check-three-gap-supergate.sh --gap=all — PASS locally.
- AGENTS_DIR=/tmp/no-such-dir bash scripts/check-three-gap-supergate.sh
--gap=durable-learning — PASS with SKIP message for compile-health
(simulates CI greenfield).
- bash scripts/generate-registry.sh --check — "OK: registry.json is up
to date".
Out of scope:
- agentops-contract-canaries cycle-45 failure (aggregate=0.9549) — same
fingerprint as the soc-l4yt closed-flake; doesn't reproduce on cycle
46/47 CI runs or in local 5/5 bats. Not addressed here.
- security-toolchain-gate (advisory; exit 3 with 0 missing tools) —
pre-existing, not introduced by this branch.
Closes soc-m47k (epic), soc-m47k.1 (TG1), soc-m47k.2 (TG2),
soc-m47k.3 (TG3).
Why
- GOALS.md three-gap table separates Currently-enforcing from
Roadmap per gap (Gap 1 council coverage, Gap 2 durable learning,
Gap 3 loop closure). Each gap had its component gates wired
individually, but no single command emitted unified per-gap
status. Operators reading the table had to chase 3-5 gates per
row to know if a gap was closed.
What
- scripts/check-three-gap-supergate.sh (NEW): composes existing
child gates and emits unified status per gap. Supports
--gap=council-coverage, --gap=durable-learning, --gap=loop-
closure, or --gap=all. Each child gate runs with its existing
protocol (skip semantics, env overrides) preserved; the super-
gate aggregates exit codes.
- TG1 council-coverage: checks .agents/council/ artifacts
(PR-diff matching tracked as a stronger follow-up; baseline
is "council surface is populated").
- TG2 durable-learning: composes flywheel-compounding-snapshot
+ flywheel-proof + compile-health.
- TG3 loop-closure: composes goals-validate + wiring-closure +
flywheel-proof.
- GOALS.md: new gate row three-gap-supergate, weight 5.
- .github/workflows/validate.yml: new validate-three-gap-supergate
job with Go setup + ao build (children need cli/bin/ao).
Registered in summary.needs[] + summary echo (59 jobs).
- AGENTS.md: CI Jobs row.
- tests/scripts/pre-push-gate.bats: stub.
Note: did NOT add to pre-push-gate.sh — the super-gate is heavy
(builds ao for goals-validate child) and overlaps with the
individual gates already in pre-push. CI lane is sufficient.
Verification
- --gap=council-coverage: PASS (10 council files present)
- --gap=durable-learning: PASS (flywheel-compounding-snapshot,
flywheel-proof, compile-health all green)
- --gap=loop-closure: PASS (goals-validate, wiring-closure,
flywheel-proof all green)
- --gap=all: PASS
- shellcheck: clean
- validate-ci-policy-parity: PASS (59 jobs, 7 non-blocking)
- pre-push --fast: green
Closes E5 epic and its 3 children.