d5925e57af
CI / detect-changes (push) Successful in 12s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 9s
CI / validate-canonical-controls (push) Successful in 8s
CI / loc-budget (push) Successful in 21s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Successful in 59s
CI / iace-gt-coverage (push) Successful in 19s
CI / test-python-backend (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
When a human accepts a proposer proposal, an AcceptedPin records a machine-scoped invariant — a pattern MUST fire (coverage/vocab→tag) or must NOT fire (dedup/framing) — that a test re-checks on every run. This makes the library's growth COMPOUND into the gate instead of eroding it: a change that re-introduces a dropped duplicate, un-gates a foreign pattern, or removes a coverage hazard breaks a pin and fails CI. One boolean covers all four proposal types. Seeded testdata/accepted_pins_warewashing.json with the accepted P1 supersessions (HP016/HP018/HP013 must NOT fire; their clean equivalents HP2201/HP144 must fire). TestWarewashing_AcceptedPins re-checks 5/5 against the live engine output; GenerateDedupPin turns an accepted dedup verdict into its pin. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
74 lines
2.7 KiB
Go
74 lines
2.7 KiB
Go
package iace
|
|
|
|
// P3: pin accepted proposer decisions into the GT gate.
|
|
//
|
|
// When a human accepts a proposal from the offline proposer (a dedup
|
|
// supersession, a foreign-framing gate, a vocab→tag mapping, a coverage hazard),
|
|
// they record an AcceptedPin. A pin is a tiny, machine-scoped invariant — "this
|
|
// pattern MUST (or must NOT) fire for this machine" — that a test re-checks on
|
|
// every run. This is what makes the library's growth COMPOUND into the gate
|
|
// instead of silently eroding it: a future change that re-introduces a dropped
|
|
// duplicate, un-gates a foreign pattern, or removes a coverage hazard breaks the
|
|
// pin and fails CI.
|
|
//
|
|
// A single boolean covers all four proposal types:
|
|
// - dedup supersession accepted → DropPattern MustFire=false
|
|
// - foreign-framing gate accepted → foreign pattern MustFire=false
|
|
// - vocab→tag / coverage hazard accepted → the enabled pattern MustFire=true
|
|
|
|
// AcceptedPin is one regression invariant for an accepted proposal.
|
|
type AcceptedPin struct {
|
|
Pattern string `json:"pattern"`
|
|
MustFire bool `json:"must_fire"`
|
|
Reason string `json:"reason"`
|
|
FromProposal string `json:"from_proposal,omitempty"`
|
|
}
|
|
|
|
// PinSet is the accepted-pin registry for one machine (testdata/accepted_pins_*.json).
|
|
type PinSet struct {
|
|
Machine string `json:"machine"`
|
|
Pins []AcceptedPin `json:"pins"`
|
|
}
|
|
|
|
// PinResult is the verdict for one pin against an engine run.
|
|
type PinResult struct {
|
|
Pin AcceptedPin
|
|
OK bool
|
|
Detail string
|
|
}
|
|
|
|
// VerifyPins checks every pin against the set of pattern IDs the engine actually
|
|
// fired for the machine. A pin holds iff the pattern's presence equals MustFire.
|
|
func VerifyPins(pins []AcceptedPin, firedPatternIDs []string) []PinResult {
|
|
fired := make(map[string]bool, len(firedPatternIDs))
|
|
for _, id := range firedPatternIDs {
|
|
fired[id] = true
|
|
}
|
|
out := make([]PinResult, 0, len(pins))
|
|
for _, p := range pins {
|
|
got := fired[p.Pattern]
|
|
ok := got == p.MustFire
|
|
detail := "ok"
|
|
if !ok {
|
|
if p.MustFire {
|
|
detail = "expected to fire but did NOT — coverage/mapping regressed"
|
|
} else {
|
|
detail = "expected to be suppressed but FIRED — gate/supersession regressed"
|
|
}
|
|
}
|
|
out = append(out, PinResult{Pin: p, OK: ok, Detail: detail})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// GenerateDedupPin turns an accepted (verdict=duplicate) dedup candidate into the
|
|
// pin that protects the supersession: the dropped pattern must no longer fire.
|
|
func GenerateDedupPin(c DedupCandidate) AcceptedPin {
|
|
return AcceptedPin{
|
|
Pattern: c.DropPattern,
|
|
MustFire: false,
|
|
Reason: "accepted duplicate of " + c.KeepPattern + " (" + c.Category + ")",
|
|
FromProposal: "dedup " + c.DropPattern + " -> " + c.KeepPattern,
|
|
}
|
|
}
|