@mmnto/totem 2.0.0 → 2.2.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 (67) hide show
  1. package/dist/compiler.d.ts +12 -0
  2. package/dist/compiler.d.ts.map +1 -1
  3. package/dist/compiler.js +17 -3
  4. package/dist/compiler.js.map +1 -1
  5. package/dist/config-schema.d.ts +28 -3
  6. package/dist/config-schema.d.ts.map +1 -1
  7. package/dist/config-schema.js +22 -3
  8. package/dist/config-schema.js.map +1 -1
  9. package/dist/config-schema.test.js +33 -0
  10. package/dist/config-schema.test.js.map +1 -1
  11. package/dist/describe.d.ts +19 -0
  12. package/dist/describe.d.ts.map +1 -1
  13. package/dist/describe.js +83 -12
  14. package/dist/describe.js.map +1 -1
  15. package/dist/describe.test.js +69 -2
  16. package/dist/describe.test.js.map +1 -1
  17. package/dist/gate-engine.d.ts +11 -1
  18. package/dist/gate-engine.d.ts.map +1 -1
  19. package/dist/gate-engine.js +27 -5
  20. package/dist/gate-engine.js.map +1 -1
  21. package/dist/gate-types.d.ts +17 -2
  22. package/dist/gate-types.d.ts.map +1 -1
  23. package/dist/index.d.ts +8 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/parity-detect.d.ts +41 -4
  28. package/dist/parity-detect.d.ts.map +1 -1
  29. package/dist/parity-detect.js +264 -1
  30. package/dist/parity-detect.js.map +1 -1
  31. package/dist/parity-detect.orientation-rows.test.d.ts +17 -0
  32. package/dist/parity-detect.orientation-rows.test.d.ts.map +1 -0
  33. package/dist/parity-detect.orientation-rows.test.js +357 -0
  34. package/dist/parity-detect.orientation-rows.test.js.map +1 -0
  35. package/dist/parity-label-canon.d.ts +160 -0
  36. package/dist/parity-label-canon.d.ts.map +1 -0
  37. package/dist/parity-label-canon.js +220 -0
  38. package/dist/parity-label-canon.js.map +1 -0
  39. package/dist/parity-label-canon.test.d.ts +11 -0
  40. package/dist/parity-label-canon.test.d.ts.map +1 -0
  41. package/dist/parity-label-canon.test.js +296 -0
  42. package/dist/parity-label-canon.test.js.map +1 -0
  43. package/dist/parity-manifest.d.ts +9 -0
  44. package/dist/parity-manifest.d.ts.map +1 -1
  45. package/dist/parity-manifest.js +47 -0
  46. package/dist/parity-manifest.js.map +1 -1
  47. package/dist/parity-manifest.test.js +45 -0
  48. package/dist/parity-manifest.test.js.map +1 -1
  49. package/dist/recurrence-stats.d.ts +10 -10
  50. package/dist/retrospect.d.ts +42 -42
  51. package/dist/selection-manifest.d.ts +4 -4
  52. package/dist/selection-manifest.d.ts.map +1 -1
  53. package/dist/selection-manifest.js +2 -0
  54. package/dist/selection-manifest.js.map +1 -1
  55. package/dist/transport-shield.d.ts +190 -0
  56. package/dist/transport-shield.d.ts.map +1 -0
  57. package/dist/transport-shield.fold.test.d.ts +2 -0
  58. package/dist/transport-shield.fold.test.d.ts.map +1 -0
  59. package/dist/transport-shield.fold.test.js +439 -0
  60. package/dist/transport-shield.fold.test.js.map +1 -0
  61. package/dist/transport-shield.js +1040 -0
  62. package/dist/transport-shield.js.map +1 -0
  63. package/dist/transport-shield.test.d.ts +2 -0
  64. package/dist/transport-shield.test.d.ts.map +1 -0
  65. package/dist/transport-shield.test.js +298 -0
  66. package/dist/transport-shield.test.js.map +1 -0
  67. package/package.json +1 -1
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Tests for the two 472-charter ORIENTATION rows the network-read-only family
3
+ * senses (mmnto-ai/totem#2791): `gh-issue-label-canon` and
4
+ * `gh-project-vocabulary`, rendered by `detectNetworkPostureContract`.
5
+ *
6
+ * Pure + synchronous + NEVER-networks: every test injects pre-fetched canned
7
+ * snapshots (the CLI-edge fetch is not exercised here) and, for the label row,
8
+ * the canon TEXT as a roster-wide surface. Zero live network, zero spawns.
9
+ *
10
+ * Invariants pinned: a cannot-verify outcome on either surface (or on the
11
+ * canon) is never a drift verdict; an empty canon can never pass; the
12
+ * provenance the CLI edge disclosed is echoed in the line; a repo with no
13
+ * project binding, or a sibling, is honest-absent; the expected option sets
14
+ * come from the row's own text; per-repo lines; consumers scoping.
15
+ */
16
+ import { describe, expect, it } from 'vitest';
17
+ import { detectNetworkPostureContract, } from './parity-detect.js';
18
+ // ─── Fixtures ───────────────────────────────────────────
19
+ const ROW_TEXT = 'Status = Todo | In Progress | Done | Closed-Lateral | Closed-Superseded | Closed-Done | Informs-Design; Priority = Now | Next | Blocked | Horizon; extra fields permitted';
20
+ const STATUS = [
21
+ 'Todo',
22
+ 'In Progress',
23
+ 'Done',
24
+ 'Closed-Lateral',
25
+ 'Closed-Superseded',
26
+ 'Closed-Done',
27
+ 'Informs-Design',
28
+ ];
29
+ const PRIORITY = ['Now', 'Next', 'Blocked', 'Horizon'];
30
+ function mkContract(id, expectedValue, consumers) {
31
+ return {
32
+ id,
33
+ dimension: 'orientation',
34
+ canonicalSource: id === 'gh-issue-label-canon' ? 'mmnto-ai/totem:scripts/sync-labels.ps1' : null,
35
+ detectionMethod: 'capability-probe',
36
+ expectedValueOrDerivation: expectedValue,
37
+ tractability: 'mechanical',
38
+ trackingIssue: 'mmnto-ai/totem-strategy#472',
39
+ manifestation: 'capability-probe',
40
+ senses: 'present',
41
+ ...(consumers !== undefined ? { consumers } : {}),
42
+ };
43
+ }
44
+ const labelContract = mkContract('gh-issue-label-canon', 'derived from scripts/sync-labels.ps1');
45
+ const vocabContract = mkContract('gh-project-vocabulary', ROW_TEXT);
46
+ const CANON_SCRIPT = [
47
+ 'gh label edit "tier-1" --color "d73a4a" --description "Immediate priority" --repo $Repo',
48
+ 'gh label edit "type: bug" --color "d73a4a" --description "Something is not working" --repo $Repo',
49
+ 'gh label edit "scope: cli" --color "de89ff" --description "CLI" --repo $Repo',
50
+ 'Merge-Label "bug" "type: bug"',
51
+ ].join('\n');
52
+ const LOCAL_PROVENANCE = 'local checkout scripts/sync-labels.ps1';
53
+ const canonOk = {
54
+ outcome: 'ok',
55
+ data: CANON_SCRIPT,
56
+ detail: LOCAL_PROVENANCE,
57
+ };
58
+ function labelsOk(labels) {
59
+ return { outcome: 'ok', data: labels };
60
+ }
61
+ const conformantLabels = labelsOk([
62
+ { name: 'tier-1', color: 'd73a4a', description: 'Immediate priority' },
63
+ { name: 'type: bug', color: 'D73A4A', description: 'Something is not working' },
64
+ { name: 'scope: cli', color: 'de89ff', description: 'CLI' },
65
+ ]);
66
+ function labelSnapshot(repoSlug, repoId, labels) {
67
+ return { repoSlug, repoId, surfaces: labels === undefined ? {} : { labels } };
68
+ }
69
+ function labelCtx(repos, labelCanon = canonOk) {
70
+ return {
71
+ row: 'gh-issue-label-canon',
72
+ repos,
73
+ ...(labelCanon !== undefined ? { labelCanon } : {}),
74
+ };
75
+ }
76
+ function fieldsBody(nodes, hasNextPage = false, projectV2 = 'present') {
77
+ return {
78
+ data: {
79
+ organization: {
80
+ projectV2: projectV2 === 'null'
81
+ ? null
82
+ : { title: 'Convergent Spine Roadmap', fields: { pageInfo: { hasNextPage }, nodes } },
83
+ },
84
+ },
85
+ };
86
+ }
87
+ const field = (name, options) => ({
88
+ name,
89
+ options: options.map((o) => ({ name: o })),
90
+ });
91
+ /** The canonical project as the GraphQL read returns it — one non-single-select node ({}) included. */
92
+ const canonicalFields = fieldsBody([{}, field('Status', STATUS), field('Priority', PRIORITY)]);
93
+ const BOUND = { kind: 'bound', owner: 'mmnto-ai', number: 1 };
94
+ function vocabSnapshot(repoSlug, repoId, project, projectFields) {
95
+ return {
96
+ repoSlug,
97
+ repoId,
98
+ surfaces: projectFields === undefined ? {} : { projectFields },
99
+ ...(project !== undefined ? { project } : {}),
100
+ };
101
+ }
102
+ function vocabCtx(repos) {
103
+ return { row: 'gh-project-vocabulary', repos };
104
+ }
105
+ // ─── gh-issue-label-canon ────────────────────────────────
106
+ describe('gh-issue-label-canon', () => {
107
+ it('passes on a conformant label list and echoes the canon provenance', () => {
108
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([labelSnapshot('mmnto-ai/totem', 'totem', conformantLabels)]));
109
+ expect(lines).toHaveLength(1);
110
+ expect(lines[0]?.lineName).toBe('Parity: gh-issue-label-canon [mmnto-ai/totem]');
111
+ expect(lines[0]?.verdict.status).toBe('pass');
112
+ // The message names the repo (the `--json` readout has no per-repo line name).
113
+ expect(lines[0]?.verdict.message).toContain('mmnto-ai/totem: 3/3 canonical labels present');
114
+ expect(lines[0]?.verdict.message).toContain('3 canonical namespaces');
115
+ expect(lines[0]?.verdict.message).toContain(`canon: ${LOCAL_PROVENANCE}`);
116
+ });
117
+ it('warns naming a missing canonical label', () => {
118
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([
119
+ labelSnapshot('mmnto-ai/totem', 'totem', labelsOk([
120
+ { name: 'tier-1', color: 'd73a4a', description: 'Immediate priority' },
121
+ { name: 'scope: cli', color: 'de89ff', description: 'CLI' },
122
+ ])),
123
+ ]));
124
+ expect(lines[0]?.verdict.status).toBe('warn');
125
+ expect(lines[0]?.verdict.message).toContain('mmnto-ai/totem: 2/3 canonical labels present');
126
+ expect(lines[0]?.verdict.message).toContain('missing [type: bug]');
127
+ });
128
+ it('warns naming a redefined colour and a redefined description', () => {
129
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([
130
+ labelSnapshot('mmnto-ai/totem', 'totem', labelsOk([
131
+ { name: 'tier-1', color: 'fbca04', description: 'Immediate priority' },
132
+ { name: 'type: bug', color: 'd73a4a', description: null },
133
+ { name: 'scope: cli', color: 'de89ff', description: 'CLI' },
134
+ ])),
135
+ ]));
136
+ expect(lines[0]?.verdict.status).toBe('warn');
137
+ expect(lines[0]?.verdict.message).toContain('tier-1 (color fbca04 vs canon d73a4a)');
138
+ expect(lines[0]?.verdict.message).toContain('type: bug (description)');
139
+ });
140
+ it('warns on a name inside a canonical namespace that is not in the canon', () => {
141
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([
142
+ labelSnapshot('mmnto-ai/totem', 'totem', labelsOk([
143
+ ...conformantLabels.data,
144
+ { name: 'scope: docs', color: 'de89ff', description: 'x' },
145
+ ])),
146
+ ]));
147
+ expect(lines[0]?.verdict.status).toBe('warn');
148
+ expect(lines[0]?.verdict.message).toContain('in a canonical namespace but not in the canon [scope: docs]');
149
+ });
150
+ it('passes with extra labels outside the namespaces and a retired name, both reported', () => {
151
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([
152
+ labelSnapshot('mmnto-ai/totem', 'totem', labelsOk([
153
+ ...conformantLabels.data,
154
+ { name: 'disposition: done', color: '000000', description: null },
155
+ { name: '1.11.0', color: 'ededed', description: null },
156
+ { name: 'bug', color: 'ededed', description: null },
157
+ ])),
158
+ ]));
159
+ expect(lines[0]?.verdict.status).toBe('pass');
160
+ expect(lines[0]?.verdict.message).toContain('2 extra outside the canonical namespaces permitted');
161
+ expect(lines[0]?.verdict.message).toContain('retired name(s) still present: bug');
162
+ });
163
+ it('skips on a no-transport label surface and is unknown on auth / not-found / error (never a drift verdict)', () => {
164
+ const outcomes = [
165
+ ['no-transport', 'skip'],
166
+ ['auth', 'unknown'],
167
+ ['not-found', 'unknown'],
168
+ ['error', 'unknown'],
169
+ ];
170
+ for (const [outcome, status] of outcomes) {
171
+ const lines = detectNetworkPostureContract(labelContract, labelCtx([labelSnapshot('mmnto-ai/totem', 'totem', { outcome })]));
172
+ expect(lines[0]?.verdict.status, outcome).toBe(status);
173
+ }
174
+ });
175
+ it('is unknown when the label surface was not probed or is not a label list', () => {
176
+ const notProbed = detectNetworkPostureContract(labelContract, labelCtx([labelSnapshot('mmnto-ai/totem', 'totem', undefined)]));
177
+ expect(notProbed[0]?.verdict.status).toBe('unknown');
178
+ // Cannot-verify messages name the repo too (pass 2 p2-F4, pinned pass 3 p3-F3).
179
+ expect(notProbed[0]?.verdict.message).toContain('mmnto-ai/totem labels: not probed');
180
+ const unshaped = detectNetworkPostureContract(labelContract, labelCtx([labelSnapshot('mmnto-ai/totem', 'totem', { outcome: 'ok', data: { nope: true } })]));
181
+ expect(unshaped[0]?.verdict.status).toBe('unknown');
182
+ expect(unshaped[0]?.verdict.message).toContain('not a label list');
183
+ });
184
+ it('is cannot-verify for EVERY repo when the canon is absent, unreadable, not text, or empty', () => {
185
+ const repos = [
186
+ labelSnapshot('mmnto-ai/totem', 'totem', conformantLabels),
187
+ labelSnapshot('mmnto-ai/totem-strategy', 'totem-strategy', conformantLabels),
188
+ ];
189
+ // Built inline: an explicit `undefined` argument would select labelCtx's DEFAULT canon.
190
+ const absent = detectNetworkPostureContract(labelContract, {
191
+ row: 'gh-issue-label-canon',
192
+ repos,
193
+ });
194
+ expect(absent.map((l) => l.verdict.status)).toEqual(['unknown', 'unknown']);
195
+ // A roster-wide canon fact still names each repo on its own line (pass 3, p3-F1).
196
+ expect(absent[0]?.verdict.message).toContain('mmnto-ai/totem: label canon');
197
+ expect(absent[0]?.verdict.message).toContain('not resolved');
198
+ expect(absent[1]?.verdict.message).toContain('mmnto-ai/totem-strategy: label canon');
199
+ const offline = detectNetworkPostureContract(labelContract, labelCtx(repos, { outcome: 'no-transport' }));
200
+ expect(offline.map((l) => l.verdict.status)).toEqual(['skip', 'skip']);
201
+ const fetchFailed = detectNetworkPostureContract(labelContract, labelCtx(repos, { outcome: 'error', detail: 'canonical fetch: HTTP 500' }));
202
+ expect(fetchFailed[0]?.verdict.status).toBe('unknown');
203
+ expect(fetchFailed[0]?.verdict.message).toContain('HTTP 500');
204
+ const notText = detectNetworkPostureContract(labelContract, labelCtx(repos, { outcome: 'ok', data: { content: 'x' }, detail: 'p' }));
205
+ expect(notText[0]?.verdict.status).toBe('unknown');
206
+ expect(notText[0]?.verdict.message).toContain('not text');
207
+ const empty = detectNetworkPostureContract(labelContract, labelCtx(repos, { outcome: 'ok', data: 'Write-Host "nothing"', detail: 'p' }));
208
+ expect(empty.map((l) => l.verdict.status)).toEqual(['unknown', 'unknown']);
209
+ expect(empty[0]?.verdict.message).toContain('empty canon');
210
+ });
211
+ it('renders one line per roster repo and applies consumers scoping per repo', () => {
212
+ const scoped = mkContract('gh-issue-label-canon', 'derived', ['totem']);
213
+ const lines = detectNetworkPostureContract(scoped, labelCtx([
214
+ labelSnapshot('mmnto-ai/totem', 'totem', conformantLabels),
215
+ labelSnapshot('mmnto-ai/liquid-city', 'liquid-city', { outcome: 'auth' }),
216
+ ]));
217
+ expect(lines.map((l) => l.lineName)).toEqual(['Parity: gh-issue-label-canon [mmnto-ai/totem]']);
218
+ const both = detectNetworkPostureContract(labelContract, labelCtx([
219
+ labelSnapshot('mmnto-ai/totem', 'totem', conformantLabels),
220
+ labelSnapshot('mmnto-ai/liquid-city', 'liquid-city', { outcome: 'auth' }),
221
+ ]));
222
+ expect(both.map((l) => l.verdict.status)).toEqual(['pass', 'unknown']);
223
+ });
224
+ });
225
+ // ─── gh-project-vocabulary ───────────────────────────────
226
+ describe('gh-project-vocabulary', () => {
227
+ it('passes when both governed option sets equal the row text, naming the project and the counts', () => {
228
+ const lines = detectNetworkPostureContract(vocabContract, vocabCtx([
229
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: canonicalFields }),
230
+ ]));
231
+ expect(lines).toHaveLength(1);
232
+ expect(lines[0]?.lineName).toBe('Parity: gh-project-vocabulary [mmnto-ai/totem]');
233
+ expect(lines[0]?.verdict.status).toBe('pass');
234
+ expect(lines[0]?.verdict.message).toContain('mmnto-ai/projects/1: Status 7/7, Priority 4/4 option sets equal the canon');
235
+ });
236
+ it('passes with an extra single-select field and a different option order, both reported', () => {
237
+ const body = fieldsBody([
238
+ field('Status', [...STATUS].reverse()),
239
+ field('Priority', PRIORITY),
240
+ field('M', ['M0', 'M1']),
241
+ ]);
242
+ const lines = detectNetworkPostureContract(vocabContract, vocabCtx([
243
+ vocabSnapshot('mmnto-ai/liquid-city', 'liquid-city', { kind: 'bound', owner: 'mmnto-ai', number: 2 }, { outcome: 'ok', data: body }),
244
+ ]));
245
+ expect(lines[0]?.verdict.status).toBe('pass');
246
+ expect(lines[0]?.verdict.message).toContain('mmnto-ai/projects/2');
247
+ expect(lines[0]?.verdict.message).toContain('1 extra field(s) permitted: M');
248
+ expect(lines[0]?.verdict.message).toContain('option order or multiplicity differs on Status');
249
+ });
250
+ it('warns naming a missing and an extra option on a governed field', () => {
251
+ const body = fieldsBody([
252
+ field('Status', [...STATUS.filter((o) => o !== 'Done'), 'Shipped']),
253
+ field('Priority', PRIORITY),
254
+ ]);
255
+ const lines = detectNetworkPostureContract(vocabContract, vocabCtx([vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: body })]));
256
+ expect(lines[0]?.verdict.status).toBe('warn');
257
+ expect(lines[0]?.verdict.message).toContain('Status: option set differs — missing [Done], extra [Shipped]');
258
+ });
259
+ it('warns when a governed field is absent from the project (the twin reads it as a fault)', () => {
260
+ const body = fieldsBody([field('Status', STATUS)]);
261
+ const lines = detectNetworkPostureContract(vocabContract, vocabCtx([vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: body })]));
262
+ expect(lines[0]?.verdict.status).toBe('warn');
263
+ expect(lines[0]?.verdict.message).toContain('Priority: field absent');
264
+ });
265
+ it('is honest-absent (skip) for an unbound current repo, a sibling, and an unresolved binding', () => {
266
+ const lines = detectNetworkPostureContract(vocabContract, vocabCtx([
267
+ vocabSnapshot('mmnto-ai/totem-status', 'totem-status', { kind: 'unbound' }),
268
+ vocabSnapshot('mmnto-ai/liquid-city', 'liquid-city', { kind: 'sibling' }),
269
+ vocabSnapshot('mmnto-ai/totem-strategy', 'totem-strategy', undefined),
270
+ ]));
271
+ expect(lines.map((l) => l.verdict.status)).toEqual(['skip', 'skip', 'skip']);
272
+ expect(lines[0]?.verdict.message).toContain('mmnto-ai/totem-status: no project bound');
273
+ expect(lines[0]?.verdict.message).toContain('orient.projectNumber unset');
274
+ expect(lines[1]?.verdict.message).toContain('mmnto-ai/liquid-city: bound project not derivable');
275
+ expect(lines[1]?.verdict.message).toContain('sibling repo');
276
+ expect(lines[2]?.verdict.message).toContain('mmnto-ai/totem-strategy: project binding not resolved');
277
+ });
278
+ it('is unknown when the row text yields no option sets (never a hardcoded pass)', () => {
279
+ const prose = mkContract('gh-project-vocabulary', 'the option sets equal Project 1 (extra fields permitted)');
280
+ const lines = detectNetworkPostureContract(prose, vocabCtx([
281
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: canonicalFields }),
282
+ ]));
283
+ expect(lines[0]?.verdict.status).toBe('unknown');
284
+ expect(lines[0]?.verdict.message).toContain('cannot derive the expected option sets');
285
+ expect(lines[0]?.verdict.message).toContain('expected-value-or-derivation text');
286
+ });
287
+ it('prefers the STRUCTURED expected-option-sets field over the prose, and names which canon it read', () => {
288
+ // The prose says one thing, the structured field another: the field wins
289
+ // (strategy's 2026-09-05 ruling — the field is the contract, the prose the
290
+ // pinned interim), and the line discloses the source it read.
291
+ const structured = {
292
+ ...mkContract('gh-project-vocabulary', 'Status = Todo | Done; Priority = Now | Next'),
293
+ expectedOptionSets: { Status: STATUS, Priority: PRIORITY },
294
+ };
295
+ const lines = detectNetworkPostureContract(structured, vocabCtx([
296
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: canonicalFields }),
297
+ ]));
298
+ expect(lines[0]?.verdict.status).toBe('pass');
299
+ expect(lines[0]?.verdict.message).toContain('Status 7/7, Priority 4/4');
300
+ expect(lines[0]?.verdict.message).toContain('(canon: expected-option-sets)');
301
+ // Prose-only rows say so too.
302
+ const prose = detectNetworkPostureContract(vocabContract, vocabCtx([
303
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: canonicalFields }),
304
+ ]));
305
+ expect(prose[0]?.verdict.message).toContain('(canon: expected-value-or-derivation text)');
306
+ });
307
+ it('is unknown when the project is null / inaccessible, when the fields overflow one page, or when the body is unshaped', () => {
308
+ const nullProject = detectNetworkPostureContract(vocabContract, vocabCtx([
309
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, {
310
+ outcome: 'ok',
311
+ data: fieldsBody([], false, 'null'),
312
+ }),
313
+ ]));
314
+ expect(nullProject[0]?.verdict.status).toBe('unknown');
315
+ expect(nullProject[0]?.verdict.message).toContain('not found or not accessible');
316
+ const overflow = detectNetworkPostureContract(vocabContract, vocabCtx([
317
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, {
318
+ outcome: 'ok',
319
+ data: fieldsBody([field('Status', STATUS), field('Priority', PRIORITY)], true),
320
+ }),
321
+ ]));
322
+ expect(overflow[0]?.verdict.status).toBe('unknown');
323
+ expect(overflow[0]?.verdict.message).toContain('more fields than one page');
324
+ const unshaped = detectNetworkPostureContract(vocabContract, vocabCtx([
325
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, {
326
+ outcome: 'ok',
327
+ data: { data: { organization: { projectV2: { fields: 'nope' } } } },
328
+ }),
329
+ ]));
330
+ expect(unshaped[0]?.verdict.status).toBe('unknown');
331
+ expect(unshaped[0]?.verdict.message).toContain('not a project field list');
332
+ });
333
+ it('skips on no-transport and is unknown on auth / error / not probed (never a drift verdict)', () => {
334
+ const offline = detectNetworkPostureContract(vocabContract, vocabCtx([vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'no-transport' })]));
335
+ expect(offline[0]?.verdict.status).toBe('skip');
336
+ const auth = detectNetworkPostureContract(vocabContract, vocabCtx([
337
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'auth', detail: 'HTTP 403' }),
338
+ ]));
339
+ expect(auth[0]?.verdict.status).toBe('unknown');
340
+ expect(auth[0]?.verdict.message).toContain('HTTP 403');
341
+ const notProbed = detectNetworkPostureContract(vocabContract, vocabCtx([vocabSnapshot('mmnto-ai/totem', 'totem', BOUND)]));
342
+ expect(notProbed[0]?.verdict.status).toBe('unknown');
343
+ expect(notProbed[0]?.verdict.message).toContain('not probed');
344
+ });
345
+ it('renders one line per roster repo and applies consumers scoping per repo', () => {
346
+ const scoped = mkContract('gh-project-vocabulary', ROW_TEXT, ['totem']);
347
+ const lines = detectNetworkPostureContract(scoped, vocabCtx([
348
+ vocabSnapshot('mmnto-ai/totem', 'totem', BOUND, { outcome: 'ok', data: canonicalFields }),
349
+ vocabSnapshot('mmnto-ai/liquid-city', 'liquid-city', { kind: 'sibling' }),
350
+ ]));
351
+ expect(lines.map((l) => l.lineName)).toEqual([
352
+ 'Parity: gh-project-vocabulary [mmnto-ai/totem]',
353
+ ]);
354
+ expect(lines[0]?.verdict.status).toBe('pass');
355
+ });
356
+ });
357
+ //# sourceMappingURL=parity-detect.orientation-rows.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parity-detect.orientation-rows.test.js","sourceRoot":"","sources":["../src/parity-detect.orientation-rows.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Pure derivations for the two ORIENTATION parity rows the network-read-only
3
+ * family senses (mmnto-ai/totem#2791; the 472 charter's § 4b / § 4c requests,
4
+ * mmnto-ai/totem-strategy:operations/472-issue-disposition-preregistration.md):
5
+ *
6
+ * - `gh-issue-label-canon` — the label canon is PARSED from
7
+ * `mmnto-ai/totem:scripts/sync-labels.ps1` at run time (Tenet 20: derived,
8
+ * never mirrored) and a repo's live label list is judged against it.
9
+ * - `gh-project-vocabulary` — the canonical option sets are PARSED from the
10
+ * manifest row's own `expected-value-or-derivation` text, and a bound
11
+ * project's single-select fields are judged against them.
12
+ *
13
+ * Everything here is pure over text / parsed JSON: no I/O, no network, no
14
+ * module-level state. The verdict LINES (status / message) are rendered by
15
+ * `parity-detect.ts`'s network-posture dispatch, which owns the cannot-verify
16
+ * ladder; this module returns the drift FACTS only. The semantics are aligned
17
+ * with the strategy-local twin (`mmnto-ai/totem-strategy:tools/gh-parity-twins.cjs`,
18
+ * rung 1 of mmnto-ai/totem-strategy#472) so the two readers agree on every
19
+ * cohort repo: colour compares without `#` and case-insensitively, description
20
+ * compares exactly (untrimmed), the namespace token keeps its trailing space,
21
+ * option ORDER is information and never a fault, and a governed field that is
22
+ * absent IS a fault (its option set is empty, which is not the canonical set).
23
+ * One disclosed asymmetry: this module strips a leading `#` from the CANON's
24
+ * colour too (the twin lower-cases both sides but strips `#` on the live side
25
+ * only), so a `#`-prefixed hex in the script would still match here — identical
26
+ * readings while the script writes bare hex, as every one of its eighteen calls
27
+ * does today. Option NAMES are compared exactly on the live side; the canon's
28
+ * authoring whitespace is trimmed (the prose grammar cannot avoid it, and a
29
+ * quoted YAML member may carry it), so a padded live option name is a real
30
+ * difference the board shows, never smoothed away.
31
+ */
32
+ /** One canonical label as the script defines it (`gh label edit "<name>" --color "<hex>" --description "<text>"`). */
33
+ export interface CanonicalLabel {
34
+ name: string;
35
+ /** Lower-case hex without a leading `#` (the API's shape). */
36
+ color: string;
37
+ description: string;
38
+ }
39
+ /** One retirement the script performs (`Merge-Label "<old>" "<new>"`). */
40
+ export interface LabelMerge {
41
+ from: string;
42
+ to: string;
43
+ }
44
+ /** The parsed canon: the defined labels, the namespace tokens derived from their names, the retirements. */
45
+ export interface LabelCanon {
46
+ labels: CanonicalLabel[];
47
+ /** Derived from the canonical names, never hand-listed; the space is part of a colon token. */
48
+ namespaces: string[];
49
+ merges: LabelMerge[];
50
+ }
51
+ /** One live label as `GET /repos/{owner}/{repo}/labels` returns it (already Zod-narrowed by the caller). */
52
+ export interface LiveLabel {
53
+ name: string;
54
+ color?: string | null;
55
+ description?: string | null;
56
+ }
57
+ /** A canonical label whose colour or description the live repo redefined. */
58
+ export interface LabelRedefinition {
59
+ name: string;
60
+ /** Present when the colour differs (expected / actual, both normalized). */
61
+ color?: {
62
+ expected: string;
63
+ actual: string;
64
+ };
65
+ /** True when the description differs from the canon's text. */
66
+ description?: boolean;
67
+ }
68
+ /** A live label that occupies a canonical namespace without being in the canon. */
69
+ export interface NamespaceSquatter {
70
+ name: string;
71
+ namespace: string;
72
+ }
73
+ /** The § 4c drift facts for one repo. */
74
+ export interface LabelCanonDrift {
75
+ /** Every fault class empty. */
76
+ conforming: boolean;
77
+ /** Canonical names absent from the live list. */
78
+ missing: string[];
79
+ /** Canonical names present with a different colour or description. */
80
+ redefined: LabelRedefinition[];
81
+ /** Live names inside a canonical namespace but outside the canon. */
82
+ squatters: NamespaceSquatter[];
83
+ /** Live names outside every canonical namespace — permitted, reported. */
84
+ extra: string[];
85
+ /** Retired names (a `Merge-Label` source) still present — reported, never a fault. */
86
+ retiredPresent: string[];
87
+ }
88
+ /** Normalize a colour to the API's shape: no leading `#`, lower-case. */
89
+ export declare function normalizeLabelColor(raw: string | null | undefined): string;
90
+ /**
91
+ * Parse the label canon out of the script text. PURE. An empty `labels` array
92
+ * means the text defined nothing — the CALLER refuses to judge against it
93
+ * (never a conformance verdict from an empty canon).
94
+ */
95
+ export declare function parseLabelCanon(scriptText: string): LabelCanon;
96
+ /**
97
+ * The namespace tokens the canonical names imply: the name through its first
98
+ * `: ` (the space IS part of the token — `type:audit` does not squat on
99
+ * `type: `), else through its first `-` (`tier-1` → `tier-`). A name with
100
+ * neither contributes no token. Derived, so a new namespace in the script
101
+ * becomes a sensed namespace here without a code change.
102
+ */
103
+ export declare function namespaceTokensOf(names: readonly string[]): string[];
104
+ /**
105
+ * The § 4c predicate over one repo's live labels. PURE.
106
+ *
107
+ * Faults: a canonical name absent; a canonical name present with a different
108
+ * colour or description; a live name inside a canonical namespace that is not
109
+ * in the canon (the "never redefine a canonical namespace" half). Live names
110
+ * outside every canonical namespace (`routine:*`, `disposition:*`, bare words)
111
+ * are permitted additions, reported and never flagged; a retired name still
112
+ * present is reported the same way.
113
+ */
114
+ export declare function labelCanonDrift(live: readonly LiveLabel[], canon: LabelCanon): LabelCanonDrift;
115
+ /**
116
+ * Parse the canonical option sets out of the row's `expected-value-or-derivation`
117
+ * text. The grammar is strict and small: clauses split on `;`, each clause
118
+ * `Field = a | b | c`; a clause without `=` (e.g. "extra fields permitted") is
119
+ * ignored; an empty field name or an empty option list drops the clause. The
120
+ * Map preserves clause order. An EMPTY map means the row text yields no
121
+ * governed field — the caller renders cannot-verify, never a hardcoded pass.
122
+ */
123
+ export declare function parseExpectedOptionSets(text: string): Map<string, string[]>;
124
+ /** One single-select field as the project's field config exposes it (already narrowed by the caller). */
125
+ export interface ProjectSingleSelectField {
126
+ name: string;
127
+ options: readonly {
128
+ name: string;
129
+ }[];
130
+ }
131
+ /**
132
+ * `{ Status: [...], Priority: [...] }` for every single-select field on the
133
+ * project. Option names are kept RAW: the live side is what the board shows, and
134
+ * the canon side is the one that carries authoring whitespace (trimmed there).
135
+ */
136
+ export declare function optionSetsOfProjectFields(fields: readonly ProjectSingleSelectField[]): Map<string, string[]>;
137
+ /** One governed field's fault. */
138
+ export interface ProjectVocabularyFault {
139
+ field: string;
140
+ kind: 'field-missing' | 'option-set-differs';
141
+ /** `option-set-differs` only: canonical options absent from the project. */
142
+ missing: string[];
143
+ /** `option-set-differs` only: project options outside the canonical set. */
144
+ extra: string[];
145
+ }
146
+ /** The § 4b drift facts for one bound project. */
147
+ export interface ProjectVocabularyDrift {
148
+ conforming: boolean;
149
+ faults: ProjectVocabularyFault[];
150
+ /** Governed fields whose SET equals the canon in a different order or multiplicity (a duplicated option) — information, never a fault. */
151
+ orderDiffers: string[];
152
+ /** Single-select fields beyond the governed ones — permitted additions (LC's `M`), reported. */
153
+ added: string[];
154
+ }
155
+ /**
156
+ * The § 4b predicate: every governed field (a key of `expected`) present on the
157
+ * project with EXACTLY the canonical option set, order-insensitive. PURE.
158
+ */
159
+ export declare function projectVocabularyDrift(actual: ReadonlyMap<string, readonly string[]>, expected: ReadonlyMap<string, readonly string[]>): ProjectVocabularyDrift;
160
+ //# sourceMappingURL=parity-label-canon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parity-label-canon.d.ts","sourceRoot":"","sources":["../src/parity-label-canon.ts"],"names":[],"mappings":"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"}