sysprom 1.17.0 → 1.19.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 +198 -87
- 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 +22 -7
- 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,51 +23,100 @@ 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
|
|
39
83
|
sysprom query trace I1
|
|
40
84
|
sysprom query timeline
|
|
41
|
-
sysprom query state-at
|
|
85
|
+
sysprom query state-at <ISO-timestamp>
|
|
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
|
|
|
68
117
|
## MCP Server
|
|
69
118
|
|
|
70
|
-
SysProM includes an MCP (Model Context Protocol) server exposing
|
|
119
|
+
SysProM includes an MCP (Model Context Protocol) server exposing tools over stdio transport. Any MCP-compatible agent — Cursor, Windsurf, VS Code Copilot, Cline, or custom clients — can use it.
|
|
71
120
|
|
|
72
121
|
### Configuration
|
|
73
122
|
|
|
@@ -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,18 +221,71 @@ 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?
|
|
184
245
|
|
|
185
246
|
SysProM models systems as directed graphs across abstraction layers — intent, concept, capability, structure, and realisation — with explicit decisions, changes, and invariants. It is domain-agnostic, format-agnostic, and recursively composable.
|
|
186
247
|
|
|
248
|
+
## System Provenance Profile
|
|
249
|
+
|
|
250
|
+
For product repositories, use SysProM to model the specification, design, and implementation of the system being built.
|
|
251
|
+
|
|
252
|
+
Recommended node usage:
|
|
253
|
+
|
|
254
|
+
- `intent`: user outcomes, business goals, and product promises
|
|
255
|
+
- `concept`: domain concepts, behavioural boundaries, and system rules
|
|
256
|
+
- `capability`: user-visible or externally meaningful system behaviours
|
|
257
|
+
- `element`: architectural components, services, stores, queues, and UI surfaces
|
|
258
|
+
- `realisation`: implementation units such as packages, modules, handlers, schemas, and jobs
|
|
259
|
+
- `protocol`: workflows and lifecycle paths such as review, publish, sync, or ingestion flows
|
|
260
|
+
- `artefact`: API contracts, documents, prompts, tests, migrations, and generated outputs
|
|
261
|
+
- `decision`: selected trade-offs and architectural choices
|
|
262
|
+
- `change`: implementation slices or delivery units
|
|
263
|
+
- `role`: human or system actors
|
|
264
|
+
- `view`: curated slices such as specification, architecture, implementation, and operations
|
|
265
|
+
|
|
266
|
+
Recommended trace chain:
|
|
267
|
+
|
|
268
|
+
```text
|
|
269
|
+
intent -> concept -> capability -> element -> realisation -> artefact
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Recommended relationship usage:
|
|
273
|
+
|
|
274
|
+
- `refines`: tighten intent into concepts and concepts into capabilities
|
|
275
|
+
- `part_of`: decompose concepts, protocols, capabilities, and architecture structures
|
|
276
|
+
- `realises`: connect design structures to implementation structures
|
|
277
|
+
- `produces`: connect capabilities or stages to the artefacts they generate
|
|
278
|
+
- `performs`: connect roles to capabilities, stages, protocols, and operational concepts
|
|
279
|
+
- `governed_by` / `constrained_by`: express rules, policies, and invariants on design and implementation
|
|
280
|
+
- `implements` / `modifies`: connect delivery changes to the nodes they implement or alter
|
|
281
|
+
- `affects` + `must_preserve`: connect decisions to impacted areas and their protected invariants
|
|
282
|
+
|
|
283
|
+
Recommended implementation provenance:
|
|
284
|
+
|
|
285
|
+
- use `external_references` on `realisation` nodes to point to code paths, packages, handlers, or schemas
|
|
286
|
+
- use `external_references` on `artefact` nodes to point to API definitions, test files, migrations, docs, PRs, and generated outputs
|
|
287
|
+
- use `status`, `scope`, and decision/change links so the graph can answer both “what is the design?” and “what has actually been built?”
|
|
288
|
+
|
|
187
289
|
## How SysProM Compares
|
|
188
290
|
|
|
189
291
|
<table>
|
|
@@ -302,7 +404,7 @@ sysprom md2json --input ./.SysProM --output .SysProM.json
|
|
|
302
404
|
|
|
303
405
|
## Claude Code Plugin
|
|
304
406
|
|
|
305
|
-
SysProM is available as a Claude Code plugin with
|
|
407
|
+
SysProM is available as a Claude Code plugin with skills for managing provenance documents. The plugin is defined in `.claude-plugin/marketplace.json` with skills in `.claude/skills/`.
|
|
306
408
|
|
|
307
409
|
### Install from Marketplace
|
|
308
410
|
|
|
@@ -322,49 +424,58 @@ When working on the SysProM repo itself, skills in `.claude/skills/` are auto-di
|
|
|
322
424
|
|
|
323
425
|
### Skills by Category
|
|
324
426
|
|
|
325
|
-
**Node Creation
|
|
427
|
+
**Node Creation**
|
|
428
|
+
|
|
326
429
|
- `add-decision` — Create decision nodes with context, options, rationale, and invariant links
|
|
327
430
|
- `add-change` — Create change nodes with scope, operations, and task tracking
|
|
328
431
|
- `add-invariant` — Create invariant nodes representing system rules and constraints
|
|
329
432
|
- `add-node` — Generic node creation for any SysProM type
|
|
330
433
|
|
|
331
|
-
**Node Modification
|
|
434
|
+
**Node Modification**
|
|
435
|
+
|
|
332
436
|
- `update-node` — Modify node fields, status, lifecycle, context, or rationale
|
|
333
437
|
- `remove-node` — Delete nodes with safety flags (hard delete, recursive, repair)
|
|
334
438
|
- `rename-node` — Rename node IDs across all references
|
|
335
439
|
|
|
336
|
-
**Relationships
|
|
440
|
+
**Relationships**
|
|
441
|
+
|
|
337
442
|
- `add-relationship` — Create relationships between nodes with specific types
|
|
338
443
|
- `remove-relationship` — Delete relationships
|
|
339
444
|
|
|
340
|
-
**Query & Analysis
|
|
445
|
+
**Query & Analysis**
|
|
446
|
+
|
|
341
447
|
- `query-nodes` — Search nodes by type, status, text, or ID
|
|
342
448
|
- `query-relationships` — Query relationships by source, target, or type
|
|
343
449
|
- `trace-node` — Trace refinement chains through abstraction layers
|
|
344
450
|
- `check-document` — Validate document structure and report issues
|
|
345
451
|
- `stats` — Show document statistics and composition metrics
|
|
346
452
|
|
|
347
|
-
**Visualisation
|
|
453
|
+
**Visualisation**
|
|
454
|
+
|
|
348
455
|
- `graph` — Generate Mermaid or DOT graphs with filtering
|
|
349
456
|
|
|
350
|
-
**Format Conversion
|
|
457
|
+
**Format Conversion**
|
|
458
|
+
|
|
351
459
|
- `init-document` — Create new SysProM documents with metadata
|
|
352
460
|
- `json-to-markdown` — Convert JSON to Markdown format
|
|
353
461
|
- `markdown-to-json` — Convert Markdown to JSON format
|
|
354
462
|
- `sync-formats` — Bidirectional sync between JSON and Markdown
|
|
355
463
|
|
|
356
|
-
**Spec-Kit Integration
|
|
464
|
+
**Spec-Kit Integration**
|
|
465
|
+
|
|
357
466
|
- `speckit-import` — Import Spec-Kit features as SysProM nodes
|
|
358
467
|
- `speckit-export` — Export SysProM nodes to Spec-Kit format
|
|
359
468
|
- `speckit-sync` — Bidirectional sync with Spec-Kit specifications
|
|
360
469
|
- `speckit-diff` — Show differences between SysProM and Spec-Kit
|
|
361
470
|
|
|
362
|
-
**Task Management
|
|
471
|
+
**Task Management**
|
|
472
|
+
|
|
363
473
|
- `task-list` — List tasks in a change node with progress
|
|
364
474
|
- `task-add` — Add tasks to a change
|
|
365
475
|
- `task-mark-done` — Mark tasks as complete
|
|
366
476
|
|
|
367
|
-
**Plan Management
|
|
477
|
+
**Plan Management**
|
|
478
|
+
|
|
368
479
|
- `plan-init` — Initialise plans with phases and gates
|
|
369
480
|
- `plan-status` — Show plan progress and phase gates
|
|
370
481
|
|
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;
|