yarramate 0.6.0 → 0.7.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 (38) hide show
  1. package/README.md +39 -12
  2. package/catalogues/core-enrichment.yaml +700 -0
  3. package/dist/adapters/mcp-cli.js +55 -49
  4. package/dist/apply-command.d.ts +2 -0
  5. package/dist/apply-command.js +199 -0
  6. package/dist/{new-command.d.ts → ask-command.d.ts} +1 -1
  7. package/dist/ask-command.js +729 -0
  8. package/dist/brief.d.ts +3 -0
  9. package/dist/brief.js +235 -0
  10. package/dist/cli-support.d.ts +1 -1
  11. package/dist/cli-support.js +1 -1
  12. package/dist/cli.js +22 -590
  13. package/dist/compiler.js +13 -0
  14. package/dist/core-contract.d.ts +1 -1
  15. package/dist/{status-command.d.ts → design-command.d.ts} +1 -1
  16. package/dist/design-command.js +218 -0
  17. package/dist/export-command.d.ts +2 -0
  18. package/dist/export-command.js +228 -0
  19. package/dist/interrogate-command.d.ts +104 -0
  20. package/dist/interrogate-command.js +268 -0
  21. package/dist/next-command.d.ts +5 -8
  22. package/dist/next-command.js +106 -211
  23. package/docs/CONSUMING-YARRAMATE.md +28 -21
  24. package/package.json +13 -11
  25. package/schema/yarramate-apply-result.schema.json +32 -0
  26. package/schema/yarramate-ask-result.schema.json +391 -0
  27. package/schema/yarramate-core-contract.schema.json +5 -11
  28. package/schema/yarramate-design-step.schema.json +152 -0
  29. package/schema/yarramate-document.schema.json +76 -9
  30. package/schema/yarramate-interrogation-report.schema.json +89 -0
  31. package/schema/yarramate-operations.schema.json +303 -0
  32. package/schema/yarramate-question-catalogue.schema.json +431 -0
  33. package/skills/yarramate-architecture/SKILL.md +42 -17
  34. package/skills/yarramate-architecture/references/native-authoring.md +73 -17
  35. package/dist/new-command.js +0 -111
  36. package/dist/status-command.js +0 -174
  37. package/schema/yarramate-next-result.schema.json +0 -85
  38. package/schema/yarramate-status-result.schema.json +0 -278
package/dist/cli.js CHANGED
@@ -1,244 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync, } from 'node:fs';
3
3
  import { dirname, relative, resolve } from 'node:path';
4
- import { isSeq, parseDocument } from 'yaml';
5
- import { compileWorkspace, compileWorkspaceWithProfileContext, } from './compiler.js';
6
- import { compareArchitectureStates } from './architecture-state.js';
7
- import { serializeSemanticGraph } from './graph.js';
8
- import { diagnosticJson, humanDiagnostics, isMainModule, resolveCliWorkspaceSources, usage, versionResult, } from './cli-support.js';
4
+ import { compileWorkspace } from './compiler.js';
5
+ import { diagnosticJson, isMainModule, usage, versionResult, } from './cli-support.js';
6
+ import { runAskCommand } from './ask-command.js';
9
7
  import { runCheckCommand } from './check-command.js';
10
- import { runNewCommand } from './new-command.js';
11
- import { runNextCommand } from './next-command.js';
12
- import { runStatusCommand } from './status-command.js';
13
- import { evaluateEvidence, evaluateEvidenceWorkspace, loadEvidence, } from './evidence.js';
8
+ import { runExportCommand } from './export-command.js';
9
+ import { runApplyCommand } from './apply-command.js';
10
+ import { runDesignCommand } from './design-command.js';
11
+ import { evaluateEvidenceWorkspace, loadEvidence, } from './evidence.js';
14
12
  import { reconcileEvidenceReports } from './reconciliation.js';
15
13
  import { loadWorkspaceManifest } from './workspace.js';
16
- import { evaluateProjection, loadProjection, renderBudgetedContext, renderProjectionMarkdown, } from './projection.js';
17
- const extractBudget = (options) => {
18
- const rest = [];
19
- let budget;
20
- for (let index = 0; index < options.length; index += 1) {
21
- const option = options[index];
22
- if (option === '--budget') {
23
- const value = options[index + 1];
24
- if (value === undefined ||
25
- budget !== undefined ||
26
- !/^[1-9][0-9]*$/.test(value)) {
27
- return { ok: false };
28
- }
29
- budget = Number(value);
30
- index += 1;
31
- continue;
32
- }
33
- if (option !== undefined)
34
- rest.push(option);
35
- }
36
- return budget === undefined ? { ok: true, rest } : { ok: true, budget, rest };
37
- };
38
- const runProjection = (options, cwd, output) => {
39
- const extracted = output === 'json' ? extractBudget(options) : { ok: true, rest: options };
40
- if (!extracted.ok) {
41
- return { exitCode: 2, stdout: '', stderr: usage };
42
- }
43
- const budget = 'budget' in extracted ? extracted.budget : undefined;
44
- const [projectionPath, ...paths] = extracted.rest;
45
- if (projectionPath === undefined ||
46
- paths.length === 0 ||
47
- extracted.rest.some((option) => option.startsWith('-'))) {
48
- return { exitCode: 2, stdout: '', stderr: usage };
49
- }
50
- try {
51
- const resolved = resolveCliWorkspaceSources(paths, cwd);
52
- if (!resolved.ok) {
53
- return {
54
- exitCode: 1,
55
- stdout: diagnosticJson(resolved.diagnostics),
56
- stderr: '',
57
- };
58
- }
59
- const loaded = loadProjection({
60
- path: projectionPath,
61
- source: readFileSync(resolve(cwd, projectionPath), 'utf8'),
62
- });
63
- if (!loaded.ok) {
64
- return {
65
- exitCode: 1,
66
- stdout: diagnosticJson(loaded.diagnostics),
67
- stderr: '',
68
- };
69
- }
70
- const compilation = compileWorkspaceWithProfileContext(resolved.paths.map((path) => ({
71
- path,
72
- source: readFileSync(resolve(cwd, path), 'utf8'),
73
- })));
74
- if (!compilation.ok) {
75
- return {
76
- exitCode: 1,
77
- stdout: diagnosticJson(compilation.diagnostics),
78
- stderr: '',
79
- };
80
- }
81
- const result = evaluateProjection(compilation.graph, loaded.projection, compilation.profileContext);
82
- return {
83
- exitCode: 0,
84
- stdout: output === 'json'
85
- ? budget === undefined
86
- ? `${JSON.stringify(result, null, 2)}\n`
87
- : renderBudgetedContext(result, budget)
88
- : renderProjectionMarkdown(result),
89
- stderr: '',
90
- };
91
- }
92
- catch (error) {
93
- const message = error instanceof Error ? error.message : String(error);
94
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
95
- }
96
- };
97
- const runAdHocContext = (options, cwd) => {
98
- const extracted = extractBudget(options);
99
- if (!extracted.ok) {
100
- return { exitCode: 2, stdout: '', stderr: usage };
101
- }
102
- const budget = 'budget' in extracted ? extracted.budget : undefined;
103
- const subjects = [];
104
- const paths = [];
105
- for (let index = 0; index < extracted.rest.length; index += 1) {
106
- const option = extracted.rest[index];
107
- if (option === '--subject') {
108
- const value = extracted.rest[index + 1];
109
- if (value === undefined || value.startsWith('-')) {
110
- return { exitCode: 2, stdout: '', stderr: usage };
111
- }
112
- subjects.push(value);
113
- index += 1;
114
- continue;
115
- }
116
- if (option === undefined || option.startsWith('-')) {
117
- return { exitCode: 2, stdout: '', stderr: usage };
118
- }
119
- paths.push(option);
120
- }
121
- if (subjects.length === 0 || paths.length === 0) {
122
- return { exitCode: 2, stdout: '', stderr: usage };
123
- }
124
- const unqualified = subjects.filter((subject) => !subject.includes('#'));
125
- if (unqualified.length > 0) {
126
- return {
127
- exitCode: 2,
128
- stdout: '',
129
- stderr: 'Ad-hoc context subjects must be globally qualified as ' +
130
- `"<document-id>#<local-id>": ${unqualified.join(', ')}\n`,
131
- };
132
- }
133
- try {
134
- const resolved = resolveCliWorkspaceSources(paths, cwd);
135
- if (!resolved.ok) {
136
- return {
137
- exitCode: 1,
138
- stdout: diagnosticJson(resolved.diagnostics),
139
- stderr: '',
140
- };
141
- }
142
- const compilation = compileWorkspaceWithProfileContext(resolved.paths.map((path) => ({
143
- path,
144
- source: readFileSync(resolve(cwd, path), 'utf8'),
145
- })));
146
- if (!compilation.ok) {
147
- return {
148
- exitCode: 1,
149
- stdout: diagnosticJson(compilation.diagnostics),
150
- stderr: '',
151
- };
152
- }
153
- const known = new Set(compilation.graph.subjects.map(({ id }) => id));
154
- const unknown = subjects.filter((subject) => !known.has(subject));
155
- if (unknown.length > 0) {
156
- return {
157
- exitCode: 1,
158
- stdout: '',
159
- stderr: `Unknown subject ${unknown.length === 1 ? 'identity' : 'identities'}: ` +
160
- `${unknown.join(', ')} (the compiled workspace declares ${known.size} subjects)\n`,
161
- };
162
- }
163
- const result = evaluateProjection(compilation.graph, {
164
- format: 'yarramate/projection/v1',
165
- id: 'ad-hoc-context',
166
- version: '0.0',
167
- query: { subjects, relationships: 'connected' },
168
- presentation: {
169
- title: 'Ad-hoc context',
170
- description: `Connected neighbourhood of ${subjects.join(', ')}`,
171
- },
172
- }, compilation.profileContext);
173
- return {
174
- exitCode: 0,
175
- stdout: budget === undefined
176
- ? `${JSON.stringify(result, null, 2)}\n`
177
- : renderBudgetedContext(result, budget),
178
- stderr: '',
179
- };
180
- }
181
- catch (error) {
182
- const message = error instanceof Error ? error.message : String(error);
183
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
184
- }
185
- };
186
- const runEvidence = (options, cwd) => {
187
- const [evidencePath, ...paths] = options;
188
- if (evidencePath === undefined ||
189
- paths.length === 0 ||
190
- options.some((option) => option.startsWith('-'))) {
191
- return { exitCode: 2, stdout: '', stderr: usage };
192
- }
193
- try {
194
- const resolved = resolveCliWorkspaceSources(paths, cwd);
195
- if (!resolved.ok) {
196
- return {
197
- exitCode: 1,
198
- stdout: diagnosticJson(resolved.diagnostics),
199
- stderr: '',
200
- };
201
- }
202
- const loaded = loadEvidence({
203
- path: evidencePath,
204
- source: readFileSync(resolve(cwd, evidencePath), 'utf8'),
205
- });
206
- if (!loaded.ok) {
207
- return {
208
- exitCode: 1,
209
- stdout: diagnosticJson(loaded.diagnostics),
210
- stderr: '',
211
- };
212
- }
213
- const compilation = compileWorkspace(resolved.paths.map((path) => ({
214
- path,
215
- source: readFileSync(resolve(cwd, path), 'utf8'),
216
- })));
217
- if (!compilation.ok) {
218
- return {
219
- exitCode: 1,
220
- stdout: diagnosticJson(compilation.diagnostics),
221
- stderr: '',
222
- };
223
- }
224
- const evaluation = evaluateEvidence(compilation.graph, loaded.evidence);
225
- return evaluation.ok
226
- ? {
227
- exitCode: 0,
228
- stdout: `${JSON.stringify(evaluation.report, null, 2)}\n`,
229
- stderr: '',
230
- }
231
- : {
232
- exitCode: 1,
233
- stdout: diagnosticJson(evaluation.diagnostics),
234
- stderr: '',
235
- };
236
- }
237
- catch (error) {
238
- const message = error instanceof Error ? error.message : String(error);
239
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
240
- }
241
- };
242
14
  const runReconciliation = (options, cwd) => {
243
15
  const [workspacePath] = options;
244
16
  if (options.length !== 1 ||
@@ -307,52 +79,6 @@ const runReconciliation = (options, cwd) => {
307
79
  return { exitCode: 2, stdout: '', stderr: `${message}\n` };
308
80
  }
309
81
  };
310
- const runStateComparison = (options, cwd) => {
311
- const [from, to, ...paths] = options;
312
- if (from === undefined ||
313
- to === undefined ||
314
- paths.length === 0 ||
315
- options.some((option) => option.startsWith('-'))) {
316
- return { exitCode: 2, stdout: '', stderr: usage };
317
- }
318
- try {
319
- const resolved = resolveCliWorkspaceSources(paths, cwd);
320
- if (!resolved.ok) {
321
- return {
322
- exitCode: 1,
323
- stdout: diagnosticJson(resolved.diagnostics),
324
- stderr: '',
325
- };
326
- }
327
- const compilation = compileWorkspace(resolved.paths.map((path) => ({
328
- path,
329
- source: readFileSync(resolve(cwd, path), 'utf8'),
330
- })));
331
- if (!compilation.ok) {
332
- return {
333
- exitCode: 1,
334
- stdout: diagnosticJson(compilation.diagnostics),
335
- stderr: '',
336
- };
337
- }
338
- const comparison = compareArchitectureStates(compilation.graph, from, to);
339
- return comparison.ok
340
- ? {
341
- exitCode: 0,
342
- stdout: `${JSON.stringify(comparison.comparison, null, 2)}\n`,
343
- stderr: '',
344
- }
345
- : {
346
- exitCode: 2,
347
- stdout: '',
348
- stderr: `${comparison.issues.map(({ message }) => message).join('\n')}\n`,
349
- };
350
- }
351
- catch (error) {
352
- const message = error instanceof Error ? error.message : String(error);
353
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
354
- }
355
- };
356
82
  const runInit = (options, cwd) => {
357
83
  const positional = options.filter((option) => option !== '--no-pointer');
358
84
  const writePointer = positional.length === options.length;
@@ -399,9 +125,9 @@ const runInit = (options, cwd) => {
399
125
  'YarraMate documents in `.yarramate/`. When prose documentation and the\n' +
400
126
  'model disagree, the model is authoritative.\n' +
401
127
  '\n' +
402
- '- Orient first: `yarramate status .yarramate/workspace.yaml --json`\n' +
128
+ '- Orient first: `yarramate ask .yarramate/workspace.yaml`\n' +
129
+ '- Continue the design interview: `yarramate design .yarramate/workspace.yaml`\n' +
403
130
  '- Validate changes: `yarramate check .yarramate/workspace.yaml --json`\n' +
404
- '- Bounded task context: `yarramate context <projection.yaml> .yarramate/workspace.yaml`\n' +
405
131
  '\n' +
406
132
  'Author native documents only; never edit generated output.\n';
407
133
  // Harnesses look in different files: AGENTS.md is the cross-harness
@@ -435,283 +161,9 @@ const runInit = (options, cwd) => {
435
161
  stderr: '',
436
162
  };
437
163
  };
438
- const parseFlags = (options) => {
439
- const [path, ...rest] = options;
440
- if (path === undefined || path.startsWith('-') || rest.length % 2 !== 0) {
441
- return undefined;
442
- }
443
- const flags = new Map();
444
- for (let index = 0; index < rest.length; index += 2) {
445
- const flag = rest[index];
446
- const value = rest[index + 1];
447
- if (flag === undefined ||
448
- value === undefined ||
449
- !flag.startsWith('--') ||
450
- value.startsWith('--')) {
451
- return undefined;
452
- }
453
- flags.set(flag, [...(flags.get(flag) ?? []), value]);
454
- }
455
- return { path, flags };
456
- };
457
- const oneFlag = (flags, flag) => {
458
- const values = flags.get(flag);
459
- return values?.length === 1 ? values[0] : undefined;
460
- };
461
- const hasRepeatedSingletonFlag = (flags) => [...flags.entries()].some(([flag, values]) => flag !== '--source' &&
462
- flag !== '--constraint' &&
463
- flag !== '--reference' &&
464
- flag !== '--present-in' &&
465
- values.length !== 1);
466
- const appendBlockItem = (document, collection, item) => {
467
- document.addIn([collection], item);
468
- const sequence = document.getIn([collection], true);
469
- if (isSeq(sequence)) {
470
- sequence.flow = false;
471
- }
472
- };
473
- const identifiedReferences = (values) => {
474
- const parsed = values.map((value) => {
475
- const separator = value.indexOf('=');
476
- return separator <= 0 || separator === value.length - 1
477
- ? undefined
478
- : {
479
- id: value.slice(0, separator),
480
- ref: value.slice(separator + 1),
481
- };
482
- });
483
- return parsed.some((reference) => reference === undefined)
484
- ? undefined
485
- : parsed;
486
- };
487
- const runAdd = (options, cwd) => {
488
- const parsed = parseFlags(options);
489
- if (parsed === undefined) {
490
- return { exitCode: 2, stdout: '', stderr: usage };
491
- }
492
- const allowed = new Set([
493
- '--id',
494
- '--kind',
495
- '--name',
496
- '--status',
497
- '--description',
498
- '--owner',
499
- '--constraint',
500
- '--reference',
501
- '--present-in',
502
- '--source',
503
- ]);
504
- if ([...parsed.flags.keys()].some((flag) => !allowed.has(flag)) ||
505
- hasRepeatedSingletonFlag(parsed.flags)) {
506
- return { exitCode: 2, stdout: '', stderr: usage };
507
- }
508
- const id = oneFlag(parsed.flags, '--id');
509
- const kind = oneFlag(parsed.flags, '--kind');
510
- const name = oneFlag(parsed.flags, '--name');
511
- if (id === undefined || kind === undefined || name === undefined) {
512
- return { exitCode: 2, stdout: '', stderr: usage };
513
- }
514
- const constraints = identifiedReferences(parsed.flags.get('--constraint') ?? []);
515
- const references = identifiedReferences(parsed.flags.get('--reference') ?? []);
516
- if (constraints === undefined || references === undefined) {
517
- return { exitCode: 2, stdout: '', stderr: usage };
518
- }
519
- try {
520
- const absolutePath = resolve(cwd, parsed.path);
521
- const document = parseDocument(readFileSync(absolutePath, 'utf8'));
522
- appendBlockItem(document, 'concepts', {
523
- id,
524
- kind,
525
- name,
526
- ...(oneFlag(parsed.flags, '--description') === undefined
527
- ? {}
528
- : { description: oneFlag(parsed.flags, '--description') }),
529
- ...(oneFlag(parsed.flags, '--status') === undefined
530
- ? {}
531
- : { status: oneFlag(parsed.flags, '--status') }),
532
- ...(oneFlag(parsed.flags, '--owner') === undefined
533
- ? {}
534
- : { owner: oneFlag(parsed.flags, '--owner') }),
535
- ...(constraints.length === 0 ? {} : { constraints }),
536
- ...(references.length === 0 ? {} : { references }),
537
- ...(parsed.flags.get('--present-in') === undefined
538
- ? {}
539
- : { presentIn: parsed.flags.get('--present-in') }),
540
- });
541
- const candidate = document.toString({ lineWidth: 0 });
542
- const companions = resolveCliWorkspaceSources(parsed.flags.get('--source') ?? [], cwd);
543
- if (!companions.ok) {
544
- return {
545
- exitCode: 1,
546
- stdout: humanDiagnostics(companions.diagnostics),
547
- stderr: '',
548
- };
549
- }
550
- const compilation = compileWorkspace([
551
- { path: parsed.path, source: candidate },
552
- ...companions.paths
553
- .filter((path) => resolve(cwd, path) !== resolve(cwd, parsed.path))
554
- .map((path) => ({
555
- path,
556
- source: readFileSync(resolve(cwd, path), 'utf8'),
557
- })),
558
- ]);
559
- if (!compilation.ok) {
560
- return {
561
- exitCode: 1,
562
- stdout: humanDiagnostics(compilation.diagnostics),
563
- stderr: '',
564
- };
565
- }
566
- writeFileSync(absolutePath, candidate, 'utf8');
567
- return {
568
- exitCode: 0,
569
- stdout: `Added concept "${id}" to ${parsed.path}\n`,
570
- stderr: '',
571
- };
572
- }
573
- catch (error) {
574
- const message = error instanceof Error ? error.message : String(error);
575
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
576
- }
577
- };
578
- const runConnect = (options, cwd) => {
579
- const parsed = parseFlags(options);
580
- if (parsed === undefined) {
581
- return { exitCode: 2, stdout: '', stderr: usage };
582
- }
583
- const allowed = new Set([
584
- '--id',
585
- '--kind',
586
- '--from',
587
- '--to',
588
- '--name',
589
- '--description',
590
- '--status',
591
- '--mode',
592
- '--content',
593
- '--reference',
594
- '--present-in',
595
- '--source',
596
- ]);
597
- if ([...parsed.flags.keys()].some((flag) => !allowed.has(flag)) ||
598
- hasRepeatedSingletonFlag(parsed.flags)) {
599
- return { exitCode: 2, stdout: '', stderr: usage };
600
- }
601
- const id = oneFlag(parsed.flags, '--id');
602
- const kind = oneFlag(parsed.flags, '--kind');
603
- const from = oneFlag(parsed.flags, '--from');
604
- const to = oneFlag(parsed.flags, '--to');
605
- if (id === undefined ||
606
- kind === undefined ||
607
- from === undefined ||
608
- to === undefined) {
609
- return { exitCode: 2, stdout: '', stderr: usage };
610
- }
611
- const references = identifiedReferences(parsed.flags.get('--reference') ?? []);
612
- if (references === undefined) {
613
- return { exitCode: 2, stdout: '', stderr: usage };
614
- }
615
- try {
616
- const absolutePath = resolve(cwd, parsed.path);
617
- const document = parseDocument(readFileSync(absolutePath, 'utf8'));
618
- appendBlockItem(document, 'relationships', {
619
- id,
620
- kind,
621
- from,
622
- to,
623
- ...(oneFlag(parsed.flags, '--name') === undefined
624
- ? {}
625
- : { name: oneFlag(parsed.flags, '--name') }),
626
- ...(oneFlag(parsed.flags, '--description') === undefined
627
- ? {}
628
- : { description: oneFlag(parsed.flags, '--description') }),
629
- ...(oneFlag(parsed.flags, '--status') === undefined
630
- ? {}
631
- : { status: oneFlag(parsed.flags, '--status') }),
632
- ...(oneFlag(parsed.flags, '--mode') === undefined
633
- ? {}
634
- : { mode: oneFlag(parsed.flags, '--mode') }),
635
- ...(oneFlag(parsed.flags, '--content') === undefined
636
- ? {}
637
- : { content: oneFlag(parsed.flags, '--content') }),
638
- ...(references.length === 0 ? {} : { references }),
639
- ...(parsed.flags.get('--present-in') === undefined
640
- ? {}
641
- : { presentIn: parsed.flags.get('--present-in') }),
642
- });
643
- const candidate = document.toString({ lineWidth: 0 });
644
- const companions = resolveCliWorkspaceSources(parsed.flags.get('--source') ?? [], cwd);
645
- if (!companions.ok) {
646
- return {
647
- exitCode: 1,
648
- stdout: humanDiagnostics(companions.diagnostics),
649
- stderr: '',
650
- };
651
- }
652
- const compilation = compileWorkspace([
653
- { path: parsed.path, source: candidate },
654
- ...companions.paths
655
- .filter((path) => resolve(cwd, path) !== resolve(cwd, parsed.path))
656
- .map((path) => ({
657
- path,
658
- source: readFileSync(resolve(cwd, path), 'utf8'),
659
- })),
660
- ]);
661
- if (!compilation.ok) {
662
- return {
663
- exitCode: 1,
664
- stdout: humanDiagnostics(compilation.diagnostics),
665
- stderr: '',
666
- };
667
- }
668
- writeFileSync(absolutePath, candidate, 'utf8');
669
- return {
670
- exitCode: 0,
671
- stdout: `Added relationship "${id}" to ${parsed.path}\n`,
672
- stderr: '',
673
- };
674
- }
675
- catch (error) {
676
- const message = error instanceof Error ? error.message : String(error);
677
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
678
- }
679
- };
680
- const runCompile = (options, cwd) => {
681
- if (options.length === 0 ||
682
- options.some((option) => option.startsWith('-'))) {
683
- return { exitCode: 2, stdout: '', stderr: usage };
684
- }
685
- try {
686
- const resolved = resolveCliWorkspaceSources(options, cwd);
687
- if (!resolved.ok) {
688
- return {
689
- exitCode: 1,
690
- stdout: humanDiagnostics(resolved.diagnostics),
691
- stderr: '',
692
- };
693
- }
694
- const result = compileWorkspace(resolved.paths.map((path) => ({
695
- path,
696
- source: readFileSync(resolve(cwd, path), 'utf8'),
697
- })));
698
- return result.ok
699
- ? {
700
- exitCode: 0,
701
- stdout: serializeSemanticGraph(result.graph),
702
- stderr: '',
703
- }
704
- : {
705
- exitCode: 1,
706
- stdout: humanDiagnostics(result.diagnostics),
707
- stderr: '',
708
- };
709
- }
710
- catch (error) {
711
- const message = error instanceof Error ? error.message : String(error);
712
- return { exitCode: 2, stdout: '', stderr: `${message}\n` };
713
- }
714
- };
164
+ // The seven-verb contract (docs/AGENT-INTERFACE.md): one verb per
165
+ // lifecycle stage — init creates, design fills, apply writes, ask reads,
166
+ // check gates, reconcile reports drift, export derives artifacts.
715
167
  export function runCli(args, cwd = process.cwd()) {
716
168
  const [command, ...options] = args;
717
169
  if (command === '--help' || command === '-h' || command === 'help') {
@@ -723,43 +175,23 @@ export function runCli(args, cwd = process.cwd()) {
723
175
  if (command === 'init') {
724
176
  return runInit(options, cwd);
725
177
  }
726
- if (command === 'add') {
727
- return runAdd(options, cwd);
728
- }
729
- if (command === 'connect') {
730
- return runConnect(options, cwd);
731
- }
732
- if (command === 'compile') {
733
- return runCompile(options, cwd);
734
- }
735
- if (command === 'context') {
736
- return options.includes('--subject')
737
- ? runAdHocContext(options, cwd)
738
- : runProjection(options, cwd, 'json');
178
+ if (command === 'design') {
179
+ return runDesignCommand(options, cwd);
739
180
  }
740
- if (command === 'view') {
741
- return runProjection(options, cwd, 'markdown');
181
+ if (command === 'apply') {
182
+ return runApplyCommand(options, cwd);
742
183
  }
743
- if (command === 'compare') {
744
- return runStateComparison(options, cwd);
745
- }
746
- if (command === 'evidence') {
747
- return runEvidence(options, cwd);
748
- }
749
- if (command === 'reconcile') {
750
- return runReconciliation(options, cwd);
184
+ if (command === 'ask') {
185
+ return runAskCommand(options, cwd);
751
186
  }
752
187
  if (command === 'check') {
753
188
  return runCheckCommand(options, cwd);
754
189
  }
755
- if (command === 'status') {
756
- return runStatusCommand(options, cwd);
757
- }
758
- if (command === 'new') {
759
- return runNewCommand(options, cwd);
190
+ if (command === 'reconcile') {
191
+ return runReconciliation(options, cwd);
760
192
  }
761
- if (command === 'next') {
762
- return runNextCommand(options, cwd);
193
+ if (command === 'export') {
194
+ return runExportCommand(options, cwd);
763
195
  }
764
196
  return { exitCode: 2, stdout: '', stderr: usage };
765
197
  }
package/dist/compiler.js CHANGED
@@ -911,6 +911,19 @@ function compileWorkspaceResolved(sources) {
911
911
  source: location(['concepts', index, 'references', referenceIndex, 'ref'], `/concepts/${index}/references/${referenceIndex}/ref`),
912
912
  });
913
913
  }
914
+ // An attestation is a recorded judgment, not content the engine
915
+ // evaluates: the claim's existence is what triggers can see, and
916
+ // revocation is deletion, reviewed at the Git boundary.
917
+ for (const [attestationIndex, attestation] of (concept.attestations ?? []).entries()) {
918
+ claims.push({
919
+ id: `${subject}~attestation-${attestation.topic}`,
920
+ subject,
921
+ predicate: `yarramate/attestation/${attestation.topic}`,
922
+ object: { value: `${attestation.by} ${attestation.on}` },
923
+ origin: 'declared',
924
+ source: location(['concepts', index, 'attestations', attestationIndex, 'topic'], `/concepts/${index}/attestations/${attestationIndex}/topic`),
925
+ });
926
+ }
914
927
  for (const [stateIndex, state] of (concept.presentIn ?? []).entries()) {
915
928
  const stateIdentity = qualifyReference(value.id, state);
916
929
  claims.push({
@@ -5,7 +5,7 @@ export interface CoreContractFormat {
5
5
  readonly packageExport: string;
6
6
  }
7
7
  export interface CoreContractCommand {
8
- readonly name: 'init' | 'add' | 'connect' | 'check' | 'compile' | 'view' | 'context' | 'compare' | 'evidence';
8
+ readonly name: 'init' | 'design' | 'apply' | 'ask' | 'check' | 'reconcile' | 'export';
9
9
  readonly binary: 'yarramate';
10
10
  readonly machineFormat?: string;
11
11
  }
@@ -1,2 +1,2 @@
1
1
  import { type CliResult } from './cli-support.js';
2
- export declare function runStatusCommand(options: readonly string[], cwd: string): CliResult;
2
+ export declare function runDesignCommand(options: readonly string[], cwd: string): CliResult;