fix: address pre-landing review (codex) on the carve

- cso section: add a scope-gate header so '--owasp' (and other scoped modes)
  run only their selected phases, not every phase bundled in the section
  ('execute in full' no longer overrides Mode Resolution).
- carve-guard-checks: gateAfterStop now compares against the LAST STOP, not the
  first, so a gate stranded between two STOPs in a multi-STOP skeleton fails.
- TODOS: behavioral section-loading hermeticity (verifier matches global-install
  path, not the fixture) — pre-existing in auq-sdk-capture.ts, deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-06-07 18:18:02 -07:00
parent 6a40aa2c2e
commit a8c295d49d
4 changed files with 31 additions and 3 deletions
+22
View File
@@ -2312,3 +2312,25 @@ from there.
**Effort:** M (human ~2d, CC ~4h).
**Depends on:** `transcript-section-logger.ts` real-session-drift rework.
### P2: Harden behavioral section-loading test hermeticity
**What:** `captureSectionReads` in `test/helpers/auq-sdk-capture.ts` accepts ANY
Read whose path matches `sections/<file>.md`. The skeleton's STOP-Read directive
points at the gstack-root install path (`scripts/resolvers/sections.ts` builds it
from `ctx.paths.skillRoot`), not the planted fixture copy. So a run can satisfy
the section-read assertion by reading the GLOBAL install's section instead of the
hermetic fixture.
**Why:** A behavioral test that passes by reading the global install doesn't prove
THIS branch's carved section loads. If the fixture's section were broken but the
global install's weren't, the test would still pass.
**Context:** Codex outside-voice finding on the carve-guard ship (v1.57.0.0).
Pre-existing in `auq-sdk-capture.ts` — affects `skill-e2e-ship-section-loading`,
`skill-e2e-plan-ceo-review-section-loading`, and the new
`carve-section-loading.test.ts`. Fix: match the fixture's ABSOLUTE sections path
(the `planDir` copy), not a bare `sections/<file>.md` regex; or rewrite the STOP
path to the fixture during the run.
**Effort:** S (human ~3h, CC ~30min). **Depends on:** None.
+2
View File
@@ -1,5 +1,7 @@
<!-- AUTO-GENERATED from audit-phases.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->
**Scope gate (read first).** This section holds every scope-dependent phase (2-11), but you run ONLY the phases your resolved mode selected back in `## Mode Resolution` (always-loaded in the skeleton). Phases 0, 1, 12, 13, 14 always run; Phases 2-11 are scope-gated. "Execute in full" means work through this section applying that selection, NOT run a phase your mode did not select just because its prose lives here. Example: `--owasp` runs Phase 9 from this section, not Phases 2-8/10/11.
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
+2
View File
@@ -1,3 +1,5 @@
**Scope gate (read first).** This section holds every scope-dependent phase (2-11), but you run ONLY the phases your resolved mode selected back in `## Mode Resolution` (always-loaded in the skeleton). Phases 0, 1, 12, 13, 14 always run; Phases 2-11 are scope-gated. "Execute in full" means work through this section applying that selection, NOT run a phase your mode did not select just because its prose lives here. Example: `--owasp` runs Phase 9 from this section, not Phases 2-8/10/11.
### Phase 2: Secrets Archaeology
Scan git history for leaked credentials, check tracked `.env` files, find CI configs with inline secrets.
+5 -3
View File
@@ -114,12 +114,14 @@ export function checkOrdering(root: string, guard: CarveGuard): string[] {
// 5. The post-STOP gate fires after the last STOP (review skills).
const gate = guard.staticInvariants.gateAfterStop;
if (gate) {
const firstStop = skeleton.indexOf(STOP);
// Gate must fire after the LAST STOP (once all section work returns), not just
// the first — for multi-STOP skeletons a gate between two STOPs is stranded.
const lastStop = skeleton.lastIndexOf(STOP);
const lastGate = skeleton.lastIndexOf(gate);
if (lastGate < 0) {
failures.push(`gateAfterStop marker missing from skeleton: "${gate}"`);
} else if (firstStop >= 0 && lastGate < firstStop) {
failures.push(`gateAfterStop "${gate}" appears before the STOP (stranded above it)`);
} else if (lastStop >= 0 && lastGate < lastStop) {
failures.push(`gateAfterStop "${gate}" appears before the last STOP (stranded above it)`);
}
}