@fission-ai/openspec 1.4.1 → 1.6.0-beta.1
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 +37 -4
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +95 -95
- package/dist/commands/change.d.ts +5 -2
- package/dist/commands/change.js +23 -55
- package/dist/commands/config.js +6 -65
- package/dist/commands/context.d.ts +3 -0
- package/dist/commands/context.js +155 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.js +163 -0
- package/dist/commands/shared-gather.d.ts +14 -0
- package/dist/commands/shared-gather.js +31 -0
- package/dist/commands/shared-output.d.ts +18 -0
- package/dist/commands/shared-output.js +61 -0
- package/dist/commands/show.d.ts +11 -6
- package/dist/commands/show.js +70 -25
- package/dist/commands/spec.d.ts +5 -1
- package/dist/commands/spec.js +15 -4
- package/dist/commands/store.d.ts +3 -0
- package/dist/commands/store.js +547 -0
- package/dist/commands/validate.d.ts +10 -0
- package/dist/commands/validate.js +88 -40
- package/dist/commands/workflow/index.d.ts +0 -2
- package/dist/commands/workflow/index.js +0 -1
- package/dist/commands/workflow/instructions.d.ts +11 -1
- package/dist/commands/workflow/instructions.js +71 -22
- package/dist/commands/workflow/new-change.d.ts +6 -3
- package/dist/commands/workflow/new-change.js +42 -77
- package/dist/commands/workflow/shared.d.ts +15 -3
- package/dist/commands/workflow/shared.js +20 -3
- package/dist/commands/workflow/status.d.ts +2 -0
- package/dist/commands/workflow/status.js +19 -17
- package/dist/commands/workset-input.d.ts +19 -0
- package/dist/commands/workset-input.js +112 -0
- package/dist/commands/workset-prompts.d.ts +12 -0
- package/dist/commands/workset-prompts.js +143 -0
- package/dist/commands/workset.d.ts +25 -0
- package/dist/commands/workset.js +446 -0
- package/dist/core/archive.d.ts +17 -6
- package/dist/core/archive.js +220 -68
- package/dist/core/artifact-graph/index.d.ts +1 -1
- package/dist/core/artifact-graph/instruction-loader.d.ts +18 -13
- package/dist/core/artifact-graph/instruction-loader.js +8 -31
- package/dist/core/change-metadata/schema.d.ts +1 -0
- package/dist/core/change-metadata/schema.js +4 -2
- package/dist/core/change-status-policy.d.ts +5 -18
- package/dist/core/change-status-policy.js +2 -37
- package/dist/core/command-generation/adapters/bob.js +1 -14
- package/dist/core/command-generation/adapters/claude.d.ts +1 -1
- package/dist/core/command-generation/adapters/claude.js +4 -15
- package/dist/core/command-generation/adapters/cursor.js +1 -14
- package/dist/core/command-generation/adapters/index.d.ts +2 -0
- package/dist/core/command-generation/adapters/index.js +2 -0
- package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
- package/dist/core/command-generation/adapters/oh-my-pi.js +44 -0
- package/dist/core/command-generation/adapters/pi.js +1 -14
- package/dist/core/command-generation/adapters/trae.d.ts +13 -0
- package/dist/core/command-generation/adapters/trae.js +48 -0
- package/dist/core/command-generation/adapters/windsurf.js +1 -14
- package/dist/core/command-generation/registry.js +4 -0
- package/dist/core/command-generation/yaml.d.ts +22 -0
- package/dist/core/command-generation/yaml.js +38 -0
- package/dist/core/completions/command-registry.js +87 -289
- package/dist/core/completions/generators/zsh-generator.js +3 -1
- package/dist/core/completions/installers/bash-installer.js +3 -0
- package/dist/core/completions/installers/fish-installer.js +8 -0
- package/dist/core/completions/installers/powershell-installer.js +30 -2
- package/dist/core/completions/installers/zsh-installer.js +3 -0
- package/dist/core/completions/shared-flags.d.ts +1 -0
- package/dist/core/completions/shared-flags.js +5 -0
- package/dist/core/config-schema.d.ts +2 -1
- package/dist/core/config-schema.js +26 -0
- package/dist/core/config.js +1 -0
- package/dist/core/file-state.d.ts +36 -0
- package/dist/core/file-state.js +112 -0
- package/dist/core/global-config.d.ts +2 -0
- package/dist/core/id.d.ts +17 -0
- package/dist/core/id.js +30 -0
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/core/init.js +27 -6
- package/dist/core/list.d.ts +2 -0
- package/dist/core/list.js +37 -14
- package/dist/core/openers.d.ts +77 -0
- package/dist/core/openers.js +251 -0
- package/dist/core/openspec-root.d.ts +45 -0
- package/dist/core/openspec-root.js +195 -0
- package/dist/core/parsers/change-parser.js +2 -1
- package/dist/core/parsers/markdown-parser.d.ts +0 -3
- package/dist/core/parsers/markdown-parser.js +5 -59
- package/dist/core/parsers/requirement-blocks.d.ts +11 -0
- package/dist/core/parsers/requirement-blocks.js +42 -8
- package/dist/core/parsers/requirement-text.d.ts +55 -0
- package/dist/core/parsers/requirement-text.js +136 -0
- package/dist/core/planning-home.d.ts +1 -6
- package/dist/core/planning-home.js +2 -43
- package/dist/core/profile-sync-drift.js +1 -0
- package/dist/core/profiles.d.ts +2 -2
- package/dist/core/profiles.js +2 -1
- package/dist/core/project-config.d.ts +44 -1
- package/dist/core/project-config.js +160 -10
- package/dist/core/references.d.ts +63 -0
- package/dist/core/references.js +310 -0
- package/dist/core/relationship-health.d.ts +65 -0
- package/dist/core/relationship-health.js +64 -0
- package/dist/core/root-selection.d.ts +122 -0
- package/dist/core/root-selection.js +337 -0
- package/dist/core/schemas/base.schema.js +7 -2
- package/dist/core/shared/allowed-tools.d.ts +12 -0
- package/dist/core/shared/allowed-tools.js +12 -0
- package/dist/core/shared/skill-generation.js +5 -1
- package/dist/core/shared/tool-detection.d.ts +2 -2
- package/dist/core/shared/tool-detection.js +2 -0
- package/dist/core/specs-apply.d.ts +6 -1
- package/dist/core/specs-apply.js +41 -5
- package/dist/core/store/errors.d.ts +20 -0
- package/dist/core/{context-store → store}/errors.js +3 -3
- package/dist/core/store/foundation.d.ts +56 -0
- package/dist/core/store/foundation.js +251 -0
- package/dist/core/store/git.d.ts +23 -0
- package/dist/core/store/git.js +137 -0
- package/dist/core/{context-store → store}/index.d.ts +0 -1
- package/dist/core/{context-store → store}/index.js +0 -1
- package/dist/core/store/operations.d.ts +114 -0
- package/dist/core/store/operations.js +803 -0
- package/dist/core/store/registry.d.ts +58 -0
- package/dist/core/store/registry.js +275 -0
- package/dist/core/templates/skill-templates.d.ts +1 -0
- package/dist/core/templates/skill-templates.js +1 -0
- package/dist/core/templates/workflows/apply-change.js +5 -4
- package/dist/core/templates/workflows/archive-change.js +5 -4
- package/dist/core/templates/workflows/bulk-archive-change.js +5 -4
- package/dist/core/templates/workflows/continue-change.js +7 -2
- package/dist/core/templates/workflows/explore.js +5 -0
- package/dist/core/templates/workflows/ff-change.js +5 -0
- package/dist/core/templates/workflows/new-change.js +5 -0
- package/dist/core/templates/workflows/onboard.js +4 -1
- package/dist/core/templates/workflows/propose.js +5 -0
- package/dist/core/templates/workflows/store-selection.d.ts +8 -0
- package/dist/core/templates/workflows/store-selection.js +8 -0
- package/dist/core/templates/workflows/sync-specs.js +5 -4
- package/dist/core/templates/workflows/update-change.d.ts +10 -0
- package/dist/core/templates/workflows/update-change.js +167 -0
- package/dist/core/templates/workflows/verify-change.js +5 -4
- package/dist/core/update.js +4 -4
- package/dist/core/validation/validator.d.ts +7 -0
- package/dist/core/validation/validator.js +101 -38
- package/dist/core/view.js +1 -1
- package/dist/core/working-set.d.ts +47 -0
- package/dist/core/working-set.js +43 -0
- package/dist/core/worksets.d.ts +75 -0
- package/dist/core/worksets.js +245 -0
- package/dist/core/zod-issues.d.ts +4 -0
- package/dist/core/zod-issues.js +10 -0
- package/dist/utils/change-metadata.d.ts +1 -0
- package/dist/utils/change-metadata.js +1 -1
- package/dist/utils/change-utils.js +15 -0
- package/dist/utils/file-system.js +36 -17
- package/dist/utils/task-progress.d.ts +10 -1
- package/dist/utils/task-progress.js +66 -2
- package/package.json +26 -23
- package/dist/commands/context-store.d.ts +0 -3
- package/dist/commands/context-store.js +0 -475
- package/dist/commands/initiative.d.ts +0 -13
- package/dist/commands/initiative.js +0 -318
- package/dist/commands/workflow/initiative-link.d.ts +0 -24
- package/dist/commands/workflow/initiative-link.js +0 -47
- package/dist/commands/workflow/set-change.d.ts +0 -13
- package/dist/commands/workflow/set-change.js +0 -87
- package/dist/commands/workspace/context-status.d.ts +0 -4
- package/dist/commands/workspace/context-status.js +0 -59
- package/dist/commands/workspace/open-target-selection.d.ts +0 -13
- package/dist/commands/workspace/open-target-selection.js +0 -146
- package/dist/commands/workspace/open-view.d.ts +0 -62
- package/dist/commands/workspace/open-view.js +0 -249
- package/dist/commands/workspace/open.d.ts +0 -37
- package/dist/commands/workspace/open.js +0 -110
- package/dist/commands/workspace/opener-selection.d.ts +0 -11
- package/dist/commands/workspace/opener-selection.js +0 -98
- package/dist/commands/workspace/operations.d.ts +0 -29
- package/dist/commands/workspace/operations.js +0 -543
- package/dist/commands/workspace/prompt-theme.d.ts +0 -29
- package/dist/commands/workspace/prompt-theme.js +0 -24
- package/dist/commands/workspace/registration.d.ts +0 -13
- package/dist/commands/workspace/registration.js +0 -84
- package/dist/commands/workspace/selection.d.ts +0 -8
- package/dist/commands/workspace/selection.js +0 -104
- package/dist/commands/workspace/setup-prompts.d.ts +0 -13
- package/dist/commands/workspace/setup-prompts.js +0 -121
- package/dist/commands/workspace/types.d.ts +0 -103
- package/dist/commands/workspace/types.js +0 -36
- package/dist/commands/workspace.d.ts +0 -5
- package/dist/commands/workspace.js +0 -574
- package/dist/core/collections/index.d.ts +0 -3
- package/dist/core/collections/index.js +0 -3
- package/dist/core/collections/initiatives/collection.d.ts +0 -4
- package/dist/core/collections/initiatives/collection.js +0 -17
- package/dist/core/collections/initiatives/index.d.ts +0 -6
- package/dist/core/collections/initiatives/index.js +0 -6
- package/dist/core/collections/initiatives/operations.d.ts +0 -49
- package/dist/core/collections/initiatives/operations.js +0 -175
- package/dist/core/collections/initiatives/resolution.d.ts +0 -87
- package/dist/core/collections/initiatives/resolution.js +0 -374
- package/dist/core/collections/initiatives/schema.d.ts +0 -41
- package/dist/core/collections/initiatives/schema.js +0 -134
- package/dist/core/collections/initiatives/templates.d.ts +0 -12
- package/dist/core/collections/initiatives/templates.js +0 -90
- package/dist/core/collections/runtime.d.ts +0 -46
- package/dist/core/collections/runtime.js +0 -194
- package/dist/core/context-store/binding.d.ts +0 -53
- package/dist/core/context-store/binding.js +0 -197
- package/dist/core/context-store/errors.d.ts +0 -20
- package/dist/core/context-store/foundation.d.ts +0 -55
- package/dist/core/context-store/foundation.js +0 -321
- package/dist/core/context-store/operations.d.ts +0 -85
- package/dist/core/context-store/operations.js +0 -528
- package/dist/core/context-store/registry.d.ts +0 -45
- package/dist/core/context-store/registry.js +0 -229
- package/dist/core/workspace/foundation.d.ts +0 -67
- package/dist/core/workspace/foundation.js +0 -295
- package/dist/core/workspace/index.d.ts +0 -8
- package/dist/core/workspace/index.js +0 -8
- package/dist/core/workspace/legacy-state.d.ts +0 -28
- package/dist/core/workspace/legacy-state.js +0 -200
- package/dist/core/workspace/link-input.d.ts +0 -9
- package/dist/core/workspace/link-input.js +0 -32
- package/dist/core/workspace/open-surface.d.ts +0 -45
- package/dist/core/workspace/open-surface.js +0 -215
- package/dist/core/workspace/openers.d.ts +0 -21
- package/dist/core/workspace/openers.js +0 -124
- package/dist/core/workspace/registry.d.ts +0 -24
- package/dist/core/workspace/registry.js +0 -146
- package/dist/core/workspace/skills.d.ts +0 -57
- package/dist/core/workspace/skills.js +0 -334
- package/dist/core/workspace/state-io.d.ts +0 -10
- package/dist/core/workspace/state-io.js +0 -121
- package/schemas/workspace-planning/schema.yaml +0 -72
- package/schemas/workspace-planning/templates/design.md +0 -33
- package/schemas/workspace-planning/templates/proposal.md +0 -28
- package/schemas/workspace-planning/templates/spec.md +0 -9
- package/schemas/workspace-planning/templates/tasks.md +0 -15
package/dist/commands/show.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isInteractive } from '../utils/interactive.js';
|
|
2
2
|
import { getActiveChangeIds, getSpecIds } from '../utils/item-discovery.js';
|
|
3
|
+
import { resolveRootForCommand, toRootOutput, withStoreFlag, isStoreSelectedRoot, } from '../core/root-selection.js';
|
|
3
4
|
import { ChangeCommand } from './change.js';
|
|
4
5
|
import { SpecCommand } from './spec.js';
|
|
5
6
|
import { nearestMatches } from '../utils/match.js';
|
|
@@ -7,6 +8,10 @@ const CHANGE_FLAG_KEYS = new Set(['deltasOnly', 'requirementsOnly']);
|
|
|
7
8
|
const SPEC_FLAG_KEYS = new Set(['requirements', 'scenarios', 'requirement']);
|
|
8
9
|
export class ShowCommand {
|
|
9
10
|
async execute(itemName, options = {}) {
|
|
11
|
+
const root = await resolveRootForCommand(options, { json: options.json });
|
|
12
|
+
if (!root) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
10
15
|
const interactive = isInteractive(options);
|
|
11
16
|
const typeOverride = this.normalizeType(options.type);
|
|
12
17
|
if (!itemName) {
|
|
@@ -19,14 +24,14 @@ export class ShowCommand {
|
|
|
19
24
|
{ name: 'Spec', value: 'spec' },
|
|
20
25
|
],
|
|
21
26
|
});
|
|
22
|
-
await this.runInteractiveByType(type, options);
|
|
27
|
+
await this.runInteractiveByType(type, options, root);
|
|
23
28
|
return;
|
|
24
29
|
}
|
|
25
|
-
this.printNonInteractiveHint();
|
|
30
|
+
this.printNonInteractiveHint(root);
|
|
26
31
|
process.exitCode = 1;
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
|
-
await this.showDirect(itemName, { typeOverride, options });
|
|
34
|
+
await this.showDirect(itemName, { typeOverride, options, root });
|
|
30
35
|
}
|
|
31
36
|
normalizeType(value) {
|
|
32
37
|
if (!value)
|
|
@@ -36,78 +41,118 @@ export class ShowCommand {
|
|
|
36
41
|
return v;
|
|
37
42
|
return undefined;
|
|
38
43
|
}
|
|
39
|
-
|
|
44
|
+
delegateOptions(root, options) {
|
|
45
|
+
return {
|
|
46
|
+
...options,
|
|
47
|
+
...(options.json ? { rootOutput: toRootOutput(root) } : {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async runInteractiveByType(type, options, root) {
|
|
40
51
|
const { select } = await import('@inquirer/prompts');
|
|
41
52
|
if (type === 'change') {
|
|
42
|
-
const changes = await getActiveChangeIds();
|
|
53
|
+
const changes = await getActiveChangeIds(root.path);
|
|
43
54
|
if (changes.length === 0) {
|
|
44
55
|
console.error('No changes found.');
|
|
45
56
|
process.exitCode = 1;
|
|
46
57
|
return;
|
|
47
58
|
}
|
|
48
59
|
const picked = await select({ message: 'Pick a change', choices: changes.map(id => ({ name: id, value: id })) });
|
|
49
|
-
const cmd = new ChangeCommand();
|
|
50
|
-
await cmd.show(picked, options);
|
|
60
|
+
const cmd = new ChangeCommand(root.path);
|
|
61
|
+
await cmd.show(picked, this.delegateOptions(root, options));
|
|
51
62
|
return;
|
|
52
63
|
}
|
|
53
|
-
const specs = await getSpecIds();
|
|
64
|
+
const specs = await getSpecIds(root.path);
|
|
54
65
|
if (specs.length === 0) {
|
|
55
66
|
console.error('No specs found.');
|
|
56
67
|
process.exitCode = 1;
|
|
57
68
|
return;
|
|
58
69
|
}
|
|
59
70
|
const picked = await select({ message: 'Pick a spec', choices: specs.map(id => ({ name: id, value: id })) });
|
|
60
|
-
const cmd = new SpecCommand();
|
|
61
|
-
await cmd.show(picked, options);
|
|
71
|
+
const cmd = new SpecCommand(root.path);
|
|
72
|
+
await cmd.show(picked, this.delegateOptions(root, options));
|
|
62
73
|
}
|
|
63
74
|
async showDirect(itemName, params) {
|
|
75
|
+
const root = params.root;
|
|
64
76
|
// Optimize lookups when type is pre-specified
|
|
65
77
|
let isChange = false;
|
|
66
78
|
let isSpec = false;
|
|
67
79
|
let changes = [];
|
|
68
80
|
let specs = [];
|
|
69
81
|
if (params.typeOverride === 'change') {
|
|
70
|
-
changes = await getActiveChangeIds();
|
|
82
|
+
changes = await getActiveChangeIds(root.path);
|
|
71
83
|
isChange = changes.includes(itemName);
|
|
72
84
|
}
|
|
73
85
|
else if (params.typeOverride === 'spec') {
|
|
74
|
-
specs = await getSpecIds();
|
|
86
|
+
specs = await getSpecIds(root.path);
|
|
75
87
|
isSpec = specs.includes(itemName);
|
|
76
88
|
}
|
|
77
89
|
else {
|
|
78
|
-
[changes, specs] = await Promise.all([getActiveChangeIds(), getSpecIds()]);
|
|
90
|
+
[changes, specs] = await Promise.all([getActiveChangeIds(root.path), getSpecIds(root.path)]);
|
|
79
91
|
isChange = changes.includes(itemName);
|
|
80
92
|
isSpec = specs.includes(itemName);
|
|
81
93
|
}
|
|
82
94
|
const resolvedType = params.typeOverride ?? (isChange ? 'change' : isSpec ? 'spec' : undefined);
|
|
83
95
|
if (!resolvedType) {
|
|
84
|
-
console.error(`Unknown item '${itemName}'`);
|
|
85
96
|
const suggestions = nearestMatches(itemName, [...changes, ...specs]);
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
const message = suggestions.length
|
|
98
|
+
? `Unknown item '${itemName}'. Did you mean: ${suggestions.join(', ')}?`
|
|
99
|
+
: `Unknown item '${itemName}'.`;
|
|
100
|
+
if (params.options.json) {
|
|
101
|
+
console.log(JSON.stringify({ status: [{ severity: 'error', code: 'unknown_item', message }] }, null, 2));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.error(message);
|
|
105
|
+
}
|
|
88
106
|
process.exitCode = 1;
|
|
89
107
|
return;
|
|
90
108
|
}
|
|
91
109
|
if (!params.typeOverride && isChange && isSpec) {
|
|
110
|
+
if (params.options.json) {
|
|
111
|
+
console.log(JSON.stringify({
|
|
112
|
+
status: [
|
|
113
|
+
{
|
|
114
|
+
severity: 'error',
|
|
115
|
+
code: 'ambiguous_item',
|
|
116
|
+
message: `Ambiguous item '${itemName}' matches both a change and a spec.`,
|
|
117
|
+
fix: 'Pass --type change|spec.',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
}, null, 2));
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
92
124
|
console.error(`Ambiguous item '${itemName}' matches both a change and a spec.`);
|
|
93
|
-
|
|
125
|
+
// The noun-form commands are cwd-based and cannot reach a selected store.
|
|
126
|
+
if (isStoreSelectedRoot(root)) {
|
|
127
|
+
console.error('Pass --type change|spec.');
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.error('Pass --type change|spec, or use: openspec change show / openspec spec show');
|
|
131
|
+
}
|
|
94
132
|
process.exitCode = 1;
|
|
95
133
|
return;
|
|
96
134
|
}
|
|
97
135
|
this.warnIrrelevantFlags(resolvedType, params.options);
|
|
98
136
|
if (resolvedType === 'change') {
|
|
99
|
-
const cmd = new ChangeCommand();
|
|
100
|
-
await cmd.show(itemName, params.options);
|
|
137
|
+
const cmd = new ChangeCommand(root.path);
|
|
138
|
+
await cmd.show(itemName, this.delegateOptions(root, params.options));
|
|
101
139
|
return;
|
|
102
140
|
}
|
|
103
|
-
const cmd = new SpecCommand();
|
|
104
|
-
await cmd.show(itemName, params.options);
|
|
141
|
+
const cmd = new SpecCommand(root.path);
|
|
142
|
+
await cmd.show(itemName, this.delegateOptions(root, params.options));
|
|
105
143
|
}
|
|
106
|
-
printNonInteractiveHint() {
|
|
144
|
+
printNonInteractiveHint(root) {
|
|
107
145
|
console.error('Nothing to show. Try one of:');
|
|
108
|
-
console.error('
|
|
109
|
-
|
|
110
|
-
|
|
146
|
+
console.error(` ${withStoreFlag(root, 'openspec show <item>')}`);
|
|
147
|
+
if (isStoreSelectedRoot(root)) {
|
|
148
|
+
// The noun-form commands are cwd-based and cannot reach a selected store.
|
|
149
|
+
console.error(` ${withStoreFlag(root, 'openspec show <item> --type change')}`);
|
|
150
|
+
console.error(` ${withStoreFlag(root, 'openspec show <item> --type spec')}`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.error(' openspec change show');
|
|
154
|
+
console.error(' openspec spec show');
|
|
155
|
+
}
|
|
111
156
|
console.error('Or run in an interactive terminal.');
|
|
112
157
|
}
|
|
113
158
|
warnIrrelevantFlags(type, options) {
|
package/dist/commands/spec.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
|
+
import type { RootOutput } from '../core/root-selection.js';
|
|
2
3
|
interface ShowOptions {
|
|
3
4
|
json?: boolean;
|
|
4
5
|
requirements?: boolean;
|
|
5
6
|
scenarios?: boolean;
|
|
6
7
|
requirement?: string;
|
|
7
8
|
noInteractive?: boolean;
|
|
9
|
+
rootOutput?: RootOutput;
|
|
8
10
|
}
|
|
9
11
|
export declare class SpecCommand {
|
|
10
|
-
private
|
|
12
|
+
private specsDir;
|
|
13
|
+
private rootPath?;
|
|
14
|
+
constructor(rootPath?: string);
|
|
11
15
|
show(specId?: string, options?: ShowOptions): Promise<void>;
|
|
12
16
|
}
|
|
13
17
|
export declare function registerSpecCommand(rootProgram: typeof program): import("commander").Command;
|
package/dist/commands/spec.js
CHANGED
|
@@ -45,11 +45,18 @@ function printSpecTextRaw(specPath) {
|
|
|
45
45
|
console.log(content);
|
|
46
46
|
}
|
|
47
47
|
export class SpecCommand {
|
|
48
|
-
|
|
48
|
+
specsDir;
|
|
49
|
+
rootPath;
|
|
50
|
+
// rootPath is set only by root-aware callers (top-level `show`); the
|
|
51
|
+
// deprecated noun-form commands stay cwd-based.
|
|
52
|
+
constructor(rootPath) {
|
|
53
|
+
this.rootPath = rootPath;
|
|
54
|
+
this.specsDir = rootPath ? join(rootPath, 'openspec', 'specs') : SPECS_DIR;
|
|
55
|
+
}
|
|
49
56
|
async show(specId, options = {}) {
|
|
50
57
|
if (!specId) {
|
|
51
58
|
const canPrompt = isInteractive(options);
|
|
52
|
-
const specIds = await getSpecIds();
|
|
59
|
+
const specIds = await getSpecIds(this.rootPath ?? process.cwd());
|
|
53
60
|
if (canPrompt && specIds.length > 0) {
|
|
54
61
|
const { select } = await import('@inquirer/prompts');
|
|
55
62
|
specId = await select({
|
|
@@ -61,9 +68,12 @@ export class SpecCommand {
|
|
|
61
68
|
throw new Error('Missing required argument <spec-id>');
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
|
-
const specPath = join(this.
|
|
71
|
+
const specPath = join(this.specsDir, specId, 'spec.md');
|
|
65
72
|
if (!existsSync(specPath)) {
|
|
66
|
-
|
|
73
|
+
// Root-aware callers get the absolute path; the cwd-based noun form
|
|
74
|
+
// keeps its historical forward-slash relative message on all platforms.
|
|
75
|
+
const displayPath = this.rootPath ? specPath : `openspec/specs/${specId}/spec.md`;
|
|
76
|
+
throw new Error(`Spec '${specId}' not found at ${displayPath}`);
|
|
67
77
|
}
|
|
68
78
|
if (options.json) {
|
|
69
79
|
if (options.requirements && options.requirement) {
|
|
@@ -78,6 +88,7 @@ export class SpecCommand {
|
|
|
78
88
|
requirementCount: filtered.requirements.length,
|
|
79
89
|
requirements: filtered.requirements,
|
|
80
90
|
metadata: parsed.metadata ?? { version: '1.0.0', format: 'openspec' },
|
|
91
|
+
...(options.rootOutput ? { root: options.rootOutput } : {}),
|
|
81
92
|
};
|
|
82
93
|
console.log(JSON.stringify(output, null, 2));
|
|
83
94
|
return;
|