Skip to content

feat(FAFF-398): fail-closed on mandatory review-chain exhaustion#284

Merged
alechill merged 2 commits into
mainfrom
faff-398-mandatory-chain-outage
Jul 7, 2026
Merged

feat(FAFF-398): fail-closed on mandatory review-chain exhaustion#284
alechill merged 2 commits into
mainfrom
faff-398-mandatory-chain-outage

Conversation

@alechill

@alechill alechill commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes FAFF-398.

What

On a lights-out (L4) run, a mandatory adversarial review whose whole backend chain is exhausted with no opinion obtained (all-unreachable exit 5, or deadline exit 8) now fails closed → needs-human instead of the pass+skip that silently no-ops the L4 second-opinion gate on an outage (recurred: all 4 merges in run-140848). Advisory (L1–L3, flag absent) is byte-for-byte unchanged.

How

  • review-call.mjs: new EXIT.MANDATORY_OUTAGE (9) + a pure mandatoryRemap(exit, mandatory) applied once at main()'s res.exit chokepoint — every exhaustion path (the three deadline returns + chain-exhausted) funnels through it, so it is miss-proof by construction; runReviewChain stays level-agnostic. New --lights-out flag.
  • SKILL.md: exit-9 row, the --lights-out pass-through (iff forwarded lights_out), the intentional autonomous-vs-lights_out asymmetry, and the checkpoint carve-out (exit 9 is a terminal needs-human, not a skip).
  • Config-fault classes (2/4/6/7) pass through unremapped; the Step-10 merge gate needs no edit (needs-human auto-parks via decideFloor).

Acceptance Criteria

  • EXIT.MANDATORY_OUTAGE (9) added — test/adversarial-call.test.mjs
  • --lights-outmandatory (default false) — parseArgs test
  • pure mandatoryRemap maps 5/8→9 only when mandatory; config-faults + OK pass through — mandatoryRemap test
  • single-chokepoint remap covers all terminal loci — main() integration: unreachable→9, deadline→9, served→0, no-flag→5, config-fault(AUTH)→7
  • runReviewChain stays level-agnostic (ignores a passed mandatory) — level-agnostic test
  • SKILL.md exit-9 row + pass-through + asymmetry — faff validate-adapters passes
  • No new eval grader KIND (the seam is deterministic)
    Verified: node --test test/adversarial-call.test.mjs → 80/80; full node --test → 1159 pass / 3 fail (pre-existing docker/spawn, unrelated to this diff); faff validate-adapters → PASS.

Spec: docs/specs/2026-07-07-faff-398-mid-run-fail-closed-on-review-chain-exhaustion-design.md. Settled punts: exit value = 9; exit 9 writes no --phase2 skipped* status.

alechill added 2 commits July 7, 2026 13:45
A lights-out (L4) adversarial review whose whole backend chain is exhausted with
no opinion obtained (all-unreachable exit 5, or deadline exit 8) now fails CLOSED
to needs-human instead of the pass+skip that silently no-ops the L4 second-opinion
gate on an outage.

- review-call.mjs: new EXIT.MANDATORY_OUTAGE (9) + a pure mandatoryRemap(exit,
  mandatory) applied ONCE at main()'s res.exit chokepoint, so every exhaustion path
  (the three deadline returns + the chain-exhausted return) is covered by
  construction; runReviewChain stays level-agnostic. New --lights-out flag.
- SKILL.md: exit-9 row, the --lights-out pass-through (iff forwarded lights_out),
  the intentional autonomous-vs-lights_out asymmetry, checkpoint note (terminal
  needs-human, not a skip).
- Advisory (L1-L3, flag absent) is byte-for-byte unchanged; config-fault classes
  (2/4/6/7) pass through unremapped. Step-10 merge gate needs no edit.

Tests: 8 new cases in test/adversarial-call.test.mjs (pure remap, level-agnostic
chain, main() integration for unreachable/deadline/served/no-flag/config-fault).
@alechill alechill merged commit ca03cb9 into main Jul 7, 2026
2 checks passed
@alechill alechill deleted the faff-398-mandatory-chain-outage branch July 7, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant