@mneme-ai/core 2.52.0 → 2.53.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.
Files changed (45) hide show
  1. package/dist/agent_manifest.d.ts.map +1 -1
  2. package/dist/agent_manifest.js +10 -0
  3. package/dist/agent_manifest.js.map +1 -1
  4. package/dist/catalog_count.d.ts +47 -0
  5. package/dist/catalog_count.d.ts.map +1 -0
  6. package/dist/catalog_count.js +76 -0
  7. package/dist/catalog_count.js.map +1 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +6 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/nemesis/corpus_augmenter.d.ts +69 -0
  13. package/dist/nemesis/corpus_augmenter.d.ts.map +1 -0
  14. package/dist/nemesis/corpus_augmenter.js +164 -0
  15. package/dist/nemesis/corpus_augmenter.js.map +1 -0
  16. package/dist/nemesis/eu_ai_act_stamp.d.ts.map +1 -1
  17. package/dist/nemesis/eu_ai_act_stamp.js +14 -0
  18. package/dist/nemesis/eu_ai_act_stamp.js.map +1 -1
  19. package/dist/nemesis/index.d.ts +3 -0
  20. package/dist/nemesis/index.d.ts.map +1 -1
  21. package/dist/nemesis/index.js +7 -0
  22. package/dist/nemesis/index.js.map +1 -1
  23. package/dist/nemesis/janus.d.ts +93 -0
  24. package/dist/nemesis/janus.d.ts.map +1 -0
  25. package/dist/nemesis/janus.js +160 -0
  26. package/dist/nemesis/janus.js.map +1 -0
  27. package/dist/nemesis/key_setup.d.ts +65 -0
  28. package/dist/nemesis/key_setup.d.ts.map +1 -0
  29. package/dist/nemesis/key_setup.js +173 -0
  30. package/dist/nemesis/key_setup.js.map +1 -0
  31. package/dist/release_gate/probe_coverage.d.ts +16 -1
  32. package/dist/release_gate/probe_coverage.d.ts.map +1 -1
  33. package/dist/release_gate/probe_coverage.js +13 -4
  34. package/dist/release_gate/probe_coverage.js.map +1 -1
  35. package/dist/release_gate/wiring_lag.d.ts +65 -0
  36. package/dist/release_gate/wiring_lag.d.ts.map +1 -0
  37. package/dist/release_gate/wiring_lag.js +116 -0
  38. package/dist/release_gate/wiring_lag.js.map +1 -0
  39. package/dist/truth_gate/claims.d.ts.map +1 -1
  40. package/dist/truth_gate/claims.js +13 -0
  41. package/dist/truth_gate/claims.js.map +1 -1
  42. package/dist/truth_gate/probes.d.ts.map +1 -1
  43. package/dist/truth_gate/probes.js +114 -0
  44. package/dist/truth_gate/probes.js.map +1 -1
  45. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * v2.53.0 — JANUS organ: cross-vendor cluster-boundary detector.
3
+ *
4
+ * The two-faced Roman god — looks at past + future simultaneously.
5
+ *
6
+ * Closes Eve's identity-swap blind spot from the Million Dollar Secret
7
+ * simulation: MOLT (v2.52) detects INTRA-vendor drift (vendor X drifts
8
+ * over time) but misses CROSS-vendor swaps (vendor X mid-session
9
+ * starts behaving like vendor Y). The classifier might still pick Y as
10
+ * the new winner, but neither MOLT nor verify_identity surfaces the
11
+ * "you crossed a cluster boundary" event.
12
+ *
13
+ * Algorithm:
14
+ * 1. Build cluster centroids from seed corpus (per vendor, per
15
+ * discriminative feature).
16
+ * 2. For an observation O, compute distance d(O, centroid_V) for every
17
+ * known vendor V.
18
+ * 3. Assign O to the nearest centroid → "current basin".
19
+ * 4. Track per-session basin history. If basin changes between
20
+ * observations → cross-cluster transition event.
21
+ * 5. Confidence: distance to old basin / distance to new basin (lower
22
+ * ratio = sharper swap).
23
+ *
24
+ * Different from MOLT because MOLT compares pre/post WINDOWS of the
25
+ * SAME vendor's drift; JANUS detects the MOMENT a vendor's fingerprint
26
+ * crosses into a DIFFERENT vendor's basin.
27
+ *
28
+ * Composes: extractFingerprint + seedStats.
29
+ *
30
+ * Pure deterministic + defensive; never throws.
31
+ */
32
+ import type { Fingerprint } from "./types.js";
33
+ export interface ClusterDistance {
34
+ vendor: string;
35
+ distance: number;
36
+ }
37
+ export interface JanusBasin {
38
+ /** Nearest vendor centroid. */
39
+ basin: string;
40
+ /** Distance to nearest centroid. */
41
+ basinDistance: number;
42
+ /** Distance to SECOND-nearest centroid (margin signal). */
43
+ secondNearest: ClusterDistance | null;
44
+ /** Margin = secondNearest.distance - basinDistance. Larger = sharper assignment. */
45
+ margin: number;
46
+ /** All centroid distances, sorted ascending. */
47
+ allDistances: ClusterDistance[];
48
+ }
49
+ export interface JanusObservation {
50
+ fingerprint: Fingerprint;
51
+ basin: JanusBasin;
52
+ }
53
+ export interface JanusTransition {
54
+ fromBasin: string;
55
+ toBasin: string;
56
+ fromDistance: number;
57
+ toDistance: number;
58
+ /** Ratio of (distance to OLD basin from CURRENT obs) / (distance to NEW basin from CURRENT obs).
59
+ * > 1 means the obs is clearly closer to NEW than OLD → confident swap. */
60
+ swapConfidence: number;
61
+ /** Plain-English citation. */
62
+ citation: string;
63
+ }
64
+ export interface JanusSessionResult {
65
+ observations: JanusObservation[];
66
+ transitions: JanusTransition[];
67
+ /** Did at least one cross-cluster swap fire? */
68
+ swapDetected: boolean;
69
+ hmac: string;
70
+ }
71
+ /**
72
+ * Locate which vendor cluster an observation belongs to.
73
+ * Defensive: empty stats → returns basin="unknown" with infinity distance.
74
+ */
75
+ export declare function locateBasin(fingerprint: Fingerprint): JanusBasin;
76
+ /**
77
+ * Observe a fixture; return {fingerprint, basin}.
78
+ */
79
+ export declare function observe(fixture: {
80
+ diff: string;
81
+ prDescription: string;
82
+ commitMessages: string[];
83
+ } | Fingerprint): JanusObservation;
84
+ /**
85
+ * Walk a sequence of observations from the SAME session; surface
86
+ * cross-cluster transitions + an HMAC-signed verdict.
87
+ */
88
+ export declare function detectIdentitySwap(observations: JanusObservation[], opts?: {
89
+ minMargin?: number;
90
+ }): JanusSessionResult;
91
+ /** Verify a session-result's HMAC. */
92
+ export declare function verifyJanusResult(r: JanusSessionResult): boolean;
93
+ //# sourceMappingURL=janus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"janus.d.ts","sourceRoot":"","sources":["../../src/nemesis/janus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AASxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,aAAa,EAAE,eAAe,GAAG,IAAI,CAAC;IACtC,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;gFAC4E;IAC5E,cAAc,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,gDAAgD;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAoBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAyBhE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,WAAW,GAAG,gBAAgB,CAMlI;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,gBAAgB,EAAE,EAChC,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,kBAAkB,CAoCpB;AAWD,sCAAsC;AACtC,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAQhE"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * v2.53.0 — JANUS organ: cross-vendor cluster-boundary detector.
3
+ *
4
+ * The two-faced Roman god — looks at past + future simultaneously.
5
+ *
6
+ * Closes Eve's identity-swap blind spot from the Million Dollar Secret
7
+ * simulation: MOLT (v2.52) detects INTRA-vendor drift (vendor X drifts
8
+ * over time) but misses CROSS-vendor swaps (vendor X mid-session
9
+ * starts behaving like vendor Y). The classifier might still pick Y as
10
+ * the new winner, but neither MOLT nor verify_identity surfaces the
11
+ * "you crossed a cluster boundary" event.
12
+ *
13
+ * Algorithm:
14
+ * 1. Build cluster centroids from seed corpus (per vendor, per
15
+ * discriminative feature).
16
+ * 2. For an observation O, compute distance d(O, centroid_V) for every
17
+ * known vendor V.
18
+ * 3. Assign O to the nearest centroid → "current basin".
19
+ * 4. Track per-session basin history. If basin changes between
20
+ * observations → cross-cluster transition event.
21
+ * 5. Confidence: distance to old basin / distance to new basin (lower
22
+ * ratio = sharper swap).
23
+ *
24
+ * Different from MOLT because MOLT compares pre/post WINDOWS of the
25
+ * SAME vendor's drift; JANUS detects the MOMENT a vendor's fingerprint
26
+ * crosses into a DIFFERENT vendor's basin.
27
+ *
28
+ * Composes: extractFingerprint + seedStats.
29
+ *
30
+ * Pure deterministic + defensive; never throws.
31
+ */
32
+ import { createHmac } from "node:crypto";
33
+ import { extractFingerprint } from "./features.js";
34
+ import { seedStats } from "./calibration_corpus.js";
35
+ const KEY_ENV = "MNEME_JANUS_KEY";
36
+ const DEFAULT_KEY = "mneme-janus-v1";
37
+ function keyOf() {
38
+ return process.env[KEY_ENV] ?? DEFAULT_KEY;
39
+ }
40
+ /** Euclidean distance between fingerprint and a vendor's per-feature means. */
41
+ function distanceToCentroid(fp, stats) {
42
+ let sumSq = 0;
43
+ let count = 0;
44
+ for (const k of Object.keys(stats.features)) {
45
+ const v = fp[k];
46
+ if (typeof v !== "number" || !Number.isFinite(v))
47
+ continue;
48
+ const m = stats.features[k].mean;
49
+ const stdev = Math.max(stats.features[k].stdev, Math.abs(m) * 0.1, 1e-3);
50
+ // Normalized squared distance per feature
51
+ const z = (v - m) / stdev;
52
+ sumSq += z * z;
53
+ count++;
54
+ }
55
+ if (count === 0)
56
+ return Number.POSITIVE_INFINITY;
57
+ return Math.sqrt(sumSq / count);
58
+ }
59
+ /**
60
+ * Locate which vendor cluster an observation belongs to.
61
+ * Defensive: empty stats → returns basin="unknown" with infinity distance.
62
+ */
63
+ export function locateBasin(fingerprint) {
64
+ let stats;
65
+ try {
66
+ stats = seedStats();
67
+ }
68
+ catch {
69
+ return { basin: "unknown", basinDistance: Number.POSITIVE_INFINITY, secondNearest: null, margin: 0, allDistances: [] };
70
+ }
71
+ const distances = [];
72
+ for (const [vendor, s] of stats) {
73
+ distances.push({ vendor, distance: distanceToCentroid(fingerprint, s) });
74
+ }
75
+ distances.sort((a, b) => a.distance - b.distance);
76
+ if (distances.length === 0) {
77
+ return { basin: "unknown", basinDistance: Number.POSITIVE_INFINITY, secondNearest: null, margin: 0, allDistances: [] };
78
+ }
79
+ const nearest = distances[0];
80
+ const second = distances[1] ?? null;
81
+ const margin = second ? second.distance - nearest.distance : 0;
82
+ return {
83
+ basin: nearest.vendor,
84
+ basinDistance: nearest.distance,
85
+ secondNearest: second,
86
+ margin,
87
+ allDistances: distances,
88
+ };
89
+ }
90
+ /**
91
+ * Observe a fixture; return {fingerprint, basin}.
92
+ */
93
+ export function observe(fixture) {
94
+ const fp = "multiline_commit_ratio" in fixture
95
+ ? fixture
96
+ : extractFingerprint(fixture);
97
+ const basin = locateBasin(fp);
98
+ return { fingerprint: fp, basin };
99
+ }
100
+ /**
101
+ * Walk a sequence of observations from the SAME session; surface
102
+ * cross-cluster transitions + an HMAC-signed verdict.
103
+ */
104
+ export function detectIdentitySwap(observations, opts = {}) {
105
+ const minMargin = opts.minMargin ?? 0.5;
106
+ const transitions = [];
107
+ if (!Array.isArray(observations) || observations.length < 2) {
108
+ return signed({ observations: observations ?? [], transitions: [], swapDetected: false });
109
+ }
110
+ let prev = observations[0];
111
+ for (let i = 1; i < observations.length; i++) {
112
+ const cur = observations[i];
113
+ if (prev.basin.basin === cur.basin.basin) {
114
+ prev = cur;
115
+ continue;
116
+ }
117
+ // Only surface as a real swap when the new basin is clearly nearer.
118
+ if (cur.basin.margin < minMargin) {
119
+ prev = cur;
120
+ continue;
121
+ }
122
+ // Distance from CURRENT obs to PREVIOUS basin vs current basin
123
+ const prevBasinDistInCur = cur.basin.allDistances.find((d) => d.vendor === prev.basin.basin);
124
+ if (!prevBasinDistInCur || !Number.isFinite(prevBasinDistInCur.distance)) {
125
+ prev = cur;
126
+ continue;
127
+ }
128
+ const swapConfidence = prevBasinDistInCur.distance / Math.max(cur.basin.basinDistance, 1e-6);
129
+ transitions.push({
130
+ fromBasin: prev.basin.basin,
131
+ toBasin: cur.basin.basin,
132
+ fromDistance: prevBasinDistInCur.distance,
133
+ toDistance: cur.basin.basinDistance,
134
+ swapConfidence,
135
+ citation: `JANUS: identity swap detected — fingerprint crossed from ${prev.basin.basin} basin to ${cur.basin.basin} basin (swap confidence ${swapConfidence.toFixed(2)}x).`,
136
+ });
137
+ prev = cur;
138
+ }
139
+ return signed({ observations, transitions, swapDetected: transitions.length > 0 });
140
+ }
141
+ function signed(body) {
142
+ const hmac = createHmac("sha256", keyOf()).update(JSON.stringify({
143
+ transitions: body.transitions,
144
+ swapDetected: body.swapDetected,
145
+ obsCount: body.observations.length,
146
+ })).digest("hex");
147
+ return { ...body, hmac };
148
+ }
149
+ /** Verify a session-result's HMAC. */
150
+ export function verifyJanusResult(r) {
151
+ if (!r || typeof r.hmac !== "string")
152
+ return false;
153
+ const expected = createHmac("sha256", keyOf()).update(JSON.stringify({
154
+ transitions: r.transitions,
155
+ swapDetected: r.swapDetected,
156
+ obsCount: r.observations.length,
157
+ })).digest("hex");
158
+ return expected === r.hmac;
159
+ }
160
+ //# sourceMappingURL=janus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"janus.js","sourceRoot":"","sources":["../../src/nemesis/janus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,SAAS,EAAoB,MAAM,yBAAyB,CAAC;AAGtE,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAClC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAErC,SAAS,KAAK;IACZ,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC;AAC7C,CAAC;AA6CD,+EAA+E;AAC/E,SAAS,kBAAkB,CAAC,EAAe,EAAE,KAAkB;IAC7D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAI,EAAwC,CAAC,CAAC,CAAC,CAAC;QACvD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAC3D,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1E,0CAA0C;QAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,KAAK,EAAE,CAAC;IACV,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,WAAwB;IAClD,IAAI,KAAiC,CAAC;IACtC,IAAI,CAAC;QACH,KAAK,GAAG,SAAS,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IACzH,CAAC;IACD,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;QAChC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IACzH,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,aAAa,EAAE,OAAO,CAAC,QAAQ;QAC/B,aAAa,EAAE,MAAM;QACrB,MAAM;QACN,YAAY,EAAE,SAAS;KACxB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAwF;IAC9G,MAAM,EAAE,GAAG,wBAAwB,IAAK,OAAkB;QACxD,CAAC,CAAE,OAAuB;QAC1B,CAAC,CAAC,kBAAkB,CAAC,OAA4E,CAAC,CAAC;IACrG,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9B,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,YAAgC,EAChC,OAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;IACxC,MAAM,WAAW,GAAsB,EAAE,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,EAAE,YAAY,EAAE,YAAY,IAAI,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,IAAI,GAAG,YAAY,CAAC,CAAC,CAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,CAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACzC,IAAI,GAAG,GAAG,CAAC;YACX,SAAS;QACX,CAAC;QACD,oEAAoE;QACpE,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACjC,IAAI,GAAG,GAAG,CAAC;YACX,SAAS;QACX,CAAC;QACD,+DAA+D;QAC/D,MAAM,kBAAkB,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7F,IAAI,CAAC,kBAAkB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,IAAI,GAAG,GAAG,CAAC;YACX,SAAS;QACX,CAAC;QACD,MAAM,cAAc,GAAG,kBAAkB,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAC7F,WAAW,CAAC,IAAI,CAAC;YACf,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;YAC3B,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK;YACxB,YAAY,EAAE,kBAAkB,CAAC,QAAQ;YACzC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa;YACnC,cAAc;YACd,QAAQ,EAAE,4DAA4D,IAAI,CAAC,KAAK,CAAC,KAAK,aAAa,GAAG,CAAC,KAAK,CAAC,KAAK,2BAA2B,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;SAC5K,CAAC,CAAC;QACH,IAAI,GAAG,GAAG,CAAC;IACb,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,MAAM,CAAC,IAAsC;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAC/D,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM;KACnC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClB,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,iBAAiB,CAAC,CAAqB;IACrD,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACnE,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,QAAQ,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;KAChC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClB,OAAO,QAAQ,KAAK,CAAC,CAAC,IAAI,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * v2.53.0 — HMAC KEY SETUP WIZARD + STRICT mode.
3
+ *
4
+ * Closes P0-1 from the v2.52 session audit: pre-v2.53 NEMESIS warned LOUD
5
+ * when falling back to the public default key, but didn't auto-fix it
6
+ * + didn't refuse to operate. Result: every developer who ignored the
7
+ * warning shipped HMAC receipts an attacker can forge.
8
+ *
9
+ * v2.53 protocol:
10
+ * 1. First-run wizard auto-generates a 32-byte random key + writes it
11
+ * to .mneme/nemesis/hmac.key with 0o600 perms (owner-only).
12
+ * 2. MNEME_NEMESIS_STRICT=1 env var → key_management refuses to return
13
+ * the default-insecure key (throws instead). For CI / production /
14
+ * regulated environments.
15
+ * 3. Idempotent: re-running detects existing key + skips generation.
16
+ *
17
+ * Defensive: never throws on filesystem errors (best-effort), only the
18
+ * STRICT-mode refusal is intentional.
19
+ */
20
+ export interface KeyWizardResult {
21
+ ok: boolean;
22
+ action: "generated-repo" | "generated-user" | "already-present" | "skipped" | "failed";
23
+ path?: string;
24
+ /** Length of the resolved key (or 0 on fail). */
25
+ keyLength: number;
26
+ reason: string;
27
+ }
28
+ export interface KeyWizardOpts {
29
+ repoRoot: string;
30
+ /** "repo" → write to <repoRoot>/.mneme/nemesis/hmac.key (default).
31
+ * "user" → write to ~/.mneme/nemesis/hmac.key (cross-repo). */
32
+ target?: "repo" | "user";
33
+ /** Re-generate even if a key already exists. Default false. */
34
+ force?: boolean;
35
+ /** Don't write — only compute the would-be path + key length. */
36
+ dryRun?: boolean;
37
+ }
38
+ /**
39
+ * Run the key setup wizard. Idempotent; never overwrites an existing
40
+ * key unless force=true. Returns structured outcome.
41
+ */
42
+ export declare function runKeyWizard(opts: KeyWizardOpts): KeyWizardResult;
43
+ /**
44
+ * Check key file permissions (Unix only). Returns warning on world-readable
45
+ * files. On Windows, returns ok=true with note since chmod is a no-op.
46
+ */
47
+ export declare function checkKeyPermissions(repoRoot: string): {
48
+ ok: boolean;
49
+ mode?: number;
50
+ reason: string;
51
+ };
52
+ /**
53
+ * STRICT MODE check: throws when the user is operating with a
54
+ * default-insecure HMAC key AND has opted into strict enforcement
55
+ * via MNEME_NEMESIS_STRICT=1. Call this from any code path that
56
+ * issues forensic-grade receipts (EU stamp / cli-activity / SIBYL).
57
+ *
58
+ * Non-strict mode: returns { ok: false, message } so caller can decide.
59
+ */
60
+ export declare function strictKeyCheck(repoRoot: string): {
61
+ ok: boolean;
62
+ usingDefault: boolean;
63
+ message: string;
64
+ };
65
+ //# sourceMappingURL=key_setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key_setup.d.ts","sourceRoot":"","sources":["../../src/nemesis/key_setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAYD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,eAAe,CAyDjE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAiBpG;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiCxG"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * v2.53.0 — HMAC KEY SETUP WIZARD + STRICT mode.
3
+ *
4
+ * Closes P0-1 from the v2.52 session audit: pre-v2.53 NEMESIS warned LOUD
5
+ * when falling back to the public default key, but didn't auto-fix it
6
+ * + didn't refuse to operate. Result: every developer who ignored the
7
+ * warning shipped HMAC receipts an attacker can forge.
8
+ *
9
+ * v2.53 protocol:
10
+ * 1. First-run wizard auto-generates a 32-byte random key + writes it
11
+ * to .mneme/nemesis/hmac.key with 0o600 perms (owner-only).
12
+ * 2. MNEME_NEMESIS_STRICT=1 env var → key_management refuses to return
13
+ * the default-insecure key (throws instead). For CI / production /
14
+ * regulated environments.
15
+ * 3. Idempotent: re-running detects existing key + skips generation.
16
+ *
17
+ * Defensive: never throws on filesystem errors (best-effort), only the
18
+ * STRICT-mode refusal is intentional.
19
+ */
20
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync, chmodSync } from "node:fs";
21
+ import { join } from "node:path";
22
+ import { randomBytes } from "node:crypto";
23
+ import { homedir } from "node:os";
24
+ const REPO_KEY_REL = ".mneme/nemesis/hmac.key";
25
+ const USER_KEY_REL = ".mneme/nemesis/hmac.key";
26
+ function keyPath(opts) {
27
+ if (opts.target === "user")
28
+ return join(homedir(), USER_KEY_REL);
29
+ return join(opts.repoRoot, REPO_KEY_REL);
30
+ }
31
+ function envHasValidKey() {
32
+ const k = process.env["MNEME_NEMESIS_KEY"];
33
+ return typeof k === "string" && k.length >= 16;
34
+ }
35
+ /**
36
+ * Run the key setup wizard. Idempotent; never overwrites an existing
37
+ * key unless force=true. Returns structured outcome.
38
+ */
39
+ export function runKeyWizard(opts) {
40
+ try {
41
+ if (envHasValidKey() && !opts.force) {
42
+ const env = process.env["MNEME_NEMESIS_KEY"];
43
+ return {
44
+ ok: true,
45
+ action: "skipped",
46
+ keyLength: env.length,
47
+ reason: "MNEME_NEMESIS_KEY already set — no file action needed",
48
+ };
49
+ }
50
+ const p = keyPath(opts);
51
+ if (existsSync(p) && !opts.force) {
52
+ try {
53
+ const k = readFileSync(p, "utf8").trim();
54
+ if (k.length >= 16) {
55
+ return {
56
+ ok: true,
57
+ action: "already-present",
58
+ path: p,
59
+ keyLength: k.length,
60
+ reason: `existing key at ${p} (${k.length} chars)`,
61
+ };
62
+ }
63
+ }
64
+ catch { /* fall through to regenerate */ }
65
+ }
66
+ if (opts.dryRun) {
67
+ return {
68
+ ok: true,
69
+ action: opts.target === "user" ? "generated-user" : "generated-repo",
70
+ path: p,
71
+ keyLength: 64,
72
+ reason: `dry-run: would write a fresh 64-char hex key to ${p}`,
73
+ };
74
+ }
75
+ // Generate + write
76
+ const dir = p.replace(/[\/\\][^\/\\]+$/, "");
77
+ try {
78
+ mkdirSync(dir, { recursive: true });
79
+ }
80
+ catch { /* ok */ }
81
+ const key = randomBytes(32).toString("hex");
82
+ writeFileSync(p, key + "\n", { mode: 0o600 });
83
+ // Best-effort chmod (Windows ignores)
84
+ try {
85
+ chmodSync(p, 0o600);
86
+ }
87
+ catch { /* */ }
88
+ return {
89
+ ok: true,
90
+ action: opts.target === "user" ? "generated-user" : "generated-repo",
91
+ path: p,
92
+ keyLength: key.length,
93
+ reason: `generated fresh 64-char hex key at ${p} (mode 0600)`,
94
+ };
95
+ }
96
+ catch (e) {
97
+ return {
98
+ ok: false,
99
+ action: "failed",
100
+ keyLength: 0,
101
+ reason: `wizard failed: ${e.message}`,
102
+ };
103
+ }
104
+ }
105
+ /**
106
+ * Check key file permissions (Unix only). Returns warning on world-readable
107
+ * files. On Windows, returns ok=true with note since chmod is a no-op.
108
+ */
109
+ export function checkKeyPermissions(repoRoot) {
110
+ const p = join(repoRoot, REPO_KEY_REL);
111
+ if (!existsSync(p))
112
+ return { ok: true, reason: "no key file present" };
113
+ try {
114
+ const s = statSync(p);
115
+ const mode = s.mode & 0o777;
116
+ if (process.platform === "win32") {
117
+ return { ok: true, mode, reason: "Windows: chmod is a no-op; key access controlled by NTFS ACLs" };
118
+ }
119
+ // Owner-only is the goal: 0o600
120
+ if (mode === 0o600 || mode === 0o400) {
121
+ return { ok: true, mode, reason: `mode ${mode.toString(8)} — owner-only (correct)` };
122
+ }
123
+ return { ok: false, mode, reason: `mode ${mode.toString(8)} is too permissive; should be 600 (owner read/write only)` };
124
+ }
125
+ catch (e) {
126
+ return { ok: false, reason: `stat failed: ${e.message}` };
127
+ }
128
+ }
129
+ /**
130
+ * STRICT MODE check: throws when the user is operating with a
131
+ * default-insecure HMAC key AND has opted into strict enforcement
132
+ * via MNEME_NEMESIS_STRICT=1. Call this from any code path that
133
+ * issues forensic-grade receipts (EU stamp / cli-activity / SIBYL).
134
+ *
135
+ * Non-strict mode: returns { ok: false, message } so caller can decide.
136
+ */
137
+ export function strictKeyCheck(repoRoot) {
138
+ // Resolve via the same path key_management uses.
139
+ const env = process.env["MNEME_NEMESIS_KEY"];
140
+ if (typeof env === "string" && env.length >= 16) {
141
+ return { ok: true, usingDefault: false, message: "MNEME_NEMESIS_KEY env var set" };
142
+ }
143
+ const repo = join(repoRoot, REPO_KEY_REL);
144
+ if (existsSync(repo)) {
145
+ try {
146
+ const k = readFileSync(repo, "utf8").trim();
147
+ if (k.length >= 16)
148
+ return { ok: true, usingDefault: false, message: `repo key at ${repo}` };
149
+ }
150
+ catch { /* */ }
151
+ }
152
+ const user = join(homedir(), USER_KEY_REL);
153
+ if (existsSync(user)) {
154
+ try {
155
+ const k = readFileSync(user, "utf8").trim();
156
+ if (k.length >= 16)
157
+ return { ok: true, usingDefault: false, message: `user key at ${user}` };
158
+ }
159
+ catch { /* */ }
160
+ }
161
+ const strict = process.env["MNEME_NEMESIS_STRICT"] === "1";
162
+ if (strict) {
163
+ throw new Error("STRICT MODE: MNEME_NEMESIS_STRICT=1 set + no production key configured. " +
164
+ `Run: node -e "require('@mneme-ai/core').nemesis.runKeyWizard({repoRoot:'${repoRoot}'})" ` +
165
+ "OR set MNEME_NEMESIS_KEY env var (≥16 chars).");
166
+ }
167
+ return {
168
+ ok: false,
169
+ usingDefault: true,
170
+ message: "using default-insecure HMAC key — receipts are forgeable. Set MNEME_NEMESIS_STRICT=1 to enforce.",
171
+ };
172
+ }
173
+ //# sourceMappingURL=key_setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key_setup.js","sourceRoot":"","sources":["../../src/nemesis/key_setup.ts"],"names":[],"mappings":"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"}
@@ -50,7 +50,22 @@ export interface CrossCheckResult {
50
50
  totalTools: number;
51
51
  totalClaims: number;
52
52
  uncovered: string[];
53
+ /** v2.53: percentage of tools with claim or exemption coverage (0..100). */
54
+ coveragePercent: number;
55
+ /** v2.53: threshold the gate accepted at (0..100). Reported for audit. */
56
+ threshold: number;
53
57
  hint: string;
54
58
  }
55
- export declare function crossCheckFromDisk(repoRoot: string): CrossCheckResult;
59
+ /**
60
+ * v2.53 addition — CrossCheck options.
61
+ * threshold: minimum coverage % required for ok=true (default 50).
62
+ * - 0 → gate disabled (always passes)
63
+ * - 50 → soft enforcement (current legacy state has 14.2% so this
64
+ * still fails until coverage rises; useful for new repos)
65
+ * - 100 → strict (every new tool needs a claim or exemption)
66
+ */
67
+ export interface CrossCheckOpts {
68
+ threshold?: number;
69
+ }
70
+ export declare function crossCheckFromDisk(repoRoot: string, opts?: CrossCheckOpts): CrossCheckResult;
56
71
  //# sourceMappingURL=probe_coverage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"probe_coverage.d.ts","sourceRoot":"","sources":["../../src/release_gate/probe_coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAmCH,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sEAAsE;IACtE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,0CAA0C;IAC1C,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,8DAA8D;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6CAA6C;IAC7C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,CAAC,CAAC;IAC1D,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CA6BjF;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA2BrE"}
1
+ {"version":3,"file":"probe_coverage.d.ts","sourceRoot":"","sources":["../../src/release_gate/probe_coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAmCH,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sEAAsE;IACtE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,0CAA0C;IAC1C,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,8DAA8D;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6CAA6C;IAC7C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,CAAC,CAAC;IAC1D,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CA6BjF;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,4EAA4E;IAC5E,eAAe,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,gBAAgB,CAoChG"}
@@ -82,12 +82,13 @@ export function checkProbeCoverage(input) {
82
82
  : `${uncovered.length} new tool(s) lack TRUTH GATE probe binding. Either: (a) add a probe.<topic> + claim.<topic> to packages/core/src/truth_gate/{probes,claims}.ts, or (b) add the tool to COVERAGE_EXEMPT in packages/core/src/release_gate/probe_coverage.ts with a written justification.`,
83
83
  };
84
84
  }
85
- export function crossCheckFromDisk(repoRoot) {
85
+ export function crossCheckFromDisk(repoRoot, opts = {}) {
86
86
  try {
87
+ const threshold = Number.isFinite(opts.threshold) ? Math.max(0, Math.min(100, opts.threshold)) : 50;
87
88
  const manifestPath = join(repoRoot, "packages", "core", "src", "agent_manifest.ts");
88
89
  const claimsPath = join(repoRoot, "packages", "core", "src", "truth_gate", "claims.ts");
89
90
  if (!existsSync(manifestPath) || !existsSync(claimsPath)) {
90
- return { ok: true, totalTools: 0, totalClaims: 0, uncovered: [], hint: "release-gate skipped: source files missing" };
91
+ return { ok: true, totalTools: 0, totalClaims: 0, uncovered: [], coveragePercent: 0, threshold, hint: "release-gate skipped: source files missing" };
91
92
  }
92
93
  const manifestBody = readFileSync(manifestPath, "utf8");
93
94
  const claimsBody = readFileSync(claimsPath, "utf8");
@@ -107,10 +108,18 @@ export function crossCheckFromDisk(repoRoot) {
107
108
  claims.push(inner[1]);
108
109
  }
109
110
  const r = checkProbeCoverage({ newTools: Array.from(tools), knownClaims: claims });
110
- return { ok: r.ok, totalTools: tools.size, totalClaims: claims.length, uncovered: r.uncovered, hint: r.hint };
111
+ const totalTools = tools.size;
112
+ const coveredCount = r.covered.length;
113
+ const coveragePercent = totalTools === 0 ? 100 : +((coveredCount / totalTools) * 100).toFixed(1);
114
+ const ok = coveragePercent >= threshold;
115
+ const hint = ok
116
+ ? `coverage ${coveragePercent}% ≥ threshold ${threshold}% — gate passed (${coveredCount}/${totalTools} tools covered)`
117
+ : `coverage ${coveragePercent}% < threshold ${threshold}% — ${r.uncovered.length} uncovered tool(s). Either add probe.<topic>+claim.<topic>, OR add to COVERAGE_EXEMPT (with justification), OR lower threshold via --min-coverage <n>.`;
118
+ return { ok, totalTools, totalClaims: claims.length, uncovered: r.uncovered, coveragePercent, threshold, hint };
111
119
  }
112
120
  catch (e) {
113
- return { ok: true, totalTools: 0, totalClaims: 0, uncovered: [], hint: `release-gate skipped: ${e.message}` };
121
+ const threshold = Number.isFinite(opts.threshold) ? opts.threshold : 50;
122
+ return { ok: true, totalTools: 0, totalClaims: 0, uncovered: [], coveragePercent: 0, threshold, hint: `release-gate skipped: ${e.message}` };
114
123
  }
115
124
  }
116
125
  //# sourceMappingURL=probe_coverage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"probe_coverage.js","sourceRoot":"","sources":["../../src/release_gate/probe_coverage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"probe_coverage.js","sourceRoot":"","sources":["../../src/release_gate/probe_coverage.ts"],"names":[],"mappings":"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"}