@mmnto/totem 1.53.3 → 1.53.4

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.
@@ -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"}