@fission-ai/openspec 1.13.1 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/dist/cli/index.js +39 -1
- package/dist/commands/spec.js +1 -0
- package/dist/commands/workflow/instructions.js +66 -18
- package/dist/commands/workflow/shared.d.ts +7 -0
- package/dist/commands/workflow/status.js +15 -2
- package/dist/core/archive.js +258 -78
- package/dist/core/artifact-graph/instruction-loader.d.ts +7 -0
- package/dist/core/artifact-graph/instruction-loader.js +18 -1
- package/dist/core/artifact-graph/outputs.d.ts +1 -1
- package/dist/core/artifact-graph/outputs.js +38 -8
- package/dist/core/change-metadata/schema.d.ts +3 -0
- package/dist/core/change-metadata/schema.js +10 -0
- package/dist/core/change-status-policy.d.ts +8 -0
- package/dist/core/change-status-policy.js +33 -2
- package/dist/core/command-generation/adapters/atomcode.d.ts +24 -0
- package/dist/core/command-generation/adapters/atomcode.js +46 -0
- package/dist/core/command-generation/adapters/codestudio.d.ts +13 -0
- package/dist/core/command-generation/adapters/codestudio.js +27 -0
- package/dist/core/command-generation/adapters/continue.js +4 -0
- package/dist/core/command-generation/adapters/easycode.d.ts +17 -0
- package/dist/core/command-generation/adapters/easycode.js +28 -0
- package/dist/core/command-generation/adapters/gemini.js +1 -35
- package/dist/core/command-generation/adapters/gigacode.d.ts +17 -0
- package/dist/core/command-generation/adapters/gigacode.js +31 -0
- package/dist/core/command-generation/adapters/index.d.ts +4 -0
- package/dist/core/command-generation/adapters/index.js +4 -0
- package/dist/core/command-generation/adapters/kilocode.d.ts +1 -1
- package/dist/core/command-generation/adapters/kilocode.js +2 -2
- package/dist/core/command-generation/registry.js +8 -0
- package/dist/core/command-generation/toml.d.ts +19 -0
- package/dist/core/command-generation/toml.js +39 -0
- package/dist/core/command-surface.js +1 -1
- package/dist/core/completions/command-registry.js +19 -0
- package/dist/core/completions/installers/zsh-installer.js +4 -2
- package/dist/core/config-prompts.js +6 -6
- package/dist/core/config.js +11 -1
- package/dist/core/init.js +44 -14
- package/dist/core/legacy-cleanup.d.ts +1 -1
- package/dist/core/legacy-cleanup.js +40 -11
- package/dist/core/list.d.ts +2 -0
- package/dist/core/list.js +49 -23
- package/dist/core/parsers/markdown-parser.js +5 -0
- package/dist/core/parsers/requirement-blocks.d.ts +40 -3
- package/dist/core/parsers/requirement-blocks.js +74 -25
- package/dist/core/project-config.js +45 -1
- package/dist/core/references.js +3 -1
- package/dist/core/root-selection.d.ts +6 -0
- package/dist/core/root-selection.js +16 -0
- package/dist/core/schemas/base.schema.d.ts +3 -0
- package/dist/core/schemas/base.schema.js +6 -0
- package/dist/core/schemas/change.schema.d.ts +8 -0
- package/dist/core/schemas/spec.schema.d.ts +2 -0
- package/dist/core/specs-apply.d.ts +20 -0
- package/dist/core/specs-apply.js +19 -6
- package/dist/core/templates/workflows/apply-change.js +5 -2
- package/dist/core/templates/workflows/archive-change.js +56 -20
- package/dist/core/templates/workflows/bulk-archive-change.js +34 -16
- 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/constants.d.ts +1 -1
- package/dist/core/validation/constants.js +1 -1
- package/dist/core/validation/purpose-placeholder.js +24 -9
- package/dist/core/validation/validator.js +15 -6
- package/dist/core/version-check.d.ts +23 -1
- package/dist/core/version-check.js +112 -26
- package/dist/core/view.d.ts +2 -0
- package/dist/core/view.js +62 -4
- package/dist/utils/change-metadata.d.ts +20 -1
- package/dist/utils/change-metadata.js +57 -1
- package/dist/utils/command-references.d.ts +1 -1
- package/dist/utils/command-references.js +2 -2
- package/dist/utils/file-system.js +20 -3
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- 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 +10 -1
- package/schemas/spec-driven/templates/proposal.md +6 -3
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { validateChangeName, createChange } from './change-utils.js';
|
|
2
2
|
export type { ValidationResult, CreateChangeOptions } from './change-utils.js';
|
|
3
|
-
export { readChangeMetadata, writeChangeMetadata, resolveSchemaForChange, validateSchemaName, ChangeMetadataError, } from './change-metadata.js';
|
|
3
|
+
export { readChangeMetadata, writeChangeMetadata, resolveSchemaForChange, validateSchemaName, ChangeMetadataError, listUnknownChangeMetadataKeys, readUnknownChangeMetadataKeys, formatUnknownChangeMetadataKeysMessage, CHANGE_METADATA_KNOWN_KEYS, } from './change-metadata.js';
|
|
4
4
|
export { FileSystemUtils, removeMarkerBlock } from './file-system.js';
|
|
5
5
|
export { transformCommandInvocations, transformToSkillReferences, getSkillReferenceTransformer, getTransformerForTool, } from './command-references.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/utils/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Shared utilities
|
|
2
2
|
export { validateChangeName, createChange } from './change-utils.js';
|
|
3
3
|
// Change metadata utilities
|
|
4
|
-
export { readChangeMetadata, writeChangeMetadata, resolveSchemaForChange, validateSchemaName, ChangeMetadataError, } from './change-metadata.js';
|
|
4
|
+
export { readChangeMetadata, writeChangeMetadata, resolveSchemaForChange, validateSchemaName, ChangeMetadataError, listUnknownChangeMetadataKeys, readUnknownChangeMetadataKeys, formatUnknownChangeMetadataKeysMessage, CHANGE_METADATA_KNOWN_KEYS, } from './change-metadata.js';
|
|
5
5
|
// File system utilities
|
|
6
6
|
export { FileSystemUtils, removeMarkerBlock } from './file-system.js';
|
|
7
7
|
// Command reference utilities
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line-ending helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every parser in this codebase normalizes CRLF to LF on the way in, so all
|
|
5
|
+
* serialization logic can assume '\n'. That leaves the write side responsible
|
|
6
|
+
* for restoring whatever convention the file already used: without it, editing
|
|
7
|
+
* one requirement in a CRLF spec rewrites every line of the file and buries the
|
|
8
|
+
* real change in the diff.
|
|
9
|
+
*/
|
|
10
|
+
export type LineEnding = '\n' | '\r\n';
|
|
11
|
+
/**
|
|
12
|
+
* The dominant line ending in `content`, or undefined when it holds no line
|
|
13
|
+
* break to judge from.
|
|
14
|
+
*
|
|
15
|
+
* Mixed files resolve to whichever ending is more common, with CRLF winning a
|
|
16
|
+
* tie: a file that is mostly CRLF is a CRLF file that picked up a stray LF, and
|
|
17
|
+
* settling the whole file on one ending is what keeps later diffs small.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectLineEnding(content: string): LineEnding | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Re-apply `ending` to LF-normalized `content`.
|
|
22
|
+
*
|
|
23
|
+
* Normalizes to LF first, so the result is uniform even if the caller passed
|
|
24
|
+
* content that already contained CRLF.
|
|
25
|
+
*/
|
|
26
|
+
export declare function applyLineEnding(content: string, ending: LineEnding): string;
|
|
27
|
+
/**
|
|
28
|
+
* Rewrite `content` to match the convention of `original`.
|
|
29
|
+
*
|
|
30
|
+
* When `original` has no line break to learn from, `content` is left as LF —
|
|
31
|
+
* the portable default this project writes new files with.
|
|
32
|
+
*/
|
|
33
|
+
export declare function matchLineEnding(content: string, original: string): string;
|
|
34
|
+
//# sourceMappingURL=line-endings.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line-ending helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every parser in this codebase normalizes CRLF to LF on the way in, so all
|
|
5
|
+
* serialization logic can assume '\n'. That leaves the write side responsible
|
|
6
|
+
* for restoring whatever convention the file already used: without it, editing
|
|
7
|
+
* one requirement in a CRLF spec rewrites every line of the file and buries the
|
|
8
|
+
* real change in the diff.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The dominant line ending in `content`, or undefined when it holds no line
|
|
12
|
+
* break to judge from.
|
|
13
|
+
*
|
|
14
|
+
* Mixed files resolve to whichever ending is more common, with CRLF winning a
|
|
15
|
+
* tie: a file that is mostly CRLF is a CRLF file that picked up a stray LF, and
|
|
16
|
+
* settling the whole file on one ending is what keeps later diffs small.
|
|
17
|
+
*/
|
|
18
|
+
export function detectLineEnding(content) {
|
|
19
|
+
const crlf = content.match(/\r\n/g)?.length ?? 0;
|
|
20
|
+
// Count LFs not preceded by CR, so CRLF is never also counted as LF.
|
|
21
|
+
const lf = content.match(/(?<!\r)\n/g)?.length ?? 0;
|
|
22
|
+
if (crlf === 0 && lf === 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
return crlf >= lf ? '\r\n' : '\n';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Re-apply `ending` to LF-normalized `content`.
|
|
28
|
+
*
|
|
29
|
+
* Normalizes to LF first, so the result is uniform even if the caller passed
|
|
30
|
+
* content that already contained CRLF.
|
|
31
|
+
*/
|
|
32
|
+
export function applyLineEnding(content, ending) {
|
|
33
|
+
const normalized = content.replace(/\r\n/g, '\n');
|
|
34
|
+
return ending === '\n' ? normalized : normalized.replace(/\n/g, '\r\n');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Rewrite `content` to match the convention of `original`.
|
|
38
|
+
*
|
|
39
|
+
* When `original` has no line break to learn from, `content` is left as LF —
|
|
40
|
+
* the portable default this project writes new files with.
|
|
41
|
+
*/
|
|
42
|
+
export function matchLineEnding(content, original) {
|
|
43
|
+
const ending = detectLineEnding(original);
|
|
44
|
+
return ending === undefined ? content : applyLineEnding(content, ending);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=line-endings.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fission-ai/openspec",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "AI-native system for spec-driven development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openspec",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"vitest": "^4.1.11"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@inquirer/core": "^
|
|
55
|
+
"@inquirer/core": "^12.0.0",
|
|
56
56
|
"@inquirer/prompts": "^8.5.2",
|
|
57
57
|
"chalk": "^5.6.2",
|
|
58
58
|
"commander": "^14.0.0",
|
|
@@ -13,7 +13,7 @@ artifacts:
|
|
|
13
13
|
- **Why**: 1-2 sentences on the problem or opportunity. What problem does this solve? Why now?
|
|
14
14
|
- **What Changes**: Bullet list of changes. Be specific about new capabilities, modifications, or removals. Mark breaking changes with **BREAKING**.
|
|
15
15
|
- **Capabilities**: Identify which specs will be created or modified:
|
|
16
|
-
- **New Capabilities**: List capabilities being introduced. Each becomes a new `specs/<capability-path>/spec.md`. Use kebab-case for path segments you introduce (e.g., `user-auth` or `identity/user-auth`) and follow the project's existing spec organization.
|
|
16
|
+
- **New Capabilities**: List capabilities being introduced. Each becomes a new `specs/<capability-path>/spec.md`. Name each capability for a durable system behavior (for example, `user-auth`), not the work in this change (for example, `add-login-endpoint`). Choose a cohesive boundary that can own related requirements as the system evolves; avoid broad catch-all capabilities. Use kebab-case for path segments you introduce (e.g., `user-auth` or `identity/user-auth`) and follow the project's existing spec organization.
|
|
17
17
|
- **Modified Capabilities**: List existing capabilities whose REQUIREMENTS are changing. Only include if spec-level behavior changes (not just implementation details). Each needs a delta spec file. Use the exact existing path under `openspec/specs/`. Leave empty if no requirement changes.
|
|
18
18
|
- **Impact**: Affected code, APIs, dependencies, or systems.
|
|
19
19
|
|
|
@@ -94,6 +94,7 @@ artifacts:
|
|
|
94
94
|
- Each scenario: `#### Scenario: <name>` with WHEN/THEN format
|
|
95
95
|
- **CRITICAL**: Scenarios MUST use exactly 4 hashtags (`####`). Using 3 hashtags or bullets will fail silently.
|
|
96
96
|
- Every requirement MUST have at least one scenario.
|
|
97
|
+
- Keep each requirement's description (the text between `### Requirement:` and its first scenario) to 500 characters or fewer. `openspec validate` flags longer descriptions once they reach the main spec. This is an informational hint, not an error. When writing a new requirement, state one behavior per requirement: move examples and edge cases into scenarios, and split a requirement that covers several behaviors into separate `### Requirement:` blocks, each with its own scenarios. Under MODIFIED, keep the existing requirement block whole; never split, trim or rewrite existing text just to meet the length.
|
|
97
98
|
|
|
98
99
|
New capabilities only: the delta spec's first section is `## Purpose` -
|
|
99
100
|
one or two sentences (50+ characters, or `openspec validate --strict`
|
|
@@ -210,6 +211,13 @@ artifacts:
|
|
|
210
211
|
that task's checkbox description. Use a separate verification task only
|
|
211
212
|
when it checks broader integration or system behavior that spans
|
|
212
213
|
multiple implementation tasks.
|
|
214
|
+
- Each task group MUST land the tests and documentation its own work
|
|
215
|
+
calls for. Do NOT collect testing or documentation into a final group -
|
|
216
|
+
when a late group first exercises work from an early one, the failures
|
|
217
|
+
cascade back through every group in between and force rework. A group
|
|
218
|
+
whose work calls for neither, such as scaffolding or dependency setup,
|
|
219
|
+
carries neither. A final group is for integration checks only, not for
|
|
220
|
+
the tests and docs an earlier group owed.
|
|
213
221
|
|
|
214
222
|
Example:
|
|
215
223
|
```
|
|
@@ -224,6 +232,7 @@ artifacts:
|
|
|
224
232
|
|
|
225
233
|
- [ ] 2.1 Implement data export function and verify the export test passes
|
|
226
234
|
- [ ] 2.2 Add CSV formatting utilities and verify unit tests cover quoting and delimiters
|
|
235
|
+
- [ ] 2.3 Document the export API in docs/export.md and verify the documented command runs as written
|
|
227
236
|
```
|
|
228
237
|
|
|
229
238
|
Reference specs for what needs to be built, design for how to build it.
|
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
## Capabilities
|
|
12
12
|
|
|
13
13
|
### New Capabilities
|
|
14
|
-
<!-- Capabilities being introduced.
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
<!-- Capabilities being introduced. Name each capability for a cohesive system
|
|
15
|
+
behavior that can own related requirements as the system evolves. Do not name
|
|
16
|
+
implementation tasks or proposal sections. Avoid broad catch-all names. Use
|
|
17
|
+
kebab-case for path segments you introduce (e.g., user-auth or identity/user-auth)
|
|
18
|
+
that follow the project's existing spec organization. Each creates
|
|
19
|
+
specs/<capability-path>/spec.md. -->
|
|
17
20
|
- `<capability-path>`: <brief description of what this capability covers>
|
|
18
21
|
|
|
19
22
|
### Modified Capabilities
|