sysprom 1.21.1 → 1.22.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/dist/schema.json +0 -31
- package/dist/src/cli/commands/plan.js +54 -3
- package/dist/src/cli/commands/speckit.js +0 -1
- package/dist/src/cli/program.js +0 -2
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/json-to-md.js +0 -8
- package/dist/src/mcp/server.js +0 -1
- package/dist/src/md-to-json.js +0 -10
- package/dist/src/operations/add-node.d.ts +0 -51
- package/dist/src/operations/add-relationship.d.ts +0 -34
- package/dist/src/operations/check.d.ts +0 -17
- package/dist/src/operations/graph-decision.d.ts +0 -17
- package/dist/src/operations/graph-dependency.d.ts +0 -17
- package/dist/src/operations/graph-refinement.d.ts +0 -17
- package/dist/src/operations/graph.d.ts +0 -17
- package/dist/src/operations/index.d.ts +3 -5
- package/dist/src/operations/index.js +3 -5
- package/dist/src/operations/infer-completeness.d.ts +0 -17
- package/dist/src/operations/infer-completeness.js +0 -4
- package/dist/src/operations/infer-derived.d.ts +0 -17
- package/dist/src/operations/infer-impact.d.ts +0 -119
- package/dist/src/operations/infer-lifecycle.d.ts +0 -17
- package/dist/src/operations/init-document.d.ts +0 -17
- package/dist/src/operations/json-to-markdown.d.ts +0 -17
- package/dist/src/operations/markdown-to-json.d.ts +0 -17
- package/dist/src/operations/next-id.d.ts +0 -17
- package/dist/src/operations/node-history.d.ts +0 -17
- package/dist/src/operations/plan-add-task.d.ts +0 -34
- package/dist/src/operations/{mark-task-done.d.ts → plan-complete-task.d.ts} +4 -41
- package/dist/src/operations/plan-complete-task.js +18 -0
- package/dist/src/operations/plan-gate.d.ts +0 -17
- package/dist/src/operations/plan-init.d.ts +0 -17
- package/dist/src/operations/plan-progress.d.ts +18 -17
- package/dist/src/operations/plan-progress.js +6 -0
- package/dist/src/operations/{mark-task-undone.d.ts → plan-reopen-task.d.ts} +4 -41
- package/dist/src/operations/plan-reopen-task.js +18 -0
- package/dist/src/operations/{add-plan-task.d.ts → plan-start-task.d.ts} +4 -41
- package/dist/src/operations/plan-start-task.js +18 -0
- package/dist/src/operations/plan-status.d.ts +22 -17
- package/dist/src/operations/plan-status.js +8 -0
- package/dist/src/operations/query-node.d.ts +0 -51
- package/dist/src/operations/query-nodes.d.ts +0 -34
- package/dist/src/operations/query-relationships.d.ts +0 -17
- package/dist/src/operations/remove-node.d.ts +0 -51
- package/dist/src/operations/remove-relationship.d.ts +0 -34
- package/dist/src/operations/rename.d.ts +0 -34
- package/dist/src/operations/search.d.ts +0 -34
- package/dist/src/operations/speckit-diff.d.ts +0 -17
- package/dist/src/operations/speckit-export.d.ts +0 -17
- package/dist/src/operations/speckit-import.d.ts +0 -17
- package/dist/src/operations/speckit-sync.d.ts +0 -51
- package/dist/src/operations/speckit-sync.js +0 -1
- package/dist/src/operations/state-at.d.ts +0 -17
- package/dist/src/operations/stats.d.ts +0 -17
- package/dist/src/operations/sync.d.ts +0 -51
- package/dist/src/operations/timeline.d.ts +0 -17
- package/dist/src/operations/trace-from-node.d.ts +0 -51
- package/dist/src/operations/update-metadata.d.ts +0 -34
- package/dist/src/operations/update-node.d.ts +0 -58
- package/dist/src/operations/validate.d.ts +0 -17
- package/dist/src/operations/validate.js +71 -0
- package/dist/src/schema.d.ts +0 -61
- package/dist/src/schema.js +0 -11
- package/dist/src/speckit/generate.js +17 -20
- package/dist/src/speckit/index.d.ts +1 -1
- package/dist/src/speckit/index.js +1 -1
- package/dist/src/speckit/parse.d.ts +1 -1
- package/dist/src/speckit/parse.js +20 -14
- package/dist/src/speckit/plan.d.ts +29 -7
- package/dist/src/speckit/plan.js +181 -47
- package/package.json +3 -3
- package/schema.json +0 -31
- package/dist/src/cli/commands/task.d.ts +0 -2
- package/dist/src/cli/commands/task.js +0 -157
- package/dist/src/operations/add-plan-task.js +0 -29
- package/dist/src/operations/mark-task-done.js +0 -30
- package/dist/src/operations/mark-task-undone.js +0 -30
- package/dist/src/operations/task-list.d.ts +0 -288
- package/dist/src/operations/task-list.js +0 -49
- package/dist/src/operations/update-plan-task.d.ts +0 -555
- package/dist/src/operations/update-plan-task.js +0 -35
|
@@ -88,18 +88,6 @@ export declare const updateMetadataOp: import("./define-operation.js").DefinedOp
|
|
|
88
88
|
description?: string | string[] | undefined;
|
|
89
89
|
};
|
|
90
90
|
}>>;
|
|
91
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
92
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
93
|
-
is(value: unknown): value is string | string[];
|
|
94
|
-
};
|
|
95
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
96
|
-
}, z.core.$loose> & {
|
|
97
|
-
is(value: unknown): value is {
|
|
98
|
-
[x: string]: unknown;
|
|
99
|
-
description: string | string[];
|
|
100
|
-
done?: boolean | undefined;
|
|
101
|
-
};
|
|
102
|
-
}>>;
|
|
103
91
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
104
92
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
105
93
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -231,11 +219,6 @@ export declare const updateMetadataOp: import("./define-operation.js").DefinedOp
|
|
|
231
219
|
target?: string | undefined;
|
|
232
220
|
description?: string | string[] | undefined;
|
|
233
221
|
}[] | undefined;
|
|
234
|
-
plan?: {
|
|
235
|
-
[x: string]: unknown;
|
|
236
|
-
description: string | string[];
|
|
237
|
-
done?: boolean | undefined;
|
|
238
|
-
}[] | undefined;
|
|
239
222
|
propagation?: Record<string, boolean> | undefined;
|
|
240
223
|
includes?: string[] | undefined;
|
|
241
224
|
external_references?: {
|
|
@@ -362,18 +345,6 @@ export declare const updateMetadataOp: import("./define-operation.js").DefinedOp
|
|
|
362
345
|
description?: string | string[] | undefined;
|
|
363
346
|
};
|
|
364
347
|
}>>;
|
|
365
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
366
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
367
|
-
is(value: unknown): value is string | string[];
|
|
368
|
-
};
|
|
369
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
370
|
-
}, z.core.$loose> & {
|
|
371
|
-
is(value: unknown): value is {
|
|
372
|
-
[x: string]: unknown;
|
|
373
|
-
description: string | string[];
|
|
374
|
-
done?: boolean | undefined;
|
|
375
|
-
};
|
|
376
|
-
}>>;
|
|
377
348
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
378
349
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
379
350
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -505,11 +476,6 @@ export declare const updateMetadataOp: import("./define-operation.js").DefinedOp
|
|
|
505
476
|
target?: string | undefined;
|
|
506
477
|
description?: string | string[] | undefined;
|
|
507
478
|
}[] | undefined;
|
|
508
|
-
plan?: {
|
|
509
|
-
[x: string]: unknown;
|
|
510
|
-
description: string | string[];
|
|
511
|
-
done?: boolean | undefined;
|
|
512
|
-
}[] | undefined;
|
|
513
479
|
propagation?: Record<string, boolean> | undefined;
|
|
514
480
|
includes?: string[] | undefined;
|
|
515
481
|
external_references?: {
|
|
@@ -91,18 +91,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
91
91
|
description?: string | string[] | undefined;
|
|
92
92
|
};
|
|
93
93
|
}>>;
|
|
94
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
95
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
96
|
-
is(value: unknown): value is string | string[];
|
|
97
|
-
};
|
|
98
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
99
|
-
}, z.core.$loose> & {
|
|
100
|
-
is(value: unknown): value is {
|
|
101
|
-
[x: string]: unknown;
|
|
102
|
-
description: string | string[];
|
|
103
|
-
done?: boolean | undefined;
|
|
104
|
-
};
|
|
105
|
-
}>>;
|
|
106
94
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
107
95
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
108
96
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -234,11 +222,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
234
222
|
target?: string | undefined;
|
|
235
223
|
description?: string | string[] | undefined;
|
|
236
224
|
}[] | undefined;
|
|
237
|
-
plan?: {
|
|
238
|
-
[x: string]: unknown;
|
|
239
|
-
description: string | string[];
|
|
240
|
-
done?: boolean | undefined;
|
|
241
|
-
}[] | undefined;
|
|
242
225
|
propagation?: Record<string, boolean> | undefined;
|
|
243
226
|
includes?: string[] | undefined;
|
|
244
227
|
external_references?: {
|
|
@@ -347,18 +330,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
347
330
|
description?: string | string[] | undefined;
|
|
348
331
|
};
|
|
349
332
|
}>>>;
|
|
350
|
-
plan: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
351
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
352
|
-
is(value: unknown): value is string | string[];
|
|
353
|
-
};
|
|
354
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
355
|
-
}, z.core.$loose> & {
|
|
356
|
-
is(value: unknown): value is {
|
|
357
|
-
[x: string]: unknown;
|
|
358
|
-
description: string | string[];
|
|
359
|
-
done?: boolean | undefined;
|
|
360
|
-
};
|
|
361
|
-
}>>>;
|
|
362
333
|
propagation: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>>;
|
|
363
334
|
includes: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
364
335
|
external_references: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -477,18 +448,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
477
448
|
description?: string | string[] | undefined;
|
|
478
449
|
};
|
|
479
450
|
}>>;
|
|
480
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
481
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
482
|
-
is(value: unknown): value is string | string[];
|
|
483
|
-
};
|
|
484
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
485
|
-
}, z.core.$loose> & {
|
|
486
|
-
is(value: unknown): value is {
|
|
487
|
-
[x: string]: unknown;
|
|
488
|
-
description: string | string[];
|
|
489
|
-
done?: boolean | undefined;
|
|
490
|
-
};
|
|
491
|
-
}>>;
|
|
492
451
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
493
452
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
494
453
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -684,18 +643,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
684
643
|
description?: string | string[] | undefined;
|
|
685
644
|
};
|
|
686
645
|
}>>;
|
|
687
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
688
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
689
|
-
is(value: unknown): value is string | string[];
|
|
690
|
-
};
|
|
691
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
692
|
-
}, z.core.$loose> & {
|
|
693
|
-
is(value: unknown): value is {
|
|
694
|
-
[x: string]: unknown;
|
|
695
|
-
description: string | string[];
|
|
696
|
-
done?: boolean | undefined;
|
|
697
|
-
};
|
|
698
|
-
}>>;
|
|
699
646
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
700
647
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
701
648
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -827,11 +774,6 @@ export declare const updateNodeOp: import("./define-operation.js").DefinedOperat
|
|
|
827
774
|
target?: string | undefined;
|
|
828
775
|
description?: string | string[] | undefined;
|
|
829
776
|
}[] | undefined;
|
|
830
|
-
plan?: {
|
|
831
|
-
[x: string]: unknown;
|
|
832
|
-
description: string | string[];
|
|
833
|
-
done?: boolean | undefined;
|
|
834
|
-
}[] | undefined;
|
|
835
777
|
propagation?: Record<string, boolean> | undefined;
|
|
836
778
|
includes?: string[] | undefined;
|
|
837
779
|
external_references?: {
|
|
@@ -104,18 +104,6 @@ export declare const validateOp: import("./define-operation.js").DefinedOperatio
|
|
|
104
104
|
description?: string | string[] | undefined;
|
|
105
105
|
};
|
|
106
106
|
}>>;
|
|
107
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
108
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
109
|
-
is(value: unknown): value is string | string[];
|
|
110
|
-
};
|
|
111
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
112
|
-
}, z.core.$loose> & {
|
|
113
|
-
is(value: unknown): value is {
|
|
114
|
-
[x: string]: unknown;
|
|
115
|
-
description: string | string[];
|
|
116
|
-
done?: boolean | undefined;
|
|
117
|
-
};
|
|
118
|
-
}>>;
|
|
119
107
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
120
108
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
121
109
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -247,11 +235,6 @@ export declare const validateOp: import("./define-operation.js").DefinedOperatio
|
|
|
247
235
|
target?: string | undefined;
|
|
248
236
|
description?: string | string[] | undefined;
|
|
249
237
|
}[] | undefined;
|
|
250
|
-
plan?: {
|
|
251
|
-
[x: string]: unknown;
|
|
252
|
-
description: string | string[];
|
|
253
|
-
done?: boolean | undefined;
|
|
254
|
-
}[] | undefined;
|
|
255
238
|
propagation?: Record<string, boolean> | undefined;
|
|
256
239
|
includes?: string[] | undefined;
|
|
257
240
|
external_references?: {
|
|
@@ -127,6 +127,77 @@ export const validateOp = defineOperation({
|
|
|
127
127
|
issues.push(`${n.id} (${n.name}): decision has no selected option`);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
const isLifecycleReached = (value) => value === true || typeof value === "string";
|
|
131
|
+
const isGateReady = (node) => {
|
|
132
|
+
if (node.type !== "gate")
|
|
133
|
+
return false;
|
|
134
|
+
const lifecycle = node.lifecycle ?? {};
|
|
135
|
+
const values = Object.values(lifecycle);
|
|
136
|
+
if (values.length === 0)
|
|
137
|
+
return false;
|
|
138
|
+
return values.every((value) => isLifecycleReached(value));
|
|
139
|
+
};
|
|
140
|
+
const globalNodeMap = new Map(input.doc.nodes.map((node) => [node.id, node]));
|
|
141
|
+
const validatePlanSubsystem = (subsystem, protocolId) => {
|
|
142
|
+
if (!subsystem)
|
|
143
|
+
return;
|
|
144
|
+
const localNodeMap = new Map(subsystem.nodes.map((node) => [node.id, node]));
|
|
145
|
+
for (const node of subsystem.nodes) {
|
|
146
|
+
if (node.type !== "change") {
|
|
147
|
+
issues.push(`${protocolId}: implementation plan contains non-change node ${node.id} (${node.type})`);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (hasLifecycleState(node, "complete")) {
|
|
151
|
+
const blockers = [];
|
|
152
|
+
for (const rel of subsystem.relationships ?? []) {
|
|
153
|
+
if (rel.from !== node.id || rel.type !== "depends_on")
|
|
154
|
+
continue;
|
|
155
|
+
const dependency = localNodeMap.get(rel.to) ?? globalNodeMap.get(rel.to);
|
|
156
|
+
if (dependency?.type !== "change") {
|
|
157
|
+
blockers.push(`dependency ${rel.to} is not a change task`);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (!hasLifecycleState(dependency, "complete")) {
|
|
161
|
+
blockers.push(`dependency ${rel.to} is not complete`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const rel of subsystem.relationships ?? []) {
|
|
165
|
+
if (rel.from !== node.id || rel.type !== "constrained_by")
|
|
166
|
+
continue;
|
|
167
|
+
const gate = localNodeMap.get(rel.to) ?? globalNodeMap.get(rel.to);
|
|
168
|
+
if (!gate || !isGateReady(gate)) {
|
|
169
|
+
blockers.push(`gate ${rel.to} is not ready`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (blockers.length > 0) {
|
|
173
|
+
issues.push(`${node.id} (${node.name}): complete task has unresolved blockers (${blockers.join(", ")})`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (node.subsystem) {
|
|
177
|
+
validatePlanSubsystem(node.subsystem, protocolId);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (const rel of subsystem.relationships ?? []) {
|
|
181
|
+
if (rel.type !== "depends_on")
|
|
182
|
+
continue;
|
|
183
|
+
const fromNode = localNodeMap.get(rel.from);
|
|
184
|
+
const toNode = localNodeMap.get(rel.to);
|
|
185
|
+
if (!fromNode || !toNode) {
|
|
186
|
+
issues.push(`${protocolId}: depends_on relationship ${rel.from} -> ${rel.to} must stay within the same plan scope`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (fromNode.type !== "change" || toNode.type !== "change") {
|
|
190
|
+
issues.push(`${protocolId}: depends_on scheduling relationship must connect change task nodes (${rel.from} -> ${rel.to})`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
for (const node of input.doc.nodes) {
|
|
195
|
+
if (node.type !== "protocol")
|
|
196
|
+
continue;
|
|
197
|
+
if (!node.id.endsWith("-PROT-IMPL"))
|
|
198
|
+
continue;
|
|
199
|
+
validatePlanSubsystem(node.subsystem, node.id);
|
|
200
|
+
}
|
|
130
201
|
return {
|
|
131
202
|
valid: issues.length === 0,
|
|
132
203
|
issues,
|
package/dist/src/schema.d.ts
CHANGED
|
@@ -202,21 +202,6 @@ export declare const Operation: z.ZodObject<{
|
|
|
202
202
|
};
|
|
203
203
|
/** An atomic operation within a change, targeting a specific node. */
|
|
204
204
|
export type Operation = z.infer<typeof Operation>;
|
|
205
|
-
/** Zod schema for a task within a change's execution plan. */
|
|
206
|
-
export declare const Task: z.ZodObject<{
|
|
207
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
208
|
-
is(value: unknown): value is string | string[];
|
|
209
|
-
};
|
|
210
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
211
|
-
}, z.core.$loose> & {
|
|
212
|
-
is(value: unknown): value is {
|
|
213
|
-
[x: string]: unknown;
|
|
214
|
-
description: string | string[];
|
|
215
|
-
done?: boolean | undefined;
|
|
216
|
-
};
|
|
217
|
-
};
|
|
218
|
-
/** A single task within a change's execution plan, with a description and done flag. */
|
|
219
|
-
export type Task = z.infer<typeof Task>;
|
|
220
205
|
/** Zod schema for an external reference — a link to a resource outside the SysProM graph. */
|
|
221
206
|
export declare const ExternalReference: z.ZodObject<{
|
|
222
207
|
role: z.ZodEnum<{
|
|
@@ -478,18 +463,6 @@ export declare const NodeBase: z.ZodObject<{
|
|
|
478
463
|
description?: string | string[] | undefined;
|
|
479
464
|
};
|
|
480
465
|
}>>;
|
|
481
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
482
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
483
|
-
is(value: unknown): value is string | string[];
|
|
484
|
-
};
|
|
485
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
486
|
-
}, z.core.$loose> & {
|
|
487
|
-
is(value: unknown): value is {
|
|
488
|
-
[x: string]: unknown;
|
|
489
|
-
description: string | string[];
|
|
490
|
-
done?: boolean | undefined;
|
|
491
|
-
};
|
|
492
|
-
}>>;
|
|
493
466
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
494
467
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
495
468
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -592,18 +565,6 @@ declare const NodeSchema: z.ZodObject<{
|
|
|
592
565
|
description?: string | string[] | undefined;
|
|
593
566
|
};
|
|
594
567
|
}>>;
|
|
595
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
596
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
597
|
-
is(value: unknown): value is string | string[];
|
|
598
|
-
};
|
|
599
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
600
|
-
}, z.core.$loose> & {
|
|
601
|
-
is(value: unknown): value is {
|
|
602
|
-
[x: string]: unknown;
|
|
603
|
-
description: string | string[];
|
|
604
|
-
done?: boolean | undefined;
|
|
605
|
-
};
|
|
606
|
-
}>>;
|
|
607
568
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
608
569
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
609
570
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -759,11 +720,6 @@ export declare const SysProMDocument: z.ZodObject<{
|
|
|
759
720
|
target?: string | undefined;
|
|
760
721
|
description?: string | string[] | undefined;
|
|
761
722
|
}[] | undefined;
|
|
762
|
-
plan?: {
|
|
763
|
-
[x: string]: unknown;
|
|
764
|
-
description: string | string[];
|
|
765
|
-
done?: boolean | undefined;
|
|
766
|
-
}[] | undefined;
|
|
767
723
|
propagation?: Record<string, boolean> | undefined;
|
|
768
724
|
includes?: string[] | undefined;
|
|
769
725
|
external_references?: {
|
|
@@ -878,18 +834,6 @@ export declare const Node: z.ZodObject<{
|
|
|
878
834
|
description?: string | string[] | undefined;
|
|
879
835
|
};
|
|
880
836
|
}>>;
|
|
881
|
-
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
882
|
-
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
883
|
-
is(value: unknown): value is string | string[];
|
|
884
|
-
};
|
|
885
|
-
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
886
|
-
}, z.core.$loose> & {
|
|
887
|
-
is(value: unknown): value is {
|
|
888
|
-
[x: string]: unknown;
|
|
889
|
-
description: string | string[];
|
|
890
|
-
done?: boolean | undefined;
|
|
891
|
-
};
|
|
892
|
-
}>>;
|
|
893
837
|
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
894
838
|
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
895
839
|
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -946,11 +890,6 @@ export declare const Node: z.ZodObject<{
|
|
|
946
890
|
target?: string | undefined;
|
|
947
891
|
description?: string | string[] | undefined;
|
|
948
892
|
}[] | undefined;
|
|
949
|
-
plan?: {
|
|
950
|
-
[x: string]: unknown;
|
|
951
|
-
description: string | string[];
|
|
952
|
-
done?: boolean | undefined;
|
|
953
|
-
}[] | undefined;
|
|
954
893
|
propagation?: Record<string, boolean> | undefined;
|
|
955
894
|
includes?: string[] | undefined;
|
|
956
895
|
external_references?: {
|
package/dist/src/schema.js
CHANGED
|
@@ -167,13 +167,6 @@ export const Operation = defineSchema(z
|
|
|
167
167
|
description: Text.optional(),
|
|
168
168
|
})
|
|
169
169
|
.describe("An atomic operation within a change."));
|
|
170
|
-
/** Zod schema for a task within a change's execution plan. */
|
|
171
|
-
export const Task = defineSchema(z
|
|
172
|
-
.looseObject({
|
|
173
|
-
description: Text,
|
|
174
|
-
done: z.boolean().default(false).optional(),
|
|
175
|
-
})
|
|
176
|
-
.describe("A single task within a change's execution plan."));
|
|
177
170
|
/** Zod schema for an external reference — a link to a resource outside the SysProM graph. */
|
|
178
171
|
export const ExternalReference = defineSchema(z
|
|
179
172
|
.object({
|
|
@@ -282,10 +275,6 @@ export const NodeBase = z
|
|
|
282
275
|
.array(Operation)
|
|
283
276
|
.describe("Operations performed. Applicable to change nodes.")
|
|
284
277
|
.optional(),
|
|
285
|
-
plan: z
|
|
286
|
-
.array(Task)
|
|
287
|
-
.describe("Execution plan as a sequence of tasks. Applicable to change nodes.")
|
|
288
|
-
.optional(),
|
|
289
278
|
propagation: z
|
|
290
279
|
.record(z.string(), z.boolean())
|
|
291
280
|
.describe("Layer propagation status. Applicable to change nodes.")
|
|
@@ -105,20 +105,12 @@ function getIdSuffix(id) {
|
|
|
105
105
|
const parts = id.split("-");
|
|
106
106
|
return parts[parts.length - 1] ?? "000";
|
|
107
107
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
* const tasks = parseTasks(changeNode);
|
|
115
|
-
* ```
|
|
116
|
-
*/
|
|
117
|
-
function parseTasks(node) {
|
|
118
|
-
return (node.plan ?? []).map((task) => ({
|
|
119
|
-
description: textToString(task.description),
|
|
120
|
-
done: task.done ?? false,
|
|
121
|
-
}));
|
|
108
|
+
function childTaskNodes(change) {
|
|
109
|
+
return (change.subsystem?.nodes ?? []).filter((n) => n.type === "change");
|
|
110
|
+
}
|
|
111
|
+
function isDone(node) {
|
|
112
|
+
return (node.lifecycle?.complete === true ||
|
|
113
|
+
typeof node.lifecycle?.complete === "string");
|
|
122
114
|
}
|
|
123
115
|
/**
|
|
124
116
|
* Format the lifecycle state for spec output: "proposed" -> "Draft", etc.
|
|
@@ -494,10 +486,10 @@ export function generateTasks(doc, prefix) {
|
|
|
494
486
|
return output.trim();
|
|
495
487
|
}
|
|
496
488
|
// Recursive helper to render a change node and its tasks, including nested child changes.
|
|
497
|
-
// Render tasks from
|
|
489
|
+
// Render tasks from child change nodes.
|
|
498
490
|
function renderPlanItems(change, taskCounter) {
|
|
499
491
|
let result = "";
|
|
500
|
-
const tasks =
|
|
492
|
+
const tasks = childTaskNodes(change);
|
|
501
493
|
for (const task of tasks) {
|
|
502
494
|
// Find capability that this change implements.
|
|
503
495
|
let usStory = null;
|
|
@@ -511,13 +503,13 @@ export function generateTasks(doc, prefix) {
|
|
|
511
503
|
usStory = getIdSuffix(implRelsDoc[0].to);
|
|
512
504
|
}
|
|
513
505
|
}
|
|
514
|
-
const checkbox = task
|
|
506
|
+
const checkbox = isDone(task) ? "[x]" : "[ ]";
|
|
515
507
|
const taskNum = String(taskCounter.value).padStart(3, "0");
|
|
516
508
|
let taskLine = `- ${checkbox} T${taskNum}`;
|
|
517
509
|
if (usStory && usStory !== "000") {
|
|
518
510
|
taskLine += ` [US${usStory}]`;
|
|
519
511
|
}
|
|
520
|
-
taskLine += ` ${
|
|
512
|
+
taskLine += ` ${task.name}`;
|
|
521
513
|
result += taskLine + "\n";
|
|
522
514
|
taskCounter.value++;
|
|
523
515
|
}
|
|
@@ -536,9 +528,14 @@ export function generateTasks(doc, prefix) {
|
|
|
536
528
|
result += "\n";
|
|
537
529
|
else
|
|
538
530
|
result += "\n\n";
|
|
539
|
-
// Recurse into child
|
|
531
|
+
// Recurse into child phase nodes only (task nodes are rendered as checkboxes above).
|
|
540
532
|
if (change.subsystem?.nodes && change.subsystem.nodes.length > 0) {
|
|
541
|
-
const childChanges = change.subsystem.nodes.filter((n) =>
|
|
533
|
+
const childChanges = change.subsystem.nodes.filter((n) => {
|
|
534
|
+
if (n.type !== "change")
|
|
535
|
+
return false;
|
|
536
|
+
const children = n.subsystem?.nodes ?? [];
|
|
537
|
+
return children.some((child) => child.type === "change");
|
|
538
|
+
});
|
|
542
539
|
for (const childChange of childChanges) {
|
|
543
540
|
result += renderChangeNode(childChange, headingLevel + 1, taskCounter);
|
|
544
541
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { detectSpecKitProject, listFeatures, getFeature, resolveConstitution, type SpecKitProject, type SpecKitFeature, } from "./project.js";
|
|
2
2
|
export { parseConstitution, parseSpec, parsePlan, parseTasks, parseChecklist, parseSpecKitFeature, type ParseResult, } from "./parse.js";
|
|
3
3
|
export { generateConstitution, generateSpec, generatePlan, generateTasks, generateChecklist, generateSpecKitProject, } from "./generate.js";
|
|
4
|
-
export { initDocument, addTask, planStatus, planProgress, checkGate, isTaskDone, countTasks, type PlanStatus, type PhaseProgress, type GateIssue, type GateResult, } from "./plan.js";
|
|
4
|
+
export { initDocument, addTask, setTaskLifecycle, planStatus, planProgress, checkGate, isTaskDone, countTasks, type PlanStatus, type PhaseProgress, type GateIssue, type GateResult, type BlockageReason, type TaskBlockage, } from "./plan.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { detectSpecKitProject, listFeatures, getFeature, resolveConstitution, } from "./project.js";
|
|
2
2
|
export { parseConstitution, parseSpec, parsePlan, parseTasks, parseChecklist, parseSpecKitFeature, } from "./parse.js";
|
|
3
3
|
export { generateConstitution, generateSpec, generatePlan, generateTasks, generateChecklist, generateSpecKitProject, } from "./generate.js";
|
|
4
|
-
export { initDocument, addTask, planStatus, planProgress, checkGate, isTaskDone, countTasks, } from "./plan.js";
|
|
4
|
+
export { initDocument, addTask, setTaskLifecycle, planStatus, planProgress, checkGate, isTaskDone, countTasks, } from "./plan.js";
|
|
@@ -40,7 +40,7 @@ export declare function parseSpec(content: string, idPrefix: string): ParseResul
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function parsePlan(content: string, idPrefix: string): ParseResult;
|
|
42
42
|
/**
|
|
43
|
-
* Parse a Spec-Kit tasks file into SysProM change nodes with task
|
|
43
|
+
* Parse a Spec-Kit tasks file into SysProM change nodes with nested task nodes.
|
|
44
44
|
* @param content - Markdown file content.
|
|
45
45
|
* @param idPrefix - ID prefix for generated nodes.
|
|
46
46
|
* @returns The result.
|
|
@@ -580,7 +580,7 @@ export function parsePlan(content, idPrefix) {
|
|
|
580
580
|
// tasks.md parser
|
|
581
581
|
// ---------------------------------------------------------------------------
|
|
582
582
|
/**
|
|
583
|
-
* Parse a Spec-Kit tasks file into SysProM change nodes with task
|
|
583
|
+
* Parse a Spec-Kit tasks file into SysProM change nodes with nested task nodes.
|
|
584
584
|
* @param content - Markdown file content.
|
|
585
585
|
* @param idPrefix - ID prefix for generated nodes.
|
|
586
586
|
* @returns The result.
|
|
@@ -631,21 +631,27 @@ export function parseTasks(content, idPrefix) {
|
|
|
631
631
|
}
|
|
632
632
|
}
|
|
633
633
|
}
|
|
634
|
-
|
|
635
|
-
|
|
634
|
+
const toTaskNode = (parentId, index, task) => ({
|
|
635
|
+
id: `${parentId}-${String(index + 1)}`,
|
|
636
|
+
type: "change",
|
|
637
|
+
name: task.text,
|
|
638
|
+
lifecycle: task.done ? { complete: true } : { proposed: true },
|
|
639
|
+
});
|
|
640
|
+
// Create change nodes for each phase (with local IDs in subsystem)
|
|
641
|
+
// Use numeric indices (CHG-1, CHG-2, etc.) for phase changes.
|
|
636
642
|
for (let i = 0; i < phases.length; i++) {
|
|
637
643
|
const phase = phases[i];
|
|
638
644
|
const tasks = changesByPhase[phase.phaseNum] ?? [];
|
|
639
|
-
const plan = tasks.map((t) => ({
|
|
640
|
-
description: t.text,
|
|
641
|
-
done: t.done,
|
|
642
|
-
}));
|
|
643
645
|
const changeLocalId = `CHG-${String(phase.phaseNum)}`;
|
|
644
646
|
subsystemNodes.push({
|
|
645
647
|
id: changeLocalId,
|
|
646
648
|
type: "change",
|
|
647
649
|
name: phase.title,
|
|
648
|
-
|
|
650
|
+
lifecycle: { introduced: true },
|
|
651
|
+
subsystem: {
|
|
652
|
+
nodes: tasks.map((task, index) => toTaskNode(changeLocalId, index, task)),
|
|
653
|
+
relationships: [],
|
|
654
|
+
},
|
|
649
655
|
});
|
|
650
656
|
// Wire must_follow between consecutive phase changes
|
|
651
657
|
if (i > 0) {
|
|
@@ -657,18 +663,18 @@ export function parseTasks(content, idPrefix) {
|
|
|
657
663
|
});
|
|
658
664
|
}
|
|
659
665
|
}
|
|
660
|
-
// Create change nodes for user stories (with
|
|
666
|
+
// Create change nodes for user stories (with local IDs in subsystem)
|
|
661
667
|
for (const [storyKey, tasks] of Object.entries(changesByStory)) {
|
|
662
|
-
const plan = tasks.map((t) => ({
|
|
663
|
-
description: t.text,
|
|
664
|
-
done: t.done,
|
|
665
|
-
}));
|
|
666
668
|
const changeLocalId = `CHG-${storyKey}`;
|
|
667
669
|
subsystemNodes.push({
|
|
668
670
|
id: changeLocalId,
|
|
669
671
|
type: "change",
|
|
670
672
|
name: storyKey,
|
|
671
|
-
|
|
673
|
+
lifecycle: { introduced: true },
|
|
674
|
+
subsystem: {
|
|
675
|
+
nodes: tasks.map((task, index) => toTaskNode(changeLocalId, index, task)),
|
|
676
|
+
relationships: [],
|
|
677
|
+
},
|
|
672
678
|
});
|
|
673
679
|
// Link to the capability at the top level (using GLOBAL ID format)
|
|
674
680
|
const changeGlobalId = `${idPrefix}-CHG-${storyKey}`;
|
|
@@ -17,6 +17,8 @@ export interface PlanStatus {
|
|
|
17
17
|
tasks: {
|
|
18
18
|
total: number;
|
|
19
19
|
done: number;
|
|
20
|
+
blocked: number;
|
|
21
|
+
blockedTasks: TaskBlockage[];
|
|
20
22
|
};
|
|
21
23
|
checklist: {
|
|
22
24
|
defined: boolean;
|
|
@@ -28,10 +30,13 @@ export interface PlanStatus {
|
|
|
28
30
|
/** Per-phase progress metrics — task counts and completion percentage. */
|
|
29
31
|
export interface PhaseProgress {
|
|
30
32
|
phase: number;
|
|
33
|
+
id: string;
|
|
31
34
|
name: string;
|
|
32
35
|
done: number;
|
|
33
36
|
total: number;
|
|
34
37
|
percent: number;
|
|
38
|
+
blocked: boolean;
|
|
39
|
+
blockageReasons: BlockageReason[];
|
|
35
40
|
}
|
|
36
41
|
/** A specific issue preventing gate entry — incomplete tasks, missing acceptance criteria, or unlinked requirements. */
|
|
37
42
|
export type GateIssue = {
|
|
@@ -58,6 +63,18 @@ export interface GateResult {
|
|
|
58
63
|
export interface TaskCount {
|
|
59
64
|
total: number;
|
|
60
65
|
done: number;
|
|
66
|
+
blocked: number;
|
|
67
|
+
blockedTasks: TaskBlockage[];
|
|
68
|
+
}
|
|
69
|
+
/** Why a task is blocked. */
|
|
70
|
+
export interface BlockageReason {
|
|
71
|
+
kind: "dependency_unmet" | "gate_not_ready";
|
|
72
|
+
nodeId: string;
|
|
73
|
+
}
|
|
74
|
+
/** Blockage detail for a specific task. */
|
|
75
|
+
export interface TaskBlockage {
|
|
76
|
+
taskId: string;
|
|
77
|
+
reasons: BlockageReason[];
|
|
61
78
|
}
|
|
62
79
|
/**
|
|
63
80
|
* Scaffold a new SysProMDocument with the standard spec-kit-compatible node
|
|
@@ -106,18 +123,22 @@ export declare function initDocument(prefix: string, name: string): SysProMDocum
|
|
|
106
123
|
* ```
|
|
107
124
|
*/
|
|
108
125
|
export declare function addTask(doc: SysProMDocument, prefix: string, name?: string, parentId?: string): SysProMDocument;
|
|
126
|
+
type TaskLifecycleAction = "start" | "complete" | "reopen";
|
|
109
127
|
/**
|
|
110
|
-
*
|
|
128
|
+
* Set lifecycle state on a task (change node) within a plan implementation protocol.
|
|
111
129
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
|
|
130
|
+
* - start: marks introduced + in_progress true
|
|
131
|
+
* - complete: marks complete true and clears in_progress
|
|
132
|
+
* - reopen: clears complete and marks in_progress true
|
|
133
|
+
*/
|
|
134
|
+
export declare function setTaskLifecycle(doc: SysProMDocument, prefix: string, taskId: string, action: TaskLifecycleAction): SysProMDocument;
|
|
135
|
+
/**
|
|
136
|
+
* Check if a task change node is complete.
|
|
116
137
|
* @param node - The change node to evaluate.
|
|
117
|
-
* @returns Whether
|
|
138
|
+
* @returns Whether the task lifecycle includes complete.
|
|
118
139
|
* @example
|
|
119
140
|
* ```ts
|
|
120
|
-
* isTaskDone(changeNode); // => true
|
|
141
|
+
* isTaskDone(changeNode); // => true when lifecycle.complete is reached
|
|
121
142
|
* ```
|
|
122
143
|
*/
|
|
123
144
|
export declare function isTaskDone(node: Node): boolean;
|
|
@@ -178,3 +199,4 @@ export declare function planProgress(doc: SysProMDocument, prefix: string): Phas
|
|
|
178
199
|
* ```
|
|
179
200
|
*/
|
|
180
201
|
export declare function checkGate(doc: SysProMDocument, prefix: string, phase: number): GateResult;
|
|
202
|
+
export {};
|