@fission-ai/openspec 1.13.0 → 1.13.2
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 +16 -4
- package/dist/commands/change.js +12 -1
- package/dist/commands/config.d.ts +9 -0
- package/dist/commands/config.js +161 -22
- package/dist/commands/feedback.js +6 -4
- package/dist/commands/schema.js +30 -9
- package/dist/commands/store.js +5 -2
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.js +63 -1
- package/dist/commands/workflow/instructions.js +69 -22
- package/dist/commands/workflow/new-change.js +20 -0
- package/dist/commands/workflow/shared.d.ts +5 -0
- package/dist/commands/workflow/shared.js +8 -0
- package/dist/commands/workflow/status.d.ts +5 -1
- package/dist/commands/workflow/status.js +42 -5
- package/dist/core/archive.js +260 -77
- package/dist/core/artifact-graph/outputs.d.ts +1 -1
- package/dist/core/artifact-graph/outputs.js +38 -8
- package/dist/core/artifact-graph/schema.d.ts +14 -0
- package/dist/core/artifact-graph/schema.js +52 -0
- package/dist/core/artifact-graph/types.js +12 -1
- package/dist/core/change-status-policy.d.ts +14 -0
- package/dist/core/change-status-policy.js +14 -6
- package/dist/core/command-generation/adapters/continue.js +4 -0
- package/dist/core/command-generation/adapters/kilocode.d.ts +1 -1
- package/dist/core/command-generation/adapters/kilocode.js +2 -2
- package/dist/core/command-generation/generator.js +2 -0
- package/dist/core/completion-tip.js +7 -7
- package/dist/core/completions/installers/bash-installer.js +15 -7
- package/dist/core/completions/installers/shell-quote.d.ts +11 -0
- package/dist/core/completions/installers/shell-quote.js +13 -0
- package/dist/core/completions/installers/zsh-installer.js +3 -2
- package/dist/core/config-schema.d.ts +1 -1
- package/dist/core/config.d.ts +16 -0
- package/dist/core/config.js +27 -1
- package/dist/core/global-config.d.ts +30 -2
- package/dist/core/global-config.js +57 -3
- package/dist/core/init.js +22 -6
- package/dist/core/legacy-cleanup.d.ts +5 -1
- package/dist/core/legacy-cleanup.js +207 -14
- package/dist/core/list.js +55 -11
- package/dist/core/migration.js +6 -1
- package/dist/core/parsers/change-parser.d.ts +12 -1
- package/dist/core/parsers/change-parser.js +85 -87
- package/dist/core/parsers/markdown-parser.js +4 -3
- package/dist/core/parsers/requirement-blocks.d.ts +78 -6
- package/dist/core/parsers/requirement-blocks.js +155 -38
- package/dist/core/parsers/requirement-text.d.ts +13 -2
- package/dist/core/parsers/requirement-text.js +34 -7
- package/dist/core/parsers/spec-structure.js +4 -1
- package/dist/core/project-config.d.ts +9 -1
- package/dist/core/project-config.js +11 -2
- package/dist/core/references.d.ts +20 -0
- package/dist/core/references.js +56 -0
- package/dist/core/shared/skill-content-equivalence.js +5 -1
- package/dist/core/shared/skill-generation.js +36 -8
- package/dist/core/shared/tool-detection.js +9 -3
- package/dist/core/specs-apply.d.ts +20 -0
- package/dist/core/specs-apply.js +101 -17
- package/dist/core/store/git.d.ts +33 -0
- package/dist/core/store/git.js +60 -6
- package/dist/core/store/operations.d.ts +1 -1
- package/dist/core/store/operations.js +32 -10
- package/dist/core/store/registry.d.ts +2 -1
- package/dist/core/store/registry.js +5 -1
- package/dist/core/templates/optional-workflow.d.ts +69 -0
- package/dist/core/templates/optional-workflow.js +140 -0
- package/dist/core/templates/workflows/apply-change.js +18 -3
- package/dist/core/templates/workflows/archive-change.js +70 -21
- package/dist/core/templates/workflows/bulk-archive-change.js +85 -21
- package/dist/core/templates/workflows/continue-change.js +14 -4
- package/dist/core/templates/workflows/explore.js +34 -16
- package/dist/core/templates/workflows/ff-change.js +21 -5
- package/dist/core/templates/workflows/new-change.js +15 -3
- package/dist/core/templates/workflows/onboard.js +76 -41
- package/dist/core/templates/workflows/project-root.d.ts +29 -0
- package/dist/core/templates/workflows/project-root.js +38 -0
- package/dist/core/templates/workflows/propose.js +22 -5
- package/dist/core/templates/workflows/sync-specs.js +40 -1
- package/dist/core/templates/workflows/update-change.js +66 -27
- package/dist/core/templates/workflows/verify-change.js +121 -49
- package/dist/core/update.d.ts +12 -0
- package/dist/core/update.js +78 -10
- package/dist/core/validation/purpose-placeholder.js +24 -9
- package/dist/core/validation/task-checkboxes.d.ts +34 -0
- package/dist/core/validation/task-checkboxes.js +181 -0
- package/dist/core/validation/validator.d.ts +53 -1
- package/dist/core/validation/validator.js +160 -45
- package/dist/core/version-check.d.ts +14 -7
- package/dist/core/version-check.js +63 -17
- package/dist/core/worksets.js +6 -4
- package/dist/prompts/searchable-multi-select.d.ts +7 -0
- package/dist/prompts/searchable-multi-select.js +35 -6
- package/dist/telemetry/config.js +14 -2
- package/dist/telemetry/index.d.ts +4 -3
- package/dist/telemetry/index.js +22 -10
- package/dist/telemetry/opt-out.d.ts +17 -0
- package/dist/telemetry/opt-out.js +27 -0
- package/dist/utils/file-system.js +20 -3
- package/dist/utils/line-endings.d.ts +34 -0
- package/dist/utils/line-endings.js +46 -0
- package/dist/utils/nested-change.d.ts +35 -0
- package/dist/utils/nested-change.js +186 -0
- package/dist/utils/spec-discovery.d.ts +20 -0
- package/dist/utils/spec-discovery.js +59 -0
- package/dist/utils/task-progress.d.ts +1 -1
- package/dist/utils/task-progress.js +38 -6
- package/package.json +5 -5
- package/schemas/spec-driven/schema.yaml +18 -3
- package/schemas/spec-driven/templates/design.md +2 -0
- package/schemas/spec-driven/templates/proposal.md +2 -0
- package/schemas/spec-driven/templates/spec.md +2 -0
- package/schemas/spec-driven/templates/tasks.md +2 -0
|
@@ -1,12 +1,25 @@
|
|
|
1
|
+
import { optionalWorkflow } from '../optional-workflow.js';
|
|
1
2
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
3
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
4
|
+
/**
|
|
5
|
+
* Archiving must merge delta specs into the main specs; the `sync` workflow is
|
|
6
|
+
* how it normally does that. A profile that selects `archive` gets `sync`
|
|
7
|
+
* injected (see getProfileWorkflows), but an install whose workflow set was
|
|
8
|
+
* read back off disk can still be missing it — in which case the merge has to
|
|
9
|
+
* happen inline rather than be handed to a workflow that is not there.
|
|
10
|
+
*/
|
|
11
|
+
const SYNC_INLINE_HANDOFF = optionalWorkflow('sync', 'run the `/opsx:sync` workflow inline (agent-driven intelligent merge)', 'perform the delta-to-main-spec merge inline yourself (agent-driven intelligent merge)');
|
|
12
|
+
const SYNC_GUARDRAIL = optionalWorkflow('sync', 'run the `/opsx:sync` workflow inline (agent-driven)', 'perform the delta-to-main-spec merge inline (agent-driven)');
|
|
2
13
|
export function getArchiveChangeSkillTemplate() {
|
|
3
14
|
return {
|
|
4
15
|
name: 'openspec-archive-change',
|
|
5
|
-
description: 'Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.',
|
|
16
|
+
description: 'Archive a completed OpenSpec change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete. Also use when the user says "openspec archive" or "opsx archive".',
|
|
6
17
|
instructions: `Archive a completed change in the experimental workflow.
|
|
7
18
|
|
|
8
19
|
${STORE_SELECTION_GUIDANCE}
|
|
9
20
|
|
|
21
|
+
${PROJECT_ROOT_GUARD}
|
|
22
|
+
|
|
10
23
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve the full path from each delta spec when resolving its main spec.
|
|
11
24
|
|
|
12
25
|
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
@@ -68,16 +81,27 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
68
81
|
|
|
69
82
|
3. **Check task completion status**
|
|
70
83
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
Run \`openspec list --json\` with the same selected-root flags and find the
|
|
85
|
+
entry in \`changes\` whose \`name\` exactly matches the selected change.
|
|
86
|
+
Require exactly one match and nonnegative integer \`totalTasks\` and
|
|
87
|
+
\`completedTasks\`, with \`completedTasks <= totalTasks\`. The CLI resolves
|
|
88
|
+
the schema's tracked task files, including custom artifact names, output
|
|
89
|
+
paths, and globs.
|
|
90
|
+
Incomplete tasks = \`totalTasks - completedTasks\`.
|
|
91
|
+
|
|
92
|
+
Do not infer task completion from artifact status or the absence of a
|
|
93
|
+
top-level \`tasks.md\`. If the lookup fails, returns invalid JSON, omits or
|
|
94
|
+
duplicates the selected change, or returns invalid counts, report the problem
|
|
95
|
+
and stop before syncing or archiving.
|
|
96
|
+
The CLI counts only \`x\`/\`X\` checkbox markers as complete;
|
|
97
|
+
other markers, including unfamiliar ones, remain incomplete.
|
|
74
98
|
|
|
75
99
|
**If incomplete tasks found:**
|
|
76
100
|
- Display warning showing count of incomplete tasks
|
|
77
101
|
- Ask the user to confirm they want to proceed
|
|
78
102
|
- Proceed if user confirms
|
|
79
103
|
|
|
80
|
-
**If
|
|
104
|
+
**If \`totalTasks\` is zero:** Proceed without a task-related warning.
|
|
81
105
|
|
|
82
106
|
4. **Assess delta spec sync state**
|
|
83
107
|
|
|
@@ -88,17 +112,23 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
88
112
|
|
|
89
113
|
**If delta specs exist:**
|
|
90
114
|
- Compare each delta spec with its corresponding main spec at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\` (use the store-aware \`planningHome.root\` from step 2, not a hardcoded repo path)
|
|
115
|
+
- A missing main spec is **not automatically** "already synced". For a new capability, the main spec is an *output* of the sync, not an input:
|
|
116
|
+
- If the delta has MODIFIED or RENAMED requirements, report that only ADDED requirements can create a new main spec and mark that capability as sync-blocked. Never invent a requirement that has no current version.
|
|
117
|
+
- Otherwise, if the delta has only REMOVED requirements and the change's \`.openspec.yaml\` declares \`retire_capabilities: true\`, the capability is already retired: count it as already synced, warn that there is nothing left to remove, and do not recreate the main spec. Apply this rule both now and when verifying a completed sync.
|
|
118
|
+
- Otherwise, if the delta has no ADDED requirements, report that no sync is possible and mark that capability as sync-blocked. For a REMOVED-only delta, warn that there is no main spec to remove from and leave the main-spec tree unchanged. \`openspec archive\` refuses the unmarked REMOVED-only case with \`Spec must have at least one requirement\`.
|
|
119
|
+
- Otherwise, count the capability as needing sync and name it in the summary (\`<capability-path>: new main spec will be created\`). If the delta also has REMOVED requirements, warn that they will be ignored because there is no main spec to remove from. The sync creates the main spec from only the delta's ADDED requirements, exactly as \`openspec archive\` does.
|
|
91
120
|
- Determine what changes would be applied (adds, modifications, removals, renames)
|
|
92
|
-
- Show a combined summary before prompting
|
|
121
|
+
- Continue assessing the remaining capabilities even when one is sync-blocked. Show a combined summary before prompting.
|
|
93
122
|
|
|
94
123
|
**Prompt options:**
|
|
95
|
-
- If
|
|
96
|
-
-
|
|
124
|
+
- If any capability is sync-blocked: explain why and offer only "Archive without syncing", "Cancel"
|
|
125
|
+
- Otherwise, if changes needed: "Sync now (recommended)", "Archive without syncing"
|
|
126
|
+
- Otherwise, if already synced: "Archive now", "Sync anyway", "Cancel"
|
|
97
127
|
|
|
98
128
|
Route on the answer:
|
|
99
129
|
- "Cancel" — stop, do not archive
|
|
100
130
|
- "Archive without syncing" or "Archive now" — proceed to archive
|
|
101
|
-
- "Sync now" or "Sync anyway" — sync, then verify (below)
|
|
131
|
+
- "Sync now" or "Sync anyway" — sync, then verify (below). Do not start any sync while a capability is sync-blocked; explain the blocker and repeat the available choices.
|
|
102
132
|
- Anything else — ask again rather than archiving
|
|
103
133
|
|
|
104
134
|
Before a selected sync writes any main spec, run
|
|
@@ -112,7 +142,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
112
142
|
|
|
113
143
|
Then run the \`openspec-sync-specs\` workflow inline (agent-driven intelligent merge) for change '<name>', passing the delta spec analysis and the fetched specs-rule snapshot from above, and wait for it to finish. The inline sync must reuse that snapshot without fetching \`specs\` instructions again. Do not delegate it to a background task — step 5 would move \`changeRoot\` out from under a sync that is still reading it, leaving the change archived and the main specs never updated. If your agent can only run it by delegation, delegate synchronously and wait for the result.
|
|
114
144
|
|
|
115
|
-
Then re-run the comparison from the top of this step against every capability that has a delta spec in \`artifactPaths.specs.existingOutputPaths\` — not only the ones the sync reports it touched. A successful sync leaves nothing left to apply, so each capability must now read as already synced:
|
|
145
|
+
Then re-run the comparison from the top of this step, including the explicitly retired, missing-spec case, against every capability that has a delta spec in \`artifactPaths.specs.existingOutputPaths\` — not only the ones the sync reports it touched. A successful sync leaves nothing left to apply, so each capability must now read as already synced:
|
|
116
146
|
- ADDED requirements present
|
|
117
147
|
- MODIFIED requirements carrying the scenario and description changes named in the delta, with their other scenarios intact
|
|
118
148
|
- REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving \`## Requirements\` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match
|
|
@@ -188,6 +218,8 @@ export function getOpsxArchiveCommandTemplate() {
|
|
|
188
218
|
|
|
189
219
|
${STORE_SELECTION_GUIDANCE}
|
|
190
220
|
|
|
221
|
+
${PROJECT_ROOT_GUARD}
|
|
222
|
+
|
|
191
223
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve the full path from each delta spec when resolving its main spec.
|
|
192
224
|
|
|
193
225
|
**Input**: Optionally specify a change name after \`/opsx:archive\` (e.g., \`/opsx:archive add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
@@ -249,16 +281,27 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
249
281
|
|
|
250
282
|
3. **Check task completion status**
|
|
251
283
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
284
|
+
Run \`openspec list --json\` with the same selected-root flags and find the
|
|
285
|
+
entry in \`changes\` whose \`name\` exactly matches the selected change.
|
|
286
|
+
Require exactly one match and nonnegative integer \`totalTasks\` and
|
|
287
|
+
\`completedTasks\`, with \`completedTasks <= totalTasks\`. The CLI resolves
|
|
288
|
+
the schema's tracked task files, including custom artifact names, output
|
|
289
|
+
paths, and globs.
|
|
290
|
+
Incomplete tasks = \`totalTasks - completedTasks\`.
|
|
291
|
+
|
|
292
|
+
Do not infer task completion from artifact status or the absence of a
|
|
293
|
+
top-level \`tasks.md\`. If the lookup fails, returns invalid JSON, omits or
|
|
294
|
+
duplicates the selected change, or returns invalid counts, report the problem
|
|
295
|
+
and stop before syncing or archiving.
|
|
296
|
+
The CLI counts only \`x\`/\`X\` checkbox markers as complete;
|
|
297
|
+
other markers, including unfamiliar ones, remain incomplete.
|
|
255
298
|
|
|
256
299
|
**If incomplete tasks found:**
|
|
257
300
|
- Display warning showing count of incomplete tasks
|
|
258
301
|
- Prompt user for confirmation to continue
|
|
259
302
|
- Proceed if user confirms
|
|
260
303
|
|
|
261
|
-
**If
|
|
304
|
+
**If \`totalTasks\` is zero:** Proceed without a task-related warning.
|
|
262
305
|
|
|
263
306
|
4. **Assess delta spec sync state**
|
|
264
307
|
|
|
@@ -269,17 +312,23 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
269
312
|
|
|
270
313
|
**If delta specs exist:**
|
|
271
314
|
- Compare each delta spec with its corresponding main spec at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\` (use the store-aware \`planningHome.root\` from step 2, not a hardcoded repo path)
|
|
315
|
+
- A missing main spec is **not automatically** "already synced". For a new capability, the main spec is an *output* of the sync, not an input:
|
|
316
|
+
- If the delta has MODIFIED or RENAMED requirements, report that only ADDED requirements can create a new main spec and mark that capability as sync-blocked. Never invent a requirement that has no current version.
|
|
317
|
+
- Otherwise, if the delta has only REMOVED requirements and the change's \`.openspec.yaml\` declares \`retire_capabilities: true\`, the capability is already retired: count it as already synced, warn that there is nothing left to remove, and do not recreate the main spec. Apply this rule both now and when verifying a completed sync.
|
|
318
|
+
- Otherwise, if the delta has no ADDED requirements, report that no sync is possible and mark that capability as sync-blocked. For a REMOVED-only delta, warn that there is no main spec to remove from and leave the main-spec tree unchanged. \`openspec archive\` refuses the unmarked REMOVED-only case with \`Spec must have at least one requirement\`.
|
|
319
|
+
- Otherwise, count the capability as needing sync and name it in the summary (\`<capability-path>: new main spec will be created\`). If the delta also has REMOVED requirements, warn that they will be ignored because there is no main spec to remove from. The sync creates the main spec from only the delta's ADDED requirements, exactly as \`openspec archive\` does.
|
|
272
320
|
- Determine what changes would be applied (adds, modifications, removals, renames)
|
|
273
|
-
- Show a combined summary before prompting
|
|
321
|
+
- Continue assessing the remaining capabilities even when one is sync-blocked. Show a combined summary before prompting.
|
|
274
322
|
|
|
275
323
|
**Prompt options:**
|
|
276
|
-
- If
|
|
277
|
-
-
|
|
324
|
+
- If any capability is sync-blocked: explain why and offer only "Archive without syncing", "Cancel"
|
|
325
|
+
- Otherwise, if changes needed: "Sync now (recommended)", "Archive without syncing"
|
|
326
|
+
- Otherwise, if already synced: "Archive now", "Sync anyway", "Cancel"
|
|
278
327
|
|
|
279
328
|
Route on the answer:
|
|
280
329
|
- "Cancel" — stop, do not archive
|
|
281
330
|
- "Archive without syncing" or "Archive now" — proceed to archive
|
|
282
|
-
- "Sync now" or "Sync anyway" — sync, then verify (below)
|
|
331
|
+
- "Sync now" or "Sync anyway" — sync, then verify (below). Do not start any sync while a capability is sync-blocked; explain the blocker and repeat the available choices.
|
|
283
332
|
- Anything else — ask again rather than archiving
|
|
284
333
|
|
|
285
334
|
Before a selected sync writes any main spec, run
|
|
@@ -291,9 +340,9 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
291
340
|
form of main specs produced by this merge; do not use them as archive guidance,
|
|
292
341
|
change CLI behavior, or copy the rule text into any output file.
|
|
293
342
|
|
|
294
|
-
Then
|
|
343
|
+
Then ${SYNC_INLINE_HANDOFF} for change '<name>', passing the delta spec analysis and the fetched specs-rule snapshot from above, and wait for it to finish. The inline sync must reuse that snapshot without fetching \`specs\` instructions again. Do not delegate it to a background task — step 5 would move \`changeRoot\` out from under a sync that is still reading it, leaving the change archived and the main specs never updated. If your agent can only run it by delegation, delegate synchronously and wait for the result.
|
|
295
344
|
|
|
296
|
-
Then re-run the comparison from the top of this step against every capability that has a delta spec in \`artifactPaths.specs.existingOutputPaths\` — not only the ones the sync reports it touched. A successful sync leaves nothing left to apply, so each capability must now read as already synced:
|
|
345
|
+
Then re-run the comparison from the top of this step, including the explicitly retired, missing-spec case, against every capability that has a delta spec in \`artifactPaths.specs.existingOutputPaths\` — not only the ones the sync reports it touched. A successful sync leaves nothing left to apply, so each capability must now read as already synced:
|
|
297
346
|
- ADDED requirements present
|
|
298
347
|
- MODIFIED requirements carrying the scenario and description changes named in the delta, with their other scenarios intact
|
|
299
348
|
- REMOVED requirements gone — and where this sync retired a capability (removed its last requirement, leaving \`## Requirements\` empty), its main spec deleted rather than left empty; a spec the sync deliberately kept and reported is also a match
|
|
@@ -393,7 +442,7 @@ Target archive directory already exists.
|
|
|
393
442
|
- Don't block archive on warnings - just inform and confirm
|
|
394
443
|
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
|
|
395
444
|
- Show clear summary of what happened
|
|
396
|
-
- If sync is requested,
|
|
445
|
+
- If sync is requested, ${SYNC_GUARDRAIL}
|
|
397
446
|
- Never archive while a spec sync is still in flight — run the sync inline and verify the main specs before moving \`changeRoot\`
|
|
398
447
|
- If delta specs exist, always run the sync assessment and show the combined summary before prompting
|
|
399
448
|
- Apply relevant runtime context and report conflicts; operation guidance remains advisory
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
+
import { optionalWorkflow } from '../optional-workflow.js';
|
|
1
2
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
3
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
4
|
+
/**
|
|
5
|
+
* Archiving must merge delta specs into the main specs; the `sync` workflow is
|
|
6
|
+
* how it normally does that. A profile that selects `archive` gets `sync`
|
|
7
|
+
* injected (see getProfileWorkflows), but an install whose workflow set was
|
|
8
|
+
* read back off disk can still be missing it — in which case the merge has to
|
|
9
|
+
* happen inline rather than be handed to a workflow that is not there.
|
|
10
|
+
*/
|
|
11
|
+
const SYNC_INLINE_HANDOFF = optionalWorkflow('sync', 'Run the `/opsx:sync` workflow inline (agent-driven intelligent merge)', 'Perform the delta-to-main-spec merge inline yourself (agent-driven intelligent merge)');
|
|
12
|
+
const SYNC_GUARDRAIL = optionalWorkflow('sync', 'run the `/opsx:sync` workflow inline (agent-driven)', 'perform the delta-to-main-spec merge inline (agent-driven)');
|
|
2
13
|
export function getBulkArchiveChangeSkillTemplate() {
|
|
3
14
|
return {
|
|
4
15
|
name: 'openspec-bulk-archive-change',
|
|
5
|
-
description: 'Archive multiple completed changes at once. Use when archiving several parallel changes.',
|
|
16
|
+
description: 'Archive multiple completed OpenSpec changes at once. Use when archiving several parallel changes. Also use for a plural archive request - "openspec bulk-archive", "opsx bulk-archive", "openspec archive all", or "openspec archive these changes".',
|
|
6
17
|
instructions: `Archive multiple completed changes in a single operation.
|
|
7
18
|
|
|
8
19
|
This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented.
|
|
9
20
|
|
|
10
21
|
${STORE_SELECTION_GUIDANCE}
|
|
11
22
|
|
|
23
|
+
${PROJECT_ROOT_GUARD}
|
|
24
|
+
|
|
12
25
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve the full path from each delta spec when resolving its main spec.
|
|
13
26
|
|
|
14
27
|
**Input**: None required (prompts for selection)
|
|
@@ -24,7 +37,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
24
37
|
2. **Prompt for change selection**
|
|
25
38
|
|
|
26
39
|
Ask the user to choose changes (multi-select):
|
|
27
|
-
- Show each change
|
|
40
|
+
- Show each change name and task status from the list output
|
|
28
41
|
- Include an option for "All changes"
|
|
29
42
|
- Allow any number of selections (1+ works, 2+ is the typical use case)
|
|
30
43
|
|
|
@@ -57,15 +70,24 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
57
70
|
|
|
58
71
|
3. **Batch validation - gather status for all selected changes**
|
|
59
72
|
|
|
73
|
+
Run \`openspec list --json\` once with the same selected-root flags for task
|
|
74
|
+
progress. If the lookup fails, returns invalid JSON, or omits any selected
|
|
75
|
+
change, contains a duplicate selected change, or returns invalid counts,
|
|
76
|
+
report the problem and stop before syncing or archiving the batch.
|
|
77
|
+
|
|
60
78
|
For each selected change, collect:
|
|
61
79
|
|
|
62
80
|
a. **Artifact status** - Run \`openspec status --change "<name>" --json\`
|
|
63
81
|
- Parse \`schemaName\`, \`artifacts\`, \`planningHome\`, \`changeRoot\`, \`artifactPaths\`, and \`actionContext\`
|
|
64
82
|
- Note which artifacts are \`done\` vs other states
|
|
65
83
|
|
|
66
|
-
b. **Task completion** -
|
|
67
|
-
-
|
|
68
|
-
-
|
|
84
|
+
b. **Task completion** - Find the \`changes\` entry from the list response whose \`name\` exactly matches this change
|
|
85
|
+
- Require nonnegative integer \`totalTasks\` and \`completedTasks\`, with \`completedTasks <= totalTasks\`
|
|
86
|
+
- Incomplete tasks = \`totalTasks - completedTasks\`
|
|
87
|
+
- The CLI resolves the schema's tracked task files, including custom artifact names, output paths, and globs
|
|
88
|
+
- Do not infer task completion from artifact status, an artifact id of \`tasks\`, or the absence of a top-level \`tasks.md\`
|
|
89
|
+
- The CLI counts only \`x\`/\`X\` checkbox markers as complete; other markers remain incomplete
|
|
90
|
+
- If \`totalTasks\` is zero, note as "No tasks"
|
|
69
91
|
|
|
70
92
|
c. **Delta specs** - Check \`artifactPaths.specs.existingOutputPaths\` from status JSON
|
|
71
93
|
- List which capability specs exist
|
|
@@ -75,6 +97,14 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
75
97
|
lookup for that change; do not infer deltas from unrelated artifacts.
|
|
76
98
|
- Evaluate this independently for every change, including mixed-schema
|
|
77
99
|
batches where some schemas have no \`specs\` artifact.
|
|
100
|
+
|
|
101
|
+
d. **Archive target** - Compute each change's target name once and record it as that change's \`<target-name>\`
|
|
102
|
+
- Use the change name as-is when it already starts with a \`YYYY-MM-DD-\` prefix; otherwise prepend the current date as \`YYYY-MM-DD-<name>\` (same rule as \`openspec archive\`)
|
|
103
|
+
- Check whether \`<planningHome.changesDir>/archive/<target-name>\` already exists
|
|
104
|
+
- If it exists, or another selected change resolves to the same target name, mark every such change \`Blocked\` with \`Archive directory already exists\`
|
|
105
|
+
- A blocked change is never synced or moved: show it as \`Blocked\` in the step 6 table, leave it out of conflict resolution (resolve its conflicts using only the other changes), and record it as Failed in step 8d
|
|
106
|
+
- Checking here, before any main spec is written, matches \`openspec archive\`: a collision found after sync would leave main specs rewritten for an archive that never happened
|
|
107
|
+
|
|
78
108
|
4. **Detect spec conflicts**
|
|
79
109
|
|
|
80
110
|
Build a map keyed by \`<capability-path>\`, the exact path relative to \`specs/\`:
|
|
@@ -147,8 +177,8 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
147
177
|
Route on the answer by intent, not by exact label — you wrote these labels,
|
|
148
178
|
so match what the user picked rather than the wording above:
|
|
149
179
|
- "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps.
|
|
150
|
-
- The archive-everything option — proceed with every selected change
|
|
151
|
-
- The ready-only option — proceed with only the changes the step 6 table marks \`Ready\` or \`Ready*\`, and record the rest as Skipped in step 8d
|
|
180
|
+
- The archive-everything option — proceed with every selected change that is not \`Blocked\`
|
|
181
|
+
- The ready-only option — proceed with only the changes the step 6 table marks \`Ready\` or \`Ready*\`, and record the rest as Skipped in step 8d, except \`Blocked\` changes, which stay Failed with \`Archive directory already exists\`. If a \`Ready*\` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived.
|
|
152
182
|
- Anything else — ask again rather than archiving
|
|
153
183
|
|
|
154
184
|
Before step 8 writes the first main spec or moves any change, fetch every
|
|
@@ -171,7 +201,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
171
201
|
Process changes in the determined order (respecting conflict resolution):
|
|
172
202
|
|
|
173
203
|
a. **Sync included delta specs**:
|
|
174
|
-
- Run the
|
|
204
|
+
- ${optionalWorkflow('sync', 'Run the `openspec-sync-specs` workflow inline (agent-driven intelligent merge)', 'Perform the delta-to-main-spec merge inline yourself (agent-driven intelligent merge)')} only for changes with entries in \`includedDeltas\`, passing only the included delta paths and explicitly instructing it to ignore that change's \`excludedDeltas\`. Wait for it to finish.
|
|
175
205
|
- For conflicts, apply in resolved order.
|
|
176
206
|
- Pass that change's fetched specs-rule snapshot into inline sync; inline
|
|
177
207
|
sync must reuse it without fetching instructions again
|
|
@@ -193,13 +223,20 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
193
223
|
|
|
194
224
|
c. **Perform the archive**:
|
|
195
225
|
|
|
196
|
-
Target name: use the change
|
|
226
|
+
Target name: use the \`<target-name>\` recorded for this change in step 3d, unchanged. Never recompute it here: a batch that runs past midnight would check one date in step 3 and move to another.
|
|
227
|
+
|
|
228
|
+
**Check if target already exists:**
|
|
229
|
+
- Check again immediately before the move, even though step 3 already checked: the target can appear mid-batch
|
|
230
|
+
- If yes: record this change as Failed with \`Archive directory already exists\`, leave \`changeRoot\` where it is, report any main specs step 8a already synced for it, and continue with the remaining changes
|
|
231
|
+
- If no: move \`changeRoot\` to the archive directory
|
|
197
232
|
|
|
198
233
|
\`\`\`bash
|
|
199
234
|
mkdir -p "<planningHome.changesDir>/archive"
|
|
200
235
|
mv "<changeRoot>" "<planningHome.changesDir>/archive/<target-name>"
|
|
201
236
|
\`\`\`
|
|
202
237
|
|
|
238
|
+
**Confirm the move did not nest:** \`mv\` exits 0 even when the target appeared after the check, moving the change *inside* it. If \`<planningHome.changesDir>/archive/<target-name>/<change-directory-name>\` now exists (the last path segment of \`changeRoot\`), move that directory back to \`changeRoot\` and record this change as Failed with \`Archive directory already exists\`. Never report it as archived.
|
|
239
|
+
|
|
203
240
|
d. **Track outcome** for each change:
|
|
204
241
|
- Success: archived successfully
|
|
205
242
|
- Failed: error during archive or spec verification (record error)
|
|
@@ -314,9 +351,10 @@ No active changes found. Create a new change to get started.
|
|
|
314
351
|
- Never archive after the user cancels the confirmation — a cancelled batch archives nothing
|
|
315
352
|
- Track and report all outcomes (success/skip/fail)
|
|
316
353
|
- Preserve .openspec.yaml when moving to archive
|
|
317
|
-
- Archive directory target uses current date: YYYY-MM-DD-<name>; a name that already starts with a \`YYYY-MM-DD-\` prefix is used as-is (never stack a second date)
|
|
354
|
+
- Archive directory target uses the current date, computed once in step 3d and reused at the move: YYYY-MM-DD-<name>; a name that already starts with a \`YYYY-MM-DD-\` prefix is used as-is (never stack a second date)
|
|
318
355
|
- If archive target exists, fail that change but continue with others
|
|
319
|
-
-
|
|
356
|
+
- Check every archive target in step 3, before the first main-spec write; a change whose target exists is never synced or moved
|
|
357
|
+
- If sync is requested, ${optionalWorkflow('sync', 'run the `openspec-sync-specs` workflow inline (agent-driven)', 'perform the delta-to-main-spec merge inline (agent-driven)')} for each change with included delta specs
|
|
320
358
|
- Carry the per-delta \`includedDeltas\` and \`excludedDeltas\` decisions into execution; sync and verify only included deltas
|
|
321
359
|
- Report every excluded delta as \`sync skipped\` without treating the archive itself as skipped
|
|
322
360
|
- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\` before moving \`changeRoot\`
|
|
@@ -347,6 +385,8 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig
|
|
|
347
385
|
|
|
348
386
|
${STORE_SELECTION_GUIDANCE}
|
|
349
387
|
|
|
388
|
+
${PROJECT_ROOT_GUARD}
|
|
389
|
+
|
|
350
390
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve the full path from each delta spec when resolving its main spec.
|
|
351
391
|
|
|
352
392
|
**Input**: None required (prompts for selection)
|
|
@@ -362,7 +402,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
362
402
|
2. **Prompt for change selection**
|
|
363
403
|
|
|
364
404
|
Ask the user to choose changes (multi-select):
|
|
365
|
-
- Show each change
|
|
405
|
+
- Show each change name and task status from the list output
|
|
366
406
|
- Include an option for "All changes"
|
|
367
407
|
- Allow any number of selections (1+ works, 2+ is the typical use case)
|
|
368
408
|
|
|
@@ -395,15 +435,24 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
395
435
|
|
|
396
436
|
3. **Batch validation - gather status for all selected changes**
|
|
397
437
|
|
|
438
|
+
Run \`openspec list --json\` once with the same selected-root flags for task
|
|
439
|
+
progress. If the lookup fails, returns invalid JSON, or omits any selected
|
|
440
|
+
change, contains a duplicate selected change, or returns invalid counts,
|
|
441
|
+
report the problem and stop before syncing or archiving the batch.
|
|
442
|
+
|
|
398
443
|
For each selected change, collect:
|
|
399
444
|
|
|
400
445
|
a. **Artifact status** - Run \`openspec status --change "<name>" --json\`
|
|
401
446
|
- Parse \`schemaName\`, \`artifacts\`, \`planningHome\`, \`changeRoot\`, \`artifactPaths\`, and \`actionContext\`
|
|
402
447
|
- Note which artifacts are \`done\` vs other states
|
|
403
448
|
|
|
404
|
-
b. **Task completion** -
|
|
405
|
-
-
|
|
406
|
-
-
|
|
449
|
+
b. **Task completion** - Find the \`changes\` entry from the list response whose \`name\` exactly matches this change
|
|
450
|
+
- Require nonnegative integer \`totalTasks\` and \`completedTasks\`, with \`completedTasks <= totalTasks\`
|
|
451
|
+
- Incomplete tasks = \`totalTasks - completedTasks\`
|
|
452
|
+
- The CLI resolves the schema's tracked task files, including custom artifact names, output paths, and globs
|
|
453
|
+
- Do not infer task completion from artifact status, an artifact id of \`tasks\`, or the absence of a top-level \`tasks.md\`
|
|
454
|
+
- The CLI counts only \`x\`/\`X\` checkbox markers as complete; other markers remain incomplete
|
|
455
|
+
- If \`totalTasks\` is zero, note as "No tasks"
|
|
407
456
|
|
|
408
457
|
c. **Delta specs** - Check \`artifactPaths.specs.existingOutputPaths\` from status JSON
|
|
409
458
|
- List which capability specs exist
|
|
@@ -414,6 +463,13 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
414
463
|
- Evaluate this independently for every change, including mixed-schema
|
|
415
464
|
batches where some schemas have no \`specs\` artifact.
|
|
416
465
|
|
|
466
|
+
d. **Archive target** - Compute each change's target name once and record it as that change's \`<target-name>\`
|
|
467
|
+
- Use the change name as-is when it already starts with a \`YYYY-MM-DD-\` prefix; otherwise prepend the current date as \`YYYY-MM-DD-<name>\` (same rule as \`openspec archive\`)
|
|
468
|
+
- Check whether \`<planningHome.changesDir>/archive/<target-name>\` already exists
|
|
469
|
+
- If it exists, or another selected change resolves to the same target name, mark every such change \`Blocked\` with \`Archive directory already exists\`
|
|
470
|
+
- A blocked change is never synced or moved: show it as \`Blocked\` in the step 6 table, leave it out of conflict resolution (resolve its conflicts using only the other changes), and record it as Failed in step 8d
|
|
471
|
+
- Checking here, before any main spec is written, matches \`openspec archive\`: a collision found after sync would leave main specs rewritten for an archive that never happened
|
|
472
|
+
|
|
417
473
|
4. **Detect spec conflicts**
|
|
418
474
|
|
|
419
475
|
Build a map keyed by \`<capability-path>\`, the exact path relative to \`specs/\`:
|
|
@@ -486,8 +542,8 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
486
542
|
Route on the answer by intent, not by exact label — you wrote these labels,
|
|
487
543
|
so match what the user picked rather than the wording above:
|
|
488
544
|
- "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps.
|
|
489
|
-
- The archive-everything option — proceed with every selected change
|
|
490
|
-
- The ready-only option — proceed with only the changes the step 6 table marks \`Ready\` or \`Ready*\`, and record the rest as Skipped in step 8d
|
|
545
|
+
- The archive-everything option — proceed with every selected change that is not \`Blocked\`
|
|
546
|
+
- The ready-only option — proceed with only the changes the step 6 table marks \`Ready\` or \`Ready*\`, and record the rest as Skipped in step 8d, except \`Blocked\` changes, which stay Failed with \`Archive directory already exists\`. If a \`Ready*\` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived.
|
|
491
547
|
- Anything else — ask again rather than archiving
|
|
492
548
|
|
|
493
549
|
Before step 8 writes the first main spec or moves any change, fetch every
|
|
@@ -510,7 +566,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
510
566
|
Process changes in the determined order (respecting conflict resolution):
|
|
511
567
|
|
|
512
568
|
a. **Sync included delta specs**:
|
|
513
|
-
-
|
|
569
|
+
- ${SYNC_INLINE_HANDOFF} only for changes with entries in \`includedDeltas\`, passing only the included delta paths and explicitly instructing it to ignore that change's \`excludedDeltas\`. Wait for it to finish.
|
|
514
570
|
- For conflicts, apply in resolved order.
|
|
515
571
|
- Pass that change's fetched specs-rule snapshot into inline sync; inline
|
|
516
572
|
sync must reuse it without fetching instructions again
|
|
@@ -532,13 +588,20 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
532
588
|
|
|
533
589
|
c. **Perform the archive**:
|
|
534
590
|
|
|
535
|
-
Target name: use the change
|
|
591
|
+
Target name: use the \`<target-name>\` recorded for this change in step 3d, unchanged. Never recompute it here: a batch that runs past midnight would check one date in step 3 and move to another.
|
|
592
|
+
|
|
593
|
+
**Check if target already exists:**
|
|
594
|
+
- Check again immediately before the move, even though step 3 already checked: the target can appear mid-batch
|
|
595
|
+
- If yes: record this change as Failed with \`Archive directory already exists\`, leave \`changeRoot\` where it is, report any main specs step 8a already synced for it, and continue with the remaining changes
|
|
596
|
+
- If no: move \`changeRoot\` to the archive directory
|
|
536
597
|
|
|
537
598
|
\`\`\`bash
|
|
538
599
|
mkdir -p "<planningHome.changesDir>/archive"
|
|
539
600
|
mv "<changeRoot>" "<planningHome.changesDir>/archive/<target-name>"
|
|
540
601
|
\`\`\`
|
|
541
602
|
|
|
603
|
+
**Confirm the move did not nest:** \`mv\` exits 0 even when the target appeared after the check, moving the change *inside* it. If \`<planningHome.changesDir>/archive/<target-name>/<change-directory-name>\` now exists (the last path segment of \`changeRoot\`), move that directory back to \`changeRoot\` and record this change as Failed with \`Archive directory already exists\`. Never report it as archived.
|
|
604
|
+
|
|
542
605
|
d. **Track outcome** for each change:
|
|
543
606
|
- Success: archived successfully
|
|
544
607
|
- Failed: error during archive or spec verification (record error)
|
|
@@ -653,9 +716,10 @@ No active changes found. Create a new change to get started.
|
|
|
653
716
|
- Never archive after the user cancels the confirmation — a cancelled batch archives nothing
|
|
654
717
|
- Track and report all outcomes (success/skip/fail)
|
|
655
718
|
- Preserve .openspec.yaml when moving to archive
|
|
656
|
-
- Archive directory target uses current date: YYYY-MM-DD-<name>; a name that already starts with a \`YYYY-MM-DD-\` prefix is used as-is (never stack a second date)
|
|
719
|
+
- Archive directory target uses the current date, computed once in step 3d and reused at the move: YYYY-MM-DD-<name>; a name that already starts with a \`YYYY-MM-DD-\` prefix is used as-is (never stack a second date)
|
|
657
720
|
- If archive target exists, fail that change but continue with others
|
|
658
|
-
-
|
|
721
|
+
- Check every archive target in step 3, before the first main-spec write; a change whose target exists is never synced or moved
|
|
722
|
+
- If sync is requested, ${SYNC_GUARDRAIL} for each change with included delta specs
|
|
659
723
|
- Carry the per-delta \`includedDeltas\` and \`excludedDeltas\` decisions into execution; sync and verify only included deltas
|
|
660
724
|
- Report every excluded delta as \`sync skipped\` without treating the archive itself as skipped
|
|
661
725
|
- Never archive a change while a spec sync is still in flight — run the sync inline and verify main specs at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\` before moving \`changeRoot\`
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import { optionalWorkflow } from '../optional-workflow.js';
|
|
1
2
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
3
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
4
|
+
/**
|
|
5
|
+
* The planning-complete handoff. Neither `apply` nor `archive` is guaranteed
|
|
6
|
+
* to be installed, so each half is resolved at generation time (see
|
|
7
|
+
* optional-workflow.ts).
|
|
8
|
+
*/
|
|
9
|
+
const PLANNING_COMPLETE_HANDOFF = optionalWorkflow('apply', 'You can now implement this change with `/opsx:apply`.', 'You can now implement this change - `openspec instructions apply --change "<name>" --json` returns the tasks and how to work them.') + ' ' + optionalWorkflow('archive', 'Once implementation and any tracked work are complete, archive it with `/opsx:archive`.', 'Once implementation and any tracked work are complete, archive it with `openspec archive "<name>"`.');
|
|
2
10
|
export function getContinueChangeSkillTemplate() {
|
|
3
11
|
return {
|
|
4
12
|
name: 'openspec-continue-change',
|
|
5
|
-
description: 'Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow.',
|
|
13
|
+
description: 'Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow. Also use when the user says "openspec continue" or "opsx continue".',
|
|
6
14
|
instructions: `Continue working on a change by creating the next artifact.
|
|
7
15
|
|
|
8
16
|
${STORE_SELECTION_GUIDANCE}
|
|
9
17
|
|
|
18
|
+
${PROJECT_ROOT_GUARD}
|
|
19
|
+
|
|
10
20
|
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
11
21
|
|
|
12
22
|
**Steps**
|
|
@@ -20,7 +30,6 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
20
30
|
|
|
21
31
|
When prompting, present the top 3-4 most recently modified changes as options, showing:
|
|
22
32
|
- Change name
|
|
23
|
-
- Schema (from \`schema\` field if present, otherwise "spec-driven")
|
|
24
33
|
- Status (e.g., "0/5 tasks", "complete", "no tasks")
|
|
25
34
|
- How recently it was modified (from \`lastModified\` field)
|
|
26
35
|
|
|
@@ -124,6 +133,8 @@ export function getOpsxContinueCommandTemplate() {
|
|
|
124
133
|
|
|
125
134
|
${STORE_SELECTION_GUIDANCE}
|
|
126
135
|
|
|
136
|
+
${PROJECT_ROOT_GUARD}
|
|
137
|
+
|
|
127
138
|
**Input**: Optionally specify a change name after \`/opsx:continue\` (e.g., \`/opsx:continue add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
128
139
|
|
|
129
140
|
**Steps**
|
|
@@ -137,7 +148,6 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
137
148
|
|
|
138
149
|
When prompting, present the top 3-4 most recently modified changes as options, showing:
|
|
139
150
|
- Change name
|
|
140
|
-
- Schema (from \`schema\` field if present, otherwise "spec-driven")
|
|
141
151
|
- Status (e.g., "0/5 tasks", "complete", "no tasks")
|
|
142
152
|
- How recently it was modified (from \`lastModified\` field)
|
|
143
153
|
|
|
@@ -162,7 +172,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
162
172
|
**If all planning artifacts are complete (\`isPlanningComplete: true\`, or legacy \`isComplete: true\`)**:
|
|
163
173
|
- Congratulate the user
|
|
164
174
|
- Show final status including the schema used
|
|
165
|
-
- Suggest: "Planning is complete!
|
|
175
|
+
- Suggest: "Planning is complete! ${PLANNING_COMPLETE_HANDOFF}"
|
|
166
176
|
- STOP
|
|
167
177
|
|
|
168
178
|
---
|