Commit b81fe3c
feat(v1.100 Amendment 3): code-A — G1/AmbiguityConflictExternal orphan-CSF split (#523)
Implements the §63 lattice extension + §64 evidence predicate from the
Amendment 3 doc seed (#522). Decision-layer only.
Lattice changes (engine.go):
- 3 new rule constants:
G1/AmbiguityConflictExternal/default → REFUSE (preserves pre-Amendment-3 hard-stop)
G1/AmbiguityConflictExternal/OrphanProceed → PROCEED PanelNative/csf
G1/AmbiguityConflictExternal/EvidenceMismatch → REFUSE (predicate any-false)
- decideAmbiguityConflictExternal() function mirrors decideAuthorityNFTBan()
in shape: Group 2 precedence preserved → quintuple-check (csf + DA + NoRecord +
--panel-auto-takeover + --accept-orphan-nftban) → §64 predicate delegation.
- Decide() now calls decideAmbiguityConflictExternal(in) for the
AuthorityAmbiguous + AmbiguityConflictExternal branch (replaces the
inline REFUSE).
Evidence predicate (types.go):
- New ExternalIndicator string field on DecisionInput (carries the
classifier's external-authority string; required for §62 entry condition).
- New AllTrueAmendment3() helper on OrphanEvidence: identical to AllTrue()
EXCEPT row E.12 (NoConflictExternal) is omitted — the §62 entry IS
AmbiguityConflictExternal so requiring "no conflict external" is
incompatible by construction.
- New FailedRowIDAmendment3() helper returns AMD3-E.{N} stable IDs so
structured logs and Code-D evidence-records distinguish which
predicate fired.
Test matrix (engine_amendment3_test.go — new file):
- 15-row §67 matrix (AMD3-1 through AMD3-15) including the 3 auditor-
required defensive-guard rows: AMD3-13 empty external, AMD3-14 rule-
label assertion ("amendment-3 orphan-intent" reason substring),
AMD3-15 multi-external "csf,ufw".
- TestAmd3_RuleConstants pins canonical rule strings.
- TestAmd3_AllTrueAmendment3_OmitsE12 verifies E.12 is excluded.
- TestAmd3_FailedRowIDAmendment3_SkipsE12 verifies row-walk skips E.12.
- TestAmd3_NilEvidence_AMD3E0 verifies nil-receiver sentinel.
Regression updates (engine_test.go, engine_amendment2_test.go):
- 2 pre-existing fixtures asserting the old "G1/AmbiguityConflictExternal"
rule string updated to RuleG1AmbConflictExtDefault. Behavior unchanged
(still REFUSE); only the rule sub-classifier name shifts. Same pattern
as Amendment 2's AuthorityNFTBan/default rename.
- declaredRules() in engine_test.go updated to include the 3 new sub-rule
constants (RuleG1AmbiguityConflictExt umbrella retained for grep parity).
- 2 sentinel fixtures added to allFixtures pinning the new
OrphanProceed and EvidenceMismatch rules for coverage assertion
(full §67 matrix lives in engine_amendment3_test.go).
NOT touched (in scope per operator):
- internal/installer/uninstall/* (classifier — semantic unchanged)
- internal/installer/restore/execute.go (mutation surface unchanged)
- internal/installer/state/* (state machine unchanged)
- cmd/nftban-installer/main.go (history gate unchanged)
- cmd/nftban-installer/flags.go (flag surface unchanged)
- .github/workflows/* (CI unchanged)
- §32 11-step ordering (unchanged)
- Amendment 2's §54 predicate (untouched; AllTrue() preserved for the
AuthorityNFTBan path; AllTrueAmendment3() is a new sibling)
Test results (lab4):
- go test ./internal/installer/restore/... → ok
- go test ./cmd/nftban-installer/... → ok
- go test ./... → 64 packages ok, 0 FAIL
No host action. No binary rebuild. No nftban-installer invocation.
dns2 stays in canonical post-Gate-A state.
Closes part of PR-26 final closure path: Gate B retry on dns2 unblocks
once this PR merges + fresh Tier 1 binary is built + reachability monitor
activates + pre-execution Gate B retry audit returns GO.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 8869392 commit b81fe3c
5 files changed
Lines changed: 749 additions & 9 deletions
File tree
- internal/installer/restore
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
55 | 71 | | |
56 | 72 | | |
57 | 73 | | |
| |||
111 | 127 | | |
112 | 128 | | |
113 | 129 | | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
| 130 | + | |
119 | 131 | | |
120 | 132 | | |
121 | 133 | | |
| |||
414 | 426 | | |
415 | 427 | | |
416 | 428 | | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
323 | 323 | | |
324 | 324 | | |
325 | 325 | | |
326 | | - | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
327 | 337 | | |
328 | 338 | | |
329 | 339 | | |
| |||
335 | 345 | | |
336 | 346 | | |
337 | 347 | | |
338 | | - | |
| 348 | + | |
339 | 349 | | |
340 | 350 | | |
341 | 351 | | |
| |||
0 commit comments