yarramate 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/adapters/likec4-cli.js +3 -0
- package/dist/adapters/likec4-project.d.ts +2 -0
- package/dist/adapters/likec4-project.js +21 -9
- package/dist/ask-command.js +102 -2
- package/dist/cli-support.d.ts +1 -1
- package/dist/cli-support.js +1 -1
- package/package.json +1 -1
- package/schema/yarramate-ask-result.schema.json +115 -1
- package/schema/yarramate-likec4-project.schema.json +5 -0
- package/skills/yarramate-architecture/SKILL.md +4 -1
package/README.md
CHANGED
|
@@ -17,6 +17,20 @@ whose gaps are found deterministically.
|
|
|
17
17
|
> YarraMate is pre-release software. Interfaces may evolve before the first
|
|
18
18
|
> stable release.
|
|
19
19
|
|
|
20
|
+
## Proven across harnesses
|
|
21
|
+
|
|
22
|
+
The design bet is that the model — not the session — is the state, so any
|
|
23
|
+
agent in any harness can resume the work cold. We tested that adversarially
|
|
24
|
+
on a real product: a Claude Code session worked the design interview all
|
|
25
|
+
day, then an OpenAI Codex session — no shared context, the tool never
|
|
26
|
+
named — resumed it from a ten-line pointer file and the published CLI. It
|
|
27
|
+
answered 63 open design questions, filed two genuine defect reports, and in
|
|
28
|
+
a later session reported that the model "was not merely documentation" — it
|
|
29
|
+
caught an approval-path regression before the release shipped.
|
|
30
|
+
|
|
31
|
+
The full story, with every commit, PR, and release attached:
|
|
32
|
+
[The model is the handover](docs/CASE-STUDY-CROSS-HARNESS.md).
|
|
33
|
+
|
|
20
34
|
## Why YarraMate?
|
|
21
35
|
|
|
22
36
|
Architecture documents often drift away from implementation or become tied to
|
|
@@ -134,6 +148,7 @@ node dist/cli.js ask .yarramate/workspace.yaml
|
|
|
134
148
|
node dist/cli.js ask .yarramate/workspace.yaml "free text about the model"
|
|
135
149
|
node dist/cli.js ask .yarramate/workspace.yaml --subjects
|
|
136
150
|
node dist/cli.js ask .yarramate/workspace.yaml --advise "a design question"
|
|
151
|
+
node dist/cli.js ask .yarramate/workspace.yaml --where "compiler"
|
|
137
152
|
node dist/cli.js check .yarramate/workspace.yaml --json
|
|
138
153
|
node dist/cli.js reconcile .yarramate/workspace.yaml
|
|
139
154
|
node dist/cli.js export graph .yarramate/workspace.yaml
|
|
@@ -712,6 +712,9 @@ export function runLikeC4Cli(args, cwd = process.cwd()) {
|
|
|
712
712
|
? [
|
|
713
713
|
{
|
|
714
714
|
...(view.id === undefined ? {} : { id: view.id }),
|
|
715
|
+
...(view.folder === undefined
|
|
716
|
+
? {}
|
|
717
|
+
: { folder: view.folder }),
|
|
715
718
|
prepared,
|
|
716
719
|
...(view.compare === undefined
|
|
717
720
|
? {}
|
|
@@ -11,6 +11,7 @@ export interface LikeC4ProjectDefinition {
|
|
|
11
11
|
readonly views: ReadonlyArray<{
|
|
12
12
|
readonly id?: string;
|
|
13
13
|
readonly projection: string;
|
|
14
|
+
readonly folder?: string;
|
|
14
15
|
readonly compare?: {
|
|
15
16
|
readonly from: string;
|
|
16
17
|
readonly to: string;
|
|
@@ -40,6 +41,7 @@ export interface LikeC4Deployment {
|
|
|
40
41
|
export declare const loadLikeC4ProjectDefinition: (source: WorkspaceSource) => import("../source-document.js").SourceDocumentResult<LikeC4ProjectDefinition>;
|
|
41
42
|
export interface PreparedLikeC4ProjectView {
|
|
42
43
|
readonly id?: string;
|
|
44
|
+
readonly folder?: string;
|
|
43
45
|
readonly prepared: Extract<LikeC4PreparationResult, {
|
|
44
46
|
readonly ok: true;
|
|
45
47
|
}>;
|
|
@@ -8,6 +8,15 @@ const Ajv2020 = Ajv2020Module.default;
|
|
|
8
8
|
const validateLikeC4Project = new Ajv2020({ allErrors: true }).compile(likeC4ProjectSchema);
|
|
9
9
|
export const loadLikeC4ProjectDefinition = (source) => loadSourceDocument(source, validateLikeC4Project, 'LikeC4 project');
|
|
10
10
|
const quote = (value) => `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'").replaceAll('\n', '\\n')}'`;
|
|
11
|
+
// A folder files the view in LikeC4's sidebar tree: the title becomes a
|
|
12
|
+
// path ('Folder / Title') whose last segment is the displayed title (ADR
|
|
13
|
+
// 0067). A view without a declared title still needs a title line to
|
|
14
|
+
// carry the path, so the view id stands in as the leaf.
|
|
15
|
+
const titleLines = (folder, title, viewId) => folder === undefined
|
|
16
|
+
? title === undefined
|
|
17
|
+
? []
|
|
18
|
+
: [` title ${quote(title)}`]
|
|
19
|
+
: [` title ${quote(`${folder} / ${title ?? viewId}`)}`];
|
|
11
20
|
const unionProjection = (project, views) => ({
|
|
12
21
|
format: 'yarramate/projection-result/v1',
|
|
13
22
|
projection: `${project.id}@${project.version}`,
|
|
@@ -28,7 +37,7 @@ const unionProjection = (project, views) => ({
|
|
|
28
37
|
...new Map(views.flatMap(({ prepared }) => prepared.projection.claims.map((claim) => [claim.id, claim]))).values(),
|
|
29
38
|
].sort((left, right) => left.id.localeCompare(right.id)),
|
|
30
39
|
});
|
|
31
|
-
const viewBody = ({ id, prepared, dynamic, deployment, }, gitChange) => {
|
|
40
|
+
const viewBody = ({ id, folder, prepared, dynamic, deployment, }, gitChange) => {
|
|
32
41
|
const source = prepared.source;
|
|
33
42
|
const startToken = '\nviews {\n';
|
|
34
43
|
const start = source.indexOf(startToken);
|
|
@@ -58,9 +67,7 @@ const viewBody = ({ id, prepared, dynamic, deployment, }, gitChange) => {
|
|
|
58
67
|
const viewId = id ?? prepared.projection.projection.split('@')[0];
|
|
59
68
|
return [
|
|
60
69
|
` deployment view ${viewId} {`,
|
|
61
|
-
...(prepared.projection.presentation?.title
|
|
62
|
-
? []
|
|
63
|
-
: [` title ${quote(prepared.projection.presentation.title)}`]),
|
|
70
|
+
...titleLines(folder, prepared.projection.presentation?.title, viewId),
|
|
64
71
|
...(prepared.projection.presentation?.description === undefined
|
|
65
72
|
? []
|
|
66
73
|
: [
|
|
@@ -105,9 +112,7 @@ const viewBody = ({ id, prepared, dynamic, deployment, }, gitChange) => {
|
|
|
105
112
|
const viewId = id ?? prepared.projection.projection.split('@')[0];
|
|
106
113
|
return [
|
|
107
114
|
` dynamic view ${viewId} {`,
|
|
108
|
-
...(prepared.projection.presentation?.title
|
|
109
|
-
? []
|
|
110
|
-
: [` title ${quote(prepared.projection.presentation.title)}`]),
|
|
115
|
+
...titleLines(folder, prepared.projection.presentation?.title, viewId),
|
|
111
116
|
...(prepared.projection.presentation?.description === undefined
|
|
112
117
|
? []
|
|
113
118
|
: [
|
|
@@ -140,10 +145,17 @@ const viewBody = ({ id, prepared, dynamic, deployment, }, gitChange) => {
|
|
|
140
145
|
...relationshipRules,
|
|
141
146
|
...overlayRules,
|
|
142
147
|
].join('\n');
|
|
143
|
-
|
|
148
|
+
const viewId = id ?? prepared.projection.projection.split('@')[0];
|
|
149
|
+
const body = source
|
|
144
150
|
.slice(start + startToken.length, end)
|
|
145
|
-
.replace(/^ view [A-Za-z_][A-Za-z0-9_-]* \{/, ` view ${
|
|
151
|
+
.replace(/^ view [A-Za-z_][A-Za-z0-9_-]* \{/, ` view ${viewId} {`)
|
|
146
152
|
.replace(' include *', membershipRules);
|
|
153
|
+
if (folder === undefined)
|
|
154
|
+
return body;
|
|
155
|
+
const title = prepared.projection.presentation?.title;
|
|
156
|
+
return title === undefined
|
|
157
|
+
? body.replace(` view ${viewId} {`, ` view ${viewId} {\n${titleLines(folder, undefined, viewId).join('\n')}`)
|
|
158
|
+
: body.replace(` title ${quote(title)}`, titleLines(folder, title, viewId).join('\n'));
|
|
147
159
|
};
|
|
148
160
|
const deploymentBody = ({ deployment, prepared, }) => {
|
|
149
161
|
if (deployment === undefined)
|
package/dist/ask-command.js
CHANGED
|
@@ -8,7 +8,7 @@ import { deriveChangedSubjects } from './changed.js';
|
|
|
8
8
|
import { runCheckCommand } from './check-command.js';
|
|
9
9
|
import { diagnosticJson, humanDiagnostics, usage, } from './cli-support.js';
|
|
10
10
|
import { compileWorkspaceWithProfileContext, } from './compiler.js';
|
|
11
|
-
import { evaluateEvidenceWorkspace, loadEvidence } from './evidence.js';
|
|
11
|
+
import { evaluateEvidenceWorkspace, loadEvidence, } from './evidence.js';
|
|
12
12
|
import { evaluateCatalogue, loadQuestionCatalogue, renderInterrogationReport, } from './interrogate-command.js';
|
|
13
13
|
import { buildNextSubjects, coverageClause, } from './next-command.js';
|
|
14
14
|
import { conceptKinds, relationshipPolicies, } from './profile.js';
|
|
@@ -124,6 +124,7 @@ export function runAskCommand(options, cwd) {
|
|
|
124
124
|
let open = false;
|
|
125
125
|
let kinds = false;
|
|
126
126
|
let advise = false;
|
|
127
|
+
let where = false;
|
|
127
128
|
let compare;
|
|
128
129
|
let changed;
|
|
129
130
|
let budget;
|
|
@@ -157,6 +158,10 @@ export function runAskCommand(options, cwd) {
|
|
|
157
158
|
advise = true;
|
|
158
159
|
continue;
|
|
159
160
|
}
|
|
161
|
+
if (option === '--where') {
|
|
162
|
+
where = true;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
160
165
|
if (option === '--compare') {
|
|
161
166
|
const from = options[index + 1];
|
|
162
167
|
const to = options[index + 2];
|
|
@@ -231,6 +236,12 @@ export function runAskCommand(options, cwd) {
|
|
|
231
236
|
exclusiveModes > 1 ||
|
|
232
237
|
(advise && exclusiveModes > 0) ||
|
|
233
238
|
(advise && query.length === 0) ||
|
|
239
|
+
(where &&
|
|
240
|
+
(exclusiveModes > 0 ||
|
|
241
|
+
advise ||
|
|
242
|
+
changed !== undefined ||
|
|
243
|
+
budget !== undefined ||
|
|
244
|
+
query.length === 0)) ||
|
|
234
245
|
(query.length > 0 && exclusiveModes > 0) ||
|
|
235
246
|
(changed !== undefined &&
|
|
236
247
|
(query.length > 0 || exclusiveModes > 0 || advise)) ||
|
|
@@ -638,7 +649,10 @@ export function runAskCommand(options, cwd) {
|
|
|
638
649
|
// names a projection file is precise addressing; anything else runs
|
|
639
650
|
// through free-text seeding, where exact subject ids win.
|
|
640
651
|
const soleTerm = query.length === 1 ? query[0] : undefined;
|
|
641
|
-
const projectionCandidate = soleTerm !== undefined &&
|
|
652
|
+
const projectionCandidate = soleTerm !== undefined &&
|
|
653
|
+
!advise &&
|
|
654
|
+
!where &&
|
|
655
|
+
existsSync(resolve(cwd, soleTerm))
|
|
642
656
|
? resolve(cwd, soleTerm)
|
|
643
657
|
: undefined;
|
|
644
658
|
if (projectionCandidate !== undefined &&
|
|
@@ -672,6 +686,92 @@ export function runAskCommand(options, cwd) {
|
|
|
672
686
|
`List the roster: yarramate ask ${workspacePath} --subjects\n`,
|
|
673
687
|
};
|
|
674
688
|
}
|
|
689
|
+
// --where: evidence-backed pointing (ADR 0068). Verified locations for
|
|
690
|
+
// the matched subjects, an explicit list of matched-but-unobserved
|
|
691
|
+
// subjects, and a hand-off note for everything outside the model —
|
|
692
|
+
// authority follows epistemic status, so the routing is stated in the
|
|
693
|
+
// output rather than assumed by the reader.
|
|
694
|
+
if (where) {
|
|
695
|
+
const evidenceDocuments = [];
|
|
696
|
+
for (const path of workspace.evidence) {
|
|
697
|
+
const loaded = loadEvidence({
|
|
698
|
+
path,
|
|
699
|
+
source: readFileSync(resolve(cwd, path), 'utf8'),
|
|
700
|
+
});
|
|
701
|
+
if (!loaded.ok)
|
|
702
|
+
return failed(loaded.diagnostics);
|
|
703
|
+
evidenceDocuments.push(loaded.evidence);
|
|
704
|
+
}
|
|
705
|
+
const subjectOf = (observation) => 'subject' in observation
|
|
706
|
+
? observation.subject
|
|
707
|
+
: (observation.claim.split('~')[0] ?? observation.claim);
|
|
708
|
+
// Subject- and claim-level observations often share a locator; the
|
|
709
|
+
// pointer is the same either way, so identical entries collapse.
|
|
710
|
+
const entriesBySeed = resolution.seeds.map((seed) => ({
|
|
711
|
+
subject: seed,
|
|
712
|
+
observations: [
|
|
713
|
+
...new Map(evidenceDocuments
|
|
714
|
+
.flatMap((document) => document.observations
|
|
715
|
+
.filter((observation) => subjectOf(observation) === seed)
|
|
716
|
+
.map((observation) => ({
|
|
717
|
+
uri: observation.evidence.uri,
|
|
718
|
+
result: observation.result,
|
|
719
|
+
provider: document.provider,
|
|
720
|
+
...(observation.evidence.message === undefined
|
|
721
|
+
? {}
|
|
722
|
+
: { message: observation.evidence.message }),
|
|
723
|
+
})))
|
|
724
|
+
.map((entry) => [
|
|
725
|
+
`${entry.uri}${entry.result}${entry.provider}${entry.message ?? ''}`,
|
|
726
|
+
entry,
|
|
727
|
+
])).values(),
|
|
728
|
+
].sort((left, right) => left.uri.localeCompare(right.uri) ||
|
|
729
|
+
left.result.localeCompare(right.result)),
|
|
730
|
+
}));
|
|
731
|
+
const located = entriesBySeed.filter(({ observations }) => observations.length > 0);
|
|
732
|
+
const unobserved = entriesBySeed
|
|
733
|
+
.filter(({ observations }) => observations.length === 0)
|
|
734
|
+
.map(({ subject }) => subject);
|
|
735
|
+
const note = workspace.evidence.length === 0
|
|
736
|
+
? 'This workspace declares no evidence overlay, so no location is verified. For code locations, use your search tools; author evidence observations to make locations verifiable.'
|
|
737
|
+
: 'Locations above are verified by evidence overlays. Subjects listed as unobserved are modeled but unlocated. For code outside the model, use your search tools or a code index.';
|
|
738
|
+
const result = {
|
|
739
|
+
format: 'yarramate/ask-result/v1',
|
|
740
|
+
workspace: workspace.id,
|
|
741
|
+
mode: 'where',
|
|
742
|
+
addressing: resolution.addressing,
|
|
743
|
+
topic,
|
|
744
|
+
seeds: resolution.seeds,
|
|
745
|
+
matched: resolution.matched,
|
|
746
|
+
located,
|
|
747
|
+
coverage: { unobserved, note },
|
|
748
|
+
};
|
|
749
|
+
const lines = [
|
|
750
|
+
`Where: "${topic}" — ${plural(resolution.matched, 'concept')} matched` +
|
|
751
|
+
(resolution.matched > resolution.seeds.length
|
|
752
|
+
? `, seeded from the top ${resolution.seeds.length}`
|
|
753
|
+
: '') +
|
|
754
|
+
`: ${resolution.seeds.join(', ')}`,
|
|
755
|
+
'',
|
|
756
|
+
];
|
|
757
|
+
for (const entry of located) {
|
|
758
|
+
lines.push(` ${entry.subject}`);
|
|
759
|
+
for (const observation of entry.observations) {
|
|
760
|
+
lines.push(` ${observation.result} ${observation.uri} (${observation.provider})`);
|
|
761
|
+
if (observation.message !== undefined) {
|
|
762
|
+
lines.push(` ${observation.message}`);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if (located.length === 0) {
|
|
767
|
+
lines.push(' no verified locations');
|
|
768
|
+
}
|
|
769
|
+
if (unobserved.length > 0) {
|
|
770
|
+
lines.push('', ` unobserved — modeled, no evidence: ${unobserved.join(', ')}`);
|
|
771
|
+
}
|
|
772
|
+
lines.push('', note);
|
|
773
|
+
return emit(result, `${lines.join('\n')}\n`);
|
|
774
|
+
}
|
|
675
775
|
const evaluated = sliceProjection(graph, resolution.seeds, topic, compilation.profileContext);
|
|
676
776
|
if (!advise) {
|
|
677
777
|
const result = {
|
package/dist/cli-support.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface CliResult {
|
|
|
7
7
|
export declare const isMainModule: (moduleUrl: string, entrypoint: string | undefined) => boolean;
|
|
8
8
|
export declare const packageVersion: string;
|
|
9
9
|
export declare const versionResult: (binary: string) => CliResult;
|
|
10
|
-
export declare const usage = "Usage:\n yarramate init <directory> [--no-pointer]\n yarramate design <workspace.yaml> [--subject <document-id>#<local-id>] [--catalogue <catalogue.yaml>] [--json]\n yarramate apply <operations.yaml> <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> \"<free text>\" | <document-id>#<local-id> ... | <projection.yaml> [--budget <tokens>] [--json]\n yarramate ask <workspace.yaml> --subjects [--kind <term>] [--status <status>] [--json]\n yarramate ask <workspace.yaml> --kinds [--json]\n yarramate ask <workspace.yaml> --advise \"<topic>\" [--budget <tokens>] [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --next [--json]\n yarramate ask <workspace.yaml> --open [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --compare <from-state> <to-state> [--json]\n yarramate ask <workspace.yaml> --changed <git-range> [--budget <tokens>] [--json]\n yarramate check <source.yaml> [source.yaml ...] [--json] [--strict]\n yarramate reconcile <workspace.yaml>\n yarramate export graph <workspace.yaml> [--out <file>]\n yarramate export markdown <projection.yaml> <workspace.yaml> [--out <file>]\n yarramate export markdown --changed <git-range> <workspace.yaml> [--out <file>]\n yarramate export briefs <projection.yaml> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export briefs --changed <git-range> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export likec4 <likec4-project.yaml> <output-dir> <workspace.yaml> [--changed <git-range>]\n";
|
|
10
|
+
export declare const usage = "Usage:\n yarramate init <directory> [--no-pointer]\n yarramate design <workspace.yaml> [--subject <document-id>#<local-id>] [--catalogue <catalogue.yaml>] [--json]\n yarramate apply <operations.yaml> <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> \"<free text>\" | <document-id>#<local-id> ... | <projection.yaml> [--budget <tokens>] [--json]\n yarramate ask <workspace.yaml> --subjects [--kind <term>] [--status <status>] [--json]\n yarramate ask <workspace.yaml> --kinds [--json]\n yarramate ask <workspace.yaml> --advise \"<topic>\" [--budget <tokens>] [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --where \"<free text>\" | <document-id>#<local-id> ... [--json]\n yarramate ask <workspace.yaml> --next [--json]\n yarramate ask <workspace.yaml> --open [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --compare <from-state> <to-state> [--json]\n yarramate ask <workspace.yaml> --changed <git-range> [--budget <tokens>] [--json]\n yarramate check <source.yaml> [source.yaml ...] [--json] [--strict]\n yarramate reconcile <workspace.yaml>\n yarramate export graph <workspace.yaml> [--out <file>]\n yarramate export markdown <projection.yaml> <workspace.yaml> [--out <file>]\n yarramate export markdown --changed <git-range> <workspace.yaml> [--out <file>]\n yarramate export briefs <projection.yaml> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export briefs --changed <git-range> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export likec4 <likec4-project.yaml> <output-dir> <workspace.yaml> [--changed <git-range>]\n";
|
|
11
11
|
export declare const diagnosticJson: (diagnostics: unknown) => string;
|
|
12
12
|
export declare const checkResultJson: (ok: boolean, diagnostics: unknown, counted?: {
|
|
13
13
|
readonly documents: number;
|
package/dist/cli-support.js
CHANGED
|
@@ -23,7 +23,7 @@ export const versionResult = (binary) => ({
|
|
|
23
23
|
stdout: `${binary} ${packageVersion}\n`,
|
|
24
24
|
stderr: '',
|
|
25
25
|
});
|
|
26
|
-
export const usage = 'Usage:\n yarramate init <directory> [--no-pointer]\n yarramate design <workspace.yaml> [--subject <document-id>#<local-id>] [--catalogue <catalogue.yaml>] [--json]\n yarramate apply <operations.yaml> <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> "<free text>" | <document-id>#<local-id> ... | <projection.yaml> [--budget <tokens>] [--json]\n yarramate ask <workspace.yaml> --subjects [--kind <term>] [--status <status>] [--json]\n yarramate ask <workspace.yaml> --kinds [--json]\n yarramate ask <workspace.yaml> --advise "<topic>" [--budget <tokens>] [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --next [--json]\n yarramate ask <workspace.yaml> --open [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --compare <from-state> <to-state> [--json]\n yarramate ask <workspace.yaml> --changed <git-range> [--budget <tokens>] [--json]\n yarramate check <source.yaml> [source.yaml ...] [--json] [--strict]\n yarramate reconcile <workspace.yaml>\n yarramate export graph <workspace.yaml> [--out <file>]\n yarramate export markdown <projection.yaml> <workspace.yaml> [--out <file>]\n yarramate export markdown --changed <git-range> <workspace.yaml> [--out <file>]\n yarramate export briefs <projection.yaml> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export briefs --changed <git-range> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export likec4 <likec4-project.yaml> <output-dir> <workspace.yaml> [--changed <git-range>]\n';
|
|
26
|
+
export const usage = 'Usage:\n yarramate init <directory> [--no-pointer]\n yarramate design <workspace.yaml> [--subject <document-id>#<local-id>] [--catalogue <catalogue.yaml>] [--json]\n yarramate apply <operations.yaml> <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> [--json]\n yarramate ask <workspace.yaml> "<free text>" | <document-id>#<local-id> ... | <projection.yaml> [--budget <tokens>] [--json]\n yarramate ask <workspace.yaml> --subjects [--kind <term>] [--status <status>] [--json]\n yarramate ask <workspace.yaml> --kinds [--json]\n yarramate ask <workspace.yaml> --advise "<topic>" [--budget <tokens>] [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --where "<free text>" | <document-id>#<local-id> ... [--json]\n yarramate ask <workspace.yaml> --next [--json]\n yarramate ask <workspace.yaml> --open [--catalogue <catalogue.yaml>] [--json]\n yarramate ask <workspace.yaml> --compare <from-state> <to-state> [--json]\n yarramate ask <workspace.yaml> --changed <git-range> [--budget <tokens>] [--json]\n yarramate check <source.yaml> [source.yaml ...] [--json] [--strict]\n yarramate reconcile <workspace.yaml>\n yarramate export graph <workspace.yaml> [--out <file>]\n yarramate export markdown <projection.yaml> <workspace.yaml> [--out <file>]\n yarramate export markdown --changed <git-range> <workspace.yaml> [--out <file>]\n yarramate export briefs <projection.yaml> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export briefs --changed <git-range> <workspace.yaml> --out <directory> [--budget <tokens>]\n yarramate export likec4 <likec4-project.yaml> <output-dir> <workspace.yaml> [--changed <git-range>]\n';
|
|
27
27
|
export const diagnosticJson = (diagnostics) => `${JSON.stringify({
|
|
28
28
|
format: 'yarramate/diagnostic-result/v1',
|
|
29
29
|
diagnostics,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://yarrasys.dev/schema/yarramate-ask-result.schema.json",
|
|
4
4
|
"title": "YarraMate ask result",
|
|
5
|
-
"description": "One envelope for every consumed-now read: orientation, roster, slice, advice, next, open questions, and state comparison, discriminated by mode.",
|
|
5
|
+
"description": "One envelope for every consumed-now read: orientation, roster, slice, advice, verified locations, next, open questions, and state comparison, discriminated by mode.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"format",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"roster",
|
|
24
24
|
"slice",
|
|
25
25
|
"advice",
|
|
26
|
+
"where",
|
|
26
27
|
"next",
|
|
27
28
|
"open",
|
|
28
29
|
"compare",
|
|
@@ -363,6 +364,119 @@
|
|
|
363
364
|
},
|
|
364
365
|
"additionalProperties": false
|
|
365
366
|
},
|
|
367
|
+
{
|
|
368
|
+
"type": "object",
|
|
369
|
+
"required": [
|
|
370
|
+
"mode",
|
|
371
|
+
"addressing",
|
|
372
|
+
"topic",
|
|
373
|
+
"seeds",
|
|
374
|
+
"matched",
|
|
375
|
+
"located",
|
|
376
|
+
"coverage"
|
|
377
|
+
],
|
|
378
|
+
"properties": {
|
|
379
|
+
"format": true,
|
|
380
|
+
"workspace": true,
|
|
381
|
+
"mode": {
|
|
382
|
+
"const": "where"
|
|
383
|
+
},
|
|
384
|
+
"addressing": {
|
|
385
|
+
"enum": [
|
|
386
|
+
"free-text",
|
|
387
|
+
"subjects"
|
|
388
|
+
]
|
|
389
|
+
},
|
|
390
|
+
"topic": {
|
|
391
|
+
"type": "string",
|
|
392
|
+
"minLength": 1
|
|
393
|
+
},
|
|
394
|
+
"seeds": {
|
|
395
|
+
"type": "array",
|
|
396
|
+
"items": {
|
|
397
|
+
"type": "string",
|
|
398
|
+
"minLength": 1
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
"matched": {
|
|
402
|
+
"type": "integer",
|
|
403
|
+
"minimum": 0
|
|
404
|
+
},
|
|
405
|
+
"located": {
|
|
406
|
+
"type": "array",
|
|
407
|
+
"items": {
|
|
408
|
+
"type": "object",
|
|
409
|
+
"required": [
|
|
410
|
+
"subject",
|
|
411
|
+
"observations"
|
|
412
|
+
],
|
|
413
|
+
"additionalProperties": false,
|
|
414
|
+
"properties": {
|
|
415
|
+
"subject": {
|
|
416
|
+
"type": "string",
|
|
417
|
+
"minLength": 1
|
|
418
|
+
},
|
|
419
|
+
"observations": {
|
|
420
|
+
"type": "array",
|
|
421
|
+
"minItems": 1,
|
|
422
|
+
"items": {
|
|
423
|
+
"type": "object",
|
|
424
|
+
"required": [
|
|
425
|
+
"uri",
|
|
426
|
+
"result",
|
|
427
|
+
"provider"
|
|
428
|
+
],
|
|
429
|
+
"additionalProperties": false,
|
|
430
|
+
"properties": {
|
|
431
|
+
"uri": {
|
|
432
|
+
"type": "string",
|
|
433
|
+
"minLength": 1
|
|
434
|
+
},
|
|
435
|
+
"result": {
|
|
436
|
+
"enum": [
|
|
437
|
+
"confirmed",
|
|
438
|
+
"contradicted",
|
|
439
|
+
"unknown",
|
|
440
|
+
"not-observed"
|
|
441
|
+
]
|
|
442
|
+
},
|
|
443
|
+
"provider": {
|
|
444
|
+
"type": "string",
|
|
445
|
+
"minLength": 1
|
|
446
|
+
},
|
|
447
|
+
"message": {
|
|
448
|
+
"type": "string",
|
|
449
|
+
"minLength": 1
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
},
|
|
457
|
+
"coverage": {
|
|
458
|
+
"type": "object",
|
|
459
|
+
"required": [
|
|
460
|
+
"unobserved",
|
|
461
|
+
"note"
|
|
462
|
+
],
|
|
463
|
+
"additionalProperties": false,
|
|
464
|
+
"properties": {
|
|
465
|
+
"unobserved": {
|
|
466
|
+
"type": "array",
|
|
467
|
+
"items": {
|
|
468
|
+
"type": "string",
|
|
469
|
+
"minLength": 1
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
"note": {
|
|
473
|
+
"type": "string",
|
|
474
|
+
"minLength": 1
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
},
|
|
366
480
|
{
|
|
367
481
|
"type": "object",
|
|
368
482
|
"required": [
|
|
@@ -72,6 +72,11 @@
|
|
|
72
72
|
"projection": {
|
|
73
73
|
"$ref": "#/$defs/path"
|
|
74
74
|
},
|
|
75
|
+
"folder": {
|
|
76
|
+
"type": "string",
|
|
77
|
+
"description": "Sidebar folder for the rendered view, emitted as a LikeC4 title path ('Folder / Title'). Nest with '/' separators; folders appear in the order their first view appears in the views list.",
|
|
78
|
+
"pattern": "^[^/]+(?:/[^/]+)*$"
|
|
79
|
+
},
|
|
75
80
|
"compare": {
|
|
76
81
|
"$ref": "#/$defs/comparison"
|
|
77
82
|
},
|
|
@@ -33,7 +33,10 @@ design questions, and the backlog — planned subjects in dependency
|
|
|
33
33
|
order. `ask <workspace.yaml> --subjects` lists every concept;
|
|
34
34
|
`ask <workspace.yaml> --kinds` lists the declarable vocabulary;
|
|
35
35
|
`ask <workspace.yaml> "<free text>"` returns the model slice matching
|
|
36
|
-
your words.
|
|
36
|
+
your words; `ask <workspace.yaml> --where "<free text>"` returns the
|
|
37
|
+
evidence-verified code locations of matching subjects — prefer those
|
|
38
|
+
over searching when the subject is modeled, and use your own search
|
|
39
|
+
tools beyond the coverage boundary the output states.
|
|
37
40
|
|
|
38
41
|
- Existing implementation is the starting point: follow **Discover an
|
|
39
42
|
existing project**.
|