feat(ai-sdk): pin accepted proposer decisions into the GT gate (P3)
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
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>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user