freeharness 0.4.1 → 0.4.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 +8 -7
- package/canonical/HARVEST.yaml +25 -14
- package/canonical/PROVENANCE.yaml +1 -1
- package/canonical/agents/README.md +77 -36
- package/canonical/agents/agentic-architect.md +2 -1
- package/canonical/agents/database-reviewer.md +6 -8
- package/canonical/agents/explorer-ai-engineer-analyst.md +2 -6
- package/canonical/agents/implementer.md +30 -0
- package/canonical/agents/pr-reviewer.md +9 -11
- package/canonical/agents/python-reviewer.md +7 -9
- package/canonical/agents/report-formatter.md +7 -3
- package/canonical/agents/security-reviewer.md +7 -8
- package/canonical/agents/test-writer.md +5 -2
- package/canonical/hooks/cost-prices.json +11 -9
- package/canonical/hooks/freeharness-config-guard.mjs +8072 -87
- package/canonical/hooks/freeharness-context-monitor.mjs +88 -54
- package/canonical/hooks/freeharness-converge.mjs +78 -23
- package/canonical/hooks/freeharness-cost-tracker.mjs +1129 -218
- package/canonical/hooks/freeharness-memory-guard.mjs +20 -23
- package/canonical/hooks/freeharness-precompact.mjs +217 -87
- package/canonical/hooks/freeharness-quota-tap.mjs +173 -0
- package/canonical/hooks/freeharness-reload-context.mjs +197 -0
- package/canonical/hooks/freeharness-repeat-tool.mjs +1 -1
- package/canonical/hooks/freeharness-sdd-context.mjs +970 -0
- package/canonical/hooks/freeharness-session-start +297 -59
- package/canonical/hooks/hooks.claude-code.json +1 -1
- package/canonical/hooks/hooks.config-guard.claude-code.json +3 -2
- package/canonical/hooks/hooks.context-monitor.claude-code.json +1 -1
- package/canonical/hooks/hooks.converge.claude-code.json +1 -1
- package/canonical/hooks/hooks.memory-guard.claude-code.json +3 -2
- package/canonical/hooks/hooks.reload-context.claude-code.json +15 -0
- package/canonical/openspec/schema.spec-driven.yaml +29 -8
- package/canonical/openspec/templates/follow-ups.md +3 -2
- package/canonical/openspec/templates/proposal.md +1 -1
- package/canonical/openspec/templates/tasks.md +8 -0
- package/canonical/rules/CLAUDE.md +5 -4
- package/canonical/rules/routing.md +10 -9
- package/canonical/skills/agent-evaluation/SKILL.md +17 -6
- package/canonical/skills/agent-evaluation/evals/cases.yaml +38 -23
- package/canonical/skills/agentic-architecture/SKILL.md +4 -0
- package/canonical/skills/agentic-architecture/evals/cases.yaml +27 -0
- package/canonical/skills/code-review/SKILL.md +9 -2
- package/canonical/skills/code-review/evals/cases.yaml +1118 -27
- package/canonical/skills/git-workflow/SKILL.md +2 -0
- package/canonical/skills/local-code/SKILL.md +2 -2
- package/canonical/skills/local-code/evals/cases.yaml +1 -1
- package/canonical/skills/report-formatting/SKILL.md +10 -2
- package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +3 -3
- package/canonical/skills/report-formatting/reference/HELPERS.md +10 -5
- package/canonical/skills/report-formatting/reference/RELEASE.md +1 -2
- package/canonical/skills/report-formatting/reference/TEMPLATES.md +3 -2
- package/canonical/skills/report-formatting/reference/authoring.md +25 -37
- package/canonical/skills/report-formatting/scripts/build-architecture.js +1 -1
- package/canonical/skills/report-formatting/scripts/build-md-claro.js +5 -8
- package/canonical/skills/report-formatting/scripts/check-env.js +0 -4
- package/canonical/skills/report-formatting/scripts/docmodel.js +3 -11
- package/canonical/skills/report-formatting/scripts/example-build.js +8 -10
- package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +8 -10
- package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +8 -10
- package/canonical/skills/report-formatting/scripts/theme-claro.js +39 -10
- package/canonical/skills/subagent-driven-development/SKILL.md +35 -28
- package/canonical/skills/subagent-driven-development/evals/cases.yaml +3496 -19
- package/canonical/skills/subagent-driven-development/reference/brief.md +185 -35
- package/canonical/skills/subagent-driven-development/reference/handoff.md +82 -2
- package/canonical/skills/subagent-driven-development/reference/loop.md +57 -0
- package/canonical/skills/subagent-driven-development/reference/trees.md +40 -0
- package/canonical/skills/subagent-driven-development/reference/workspace.md +31 -0
- package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +4771 -326
- package/dist/adapters/harness/claude-code.d.ts +19 -3
- package/dist/adapters/harness/claude-code.js +204 -39
- package/dist/adapters/harness/opencode.js +16 -2
- package/dist/adapters/harness/plugin.js +28 -17
- package/dist/adapters/memory/doctor.d.ts +174 -29
- package/dist/adapters/memory/doctor.js +758 -134
- package/dist/adapters/memory/migrate.d.ts +95 -0
- package/dist/adapters/memory/migrate.js +497 -0
- package/dist/adapters/memory/paths.d.ts +22 -0
- package/dist/adapters/memory/paths.js +85 -0
- package/dist/adapters/memory/vendored.d.ts +56 -29
- package/dist/adapters/memory/vendored.js +191 -154
- package/dist/adapters/sync/diff.js +4 -1
- package/dist/cli/cleanup-prompt.d.ts +35 -0
- package/dist/cli/cleanup-prompt.js +68 -0
- package/dist/cli/cleanup.d.ts +22 -24
- package/dist/cli/cleanup.js +182 -68
- package/dist/cli/cost-quota.d.ts +158 -0
- package/dist/cli/cost-quota.js +645 -0
- package/dist/cli/cost.d.ts +408 -46
- package/dist/cli/cost.js +1731 -57
- package/dist/cli/doctor.d.ts +52 -13
- package/dist/cli/doctor.js +193 -44
- package/dist/cli/hard-cleanup.d.ts +93 -0
- package/dist/cli/hard-cleanup.js +552 -0
- package/dist/cli/install-facts.d.ts +28 -0
- package/dist/cli/install-facts.js +66 -0
- package/dist/cli/json-key-edit.d.ts +18 -0
- package/dist/cli/json-key-edit.js +118 -0
- package/dist/cli/memory-import.d.ts +74 -0
- package/dist/cli/memory-import.js +469 -0
- package/dist/cli/plugin-validate.d.ts +12 -0
- package/dist/cli/plugin-validate.js +43 -0
- package/dist/cli/uninstall.d.ts +1 -1
- package/dist/cli/uninstall.js +2 -2
- package/dist/cli/upstream-launchers.d.ts +49 -0
- package/dist/cli/upstream-launchers.js +287 -0
- package/dist/index.js +247 -70
- package/dist/infra/fsutil.d.ts +31 -3
- package/dist/infra/fsutil.js +69 -6
- package/dist/infra/manifest.d.ts +2 -1
- package/dist/infra/manifest.js +3 -2
- package/dist/infra/prices.d.ts +18 -0
- package/dist/infra/prices.js +64 -0
- package/node_modules/@freeharness/core/dist/tiers.d.ts +10 -1
- package/node_modules/@freeharness/core/dist/tiers.js +24 -2
- package/node_modules/@freeharness/core/package.json +1 -1
- package/node_modules/@freeharness/sdd/PROVENANCE.yaml +279 -2
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +34 -8
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +7 -6
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +72 -64
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +48 -16
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +168 -70
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +36 -6
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +110 -49
- package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +1 -1
- package/node_modules/@freeharness/sdd/dist/src/shim/list.js +57 -14
- package/node_modules/@freeharness/sdd/dist/src/shim/nested-change.d.ts +7 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/nested-change.js +118 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +3 -1
- package/node_modules/@freeharness/sdd/dist/src/shim/proposal-capabilities.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/proposal-capabilities.js +94 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +182 -1
- package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +2 -2
- package/node_modules/@freeharness/sdd/dist/src/shim/status.js +34 -5
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +49 -41
- package/node_modules/@freeharness/sdd/dist/src/shim/warnings.d.ts +21 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/warnings.js +66 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/line-endings.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/line-endings.js +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +95 -22
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +14 -6
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +1 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +1 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +3 -3
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +24 -4
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +4 -7
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +13 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +21 -6
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +80 -19
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +42 -22
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/project-root.d.ts +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/project-root.js +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +16 -9
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +36 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +65 -30
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +1 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +1 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +8 -13
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +79 -102
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +4 -9
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +50 -10
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +165 -37
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +24 -3
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +55 -8
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +4 -1
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +19 -9
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +115 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +3 -3
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +20 -20
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +75 -14
- package/node_modules/@freeharness/sdd/package.json +1 -1
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +47 -7
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +25 -7
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +50 -11
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +48 -10
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +27 -7
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +25 -12
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +17 -5
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +12 -1
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +47 -33
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +17 -5
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +29 -1
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +31 -13
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +75 -27
- package/package.json +6 -4
- package/provenance/canonical.PROVENANCE.yaml +1 -1
- package/provenance/memory.PROVENANCE.yaml +458 -6
- package/provenance/sdd.PROVENANCE.yaml +279 -2
- package/canonical/hooks/freeharness-auto-memory.mjs +0 -158
- package/canonical/hooks/hooks.auto-memory.claude-code.json +0 -16
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
2
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
2
3
|
export function getArchiveChangeSkillTemplate() {
|
|
3
4
|
return {
|
|
4
5
|
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.',
|
|
6
|
+
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.',
|
|
6
7
|
instructions: `Archive a completed change in the experimental workflow.
|
|
7
8
|
|
|
8
9
|
${STORE_SELECTION_GUIDANCE}
|
|
9
10
|
|
|
11
|
+
${PROJECT_ROOT_GUARD}
|
|
12
|
+
|
|
10
13
|
\`<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
14
|
|
|
12
15
|
**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 +71,27 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
68
71
|
|
|
69
72
|
3. **Check task completion status**
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
Run \`openspec list --json\` with the same selected-root flags and find the
|
|
75
|
+
entry in \`changes\` whose \`name\` exactly matches the selected change.
|
|
76
|
+
Require exactly one match and nonnegative integer \`totalTasks\` and
|
|
77
|
+
\`completedTasks\`, with \`completedTasks <= totalTasks\`. The CLI resolves
|
|
78
|
+
the schema's tracked task files, including custom artifact names, output
|
|
79
|
+
paths, and globs.
|
|
80
|
+
Incomplete tasks = \`totalTasks - completedTasks\`.
|
|
81
|
+
|
|
82
|
+
Do not infer task completion from artifact status or the absence of a
|
|
83
|
+
top-level \`tasks.md\`. If the lookup fails, returns invalid JSON, omits or
|
|
84
|
+
duplicates the selected change, or returns invalid counts, report the problem
|
|
85
|
+
and stop before syncing or archiving.
|
|
86
|
+
The CLI counts only \`x\`/\`X\` checkbox markers as complete;
|
|
87
|
+
other markers, including unfamiliar ones, remain incomplete.
|
|
74
88
|
|
|
75
89
|
**If incomplete tasks found:**
|
|
76
90
|
- Display warning showing count of incomplete tasks
|
|
77
91
|
- Ask the user to confirm they want to proceed
|
|
78
92
|
- Proceed if user confirms
|
|
79
93
|
|
|
80
|
-
**If
|
|
94
|
+
**If \`totalTasks\` is zero:** Proceed without a task-related warning.
|
|
81
95
|
|
|
82
96
|
4. **Assess delta spec sync state**
|
|
83
97
|
|
|
@@ -88,17 +102,23 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
88
102
|
|
|
89
103
|
**If delta specs exist:**
|
|
90
104
|
- 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)
|
|
105
|
+
- 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:
|
|
106
|
+
- 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.
|
|
107
|
+
- 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.
|
|
108
|
+
- 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\`.
|
|
109
|
+
- 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
110
|
- Determine what changes would be applied (adds, modifications, removals, renames)
|
|
92
|
-
- Show a combined summary before prompting
|
|
111
|
+
- Continue assessing the remaining capabilities even when one is sync-blocked. Show a combined summary before prompting.
|
|
93
112
|
|
|
94
113
|
**Prompt options:**
|
|
95
|
-
- If
|
|
96
|
-
-
|
|
114
|
+
- If any capability is sync-blocked: explain why and offer only "Archive without syncing", "Cancel"
|
|
115
|
+
- Otherwise, if changes needed: "Sync now (recommended)", "Archive without syncing"
|
|
116
|
+
- Otherwise, if already synced: "Archive now", "Sync anyway", "Cancel"
|
|
97
117
|
|
|
98
118
|
Route on the answer:
|
|
99
119
|
- "Cancel" — stop, do not archive
|
|
100
120
|
- "Archive without syncing" or "Archive now" — proceed to archive
|
|
101
|
-
- "Sync now" or "Sync anyway" — sync, then verify (below)
|
|
121
|
+
- "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
122
|
- Anything else — ask again rather than archiving
|
|
103
123
|
|
|
104
124
|
Before a selected sync writes any main spec, run
|
|
@@ -112,10 +132,21 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
112
132
|
|
|
113
133
|
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
134
|
|
|
135
|
+
If the sync reports any stop or blocking condition, treat the sync as failed.
|
|
136
|
+
Stop the archive immediately. Do not perform the post-sync content comparison and do not move its \`changeRoot\`.
|
|
137
|
+
Nothing has moved, so the user can fix the blocking condition or re-run the sync.
|
|
138
|
+
|
|
139
|
+
After the sync writes each main spec, verify its structure against the canonical sync contract:
|
|
140
|
+
- A new main spec starts with a \`# <capability> Specification\` title. An existing main spec keeps its title exactly as it is.
|
|
141
|
+
- Preserve existing \`## Purpose\` sections completely untouched for established main specs.
|
|
142
|
+
- For a new main spec, copy the delta \`## Purpose\` verbatim. Warn only if the purpose text is shorter than standard validation expects. Do not regenerate or rewrite existing authored purpose. If no usable \`## Purpose\` is provided, use the existing TBD Purpose behavior and warning.
|
|
143
|
+
- Verify that no delta-style section headers (\`## ADDED Requirements\`, \`## MODIFIED Requirements\`, \`## REMOVED Requirements\`, \`## RENAMED Requirements\`) remain in the main spec, adhering strictly to the sync workflow formatting rules.
|
|
144
|
+
- Requirement blocks the sync wrote or changed use \`### Requirement:\` headings, and their scenarios use \`#### Scenario:\` headings, under the spec's \`## Requirements\` section. Leave content the delta does not mention exactly as it is.
|
|
145
|
+
|
|
115
146
|
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:
|
|
116
147
|
- ADDED requirements present
|
|
117
148
|
- MODIFIED requirements carrying the scenario and description changes named in the delta, with their other scenarios intact
|
|
118
|
-
- 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
|
|
149
|
+
- 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.
|
|
119
150
|
- RENAMED requirements present under the new name and absent under the old one
|
|
120
151
|
|
|
121
152
|
If the sync failed, or any capability does not match, report what differs and stop — do not archive. Nothing has moved and \`changeRoot\` is intact, so the user can fix the mismatch or re-run the sync and start the archive again.
|
|
@@ -190,6 +221,8 @@ export function getOpsxArchiveCommandTemplate() {
|
|
|
190
221
|
|
|
191
222
|
${STORE_SELECTION_GUIDANCE}
|
|
192
223
|
|
|
224
|
+
${PROJECT_ROOT_GUARD}
|
|
225
|
+
|
|
193
226
|
\`<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.
|
|
194
227
|
|
|
195
228
|
**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.
|
|
@@ -251,16 +284,27 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
251
284
|
|
|
252
285
|
3. **Check task completion status**
|
|
253
286
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
287
|
+
Run \`openspec list --json\` with the same selected-root flags and find the
|
|
288
|
+
entry in \`changes\` whose \`name\` exactly matches the selected change.
|
|
289
|
+
Require exactly one match and nonnegative integer \`totalTasks\` and
|
|
290
|
+
\`completedTasks\`, with \`completedTasks <= totalTasks\`. The CLI resolves
|
|
291
|
+
the schema's tracked task files, including custom artifact names, output
|
|
292
|
+
paths, and globs.
|
|
293
|
+
Incomplete tasks = \`totalTasks - completedTasks\`.
|
|
294
|
+
|
|
295
|
+
Do not infer task completion from artifact status or the absence of a
|
|
296
|
+
top-level \`tasks.md\`. If the lookup fails, returns invalid JSON, omits or
|
|
297
|
+
duplicates the selected change, or returns invalid counts, report the problem
|
|
298
|
+
and stop before syncing or archiving.
|
|
299
|
+
The CLI counts only \`x\`/\`X\` checkbox markers as complete;
|
|
300
|
+
other markers, including unfamiliar ones, remain incomplete.
|
|
257
301
|
|
|
258
302
|
**If incomplete tasks found:**
|
|
259
303
|
- Display warning showing count of incomplete tasks
|
|
260
304
|
- Prompt user for confirmation to continue
|
|
261
305
|
- Proceed if user confirms
|
|
262
306
|
|
|
263
|
-
**If
|
|
307
|
+
**If \`totalTasks\` is zero:** Proceed without a task-related warning.
|
|
264
308
|
|
|
265
309
|
4. **Assess delta spec sync state**
|
|
266
310
|
|
|
@@ -271,17 +315,23 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
271
315
|
|
|
272
316
|
**If delta specs exist:**
|
|
273
317
|
- 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)
|
|
318
|
+
- 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:
|
|
319
|
+
- 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.
|
|
320
|
+
- 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.
|
|
321
|
+
- 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\`.
|
|
322
|
+
- 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.
|
|
274
323
|
- Determine what changes would be applied (adds, modifications, removals, renames)
|
|
275
|
-
- Show a combined summary before prompting
|
|
324
|
+
- Continue assessing the remaining capabilities even when one is sync-blocked. Show a combined summary before prompting.
|
|
276
325
|
|
|
277
326
|
**Prompt options:**
|
|
278
|
-
- If
|
|
279
|
-
-
|
|
327
|
+
- If any capability is sync-blocked: explain why and offer only "Archive without syncing", "Cancel"
|
|
328
|
+
- Otherwise, if changes needed: "Sync now (recommended)", "Archive without syncing"
|
|
329
|
+
- Otherwise, if already synced: "Archive now", "Sync anyway", "Cancel"
|
|
280
330
|
|
|
281
331
|
Route on the answer:
|
|
282
332
|
- "Cancel" — stop, do not archive
|
|
283
333
|
- "Archive without syncing" or "Archive now" — proceed to archive
|
|
284
|
-
- "Sync now" or "Sync anyway" — sync, then verify (below)
|
|
334
|
+
- "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.
|
|
285
335
|
- Anything else — ask again rather than archiving
|
|
286
336
|
|
|
287
337
|
Before a selected sync writes any main spec, run
|
|
@@ -295,10 +345,21 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
295
345
|
|
|
296
346
|
Then run the \`/opsx:sync\` 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.
|
|
297
347
|
|
|
348
|
+
If the sync reports any stop or blocking condition, treat the sync as failed.
|
|
349
|
+
Stop the archive immediately. Do not perform the post-sync content comparison and do not move its \`changeRoot\`.
|
|
350
|
+
Nothing has moved, so the user can fix the blocking condition or re-run the sync.
|
|
351
|
+
|
|
352
|
+
After the sync writes each main spec, verify its structure against the canonical sync contract:
|
|
353
|
+
- A new main spec starts with a \`# <capability> Specification\` title. An existing main spec keeps its title exactly as it is.
|
|
354
|
+
- Preserve existing \`## Purpose\` sections completely untouched for established main specs.
|
|
355
|
+
- For a new main spec, copy the delta \`## Purpose\` verbatim. Warn only if the purpose text is shorter than standard validation expects. Do not regenerate or rewrite existing authored purpose. If no usable \`## Purpose\` is provided, use the existing TBD Purpose behavior and warning.
|
|
356
|
+
- Verify that no delta-style section headers (\`## ADDED Requirements\`, \`## MODIFIED Requirements\`, \`## REMOVED Requirements\`, \`## RENAMED Requirements\`) remain in the main spec, adhering strictly to the sync workflow formatting rules.
|
|
357
|
+
- Requirement blocks the sync wrote or changed use \`### Requirement:\` headings, and their scenarios use \`#### Scenario:\` headings, under the spec's \`## Requirements\` section. Leave content the delta does not mention exactly as it is.
|
|
358
|
+
|
|
298
359
|
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:
|
|
299
360
|
- ADDED requirements present
|
|
300
361
|
- MODIFIED requirements carrying the scenario and description changes named in the delta, with their other scenarios intact
|
|
301
|
-
- 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
|
|
362
|
+
- 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.
|
|
302
363
|
- RENAMED requirements present under the new name and absent under the old one
|
|
303
364
|
|
|
304
365
|
If the sync failed, or any capability does not match, report what differs and stop — do not archive. Nothing has moved and \`changeRoot\` is intact, so the user can fix the mismatch or re-run the sync and start the archive again.
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
2
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
2
3
|
const PLANNING_GUIDANCE = `## Planning a Change
|
|
3
4
|
|
|
4
5
|
When the user is planning a change, guide them toward shared understanding with focused discovery questions. For open-ended discussion, follow the conversation without imposing an interview or a required output.
|
|
@@ -20,18 +21,31 @@ across devices in scope? That determines whether local storage is enough.
|
|
|
20
21
|
If this stays a single-device tool, I recommend keeping SQLite to avoid
|
|
21
22
|
adding a service to operate; shared state would need a separate sync design.
|
|
22
23
|
\`\`\``;
|
|
24
|
+
/**
|
|
25
|
+
* Explore's handoffs to propose and apply. FreeHarness always emits both
|
|
26
|
+
* workflows, so each handoff renders the shipped-workflow wording rather than
|
|
27
|
+
* the CLI-only fallback a partial install would need.
|
|
28
|
+
*/
|
|
29
|
+
const IMPLEMENT_REQUEST_HANDOFF = 'point them at `/opsx:propose`, which turns the discussion into a change';
|
|
30
|
+
const CAPTURE_PLANNING_HANDOFF = '`/opsx:propose` writes the remaining planning artifacts';
|
|
31
|
+
const CAPTURE_APPLY_HANDOFF = '`/opsx:apply` implements the change once tasks exist';
|
|
32
|
+
const DISCOVERY_END_HANDOFF = 'Ready to start? Run `/opsx:propose` and this becomes a change.';
|
|
33
|
+
const SUMMARY_NEXT_STEP = '- Turn this into a change: `/opsx:propose`';
|
|
34
|
+
const GUARDRAIL_HANDOFF = '`/opsx:propose` turns the discussion into a change, and the work happens there';
|
|
23
35
|
export function getExploreSkillTemplate() {
|
|
24
36
|
return {
|
|
25
37
|
name: 'openspec-explore',
|
|
26
|
-
description: 'Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during
|
|
38
|
+
description: 'Enter OpenSpec explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements in a project that uses OpenSpec. Use when the user wants to think through something before or during an OpenSpec change.',
|
|
27
39
|
instructions: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
|
|
28
40
|
|
|
29
|
-
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something,
|
|
41
|
+
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, do not start it here: say that explore mode does not implement, and ${IMPLEMENT_REQUEST_HANDOFF}. The work happens from that change, never from explore mode. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request from the user to capture the exploration as a new change is itself that confirmation, covering the change and the change artifacts the request names; scaffold it first as described below.
|
|
30
42
|
|
|
31
43
|
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
|
|
32
44
|
|
|
33
45
|
${STORE_SELECTION_GUIDANCE}
|
|
34
46
|
|
|
47
|
+
${PROJECT_ROOT_GUARD}
|
|
48
|
+
|
|
35
49
|
---
|
|
36
50
|
|
|
37
51
|
## The Stance
|
|
@@ -112,7 +126,7 @@ openspec list --json
|
|
|
112
126
|
|
|
113
127
|
This tells you:
|
|
114
128
|
- If there are active changes
|
|
115
|
-
- Their names
|
|
129
|
+
- Their names and task status
|
|
116
130
|
- What the user might be working on
|
|
117
131
|
|
|
118
132
|
That is the *change* list - work in flight. It does not include the project's durable capabilities, so list those too:
|
|
@@ -136,14 +150,14 @@ Think freely. When insights crystallize, you might offer:
|
|
|
136
150
|
- "This feels solid enough to start a change. Want me to create a proposal?"
|
|
137
151
|
- Or keep exploring - no pressure to formalize
|
|
138
152
|
|
|
139
|
-
If the user asks you to capture the exploration as a new change,
|
|
153
|
+
If the user asks you to capture the exploration as a new change, that request is the confirmation required above. It covers scaffolding that change and creating the change artifacts the request names, and nothing else. This holds only when the request is theirs: a yes to an offer you made confirms only the scope your offer itself named, so name the change and the artifacts in the offer. Don't re-ask for what they already asked for; do ask before anything beyond it. Transition seamlessly into the requested capture:
|
|
140
154
|
|
|
141
155
|
1. Run \`openspec new change "<name>"\` (with \`--store <id>\` when applicable) before creating any artifacts. Never create a new change directory under \`openspec/changes/\` by hand; the CLI scaffold creates required metadata such as \`.openspec.yaml\`. Keep the selected \`--store <id>\` on every applicable follow-up \`status\` and \`instructions\` command.
|
|
142
156
|
2. Run \`openspec status --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store), then process the requested artifacts in dependency order. For each requested artifact that is \`ready\`, run \`openspec instructions "<artifact-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store). Before creating a requested artifact, evaluate any condition in its own \`instruction\` against the explored change; record a deliberate skip instead when the condition does not apply. If a requested artifact is blocked by a direct prerequisite the user did not request, run \`openspec instructions "<prerequisite-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) for that prerequisite whether it is \`ready\` or \`blocked\`. If its own \`instruction\` states a condition, evaluate that condition against the explored change and record a deliberate skip only when the condition does not apply. If the condition applies, or the prerequisite is not conditional, treat it as a normal prerequisite and ask before expanding the capture. Do not create an unrequested prerequisite unless the user approves.
|
|
143
|
-
3. Follow the returned \`template\` and \`instruction\` fields. Read completed dependency files listed in \`dependencies\`, and apply \`context\` and \`rules\` as constraints without copying them into the artifact. If the instruction delegates creation to a specific skill or command, invoke it
|
|
157
|
+
3. Follow the returned \`template\` and \`instruction\` fields. Read completed dependency files listed in \`dependencies\`, and apply \`context\` and \`rules\` as constraints without copying them into the artifact. Choose the output path before creating anything: when \`resolvedOutputPath\` is a glob, use the instruction to choose a concrete path inside \`changeRoot\` and verify it remains inside \`changeRoot\` after resolving symlinks, both in its parent directories and in the file itself if it already exists; if it does not, stop and tell the user. Otherwise the output path is \`resolvedOutputPath\`. If the instruction delegates creation to a specific skill or command, invoke it only if it can write the artifact to that output path; otherwise stop and tell the user. Otherwise write the artifact to that output path. Verify that the selected concrete output exists at that output path.
|
|
144
158
|
4. After creating each artifact, re-run \`openspec status --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) and continue until every requested artifact is \`done\`, \`skipped\`, or was deliberately skipped because its own \`instruction\` stated a condition that did not apply. Tell the user about a deliberate conditional skip, remember it, and do not reconsider it. Dependencies are enablers, not gates: if a requested artifact is still \`blocked\` only because you deliberately skipped a conditional prerequisite, run \`openspec instructions "<artifact-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) despite the blocked status, then create it using step 3 only when those recorded conditional skips are its sole missing dependencies. If a requested artifact is blocked by a prerequisite the user did not ask to capture and cannot be conditionally skipped, explain that dependency and ask before expanding the capture.
|
|
145
159
|
|
|
146
|
-
Capture the artifact(s) the user requested without asking them to invoke another workflow command. If they asked only to start a change, stop after scaffolding and show its status.
|
|
160
|
+
Capture the artifact(s) the user requested without asking them to invoke another workflow command. If they asked only to start a change, stop after scaffolding and show its status. When the requested capture is done, stop there and name where the work continues: ${CAPTURE_PLANNING_HANDOFF}, and ${CAPTURE_APPLY_HANDOFF}. Capturing artifacts never starts implementing them.
|
|
147
161
|
|
|
148
162
|
### When a change exists
|
|
149
163
|
|
|
@@ -162,6 +176,8 @@ If the user mentions a change or you detect one is relevant:
|
|
|
162
176
|
|
|
163
177
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve an existing capability's full path and follow the project's established organization for new capabilities.
|
|
164
178
|
|
|
179
|
+
The files below are the default spec-driven schema's. With another schema, capture each insight in whichever artifact from \`artifactPaths\` fits it, and name that artifact in your offer; never create an artifact the schema does not define.
|
|
180
|
+
|
|
165
181
|
| Insight Type | Where to Capture |
|
|
166
182
|
|----------------------------|-------------------------------------|
|
|
167
183
|
| New requirement discovered | \`specs/<capability-path>/spec.md\` |
|
|
@@ -171,7 +187,7 @@ If the user mentions a change or you detect one is relevant:
|
|
|
171
187
|
| New work identified | \`tasks.md\` |
|
|
172
188
|
| Assumption invalidated | Relevant artifact |
|
|
173
189
|
|
|
174
|
-
Example offers:
|
|
190
|
+
Example offers (default schema):
|
|
175
191
|
- "That's a design decision. Capture it in design.md?"
|
|
176
192
|
- "This is a new requirement. Add it to specs?"
|
|
177
193
|
- "This changes scope. Update the proposal?"
|
|
@@ -299,8 +315,8 @@ You: That changes everything.
|
|
|
299
315
|
|
|
300
316
|
There's no required ending. Discovery might:
|
|
301
317
|
|
|
302
|
-
- **Flow into a proposal**: "
|
|
303
|
-
- **Result in artifact updates**: "Updated design
|
|
318
|
+
- **Flow into a proposal**: "${DISCOVERY_END_HANDOFF}"
|
|
319
|
+
- **Result in artifact updates**: "Updated the design with these decisions"
|
|
304
320
|
- **Just provide clarity**: User has what they need, moves on
|
|
305
321
|
- **Continue later**: "We can pick this up anytime"
|
|
306
322
|
|
|
@@ -316,7 +332,7 @@ When it feels like things are crystallizing, you might summarize:
|
|
|
316
332
|
**Open questions**: [if any remain]
|
|
317
333
|
|
|
318
334
|
**Next steps** (if ready):
|
|
319
|
-
|
|
335
|
+
${SUMMARY_NEXT_STEP}
|
|
320
336
|
- Keep exploring: just keep talking
|
|
321
337
|
\`\`\`
|
|
322
338
|
|
|
@@ -326,11 +342,11 @@ But this summary is optional. Sometimes the thinking IS the value.
|
|
|
326
342
|
|
|
327
343
|
## Guardrails
|
|
328
344
|
|
|
329
|
-
- **Don't implement** - Never write code or implement features. Workflow configuration counts too: creating or editing schemas, templates, or \`openspec/config.yaml\` is a change, not thinking. Creating or updating OpenSpec change artifacts within the confirmed scope is fine, writing anything else is not.
|
|
345
|
+
- **Don't implement** - Never write code or implement features. Workflow configuration counts too: creating or editing schemas, templates, or \`openspec/config.yaml\` is a change, not thinking. Creating or updating OpenSpec change artifacts within the confirmed scope is fine, writing anything else is not. When the user is ready to build, name the handoff rather than starting: ${GUARDRAIL_HANDOFF}.
|
|
330
346
|
- **Don't fake understanding** - If something is unclear, dig deeper
|
|
331
347
|
- **Don't rush** - Discovery is thinking time, not task time
|
|
332
348
|
- **Don't force structure** - Let patterns emerge naturally
|
|
333
|
-
- **Don't auto-capture** - Offer to save insights, don't just do it. Read-only commands and tools need no confirmation. Before the first write-capable action—including \`openspec new change\` or another command that writes files—name the artifacts or files and proposed changes, ask a direct yes/no question, and wait for explicit confirmation in a separate user message. That confirmation covers only the described scope; ask again before expanding it. Answers to design or clarifying questions are never consent to write.
|
|
349
|
+
- **Don't auto-capture** - Offer to save insights, don't just do it. Read-only commands and tools need no confirmation. Before the first write-capable action—including \`openspec new change\` or another command that writes files—name the artifacts or files and proposed changes, ask a direct yes/no question, and wait for explicit confirmation in a separate user message. That confirmation covers only the described scope; ask again before expanding it. Answers to design or clarifying questions are never consent to write. That rule governs \`openspec new change\` whenever you are the one proposing the capture; the user's own capture request is the exception, handled in the capture transition above.
|
|
334
350
|
- **Don't manually scaffold changes** - Never create a new change directory under \`openspec/changes/\` by hand. Always use \`openspec new change "<name>"\` (with \`--store <id>\` when applicable) so required metadata such as \`.openspec.yaml\` is created before writing artifacts.
|
|
335
351
|
- **Do visualize** - A good diagram is worth many paragraphs
|
|
336
352
|
- **Do explore the codebase** - Ground discussions in reality
|
|
@@ -348,12 +364,14 @@ export function getOpsxExploreCommandTemplate() {
|
|
|
348
364
|
tags: ['workflow', 'explore', 'experimental', 'thinking'],
|
|
349
365
|
content: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
|
|
350
366
|
|
|
351
|
-
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something,
|
|
367
|
+
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, investigate the codebase, and run read-only commands or tools without confirmation, but you must NEVER write code or implement features. If the user asks you to implement something, do not start it here: say that explore mode does not implement, and ${IMPLEMENT_REQUEST_HANDOFF}. The work happens from that change, never from explore mode. You MAY create or update OpenSpec change artifacts (proposals, designs, specs) within a confirmed scope—that's capturing thinking, not implementing. Answering design or clarifying questions is never consent to write. Before the first write-capable action, name the artifacts or files you would change and what you would do, ask a direct yes/no question, and wait for the user's confirmation in a separate message. Confirmation covers only the scope you described; ask again before expanding it. An explicit request from the user to capture the exploration as a new change is itself that confirmation, covering the change and the change artifacts the request names; scaffold it first as described below.
|
|
352
368
|
|
|
353
369
|
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
|
|
354
370
|
|
|
355
371
|
${STORE_SELECTION_GUIDANCE}
|
|
356
372
|
|
|
373
|
+
${PROJECT_ROOT_GUARD}
|
|
374
|
+
|
|
357
375
|
**Input**: The argument after \`/opsx:explore\` is whatever the user wants to think about. Could be:
|
|
358
376
|
- A vague idea: "real-time collaboration"
|
|
359
377
|
- A specific problem: "the auth system is getting unwieldy"
|
|
@@ -441,7 +459,7 @@ openspec list --json
|
|
|
441
459
|
|
|
442
460
|
This tells you:
|
|
443
461
|
- If there are active changes
|
|
444
|
-
- Their names
|
|
462
|
+
- Their names and task status
|
|
445
463
|
- What the user might be working on
|
|
446
464
|
|
|
447
465
|
That is the *change* list - work in flight. It does not include the project's durable capabilities, so list those too:
|
|
@@ -467,14 +485,14 @@ Think freely. When insights crystallize, you might offer:
|
|
|
467
485
|
- "This feels solid enough to start a change. Want me to create a proposal?"
|
|
468
486
|
- Or keep exploring - no pressure to formalize
|
|
469
487
|
|
|
470
|
-
If the user asks you to capture the exploration as a new change,
|
|
488
|
+
If the user asks you to capture the exploration as a new change, that request is the confirmation required above. It covers scaffolding that change and creating the change artifacts the request names, and nothing else. This holds only when the request is theirs: a yes to an offer you made confirms only the scope your offer itself named, so name the change and the artifacts in the offer. Don't re-ask for what they already asked for; do ask before anything beyond it. Transition seamlessly into the requested capture:
|
|
471
489
|
|
|
472
490
|
1. Run \`openspec new change "<name>"\` (with \`--store <id>\` when applicable) before creating any artifacts. Never create a new change directory under \`openspec/changes/\` by hand; the CLI scaffold creates required metadata such as \`.openspec.yaml\`. Keep the selected \`--store <id>\` on every applicable follow-up \`status\` and \`instructions\` command.
|
|
473
491
|
2. Run \`openspec status --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store), then process the requested artifacts in dependency order. For each requested artifact that is \`ready\`, run \`openspec instructions "<artifact-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store). Before creating a requested artifact, evaluate any condition in its own \`instruction\` against the explored change; record a deliberate skip instead when the condition does not apply. If a requested artifact is blocked by a direct prerequisite the user did not request, run \`openspec instructions "<prerequisite-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) for that prerequisite whether it is \`ready\` or \`blocked\`. If its own \`instruction\` states a condition, evaluate that condition against the explored change and record a deliberate skip only when the condition does not apply. If the condition applies, or the prerequisite is not conditional, treat it as a normal prerequisite and ask before expanding the capture. Do not create an unrequested prerequisite unless the user approves.
|
|
474
|
-
3. Follow the returned \`template\` and \`instruction\` fields. Read completed dependency files listed in \`dependencies\`, and apply \`context\` and \`rules\` as constraints without copying them into the artifact. If the instruction delegates creation to a specific skill or command, invoke it
|
|
492
|
+
3. Follow the returned \`template\` and \`instruction\` fields. Read completed dependency files listed in \`dependencies\`, and apply \`context\` and \`rules\` as constraints without copying them into the artifact. Choose the output path before creating anything: when \`resolvedOutputPath\` is a glob, use the instruction to choose a concrete path inside \`changeRoot\` and verify it remains inside \`changeRoot\` after resolving symlinks, both in its parent directories and in the file itself if it already exists; if it does not, stop and tell the user. Otherwise the output path is \`resolvedOutputPath\`. If the instruction delegates creation to a specific skill or command, invoke it only if it can write the artifact to that output path; otherwise stop and tell the user. Otherwise write the artifact to that output path. Verify that the selected concrete output exists at that output path.
|
|
475
493
|
4. After creating each artifact, re-run \`openspec status --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) and continue until every requested artifact is \`done\`, \`skipped\`, or was deliberately skipped because its own \`instruction\` stated a condition that did not apply. Tell the user about a deliberate conditional skip, remember it, and do not reconsider it. Dependencies are enablers, not gates: if a requested artifact is still \`blocked\` only because you deliberately skipped a conditional prerequisite, run \`openspec instructions "<artifact-id>" --change "<name>" --json\` (append the confirmed \`--store "<id>"\` only for a registered standalone store) despite the blocked status, then create it using step 3 only when those recorded conditional skips are its sole missing dependencies. If a requested artifact is blocked by a prerequisite the user did not ask to capture and cannot be conditionally skipped, explain that dependency and ask before expanding the capture.
|
|
476
494
|
|
|
477
|
-
Capture the artifact(s) the user requested without asking them to invoke another workflow command. If they asked only to start a change, stop after scaffolding and show its status.
|
|
495
|
+
Capture the artifact(s) the user requested without asking them to invoke another workflow command. If they asked only to start a change, stop after scaffolding and show its status. When the requested capture is done, stop there and name where the work continues: ${CAPTURE_PLANNING_HANDOFF}, and ${CAPTURE_APPLY_HANDOFF}. Capturing artifacts never starts implementing them.
|
|
478
496
|
|
|
479
497
|
### When a change exists
|
|
480
498
|
|
|
@@ -493,6 +511,8 @@ If the user mentions a change or you detect one is relevant:
|
|
|
493
511
|
|
|
494
512
|
\`<capability-path>\` is the spec directory relative to \`specs/\` (for example, \`user-auth\` or \`identity/user-auth\`). Preserve an existing capability's full path and follow the project's established organization for new capabilities.
|
|
495
513
|
|
|
514
|
+
The files below are the default spec-driven schema's. With another schema, capture each insight in whichever artifact from \`artifactPaths\` fits it, and name that artifact in your offer; never create an artifact the schema does not define.
|
|
515
|
+
|
|
496
516
|
| Insight Type | Where to Capture |
|
|
497
517
|
|----------------------------|-------------------------------------|
|
|
498
518
|
| New requirement discovered | \`specs/<capability-path>/spec.md\` |
|
|
@@ -502,7 +522,7 @@ If the user mentions a change or you detect one is relevant:
|
|
|
502
522
|
| New work identified | \`tasks.md\` |
|
|
503
523
|
| Assumption invalidated | Relevant artifact |
|
|
504
524
|
|
|
505
|
-
Example offers:
|
|
525
|
+
Example offers (default schema):
|
|
506
526
|
- "That's a design decision. Capture it in design.md?"
|
|
507
527
|
- "This is a new requirement. Add it to specs?"
|
|
508
528
|
- "This changes scope. Update the proposal?"
|
|
@@ -526,8 +546,8 @@ If the user mentions a change or you detect one is relevant:
|
|
|
526
546
|
|
|
527
547
|
There's no required ending. Discovery might:
|
|
528
548
|
|
|
529
|
-
- **Flow into a proposal**: "
|
|
530
|
-
- **Result in artifact updates**: "Updated design
|
|
549
|
+
- **Flow into a proposal**: "${DISCOVERY_END_HANDOFF}"
|
|
550
|
+
- **Result in artifact updates**: "Updated the design with these decisions"
|
|
531
551
|
- **Just provide clarity**: User has what they need, moves on
|
|
532
552
|
- **Continue later**: "We can pick this up anytime"
|
|
533
553
|
|
|
@@ -537,11 +557,11 @@ When things crystallize, you might offer a summary - but it's optional. Sometime
|
|
|
537
557
|
|
|
538
558
|
## Guardrails
|
|
539
559
|
|
|
540
|
-
- **Don't implement** - Never write code or implement features. Workflow configuration counts too: creating or editing schemas, templates, or \`openspec/config.yaml\` is a change, not thinking. Creating or updating OpenSpec change artifacts within the confirmed scope is fine, writing anything else is not.
|
|
560
|
+
- **Don't implement** - Never write code or implement features. Workflow configuration counts too: creating or editing schemas, templates, or \`openspec/config.yaml\` is a change, not thinking. Creating or updating OpenSpec change artifacts within the confirmed scope is fine, writing anything else is not. When the user is ready to build, name the handoff rather than starting: ${GUARDRAIL_HANDOFF}.
|
|
541
561
|
- **Don't fake understanding** - If something is unclear, dig deeper
|
|
542
562
|
- **Don't rush** - Discovery is thinking time, not task time
|
|
543
563
|
- **Don't force structure** - Let patterns emerge naturally
|
|
544
|
-
- **Don't auto-capture** - Offer to save insights, don't just do it. Read-only commands and tools need no confirmation. Before the first write-capable action—including \`openspec new change\` or another command that writes files—name the artifacts or files and proposed changes, ask a direct yes/no question, and wait for explicit confirmation in a separate user message. That confirmation covers only the described scope; ask again before expanding it. Answers to design or clarifying questions are never consent to write.
|
|
564
|
+
- **Don't auto-capture** - Offer to save insights, don't just do it. Read-only commands and tools need no confirmation. Before the first write-capable action—including \`openspec new change\` or another command that writes files—name the artifacts or files and proposed changes, ask a direct yes/no question, and wait for explicit confirmation in a separate user message. That confirmation covers only the described scope; ask again before expanding it. Answers to design or clarifying questions are never consent to write. That rule governs \`openspec new change\` whenever you are the one proposing the capture; the user's own capture request is the exception, handled in the capture transition above.
|
|
545
565
|
- **Don't manually scaffold changes** - Never create a new change directory under \`openspec/changes/\` by hand. Always use \`openspec new change "<name>"\` (with \`--store <id>\` when applicable) so required metadata such as \`.openspec.yaml\` is created before writing artifacts.
|
|
546
566
|
- **Do visualize** - A good diagram is worth many paragraphs
|
|
547
567
|
- **Do explore the codebase** - Ground discussions in reality
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared project-root guidance for skill template workflows.
|
|
3
|
+
*
|
|
4
|
+
* Generated skills and commands are installed once per machine, so they are
|
|
5
|
+
* offered in every repository the agent opens - including repositories that
|
|
6
|
+
* never ran `openspec init`. Nothing stops the workflow there: `openspec new
|
|
7
|
+
* change` falls back to an implicit root and creates `openspec/` in whatever
|
|
8
|
+
* directory the agent happens to be in.
|
|
9
|
+
*
|
|
10
|
+
* This guidance is interpolated into every workflow so the agent checks for a
|
|
11
|
+
* root before writing. `openspec list --json` is the check because it refuses
|
|
12
|
+
* to fabricate an implicit root: it reports `root: null` both when nothing is
|
|
13
|
+
* set up and when only stores are registered.
|
|
14
|
+
*
|
|
15
|
+
* What follows the check depends on how the workflow was reached, because the
|
|
16
|
+
* two cases want opposite things. A skill the model picked on its own in an
|
|
17
|
+
* unrelated repository must get out of the way: the user asked for help, not
|
|
18
|
+
* for OpenSpec, and answering with a setup menu is the reported failure mode.
|
|
19
|
+
* A user who named OpenSpec, named the skill, or ran its slash command is
|
|
20
|
+
* owed an answer about OpenSpec, so that case stops and asks.
|
|
21
|
+
*
|
|
22
|
+
* One text serves both surfaces. `apply-change` and `onboard` render a single
|
|
23
|
+
* body into the skill and the command alike, so a command-only variant would
|
|
24
|
+
* mean threading a surface flag through bodies that deliberately have none.
|
|
25
|
+
* The bullets scope themselves instead: a slash command is an explicit
|
|
26
|
+
* invocation, so its branch is the only one that can apply there.
|
|
27
|
+
*
|
|
28
|
+
* FreeHarness emits no store-selection commands, so this guard never reads
|
|
29
|
+
* `root: null` for a declared-but-unresolved store: the check and its explicit
|
|
30
|
+
* branch both stay free of `--store`, unlike the upstream template.
|
|
31
|
+
*/
|
|
32
|
+
export declare const PROJECT_ROOT_GUARD = "**Project check:** These steps expect a project that already uses OpenSpec. Before the first step that writes anything (`new change`, `archive`, `sync specs`, or authoring an artifact file), confirm the project has a root: run `openspec list --json` and read `root`. A root object means the project is set up. `\"root\": null` means it is not - there is no `openspec/` directory here, and a write such as `openspec new change` would create one as a side effect. The command also exits non-zero, which is that answer rather than a broken CLI, so read the JSON instead of retrying or working around it.\n\nWith no root, what happens next depends on how this workflow was reached:\n\n- **Auto-selected**: you chose this workflow yourself, without the user naming OpenSpec, naming this skill, or running its slash command. Stop using OpenSpec and answer the request normally, as you would with no OpenSpec installed. Do not ask them to set anything up and do not mention OpenSpec setup.\n- **Explicit OpenSpec request**: the user named OpenSpec, named this skill, or ran its slash command. Stop before writing and ask how to proceed: set this project up (`freeharness bootstrap`), or continue without OpenSpec for this request. Wait for their answer.\n\nIn both branches, never create the root as a side effect: do not run `freeharness bootstrap` until the user asks for it, do not hand-create `openspec/` files, and do not let a command create it.";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared project-root guidance for skill template workflows.
|
|
3
|
+
*
|
|
4
|
+
* Generated skills and commands are installed once per machine, so they are
|
|
5
|
+
* offered in every repository the agent opens - including repositories that
|
|
6
|
+
* never ran `openspec init`. Nothing stops the workflow there: `openspec new
|
|
7
|
+
* change` falls back to an implicit root and creates `openspec/` in whatever
|
|
8
|
+
* directory the agent happens to be in.
|
|
9
|
+
*
|
|
10
|
+
* This guidance is interpolated into every workflow so the agent checks for a
|
|
11
|
+
* root before writing. `openspec list --json` is the check because it refuses
|
|
12
|
+
* to fabricate an implicit root: it reports `root: null` both when nothing is
|
|
13
|
+
* set up and when only stores are registered.
|
|
14
|
+
*
|
|
15
|
+
* What follows the check depends on how the workflow was reached, because the
|
|
16
|
+
* two cases want opposite things. A skill the model picked on its own in an
|
|
17
|
+
* unrelated repository must get out of the way: the user asked for help, not
|
|
18
|
+
* for OpenSpec, and answering with a setup menu is the reported failure mode.
|
|
19
|
+
* A user who named OpenSpec, named the skill, or ran its slash command is
|
|
20
|
+
* owed an answer about OpenSpec, so that case stops and asks.
|
|
21
|
+
*
|
|
22
|
+
* One text serves both surfaces. `apply-change` and `onboard` render a single
|
|
23
|
+
* body into the skill and the command alike, so a command-only variant would
|
|
24
|
+
* mean threading a surface flag through bodies that deliberately have none.
|
|
25
|
+
* The bullets scope themselves instead: a slash command is an explicit
|
|
26
|
+
* invocation, so its branch is the only one that can apply there.
|
|
27
|
+
*
|
|
28
|
+
* FreeHarness emits no store-selection commands, so this guard never reads
|
|
29
|
+
* `root: null` for a declared-but-unresolved store: the check and its explicit
|
|
30
|
+
* branch both stay free of `--store`, unlike the upstream template.
|
|
31
|
+
*/
|
|
32
|
+
export const PROJECT_ROOT_GUARD = `**Project check:** These steps expect a project that already uses OpenSpec. Before the first step that writes anything (\`new change\`, \`archive\`, \`sync specs\`, or authoring an artifact file), confirm the project has a root: run \`openspec list --json\` and read \`root\`. A root object means the project is set up. \`"root": null\` means it is not - there is no \`openspec/\` directory here, and a write such as \`openspec new change\` would create one as a side effect. The command also exits non-zero, which is that answer rather than a broken CLI, so read the JSON instead of retrying or working around it.
|
|
33
|
+
|
|
34
|
+
With no root, what happens next depends on how this workflow was reached:
|
|
35
|
+
|
|
36
|
+
- **Auto-selected**: you chose this workflow yourself, without the user naming OpenSpec, naming this skill, or running its slash command. Stop using OpenSpec and answer the request normally, as you would with no OpenSpec installed. Do not ask them to set anything up and do not mention OpenSpec setup.
|
|
37
|
+
- **Explicit OpenSpec request**: the user named OpenSpec, named this skill, or ran its slash command. Stop before writing and ask how to proceed: set this project up (\`freeharness bootstrap\`), or continue without OpenSpec for this request. Wait for their answer.
|
|
38
|
+
|
|
39
|
+
In both branches, never create the root as a side effect: do not run \`freeharness bootstrap\` until the user asks for it, do not hand-create \`openspec/\` files, and do not let a command create it.`;
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';
|
|
2
|
+
import { PROJECT_ROOT_GUARD } from './project-root.js';
|
|
2
3
|
export function getOpsxProposeSkillTemplate() {
|
|
3
4
|
return {
|
|
4
5
|
name: 'openspec-propose',
|
|
5
|
-
description: 'Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.',
|
|
6
|
+
description: 'Propose a new OpenSpec change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.',
|
|
6
7
|
instructions: `Propose a new change - create the change and generate all artifacts in one step.
|
|
7
8
|
|
|
8
9
|
**Planning boundary**: This workflow creates planning artifacts only. The user request that selected or triggered this workflow authorizes planning only, even if it asks to build or fix something. Do not edit project code. After the planning artifacts are complete, stop. Do not start implementation in the same response, even if the initial request asks for it. Wait for a new user request after the artifacts are presented; then start the apply workflow.
|
|
@@ -21,6 +22,8 @@ When the user is ready to implement, they must start the apply workflow explicit
|
|
|
21
22
|
|
|
22
23
|
${STORE_SELECTION_GUIDANCE}
|
|
23
24
|
|
|
25
|
+
${PROJECT_ROOT_GUARD}
|
|
26
|
+
|
|
24
27
|
**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
|
|
25
28
|
|
|
26
29
|
**Steps**
|
|
@@ -38,7 +41,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
38
41
|
|
|
39
42
|
2. **Load project context**
|
|
40
43
|
|
|
41
|
-
Run \`openspec context --json\` from the current working directory. Use the returned \`root.path\` as the authoritative OpenSpec root. If context reports \`no_openspec_root\`, stop without creating or changing any files. Offer \`
|
|
44
|
+
Run \`openspec context --json\` from the current working directory. Use the returned \`root.path\` as the authoritative OpenSpec root. If context reports \`no_openspec_root\`, stop without creating or changing any files and follow the **Project check** above for how this workflow was reached. Offer \`freeharness bootstrap\` only for an explicit OpenSpec request, and wait for the user to request initialization. Do not initialize automatically or run \`openspec new change\`. After initialization, rerun this context check before continuing. For any other context failure, stop and report the error; do not fall back to the current directory or run later OpenSpec commands.
|
|
42
45
|
|
|
43
46
|
Only when context returns a resolved \`root.path\`, read \`<root.path>/openspec/config.yaml\`. Use \`config.yml\` only when \`config.yaml\` does not exist. If neither file exists, continue without project context. Do not fall back to \`config.yml\` if \`config.yaml\` is unreadable or invalid.
|
|
44
47
|
|
|
@@ -105,8 +108,9 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
105
108
|
- Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct.
|
|
106
109
|
- Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question.
|
|
107
110
|
- **Supersession check (FreeHarness)**: before drafting the proposal, search \`openspec/specs\` and \`openspec/changes/archive\` for an existing decision or mechanism on the same subject (grep the requirement names and the design Decision titles). When one exists, this change supersedes it explicitly: name it in the proposal and add a \`Supersedes: <change-id>\` line at the top of design.md so archive cross-links both ways (the archived record keeps its text and receives \`Superseded-by: <this change>\`). Never edit a published decision in place into a different decision; a partially superseded decision stays active and cross-linked.
|
|
108
|
-
-
|
|
109
|
-
-
|
|
111
|
+
- Choose the output path before creating anything. If \`resolvedOutputPath\` is a glob, follow \`instruction\` to choose a concrete path inside \`changeRoot\` that matches the glob, and verify it remains inside \`changeRoot\` after resolving symlinks, both in its parent directories and in the file itself if it already exists; if it does not, stop and tell the user. Otherwise the output path is \`resolvedOutputPath\`
|
|
112
|
+
- If the \`instruction\` field delegates creation to a specific skill or command, invoke it only if it can write the artifact to that output path; otherwise stop and tell the user. Then verify the artifact file exists at that output path
|
|
113
|
+
- Otherwise create the artifact file using \`template\` as the structure and write it to that output path
|
|
110
114
|
- Apply \`context\` and \`rules\` as constraints - but do NOT copy them into the file
|
|
111
115
|
- Show brief progress: "Created <artifact-id>"
|
|
112
116
|
|
|
@@ -140,7 +144,7 @@ After completing all artifacts, summarize:
|
|
|
140
144
|
**Artifact Creation Guidelines**
|
|
141
145
|
|
|
142
146
|
- Follow the \`instruction\` field from \`openspec instructions\` for each artifact type - it is the authoritative guidance, even for familiar artifact names
|
|
143
|
-
- If the \`instruction\` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly
|
|
147
|
+
- If the \`instruction\` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly - but only once you have chosen and checked the output path, and only if it can write there
|
|
144
148
|
- The schema defines what each artifact should contain - follow it
|
|
145
149
|
- Read dependency artifacts for context before creating new ones
|
|
146
150
|
- Use \`template\` as the structure for your output file - fill in its sections
|
|
@@ -184,6 +188,8 @@ When the user is ready to implement, they must start the apply workflow explicit
|
|
|
184
188
|
|
|
185
189
|
${STORE_SELECTION_GUIDANCE}
|
|
186
190
|
|
|
191
|
+
${PROJECT_ROOT_GUARD}
|
|
192
|
+
|
|
187
193
|
**Input**: The argument after \`/opsx:propose\` is the change name (kebab-case), OR a description of what the user wants to build.
|
|
188
194
|
|
|
189
195
|
**Steps**
|
|
@@ -201,7 +207,7 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
201
207
|
|
|
202
208
|
2. **Load project context**
|
|
203
209
|
|
|
204
|
-
Run \`openspec context --json\` from the current working directory. Use the returned \`root.path\` as the authoritative OpenSpec root. If context reports \`no_openspec_root\`, stop without creating or changing any files. Offer \`
|
|
210
|
+
Run \`openspec context --json\` from the current working directory. Use the returned \`root.path\` as the authoritative OpenSpec root. If context reports \`no_openspec_root\`, stop without creating or changing any files and follow the **Project check** above for how this workflow was reached. Offer \`freeharness bootstrap\` only for an explicit OpenSpec request, and wait for the user to request initialization. Do not initialize automatically or run \`openspec new change\`. After initialization, rerun this context check before continuing. For any other context failure, stop and report the error; do not fall back to the current directory or run later OpenSpec commands.
|
|
205
211
|
|
|
206
212
|
Only when context returns a resolved \`root.path\`, read \`<root.path>/openspec/config.yaml\`. Use \`config.yml\` only when \`config.yaml\` does not exist. If neither file exists, continue without project context. Do not fall back to \`config.yml\` if \`config.yaml\` is unreadable or invalid.
|
|
207
213
|
|
|
@@ -268,8 +274,9 @@ ${STORE_SELECTION_GUIDANCE}
|
|
|
268
274
|
- Ground scope, approach, and tasks in what you find. Distinguish observed behavior from assumptions and proposed additions; surface conflicts with existing specs instead of silently deciding which is correct.
|
|
269
275
|
- Do this discovery now, rather than leaving generic "explore the codebase" or "make a plan" tasks for implementation. Keep any necessary follow-up investigation specific to an unresolved question.
|
|
270
276
|
- **Supersession check (FreeHarness)**: before drafting the proposal, search \`openspec/specs\` and \`openspec/changes/archive\` for an existing decision or mechanism on the same subject (grep the requirement names and the design Decision titles). When one exists, this change supersedes it explicitly: name it in the proposal and add a \`Supersedes: <change-id>\` line at the top of design.md so archive cross-links both ways (the archived record keeps its text and receives \`Superseded-by: <this change>\`). Never edit a published decision in place into a different decision; a partially superseded decision stays active and cross-linked.
|
|
271
|
-
-
|
|
272
|
-
-
|
|
277
|
+
- Choose the output path before creating anything. If \`resolvedOutputPath\` is a glob, follow \`instruction\` to choose a concrete path inside \`changeRoot\` that matches the glob, and verify it remains inside \`changeRoot\` after resolving symlinks, both in its parent directories and in the file itself if it already exists; if it does not, stop and tell the user. Otherwise the output path is \`resolvedOutputPath\`
|
|
278
|
+
- If the \`instruction\` field delegates creation to a specific skill or command, invoke it only if it can write the artifact to that output path; otherwise stop and tell the user. Then verify the artifact file exists at that output path
|
|
279
|
+
- Otherwise create the artifact file using \`template\` as the structure and write it to that output path
|
|
273
280
|
- Apply \`context\` and \`rules\` as constraints - but do NOT copy them into the file
|
|
274
281
|
- Show brief progress: "Created <artifact-id>"
|
|
275
282
|
|
|
@@ -303,7 +310,7 @@ After completing all artifacts, summarize:
|
|
|
303
310
|
**Artifact Creation Guidelines**
|
|
304
311
|
|
|
305
312
|
- Follow the \`instruction\` field from \`openspec instructions\` for each artifact type - it is the authoritative guidance, even for familiar artifact names
|
|
306
|
-
- If the \`instruction\` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly
|
|
313
|
+
- If the \`instruction\` field directs you to use a specific skill or command to create the artifact, invoke it instead of writing the artifact directly - but only once you have chosen and checked the output path, and only if it can write there
|
|
307
314
|
- The schema defines what each artifact should contain - follow it
|
|
308
315
|
- Read dependency artifacts for context before creating new ones
|
|
309
316
|
- Use \`template\` as the structure for your output file - fill in its sections
|