Skip to content

feat(rfc-008): P4d S8 P12 invariant CI gate (REQ-10/REQ-11)#419

Merged
lantiscooperdev merged 1 commit into
mainfrom
feat/rfc-008-p4d-s8-ci-gate
Jun 22, 2026
Merged

feat(rfc-008): P4d S8 P12 invariant CI gate (REQ-10/REQ-11)#419
lantiscooperdev merged 1 commit into
mainfrom
feat/rfc-008-p4d-s8-ci-gate

Conversation

@lantisprime

@lantisprime lantisprime commented Jun 21, 2026

Copy link
Copy Markdown
Owner

RFC-008 P4d S8: P12 invariant CI gate (the last P4d slice)

Promotes the Principle-12 invariants into ONE separately-named required CI check whose membership is defined in code. Closes REQ-10 and REQ-11.

What changed

  • NEW tests/test-p12-invariant-suite.mjs: a code-defined meta-runner. Membership is glob(tests/test-p12-*.mjs) union an EXPLICIT set (7 members), minus this runner and any sibling meta-runner. It runs each member as a node subprocess and exits non-zero if any member fails.
  • NEW CI job p12-invariant-gate in .github/workflows/plan-marker-validate.yml. The existing validate job is byte-untouched.

Why it matters

The S5 uninstall round-trip (test-uninstall-enforcement.mjs) and the S6 seed-identity guard (test-enforce-config-seed-identity.mjs) had no CI step before this. The gate brings them, plus the S1 substrate-hook-independence, S4 gate-toggle, ESC enforcement-scope, contract-deploy, and global-clean invariants, under one named check.

Members (7): test-activation-scoping-e2e, test-enforce-config-seed-identity, test-enforcement-scope, test-install-contract-deploy, test-p12-global-clean, test-s4-gate-e2e, test-uninstall-enforcement.

Requirements

  • REQ-10 (membership in code): t_membership_complete re-derives the set, pins the EXPLICIT half against an independent literal (so a silent deletion trips), asserts every member exists on disk, and excludes the runner plus any sibling meta-runner.
  • REQ-11 (no silent skip): t_runner_fails_on_member_failure is the negative control. P12_INJECT_FAIL=1 injects a synthetic failing member and asserts the runner exits 1.

Test plan

  • node tests/test-p12-invariant-suite.mjs returns P12 INVARIANT GATE: PASS (exit 0); 2 meta-tests plus 7 members all green (activation-scoping 13, seed-identity 6, enforcement-scope 17, contract-deploy 36, global-clean 6, s4-gate 5, uninstall 14).
  • Negative control captured exit 1 on an injected failing member.
  • Workflow YAML parses with jobs = validate, p12-invariant-gate.
  • No global deploy (CI and test only).

Review

negative-scenario-reviewer returned ACCEPT-WITH-MODIFICATION. Dispositions, all applied in this PR:

  • M1 (MAJOR) ACCEPT: added the wrongly-omitted test-activation-scoping-e2e.mjs member (it asserts the global and project enforcement-clean plus substrate hook-independence contract).
  • M2 (MINOR) ACCEPT-WITH-MOD: independent literal pin of the EXPLICIT half (defeats the reviewer's captured silent-drop scenario).
  • M3 (MINOR) ACCEPT: meta-runner basenames excluded from membership plus an assertion (fork-bomb guard).
  • N1 (NIT) REJECT with evidence: spawnSync status null and ENOENT already fail closed via !== 0.

Follow-ups (tracked as issues)

After this merges, P4d is complete; remaining RFC-008 work is P5-P8 tool breadth.

Code-defined meta-runner (tests/test-p12-invariant-suite.mjs) plus a separately-named required CI job p12-invariant-gate. Membership = glob(test-p12-*.mjs) union an EXPLICIT set (7 members, including the S5 uninstall and S6 seed-identity invariants that had no other CI step). Runner exits non-zero if any member fails; t_runner_fails_on_member_failure is the REQ-11 negative control. Self and sibling meta-runners are excluded from membership to prevent recursion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@lantiscooperdev lantiscooperdev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR-level review (bot account): RFC-008 P4d S8 p12-invariant-gate

Reviewed the full diff (2 files, +219) at the PR level, after the per-artifact negative-scenario-reviewer pass. The slice delivers REQ-10/REQ-11 in code and is internally consistent. Confirmations and observations below; final approval is the maintainer's.

Confirmed

  • Membership maps cleanly to PRINCIPLES.md SS12 "Test this": global-clean (test-p12-global-clean), per-project scope and ESC (enforcement-scope, install-contract-deploy, activation-scoping), the S4 gate toggle (s4-gate-e2e), the S5 uninstall round-trip, and the S6 seed-identity guard. The two previously-uncovered tests (uninstall, seed-identity) now have a CI home.
  • The validate job is byte-untouched; the new job is a clean sibling. No risk to existing CI.
  • REQ-11 negative control is real: t_runner_fails_on_member_failure spawns the runner with P12_INJECT_FAIL=1 and asserts exit 1 through the shared status-check path.
  • M1/M2/M3 from the per-artifact review are addressed in the committed code; N1 was correctly rejected as fail-closed-by-construction.

Observations (non-blocking)

  1. CI-time duplication. Five of the seven members (activation-scoping, install-contract-deploy, s4-gate-e2e, enforcement-scope, global-clean) also run as flat steps in the validate job, so they execute twice per CI run. This is the intended minimal-diff choice (the meta-runner is the authoritative named gate; the flat steps predate it). A future cleanup could drop the now-redundant flat steps from validate once p12-invariant-gate is the required check. Worth a follow-up, not a blocker.
  2. "Required" is half-delivered by design. The job runs on every PR, but a failure will not block merge until branch protection marks p12-invariant-gate a required status check. That out-of-band toggle is correctly tracked as OD-3. Until then REQ-10's "required" property is documentary.

Verdict

ACCEPT (comment-level). The code half of REQ-10/REQ-11 is complete, tested, and review-clean. Recommend the maintainer (a) approve and merge, then (b) apply the OD-3 branch-protection toggle so the gate actually blocks.

@lantiscooperdev lantiscooperdev merged commit c8651f4 into main Jun 22, 2026
3 checks passed
lantiscooperdev pushed a commit that referenced this pull request Jun 22, 2026
S7 (#418) and S8 (#419) are merged, completing P4d and therefore P4 (P4a #397 + P4c #398 + P4d S1-S8 all merged). Flips the stale 'S7-S8 open' / 'IN PROGRESS' status in the RFC body ledger (:1216), the RFC-008/README.md phase matrix (:21), and P4-enforce-config.md status line + the S7/S8 slice-table rows. Rule 10 doc-sync; no code change.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants