@fission-ai/openspec 1.13.1 → 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 +15 -3
- package/dist/commands/workflow/instructions.js +36 -8
- package/dist/commands/workflow/shared.d.ts +5 -0
- package/dist/core/archive.js +243 -76
- package/dist/core/artifact-graph/outputs.d.ts +1 -1
- package/dist/core/artifact-graph/outputs.js +38 -8
- 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/init.js +9 -3
- package/dist/core/legacy-cleanup.d.ts +1 -1
- package/dist/core/legacy-cleanup.js +29 -4
- package/dist/core/parsers/requirement-blocks.d.ts +34 -3
- package/dist/core/parsers/requirement-blocks.js +65 -23
- package/dist/core/specs-apply.d.ts +20 -0
- package/dist/core/specs-apply.js +19 -6
- package/dist/core/templates/workflows/archive-change.js +30 -16
- package/dist/core/templates/workflows/bulk-archive-change.js +28 -14
- package/dist/core/templates/workflows/continue-change.js +0 -2
- package/dist/core/templates/workflows/explore.js +2 -2
- package/dist/core/templates/workflows/ff-change.js +2 -2
- package/dist/core/templates/workflows/onboard.js +9 -4
- package/dist/core/templates/workflows/update-change.js +21 -9
- package/dist/core/templates/workflows/verify-change.js +115 -52
- package/dist/core/update.js +20 -7
- package/dist/core/validation/purpose-placeholder.js +24 -9
- package/dist/core/validation/validator.js +6 -5
- 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/package.json +2 -2
- package/schemas/spec-driven/schema.yaml +8 -0
|
@@ -10,7 +10,7 @@ import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
|
10
10
|
const CONTINUE_SCOPE_NOTE = optionalWorkflow('continue', 'This workflow revises artifacts that already exist; `/opsx:continue` is what creates the ones that do not.', 'This workflow revises artifacts that already exist; it never creates missing ones. When an artifact is missing, `openspec status --change "<name>" --json` names the next one and `openspec instructions "<artifact-id>" --change "<name>" --json` explains how to write it.');
|
|
11
11
|
const CONTINUE_CREATE_THEM = optionalWorkflow('continue', 'point the user to `/opsx:continue` to create them', 'point the user to `openspec instructions "<artifact-id>" --change "<name>" --json` for how to create them');
|
|
12
12
|
const CONTINUE_NEXT_STEP = optionalWorkflow('continue', 'suggest `/opsx:continue` to create them', 'run `openspec status --change "<name>" --json` for the next artifact and point the user to `openspec instructions "<artifact-id>" --change "<name>" --json` for how to create it');
|
|
13
|
-
const CONTINUE_DEFERRED = optionalWorkflow('continue', 'Anything deferred to `/opsx:continue` (
|
|
13
|
+
const CONTINUE_DEFERRED = optionalWorkflow('continue', 'Anything deferred to `/opsx:continue` (artifacts with no files yet and status `ready` or `blocked`, never `skipped` artifacts)', 'Anything deferred because it does not exist yet (artifacts with no files and status `ready` or `blocked`, never `skipped` artifacts)');
|
|
14
14
|
const CONTINUE_FRONTIER = optionalWorkflow('continue', "that is `/opsx:continue`'s job", 'creating them is a separate step, outside this workflow');
|
|
15
15
|
/**
|
|
16
16
|
* `apply` and `archive` are in the `core` profile but not guaranteed in a
|
|
@@ -45,7 +45,6 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
45
45
|
|
|
46
46
|
When prompting, present the top 3-4 most recently modified changes as options, showing:
|
|
47
47
|
- Change name
|
|
48
|
-
- Schema (from \`schema\` field if present, otherwise "spec-driven")
|
|
49
48
|
- Status (e.g., "0/5 tasks", "complete", "no tasks")
|
|
50
49
|
- How recently it was modified (from \`lastModified\` field)
|
|
51
50
|
|
|
@@ -75,7 +74,13 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
75
74
|
- Read the artifact(s) the request touches and the change's other existing artifacts.
|
|
76
75
|
- Draft the requested edit in the conversation, not in files. Work out exactly what it changes; step 5 owns every write. Then check every other existing artifact against the drafted edit - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised.
|
|
77
76
|
- Note everything that is now inconsistent, missing, or contradictory.
|
|
78
|
-
- Propose revisions
|
|
77
|
+
- Propose revisions to files that already exist (\`existingOutputPaths\`). If an artifact has no existing output files and status \`ready\` or \`blocked\`, note it and ${CONTINUE_CREATE_THEM}. Leave \`skipped\` artifacts untouched; do not treat them as missing or defer them to the continue workflow.
|
|
78
|
+
- A glob artifact (e.g. \`specs/**/*.md\`) is marked \`done\` after at least one file matches, and the continue workflow only handles \`ready\` artifacts. When reconciliation identifies a missing file for a glob artifact whose \`existingOutputPaths\` is non-empty:
|
|
79
|
+
1. Run \`openspec instructions "<artifact-id>" --change "<name>" --json\` and use its \`instruction\` and \`template\`. Treat \`context\` and \`rules\` as constraints; do not copy them into the file. If instructions report \`skipped: true\`, do not create the file. Read current dependency files from disk; if a required non-skipped dependency is missing, stop and ask the user to restore it first.
|
|
80
|
+
2. Choose a concrete path inside \`changeRoot\` that matches \`artifactPaths.<id>.outputPath\` and does not already exist. Verify it remains inside \`changeRoot\` after resolving any symlinked parent directories. The glob \`resolvedOutputPath\` is not a valid target.
|
|
81
|
+
3. Include the new file in step 5's proposed revisions and create it only after the user confirms.
|
|
82
|
+
4. After confirmation, immediately before creation, refresh status and instructions. Verify the artifact is still in scope, not skipped, and partially populated; repeat the concrete-path checks above.
|
|
83
|
+
5. Use a create operation that fails if the target already exists. If \`instruction\` delegates creation to another skill or command, invoke it only if it can honor the confirmed path and these guardrails; otherwise stop. If any check fails or the confirmed draft is no longer valid, stop and reconcile with the user rather than replacing existing content or choosing a different path.
|
|
79
84
|
- If the change is already coherent, say so and propose no revisions.
|
|
80
85
|
|
|
81
86
|
5. **Confirm and apply, one artifact at a time**
|
|
@@ -88,7 +93,7 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
88
93
|
\`\`\`
|
|
89
94
|
|
|
90
95
|
6. **Point to the next step (guidance only - NEVER act on it)**
|
|
91
|
-
- Artifacts
|
|
96
|
+
- Artifacts with empty \`existingOutputPaths\` and status \`ready\` or \`blocked\` -> ${CONTINUE_NEXT_STEP}.
|
|
92
97
|
- Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; ${APPLY_DELTA_HANDOFF}.
|
|
93
98
|
- Everything done and implemented -> ${ARCHIVE_HANDOFF}.
|
|
94
99
|
|
|
@@ -96,6 +101,7 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
96
101
|
|
|
97
102
|
After each invocation, show:
|
|
98
103
|
- Which artifacts were revised (and which proposed revisions were rejected)
|
|
104
|
+
- Any file created under a glob artifact that was already partially populated
|
|
99
105
|
- ${CONTINUE_DEFERRED}
|
|
100
106
|
- Where the change stands and the recommended next command
|
|
101
107
|
|
|
@@ -103,7 +109,7 @@ After each invocation, show:
|
|
|
103
109
|
- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, ${APPLY_GUARDRAIL}.
|
|
104
110
|
- Use the artifact ids and paths reported by \`openspec status\`; never branch on hardcoded artifact names.
|
|
105
111
|
- Edit only the concrete files in \`existingOutputPaths\`; never write to a glob \`resolvedOutputPath\`.
|
|
106
|
-
- Do not advance the build frontier:
|
|
112
|
+
- Do not advance the build frontier: if an artifact has empty \`existingOutputPaths\` and status \`ready\` or \`blocked\`, ${CONTINUE_FRONTIER}. Leave \`skipped\` artifacts untouched. The only new-file scope is a confirmed concrete path under a glob artifact whose \`existingOutputPaths\` is non-empty.
|
|
107
113
|
- Confirm every edit with the user before writing.
|
|
108
114
|
- If the request changes the change's *intent* rather than refining it, ${INTENT_CHANGE_GUARDRAIL}.`,
|
|
109
115
|
license: 'MIT',
|
|
@@ -138,7 +144,6 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
138
144
|
|
|
139
145
|
When prompting, present the top 3-4 most recently modified changes as options, showing:
|
|
140
146
|
- Change name
|
|
141
|
-
- Schema (from \`schema\` field if present, otherwise "spec-driven")
|
|
142
147
|
- Status (e.g., "0/5 tasks", "complete", "no tasks")
|
|
143
148
|
- How recently it was modified (from \`lastModified\` field)
|
|
144
149
|
|
|
@@ -168,7 +173,13 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
168
173
|
- Read the artifact(s) the request touches and the change's other existing artifacts.
|
|
169
174
|
- Draft the requested edit in the conversation, not in files. Work out exactly what it changes; step 5 owns every write. Then check every other existing artifact against the drafted edit - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised.
|
|
170
175
|
- Note everything that is now inconsistent, missing, or contradictory.
|
|
171
|
-
- Propose revisions
|
|
176
|
+
- Propose revisions to files that already exist (\`existingOutputPaths\`). If an artifact has no existing output files and status \`ready\` or \`blocked\`, note it and ${CONTINUE_CREATE_THEM}. Leave \`skipped\` artifacts untouched; do not treat them as missing or defer them to the continue workflow.
|
|
177
|
+
- A glob artifact (e.g. \`specs/**/*.md\`) is marked \`done\` after at least one file matches, and the continue workflow only handles \`ready\` artifacts. When reconciliation identifies a missing file for a glob artifact whose \`existingOutputPaths\` is non-empty:
|
|
178
|
+
1. Run \`openspec instructions "<artifact-id>" --change "<name>" --json\` and use its \`instruction\` and \`template\`. Treat \`context\` and \`rules\` as constraints; do not copy them into the file. If instructions report \`skipped: true\`, do not create the file. Read current dependency files from disk; if a required non-skipped dependency is missing, stop and ask the user to restore it first.
|
|
179
|
+
2. Choose a concrete path inside \`changeRoot\` that matches \`artifactPaths.<id>.outputPath\` and does not already exist. Verify it remains inside \`changeRoot\` after resolving any symlinked parent directories. The glob \`resolvedOutputPath\` is not a valid target.
|
|
180
|
+
3. Include the new file in step 5's proposed revisions and create it only after the user confirms.
|
|
181
|
+
4. After confirmation, immediately before creation, refresh status and instructions. Verify the artifact is still in scope, not skipped, and partially populated; repeat the concrete-path checks above.
|
|
182
|
+
5. Use a create operation that fails if the target already exists. If \`instruction\` delegates creation to another skill or command, invoke it only if it can honor the confirmed path and these guardrails; otherwise stop. If any check fails or the confirmed draft is no longer valid, stop and reconcile with the user rather than replacing existing content or choosing a different path.
|
|
172
183
|
- If the change is already coherent, say so and propose no revisions.
|
|
173
184
|
|
|
174
185
|
5. **Confirm and apply, one artifact at a time**
|
|
@@ -181,7 +192,7 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
181
192
|
\`\`\`
|
|
182
193
|
|
|
183
194
|
6. **Point to the next step (guidance only - NEVER act on it)**
|
|
184
|
-
- Artifacts
|
|
195
|
+
- Artifacts with empty \`existingOutputPaths\` and status \`ready\` or \`blocked\` -> ${CONTINUE_NEXT_STEP}.
|
|
185
196
|
- Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; ${APPLY_DELTA_HANDOFF}.
|
|
186
197
|
- Everything done and implemented -> ${ARCHIVE_HANDOFF}.
|
|
187
198
|
|
|
@@ -189,6 +200,7 @@ ${CONTINUE_SCOPE_NOTE}
|
|
|
189
200
|
|
|
190
201
|
After each invocation, show:
|
|
191
202
|
- Which artifacts were revised (and which proposed revisions were rejected)
|
|
203
|
+
- Any file created under a glob artifact that was already partially populated
|
|
192
204
|
- ${CONTINUE_DEFERRED}
|
|
193
205
|
- Where the change stands and the recommended next command
|
|
194
206
|
|
|
@@ -196,7 +208,7 @@ After each invocation, show:
|
|
|
196
208
|
- Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, ${APPLY_GUARDRAIL}.
|
|
197
209
|
- Use the artifact ids and paths reported by \`openspec status\`; never branch on hardcoded artifact names.
|
|
198
210
|
- Edit only the concrete files in \`existingOutputPaths\`; never write to a glob \`resolvedOutputPath\`.
|
|
199
|
-
- Do not advance the build frontier:
|
|
211
|
+
- Do not advance the build frontier: if an artifact has empty \`existingOutputPaths\` and status \`ready\` or \`blocked\`, ${CONTINUE_FRONTIER}. Leave \`skipped\` artifacts untouched. The only new-file scope is a confirmed concrete path under a glob artifact whose \`existingOutputPaths\` is non-empty.
|
|
200
212
|
- Confirm every edit with the user before writing.
|
|
201
213
|
- If the request changes the change's *intent* rather than refining it, ${INTENT_CHANGE_GUARDRAIL}.`
|
|
202
214
|
};
|
|
@@ -21,7 +21,7 @@ ${PROJECT_ROOT_GUARD}
|
|
|
21
21
|
- Auto-select if only one active change exists
|
|
22
22
|
- If ambiguous, run \`openspec list --json\` to get available changes and ask the user to select one
|
|
23
23
|
|
|
24
|
-
When prompting, show changes
|
|
24
|
+
When prompting, show all active changes returned by the list, including changes with \`status: "no-tasks"\`.
|
|
25
25
|
Include the schema used for each change if available.
|
|
26
26
|
Mark changes with incomplete tasks as "(In Progress)".
|
|
27
27
|
|
|
@@ -42,7 +42,9 @@ ${PROJECT_ROOT_GUARD}
|
|
|
42
42
|
openspec instructions apply --change "<name>" --json
|
|
43
43
|
\`\`\`
|
|
44
44
|
|
|
45
|
-
This returns the change directory
|
|
45
|
+
This returns the change directory, \`contextFiles\` (artifact ID -> array of concrete file paths), \`taskTrackingConfigured\`, and top-level \`tasks\` and \`progress\` aggregated from every concrete file matched by the schema's \`apply.tracks\` configuration that could be read. Read all available artifacts from \`contextFiles\`.
|
|
46
|
+
|
|
47
|
+
Treat apply \`state\` and \`instruction\` as context, not a verification verdict. Do not implement tasks or archive the change during verification.
|
|
46
48
|
|
|
47
49
|
4. **Initialize verification report structure**
|
|
48
50
|
|
|
@@ -53,32 +55,59 @@ ${PROJECT_ROOT_GUARD}
|
|
|
53
55
|
|
|
54
56
|
Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.
|
|
55
57
|
|
|
58
|
+
Verification is advisory. Respect intentional omissions such as \`skip_specs: true\`, optional design documents, and schemas without task tracking. Do not require or invent optional or intentionally omitted artifacts to obtain a clean report. \`Not verified\` describes a limit of this report, not a new archive prerequisite. Archive retains its own checks and user-confirmation behavior.
|
|
59
|
+
|
|
60
|
+
Mark checks the schema does not define, or artifacts the status reports as intentionally skipped, as **Not applicable**. The correctness checks of a change whose readable delta specs contain REMOVED or RENAMED requirements but no ADDED or MODIFIED requirements are also **Not applicable** (see step 6). Exclude them from skipped-check counts and the archive-readiness assessment. Reserve **Not verified** for applicable checks whose evidence is missing or unusable.
|
|
61
|
+
|
|
62
|
+
If only task evidence is available for applicable checks, verify task completion only and mark the remaining applicable checks, including **Code Pattern Consistency**, as not verified with the reason "Only task evidence available".
|
|
63
|
+
|
|
64
|
+
If artifacts cannot be read or contain no usable requirements, scenarios, or design decisions, mark the affected checks as not verified with the specific reason. Continue checks supported by the remaining evidence, but a partially checked input set is not a fully verified check. Missing requirements affect Spec Coverage and Requirement Implementation Mapping; missing scenarios affect Scenario Coverage; missing design decisions affect Design Adherence.
|
|
65
|
+
|
|
56
66
|
5. **Verify Completeness**
|
|
57
67
|
|
|
58
68
|
**Task Completion**:
|
|
59
|
-
- If \`
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
- If
|
|
65
|
-
- Add CRITICAL issue for each incomplete task
|
|
69
|
+
- If \`taskTrackingConfigured\` is false, report **Task Completion** as not applicable. Do not treat empty \`tasks\` as missing evidence.
|
|
70
|
+
- Otherwise, use the top-level \`tasks\` and \`progress\` fields. They already aggregate every readable concrete file matched by \`apply.tracks\`, regardless of the tracked artifact's ID; do not infer tracking from a \`contextFiles\` key.
|
|
71
|
+
- If \`unavailableTrackingFiles\` is nonempty, mark **Task Completion** as not verified and include every unavailable path and reason. Continue using any readable task evidence, but do not infer completion from the partial \`tasks\` and \`progress\` fields.
|
|
72
|
+
- If \`taskTrackingConfigured\` is true and \`tasks\` is empty, mark **Task Completion** as not verified and record the reason from apply \`state\` and \`instruction\`. Nonzero totals alone do not establish evaluable task descriptions.
|
|
73
|
+
- Report complete vs total tasks from \`progress\`.
|
|
74
|
+
- If \`progress.remaining\` is greater than 0:
|
|
75
|
+
- Add CRITICAL issue for each listed incomplete task. If the remaining count exceeds the listed incomplete tasks, also report the incomplete checkboxes without descriptions and recommend adding descriptions and completing them. Do not infer completion from the listed tasks alone.
|
|
66
76
|
- Recommendation: "Complete task: <description>" or "Mark as done if already implemented"
|
|
67
77
|
|
|
68
78
|
**Spec Coverage**:
|
|
79
|
+
- If status marks the spec artifact skipped by \`skip_specs: true\`, or the schema defines no spec artifact, report the spec-dependent checks as not applicable.
|
|
80
|
+
- Otherwise, \`contextFiles\` is keyed by artifact id, and artifact ids come from the active schema. If \`contextFiles.specs\` is absent or empty, mark **Spec Coverage**, **Requirement Implementation Mapping**, and **Scenario Coverage** as not verified; do not treat any of them as clean.
|
|
69
81
|
- If delta specs exist in \`contextFiles.specs\`:
|
|
70
|
-
- Extract all requirements (marked with "### Requirement:")
|
|
71
|
-
- For each requirement:
|
|
82
|
+
- Extract all requirements (marked with "### Requirement:", or listed as \`FROM:\`/\`TO:\` pairs under \`## RENAMED Requirements\`) and note the delta section each one sits under: \`## ADDED\`, \`## MODIFIED\`, \`## REMOVED\`, or \`## RENAMED Requirements\`. The section decides what the check looks for.
|
|
83
|
+
- For each ADDED or MODIFIED requirement (for MODIFIED, check the text in the delta, not the old wording):
|
|
72
84
|
- Search codebase for keywords related to the requirement
|
|
73
85
|
- Assess if implementation likely exists
|
|
74
|
-
- If requirements appear unimplemented:
|
|
86
|
+
- If ADDED or MODIFIED requirements appear unimplemented:
|
|
75
87
|
- Add CRITICAL issue: "Requirement not found: <requirement name>"
|
|
76
88
|
- Recommendation: "Implement requirement X: <description>"
|
|
89
|
+
- For each REMOVED requirement, the change asks for the behavior to be gone, so invert the check:
|
|
90
|
+
- Search codebase for the removed behavior. Matches in \`openspec/\` artifacts or docs, or in code that serves only the Migration note or an ADDED requirement, are not evidence by themselves. Report any code path that still delivers the removed behavior, including one shared with an ADDED requirement.
|
|
91
|
+
- Finding no implementation is the expected result. Never report a REMOVED requirement as "Requirement not found" or recommend implementing it.
|
|
92
|
+
- If the behavior is still present:
|
|
93
|
+
- Add CRITICAL issue: "Removed requirement still implemented: <requirement name>"
|
|
94
|
+
- Recommendation: "Remove the remaining implementation at <file>:<lines>, following the requirement's Migration note if it has one"
|
|
95
|
+
- For each RENAMED entry (\`FROM:\`/\`TO:\`), the name changes but the behavior stays, so check the TO requirement for that unchanged behavior:
|
|
96
|
+
- Do not report the FROM name as missing, and do not require code symbols, identifiers, or file names to be renamed.
|
|
97
|
+
- If the TO name also appears under MODIFIED, its behavior is checked there against the MODIFIED text; skip it here.
|
|
98
|
+
- Otherwise, read the baseline requirement in the main spec at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\`, using the same capability path as the delta spec: the requirement under the FROM name, or under the TO name only when the FROM name is absent because the main spec is already synced. Its body and scenarios are the evidence for the behavior the TO requirement keeps.
|
|
99
|
+
- Search codebase for that behavior and assess if it is still implemented.
|
|
100
|
+
- If it appears unimplemented:
|
|
101
|
+
- Add CRITICAL issue: "Renamed requirement not found: <TO name>"
|
|
102
|
+
- Recommendation: "Restore the behavior of <TO name> (renamed from <FROM name>); a rename must not change behavior"
|
|
103
|
+
- If the baseline requirement cannot be found or read, mark **Spec Coverage** as not verified for that entry with the reason. Never count an unchecked rename as passing.
|
|
77
104
|
|
|
78
105
|
6. **Verify Correctness**
|
|
79
106
|
|
|
107
|
+
If the delta specs are readable and contain at least one REMOVED or RENAMED requirement but no ADDED or MODIFIED requirements (the change only removes or renames requirements), report **Requirement Implementation Mapping** and **Scenario Coverage** as **Not applicable**. The REMOVED and RENAMED checks under Spec Coverage are the evidence for such a change (each RENAMED entry is checked there against its baseline behavior), so do not mark these two checks as not verified. A delta spec with no parseable requirements at all is unusable evidence, not a removal-only change: mark these checks as not verified.
|
|
108
|
+
|
|
80
109
|
**Requirement Implementation Mapping**:
|
|
81
|
-
- For each requirement from delta specs:
|
|
110
|
+
- For each ADDED or MODIFIED requirement from delta specs (REMOVED entries, and RENAMED entries without a MODIFIED block, were settled under Spec Coverage):
|
|
82
111
|
- Search codebase for implementation evidence
|
|
83
112
|
- If found, note file paths and line ranges
|
|
84
113
|
- Assess if implementation matches requirement intent
|
|
@@ -87,26 +116,29 @@ ${PROJECT_ROOT_GUARD}
|
|
|
87
116
|
- Recommendation: "Review <file>:<lines> against requirement X"
|
|
88
117
|
|
|
89
118
|
**Scenario Coverage**:
|
|
90
|
-
- For each scenario in delta specs (marked with "#### Scenario:"):
|
|
119
|
+
- For each scenario under an ADDED or MODIFIED requirement in delta specs (marked with "#### Scenario:"):
|
|
91
120
|
- Check if conditions are handled in code
|
|
92
121
|
- Check if tests exist covering the scenario
|
|
93
122
|
- If scenario appears uncovered:
|
|
94
123
|
- Add WARNING: "Scenario not covered: <scenario name>"
|
|
95
124
|
- Recommendation: "Add test or implementation for scenario: <description>"
|
|
125
|
+
- Skip scenarios under a REMOVED requirement; that behavior is meant to be gone.
|
|
96
126
|
|
|
97
127
|
7. **Verify Coherence**
|
|
98
128
|
|
|
99
129
|
**Design Adherence**:
|
|
130
|
+
- If the schema defines no design artifact, report **Design Adherence** as not applicable.
|
|
100
131
|
- If \`contextFiles.design\` exists:
|
|
101
132
|
- Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:")
|
|
102
133
|
- Verify implementation follows those decisions
|
|
103
134
|
- If contradiction detected:
|
|
104
135
|
- Add WARNING: "Design decision not followed: <decision>"
|
|
105
136
|
- Recommendation: "Update implementation or revise design.md to match reality"
|
|
106
|
-
-
|
|
137
|
+
- Otherwise, if \`contextFiles.design\` is absent or empty: mark **Design Adherence** as not verified. With other supporting artifacts, **Code Pattern Consistency** still runs; the task-only case remains limited to task completion.
|
|
107
138
|
|
|
108
139
|
**Code Pattern Consistency**:
|
|
109
|
-
-
|
|
140
|
+
- If implementation changes cannot be identified, mark **Code Pattern Consistency** as not verified and explain the missing evidence.
|
|
141
|
+
- Otherwise, review new code for consistency with project patterns
|
|
110
142
|
- Check file naming, directory structure, coding style
|
|
111
143
|
- If significant deviations found:
|
|
112
144
|
- Add SUGGESTION: "Code pattern deviation: <details>"
|
|
@@ -126,11 +158,15 @@ ${PROJECT_ROOT_GUARD}
|
|
|
126
158
|
| Coherence | Followed/Issues |
|
|
127
159
|
\`\`\`
|
|
128
160
|
|
|
161
|
+
In each Status cell, report the results of checks that ran and \`Not verified (<reason>)\` for every skipped check. If all checks in a dimension were skipped, start the cell with \`Not verified\`. Never score a skipped check as passing. Treat every not verified or partially verified check as skipped in the final assessment. Count only ADDED and MODIFIED requirements in N, and report REMOVED and RENAMED requirements separately (for example, "1 removal confirmed, 1 rename verified"). For a change that only removes or renames requirements, the Correctness cell reads \`Not applicable (no ADDED or MODIFIED requirements)\`.
|
|
162
|
+
|
|
129
163
|
**Issues by Priority**:
|
|
130
164
|
|
|
131
165
|
1. **CRITICAL** (Must fix before archive):
|
|
132
166
|
- Incomplete tasks
|
|
133
167
|
- Missing requirement implementations
|
|
168
|
+
- Removed requirements still implemented
|
|
169
|
+
- Renamed requirements whose behavior is no longer implemented
|
|
134
170
|
- Each with specific, actionable recommendation
|
|
135
171
|
|
|
136
172
|
2. **WARNING** (Should fix):
|
|
@@ -144,9 +180,12 @@ ${PROJECT_ROOT_GUARD}
|
|
|
144
180
|
- Each with specific recommendation
|
|
145
181
|
|
|
146
182
|
**Final Assessment**:
|
|
147
|
-
- If CRITICAL issues: "X critical issue(s) found. Fix before archiving."
|
|
148
|
-
- If
|
|
149
|
-
- If
|
|
183
|
+
- If CRITICAL issues: "X critical issue(s) found. Fix before archiving." If any check was skipped, also name every skipped check and its reason.
|
|
184
|
+
- If no CRITICAL issues, one or more warnings, and no checks were skipped: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)."
|
|
185
|
+
- If only suggestions and no checks were skipped: "No critical issues or warnings. Z suggestion(s) to consider. Ready for archive (with noted improvements)."
|
|
186
|
+
- If no issues and no checks were skipped: "All checks passed. Ready for archive."
|
|
187
|
+
- If any check was skipped and there are no CRITICAL issues: do not claim readiness. Say "No critical issues found in the checks that ran. <check(s)> not verified: <reason>." Include the warning count when nonzero.
|
|
188
|
+
- Include the suggestion count when nonzero in every final assessment.
|
|
150
189
|
|
|
151
190
|
**Verification Heuristics**
|
|
152
191
|
|
|
@@ -156,13 +195,6 @@ ${PROJECT_ROOT_GUARD}
|
|
|
156
195
|
- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL
|
|
157
196
|
- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable
|
|
158
197
|
|
|
159
|
-
**Graceful Degradation**
|
|
160
|
-
|
|
161
|
-
- If only tasks.md exists: verify task completion only, skip spec/design checks
|
|
162
|
-
- If tasks + specs exist: verify completeness and correctness, skip design
|
|
163
|
-
- If full artifacts: verify all three dimensions
|
|
164
|
-
- Always note which checks were skipped and why
|
|
165
|
-
|
|
166
198
|
**Output Format**
|
|
167
199
|
|
|
168
200
|
Use clear markdown with:
|
|
@@ -199,7 +231,7 @@ ${PROJECT_ROOT_GUARD}
|
|
|
199
231
|
- Auto-select if only one active change exists
|
|
200
232
|
- If ambiguous, run \`openspec list --json\` to get available changes and ask the user to select one
|
|
201
233
|
|
|
202
|
-
When prompting, show changes
|
|
234
|
+
When prompting, show all active changes returned by the list, including changes with \`status: "no-tasks"\`.
|
|
203
235
|
Include the schema used for each change if available.
|
|
204
236
|
Mark changes with incomplete tasks as "(In Progress)".
|
|
205
237
|
|
|
@@ -220,7 +252,9 @@ ${PROJECT_ROOT_GUARD}
|
|
|
220
252
|
openspec instructions apply --change "<name>" --json
|
|
221
253
|
\`\`\`
|
|
222
254
|
|
|
223
|
-
This returns the change directory
|
|
255
|
+
This returns the change directory, \`contextFiles\` (artifact ID -> array of concrete file paths), \`taskTrackingConfigured\`, and top-level \`tasks\` and \`progress\` aggregated from every concrete file matched by the schema's \`apply.tracks\` configuration that could be read. Read all available artifacts from \`contextFiles\`.
|
|
256
|
+
|
|
257
|
+
Treat apply \`state\` and \`instruction\` as context, not a verification verdict. Do not implement tasks or archive the change during verification.
|
|
224
258
|
|
|
225
259
|
4. **Initialize verification report structure**
|
|
226
260
|
|
|
@@ -231,32 +265,58 @@ ${PROJECT_ROOT_GUARD}
|
|
|
231
265
|
|
|
232
266
|
Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.
|
|
233
267
|
|
|
268
|
+
Verification is advisory. Respect intentional omissions such as \`skip_specs: true\`, optional design documents, and schemas without task tracking. Do not require or invent optional or intentionally omitted artifacts to obtain a clean report. \`Not verified\` describes a limit of this report, not a new archive prerequisite. Archive retains its own checks and user-confirmation behavior.
|
|
269
|
+
Mark checks the schema does not define, or artifacts the status reports as intentionally skipped, as **Not applicable**. The correctness checks of a change whose readable delta specs contain REMOVED or RENAMED requirements but no ADDED or MODIFIED requirements are also **Not applicable** (see step 6). Exclude them from skipped-check counts and the archive-readiness assessment. Reserve **Not verified** for applicable checks whose evidence is missing or unusable.
|
|
270
|
+
|
|
271
|
+
If only task evidence is available for applicable checks, verify task completion only and mark the remaining applicable checks, including **Code Pattern Consistency**, as not verified with the reason "Only task evidence available".
|
|
272
|
+
|
|
273
|
+
If artifacts cannot be read or contain no usable requirements, scenarios, or design decisions, mark the affected checks as not verified with the specific reason. Continue checks supported by the remaining evidence, but a partially checked input set is not a fully verified check. Missing requirements affect Spec Coverage and Requirement Implementation Mapping; missing scenarios affect Scenario Coverage; missing design decisions affect Design Adherence.
|
|
274
|
+
|
|
234
275
|
5. **Verify Completeness**
|
|
235
276
|
|
|
236
277
|
**Task Completion**:
|
|
237
|
-
- If \`
|
|
238
|
-
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
-
|
|
242
|
-
- If
|
|
243
|
-
- Add CRITICAL issue for each incomplete task
|
|
278
|
+
- If \`taskTrackingConfigured\` is false, report **Task Completion** as not applicable. Do not treat empty \`tasks\` as missing evidence.
|
|
279
|
+
- Otherwise, use the top-level \`tasks\` and \`progress\` fields. They already aggregate every readable concrete file matched by \`apply.tracks\`, regardless of the tracked artifact's ID; do not infer tracking from a \`contextFiles\` key.
|
|
280
|
+
- If \`unavailableTrackingFiles\` is nonempty, mark **Task Completion** as not verified and include every unavailable path and reason. Continue using any readable task evidence, but do not infer completion from the partial \`tasks\` and \`progress\` fields.
|
|
281
|
+
- If \`taskTrackingConfigured\` is true and \`tasks\` is empty, mark **Task Completion** as not verified and record the reason from apply \`state\` and \`instruction\`. Nonzero totals alone do not establish evaluable task descriptions.
|
|
282
|
+
- Report complete vs total tasks from \`progress\`.
|
|
283
|
+
- If \`progress.remaining\` is greater than 0:
|
|
284
|
+
- Add CRITICAL issue for each listed incomplete task. If the remaining count exceeds the listed incomplete tasks, also report the incomplete checkboxes without descriptions and recommend adding descriptions and completing them. Do not infer completion from the listed tasks alone.
|
|
244
285
|
- Recommendation: "Complete task: <description>" or "Mark as done if already implemented"
|
|
245
286
|
|
|
246
287
|
**Spec Coverage**:
|
|
288
|
+
- If status marks the spec artifact skipped by \`skip_specs: true\`, or the schema defines no spec artifact, report the spec-dependent checks as not applicable.
|
|
289
|
+
- Otherwise, \`contextFiles\` is keyed by artifact id, and artifact ids come from the active schema. If \`contextFiles.specs\` is absent or empty, mark **Spec Coverage**, **Requirement Implementation Mapping**, and **Scenario Coverage** as not verified; do not treat any of them as clean.
|
|
247
290
|
- If delta specs exist in \`contextFiles.specs\`:
|
|
248
|
-
- Extract all requirements (marked with "### Requirement:")
|
|
249
|
-
- For each requirement:
|
|
291
|
+
- Extract all requirements (marked with "### Requirement:", or listed as \`FROM:\`/\`TO:\` pairs under \`## RENAMED Requirements\`) and note the delta section each one sits under: \`## ADDED\`, \`## MODIFIED\`, \`## REMOVED\`, or \`## RENAMED Requirements\`. The section decides what the check looks for.
|
|
292
|
+
- For each ADDED or MODIFIED requirement (for MODIFIED, check the text in the delta, not the old wording):
|
|
250
293
|
- Search codebase for keywords related to the requirement
|
|
251
294
|
- Assess if implementation likely exists
|
|
252
|
-
- If requirements appear unimplemented:
|
|
295
|
+
- If ADDED or MODIFIED requirements appear unimplemented:
|
|
253
296
|
- Add CRITICAL issue: "Requirement not found: <requirement name>"
|
|
254
297
|
- Recommendation: "Implement requirement X: <description>"
|
|
298
|
+
- For each REMOVED requirement, the change asks for the behavior to be gone, so invert the check:
|
|
299
|
+
- Search codebase for the removed behavior. Matches in \`openspec/\` artifacts or docs, or in code that serves only the Migration note or an ADDED requirement, are not evidence by themselves. Report any code path that still delivers the removed behavior, including one shared with an ADDED requirement.
|
|
300
|
+
- Finding no implementation is the expected result. Never report a REMOVED requirement as "Requirement not found" or recommend implementing it.
|
|
301
|
+
- If the behavior is still present:
|
|
302
|
+
- Add CRITICAL issue: "Removed requirement still implemented: <requirement name>"
|
|
303
|
+
- Recommendation: "Remove the remaining implementation at <file>:<lines>, following the requirement's Migration note if it has one"
|
|
304
|
+
- For each RENAMED entry (\`FROM:\`/\`TO:\`), the name changes but the behavior stays, so check the TO requirement for that unchanged behavior:
|
|
305
|
+
- Do not report the FROM name as missing, and do not require code symbols, identifiers, or file names to be renamed.
|
|
306
|
+
- If the TO name also appears under MODIFIED, its behavior is checked there against the MODIFIED text; skip it here.
|
|
307
|
+
- Otherwise, read the baseline requirement in the main spec at \`<planningHome.root>/openspec/specs/<capability-path>/spec.md\`, using the same capability path as the delta spec: the requirement under the FROM name, or under the TO name only when the FROM name is absent because the main spec is already synced. Its body and scenarios are the evidence for the behavior the TO requirement keeps.
|
|
308
|
+
- Search codebase for that behavior and assess if it is still implemented.
|
|
309
|
+
- If it appears unimplemented:
|
|
310
|
+
- Add CRITICAL issue: "Renamed requirement not found: <TO name>"
|
|
311
|
+
- Recommendation: "Restore the behavior of <TO name> (renamed from <FROM name>); a rename must not change behavior"
|
|
312
|
+
- If the baseline requirement cannot be found or read, mark **Spec Coverage** as not verified for that entry with the reason. Never count an unchecked rename as passing.
|
|
255
313
|
|
|
256
314
|
6. **Verify Correctness**
|
|
257
315
|
|
|
316
|
+
If the delta specs are readable and contain at least one REMOVED or RENAMED requirement but no ADDED or MODIFIED requirements (the change only removes or renames requirements), report **Requirement Implementation Mapping** and **Scenario Coverage** as **Not applicable**. The REMOVED and RENAMED checks under Spec Coverage are the evidence for such a change (each RENAMED entry is checked there against its baseline behavior), so do not mark these two checks as not verified. A delta spec with no parseable requirements at all is unusable evidence, not a removal-only change: mark these checks as not verified.
|
|
317
|
+
|
|
258
318
|
**Requirement Implementation Mapping**:
|
|
259
|
-
- For each requirement from delta specs:
|
|
319
|
+
- For each ADDED or MODIFIED requirement from delta specs (REMOVED entries, and RENAMED entries without a MODIFIED block, were settled under Spec Coverage):
|
|
260
320
|
- Search codebase for implementation evidence
|
|
261
321
|
- If found, note file paths and line ranges
|
|
262
322
|
- Assess if implementation matches requirement intent
|
|
@@ -265,26 +325,29 @@ ${PROJECT_ROOT_GUARD}
|
|
|
265
325
|
- Recommendation: "Review <file>:<lines> against requirement X"
|
|
266
326
|
|
|
267
327
|
**Scenario Coverage**:
|
|
268
|
-
- For each scenario in delta specs (marked with "#### Scenario:"):
|
|
328
|
+
- For each scenario under an ADDED or MODIFIED requirement in delta specs (marked with "#### Scenario:"):
|
|
269
329
|
- Check if conditions are handled in code
|
|
270
330
|
- Check if tests exist covering the scenario
|
|
271
331
|
- If scenario appears uncovered:
|
|
272
332
|
- Add WARNING: "Scenario not covered: <scenario name>"
|
|
273
333
|
- Recommendation: "Add test or implementation for scenario: <description>"
|
|
334
|
+
- Skip scenarios under a REMOVED requirement; that behavior is meant to be gone.
|
|
274
335
|
|
|
275
336
|
7. **Verify Coherence**
|
|
276
337
|
|
|
277
338
|
**Design Adherence**:
|
|
339
|
+
- If the schema defines no design artifact, report **Design Adherence** as not applicable.
|
|
278
340
|
- If \`contextFiles.design\` exists:
|
|
279
341
|
- Extract key decisions (look for sections like "Decision:", "Approach:", "Architecture:")
|
|
280
342
|
- Verify implementation follows those decisions
|
|
281
343
|
- If contradiction detected:
|
|
282
344
|
- Add WARNING: "Design decision not followed: <decision>"
|
|
283
345
|
- Recommendation: "Update implementation or revise design.md to match reality"
|
|
284
|
-
-
|
|
346
|
+
- Otherwise, if \`contextFiles.design\` is absent or empty: mark **Design Adherence** as not verified. With other supporting artifacts, **Code Pattern Consistency** still runs; the task-only case remains limited to task completion.
|
|
285
347
|
|
|
286
348
|
**Code Pattern Consistency**:
|
|
287
|
-
-
|
|
349
|
+
- If implementation changes cannot be identified, mark **Code Pattern Consistency** as not verified and explain the missing evidence.
|
|
350
|
+
- Otherwise, review new code for consistency with project patterns
|
|
288
351
|
- Check file naming, directory structure, coding style
|
|
289
352
|
- If significant deviations found:
|
|
290
353
|
- Add SUGGESTION: "Code pattern deviation: <details>"
|
|
@@ -304,11 +367,15 @@ ${PROJECT_ROOT_GUARD}
|
|
|
304
367
|
| Coherence | Followed/Issues |
|
|
305
368
|
\`\`\`
|
|
306
369
|
|
|
370
|
+
In each Status cell, report the results of checks that ran and \`Not verified (<reason>)\` for every skipped check. If all checks in a dimension were skipped, start the cell with \`Not verified\`. Never score a skipped check as passing. Treat every not verified or partially verified check as skipped in the final assessment. Count only ADDED and MODIFIED requirements in N, and report REMOVED and RENAMED requirements separately (for example, "1 removal confirmed, 1 rename verified"). For a change that only removes or renames requirements, the Correctness cell reads \`Not applicable (no ADDED or MODIFIED requirements)\`.
|
|
371
|
+
|
|
307
372
|
**Issues by Priority**:
|
|
308
373
|
|
|
309
374
|
1. **CRITICAL** (Must fix before archive):
|
|
310
375
|
- Incomplete tasks
|
|
311
376
|
- Missing requirement implementations
|
|
377
|
+
- Removed requirements still implemented
|
|
378
|
+
- Renamed requirements whose behavior is no longer implemented
|
|
312
379
|
- Each with specific, actionable recommendation
|
|
313
380
|
|
|
314
381
|
2. **WARNING** (Should fix):
|
|
@@ -322,9 +389,12 @@ ${PROJECT_ROOT_GUARD}
|
|
|
322
389
|
- Each with specific recommendation
|
|
323
390
|
|
|
324
391
|
**Final Assessment**:
|
|
325
|
-
- If CRITICAL issues: "X critical issue(s) found. Fix before archiving."
|
|
326
|
-
- If
|
|
327
|
-
- If
|
|
392
|
+
- If CRITICAL issues: "X critical issue(s) found. Fix before archiving." If any check was skipped, also name every skipped check and its reason.
|
|
393
|
+
- If no CRITICAL issues, one or more warnings, and no checks were skipped: "No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements)."
|
|
394
|
+
- If only suggestions and no checks were skipped: "No critical issues or warnings. Z suggestion(s) to consider. Ready for archive (with noted improvements)."
|
|
395
|
+
- If no issues and no checks were skipped: "All checks passed. Ready for archive."
|
|
396
|
+
- If any check was skipped and there are no CRITICAL issues: do not claim readiness. Say "No critical issues found in the checks that ran. <check(s)> not verified: <reason>." Include the warning count when nonzero.
|
|
397
|
+
- Include the suggestion count when nonzero in every final assessment.
|
|
328
398
|
|
|
329
399
|
**Verification Heuristics**
|
|
330
400
|
|
|
@@ -334,13 +404,6 @@ ${PROJECT_ROOT_GUARD}
|
|
|
334
404
|
- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL
|
|
335
405
|
- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable
|
|
336
406
|
|
|
337
|
-
**Graceful Degradation**
|
|
338
|
-
|
|
339
|
-
- If only tasks.md exists: verify task completion only, skip spec/design checks
|
|
340
|
-
- If tasks + specs exist: verify completeness and correctness, skip design
|
|
341
|
-
- If full artifacts: verify all three dimensions
|
|
342
|
-
- Always note which checks were skipped and why
|
|
343
|
-
|
|
344
407
|
**Output Format**
|
|
345
408
|
|
|
346
409
|
Use clear markdown with:
|
package/dist/core/update.js
CHANGED
|
@@ -27,6 +27,11 @@ import { resolveSharedSkillWriters, writeSharedSkillTarget, } from './shared-ski
|
|
|
27
27
|
import { includesGitHubCopilot, writeCopilotCloudFiles, removeCopilotCloudFiles, isCopilotCloudEnabled, readCopilotCloudOptIn, findUnmanagedCloudFiles } from './github-copilot/cloud-agent.js';
|
|
28
28
|
const require = createRequire(import.meta.url);
|
|
29
29
|
const { version: OPENSPEC_VERSION } = require('../../package.json');
|
|
30
|
+
function throwIfUpdateFailed(failedTools) {
|
|
31
|
+
if (failedTools.length > 0) {
|
|
32
|
+
throw new Error(`OpenSpec update failed for: ${failedTools.map((tool) => tool.name).join(', ')}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
30
35
|
/**
|
|
31
36
|
* Checkout artifacts that are not real content drift: a UTF-8 BOM and the CRLF
|
|
32
37
|
* line endings a Windows clone with `core.autocrlf` reintroduces on every
|
|
@@ -87,7 +92,7 @@ export class UpdateCommand {
|
|
|
87
92
|
const desiredWorkflows = profileWorkflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
|
|
88
93
|
// 4. Detect and handle legacy artifacts + upgrade legacy tools using effective config
|
|
89
94
|
const legacyUpgrade = await this.handleLegacyCleanup(resolvedProjectPath, desiredWorkflows, delivery);
|
|
90
|
-
const { newlyConfiguredTools, workflowOverrides: legacyWorkflowOverrides, deferredGlobalCleanup, } = legacyUpgrade;
|
|
95
|
+
const { newlyConfiguredTools, workflowOverrides: legacyWorkflowOverrides, deferredGlobalCleanup, failedTools: legacyUpgradeFailures = [], } = legacyUpgrade;
|
|
91
96
|
// 5. Find configured tools
|
|
92
97
|
const configuredTools = getConfiguredToolsForProfileSync(resolvedProjectPath);
|
|
93
98
|
const configuredAndNewTools = [...new Set([...configuredTools, ...newlyConfiguredTools])];
|
|
@@ -95,6 +100,7 @@ export class UpdateCommand {
|
|
|
95
100
|
if (deferredGlobalCleanup) {
|
|
96
101
|
await this.performDeferredGlobalPromptCleanup(resolvedProjectPath, deferredGlobalCleanup);
|
|
97
102
|
}
|
|
103
|
+
throwIfUpdateFailed(legacyUpgradeFailures);
|
|
98
104
|
if (declinedMigrations.length > 0) {
|
|
99
105
|
// Not an unconfigured project — a configured one the user chose to
|
|
100
106
|
// leave in its former directory. Saying "run init" would be wrong.
|
|
@@ -146,6 +152,7 @@ export class UpdateCommand {
|
|
|
146
152
|
this.detectNewTools(resolvedProjectPath, configuredTools);
|
|
147
153
|
this.displayProfileNotes(resolvedProjectPath, configuredTools, desiredWorkflows, profile, delivery);
|
|
148
154
|
this.displaySetupNotes(configuredTools);
|
|
155
|
+
throwIfUpdateFailed(legacyUpgradeFailures);
|
|
149
156
|
return;
|
|
150
157
|
}
|
|
151
158
|
// 8. Display update plan
|
|
@@ -168,7 +175,7 @@ export class UpdateCommand {
|
|
|
168
175
|
.filter((tool) => tool !== undefined));
|
|
169
176
|
const updatedTools = [];
|
|
170
177
|
const updatedToolIds = [];
|
|
171
|
-
const failedTools = [];
|
|
178
|
+
const failedTools = [...legacyUpgradeFailures];
|
|
172
179
|
const skillsInvocableCommandSkips = [];
|
|
173
180
|
const zeroArtifactTools = [];
|
|
174
181
|
let removedCommandCount = 0;
|
|
@@ -339,9 +346,7 @@ export class UpdateCommand {
|
|
|
339
346
|
if (restartHint) {
|
|
340
347
|
console.log(chalk.dim(restartHint));
|
|
341
348
|
}
|
|
342
|
-
|
|
343
|
-
throw new Error(`OpenSpec update failed for: ${failedTools.map((tool) => tool.name).join(', ')}`);
|
|
344
|
-
}
|
|
349
|
+
throwIfUpdateFailed(failedTools);
|
|
345
350
|
}
|
|
346
351
|
async syncCopilotCloudFiles(projectPath, configuredTools) {
|
|
347
352
|
try {
|
|
@@ -901,6 +906,7 @@ export class UpdateCommand {
|
|
|
901
906
|
// Create skills/commands for selected tools using effective profile+delivery.
|
|
902
907
|
const newlyConfigured = [];
|
|
903
908
|
const skippedSharedSkillTools = [];
|
|
909
|
+
const failedTools = [];
|
|
904
910
|
const workflowOverrides = {};
|
|
905
911
|
const arbitrationTools = [...new Set([...configuredTools, ...selectedTools])]
|
|
906
912
|
.map((toolId) => AI_TOOLS.find((tool) => tool.value === toolId))
|
|
@@ -974,13 +980,20 @@ export class UpdateCommand {
|
|
|
974
980
|
}
|
|
975
981
|
catch (error) {
|
|
976
982
|
spinner.fail(`Failed to set up ${tool.name}`);
|
|
977
|
-
|
|
983
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
984
|
+
console.log(chalk.red(` ${message}`));
|
|
985
|
+
failedTools.push({ name: tool.name, error: message });
|
|
978
986
|
}
|
|
979
987
|
}
|
|
980
988
|
if (newlyConfigured.length > 0) {
|
|
981
989
|
console.log();
|
|
982
990
|
}
|
|
983
|
-
return {
|
|
991
|
+
return {
|
|
992
|
+
newlyConfiguredTools: newlyConfigured,
|
|
993
|
+
workflowOverrides,
|
|
994
|
+
skippedSharedSkillTools,
|
|
995
|
+
failedTools,
|
|
996
|
+
};
|
|
984
997
|
}
|
|
985
998
|
}
|
|
986
999
|
//# sourceMappingURL=update.js.map
|
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import { buildCodeFenceMask } from '../parsers/code-fence.js';
|
|
2
2
|
import { PURPOSE_PLACEHOLDER_PREFIX, PURPOSE_PLACEHOLDER_SUFFIX } from './constants.js';
|
|
3
3
|
/**
|
|
4
|
-
* A `TBD` or `TODO` opening the Purpose.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* A `TBD` or `TODO` opening the Purpose.
|
|
5
|
+
*
|
|
6
|
+
* `WORD_END` keeps the marker off a longer word that merely begins with those
|
|
7
|
+
* letters, like "TBDs" or "TODOs", while still allowing the punctuation a
|
|
8
|
+
* marker is usually written with: `TODO:`, `TBD -`. It rejects any letter,
|
|
9
|
+
* digit or combining mark rather than only the ASCII ones `\b` knows about,
|
|
10
|
+
* because a Purpose is prose and prose is not always written in Latin script -
|
|
11
|
+
* `TBD` followed by an Arabic-Indic digit is as much a longer word as `TBDs`.
|
|
12
|
+
*
|
|
13
|
+
* Case is what separates the marker from the word. `TODO` shouted in capitals
|
|
14
|
+
* is the marker whatever follows it, so `TODO write this later` is still an
|
|
15
|
+
* unwritten Purpose. Written in any other case it is only a marker when
|
|
16
|
+
* punctuation or the end of the line says so, because `todo` is an extremely
|
|
17
|
+
* frequent sentence opener in Spanish ("Todo el...") and Portuguese ("Todo
|
|
18
|
+
* o..."), and ordinary prose in those languages is not a placeholder. That
|
|
19
|
+
* keeps the lowercase forms an agent really does leave behind - `todo - write
|
|
20
|
+
* this later`, `tbd.` - reported, without reading a Spanish sentence as one.
|
|
11
21
|
*/
|
|
12
|
-
const
|
|
22
|
+
const WORD_END = '(?![\\p{L}\\p{N}\\p{M}_])';
|
|
23
|
+
const MARKER_PUNCTUATION = '(?=[ \\t]*(?:$|\\n|[:\\-\u2013\u2014.,;()\\[\\]{}]))';
|
|
24
|
+
/** `TBD`/`TODO` in capitals: the marker, whatever follows it. */
|
|
25
|
+
const LEADING_MARKER_SHOUTED = new RegExp(`^(?:TBD|TODO)${WORD_END}`, 'u');
|
|
26
|
+
/** Any other case: a marker only when punctuation or the line end says so. */
|
|
27
|
+
const LEADING_MARKER_PUNCTUATED = new RegExp(`^(?:TBD|TODO)${WORD_END}${MARKER_PUNCTUATION}`, 'iu');
|
|
13
28
|
const PURPOSE_HEADER = /^ {0,3}##(?!#)[ \t]+Purpose[ \t]*$/i;
|
|
14
29
|
const TOP_LEVEL_HEADER = /^ {0,3}#{1,2}(?!#)[ \t]+/;
|
|
15
30
|
/**
|
|
@@ -60,7 +75,7 @@ export function findPurposePlaceholderIssue(overview, content) {
|
|
|
60
75
|
// that is nothing but a fenced block reduces to the same empty text here, and
|
|
61
76
|
// is left to the brevity and empty-Purpose rules for the same reason.
|
|
62
77
|
const prose = unfencedLines(overview).join('\n').trim();
|
|
63
|
-
const leading =
|
|
78
|
+
const leading = LEADING_MARKER_SHOUTED.test(prose) || LEADING_MARKER_PUNCTUATED.test(prose);
|
|
64
79
|
if (!leading && generatedPlaceholderPrefixIndex(prose) === undefined)
|
|
65
80
|
return null;
|
|
66
81
|
// Which rule matched decides where the placeholder is, so the locator is told.
|