sysprom 1.17.0 → 1.18.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 (76) hide show
  1. package/README.md +145 -75
  2. package/dist/schema.json +2 -1
  3. package/dist/src/cli/commands/graph.d.ts +15 -0
  4. package/dist/src/cli/commands/graph.js +51 -2
  5. package/dist/src/cli/commands/init.d.ts +1 -1
  6. package/dist/src/cli/commands/json2md.d.ts +30 -1
  7. package/dist/src/cli/commands/json2md.js +42 -1
  8. package/dist/src/cli/commands/md2json.d.ts +1 -1
  9. package/dist/src/cli/commands/sync.d.ts +1 -1
  10. package/dist/src/cli/define-command.d.ts +1 -1
  11. package/dist/src/cli/define-command.js +176 -156
  12. package/dist/src/endpoint-types.js +13 -6
  13. package/dist/src/json-to-md.d.ts +32 -2
  14. package/dist/src/json-to-md.js +145 -5
  15. package/dist/src/md-to-json.js +7 -0
  16. package/dist/src/operations/add-node.d.ts +12 -9
  17. package/dist/src/operations/add-plan-task.d.ts +8 -6
  18. package/dist/src/operations/add-relationship.d.ts +11 -8
  19. package/dist/src/operations/check.d.ts +4 -3
  20. package/dist/src/operations/define-operation.d.ts +1 -1
  21. package/dist/src/operations/graph-decision.d.ts +329 -0
  22. package/dist/src/operations/graph-decision.js +96 -0
  23. package/dist/src/operations/graph-dependency.d.ts +329 -0
  24. package/dist/src/operations/graph-dependency.js +121 -0
  25. package/dist/src/operations/graph-refinement.d.ts +329 -0
  26. package/dist/src/operations/graph-refinement.js +97 -0
  27. package/dist/src/operations/graph-shared.d.ts +116 -0
  28. package/dist/src/operations/graph-shared.js +257 -0
  29. package/dist/src/operations/graph.d.ts +20 -4
  30. package/dist/src/operations/graph.js +129 -36
  31. package/dist/src/operations/index.d.ts +3 -0
  32. package/dist/src/operations/index.js +3 -0
  33. package/dist/src/operations/infer-completeness.d.ts +4 -3
  34. package/dist/src/operations/infer-derived.d.ts +4 -3
  35. package/dist/src/operations/infer-impact.d.ts +28 -21
  36. package/dist/src/operations/infer-lifecycle.d.ts +4 -3
  37. package/dist/src/operations/init-document.d.ts +4 -3
  38. package/dist/src/operations/json-to-markdown.d.ts +28 -3
  39. package/dist/src/operations/json-to-markdown.js +11 -1
  40. package/dist/src/operations/mark-task-done.d.ts +8 -6
  41. package/dist/src/operations/mark-task-undone.d.ts +8 -6
  42. package/dist/src/operations/markdown-to-json.d.ts +4 -3
  43. package/dist/src/operations/next-id.d.ts +4 -3
  44. package/dist/src/operations/node-history.d.ts +4 -3
  45. package/dist/src/operations/plan-add-task.d.ts +8 -6
  46. package/dist/src/operations/plan-gate.d.ts +4 -3
  47. package/dist/src/operations/plan-init.d.ts +4 -3
  48. package/dist/src/operations/plan-progress.d.ts +4 -3
  49. package/dist/src/operations/plan-status.d.ts +4 -3
  50. package/dist/src/operations/query-node.d.ts +24 -17
  51. package/dist/src/operations/query-nodes.d.ts +8 -6
  52. package/dist/src/operations/query-relationships.d.ts +7 -5
  53. package/dist/src/operations/remove-node.d.ts +12 -9
  54. package/dist/src/operations/remove-relationship.d.ts +10 -7
  55. package/dist/src/operations/rename.d.ts +8 -6
  56. package/dist/src/operations/search.d.ts +8 -6
  57. package/dist/src/operations/speckit-diff.d.ts +4 -3
  58. package/dist/src/operations/speckit-export.d.ts +4 -3
  59. package/dist/src/operations/speckit-import.d.ts +4 -3
  60. package/dist/src/operations/speckit-sync.d.ts +12 -9
  61. package/dist/src/operations/state-at.d.ts +4 -3
  62. package/dist/src/operations/stats.d.ts +4 -3
  63. package/dist/src/operations/sync.d.ts +12 -9
  64. package/dist/src/operations/task-list.d.ts +4 -3
  65. package/dist/src/operations/timeline.d.ts +4 -3
  66. package/dist/src/operations/trace-from-node.d.ts +12 -9
  67. package/dist/src/operations/update-metadata.d.ts +8 -6
  68. package/dist/src/operations/update-node.d.ts +11 -8
  69. package/dist/src/operations/update-plan-task.d.ts +8 -6
  70. package/dist/src/operations/validate.d.ts +4 -3
  71. package/dist/src/schema.d.ts +15 -10
  72. package/dist/src/schema.js +3 -11
  73. package/dist/src/utils/define-schema.d.ts +17 -0
  74. package/dist/src/utils/define-schema.js +21 -0
  75. package/package.json +98 -93
  76. package/schema.json +2 -1
@@ -0,0 +1,329 @@
1
+ import * as z from "zod";
2
+ /** Generate a refinement chain diagram showing how nodes elaborate through abstraction layers. */
3
+ export declare const graphRefinementOp: import("./define-operation.js").DefinedOperation<z.ZodObject<{
4
+ doc: z.ZodObject<{
5
+ $schema: z.ZodOptional<z.ZodString>;
6
+ metadata: z.ZodOptional<z.ZodObject<{
7
+ title: z.ZodOptional<z.ZodString>;
8
+ doc_type: z.ZodOptional<z.ZodString>;
9
+ scope: z.ZodOptional<z.ZodString>;
10
+ status: z.ZodOptional<z.ZodString>;
11
+ version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodInt]>>;
12
+ }, z.core.$loose> & {
13
+ is(value: unknown): value is {
14
+ [x: string]: unknown;
15
+ title?: string | undefined;
16
+ doc_type?: string | undefined;
17
+ scope?: string | undefined;
18
+ status?: string | undefined;
19
+ version?: string | number | undefined;
20
+ };
21
+ }>;
22
+ nodes: z.ZodArray<z.ZodObject<{
23
+ id: z.ZodString;
24
+ type: z.ZodEnum<{
25
+ intent: "intent";
26
+ concept: "concept";
27
+ capability: "capability";
28
+ element: "element";
29
+ realisation: "realisation";
30
+ invariant: "invariant";
31
+ principle: "principle";
32
+ policy: "policy";
33
+ protocol: "protocol";
34
+ stage: "stage";
35
+ role: "role";
36
+ gate: "gate";
37
+ mode: "mode";
38
+ artefact: "artefact";
39
+ artefact_flow: "artefact_flow";
40
+ decision: "decision";
41
+ change: "change";
42
+ view: "view";
43
+ milestone: "milestone";
44
+ version: "version";
45
+ }> & {
46
+ is(value: unknown): value is "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
47
+ };
48
+ name: z.ZodString;
49
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
50
+ is(value: unknown): value is string | string[];
51
+ }>;
52
+ status: z.ZodOptional<z.ZodEnum<{
53
+ deprecated: "deprecated";
54
+ proposed: "proposed";
55
+ accepted: "accepted";
56
+ active: "active";
57
+ implemented: "implemented";
58
+ adopted: "adopted";
59
+ defined: "defined";
60
+ introduced: "introduced";
61
+ in_progress: "in_progress";
62
+ complete: "complete";
63
+ consolidated: "consolidated";
64
+ experimental: "experimental";
65
+ retired: "retired";
66
+ superseded: "superseded";
67
+ abandoned: "abandoned";
68
+ deferred: "deferred";
69
+ }> & {
70
+ is(value: unknown): value is "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred";
71
+ }>;
72
+ lifecycle: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
73
+ context: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
74
+ is(value: unknown): value is string | string[];
75
+ }>;
76
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
77
+ id: z.ZodString;
78
+ description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
79
+ is(value: unknown): value is string | string[];
80
+ };
81
+ }, z.core.$loose> & {
82
+ is(value: unknown): value is {
83
+ [x: string]: unknown;
84
+ id: string;
85
+ description: string | string[];
86
+ };
87
+ }>>;
88
+ selected: z.ZodOptional<z.ZodString>;
89
+ rationale: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
90
+ is(value: unknown): value is string | string[];
91
+ }>;
92
+ scope: z.ZodOptional<z.ZodArray<z.ZodString>>;
93
+ operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
94
+ type: z.ZodEnum<{
95
+ link: "link";
96
+ add: "add";
97
+ update: "update";
98
+ remove: "remove";
99
+ }>;
100
+ target: z.ZodOptional<z.ZodString>;
101
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
102
+ is(value: unknown): value is string | string[];
103
+ }>;
104
+ }, z.core.$loose> & {
105
+ is(value: unknown): value is {
106
+ [x: string]: unknown;
107
+ type: "link" | "add" | "update" | "remove";
108
+ target?: string | undefined;
109
+ description?: string | string[] | undefined;
110
+ };
111
+ }>>;
112
+ plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
113
+ description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
114
+ is(value: unknown): value is string | string[];
115
+ };
116
+ done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
117
+ }, z.core.$loose> & {
118
+ is(value: unknown): value is {
119
+ [x: string]: unknown;
120
+ description: string | string[];
121
+ done?: boolean | undefined;
122
+ };
123
+ }>>;
124
+ propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
125
+ includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
126
+ input: z.ZodOptional<z.ZodString>;
127
+ output: z.ZodOptional<z.ZodString>;
128
+ external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
129
+ role: z.ZodEnum<{
130
+ output: "output";
131
+ input: "input";
132
+ context: "context";
133
+ evidence: "evidence";
134
+ source: "source";
135
+ standard: "standard";
136
+ prior_art: "prior_art";
137
+ }> & {
138
+ is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
139
+ };
140
+ identifier: z.ZodString;
141
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
142
+ is(value: unknown): value is string | string[];
143
+ }>;
144
+ node_id: z.ZodOptional<z.ZodString>;
145
+ internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
146
+ is(value: unknown): value is string | string[];
147
+ }>;
148
+ }, z.core.$strip> & {
149
+ is(value: unknown): value is {
150
+ role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
151
+ identifier: string;
152
+ description?: string | string[] | undefined;
153
+ node_id?: string | undefined;
154
+ internalised?: string | string[] | undefined;
155
+ };
156
+ }>>;
157
+ readonly subsystem: z.ZodOptional<z.ZodObject</*elided*/ any, z.core.$strip>>;
158
+ }, z.core.$loose>>;
159
+ relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
160
+ from: z.ZodString;
161
+ to: z.ZodString;
162
+ type: z.ZodEnum<{
163
+ refines: "refines";
164
+ realises: "realises";
165
+ implements: "implements";
166
+ depends_on: "depends_on";
167
+ constrained_by: "constrained_by";
168
+ affects: "affects";
169
+ supersedes: "supersedes";
170
+ must_preserve: "must_preserve";
171
+ performs: "performs";
172
+ part_of: "part_of";
173
+ precedes: "precedes";
174
+ must_follow: "must_follow";
175
+ blocks: "blocks";
176
+ routes_to: "routes_to";
177
+ governed_by: "governed_by";
178
+ modifies: "modifies";
179
+ triggered_by: "triggered_by";
180
+ applies_to: "applies_to";
181
+ produces: "produces";
182
+ consumes: "consumes";
183
+ transforms_into: "transforms_into";
184
+ selects: "selects";
185
+ requires: "requires";
186
+ disables: "disables";
187
+ influence: "influence";
188
+ justifies: "justifies";
189
+ }> & {
190
+ is(value: unknown): value is "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables" | "influence" | "justifies";
191
+ };
192
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
193
+ is(value: unknown): value is string | string[];
194
+ }>;
195
+ polarity: z.ZodOptional<z.ZodEnum<{
196
+ positive: "positive";
197
+ negative: "negative";
198
+ neutral: "neutral";
199
+ uncertain: "uncertain";
200
+ }> & {
201
+ is(value: unknown): value is "positive" | "negative" | "neutral" | "uncertain";
202
+ }>;
203
+ strength: z.ZodOptional<z.ZodNumber>;
204
+ }, z.core.$loose> & {
205
+ is(value: unknown): value is {
206
+ [x: string]: unknown;
207
+ from: string;
208
+ to: string;
209
+ type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables" | "influence" | "justifies";
210
+ description?: string | string[] | undefined;
211
+ polarity?: "positive" | "negative" | "neutral" | "uncertain" | undefined;
212
+ strength?: number | undefined;
213
+ };
214
+ }>>;
215
+ external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
216
+ role: z.ZodEnum<{
217
+ output: "output";
218
+ input: "input";
219
+ context: "context";
220
+ evidence: "evidence";
221
+ source: "source";
222
+ standard: "standard";
223
+ prior_art: "prior_art";
224
+ }> & {
225
+ is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
226
+ };
227
+ identifier: z.ZodString;
228
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
229
+ is(value: unknown): value is string | string[];
230
+ }>;
231
+ node_id: z.ZodOptional<z.ZodString>;
232
+ internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
233
+ is(value: unknown): value is string | string[];
234
+ }>;
235
+ }, z.core.$strip> & {
236
+ is(value: unknown): value is {
237
+ role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
238
+ identifier: string;
239
+ description?: string | string[] | undefined;
240
+ node_id?: string | undefined;
241
+ internalised?: string | string[] | undefined;
242
+ };
243
+ }>>;
244
+ }, z.core.$strip> & {
245
+ is(value: unknown): value is {
246
+ nodes: {
247
+ [x: string]: unknown;
248
+ id: string;
249
+ type: "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
250
+ name: string;
251
+ description?: string | string[] | undefined;
252
+ status?: "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred" | undefined;
253
+ lifecycle?: Record<string, string | boolean> | undefined;
254
+ context?: string | string[] | undefined;
255
+ options?: {
256
+ [x: string]: unknown;
257
+ id: string;
258
+ description: string | string[];
259
+ }[] | undefined;
260
+ selected?: string | undefined;
261
+ rationale?: string | string[] | undefined;
262
+ scope?: string[] | undefined;
263
+ operations?: {
264
+ [x: string]: unknown;
265
+ type: "link" | "add" | "update" | "remove";
266
+ target?: string | undefined;
267
+ description?: string | string[] | undefined;
268
+ }[] | undefined;
269
+ plan?: {
270
+ [x: string]: unknown;
271
+ description: string | string[];
272
+ done?: boolean | undefined;
273
+ }[] | undefined;
274
+ propagation?: Record<string, boolean> | undefined;
275
+ includes?: string[] | undefined;
276
+ input?: string | undefined;
277
+ output?: string | undefined;
278
+ external_references?: {
279
+ role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
280
+ identifier: string;
281
+ description?: string | string[] | undefined;
282
+ node_id?: string | undefined;
283
+ internalised?: string | string[] | undefined;
284
+ }[] | undefined;
285
+ subsystem?: /*elided*/ any | undefined;
286
+ }[];
287
+ $schema?: string | undefined;
288
+ metadata?: {
289
+ [x: string]: unknown;
290
+ title?: string | undefined;
291
+ doc_type?: string | undefined;
292
+ scope?: string | undefined;
293
+ status?: string | undefined;
294
+ version?: string | number | undefined;
295
+ } | undefined;
296
+ relationships?: {
297
+ [x: string]: unknown;
298
+ from: string;
299
+ to: string;
300
+ type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables" | "influence" | "justifies";
301
+ description?: string | string[] | undefined;
302
+ polarity?: "positive" | "negative" | "neutral" | "uncertain" | undefined;
303
+ strength?: number | undefined;
304
+ }[] | undefined;
305
+ external_references?: {
306
+ role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
307
+ identifier: string;
308
+ description?: string | string[] | undefined;
309
+ node_id?: string | undefined;
310
+ internalised?: string | string[] | undefined;
311
+ }[] | undefined;
312
+ };
313
+ };
314
+ format: z.ZodDefault<z.ZodEnum<{
315
+ dot: "dot";
316
+ mermaid: "mermaid";
317
+ }>>;
318
+ seedIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
319
+ layout: z.ZodDefault<z.ZodEnum<{
320
+ TD: "TD";
321
+ BT: "BT";
322
+ RL: "RL";
323
+ LR: "LR";
324
+ }>>;
325
+ labelMode: z.ZodDefault<z.ZodEnum<{
326
+ friendly: "friendly";
327
+ compact: "compact";
328
+ }>>;
329
+ }, z.core.$strip>, z.ZodString>;
@@ -0,0 +1,97 @@
1
+ import * as z from "zod";
2
+ import { defineOperation } from "./define-operation.js";
3
+ import { SysProMDocument } from "../schema.js";
4
+ import { sanitiseMermaidId, mermaidShapeForNode, renderMermaidNode, renderMermaidClassDefs, mermaidClassForNode, dotNodeAttrsWithMode, renderRelationshipLabel, } from "./graph-shared.js";
5
+ const REFINEMENT_REL_TYPES = new Set(["refines", "realises", "implements"]);
6
+ function collectRefinementChain(doc, seedIds) {
7
+ const rels = (doc.relationships ?? []).filter((r) => REFINEMENT_REL_TYPES.has(r.type));
8
+ if (seedIds && seedIds.length > 0) {
9
+ const reachable = new Set(seedIds);
10
+ let changed = true;
11
+ while (changed) {
12
+ changed = false;
13
+ for (const r of rels) {
14
+ if (reachable.has(r.from) && !reachable.has(r.to)) {
15
+ reachable.add(r.to);
16
+ changed = true;
17
+ }
18
+ if (reachable.has(r.to) && !reachable.has(r.from)) {
19
+ reachable.add(r.from);
20
+ changed = true;
21
+ }
22
+ }
23
+ }
24
+ const filteredRels = rels.filter((r) => reachable.has(r.from) && reachable.has(r.to));
25
+ const nodes = doc.nodes.filter((n) => reachable.has(n.id));
26
+ return { nodes, rels: filteredRels };
27
+ }
28
+ const nodeIds = new Set(rels.flatMap((r) => [r.from, r.to]));
29
+ const nodes = doc.nodes.filter((n) => nodeIds.has(n.id));
30
+ return { nodes, rels };
31
+ }
32
+ function generateRefinementMermaid(nodes, rels, labelMode) {
33
+ const lines = [];
34
+ lines.push("graph TD");
35
+ for (const def of renderMermaidClassDefs()) {
36
+ lines.push(` ${def}`);
37
+ }
38
+ lines.push("");
39
+ for (const node of nodes) {
40
+ const shape = mermaidShapeForNode(node);
41
+ const cls = mermaidClassForNode(node);
42
+ lines.push(` ${renderMermaidNode(node.id, node.name, shape, labelMode)}:::${cls}`);
43
+ }
44
+ lines.push("");
45
+ for (const rel of rels) {
46
+ const fromId = sanitiseMermaidId(rel.from);
47
+ const toId = sanitiseMermaidId(rel.to);
48
+ const label = renderRelationshipLabel(rel);
49
+ lines.push(` ${fromId} -->|${label}| ${toId}`);
50
+ }
51
+ return lines.join("\n");
52
+ }
53
+ function generateRefinementDot(nodes, rels, layout, labelMode) {
54
+ const lines = [];
55
+ lines.push("digraph RefinementChain {");
56
+ const rankdir = layout === "TD"
57
+ ? "TB"
58
+ : layout === "BT"
59
+ ? "BT"
60
+ : layout === "RL"
61
+ ? "RL"
62
+ : "LR";
63
+ lines.push(` rankdir=${rankdir};`);
64
+ lines.push(" node [style=filled];");
65
+ for (const node of nodes) {
66
+ lines.push(` "${node.id}" ${dotNodeAttrsWithMode(node, labelMode)};`);
67
+ }
68
+ for (const rel of rels) {
69
+ const label = renderRelationshipLabel(rel);
70
+ lines.push(` "${rel.from}" -> "${rel.to}" [label="${label}"];`);
71
+ }
72
+ lines.push("}");
73
+ return lines.join("\n");
74
+ }
75
+ /** Generate a refinement chain diagram showing how nodes elaborate through abstraction layers. */
76
+ export const graphRefinementOp = defineOperation({
77
+ name: "graphRefinement",
78
+ description: "Generate a refinement chain diagram showing intent → concept → capability → element → realisation relationships.",
79
+ input: z.object({
80
+ doc: SysProMDocument,
81
+ format: z.enum(["mermaid", "dot"]).default("mermaid"),
82
+ seedIds: z.array(z.string()).optional(),
83
+ layout: z.enum(["LR", "TD", "RL", "BT"]).default("TD"),
84
+ labelMode: z.enum(["friendly", "compact"]).default("friendly"),
85
+ }),
86
+ output: z.string(),
87
+ fn({ doc, format, seedIds, layout, labelMode }) {
88
+ const { nodes, rels } = collectRefinementChain(doc, seedIds);
89
+ if (format === "dot") {
90
+ return generateRefinementDot(nodes, rels, layout, labelMode);
91
+ }
92
+ const mermaid = generateRefinementMermaid(nodes, rels, labelMode);
93
+ const mermaidLines = mermaid.split("\n");
94
+ mermaidLines[0] = `graph ${layout}`;
95
+ return mermaidLines.join("\n");
96
+ },
97
+ });
@@ -0,0 +1,116 @@
1
+ import { type Node, type Relationship } from "../schema.js";
2
+ /**
3
+ * Sanitise an identifier for use in Mermaid diagrams by replacing
4
+ * non-alphanumeric/underscore characters with an underscore.
5
+ * @param id - Identifier to sanitise
6
+ * @example
7
+ * // sanitiseMermaidId('I1:Name') // 'I1_Name'
8
+ */
9
+ export declare function sanitiseMermaidId(id: string): string;
10
+ /**
11
+ *
12
+ */
13
+ export interface NodeCategory {
14
+ name: string;
15
+ label: string;
16
+ types: string[];
17
+ colour: string;
18
+ textColour: string;
19
+ }
20
+ export declare const NODE_CATEGORIES: NodeCategory[];
21
+ /**
22
+ * Return the category for a given node. Falls back to the last category
23
+ * if the node type is unknown.
24
+ * @param node - Node to obtain category for
25
+ * @example
26
+ * // categoryForNode(node).name
27
+ */
28
+ export declare function categoryForNode(node: Node): NodeCategory;
29
+ /**
30
+ * Return the category for a node type.
31
+ * @param type - Node type string
32
+ * @example
33
+ * // categoryForType('intent').name // 'intent'
34
+ */
35
+ export declare function categoryForType(type: string): NodeCategory;
36
+ /**
37
+ *
38
+ */
39
+ export type MermaidShape = "rounded" | "rectangle" | "rhombus" | "parallelogram";
40
+ /**
41
+ * Map a node to its Mermaid shape.
42
+ * @param node - Node to determine shape for
43
+ * @example
44
+ */
45
+ export declare function mermaidShapeForNode(node: Node): MermaidShape;
46
+ /**
47
+ * Render a Mermaid node definition for a node id/name/shape.
48
+ * @param id - Node id
49
+ * @param name - Node name
50
+ * @param shape - Shape to render
51
+ * @param mode - Label mode, friendly shows id and name, compact shows id only
52
+ * @example
53
+ */
54
+ export declare function renderMermaidNode(id: string, name: string, shape: MermaidShape, mode?: "friendly" | "compact"): string;
55
+ /**
56
+ * Render a human-friendly relationship label including polarity and strength
57
+ * @param rel
58
+ * @example
59
+ */
60
+ export declare function renderRelationshipLabel(rel: Relationship): string;
61
+ /**
62
+ * @example
63
+ */
64
+ export declare function renderMermaidClassDefs(): string[];
65
+ /**
66
+ * @param node
67
+ * @example
68
+ */
69
+ export declare function mermaidClassForNode(node: Node): string;
70
+ /**
71
+ * @param node
72
+ * @example
73
+ */
74
+ export declare function dotNodeAttrs(node: Node): string;
75
+ /**
76
+ * Format a node label according to a mode. "friendly" shows id and name,
77
+ * "compact" shows only the id.
78
+ * @param node
79
+ * @param mode
80
+ * @example
81
+ */
82
+ export declare function formatNodeLabel(node: Node, mode: "friendly" | "compact"): string;
83
+ /**
84
+ * @param node
85
+ * @param mode
86
+ * @example
87
+ */
88
+ export declare function dotNodeAttrsWithMode(node: Node, mode?: "friendly" | "compact"): string;
89
+ /**
90
+ *
91
+ */
92
+ export interface GraphFilterOptions {
93
+ nodeTypes?: string[];
94
+ nodeIds?: string[];
95
+ relTypes?: string[];
96
+ connectedOnly?: boolean;
97
+ }
98
+ /**
99
+ * @param nodes
100
+ * @param opts
101
+ * @example
102
+ */
103
+ export declare function filterNodes(nodes: Node[], opts: GraphFilterOptions): Node[];
104
+ /**
105
+ * @param rels
106
+ * @param opts
107
+ * @param allowedNodeIds
108
+ * @example
109
+ */
110
+ export declare function filterRelationships(rels: Relationship[], opts: GraphFilterOptions, allowedNodeIds?: Set<string>): Relationship[];
111
+ /**
112
+ * @param nodes
113
+ * @param rels
114
+ * @example
115
+ */
116
+ export declare function applyConnectedOnly(nodes: Node[], rels: Relationship[]): Node[];