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.
- package/README.md +145 -75
- package/dist/schema.json +2 -1
- package/dist/src/cli/commands/graph.d.ts +15 -0
- package/dist/src/cli/commands/graph.js +51 -2
- package/dist/src/cli/commands/init.d.ts +1 -1
- package/dist/src/cli/commands/json2md.d.ts +30 -1
- package/dist/src/cli/commands/json2md.js +42 -1
- package/dist/src/cli/commands/md2json.d.ts +1 -1
- package/dist/src/cli/commands/sync.d.ts +1 -1
- package/dist/src/cli/define-command.d.ts +1 -1
- package/dist/src/cli/define-command.js +176 -156
- package/dist/src/endpoint-types.js +13 -6
- package/dist/src/json-to-md.d.ts +32 -2
- package/dist/src/json-to-md.js +145 -5
- package/dist/src/md-to-json.js +7 -0
- package/dist/src/operations/add-node.d.ts +12 -9
- package/dist/src/operations/add-plan-task.d.ts +8 -6
- package/dist/src/operations/add-relationship.d.ts +11 -8
- package/dist/src/operations/check.d.ts +4 -3
- package/dist/src/operations/define-operation.d.ts +1 -1
- package/dist/src/operations/graph-decision.d.ts +329 -0
- package/dist/src/operations/graph-decision.js +96 -0
- package/dist/src/operations/graph-dependency.d.ts +329 -0
- package/dist/src/operations/graph-dependency.js +121 -0
- package/dist/src/operations/graph-refinement.d.ts +329 -0
- package/dist/src/operations/graph-refinement.js +97 -0
- package/dist/src/operations/graph-shared.d.ts +116 -0
- package/dist/src/operations/graph-shared.js +257 -0
- package/dist/src/operations/graph.d.ts +20 -4
- package/dist/src/operations/graph.js +129 -36
- package/dist/src/operations/index.d.ts +3 -0
- package/dist/src/operations/index.js +3 -0
- package/dist/src/operations/infer-completeness.d.ts +4 -3
- package/dist/src/operations/infer-derived.d.ts +4 -3
- package/dist/src/operations/infer-impact.d.ts +28 -21
- package/dist/src/operations/infer-lifecycle.d.ts +4 -3
- package/dist/src/operations/init-document.d.ts +4 -3
- package/dist/src/operations/json-to-markdown.d.ts +28 -3
- package/dist/src/operations/json-to-markdown.js +11 -1
- package/dist/src/operations/mark-task-done.d.ts +8 -6
- package/dist/src/operations/mark-task-undone.d.ts +8 -6
- package/dist/src/operations/markdown-to-json.d.ts +4 -3
- package/dist/src/operations/next-id.d.ts +4 -3
- package/dist/src/operations/node-history.d.ts +4 -3
- package/dist/src/operations/plan-add-task.d.ts +8 -6
- package/dist/src/operations/plan-gate.d.ts +4 -3
- package/dist/src/operations/plan-init.d.ts +4 -3
- package/dist/src/operations/plan-progress.d.ts +4 -3
- package/dist/src/operations/plan-status.d.ts +4 -3
- package/dist/src/operations/query-node.d.ts +24 -17
- package/dist/src/operations/query-nodes.d.ts +8 -6
- package/dist/src/operations/query-relationships.d.ts +7 -5
- package/dist/src/operations/remove-node.d.ts +12 -9
- package/dist/src/operations/remove-relationship.d.ts +10 -7
- package/dist/src/operations/rename.d.ts +8 -6
- package/dist/src/operations/search.d.ts +8 -6
- package/dist/src/operations/speckit-diff.d.ts +4 -3
- package/dist/src/operations/speckit-export.d.ts +4 -3
- package/dist/src/operations/speckit-import.d.ts +4 -3
- package/dist/src/operations/speckit-sync.d.ts +12 -9
- package/dist/src/operations/state-at.d.ts +4 -3
- package/dist/src/operations/stats.d.ts +4 -3
- package/dist/src/operations/sync.d.ts +12 -9
- package/dist/src/operations/task-list.d.ts +4 -3
- package/dist/src/operations/timeline.d.ts +4 -3
- package/dist/src/operations/trace-from-node.d.ts +12 -9
- package/dist/src/operations/update-metadata.d.ts +8 -6
- package/dist/src/operations/update-node.d.ts +11 -8
- package/dist/src/operations/update-plan-task.d.ts +8 -6
- package/dist/src/operations/validate.d.ts +4 -3
- package/dist/src/schema.d.ts +15 -10
- package/dist/src/schema.js +3 -11
- package/dist/src/utils/define-schema.d.ts +17 -0
- package/dist/src/utils/define-schema.js +21 -0
- package/package.json +98 -93
- package/schema.json +2 -1
package/README.md
CHANGED
|
@@ -23,16 +23,60 @@ Both `sysprom` and `spm` are available as commands — use `sysprom` for new pro
|
|
|
23
23
|
|
|
24
24
|
## CLI
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
````sh
|
|
27
27
|
# Convert between formats
|
|
28
28
|
sysprom json2md --input .SysProM.json --output ./.SysProM
|
|
29
29
|
sysprom md2json --input ./.SysProM --output output.SysProM.json
|
|
30
30
|
|
|
31
|
+
# Diagram and label options
|
|
32
|
+
|
|
33
|
+
The `graph` and `json2md` commands support options to control diagram layout and node label style used when generating Mermaid/DOT output.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
# Generate a Mermaid graph with friendly labels (default)
|
|
39
|
+
sysprom graph --path .SysProM.json --format mermaid
|
|
40
|
+
|
|
41
|
+
# Compact node labels (IDs only) instead of `ID: Name`
|
|
42
|
+
sysprom graph --path .SysProM.json --format mermaid --label-mode compact
|
|
43
|
+
|
|
44
|
+
# Embed diagrams when converting JSON → Markdown, using compact labels
|
|
45
|
+
sysprom json2md --input .SysProM.json --output ./.SysProM --embed-diagrams --label-mode compact
|
|
46
|
+
|
|
47
|
+
# Control layout direction for graph (LR, TD, RL, BT)
|
|
48
|
+
sysprom graph --path .SysProM.json --format mermaid --layout LR
|
|
49
|
+
````
|
|
50
|
+
|
|
51
|
+
Notes:
|
|
52
|
+
|
|
53
|
+
- `--label-mode friendly|compact` controls whether nodes show `ID: Name` (`friendly`) or just `ID` (`compact`).
|
|
54
|
+
- `--layout LR|TD|RL|BT` controls graph direction. `json2md` uses sensible per-diagram defaults (relationship/refinement/decision diagrams default to `TD`, dependency diagrams default to `LR`) but you can override when calling `graph` directly.
|
|
55
|
+
- `--label-mode friendly|compact` controls whether nodes show `ID: Name` (`friendly`) or just `ID` (`compact`).
|
|
56
|
+
- `--layout LR|TD|RL|BT` controls graph direction. `json2md` uses sensible per-diagram defaults (relationship/refinement/decision diagrams default to `TD`, dependency diagrams default to `LR`) but you can override when calling `graph` directly.
|
|
57
|
+
- `json2md` supports per-diagram layout overrides to control each embedded diagram independently:
|
|
58
|
+
- `--relationship-layout LR|TD|RL|BT` — override the layout used for the Relationship Graph.
|
|
59
|
+
- `--refinement-layout LR|TD|RL|BT` — override the layout used for the Refinement Chain.
|
|
60
|
+
- `--decision-layout LR|TD|RL|BT` — override the layout used for the Decision Map.
|
|
61
|
+
- `--dependency-layout LR|TD|RL|BT` — override the layout used for the Dependency Graph.
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
# Embed diagrams in multi-doc output but make dependency graph top-to-bottom (TD)
|
|
67
|
+
sysprom json2md --input .SysProM.json --output ./.SysProM --embed-diagrams --dependency-layout TD
|
|
68
|
+
|
|
69
|
+
# Override relationship and refinement layouts independently
|
|
70
|
+
sysprom json2md --input .SysProM.json --output ./.SysProM --embed-diagrams --relationship-layout LR --refinement-layout TD
|
|
71
|
+
```
|
|
72
|
+
|
|
31
73
|
# Validate and summarise (auto-detects .SysProM.json in current directory)
|
|
74
|
+
|
|
32
75
|
sysprom validate
|
|
33
76
|
sysprom stats
|
|
34
77
|
|
|
35
78
|
# Query nodes and relationships
|
|
79
|
+
|
|
36
80
|
sysprom query nodes --type decision
|
|
37
81
|
sysprom query node D1
|
|
38
82
|
sysprom query rels --from D1
|
|
@@ -41,27 +85,32 @@ sysprom query timeline
|
|
|
41
85
|
sysprom query state-at 2026-03-22
|
|
42
86
|
|
|
43
87
|
# Add nodes (ID auto-generated from type prefix if --id omitted)
|
|
88
|
+
|
|
44
89
|
sysprom add invariant --name "New Rule" --description "Must hold"
|
|
45
90
|
sysprom add decision --name "Choose X" \
|
|
46
|
-
|
|
47
|
-
|
|
91
|
+
--option "OPT-A:Use framework X" --option "OPT-B:Use framework Y" \
|
|
92
|
+
--selected OPT-A --rationale "Lower migration effort"
|
|
48
93
|
|
|
49
94
|
# Remove nodes
|
|
95
|
+
|
|
50
96
|
sysprom remove INV23
|
|
51
97
|
|
|
52
98
|
# Update nodes, relationships, and metadata
|
|
99
|
+
|
|
53
100
|
sysprom update node D1 --status deprecated
|
|
54
101
|
sysprom update add-rel D1 affects EL5
|
|
55
102
|
sysprom update remove-rel D1 affects EL5
|
|
56
103
|
sysprom update meta --fields version=2
|
|
57
104
|
|
|
58
105
|
# Inference operations (deterministic graph analysis)
|
|
59
|
-
|
|
60
|
-
sysprom infer
|
|
61
|
-
sysprom infer
|
|
62
|
-
sysprom infer
|
|
63
|
-
sysprom infer
|
|
64
|
-
|
|
106
|
+
|
|
107
|
+
sysprom infer completeness # Score node completeness (0-1)
|
|
108
|
+
sysprom infer lifecycle # Infer lifecycle phases
|
|
109
|
+
sysprom infer impact I1 # Trace impact from node
|
|
110
|
+
sysprom infer derived # Compute transitive closure
|
|
111
|
+
sysprom infer all # Run all analyses
|
|
112
|
+
|
|
113
|
+
````
|
|
65
114
|
|
|
66
115
|
All commands auto-detect the document — they search the current directory for `.SysProM.json`, `.SysProM.md`, or `.SysProM/` (in that priority order), then fall back to `.spm.json`, `.spm.md`, or `.spm/`. Use `--path` to specify an explicit path. Note: `spm` is an alias for `sysprom` for backwards compatibility.
|
|
67
116
|
|
|
@@ -82,7 +131,7 @@ Add the following to your MCP client's configuration (e.g. `.cursor/mcp.json`, `
|
|
|
82
131
|
}
|
|
83
132
|
}
|
|
84
133
|
}
|
|
85
|
-
|
|
134
|
+
````
|
|
86
135
|
|
|
87
136
|
Or via the CLI subcommand (equivalent):
|
|
88
137
|
|
|
@@ -92,23 +141,23 @@ sysprom mcp # starts the MCP server on stdio
|
|
|
92
141
|
|
|
93
142
|
### Available Tools
|
|
94
143
|
|
|
95
|
-
| Tool
|
|
96
|
-
|
|
97
|
-
| `validate`
|
|
98
|
-
| `stats`
|
|
99
|
-
| `query-nodes`
|
|
100
|
-
| `query-node`
|
|
101
|
-
| `query-relationships` | Query relationships by source, target, or type
|
|
102
|
-
| `trace`
|
|
103
|
-
| `add-node`
|
|
104
|
-
| `remove-node`
|
|
105
|
-
| `update-node`
|
|
106
|
-
| `add-relationship`
|
|
107
|
-
| `remove-relationship` | Remove a relationship
|
|
108
|
-
| `infer-completeness`
|
|
109
|
-
| `infer-lifecycle`
|
|
110
|
-
| `infer-impact`
|
|
111
|
-
| `infer-derived`
|
|
144
|
+
| Tool | Description |
|
|
145
|
+
| --------------------- | --------------------------------------------------------------- |
|
|
146
|
+
| `validate` | Validate a SysProM document and return issues |
|
|
147
|
+
| `stats` | Return document statistics |
|
|
148
|
+
| `query-nodes` | Query nodes by type, status, or text |
|
|
149
|
+
| `query-node` | Retrieve a single node by ID |
|
|
150
|
+
| `query-relationships` | Query relationships by source, target, or type |
|
|
151
|
+
| `trace` | Trace refinement chains from a node |
|
|
152
|
+
| `add-node` | Add a new node to the document |
|
|
153
|
+
| `remove-node` | Remove a node by ID |
|
|
154
|
+
| `update-node` | Update fields on an existing node |
|
|
155
|
+
| `add-relationship` | Add a relationship between nodes |
|
|
156
|
+
| `remove-relationship` | Remove a relationship |
|
|
157
|
+
| `infer-completeness` | Score node completeness (0-1) based on refinement relationships |
|
|
158
|
+
| `infer-lifecycle` | Infer lifecycle phase from status and lifecycle fields |
|
|
159
|
+
| `infer-impact` | Trace impact propagation from a starting node |
|
|
160
|
+
| `infer-derived` | Compute transitive closure and inverse relationships |
|
|
112
161
|
|
|
113
162
|
All tools accept a `path` parameter to specify the SysProM document location.
|
|
114
163
|
|
|
@@ -116,50 +165,50 @@ All tools accept a `path` parameter to specify the SysProM document location.
|
|
|
116
165
|
|
|
117
166
|
```ts
|
|
118
167
|
import {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
// Schema and types
|
|
169
|
+
sysproMDocument,
|
|
170
|
+
node,
|
|
171
|
+
nodeType,
|
|
172
|
+
relationshipType,
|
|
173
|
+
type SysProMDocument,
|
|
174
|
+
type Node,
|
|
175
|
+
type Relationship,
|
|
176
|
+
|
|
177
|
+
// Conversion
|
|
178
|
+
jsonToMarkdown,
|
|
179
|
+
jsonToMarkdownSingle,
|
|
180
|
+
jsonToMarkdownMultiDoc,
|
|
181
|
+
markdownToJson,
|
|
182
|
+
|
|
183
|
+
// Validation and query
|
|
184
|
+
validate,
|
|
185
|
+
stats,
|
|
186
|
+
queryNodes,
|
|
187
|
+
queryNode,
|
|
188
|
+
queryRelationships,
|
|
189
|
+
traceFromNode,
|
|
190
|
+
|
|
191
|
+
// Mutation
|
|
192
|
+
addNode,
|
|
193
|
+
removeNode,
|
|
194
|
+
updateNode,
|
|
195
|
+
addRelationship,
|
|
196
|
+
removeRelationship,
|
|
197
|
+
updateMetadata,
|
|
198
|
+
|
|
199
|
+
// Inference
|
|
200
|
+
inferCompletenessOp,
|
|
201
|
+
inferLifecycleOp,
|
|
202
|
+
inferImpactOp,
|
|
203
|
+
inferDerivedOp,
|
|
204
|
+
|
|
205
|
+
// File I/O
|
|
206
|
+
loadDocument,
|
|
207
|
+
saveDocument,
|
|
208
|
+
|
|
209
|
+
// Utilities
|
|
210
|
+
canonicalise,
|
|
211
|
+
toJSONSchema,
|
|
163
212
|
} from "sysprom";
|
|
164
213
|
|
|
165
214
|
// Validate
|
|
@@ -172,12 +221,24 @@ const decisions = queryNodes(doc, { type: "decision" });
|
|
|
172
221
|
const trace = traceFromNode(doc, "I1");
|
|
173
222
|
|
|
174
223
|
// Mutate
|
|
175
|
-
const updated = addNode(doc, {
|
|
176
|
-
|
|
224
|
+
const updated = addNode(doc, {
|
|
225
|
+
id: "INV23",
|
|
226
|
+
type: "invariant",
|
|
227
|
+
name: "New Rule",
|
|
228
|
+
});
|
|
229
|
+
const withRel = addRelationship(updated, {
|
|
230
|
+
from: "D1",
|
|
231
|
+
to: "INV23",
|
|
232
|
+
type: "must_preserve",
|
|
233
|
+
});
|
|
177
234
|
|
|
178
235
|
// Type guards
|
|
179
|
-
if (sysproMDocument.is(data)) {
|
|
180
|
-
|
|
236
|
+
if (sysproMDocument.is(data)) {
|
|
237
|
+
/* data is SysProMDocument */
|
|
238
|
+
}
|
|
239
|
+
if (node.is(thing)) {
|
|
240
|
+
/* thing is Node */
|
|
241
|
+
}
|
|
181
242
|
```
|
|
182
243
|
|
|
183
244
|
## What is SysProM?
|
|
@@ -323,21 +384,25 @@ When working on the SysProM repo itself, skills in `.claude/skills/` are auto-di
|
|
|
323
384
|
### Skills by Category
|
|
324
385
|
|
|
325
386
|
**Node Creation (4 skills)**
|
|
387
|
+
|
|
326
388
|
- `add-decision` — Create decision nodes with context, options, rationale, and invariant links
|
|
327
389
|
- `add-change` — Create change nodes with scope, operations, and task tracking
|
|
328
390
|
- `add-invariant` — Create invariant nodes representing system rules and constraints
|
|
329
391
|
- `add-node` — Generic node creation for any SysProM type
|
|
330
392
|
|
|
331
393
|
**Node Modification (3 skills)**
|
|
394
|
+
|
|
332
395
|
- `update-node` — Modify node fields, status, lifecycle, context, or rationale
|
|
333
396
|
- `remove-node` — Delete nodes with safety flags (hard delete, recursive, repair)
|
|
334
397
|
- `rename-node` — Rename node IDs across all references
|
|
335
398
|
|
|
336
399
|
**Relationships (2 skills)**
|
|
400
|
+
|
|
337
401
|
- `add-relationship` — Create relationships between nodes with specific types
|
|
338
402
|
- `remove-relationship` — Delete relationships
|
|
339
403
|
|
|
340
404
|
**Query & Analysis (5 skills)**
|
|
405
|
+
|
|
341
406
|
- `query-nodes` — Search nodes by type, status, text, or ID
|
|
342
407
|
- `query-relationships` — Query relationships by source, target, or type
|
|
343
408
|
- `trace-node` — Trace refinement chains through abstraction layers
|
|
@@ -345,26 +410,31 @@ When working on the SysProM repo itself, skills in `.claude/skills/` are auto-di
|
|
|
345
410
|
- `stats` — Show document statistics and composition metrics
|
|
346
411
|
|
|
347
412
|
**Visualisation (1 skill)**
|
|
413
|
+
|
|
348
414
|
- `graph` — Generate Mermaid or DOT graphs with filtering
|
|
349
415
|
|
|
350
416
|
**Format Conversion (4 skills)**
|
|
417
|
+
|
|
351
418
|
- `init-document` — Create new SysProM documents with metadata
|
|
352
419
|
- `json-to-markdown` — Convert JSON to Markdown format
|
|
353
420
|
- `markdown-to-json` — Convert Markdown to JSON format
|
|
354
421
|
- `sync-formats` — Bidirectional sync between JSON and Markdown
|
|
355
422
|
|
|
356
423
|
**Spec-Kit Integration (4 skills)**
|
|
424
|
+
|
|
357
425
|
- `speckit-import` — Import Spec-Kit features as SysProM nodes
|
|
358
426
|
- `speckit-export` — Export SysProM nodes to Spec-Kit format
|
|
359
427
|
- `speckit-sync` — Bidirectional sync with Spec-Kit specifications
|
|
360
428
|
- `speckit-diff` — Show differences between SysProM and Spec-Kit
|
|
361
429
|
|
|
362
430
|
**Task Management (3 skills)**
|
|
431
|
+
|
|
363
432
|
- `task-list` — List tasks in a change node with progress
|
|
364
433
|
- `task-add` — Add tasks to a change
|
|
365
434
|
- `task-mark-done` — Mark tasks as complete
|
|
366
435
|
|
|
367
436
|
**Plan Management (2 skills)**
|
|
437
|
+
|
|
368
438
|
- `plan-init` — Initialise plans with phases and gates
|
|
369
439
|
- `plan-status` — Show plan progress and phase gates
|
|
370
440
|
|
package/dist/schema.json
CHANGED
|
@@ -9,6 +9,21 @@ declare const optsSchema: z.ZodObject<{
|
|
|
9
9
|
mermaid: "mermaid";
|
|
10
10
|
}>>;
|
|
11
11
|
type: z.ZodOptional<z.ZodString>;
|
|
12
|
+
nodeTypes: z.ZodOptional<z.ZodString>;
|
|
13
|
+
nodeIds: z.ZodOptional<z.ZodString>;
|
|
14
|
+
relTypes: z.ZodOptional<z.ZodString>;
|
|
15
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
16
|
+
TD: "TD";
|
|
17
|
+
BT: "BT";
|
|
18
|
+
RL: "RL";
|
|
19
|
+
LR: "LR";
|
|
20
|
+
}>>;
|
|
21
|
+
labelMode: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
friendly: "friendly";
|
|
23
|
+
compact: "compact";
|
|
24
|
+
}>>;
|
|
25
|
+
cluster: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
connectedOnly: z.ZodOptional<z.ZodBoolean>;
|
|
12
27
|
}, z.core.$strip>;
|
|
13
28
|
export declare const graphCommand: CommandDef<typeof noArgs, typeof optsSchema>;
|
|
14
29
|
export {};
|
|
@@ -1,9 +1,41 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import * as z from "zod";
|
|
2
3
|
import { graphOp } from "../../operations/index.js";
|
|
3
4
|
import { readOpts, loadDoc } from "../shared.js";
|
|
4
5
|
const optsSchema = readOpts.extend({
|
|
5
6
|
format: z.enum(["mermaid", "dot"]).optional().describe("Output format"),
|
|
6
|
-
type: z
|
|
7
|
+
type: z
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Filter by relationship type (backward compatible)"),
|
|
11
|
+
nodeTypes: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Filter by node types (comma-separated)"),
|
|
15
|
+
nodeIds: z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Filter by node IDs (comma-separated)"),
|
|
19
|
+
relTypes: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Filter by relationship types (comma-separated)"),
|
|
23
|
+
layout: z
|
|
24
|
+
.enum(["LR", "TD", "RL", "BT"])
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Graph layout direction"),
|
|
27
|
+
labelMode: z
|
|
28
|
+
.enum(["friendly", "compact"])
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Node label mode: "friendly" shows `id: name`, "compact" shows `id`'),
|
|
31
|
+
cluster: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Group nodes by category in subgraphs"),
|
|
35
|
+
connectedOnly: z
|
|
36
|
+
.boolean()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Only show nodes that have relationships"),
|
|
7
39
|
});
|
|
8
40
|
export const graphCommand = {
|
|
9
41
|
name: "graph",
|
|
@@ -13,15 +45,32 @@ export const graphCommand = {
|
|
|
13
45
|
action(_args, opts) {
|
|
14
46
|
try {
|
|
15
47
|
const { doc } = loadDoc(opts.path);
|
|
48
|
+
const nodeTypes = opts.nodeTypes
|
|
49
|
+
? opts.nodeTypes.split(",").map((s) => s.trim())
|
|
50
|
+
: undefined;
|
|
51
|
+
const nodeIds = opts.nodeIds
|
|
52
|
+
? opts.nodeIds.split(",").map((s) => s.trim())
|
|
53
|
+
: undefined;
|
|
54
|
+
const relTypes = opts.relTypes
|
|
55
|
+
? opts.relTypes.split(",").map((s) => s.trim())
|
|
56
|
+
: undefined;
|
|
16
57
|
const output = graphOp({
|
|
17
58
|
doc,
|
|
18
59
|
format: opts.format ?? "mermaid",
|
|
19
60
|
typeFilter: opts.type,
|
|
61
|
+
nodeTypes,
|
|
62
|
+
nodeIds,
|
|
63
|
+
relTypes,
|
|
64
|
+
layout: opts.layout ?? "TD",
|
|
65
|
+
cluster: opts.cluster ?? true,
|
|
66
|
+
labelMode: opts.labelMode ?? "friendly",
|
|
67
|
+
connectedOnly: opts.connectedOnly ?? false,
|
|
20
68
|
});
|
|
21
69
|
console.log(output);
|
|
22
70
|
}
|
|
23
71
|
catch (err) {
|
|
24
|
-
|
|
72
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
73
|
+
console.error(message);
|
|
25
74
|
process.exit(1);
|
|
26
75
|
}
|
|
27
76
|
},
|
|
@@ -10,5 +10,5 @@ declare const optsSchema: z.ZodObject<{
|
|
|
10
10
|
dir: "dir";
|
|
11
11
|
}>>;
|
|
12
12
|
}, z.core.$strict>;
|
|
13
|
-
export declare const initCommand: CommandDef<z.ZodObject
|
|
13
|
+
export declare const initCommand: CommandDef<z.ZodObject, typeof optsSchema>;
|
|
14
14
|
export {};
|
|
@@ -4,6 +4,35 @@ declare const optsSchema: z.ZodObject<{
|
|
|
4
4
|
input: z.ZodString;
|
|
5
5
|
output: z.ZodString;
|
|
6
6
|
singleFile: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
embedDiagrams: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
labelMode: z.ZodOptional<z.ZodEnum<{
|
|
9
|
+
friendly: "friendly";
|
|
10
|
+
compact: "compact";
|
|
11
|
+
}>>;
|
|
12
|
+
relationshipLayout: z.ZodOptional<z.ZodEnum<{
|
|
13
|
+
TD: "TD";
|
|
14
|
+
BT: "BT";
|
|
15
|
+
RL: "RL";
|
|
16
|
+
LR: "LR";
|
|
17
|
+
}>>;
|
|
18
|
+
refinementLayout: z.ZodOptional<z.ZodEnum<{
|
|
19
|
+
TD: "TD";
|
|
20
|
+
BT: "BT";
|
|
21
|
+
RL: "RL";
|
|
22
|
+
LR: "LR";
|
|
23
|
+
}>>;
|
|
24
|
+
decisionLayout: z.ZodOptional<z.ZodEnum<{
|
|
25
|
+
TD: "TD";
|
|
26
|
+
BT: "BT";
|
|
27
|
+
RL: "RL";
|
|
28
|
+
LR: "LR";
|
|
29
|
+
}>>;
|
|
30
|
+
dependencyLayout: z.ZodOptional<z.ZodEnum<{
|
|
31
|
+
TD: "TD";
|
|
32
|
+
BT: "BT";
|
|
33
|
+
RL: "RL";
|
|
34
|
+
LR: "LR";
|
|
35
|
+
}>>;
|
|
7
36
|
}, z.core.$strict>;
|
|
8
|
-
export declare const json2mdCommand: CommandDef<z.ZodObject
|
|
37
|
+
export declare const json2mdCommand: CommandDef<z.ZodObject, typeof optsSchema>;
|
|
9
38
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import * as z from "zod";
|
|
2
3
|
import { readFileSync } from "node:fs";
|
|
3
4
|
import { resolve } from "node:path";
|
|
@@ -12,6 +13,30 @@ const optsSchema = z
|
|
|
12
13
|
.boolean()
|
|
13
14
|
.optional()
|
|
14
15
|
.describe("Force single-file output format"),
|
|
16
|
+
embedDiagrams: z
|
|
17
|
+
.boolean()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Embed Mermaid diagrams in the output"),
|
|
20
|
+
labelMode: z
|
|
21
|
+
.enum(["friendly", "compact"])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Node label mode for embedded diagrams"),
|
|
24
|
+
relationshipLayout: z
|
|
25
|
+
.enum(["LR", "TD", "RL", "BT"])
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Override layout for relationship diagrams"),
|
|
28
|
+
refinementLayout: z
|
|
29
|
+
.enum(["LR", "TD", "RL", "BT"])
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Override layout for refinement diagrams"),
|
|
32
|
+
decisionLayout: z
|
|
33
|
+
.enum(["LR", "TD", "RL", "BT"])
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Override layout for decision diagrams"),
|
|
36
|
+
dependencyLayout: z
|
|
37
|
+
.enum(["LR", "TD", "RL", "BT"])
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Override layout for dependency diagrams"),
|
|
15
40
|
})
|
|
16
41
|
.strict();
|
|
17
42
|
export const json2mdCommand = {
|
|
@@ -23,6 +48,7 @@ export const json2mdCommand = {
|
|
|
23
48
|
const inputPath = resolve(opts.input);
|
|
24
49
|
const outputPath = resolve(opts.output);
|
|
25
50
|
const raw = JSON.parse(readFileSync(inputPath, "utf8"));
|
|
51
|
+
// Use the attached type guard for clearer intent and narrower runtime checks
|
|
26
52
|
if (!SysProMDocument.is(raw)) {
|
|
27
53
|
const result = SysProMDocument.safeParse(raw);
|
|
28
54
|
if (!result.success) {
|
|
@@ -36,7 +62,22 @@ export const json2mdCommand = {
|
|
|
36
62
|
const form = opts.singleFile || outputPath.endsWith(".md")
|
|
37
63
|
? "single-file"
|
|
38
64
|
: "multi-doc";
|
|
39
|
-
|
|
65
|
+
// Forward per-diagram layout overrides via environment-like flags.
|
|
66
|
+
// We accept flags on the command line for common diagram layouts but also
|
|
67
|
+
// preserve sensible per-diagram defaults in jsonToMarkdown when not set.
|
|
68
|
+
// For now we expose a single --label-mode flag and keep per-diagram layout
|
|
69
|
+
// defaults internal; a future enhancement could expose per-diagram
|
|
70
|
+
// flags such as --relationship-layout, --dependency-layout, etc.
|
|
71
|
+
jsonToMarkdown(raw, outputPath, {
|
|
72
|
+
form,
|
|
73
|
+
embedDiagrams: opts.embedDiagrams,
|
|
74
|
+
// forward labelMode for embedded diagrams (default friendly)
|
|
75
|
+
labelMode: opts.labelMode ?? "friendly",
|
|
76
|
+
relationshipLayout: opts.relationshipLayout,
|
|
77
|
+
refinementLayout: opts.refinementLayout,
|
|
78
|
+
decisionLayout: opts.decisionLayout,
|
|
79
|
+
dependencyLayout: opts.dependencyLayout,
|
|
80
|
+
});
|
|
40
81
|
if (form === "single-file") {
|
|
41
82
|
console.log(`Written to ${outputPath}`);
|
|
42
83
|
}
|
|
@@ -4,5 +4,5 @@ declare const optsSchema: z.ZodObject<{
|
|
|
4
4
|
input: z.ZodString;
|
|
5
5
|
output: z.ZodString;
|
|
6
6
|
}, z.core.$strict>;
|
|
7
|
-
export declare const md2jsonCommand: CommandDef<z.ZodObject
|
|
7
|
+
export declare const md2jsonCommand: CommandDef<z.ZodObject, typeof optsSchema>;
|
|
8
8
|
export {};
|
|
@@ -23,5 +23,5 @@ declare const syncOpts: z.ZodObject<{
|
|
|
23
23
|
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
24
24
|
report: z.ZodOptional<z.ZodBoolean>;
|
|
25
25
|
}, z.core.$strict>;
|
|
26
|
-
export declare const syncCommandDef: CommandDef<z.ZodObject
|
|
26
|
+
export declare const syncCommandDef: CommandDef<z.ZodObject, typeof syncOpts>;
|
|
27
27
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
/** Definition of a CLI command — name, description, Zod schemas for args/opts, optional subcommands, and action handler. */
|
|
4
|
-
export interface CommandDef<TArgs extends z.ZodObject
|
|
4
|
+
export interface CommandDef<TArgs extends z.ZodObject = z.ZodObject, TOpts extends z.ZodObject = z.ZodObject> {
|
|
5
5
|
name: string;
|
|
6
6
|
description: string;
|
|
7
7
|
args?: TArgs;
|