@mmnto/totem 1.53.3 → 1.53.5
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/config-schema.d.ts +28 -0
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config-schema.js +11 -0
- package/dist/config-schema.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/parity-detect.d.ts +182 -0
- package/dist/parity-detect.d.ts.map +1 -0
- package/dist/parity-detect.js +478 -0
- package/dist/parity-detect.js.map +1 -0
- package/dist/parity-detect.test.d.ts +18 -0
- package/dist/parity-detect.test.d.ts.map +1 -0
- package/dist/parity-detect.test.js +274 -0
- package/dist/parity-detect.test.js.map +1 -0
- package/dist/parity-manifest.d.ts +177 -0
- package/dist/parity-manifest.d.ts.map +1 -0
- package/dist/parity-manifest.js +233 -0
- package/dist/parity-manifest.js.map +1 -0
- package/dist/parity-manifest.test.d.ts +12 -0
- package/dist/parity-manifest.test.d.ts.map +1 -0
- package/dist/parity-manifest.test.js +228 -0
- package/dist/parity-manifest.test.js.map +1 -0
- package/dist/sys/git.d.ts.map +1 -1
- package/dist/sys/git.js +12 -3
- package/dist/sys/git.js.map +1 -1
- package/dist/sys/git.test.js +71 -1
- package/dist/sys/git.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the version-pinned parity drift detector (PR-1,
|
|
3
|
+
* mmnto-ai/totem#2069 on top of skeleton #2070).
|
|
4
|
+
*
|
|
5
|
+
* The detector is pure + side-effect-free: every filesystem / git seam is
|
|
6
|
+
* injectable so these tests drive it against synthetic fixtures, NOT the live
|
|
7
|
+
* cohort. Each invariant from the spec's "Invariants to lock via tests" list
|
|
8
|
+
* gets a case: pass / warn / fail-under-blocking+strict (the fail-promotion is a
|
|
9
|
+
* CLI-edge concern — the detector itself only ever returns warn here) / skip on
|
|
10
|
+
* not-declared / skip on not-a-consumer / skip on floor-unresolved /
|
|
11
|
+
* no-throw-on-read-failure / never-networks / claim-class-bound (pin currency
|
|
12
|
+
* only, never content equality).
|
|
13
|
+
*
|
|
14
|
+
* Mirrors the temp-file + discriminated-union style of `parity-manifest.test.ts`
|
|
15
|
+
* and the injected-seam style of `strategy-resolver.test.ts`.
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as os from 'node:os';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
21
|
+
import { deriveCohortRepoId, detectVersionPinnedContract, packageNameForContract, resolveCohortFloor, } from './parity-detect.js';
|
|
22
|
+
import { cleanTmpDir } from './test-utils.js';
|
|
23
|
+
let tmpRoot;
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-parity-detect-'));
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
cleanTmpDir(tmpRoot);
|
|
29
|
+
});
|
|
30
|
+
// ─── Fixture builders ───────────────────────────────────
|
|
31
|
+
/** Build a minimal version-pinned deps contract for one of the 4 PR-1 ids. */
|
|
32
|
+
function depsContract(over = {}) {
|
|
33
|
+
return {
|
|
34
|
+
id: 'mmnto-totem-version',
|
|
35
|
+
dimension: 'dependency-cohort',
|
|
36
|
+
canonicalSource: 'mmnto-ai/totem',
|
|
37
|
+
detectionMethod: 'consumer package.json caret range + resolved install vs floor',
|
|
38
|
+
expectedValueOrDerivation: 'consumer pin resolves to the current published @mmnto/totem',
|
|
39
|
+
tractability: 'version-pinned',
|
|
40
|
+
trackingIssue: 'mmnto-ai/totem-strategy#482',
|
|
41
|
+
...over,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Write a `packages/<dir>/package.json` with the given name + version. */
|
|
45
|
+
function writePackage(rootDir, dir, name, version) {
|
|
46
|
+
const pkgDir = path.join(rootDir, 'packages', dir);
|
|
47
|
+
fs.mkdirSync(pkgDir, { recursive: true });
|
|
48
|
+
fs.writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify({ name, version }, null, 2), 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Write a self-in-tree totem monorepo at `rootDir` carrying `@mmnto/totem` at
|
|
52
|
+
* `version`, plus a marker package so the glob has more than one entry.
|
|
53
|
+
*/
|
|
54
|
+
function writeSelfInTree(rootDir, version) {
|
|
55
|
+
writePackage(rootDir, 'totem', '@mmnto/totem', version);
|
|
56
|
+
writePackage(rootDir, 'cli', '@mmnto/cli', version);
|
|
57
|
+
}
|
|
58
|
+
/** Build a base context with all seams pointed at the temp consumer repo. */
|
|
59
|
+
function baseCtx(over = {}) {
|
|
60
|
+
return {
|
|
61
|
+
cwd: tmpRoot,
|
|
62
|
+
gitRoot: tmpRoot,
|
|
63
|
+
repoId: 'totem-status',
|
|
64
|
+
...over,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Write the consumer's package.json declaring `name` in `dependencies`. */
|
|
68
|
+
function writeConsumerPkg(rootDir, deps, field = 'dependencies') {
|
|
69
|
+
fs.writeFileSync(path.join(rootDir, 'package.json'), JSON.stringify({ name: 'consumer-repo', [field]: deps }, null, 2), 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
/** Write `node_modules/<pkg>/package.json#version` so install resolution wins. */
|
|
72
|
+
function writeInstalled(rootDir, pkg, version) {
|
|
73
|
+
const dir = path.join(rootDir, 'node_modules', ...pkg.split('/'));
|
|
74
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
75
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: pkg, version }, null, 2), 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
// ─── packageNameForContract ─────────────────────────────
|
|
78
|
+
describe('packageNameForContract', () => {
|
|
79
|
+
it('derives @mmnto/<x> from an `mmnto-<x>-version` id with no path locator', () => {
|
|
80
|
+
expect(packageNameForContract(depsContract({ id: 'mmnto-totem-version' }))).toBe('@mmnto/totem');
|
|
81
|
+
expect(packageNameForContract(depsContract({ id: 'mmnto-mcp-version' }))).toBe('@mmnto/mcp');
|
|
82
|
+
expect(packageNameForContract(depsContract({ id: 'mmnto-cli-version' }))).toBe('@mmnto/cli');
|
|
83
|
+
expect(packageNameForContract(depsContract({ id: 'mmnto-pack-rust-architecture-version' }))).toBe('@mmnto/pack-rust-architecture');
|
|
84
|
+
});
|
|
85
|
+
it('prefers the canonical-source package.json `name` when a path locator is present', () => {
|
|
86
|
+
writePackage(tmpRoot, 'cli', '@mmnto/cli', '1.0.0');
|
|
87
|
+
const contract = depsContract({
|
|
88
|
+
id: 'mmnto-cli-version',
|
|
89
|
+
canonicalSource: 'mmnto-ai/totem:packages/cli/package.json#version',
|
|
90
|
+
});
|
|
91
|
+
expect(packageNameForContract(contract, tmpRoot)).toBe('@mmnto/cli');
|
|
92
|
+
});
|
|
93
|
+
it('returns undefined for ids that are not deps-version contracts', () => {
|
|
94
|
+
expect(packageNameForContract(depsContract({ id: 'governance-doctrine' }))).toBeUndefined();
|
|
95
|
+
expect(packageNameForContract(depsContract({ id: 'agent-memory-doctrine' }))).toBeUndefined();
|
|
96
|
+
expect(packageNameForContract(depsContract({ id: 'gate-config' }))).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
it('prefers an explicit package: field over the id convention (derive-not-guess, strategy#517)', () => {
|
|
99
|
+
// Vendor name + a non-conventional id: only the package: field can resolve it.
|
|
100
|
+
expect(packageNameForContract(depsContract({ id: 'google-genai-coupling', package: '@google/genai' }))).toBe('@google/genai');
|
|
101
|
+
// package: wins even when the id convention WOULD match (no silent divergence).
|
|
102
|
+
expect(packageNameForContract(depsContract({ id: 'mmnto-totem-version', package: '@mmnto/totem' }))).toBe('@mmnto/totem');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
// ─── deriveCohortRepoId ─────────────────────────────────
|
|
106
|
+
describe('deriveCohortRepoId', () => {
|
|
107
|
+
it('extracts <name> from an mmnto-ai/<name> git origin remote (ssh + https, .git suffix)', () => {
|
|
108
|
+
expect(deriveCohortRepoId(tmpRoot, { remoteUrl: 'git@github.com:mmnto-ai/totem-status.git' })).toBe('totem-status');
|
|
109
|
+
expect(deriveCohortRepoId(tmpRoot, { remoteUrl: 'https://github.com/mmnto-ai/totem.git' })).toBe('totem');
|
|
110
|
+
expect(deriveCohortRepoId(tmpRoot, { remoteUrl: 'https://github.com/mmnto-ai/liquid-city' })).toBe('liquid-city');
|
|
111
|
+
});
|
|
112
|
+
it('falls back to package.json name basename (scope stripped) when no remote', () => {
|
|
113
|
+
writeConsumerPkg(tmpRoot, {});
|
|
114
|
+
fs.writeFileSync(path.join(tmpRoot, 'package.json'), JSON.stringify({ name: '@mmnto/totem-status' }, null, 2), 'utf-8');
|
|
115
|
+
expect(deriveCohortRepoId(tmpRoot, { remoteUrl: undefined, gitRoot: tmpRoot })).toBe('totem-status');
|
|
116
|
+
});
|
|
117
|
+
it('falls back to the git-root dir basename when neither remote nor package name resolve', () => {
|
|
118
|
+
const named = path.join(tmpRoot, 'my-cohort-repo');
|
|
119
|
+
fs.mkdirSync(named, { recursive: true });
|
|
120
|
+
expect(deriveCohortRepoId(named, { remoteUrl: undefined, gitRoot: named })).toBe('my-cohort-repo');
|
|
121
|
+
});
|
|
122
|
+
it('never networks / never throws on a git failure (returns a fallback or undefined)', () => {
|
|
123
|
+
// A remote-reader that throws must not propagate — the helper degrades.
|
|
124
|
+
expect(() => deriveCohortRepoId(tmpRoot, {
|
|
125
|
+
readRemote: () => {
|
|
126
|
+
throw new Error('git exploded');
|
|
127
|
+
},
|
|
128
|
+
gitRoot: tmpRoot,
|
|
129
|
+
})).not.toThrow();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
// ─── resolveCohortFloor ─────────────────────────────────
|
|
133
|
+
describe('resolveCohortFloor', () => {
|
|
134
|
+
it('resolves self-in-tree when the current git root IS the canonical-source repo', () => {
|
|
135
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
136
|
+
const result = resolveCohortFloor('@mmnto/totem', tmpRoot);
|
|
137
|
+
expect(result.resolved).toBe(true);
|
|
138
|
+
if (result.resolved) {
|
|
139
|
+
expect(result.version).toBe('1.53.3');
|
|
140
|
+
expect(result.source).toBe('self-in-tree');
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
it('resolves a sibling ../totem checkout when not self-in-tree', () => {
|
|
144
|
+
// gitRoot is the consumer; the floor lives in a sibling totem checkout.
|
|
145
|
+
const consumer = path.join(tmpRoot, 'totem-status');
|
|
146
|
+
const sibling = path.join(tmpRoot, 'totem');
|
|
147
|
+
fs.mkdirSync(consumer, { recursive: true });
|
|
148
|
+
writeSelfInTree(sibling, '2.0.0');
|
|
149
|
+
const result = resolveCohortFloor('@mmnto/totem', consumer);
|
|
150
|
+
expect(result.resolved).toBe(true);
|
|
151
|
+
if (result.resolved) {
|
|
152
|
+
expect(result.version).toBe('2.0.0');
|
|
153
|
+
expect(result.source).toBe('sibling');
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
it('is honest-absent (resolved:false + reason) when no floor is reachable + NEVER networks', () => {
|
|
157
|
+
const consumer = path.join(tmpRoot, 'lonely');
|
|
158
|
+
fs.mkdirSync(consumer, { recursive: true });
|
|
159
|
+
const result = resolveCohortFloor('@mmnto/totem', consumer);
|
|
160
|
+
expect(result.resolved).toBe(false);
|
|
161
|
+
if (!result.resolved) {
|
|
162
|
+
expect(result.reason).toMatch(/not locally determinable|sibling/i);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
it('does not throw when a package.json in the glob is unreadable/corrupt', () => {
|
|
166
|
+
const pkgDir = path.join(tmpRoot, 'packages', 'totem');
|
|
167
|
+
fs.mkdirSync(pkgDir, { recursive: true });
|
|
168
|
+
fs.writeFileSync(path.join(pkgDir, 'package.json'), '{ not valid json', 'utf-8');
|
|
169
|
+
expect(() => resolveCohortFloor('@mmnto/totem', tmpRoot)).not.toThrow();
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
// ─── detectVersionPinnedContract ────────────────────────
|
|
173
|
+
describe('detectVersionPinnedContract', () => {
|
|
174
|
+
it('PASS — installed ≥ floor, consumer declares the pin (sensor reports pass)', () => {
|
|
175
|
+
writeSelfInTree(tmpRoot, '1.50.0');
|
|
176
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.50.0' });
|
|
177
|
+
writeInstalled(tmpRoot, '@mmnto/totem', '1.53.3');
|
|
178
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
179
|
+
expect(verdict.status).toBe('pass');
|
|
180
|
+
});
|
|
181
|
+
it('WARN — installed < floor (stale pin); message carries declared/installed/floor', () => {
|
|
182
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
183
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.40.0' });
|
|
184
|
+
writeInstalled(tmpRoot, '@mmnto/totem', '1.40.0');
|
|
185
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
186
|
+
expect(verdict.status).toBe('warn');
|
|
187
|
+
expect(verdict.message).toContain('1.40.0'); // installed
|
|
188
|
+
expect(verdict.message).toContain('1.53.3'); // floor
|
|
189
|
+
});
|
|
190
|
+
it('detector NEVER emits fail — even a blocking contract returns warn (CLI promotes)', () => {
|
|
191
|
+
// Claim-class + layering invariant: fail-promotion is a CLI-edge concern.
|
|
192
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
193
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.40.0' });
|
|
194
|
+
writeInstalled(tmpRoot, '@mmnto/totem', '1.40.0');
|
|
195
|
+
const verdict = detectVersionPinnedContract(depsContract({ blocking: true }), baseCtx({ repoId: 'totem' }));
|
|
196
|
+
expect(verdict.status).toBe('warn');
|
|
197
|
+
expect(verdict.status).not.toBe('fail');
|
|
198
|
+
});
|
|
199
|
+
it('SKIP (distinct) — applicable consumer missing an expected pin is expected-but-absent, NOT cohort-permitted', () => {
|
|
200
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
201
|
+
writeConsumerPkg(tmpRoot, { 'unrelated-dep': '^1.0.0' });
|
|
202
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
203
|
+
expect(verdict.status).toBe('skip');
|
|
204
|
+
expect(verdict.message).toMatch(/expected but not declared|applicable consumer/i);
|
|
205
|
+
// Must stay DISTINCT from the not-a-consumer skip — else the consumers field
|
|
206
|
+
// does nothing for the missing case (strategy design-call 3).
|
|
207
|
+
expect(verdict.message).not.toMatch(/permits absence|not in consumers/i);
|
|
208
|
+
});
|
|
209
|
+
it('SKIP — consumers present and current repo not listed (not-a-consumer)', () => {
|
|
210
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
211
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.50.0' });
|
|
212
|
+
const verdict = detectVersionPinnedContract(depsContract({ consumers: ['totem-strategy', 'liquid-city'] }), baseCtx({ repoId: 'totem-status' }));
|
|
213
|
+
expect(verdict.status).toBe('skip');
|
|
214
|
+
});
|
|
215
|
+
it('SKIP — consumers present but repo id unresolvable: surface it, do NOT silently apply (Greptile P1)', () => {
|
|
216
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
217
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.50.0' });
|
|
218
|
+
const verdict = detectVersionPinnedContract(depsContract({ consumers: ['totem-strategy'] }), baseCtx({ repoId: undefined }));
|
|
219
|
+
expect(verdict.status).toBe('skip');
|
|
220
|
+
expect(verdict.message).toMatch(/cannot determine applicability|repo id unresolvable/i);
|
|
221
|
+
});
|
|
222
|
+
it('resolves an installed version hoisted to a PARENT node_modules (monorepo, GCA-1)', () => {
|
|
223
|
+
// Floor 2.0.0 self-in-tree at the git root; the consumer cwd is a nested
|
|
224
|
+
// subdir whose dep is hoisted to the root node_modules, not its own.
|
|
225
|
+
writeSelfInTree(tmpRoot, '2.0.0');
|
|
226
|
+
const sub = path.join(tmpRoot, 'apps', 'web');
|
|
227
|
+
fs.mkdirSync(sub, { recursive: true });
|
|
228
|
+
writeConsumerPkg(sub, { '@mmnto/totem': '^2.0.0' });
|
|
229
|
+
writeInstalled(tmpRoot, '@mmnto/totem', '2.0.0'); // hoisted at the root, not in sub
|
|
230
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ cwd: sub, gitRoot: tmpRoot, repoId: 'totem' }));
|
|
231
|
+
expect(verdict.status).toBe('pass');
|
|
232
|
+
expect(verdict.message).toContain('2.0.0');
|
|
233
|
+
});
|
|
234
|
+
it('SKIP — floor unresolvable (no self-in-tree, no sibling); reason in message, no throw', () => {
|
|
235
|
+
const consumer = path.join(tmpRoot, 'lonely');
|
|
236
|
+
fs.mkdirSync(consumer, { recursive: true });
|
|
237
|
+
writeConsumerPkg(consumer, { '@mmnto/totem': '^1.50.0' });
|
|
238
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ cwd: consumer, gitRoot: consumer, repoId: 'totem-status' }));
|
|
239
|
+
expect(verdict.status).toBe('skip');
|
|
240
|
+
});
|
|
241
|
+
it('SKIP — id resolves no deps package name (doctrine pin handed back to CLI as skip)', () => {
|
|
242
|
+
const verdict = detectVersionPinnedContract(depsContract({ id: 'governance-doctrine' }), baseCtx({ repoId: 'totem' }));
|
|
243
|
+
expect(verdict.status).toBe('skip');
|
|
244
|
+
});
|
|
245
|
+
it('no-throw on a corrupt consumer package.json — degrades to skip/warn', () => {
|
|
246
|
+
fs.writeFileSync(path.join(tmpRoot, 'package.json'), '{ broken', 'utf-8');
|
|
247
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
248
|
+
expect(() => detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }))).not.toThrow();
|
|
249
|
+
});
|
|
250
|
+
it('falls back to semver.minVersion(range) when node_modules is absent', () => {
|
|
251
|
+
// No install — minVersion('^1.53.0') = 1.53.0, equals floor → pass.
|
|
252
|
+
writeSelfInTree(tmpRoot, '1.53.0');
|
|
253
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.53.0' });
|
|
254
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
255
|
+
expect(verdict.status).toBe('pass');
|
|
256
|
+
});
|
|
257
|
+
it('SKIP (never throws) on an invalid declared range — claim guarded', () => {
|
|
258
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
259
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': 'not-a-range' });
|
|
260
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
261
|
+
expect(verdict.status).toBe('skip');
|
|
262
|
+
});
|
|
263
|
+
it('claim-class bound — the verdict is pin-currency only, never a content-equality verdict', () => {
|
|
264
|
+
// A version-pinned contract must never assert content drift. We assert the
|
|
265
|
+
// message is framed around versions/pins, not file content equality.
|
|
266
|
+
writeSelfInTree(tmpRoot, '1.53.3');
|
|
267
|
+
writeConsumerPkg(tmpRoot, { '@mmnto/totem': '^1.40.0' });
|
|
268
|
+
writeInstalled(tmpRoot, '@mmnto/totem', '1.40.0');
|
|
269
|
+
const verdict = detectVersionPinnedContract(depsContract(), baseCtx({ repoId: 'totem' }));
|
|
270
|
+
expect(verdict.message).not.toMatch(/content|file|hash|byte/i);
|
|
271
|
+
expect(verdict.message).toMatch(/version|pin|floor|install/i);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
//# sourceMappingURL=parity-detect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parity-detect.test.js","sourceRoot":"","sources":["../src/parity-detect.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parity-manifest parser + config-path resolver (mmnto-ai/totem-strategy#448).
|
|
3
|
+
*
|
|
4
|
+
* The strategy repo owns `doctrine/parity-manifest.yaml` — the canonical,
|
|
5
|
+
* machine-readable enumeration of cohort parity dimensions the `totem doctor
|
|
6
|
+
* --parity` sensor checks for drift. This module is the SKELETON foundation:
|
|
7
|
+
* it resolves the consumer-configured config-path to the manifest, parses +
|
|
8
|
+
* Zod-validates the manifest at the system boundary, and maps the YAML
|
|
9
|
+
* kebab-case keys to camelCase type fields. Per-contract drift detection
|
|
10
|
+
* (per-dimension semantics against populated deps contracts) is OUT OF SCOPE
|
|
11
|
+
* for this skeleton and lives in a follow-on.
|
|
12
|
+
*
|
|
13
|
+
* Design invariants:
|
|
14
|
+
* - **Honest-absent (Tenet 14):** absence is never an error. Unconfigured →
|
|
15
|
+
* a `not-configured` signal; configured-but-missing → a distinct
|
|
16
|
+
* `not-found` signal. The resolver and parser NEVER throw for absence.
|
|
17
|
+
* - **Zod at the boundary only:** the manifest is untrusted on-disk input;
|
|
18
|
+
* Zod validates it once at the parse boundary, then callers work with
|
|
19
|
+
* typed values.
|
|
20
|
+
* - **schema-version gate:** the supported schema version is `1`. An
|
|
21
|
+
* unsupported version does NOT parse contracts — the parser returns an
|
|
22
|
+
* `unsupported-schema` signal so the doctor can refuse an incompatible
|
|
23
|
+
* future shape (per the manifest's own header contract).
|
|
24
|
+
* - **Pure:** no caching, no logging, no process state. Each call reads from
|
|
25
|
+
* scratch.
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
/**
|
|
29
|
+
* The single parity-manifest schema version this doctor build understands.
|
|
30
|
+
* The manifest carries `schema-version: 1` as top-level lifecycle DATA so the
|
|
31
|
+
* doctor can refuse to parse an incompatible future shape rather than
|
|
32
|
+
* silently misread it. Bump in lockstep with a schema migration.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SUPPORTED_PARITY_SCHEMA_VERSION = 1;
|
|
35
|
+
/**
|
|
36
|
+
* Tractability bounds what the doctor may assert about a contract (the
|
|
37
|
+
* honest-absent rule):
|
|
38
|
+
* - `mechanical` file-content / structural equality; doctor may
|
|
39
|
+
* pass/warn/fail.
|
|
40
|
+
* - `version-pinned` consumer pins a canonical version/SHA; doctor checks
|
|
41
|
+
* pin currency only, never semantic content.
|
|
42
|
+
* - `manual-attestation` genuinely semantic, no mechanical sensor; doctor
|
|
43
|
+
* surfaces staleness only, NEVER fails.
|
|
44
|
+
*/
|
|
45
|
+
export declare const ParityTractabilitySchema: z.ZodEnum<["mechanical", "version-pinned", "manual-attestation"]>;
|
|
46
|
+
export type ParityTractability = z.infer<typeof ParityTractabilitySchema>;
|
|
47
|
+
/**
|
|
48
|
+
* One parsed parity contract — the camelCase public shape. Mirrors the #508
|
|
49
|
+
* manifest schema exactly. `blocking` is parsed but UNUSED in the skeleton
|
|
50
|
+
* (per-contract gating is post-skeleton). `consumers` (absent = applies to all
|
|
51
|
+
* cohort repos) supports ADR-102 per-consumer applicability so the doctor can
|
|
52
|
+
* later distinguish drift from cohort-permits-absence.
|
|
53
|
+
*/
|
|
54
|
+
export interface ParityContract {
|
|
55
|
+
id: string;
|
|
56
|
+
dimension: string;
|
|
57
|
+
/** `null` = no external canonical source. The ONLY ref the resolver touches. */
|
|
58
|
+
canonicalSource: string | null;
|
|
59
|
+
/** Human-only context for `canonicalSource`. NEVER parsed as a ref. */
|
|
60
|
+
sourceNote?: string;
|
|
61
|
+
detectionMethod: string;
|
|
62
|
+
expectedValueOrDerivation: string;
|
|
63
|
+
tractability: ParityTractability;
|
|
64
|
+
trackingIssue: string;
|
|
65
|
+
/** Optional human-readable title. */
|
|
66
|
+
title?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Optional doctor exit-code policy flag. Parsed but UNUSED in the skeleton —
|
|
69
|
+
* per-contract gating is deferred to a follow-on.
|
|
70
|
+
*/
|
|
71
|
+
blocking?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Optional cohort applicability (which repos carry this contract). Absent =
|
|
74
|
+
* applies to all cohort repos (ADR-102 per-consumer applicability).
|
|
75
|
+
*/
|
|
76
|
+
consumers?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Optional explicit package identifier (mmnto-ai/totem-strategy#517) — the
|
|
79
|
+
* machine-parseable `@mmnto/*` (or vendor) package name a version/vendor
|
|
80
|
+
* contract pins. Preferred over the id-convention guess when present.
|
|
81
|
+
*/
|
|
82
|
+
package?: string;
|
|
83
|
+
}
|
|
84
|
+
/** A fully parsed + validated parity manifest. */
|
|
85
|
+
export interface ParityManifest {
|
|
86
|
+
schemaVersion: number;
|
|
87
|
+
status: string;
|
|
88
|
+
contracts: ParityContract[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Honest-absent resolver outcome (discriminated union):
|
|
92
|
+
* - `not-configured` — no `orient.parityManifest` set. Sensor → `skip`.
|
|
93
|
+
* - `not-found` — configured, but no file at the resolved path. Sensor
|
|
94
|
+
* → `warn` (distinct, actionable).
|
|
95
|
+
* - `resolved` — a file exists at `path` (absolute).
|
|
96
|
+
*
|
|
97
|
+
* Resolution NEVER throws for absence — both absent states are first-class
|
|
98
|
+
* return values, not exceptions.
|
|
99
|
+
*/
|
|
100
|
+
export type ParityManifestPathStatus = {
|
|
101
|
+
status: 'not-configured';
|
|
102
|
+
} | {
|
|
103
|
+
status: 'not-found';
|
|
104
|
+
path: string;
|
|
105
|
+
} | {
|
|
106
|
+
status: 'resolved';
|
|
107
|
+
path: string;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the configured `orient.parityManifest` config-path to an absolute
|
|
111
|
+
* manifest path. Relative values anchor at `root` (the config/repo root);
|
|
112
|
+
* absolute values are normalized as-is. Mirrors `resolveStrategyRoot`'s
|
|
113
|
+
* relative-anchoring behavior so a deep cwd doesn't mis-anchor the value.
|
|
114
|
+
*
|
|
115
|
+
* @param configValue The raw `orient.parityManifest` config string (or undefined).
|
|
116
|
+
* @param root The config/repo root to anchor relative values against.
|
|
117
|
+
*/
|
|
118
|
+
export declare function resolveParityManifestPath(configValue: string | undefined, root: string): ParityManifestPathStatus;
|
|
119
|
+
/**
|
|
120
|
+
* Honest-absent parse outcome (discriminated union):
|
|
121
|
+
* - `unparseable` — invalid YAML or Zod-schema validation failure.
|
|
122
|
+
* Sensor → `warn` (never crash).
|
|
123
|
+
* - `unsupported-schema` — `schema-version` ≠ the supported version.
|
|
124
|
+
* Contracts are NOT parsed. Sensor → `warn`.
|
|
125
|
+
* - `ok` — a fully parsed + validated manifest.
|
|
126
|
+
*
|
|
127
|
+
* Parsing NEVER throws — every failure is a first-class return value so the
|
|
128
|
+
* doctor pipeline degrades to a `warn` line rather than crashing (mirrors the
|
|
129
|
+
* `findStaleRules` best-effort fallback idiom).
|
|
130
|
+
*/
|
|
131
|
+
export type ParityManifestParseResult = {
|
|
132
|
+
status: 'unparseable';
|
|
133
|
+
reason: string;
|
|
134
|
+
} | {
|
|
135
|
+
status: 'unsupported-schema';
|
|
136
|
+
schemaVersion: number;
|
|
137
|
+
} | {
|
|
138
|
+
status: 'ok';
|
|
139
|
+
manifest: ParityManifest;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Parse raw YAML manifest text into a validated `ParityManifest`.
|
|
143
|
+
*
|
|
144
|
+
* Order of operations matters: the `schema-version` gate runs BEFORE the full
|
|
145
|
+
* contract validation so an unsupported future shape is rejected with a clear
|
|
146
|
+
* `unsupported-schema` signal rather than a confusing Zod failure against a
|
|
147
|
+
* v1-shaped schema. Within v1, contracts are Zod-validated and the kebab-case
|
|
148
|
+
* YAML keys are mapped to the camelCase `ParityContract` fields.
|
|
149
|
+
*/
|
|
150
|
+
export declare function parseParityManifest(yamlText: string): ParityManifestParseResult;
|
|
151
|
+
/**
|
|
152
|
+
* Convenience: resolve the config-path, read the file, and parse it in one
|
|
153
|
+
* call. Returns the resolver's honest-absent signals (`not-configured` /
|
|
154
|
+
* `not-found`) directly, or the parse result. Read failures degrade to an
|
|
155
|
+
* `unparseable` parse result (never throws), so the doctor surface has a single
|
|
156
|
+
* exhaustive switch to render against.
|
|
157
|
+
*/
|
|
158
|
+
export type ParityManifestLoadResult = {
|
|
159
|
+
status: 'not-configured';
|
|
160
|
+
} | {
|
|
161
|
+
status: 'not-found';
|
|
162
|
+
path: string;
|
|
163
|
+
} | {
|
|
164
|
+
status: 'unparseable';
|
|
165
|
+
reason: string;
|
|
166
|
+
path: string;
|
|
167
|
+
} | {
|
|
168
|
+
status: 'unsupported-schema';
|
|
169
|
+
schemaVersion: number;
|
|
170
|
+
path: string;
|
|
171
|
+
} | {
|
|
172
|
+
status: 'ok';
|
|
173
|
+
manifest: ParityManifest;
|
|
174
|
+
path: string;
|
|
175
|
+
};
|
|
176
|
+
export declare function loadParityManifest(configValue: string | undefined, root: string): ParityManifestLoadResult;
|
|
177
|
+
//# sourceMappingURL=parity-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parity-manifest.d.ts","sourceRoot":"","sources":["../src/parity-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAIjD;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,mEAInC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AA8C1E;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,EAAE,kBAAkB,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAID;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GAChC;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GACX,wBAAwB,CAgB1B;AAkBD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,yBAAyB,GACjC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAAC;AAE/C;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,yBAAyB,CA+C/E;AAoBD;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAChC;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GACX,wBAAwB,CA4B1B"}
|