@mmnto/totem 1.54.1 → 1.55.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/dist/artifacts/grounding.d.ts +54 -0
- package/dist/artifacts/grounding.d.ts.map +1 -0
- package/dist/artifacts/grounding.js +79 -0
- package/dist/artifacts/grounding.js.map +1 -0
- package/dist/artifacts/grounding.test.d.ts +13 -0
- package/dist/artifacts/grounding.test.d.ts.map +1 -0
- package/dist/artifacts/grounding.test.js +168 -0
- package/dist/artifacts/grounding.test.js.map +1 -0
- package/dist/artifacts/schema.d.ts +267 -10
- package/dist/artifacts/schema.d.ts.map +1 -1
- package/dist/artifacts/schema.js +73 -8
- package/dist/artifacts/schema.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/parity-detect.d.ts +5 -5
- package/dist/parity-detect.d.ts.map +1 -1
- package/dist/parity-detect.js +4 -3
- package/dist/parity-detect.js.map +1 -1
- package/dist/parity-manifest.d.ts +10 -0
- package/dist/parity-manifest.d.ts.map +1 -1
- package/dist/parity-manifest.js +10 -0
- package/dist/parity-manifest.js.map +1 -1
- package/dist/parity-manifest.test.js +14 -0
- package/dist/parity-manifest.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grounding-bundle assembly (mmnto-ai/totem#2101, strategy#474 slice 2).
|
|
3
|
+
*
|
|
4
|
+
* The bundle is the per-item provenance record for everything the
|
|
5
|
+
* deterministic layer DELIVERED into a run's prompt: each item names what it
|
|
6
|
+
* is (`sourceType` + `filePath` + optional `sourceRepo`), what it contained
|
|
7
|
+
* (`contentHash` — identity, never bytes), and HOW it was obtained
|
|
8
|
+
* (`provenance` class). The first cut wraps similarity retrieval honestly as
|
|
9
|
+
* `similarity-only`; structural resolvers (mmnto-ai/totem#344/#375) graduate items to
|
|
10
|
+
* `structurally-verified` by supplying them explicitly — this builder can
|
|
11
|
+
* never upgrade a class on its own (honest-absent: nothing upgrades
|
|
12
|
+
* provenance silently).
|
|
13
|
+
*
|
|
14
|
+
* Assembly is caller-side (the deterministic layer) — providers stay dumb
|
|
15
|
+
* pipes. The bundle is what `grounding.hash` attests, so it must be a pure
|
|
16
|
+
* function of the logical item set: items are canonically sorted here because
|
|
17
|
+
* retrieval order is score-dependent and `calculateDeterministicHash` is
|
|
18
|
+
* order-significant for arrays.
|
|
19
|
+
*/
|
|
20
|
+
import { type GroundingBundle } from './schema.js';
|
|
21
|
+
/**
|
|
22
|
+
* One retrieved evidence item as the caller holds it — the `result` shape is
|
|
23
|
+
* the identity-relevant subset of `SearchResult`, kept structural so callers
|
|
24
|
+
* and tests don't need a full store hit to build one.
|
|
25
|
+
*/
|
|
26
|
+
export interface GroundingSourceItem {
|
|
27
|
+
/** Retrieval partition the item entered the prompt under (`spec` | `session_log` | `code` | `lesson`). */
|
|
28
|
+
sourceType: string;
|
|
29
|
+
result: {
|
|
30
|
+
content: string;
|
|
31
|
+
filePath: string;
|
|
32
|
+
/** Linked-index name for cross-repo hits; absent = the run's own repo (strategy review F1 on mmnto-ai/totem#2101). */
|
|
33
|
+
sourceRepo?: string | undefined;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Map retrieved items into a canonical grounding bundle. Every input item is
|
|
38
|
+
* included — duplicates are delivery records, not noise (the bundle records
|
|
39
|
+
* what entered the prompt, and a snippet delivered twice was delivered
|
|
40
|
+
* twice). All items are classed `similarity-only`: this is the first-cut
|
|
41
|
+
* wrapper around the existing retrieval, and the ONLY class this builder can
|
|
42
|
+
* emit by construction.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildGroundingBundle(items: GroundingSourceItem[]): GroundingBundle;
|
|
45
|
+
/**
|
|
46
|
+
* Derive the artifact's `provenanceSummary` from the bundle — never asserted
|
|
47
|
+
* wholesale (derive-or-couple: a stored summary is a mirror that can drift
|
|
48
|
+
* from `items`). Sorted class-count string (`similarity-only:14`,
|
|
49
|
+
* `compiled-rule:1,similarity-only:2`) so the eval harness can threshold on
|
|
50
|
+
* it deterministically; zero items → `'ungrounded'` (abstention named, not
|
|
51
|
+
* silent — Tenet 14 honest-absent).
|
|
52
|
+
*/
|
|
53
|
+
export declare function summarizeProvenance(bundle: GroundingBundle): string;
|
|
54
|
+
//# sourceMappingURL=grounding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.d.ts","sourceRoot":"","sources":["../../src/artifacts/grounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,0GAA0G;IAC1G,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,sHAAsH;QACtH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,CAAC;CACH;AAqBD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,eAAe,CAUlF;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAenE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grounding-bundle assembly (mmnto-ai/totem#2101, strategy#474 slice 2).
|
|
3
|
+
*
|
|
4
|
+
* The bundle is the per-item provenance record for everything the
|
|
5
|
+
* deterministic layer DELIVERED into a run's prompt: each item names what it
|
|
6
|
+
* is (`sourceType` + `filePath` + optional `sourceRepo`), what it contained
|
|
7
|
+
* (`contentHash` — identity, never bytes), and HOW it was obtained
|
|
8
|
+
* (`provenance` class). The first cut wraps similarity retrieval honestly as
|
|
9
|
+
* `similarity-only`; structural resolvers (mmnto-ai/totem#344/#375) graduate items to
|
|
10
|
+
* `structurally-verified` by supplying them explicitly — this builder can
|
|
11
|
+
* never upgrade a class on its own (honest-absent: nothing upgrades
|
|
12
|
+
* provenance silently).
|
|
13
|
+
*
|
|
14
|
+
* Assembly is caller-side (the deterministic layer) — providers stay dumb
|
|
15
|
+
* pipes. The bundle is what `grounding.hash` attests, so it must be a pure
|
|
16
|
+
* function of the logical item set: items are canonically sorted here because
|
|
17
|
+
* retrieval order is score-dependent and `calculateDeterministicHash` is
|
|
18
|
+
* order-significant for arrays.
|
|
19
|
+
*/
|
|
20
|
+
import { calculateDeterministicHash } from './hash.js';
|
|
21
|
+
import { PROVENANCE_SIMILARITY_ONLY, PROVENANCE_UNGROUNDED, } from './schema.js';
|
|
22
|
+
/**
|
|
23
|
+
* Locale-independent string compare (localeCompare is environment-dependent
|
|
24
|
+
* and would let two machines disagree on the canonical order — and therefore
|
|
25
|
+
* the hash — of the same bundle).
|
|
26
|
+
*/
|
|
27
|
+
function compareStrings(a, b) {
|
|
28
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
29
|
+
}
|
|
30
|
+
/** Canonical item order: (sourceType, sourceRepo, filePath, contentHash). */
|
|
31
|
+
function compareItems(a, b) {
|
|
32
|
+
return (compareStrings(a.sourceType, b.sourceType) ||
|
|
33
|
+
compareStrings(a.sourceRepo ?? '', b.sourceRepo ?? '') ||
|
|
34
|
+
compareStrings(a.filePath, b.filePath) ||
|
|
35
|
+
compareStrings(a.contentHash, b.contentHash));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Map retrieved items into a canonical grounding bundle. Every input item is
|
|
39
|
+
* included — duplicates are delivery records, not noise (the bundle records
|
|
40
|
+
* what entered the prompt, and a snippet delivered twice was delivered
|
|
41
|
+
* twice). All items are classed `similarity-only`: this is the first-cut
|
|
42
|
+
* wrapper around the existing retrieval, and the ONLY class this builder can
|
|
43
|
+
* emit by construction.
|
|
44
|
+
*/
|
|
45
|
+
export function buildGroundingBundle(items) {
|
|
46
|
+
const mapped = items.map(({ sourceType, result }) => ({
|
|
47
|
+
provenance: PROVENANCE_SIMILARITY_ONLY,
|
|
48
|
+
contentHash: calculateDeterministicHash(result.content),
|
|
49
|
+
sourceType,
|
|
50
|
+
filePath: result.filePath,
|
|
51
|
+
...(result.sourceRepo !== undefined ? { sourceRepo: result.sourceRepo } : {}),
|
|
52
|
+
}));
|
|
53
|
+
mapped.sort(compareItems);
|
|
54
|
+
return { items: mapped };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Derive the artifact's `provenanceSummary` from the bundle — never asserted
|
|
58
|
+
* wholesale (derive-or-couple: a stored summary is a mirror that can drift
|
|
59
|
+
* from `items`). Sorted class-count string (`similarity-only:14`,
|
|
60
|
+
* `compiled-rule:1,similarity-only:2`) so the eval harness can threshold on
|
|
61
|
+
* it deterministically; zero items → `'ungrounded'` (abstention named, not
|
|
62
|
+
* silent — Tenet 14 honest-absent).
|
|
63
|
+
*/
|
|
64
|
+
export function summarizeProvenance(bundle) {
|
|
65
|
+
if (bundle.items.length === 0)
|
|
66
|
+
return PROVENANCE_UNGROUNDED;
|
|
67
|
+
const counts = new Map();
|
|
68
|
+
for (const item of bundle.items) {
|
|
69
|
+
counts.set(item.provenance, (counts.get(item.provenance) ?? 0) + 1);
|
|
70
|
+
}
|
|
71
|
+
return ([...counts.keys()]
|
|
72
|
+
.sort(compareStrings)
|
|
73
|
+
// Non-null assertion: every key comes from the same map's own key set
|
|
74
|
+
// (Greptile R1 on mmnto-ai/totem#2122 — a future logic change must fail
|
|
75
|
+
// the type check, not silently render `class:undefined`).
|
|
76
|
+
.map((cls) => `${cls}:${counts.get(cls)}`)
|
|
77
|
+
.join(','));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=grounding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.js","sourceRoot":"","sources":["../../src/artifacts/grounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAGL,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAkBrB;;;;GAIG;AACH,SAAS,cAAc,CAAC,CAAS,EAAE,CAAS;IAC1C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,6EAA6E;AAC7E,SAAS,YAAY,CAAC,CAAgB,EAAE,CAAgB;IACtD,OAAO,CACL,cAAc,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC;QAC1C,cAAc,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;QACtD,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;QACtC,cAAc,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAC7C,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAA4B;IAC/D,MAAM,MAAM,GAAoB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACrE,UAAU,EAAE,0BAA0B;QACtC,WAAW,EAAE,0BAA0B,CAAC,MAAM,CAAC,OAAO,CAAC;QACvD,UAAU;QACV,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9E,CAAC,CAAC,CAAC;IACJ,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAuB;IACzD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,qBAAqB,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,CACL,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;SACf,IAAI,CAAC,cAAc,CAAC;QACrB,sEAAsE;QACtE,wEAAwE;QACxE,0DAA0D;SACzD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,CAAC;SAC1C,IAAI,CAAC,GAAG,CAAC,CACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grounding-bundle tests (mmnto-ai/totem#2101, strategy#474 slice 2).
|
|
3
|
+
*
|
|
4
|
+
* The invariants under test are the design doc's eight, minus the caller-side
|
|
5
|
+
* ones (those live in the CLI test suites):
|
|
6
|
+
* 1. first-cut builder emits ONLY similarity-only items,
|
|
7
|
+
* 2. input order never moves the bundle hash (canonical sort),
|
|
8
|
+
* 3. summary derives from items alone; zero items → 'ungrounded',
|
|
9
|
+
* 5. slice-1 artifacts (no bundle) still parse (F1 tolerance),
|
|
10
|
+
* 7. items carry identity + hash, never content bytes.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=grounding.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.test.d.ts","sourceRoot":"","sources":["../../src/artifacts/grounding.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grounding-bundle tests (mmnto-ai/totem#2101, strategy#474 slice 2).
|
|
3
|
+
*
|
|
4
|
+
* The invariants under test are the design doc's eight, minus the caller-side
|
|
5
|
+
* ones (those live in the CLI test suites):
|
|
6
|
+
* 1. first-cut builder emits ONLY similarity-only items,
|
|
7
|
+
* 2. input order never moves the bundle hash (canonical sort),
|
|
8
|
+
* 3. summary derives from items alone; zero items → 'ungrounded',
|
|
9
|
+
* 5. slice-1 artifacts (no bundle) still parse (F1 tolerance),
|
|
10
|
+
* 7. items carry identity + hash, never content bytes.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, expect, it } from 'vitest';
|
|
13
|
+
import { buildGroundingBundle, summarizeProvenance, } from './grounding.js';
|
|
14
|
+
import { calculateDeterministicHash } from './hash.js';
|
|
15
|
+
import { GroundingItemSchema, PROVENANCE_CLASSES, PROVENANCE_COMPILED_RULE, PROVENANCE_SIMILARITY_ONLY, PROVENANCE_UNGROUNDED, RUN_ARTIFACT_SCHEMA_VERSION, RunArtifactSchema, } from './schema.js';
|
|
16
|
+
function source(overrides = {}, sourceType = 'code') {
|
|
17
|
+
return {
|
|
18
|
+
sourceType,
|
|
19
|
+
result: { content: 'function x() {}', filePath: 'src/x.ts', ...overrides },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function baseArtifact() {
|
|
23
|
+
return {
|
|
24
|
+
schemaVersion: RUN_ARTIFACT_SCHEMA_VERSION,
|
|
25
|
+
inputBundle: { maskedPrompt: 'prompt after DLP' },
|
|
26
|
+
inputHash: 'a'.repeat(64),
|
|
27
|
+
grounding: { hash: 'b'.repeat(64), provenanceSummary: 'similarity-only' },
|
|
28
|
+
backend: {
|
|
29
|
+
provider: 'gemini',
|
|
30
|
+
model: 'gemini-3.1-pro-preview',
|
|
31
|
+
qualifiedModel: 'gemini:gemini-3.1-pro-preview',
|
|
32
|
+
admissionClass: 'completion_only',
|
|
33
|
+
taskProfile: 'Spec',
|
|
34
|
+
},
|
|
35
|
+
output: { content: 'response', metrics: { durationMs: 100 } },
|
|
36
|
+
createdAt: '2026-06-07T23:00:00.000Z',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
describe('buildGroundingBundle', () => {
|
|
40
|
+
it('includes every input item — duplicates are delivery records, never deduped', () => {
|
|
41
|
+
const item = source();
|
|
42
|
+
const bundle = buildGroundingBundle([item, item, source({ filePath: 'src/y.ts' })]);
|
|
43
|
+
expect(bundle.items).toHaveLength(3);
|
|
44
|
+
});
|
|
45
|
+
it('first cut emits only similarity-only — no input shape produces an upgraded class', () => {
|
|
46
|
+
const bundle = buildGroundingBundle([
|
|
47
|
+
source(),
|
|
48
|
+
source({ filePath: 'lessons/l1.md' }, 'lesson'),
|
|
49
|
+
source({ filePath: 'spec.md', sourceRepo: 'strategy' }, 'spec'),
|
|
50
|
+
]);
|
|
51
|
+
expect(bundle.items.every((i) => i.provenance === PROVENANCE_SIMILARITY_ONLY)).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
it('same item set in any input order produces a deep-equal bundle and identical hash', () => {
|
|
54
|
+
const items = [
|
|
55
|
+
source({ filePath: 'src/b.ts' }),
|
|
56
|
+
source({ filePath: 'src/a.ts' }, 'spec'),
|
|
57
|
+
source({ filePath: 'src/a.ts', sourceRepo: 'strategy' }),
|
|
58
|
+
source({ content: 'other content', filePath: 'src/a.ts' }),
|
|
59
|
+
];
|
|
60
|
+
const forward = buildGroundingBundle(items);
|
|
61
|
+
const reversed = buildGroundingBundle([...items].reverse());
|
|
62
|
+
expect(forward).toEqual(reversed);
|
|
63
|
+
expect(calculateDeterministicHash(forward)).toBe(calculateDeterministicHash(reversed));
|
|
64
|
+
});
|
|
65
|
+
it('contentHash uses the one deterministic-hash convention; items carry no content bytes', () => {
|
|
66
|
+
const bundle = buildGroundingBundle([source({ content: 'the snippet' })]);
|
|
67
|
+
expect(bundle.items[0].contentHash).toBe(calculateDeterministicHash('the snippet'));
|
|
68
|
+
expect(JSON.stringify(bundle)).not.toContain('the snippet');
|
|
69
|
+
});
|
|
70
|
+
it("carries sourceRepo only when present — absent means the run's own repo (F1)", () => {
|
|
71
|
+
const bundle = buildGroundingBundle([
|
|
72
|
+
source({ sourceRepo: 'strategy' }),
|
|
73
|
+
source({ filePath: 'src/local.ts' }),
|
|
74
|
+
]);
|
|
75
|
+
const cross = bundle.items.find((i) => i.sourceRepo !== undefined);
|
|
76
|
+
const local = bundle.items.find((i) => i.sourceRepo === undefined);
|
|
77
|
+
expect(cross?.sourceRepo).toBe('strategy');
|
|
78
|
+
expect(local).toBeDefined();
|
|
79
|
+
expect('sourceRepo' in local).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('summarizeProvenance', () => {
|
|
83
|
+
it('derives sorted class counts from items alone', () => {
|
|
84
|
+
const bundle = buildGroundingBundle([source(), source({ filePath: 'src/y.ts' })]);
|
|
85
|
+
expect(summarizeProvenance(bundle)).toBe(`${PROVENANCE_SIMILARITY_ONLY}:2`);
|
|
86
|
+
});
|
|
87
|
+
it('renders multi-class bundles in sorted class order (deterministic string)', () => {
|
|
88
|
+
// Hand-built bundle: the builder cannot emit upgraded classes (by design),
|
|
89
|
+
// but the summarizer must handle them for the mmnto-ai/totem#344/#375 graduation path.
|
|
90
|
+
const bundle = {
|
|
91
|
+
items: [
|
|
92
|
+
{
|
|
93
|
+
provenance: PROVENANCE_SIMILARITY_ONLY,
|
|
94
|
+
contentHash: 'c'.repeat(64),
|
|
95
|
+
sourceType: 'code',
|
|
96
|
+
filePath: 'a.ts',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
provenance: PROVENANCE_COMPILED_RULE,
|
|
100
|
+
contentHash: 'd'.repeat(64),
|
|
101
|
+
sourceType: 'lesson',
|
|
102
|
+
filePath: 'b.md',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
provenance: PROVENANCE_SIMILARITY_ONLY,
|
|
106
|
+
contentHash: 'e'.repeat(64),
|
|
107
|
+
sourceType: 'code',
|
|
108
|
+
filePath: 'c.ts',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
expect(summarizeProvenance(bundle)).toBe(`${PROVENANCE_COMPILED_RULE}:1,${PROVENANCE_SIMILARITY_ONLY}:2`);
|
|
113
|
+
});
|
|
114
|
+
it("zero items → 'ungrounded' — abstention named, never empty", () => {
|
|
115
|
+
expect(summarizeProvenance({ items: [] })).toBe(PROVENANCE_UNGROUNDED);
|
|
116
|
+
expect(PROVENANCE_UNGROUNDED.length).toBeGreaterThan(0);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('grounding schemas', () => {
|
|
120
|
+
it('item requires identity fields — fabricated/absent identity is the illusion-of-grounding trap', () => {
|
|
121
|
+
expect(() => GroundingItemSchema.parse({
|
|
122
|
+
provenance: PROVENANCE_SIMILARITY_ONLY,
|
|
123
|
+
contentHash: 'f'.repeat(64),
|
|
124
|
+
sourceType: 'code',
|
|
125
|
+
})).toThrow();
|
|
126
|
+
expect(() => GroundingItemSchema.parse({
|
|
127
|
+
provenance: PROVENANCE_SIMILARITY_ONLY,
|
|
128
|
+
contentHash: 'not-a-hash',
|
|
129
|
+
sourceType: 'code',
|
|
130
|
+
filePath: 'a.ts',
|
|
131
|
+
})).toThrow();
|
|
132
|
+
});
|
|
133
|
+
it('accepts non-canonical class strings — open vocabulary; consumers fail-safe-down (F2)', () => {
|
|
134
|
+
const parsed = GroundingItemSchema.parse({
|
|
135
|
+
provenance: 'execution-verified',
|
|
136
|
+
contentHash: 'f'.repeat(64),
|
|
137
|
+
sourceType: 'code',
|
|
138
|
+
filePath: 'a.ts',
|
|
139
|
+
});
|
|
140
|
+
expect(parsed.provenance).toBe('execution-verified');
|
|
141
|
+
expect(PROVENANCE_CLASSES).not.toContain('execution-verified');
|
|
142
|
+
});
|
|
143
|
+
it('a bundled artifact parses, and a slice-1 artifact without a bundle still parses (F1 tolerance)', () => {
|
|
144
|
+
const slice1 = { ...baseArtifact(), schemaVersion: '1.0.0' };
|
|
145
|
+
expect(() => RunArtifactSchema.parse(slice1)).not.toThrow();
|
|
146
|
+
const bundle = buildGroundingBundle([source()]);
|
|
147
|
+
const bundled = {
|
|
148
|
+
...baseArtifact(),
|
|
149
|
+
grounding: {
|
|
150
|
+
hash: calculateDeterministicHash(bundle),
|
|
151
|
+
provenanceSummary: summarizeProvenance(bundle),
|
|
152
|
+
bundle,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const parsed = RunArtifactSchema.parse(bundled);
|
|
156
|
+
// Explicit presence guard (Greptile R1 on mmnto-ai/totem#2122): an absent
|
|
157
|
+
// bundle must fail HERE as a clear assertion, not as a confusing
|
|
158
|
+
// crypto.update error inside the hash recompute below.
|
|
159
|
+
expect(parsed.grounding.bundle).toBeDefined();
|
|
160
|
+
expect(parsed.grounding.bundle?.items).toHaveLength(1);
|
|
161
|
+
// Invariant 4: the attested hash is recomputable from the artifact surface alone.
|
|
162
|
+
expect(parsed.grounding.hash).toBe(calculateDeterministicHash(parsed.grounding.bundle));
|
|
163
|
+
});
|
|
164
|
+
it('the written schema version is a 1.x minor bump marking the bundle semantics (Q3)', () => {
|
|
165
|
+
expect(RUN_ARTIFACT_SCHEMA_VERSION).toBe('1.1.0');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=grounding.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grounding.test.js","sourceRoot":"","sources":["../../src/artifacts/grounding.test.ts"],"names":[],"mappings":"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"}
|