@mmnto/cli 1.88.0 → 1.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/author-sandbox.d.ts +32 -0
- package/dist/author-sandbox.d.ts.map +1 -0
- package/dist/author-sandbox.js +95 -0
- package/dist/author-sandbox.js.map +1 -0
- package/dist/authored-rule-intake-prewindow.test.d.ts +2 -0
- package/dist/authored-rule-intake-prewindow.test.d.ts.map +1 -0
- package/dist/authored-rule-intake-prewindow.test.js +84 -0
- package/dist/authored-rule-intake-prewindow.test.js.map +1 -0
- package/dist/authored-rule-intake.d.ts +21 -1
- package/dist/authored-rule-intake.d.ts.map +1 -1
- package/dist/authored-rule-intake.js +56 -1
- package/dist/authored-rule-intake.js.map +1 -1
- package/dist/commands/authored-whitelist.d.ts.map +1 -1
- package/dist/commands/authored-whitelist.js +19 -8
- package/dist/commands/authored-whitelist.js.map +1 -1
- package/dist/commands/ecl-gc.d.ts +259 -0
- package/dist/commands/ecl-gc.d.ts.map +1 -0
- package/dist/commands/ecl-gc.js +579 -0
- package/dist/commands/ecl-gc.js.map +1 -0
- package/dist/commands/ecl-gc.test.d.ts +12 -0
- package/dist/commands/ecl-gc.test.d.ts.map +1 -0
- package/dist/commands/ecl-gc.test.js +609 -0
- package/dist/commands/ecl-gc.test.js.map +1 -0
- package/dist/commands/eject.d.ts.map +1 -1
- package/dist/commands/eject.js +10 -6
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/eject.test.js +5 -1
- package/dist/commands/eject.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +4 -0
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +30 -2
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.test.js +26 -3
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/mail.d.ts +11 -0
- package/dist/commands/mail.d.ts.map +1 -1
- package/dist/commands/mail.js +5 -1
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/mail.test.js +19 -0
- package/dist/commands/mail.test.js.map +1 -1
- package/dist/commands/rule-author-command.test.js +29 -2
- package/dist/commands/rule-author-command.test.js.map +1 -1
- package/dist/commands/rule-author-teardown.test.d.ts +2 -0
- package/dist/commands/rule-author-teardown.test.d.ts.map +1 -0
- package/dist/commands/rule-author-teardown.test.js +123 -0
- package/dist/commands/rule-author-teardown.test.js.map +1 -0
- package/dist/commands/rule-author.d.ts +1 -0
- package/dist/commands/rule-author.d.ts.map +1 -1
- package/dist/commands/rule-author.js +143 -2
- package/dist/commands/rule-author.js.map +1 -1
- package/dist/commands/spine-authored-cert-corpus.d.ts +15 -0
- package/dist/commands/spine-authored-cert-corpus.d.ts.map +1 -1
- package/dist/commands/spine-authored-cert-corpus.js +17 -1
- package/dist/commands/spine-authored-cert-corpus.js.map +1 -1
- package/dist/commands/spine-authored-cert-corpus.test.js +440 -4
- package/dist/commands/spine-authored-cert-corpus.test.js.map +1 -1
- package/dist/commands/spine-authored-materialize.d.ts +55 -0
- package/dist/commands/spine-authored-materialize.d.ts.map +1 -0
- package/dist/commands/spine-authored-materialize.js +315 -0
- package/dist/commands/spine-authored-materialize.js.map +1 -0
- package/dist/commands/spine-cert-materialize.d.ts.map +1 -1
- package/dist/commands/spine-cert-materialize.js +17 -0
- package/dist/commands/spine-cert-materialize.js.map +1 -1
- package/dist/commands/spine-cert-persist.d.ts +17 -1
- package/dist/commands/spine-cert-persist.d.ts.map +1 -1
- package/dist/commands/spine-cert-persist.js +17 -5
- package/dist/commands/spine-cert-persist.js.map +1 -1
- package/dist/commands/spine-cert-persist.test.js +60 -0
- package/dist/commands/spine-cert-persist.test.js.map +1 -1
- package/dist/commands/spine-cert-run-corpus.d.ts +18 -28
- package/dist/commands/spine-cert-run-corpus.d.ts.map +1 -1
- package/dist/commands/spine-cert-run-corpus.js +162 -21
- package/dist/commands/spine-cert-run-corpus.js.map +1 -1
- package/dist/commands/spine-derive-labels.d.ts.map +1 -1
- package/dist/commands/spine-derive-labels.js +9 -1
- package/dist/commands/spine-derive-labels.js.map +1 -1
- package/dist/commands/spine-freeze-orchestration.test.d.ts +2 -0
- package/dist/commands/spine-freeze-orchestration.test.d.ts.map +1 -0
- package/dist/commands/spine-freeze-orchestration.test.js +468 -0
- package/dist/commands/spine-freeze-orchestration.test.js.map +1 -0
- package/dist/commands/spine-freeze-split.d.ts +10 -0
- package/dist/commands/spine-freeze-split.d.ts.map +1 -0
- package/dist/commands/spine-freeze-split.js +131 -0
- package/dist/commands/spine-freeze-split.js.map +1 -0
- package/dist/commands/spine-windtunnel.d.ts +35 -0
- package/dist/commands/spine-windtunnel.d.ts.map +1 -1
- package/dist/commands/spine-windtunnel.js +47 -7
- package/dist/commands/spine-windtunnel.js.map +1 -1
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -1
- package/dist/spine-fixture-ancestry.d.ts +20 -0
- package/dist/spine-fixture-ancestry.d.ts.map +1 -0
- package/dist/spine-fixture-ancestry.js +46 -0
- package/dist/spine-fixture-ancestry.js.map +1 -0
- package/dist/spine-fixture-ancestry.test.d.ts +2 -0
- package/dist/spine-fixture-ancestry.test.d.ts.map +1 -0
- package/dist/spine-fixture-ancestry.test.js +62 -0
- package/dist/spine-fixture-ancestry.test.js.map +1 -0
- package/dist/spine-freeze-proof.d.ts +89 -0
- package/dist/spine-freeze-proof.d.ts.map +1 -0
- package/dist/spine-freeze-proof.js +237 -0
- package/dist/spine-freeze-proof.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-author.js","sourceRoot":"","sources":["../../src/commands/rule-author.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,+EAA+E;AAC/E,kFAAkF;AAClF,4EAA4E;AAC5E,6EAA6E;AAC7E,uFAAuF;AAEvF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"rule-author.js","sourceRoot":"","sources":["../../src/commands/rule-author.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AuthoredControlsDeps, GroundTruthLabel, ResolvedPrDiff, SplitArtifact, Stage4VerifierDeps } from '@mmnto/totem';
|
|
2
|
+
import type { FreezeBinding } from '../spine-freeze-proof.js';
|
|
2
3
|
import type { CertifyingCorpus } from './spine-windtunnel.js';
|
|
3
4
|
export interface BuildAuthoredCertifyingCorpusDeps {
|
|
4
5
|
/** `.totem` dir holding `spine/authored-rules.yaml` + the authoring-ledger. */
|
|
@@ -23,6 +24,20 @@ export interface BuildAuthoredCertifyingCorpusDeps {
|
|
|
23
24
|
now: string;
|
|
24
25
|
/** Optional §4 differential-evaluator injection for `deriveAuthoredControls` (defaults to the real one). */
|
|
25
26
|
authoredControlsDeps?: AuthoredControlsDeps;
|
|
27
|
+
/**
|
|
28
|
+
* R1: the PROVEN freeze binding for a content-addressed `expectedSplitRef`
|
|
29
|
+
* (constructed ONLY by `resolveProvenFreezeBinding` at the cert-run boundary —
|
|
30
|
+
* this builder is git-free and never proves). Absent on a legacy free-text run;
|
|
31
|
+
* absent on a content-addressed run ⇒ the intake's total partition fails loud.
|
|
32
|
+
*/
|
|
33
|
+
freezeBinding?: FreezeBinding;
|
|
34
|
+
/**
|
|
35
|
+
* §5.2 leakage semantics (#2294 couple, option (a)): fixture PRs the git-holding
|
|
36
|
+
* run boundary PROVED strictly pre-window by ancestry to the artifact's
|
|
37
|
+
* cutBoundarySha (`verifyPreWindowFixturePrs`). Threaded to the intake gate and
|
|
38
|
+
* the §6 deriver; absent/empty ⇒ strict train-only, byte-unchanged.
|
|
39
|
+
*/
|
|
40
|
+
verifiedPreWindowFixturePrs?: ReadonlySet<number>;
|
|
26
41
|
}
|
|
27
42
|
/**
|
|
28
43
|
* Assemble an AUTHORED `CertifyingCorpus` from `.totem/spine/authored-rules.yaml`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spine-authored-cert-corpus.d.ts","sourceRoot":"","sources":["../../src/commands/spine-authored-cert-corpus.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,oBAAoB,EAEpB,gBAAgB,EAEhB,cAAc,EACd,aAAa,EACb,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,WAAW,iCAAiC;IAChD,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IAKjB;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,KAAK,EAAE,aAAa,CAAC;IACrB,uFAAuF;IACvF,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,wEAAwE;IACxE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,4GAA4G;IAC5G,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"spine-authored-cert-corpus.d.ts","sourceRoot":"","sources":["../../src/commands/spine-authored-cert-corpus.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,oBAAoB,EAEpB,gBAAgB,EAEhB,cAAc,EACd,aAAa,EACb,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,WAAW,iCAAiC;IAChD,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IAKjB;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,KAAK,EAAE,aAAa,CAAC;IACrB,uFAAuF;IACvF,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,wEAAwE;IACxE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,4GAA4G;IAC5G,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,iCAAiC,GACtC,OAAO,CAAC,gBAAgB,CAAC,CAqO3B"}
|
|
@@ -66,7 +66,20 @@ export async function buildAuthoredCertifyingCorpus(deps) {
|
|
|
66
66
|
// cover (non-empty-but-stale): step-0 empty → no-mint stale → step-3 verdict/binding (Q3 layered).
|
|
67
67
|
// The producer establishes eligibility/identity; NEVER construct AuthoredRuleRecord[] ad hoc or
|
|
68
68
|
// read YAML→record here.
|
|
69
|
-
|
|
69
|
+
// R1: a content-addressed expectedSplitRef binds the run to a FROZEN artifact — the caller
|
|
70
|
+
// resolves + PROVES the binding at the cert-run boundary (`resolveProvenFreezeBinding`) and
|
|
71
|
+
// threads it here, or the intake's own content-ref gate voids the verifyOnly re-derive
|
|
72
|
+
// (CR #2293 round 1: the cert re-derive ran bindingless). This builder stays git-free:
|
|
73
|
+
// it CONSUMES a proven binding, never constructs one (the never-unverified-binding
|
|
74
|
+
// invariant — proof lives with the boundary that has git).
|
|
75
|
+
const authorResult = runRuleAuthor(deps.totemDir, {
|
|
76
|
+
judgedBy,
|
|
77
|
+
verifyOnly: true,
|
|
78
|
+
...(deps.freezeBinding !== undefined ? { freezeBinding: deps.freezeBinding } : {}),
|
|
79
|
+
...(deps.verifiedPreWindowFixturePrs !== undefined
|
|
80
|
+
? { verifiedPreWindowFixturePrs: deps.verifiedPreWindowFixturePrs }
|
|
81
|
+
: {}),
|
|
82
|
+
});
|
|
70
83
|
// 2. rejected.length === 0 precondition: a partially-invalid authored file is broken
|
|
71
84
|
// cert input — never certify the eligible subset (fail loud, not a partial corpus).
|
|
72
85
|
if (authorResult.rejected.length > 0) {
|
|
@@ -165,6 +178,9 @@ export async function buildAuthoredCertifyingCorpus(deps) {
|
|
|
165
178
|
split: deps.split,
|
|
166
179
|
provenanceByRule,
|
|
167
180
|
...(deps.authoredControlsDeps ? { deps: deps.authoredControlsDeps } : {}),
|
|
181
|
+
...(deps.verifiedPreWindowFixturePrs !== undefined
|
|
182
|
+
? { verifiedPreWindowFixturePrs: deps.verifiedPreWindowFixturePrs }
|
|
183
|
+
: {}),
|
|
168
184
|
});
|
|
169
185
|
return {
|
|
170
186
|
rules,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spine-authored-cert-corpus.js","sourceRoot":"","sources":["../../src/commands/spine-authored-cert-corpus.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,iFAAiF;AACjF,oFAAoF;AACpF,qFAAqF;AACrF,gFAAgF;AAChF,qFAAqF;AACrF,oFAAoF;AACpF,6EAA6E;AAC7E,EAAE;AACF,iFAAiF;AACjF,qFAAqF;AACrF,iFAAiF;
|
|
1
|
+
{"version":3,"file":"spine-authored-cert-corpus.js","sourceRoot":"","sources":["../../src/commands/spine-authored-cert-corpus.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,iFAAiF;AACjF,oFAAoF;AACpF,qFAAqF;AACrF,gFAAgF;AAChF,qFAAqF;AACrF,oFAAoF;AACpF,6EAA6E;AAC7E,EAAE;AACF,iFAAiF;AACjF,qFAAqF;AACrF,iFAAiF;AA0DjF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,IAAuC;IAEvC,MAAM,EACJ,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,GACX,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACjC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAErE,sFAAsF;IACtF,uFAAuF;IACvF,yFAAyF;IACzF,uFAAuF;IACvF,2FAA2F;IAC3F,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAEjC,sFAAsF;IACtF,yFAAyF;IACzF,yFAAyF;IACzF,6FAA6F;IAC7F,6FAA6F;IAC7F,6FAA6F;IAC7F,4FAA4F;IAC5F,2FAA2F;IAC3F,oGAAoG;IACpG,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,+FAA+F,EAC/F,gGAAgG,CACjG,CAAC;IACJ,CAAC;IACD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAwC,CAAC;IACvE,KAAK,MAAM,KAAK,IAAI,WAAW;QAAE,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAC1E,CAAC;IACF,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,sDAAsD,SAAS,CAAC,IAAI,4BAA4B;YAC9F,IAAI,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,uDAAuD,EAC5F,oHAAoH,CACrH,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAE,CAAC;IAEpC,yFAAyF;IACzF,4FAA4F;IAC5F,gGAAgG;IAChG,mGAAmG;IACnG,mGAAmG;IACnG,sGAAsG;IACtG,mGAAmG;IACnG,4BAA4B;IAC5B,8FAA8F;IAC9F,+FAA+F;IAC/F,0FAA0F;IAC1F,0FAA0F;IAC1F,sFAAsF;IACtF,8DAA8D;IAC9D,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE;QAChD,QAAQ;QACR,UAAU,EAAE,IAAI;QAChB,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,IAAI,CAAC,2BAA2B,KAAK,SAAS;YAChD,CAAC,CAAC,EAAE,2BAA2B,EAAE,IAAI,CAAC,2BAA2B,EAAE;YACnE,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC;IAEH,qFAAqF;IACrF,uFAAuF;IACvF,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC9E,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,yBAAyB,YAAY,CAAC,QAAQ,CAAC,MAAM,yCAAyC;YAC5F,kCAAkC,OAAO,EAAE,EAC7C,+FAA+F;YAC7F,+CAA+C,CAClD,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,8EAA8E,EAC9E,mGAAmG,CACpG,CAAC;IACJ,CAAC;IAED,oFAAoF;IACpF,uFAAuF;IACvF,mFAAmF;IACnF,gFAAgF;IAChF,mEAAmE;IACnE,2FAA2F;IAC3F,uFAAuF;IACvF,qFAAqF;IACrF,0FAA0F;IAC1F,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAmC,CAAC;IACrE,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,6DAA6D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa;gBAC3F,iDAAiD,EACnD,oFAAoF,CACrF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7C,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,+BAA+B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,+BAA+B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS;gBAC5G,oCAAoC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,sCAAsC;gBACrG,6CAA6C,EAC/C,8GAA8G,CAC/G,CAAC;QACJ,CAAC;QACD,4FAA4F;QAC5F,sFAAsF;QACtF,6FAA6F;QAC7F,0FAA0F;QAC1F,0FAA0F;QAC1F,IAAI,KAAK,CAAC,qBAAqB,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACtD,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,+BAA+B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB;gBACrE,IAAI,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,gDAAgD;gBAC9F,aAAa,IAAI,CAAC,QAAQ,CAAC,0DAA0D,EACvF,uFAAuF,CACxF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,wEAAwE;IACxE,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,MAAM,eAAe,CACzC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,EACxE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CACvC,CAAC;IAEF,qFAAqF;IACrF,oFAAoF;IACpF,2DAA2D;IAC3D,MAAM,YAAY,GAAG,aAAa,CAAC,gBAAgB,CAAC,OAAO;SACxD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,kBAAkB,CAAC;SACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAC9B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,yBAAyB,YAAY,CAAC,MAAM,kDAAkD;YAC5F,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,2DAA2D,EAC9F,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,iFAAiF;IACjF,oFAAoF;IACpF,0FAA0F;IAC1F,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAClF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,8FAA8F;YAC5F,wBAAwB,EAC1B,wGAAwG,CACzG,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,gFAAgF;IAChF,0EAA0E;IAC1E,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,mFAAmF;QACnF,oFAAoF;QACpF,6EAA6E;QAC7E,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,+BAA+B,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI;gBAClG,yFAAyF,EAC3F,oFAAoF,CACrF,CAAC;QACJ,CAAC;QACD,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,kDAAkD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,2BAA2B;gBAClG,4DAA4D,EAC9D,8FAA8F,CAC/F,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnB,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,iFAAiF;IACjF,wFAAwF;IACxF,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CAAC;QACpD,KAAK;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,gBAAgB;QAChB,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,IAAI,CAAC,2BAA2B,KAAK,SAAS;YAChD,CAAC,CAAC,EAAE,2BAA2B,EAAE,IAAI,CAAC,2BAA2B,EAAE;YACnE,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -4,8 +4,10 @@ import * as os from 'node:os';
|
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
6
|
import { stringify } from 'yaml';
|
|
7
|
+
import { CertCorpusSeedSchema, firingLabelId, scoreWindtunnel, WindtunnelLockSchema, } from '@mmnto/totem';
|
|
7
8
|
import { runRuleAuthor } from '../authored-rule-intake.js';
|
|
8
9
|
import { buildAuthoredCertifyingCorpus, } from './spine-authored-cert-corpus.js';
|
|
10
|
+
import { materializeAuthored } from './spine-authored-materialize.js';
|
|
9
11
|
import { assembleAuthoredCertifyingCorpus, resolveCertifyingCorpusProvider, } from './spine-cert-run-corpus.js';
|
|
10
12
|
// ─── Fixtures (mirror the slice-2/3/4 + authored-controls tests) ──────────────
|
|
11
13
|
const sha = (n) => String(n).padStart(40, '0');
|
|
@@ -242,9 +244,12 @@ describe('resolveCertifyingCorpusProvider — producerKind dispatch (D2 async si
|
|
|
242
244
|
});
|
|
243
245
|
/** A minimal lock cast — the resolver only reads producerKind / authored / integrity shas. */
|
|
244
246
|
const lock = (overrides) => ({ controls: { integrity: {} }, ...overrides });
|
|
245
|
-
it('a mined lock (explicit or absent) resolves to a provider
|
|
246
|
-
|
|
247
|
-
|
|
247
|
+
it('a mined lock (explicit or absent) resolves to a { provider, score } bundle', async () => {
|
|
248
|
+
for (const overrides of [{ producerKind: 'mined' }, {}]) {
|
|
249
|
+
const resolved = await resolveCertifyingCorpusProvider(lock(overrides), inputs());
|
|
250
|
+
expect(resolved.provider).toBeTypeOf('function');
|
|
251
|
+
expect(resolved.score).toBeTypeOf('function');
|
|
252
|
+
}
|
|
248
253
|
});
|
|
249
254
|
it('an authored lock WITHOUT an `authored` block fails loud (require-when-authored)', async () => {
|
|
250
255
|
await expect(resolveCertifyingCorpusProvider(lock({ producerKind: 'authored' }), inputs())).rejects.toThrow(/run-input block/);
|
|
@@ -266,7 +271,9 @@ describe('resolveCertifyingCorpusProvider — producerKind dispatch (D2 async si
|
|
|
266
271
|
authored: { expectedSplitRef: SPLIT_REF },
|
|
267
272
|
controls: { integrity: { prDiffsSha, groundTruthSha } },
|
|
268
273
|
});
|
|
269
|
-
const provider = await resolveCertifyingCorpusProvider(authoredLock, inputs({ authoredControlsDeps: diffDeps('differential-holds') }));
|
|
274
|
+
const { provider, score } = await resolveCertifyingCorpusProvider(authoredLock, inputs({ authoredControlsDeps: diffDeps('differential-holds') }));
|
|
275
|
+
// D4: the §8 single home also binds the producer-kind scorer alongside the provider.
|
|
276
|
+
expect(score).toBeTypeOf('function');
|
|
270
277
|
const corpus = await provider(authoredLock);
|
|
271
278
|
expect(corpus.authoredControls).toBeDefined();
|
|
272
279
|
expect(corpus.authoredControls.positive).toHaveLength(1);
|
|
@@ -343,4 +350,433 @@ describe('assembleAuthoredCertifyingCorpus (D2.6 derive-path sibling)', () => {
|
|
|
343
350
|
await expect(assembleAuthoredCertifyingCorpus(opts(), authoredLock)).rejects.toThrow(/pr-diffs\.json integrity/);
|
|
344
351
|
});
|
|
345
352
|
});
|
|
353
|
+
// ─── 6. Slice D4 — the reachable flip: resolved.score(base) end-to-end ─────────
|
|
354
|
+
//
|
|
355
|
+
// The whole-path couple strategy reviews (ruling 2318Z, Q4 — 4 seams): (1) authored
|
|
356
|
+
// corpus resolution (§8 single-home), (2) the no-mint verifyOnly gate FIRING, (3)
|
|
357
|
+
// scoreAuthoredWindtunnel invocation (Q1 threading guard), (4) the Gate-2 emit
|
|
358
|
+
// (verdict-inert, §1(k)-guarded). These rows drive a REAL resolve → real scorer
|
|
359
|
+
// (never a mock) → real deriveGate2Eligibility, reusing the D1–D3 fixtures.
|
|
360
|
+
describe('ADR-112 D4 — reachable flip: resolved.score(base) end-to-end', () => {
|
|
361
|
+
let gate1Dir;
|
|
362
|
+
beforeEach(() => {
|
|
363
|
+
gate1Dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-d4-gate1-'));
|
|
364
|
+
});
|
|
365
|
+
afterEach(() => {
|
|
366
|
+
fs.rmSync(gate1Dir, { recursive: true, force: true });
|
|
367
|
+
});
|
|
368
|
+
const inputs = (extra = {}) => ({
|
|
369
|
+
gate1Dir,
|
|
370
|
+
stage4: stage4(),
|
|
371
|
+
now: NOW,
|
|
372
|
+
totemDir,
|
|
373
|
+
...extra,
|
|
374
|
+
});
|
|
375
|
+
const lock = (overrides) => ({ controls: { integrity: {} }, ...overrides });
|
|
376
|
+
/** An authored lock bound to a substrate's integrity shas. */
|
|
377
|
+
const authoredLock = (prDiffsSha, groundTruthSha) => lock({
|
|
378
|
+
producerKind: 'authored',
|
|
379
|
+
authored: { expectedSplitRef: SPLIT_REF },
|
|
380
|
+
controls: { integrity: { prDiffsSha, groundTruthSha } },
|
|
381
|
+
});
|
|
382
|
+
/** A ScorerInput `base` (exposure floors 0 so a clean run reaches PASS). The authored
|
|
383
|
+
* closure strips `positiveControlTargets` (Q1 guard); the mined closure keeps it. */
|
|
384
|
+
const baseScorerInput = (over) => ({
|
|
385
|
+
firings: [],
|
|
386
|
+
groundTruth: new Map(),
|
|
387
|
+
positiveControlTargets: [],
|
|
388
|
+
mintedRuleIds: [],
|
|
389
|
+
cullRateThreshold: 0.5,
|
|
390
|
+
exposureFloors: {
|
|
391
|
+
activeRulesEvaluated: 0,
|
|
392
|
+
filesTouchedInWindow: 0,
|
|
393
|
+
positiveControlsExercised: 0,
|
|
394
|
+
},
|
|
395
|
+
actualExposure: {
|
|
396
|
+
activeRulesEvaluated: 1,
|
|
397
|
+
filesTouchedInWindow: 5,
|
|
398
|
+
positiveControlsExercised: 1,
|
|
399
|
+
},
|
|
400
|
+
...over,
|
|
401
|
+
});
|
|
402
|
+
const firing = (ruleId, pr, controlKind, matchedLine = 'gen();', filePath = 'src/a.ts') => ({
|
|
403
|
+
ruleId,
|
|
404
|
+
pr,
|
|
405
|
+
filePath,
|
|
406
|
+
matchedLine,
|
|
407
|
+
controlKind,
|
|
408
|
+
labelId: firingLabelId(ruleId, pr, filePath, matchedLine),
|
|
409
|
+
});
|
|
410
|
+
/** Resolve an authored run over a split with held-out prs, then read the minted ruleId
|
|
411
|
+
* the real corpus derived (the Gate-2 join-back key). */
|
|
412
|
+
const resolveAuthored = async (split) => {
|
|
413
|
+
writeAuthoredYaml(totemDir);
|
|
414
|
+
const { prDiffsSha, groundTruthSha } = writeSubstrate(gate1Dir, { split });
|
|
415
|
+
const alock = authoredLock(prDiffsSha, groundTruthSha);
|
|
416
|
+
const resolved = await resolveCertifyingCorpusProvider(alock, inputs({ authoredControlsDeps: diffDeps('differential-holds') }));
|
|
417
|
+
const corpus = await resolved.provider(alock);
|
|
418
|
+
const ruleId = corpus.authoredControls.positive[0].targetRuleId;
|
|
419
|
+
return { resolved, ruleId };
|
|
420
|
+
};
|
|
421
|
+
it('(i) authored happy path: resolve → real scoreAuthoredWindtunnel → PASS + Gate-2 eligible', async () => {
|
|
422
|
+
const split = { ...SPLIT, trainPrs: [1], heldOutPrs: [2] };
|
|
423
|
+
const { resolved, ruleId } = await resolveAuthored(split);
|
|
424
|
+
const ctrl = firing(ruleId, 1, 'positive', 'ctrl();'); // train-side positive control
|
|
425
|
+
const heldCorpus = firing(ruleId, 2, 'corpus', 'gen();'); // held-out generalization
|
|
426
|
+
const scored = resolved.score(baseScorerInput({
|
|
427
|
+
firings: [ctrl, heldCorpus],
|
|
428
|
+
groundTruth: new Map([
|
|
429
|
+
[ctrl.labelId, 'TP'],
|
|
430
|
+
[heldCorpus.labelId, 'TP'],
|
|
431
|
+
]),
|
|
432
|
+
mintedRuleIds: [ruleId],
|
|
433
|
+
positiveControlTargets: [{ pr: 1, targetRuleId: ruleId }],
|
|
434
|
+
}));
|
|
435
|
+
expect(scored.kind).toBe('authored');
|
|
436
|
+
if (scored.kind !== 'authored')
|
|
437
|
+
throw new Error('unreachable');
|
|
438
|
+
expect(scored.verdict.verdict).toBe('PASS');
|
|
439
|
+
// O3 metric: the held-out corpus firing counts; the train-side control does not.
|
|
440
|
+
expect(scored.verdict.heldOutActivationsByRule).toEqual({ [ruleId]: 1 });
|
|
441
|
+
// Gate-2: a non-disqualified window's survivor with heldOut>0 is eligible (§1(k) satisfied).
|
|
442
|
+
expect(scored.gate2.windowDisqualified).toBe(false);
|
|
443
|
+
expect(scored.gate2.eligibleRuleIds).toEqual([ruleId]);
|
|
444
|
+
});
|
|
445
|
+
it('(ii) no-mint gate FIRES: a would-be-minted rule ⇒ GATE_INVALID at resolve, scorer unreachable, ledger byte-unchanged', async () => {
|
|
446
|
+
writeAuthoredYaml(totemDir); // seeds YAML + ledger (rule → `unchanged` on re-read)
|
|
447
|
+
const { prDiffsSha, groundTruthSha } = writeSubstrate(gate1Dir);
|
|
448
|
+
const ledgerPath = path.join(totemDir, 'spine', 'authoring-ledger.ndjson');
|
|
449
|
+
const ledgerBefore = fs.readFileSync(ledgerPath, 'utf-8');
|
|
450
|
+
// agy's dynamic in-memory mutate: rewrite ONLY the YAML to add a SECOND (unledgered)
|
|
451
|
+
// rule — the cert re-derive would MINT it. Do NOT re-seed the ledger (no runRuleAuthor).
|
|
452
|
+
fs.writeFileSync(path.join(totemDir, 'spine', 'authored-rules.yaml'), stringify({
|
|
453
|
+
splitRef: SPLIT_REF,
|
|
454
|
+
authoredAfterSplit: true,
|
|
455
|
+
heldOutNonInspectionAttestation: true,
|
|
456
|
+
rules: [
|
|
457
|
+
authoredRuleInput(),
|
|
458
|
+
authoredRuleInput({ targetDefect: 'a SECOND distinct defect' }),
|
|
459
|
+
],
|
|
460
|
+
}), 'utf-8');
|
|
461
|
+
// The gate throws during the resolver's EAGER build — before `score` is returned (a
|
|
462
|
+
// stronger guarantee than a scorer spy: the closure never exists to be called).
|
|
463
|
+
await expect(resolveCertifyingCorpusProvider(authoredLock(prDiffsSha, groundTruthSha), inputs({ authoredControlsDeps: diffDeps('differential-holds') }))).rejects.toThrow(/would be authored \(minted\/revised\)/);
|
|
464
|
+
// §8 no-mint: the cert re-derive is read-only — the gate fired before Pass-2 append.
|
|
465
|
+
expect(fs.readFileSync(ledgerPath, 'utf-8')).toBe(ledgerBefore);
|
|
466
|
+
});
|
|
467
|
+
it('(v) mined path regression: producerKind absent ⇒ kind mined, NO gate2 key, verdict byte-identical to scoreWindtunnel', async () => {
|
|
468
|
+
const resolved = await resolveCertifyingCorpusProvider(lock({}), inputs());
|
|
469
|
+
const ctrl = firing('mined-rule', 1, 'positive', 'ctrl();');
|
|
470
|
+
const base = baseScorerInput({
|
|
471
|
+
firings: [ctrl],
|
|
472
|
+
groundTruth: new Map([[ctrl.labelId, 'TP']]),
|
|
473
|
+
mintedRuleIds: ['mined-rule'],
|
|
474
|
+
positiveControlTargets: [{ pr: 1, targetRuleId: 'mined-rule' }],
|
|
475
|
+
});
|
|
476
|
+
const scored = resolved.score(base);
|
|
477
|
+
expect(scored.kind).toBe('mined');
|
|
478
|
+
// The mined bundle carries NO Gate-2 surface at all (not an empty one).
|
|
479
|
+
expect('gate2' in scored).toBe(false);
|
|
480
|
+
// Byte-identity: the mined closure is a pass-through to the real scoreWindtunnel.
|
|
481
|
+
expect(scored.verdict).toEqual(scoreWindtunnel(base));
|
|
482
|
+
});
|
|
483
|
+
it('(vi) cross-partition leakage guard: a train-only-activating rule → zero held-out → excluded from Gate-2 despite PASS', async () => {
|
|
484
|
+
const split = { ...SPLIT, trainPrs: [1], heldOutPrs: [2] };
|
|
485
|
+
// Structural guard: the partitions the metric keys off are disjoint (heldOut ∩ train = ∅).
|
|
486
|
+
expect(split.heldOutPrs.some((pr) => split.trainPrs.includes(pr))).toBe(false);
|
|
487
|
+
const { resolved, ruleId } = await resolveAuthored(split);
|
|
488
|
+
const ctrl = firing(ruleId, 1, 'positive', 'ctrl();'); // train-side ONLY — no held-out corpus firing
|
|
489
|
+
const scored = resolved.score(baseScorerInput({
|
|
490
|
+
firings: [ctrl],
|
|
491
|
+
groundTruth: new Map([[ctrl.labelId, 'TP']]),
|
|
492
|
+
mintedRuleIds: [ruleId],
|
|
493
|
+
positiveControlTargets: [{ pr: 1, targetRuleId: ruleId }],
|
|
494
|
+
}));
|
|
495
|
+
expect(scored.kind).toBe('authored');
|
|
496
|
+
if (scored.kind !== 'authored')
|
|
497
|
+
throw new Error('unreachable');
|
|
498
|
+
// Clean rare-defect window: the verdict PASSES…
|
|
499
|
+
expect(scored.verdict.verdict).toBe('PASS');
|
|
500
|
+
expect(scored.verdict.heldOutActivationsByRule).toEqual({ [ruleId]: 0 });
|
|
501
|
+
// …yet Gate-2 excludes the rule (survivor recorded, ineligible at zero held-out).
|
|
502
|
+
expect(scored.gate2.survivors).toEqual([
|
|
503
|
+
{ ruleId, heldOutActivations: 0, gate2Eligible: false },
|
|
504
|
+
]);
|
|
505
|
+
expect(scored.gate2.eligibleRuleIds).toEqual([]);
|
|
506
|
+
});
|
|
507
|
+
it('(vii) unlabeled-demotion partition: held-out UNLABELED corpus firing ⇒ HONEST-NEGATIVE, no FP, metric verdict-inert', async () => {
|
|
508
|
+
const split = { ...SPLIT, trainPrs: [1], heldOutPrs: [2] };
|
|
509
|
+
const { resolved, ruleId } = await resolveAuthored(split);
|
|
510
|
+
const ctrl = firing(ruleId, 1, 'positive', 'ctrl();'); // train-side, TP-labeled
|
|
511
|
+
const unlabeled = firing(ruleId, 2, 'corpus', 'gen();'); // held-out, NO ground-truth entry
|
|
512
|
+
const scored = resolved.score(baseScorerInput({
|
|
513
|
+
firings: [ctrl, unlabeled],
|
|
514
|
+
groundTruth: new Map([[ctrl.labelId, 'TP']]),
|
|
515
|
+
mintedRuleIds: [ruleId],
|
|
516
|
+
positiveControlTargets: [{ pr: 1, targetRuleId: ruleId }],
|
|
517
|
+
}));
|
|
518
|
+
expect(scored.kind).toBe('authored');
|
|
519
|
+
if (scored.kind !== 'authored')
|
|
520
|
+
throw new Error('unreachable');
|
|
521
|
+
// Clean demotion — needs adjudication, NOT a FAIL/FP.
|
|
522
|
+
expect(scored.verdict.verdict).toBe('HONEST-NEGATIVE');
|
|
523
|
+
expect(scored.verdict.needsAdjudication).toContain(unlabeled.labelId);
|
|
524
|
+
expect(scored.gate2.windowDisqualified).toBe(false);
|
|
525
|
+
// The O3 metric is label-independent (verdict-inert): the unlabeled held-out firing still counts.
|
|
526
|
+
expect(scored.verdict.heldOutActivationsByRule).toEqual({ [ruleId]: 1 });
|
|
527
|
+
});
|
|
528
|
+
it('(viii) §6 cull-unbroken: a fix-shaped differential ⇒ positive:[] + illegitimate non-emission ⇒ FAIL, never a mined PASS via empty positives (codex assertion #1)', async () => {
|
|
529
|
+
writeAuthoredYaml(totemDir);
|
|
530
|
+
const split = { ...SPLIT, trainPrs: [1], heldOutPrs: [2] };
|
|
531
|
+
const { prDiffsSha, groundTruthSha } = writeSubstrate(gate1Dir, { split });
|
|
532
|
+
const alock = authoredLock(prDiffsSha, groundTruthSha);
|
|
533
|
+
// fix-shaped: the §4 differential culls every fixture to an illegitimate non-emission —
|
|
534
|
+
// NOTHING reaches positive[]. resolveAuthored is not reusable here (it reads positive[0]).
|
|
535
|
+
const resolved = await resolveCertifyingCorpusProvider(alock, inputs({ authoredControlsDeps: diffDeps('fix-shaped') }));
|
|
536
|
+
const corpus = await resolved.provider(alock);
|
|
537
|
+
// The §6 cull holds end-to-end: a fix-shaped fixture lands in nonEmissions, never positive[].
|
|
538
|
+
expect(corpus.authoredControls.positive).toEqual([]);
|
|
539
|
+
expect(corpus.authoredControls.nonEmissions).toHaveLength(1);
|
|
540
|
+
expect(corpus.authoredControls.nonEmissions[0].class).toBe('illegitimate');
|
|
541
|
+
const ruleId = corpus.rules[0].lessonHash;
|
|
542
|
+
// The hazard codex assertion #1 guards: an empty positive control MUST NOT let the run
|
|
543
|
+
// degenerate to a mined PASS via positiveControlTargets:[] — the illegitimate non-emission
|
|
544
|
+
// FAILs the whole window. (Core-altitude sibling: windtunnel-scorer-authored.test.ts codex-1.)
|
|
545
|
+
const scored = resolved.score(baseScorerInput({
|
|
546
|
+
firings: [],
|
|
547
|
+
groundTruth: new Map(),
|
|
548
|
+
mintedRuleIds: [ruleId],
|
|
549
|
+
positiveControlTargets: [],
|
|
550
|
+
}));
|
|
551
|
+
expect(scored.kind).toBe('authored');
|
|
552
|
+
if (scored.kind !== 'authored')
|
|
553
|
+
throw new Error('unreachable');
|
|
554
|
+
// NOT a silent mined PASS — a structural, no-claim FAIL (precision null, never 0).
|
|
555
|
+
expect(scored.verdict.verdict).toBe('FAIL');
|
|
556
|
+
expect(scored.verdict.precision).toBeNull();
|
|
557
|
+
expect(scored.verdict.authoredControlGate.illegitimate).toBe(1);
|
|
558
|
+
expect(scored.verdict.authoredControlGate.effect).toBe('fail-illegitimate');
|
|
559
|
+
// Gate-2: illegitimate > 0 ⇒ window disqualified ⇒ no survivor eligible (Q4).
|
|
560
|
+
expect(scored.gate2.windowDisqualified).toBe(true);
|
|
561
|
+
expect(scored.gate2.eligibleRuleIds).toEqual([]);
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
// ─── 7. Slice D5 — the authored materialize/freeze seam (producer → consumer) ──
|
|
565
|
+
//
|
|
566
|
+
// `materializeAuthored` is the sibling authored producer: it FREEZES the window-wide
|
|
567
|
+
// substrate + a `frozenAt` split + the `producerKind:'authored'` lock, gated by the
|
|
568
|
+
// §5.1/§5.3 freeze preconditions. Git is injected so the producer is exercised without
|
|
569
|
+
// a real clone (the mined materializer has no unit test at all). Row (i) closes the
|
|
570
|
+
// producer→consumer loop: the PRODUCED lock+substrate drives a real authored resolve.
|
|
571
|
+
describe('ADR-112 D5 — materializeAuthored (authored producer)', () => {
|
|
572
|
+
const AUTHORED_AT = '2026-06-15T12:00:00.000Z';
|
|
573
|
+
const FROZEN_AT = '2026-06-01T00:00:00.000Z'; // strictly BEFORE authoring (Q3 temporal)
|
|
574
|
+
let repoRoot;
|
|
575
|
+
let gate1Dir;
|
|
576
|
+
beforeEach(() => {
|
|
577
|
+
repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-d5-repo-'));
|
|
578
|
+
gate1Dir = path.join(repoRoot, 'gate-1');
|
|
579
|
+
});
|
|
580
|
+
afterEach(() => {
|
|
581
|
+
fs.rmSync(repoRoot, { recursive: true, force: true });
|
|
582
|
+
});
|
|
583
|
+
/** Newest-first metas for PRs 2,1 → corpus [1,2] (all code-touching non-bot). */
|
|
584
|
+
const metas = () => [2, 1].map((pr) => ({
|
|
585
|
+
pr,
|
|
586
|
+
mergeCommit: sha(pr),
|
|
587
|
+
author: 'Dev <dev@example.com>',
|
|
588
|
+
isBotAuthor: false,
|
|
589
|
+
changedFiles: ['src/a.ts'],
|
|
590
|
+
}));
|
|
591
|
+
/** An authored seed: producerKind authored, cutIndex 1 ⇒ train [1] / held-out [2] (floor 0.5). */
|
|
592
|
+
const authoredSeed = (over = {}) => CertCorpusSeedSchema.parse({
|
|
593
|
+
producerKind: 'authored',
|
|
594
|
+
gate: 'gate-1',
|
|
595
|
+
canonicalPath: 'gate-1/windtunnel.lock.json',
|
|
596
|
+
repo: 'mmnto-ai/liquid-city',
|
|
597
|
+
phase: 'certifying',
|
|
598
|
+
selectionRule: {
|
|
599
|
+
state: 'merged',
|
|
600
|
+
predicate: 'code-touching non-bot',
|
|
601
|
+
window: { type: 'all' },
|
|
602
|
+
asOfCommit: sha(999),
|
|
603
|
+
codePathClassifier: { includeGlobs: ['**'], excludeGlobs: [] },
|
|
604
|
+
},
|
|
605
|
+
split: { cutIndex: 1, excludedPrs: [], frozenAt: FROZEN_AT },
|
|
606
|
+
controls: {
|
|
607
|
+
positiveRef: 'gate-1/controls/positive',
|
|
608
|
+
negativeRef: 'gate-1/controls/negative',
|
|
609
|
+
mechanism: 'git-hash-object',
|
|
610
|
+
positive: [], // authored controls are train-side (derived at run), NOT seed-designated
|
|
611
|
+
negative: [],
|
|
612
|
+
},
|
|
613
|
+
fpDefinition: { rubricRef: 'r', groundTruthRef: 'g', adjudicator: 'disposition-derived' },
|
|
614
|
+
cullRateThreshold: 0.1,
|
|
615
|
+
exposureDenominator: {
|
|
616
|
+
activeRulesEvaluated: { floor: 2 },
|
|
617
|
+
filesTouchedInWindow: { floor: 0 },
|
|
618
|
+
positiveControlsExercised: { floor: 0 },
|
|
619
|
+
},
|
|
620
|
+
...over,
|
|
621
|
+
});
|
|
622
|
+
const ctx = (seed) => ({
|
|
623
|
+
seed,
|
|
624
|
+
lcDir: '/unused-git-injected',
|
|
625
|
+
repoRoot,
|
|
626
|
+
cwd: repoRoot,
|
|
627
|
+
totemDir,
|
|
628
|
+
outDir: gate1Dir,
|
|
629
|
+
resolveWithinRepo: (input) => path.resolve(repoRoot, input),
|
|
630
|
+
safeExec: (() => {
|
|
631
|
+
throw new Error('git must be injected');
|
|
632
|
+
}),
|
|
633
|
+
});
|
|
634
|
+
/** Injected git: canned metas + non-empty diffs + a fixed fixtureSha. No `now` — `frozenAt` is
|
|
635
|
+
* the seed's recorded pre-authoring instant (real chronology), never a materialize clock. */
|
|
636
|
+
const gitDeps = (over = {}) => ({
|
|
637
|
+
enumerateMetas: () => metas(),
|
|
638
|
+
resolvePrDiff: (mergeCommit) => ({
|
|
639
|
+
baseSha: sha(500),
|
|
640
|
+
headSha: sha(600),
|
|
641
|
+
diff: `diff ${mergeCommit}\n+forbiddenCall()\n`,
|
|
642
|
+
}),
|
|
643
|
+
computeControlFixtureSha: () => sha(7),
|
|
644
|
+
...over,
|
|
645
|
+
});
|
|
646
|
+
it('(i) produces a valid authored lock + window-wide substrate + frozenAt split', async () => {
|
|
647
|
+
writeAuthoredYaml(totemDir, {
|
|
648
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
649
|
+
});
|
|
650
|
+
await materializeAuthored(ctx(authoredSeed()), gitDeps());
|
|
651
|
+
// Lock: parses, producerKind authored, expectedSplitRef = the ledger's splitRef, no groundTruthSha.
|
|
652
|
+
const lockRaw = JSON.parse(fs.readFileSync(path.join(gate1Dir, 'windtunnel.lock.json'), 'utf-8'));
|
|
653
|
+
const lock = WindtunnelLockSchema.parse(lockRaw);
|
|
654
|
+
expect(lock.producerKind).toBe('authored');
|
|
655
|
+
expect(lock.authored).toEqual({ expectedSplitRef: SPLIT_REF });
|
|
656
|
+
expect(lock.controls.integrity.groundTruthSha).toBeUndefined(); // derive-labels stamps it
|
|
657
|
+
// Split: carries the mechanical frozenAt; train [1] / held-out [2].
|
|
658
|
+
const split = JSON.parse(fs.readFileSync(path.join(gate1Dir, 'split.json'), 'utf-8'));
|
|
659
|
+
expect(split.frozenAt).toBe(FROZEN_AT);
|
|
660
|
+
expect(split.trainPrs).toEqual([1]);
|
|
661
|
+
expect(split.heldOutPrs).toEqual([2]);
|
|
662
|
+
// pr-diffs: WINDOW-WIDE (train ∪ held-out = [1,2]), not held-out-only.
|
|
663
|
+
const prDiffs = JSON.parse(fs.readFileSync(path.join(gate1Dir, 'pr-diffs.json'), 'utf-8'));
|
|
664
|
+
expect(prDiffs.map((d) => d.pr)).toEqual([1, 2]);
|
|
665
|
+
// The train-side positive-control fixture diff was written for the integrity gate.
|
|
666
|
+
expect(fs.existsSync(path.join(repoRoot, 'gate-1/controls/positive/1.diff'))).toBe(true);
|
|
667
|
+
});
|
|
668
|
+
it('(i-consumer) the PRODUCED lock+substrate drives a real authored resolve (producer→consumer)', async () => {
|
|
669
|
+
writeAuthoredYaml(totemDir, {
|
|
670
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
671
|
+
});
|
|
672
|
+
await materializeAuthored(ctx(authoredSeed()), gitDeps());
|
|
673
|
+
// Simulate the `derive-labels` seal: write the answer key + stamp groundTruthSha onto the lock.
|
|
674
|
+
const gtJson = JSON.stringify({});
|
|
675
|
+
fs.writeFileSync(path.join(gate1Dir, 'ground-truth-labels.json'), gtJson, 'utf-8');
|
|
676
|
+
const groundTruthSha = createHash('sha256')
|
|
677
|
+
.update(gtJson.replace(/\r\n/g, '\n'), 'utf-8')
|
|
678
|
+
.digest('hex');
|
|
679
|
+
const lock = WindtunnelLockSchema.parse(JSON.parse(fs.readFileSync(path.join(gate1Dir, 'windtunnel.lock.json'), 'utf-8')));
|
|
680
|
+
const sealedLock = {
|
|
681
|
+
...lock,
|
|
682
|
+
controls: {
|
|
683
|
+
...lock.controls,
|
|
684
|
+
integrity: { ...lock.controls.integrity, groundTruthSha },
|
|
685
|
+
},
|
|
686
|
+
};
|
|
687
|
+
const { provider, score } = await resolveCertifyingCorpusProvider(sealedLock, {
|
|
688
|
+
gate1Dir,
|
|
689
|
+
stage4: stage4(),
|
|
690
|
+
now: NOW,
|
|
691
|
+
totemDir,
|
|
692
|
+
authoredControlsDeps: diffDeps('differential-holds'),
|
|
693
|
+
});
|
|
694
|
+
const corpus = await provider(sealedLock);
|
|
695
|
+
// The authored channel resolved from the PRODUCED substrate (fixture #1 is train-side positive).
|
|
696
|
+
expect(corpus.authoredControls).toBeDefined();
|
|
697
|
+
expect(corpus.authoredControls.positive).toHaveLength(1);
|
|
698
|
+
expect(score).toBeTypeOf('function');
|
|
699
|
+
});
|
|
700
|
+
it('(ii) temporal violation: seed frozenAt AFTER authoring ⇒ GATE_INVALID, nothing written', async () => {
|
|
701
|
+
// A real (undoctored) run: the seed's recorded frozenAt post-dates the rule's authoredAt, so
|
|
702
|
+
// the split was NOT frozen before authoring — a §5.1 leakage event the gate must reject.
|
|
703
|
+
writeAuthoredYaml(totemDir, {
|
|
704
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
705
|
+
});
|
|
706
|
+
const lateSeed = authoredSeed({
|
|
707
|
+
split: { cutIndex: 1, excludedPrs: [], frozenAt: '2026-06-20T00:00:00.000Z' },
|
|
708
|
+
});
|
|
709
|
+
await expect(materializeAuthored(ctx(lateSeed), gitDeps())).rejects.toThrow(/Q3 temporal/);
|
|
710
|
+
// Nothing written: the freeze gate throws BEFORE gate1Dir is created (CR — no partial write).
|
|
711
|
+
expect(fs.existsSync(gate1Dir)).toBe(false);
|
|
712
|
+
});
|
|
713
|
+
it('(vii) absent seed frozenAt ⇒ fail-loud (materialize never stamps its own clock)', async () => {
|
|
714
|
+
// The production-honesty guard (#2287 couple HOLD): with no recorded pre-authoring freeze
|
|
715
|
+
// instant, materialize MUST fail loud — never fall back to a materialize-`now()` freeze.
|
|
716
|
+
writeAuthoredYaml(totemDir, {
|
|
717
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
718
|
+
});
|
|
719
|
+
// Hand-built (not schema-parsed): the parse-time presence guard (strategy#804
|
|
720
|
+
// layered clauses) now rejects this shape at parse, so the materialize-time
|
|
721
|
+
// defense must be proven on its own for programmatic callers. No cast: the
|
|
722
|
+
// absence is refinement-invalid but structurally legal (`frozenAt` is
|
|
723
|
+
// optional), so the fixture keeps full compile-time property checking.
|
|
724
|
+
const noFreezeSeed = {
|
|
725
|
+
...authoredSeed(),
|
|
726
|
+
split: { cutIndex: 1, excludedPrs: [] },
|
|
727
|
+
};
|
|
728
|
+
await expect(materializeAuthored(ctx(noFreezeSeed), gitDeps())).rejects.toThrow(/frozen BEFORE authoring/);
|
|
729
|
+
expect(fs.existsSync(gate1Dir)).toBe(false);
|
|
730
|
+
});
|
|
731
|
+
it('(v) Q2 floor violation: held-out < 50% of the window ⇒ GATE_INVALID', async () => {
|
|
732
|
+
// corpus [1,2,3], cutIndex 2 ⇒ train [1,2] / held-out [3] ⇒ 1/3 < 0.5.
|
|
733
|
+
const threeMetas = [3, 2, 1].map((pr) => ({
|
|
734
|
+
pr,
|
|
735
|
+
mergeCommit: sha(pr),
|
|
736
|
+
author: 'Dev <dev@example.com>',
|
|
737
|
+
isBotAuthor: false,
|
|
738
|
+
changedFiles: ['src/a.ts'],
|
|
739
|
+
}));
|
|
740
|
+
writeAuthoredYaml(totemDir, {
|
|
741
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
742
|
+
});
|
|
743
|
+
await expect(materializeAuthored(ctx(authoredSeed({ split: { cutIndex: 2, excludedPrs: [], frozenAt: FROZEN_AT } })), gitDeps({ enumerateMetas: () => threeMetas }))).rejects.toThrow(/Q2 held-out floor/);
|
|
744
|
+
expect(fs.existsSync(gate1Dir)).toBe(false);
|
|
745
|
+
});
|
|
746
|
+
it('(iii) membership violation: a held-out positive fixture ⇒ GATE_INVALID naming the PR', async () => {
|
|
747
|
+
// fixture pr=2 is the HELD-OUT slice ⇒ §5(2) leakage.
|
|
748
|
+
writeAuthoredYaml(totemDir, {
|
|
749
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(2)] })],
|
|
750
|
+
});
|
|
751
|
+
await expect(materializeAuthored(ctx(authoredSeed()), gitDeps())).rejects.toThrow(/Q3 membership.*#2/s);
|
|
752
|
+
expect(fs.existsSync(gate1Dir)).toBe(false);
|
|
753
|
+
});
|
|
754
|
+
it('(iv) vacuous effective ledger: zero positive-fixture PRs ⇒ GATE_INVALID before any git work', async () => {
|
|
755
|
+
// `runRuleAuthor` intake enforces ≥1 positive fixture per rule, but the ledger reader
|
|
756
|
+
// (`.strict()`, no `.min`) still parses a legacy/hand-edited row with `positiveFixturePrs: []`
|
|
757
|
+
// — the ndjson file IS the boundary the materializer trusts. Degrade the row to that shape.
|
|
758
|
+
writeAuthoredYaml(totemDir, {
|
|
759
|
+
rules: [authoredRuleInput({ authoredAt: AUTHORED_AT, positiveFixtures: [posFixture(1)] })],
|
|
760
|
+
});
|
|
761
|
+
const ledgerFile = path.join(totemDir, 'spine', 'authoring-ledger.ndjson');
|
|
762
|
+
const degraded = fs
|
|
763
|
+
.readFileSync(ledgerFile, 'utf-8')
|
|
764
|
+
.trim()
|
|
765
|
+
.split('\n')
|
|
766
|
+
.map((row) => JSON.stringify({ ...JSON.parse(row), positiveFixturePrs: [] }))
|
|
767
|
+
.join('\n');
|
|
768
|
+
fs.writeFileSync(ledgerFile, `${degraded}\n`, 'utf-8');
|
|
769
|
+
// The non-vacuity gate precedes ALL per-PR git resolution (CR round-2 hoist): a vacuous
|
|
770
|
+
// ledger must cost zero `resolvePrDiff` shell-outs — and, as ever, zero bytes on disk.
|
|
771
|
+
let gitCalls = 0;
|
|
772
|
+
await expect(materializeAuthored(ctx(authoredSeed()), gitDeps({
|
|
773
|
+
resolvePrDiff: (mergeCommit) => {
|
|
774
|
+
gitCalls += 1;
|
|
775
|
+
return { baseSha: sha(500), headSha: sha(600), diff: `diff ${mergeCommit}\n` };
|
|
776
|
+
},
|
|
777
|
+
}))).rejects.toThrow(/no positive-control fixture PRs in the effective authoring-ledger/);
|
|
778
|
+
expect(gitCalls).toBe(0);
|
|
779
|
+
expect(fs.existsSync(gate1Dir)).toBe(false);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
346
782
|
//# sourceMappingURL=spine-authored-cert-corpus.test.js.map
|