@codewalla_india/openspec 1.0.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/LICENSE +22 -0
- package/README.md +225 -0
- package/bin/openspec.js +5 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +548 -0
- package/dist/commands/change.d.ts +39 -0
- package/dist/commands/change.js +279 -0
- package/dist/commands/completion.d.ts +72 -0
- package/dist/commands/completion.js +264 -0
- package/dist/commands/config.d.ts +36 -0
- package/dist/commands/config.js +552 -0
- 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/feedback.d.ts +9 -0
- package/dist/commands/feedback.js +183 -0
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/schema.js +869 -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 +19 -0
- package/dist/commands/show.js +177 -0
- package/dist/commands/spec.d.ts +19 -0
- package/dist/commands/spec.js +236 -0
- package/dist/commands/store.d.ts +3 -0
- package/dist/commands/store.js +547 -0
- package/dist/commands/validate.d.ts +26 -0
- package/dist/commands/validate.js +330 -0
- package/dist/commands/workflow/index.d.ts +17 -0
- package/dist/commands/workflow/index.js +12 -0
- package/dist/commands/workflow/instructions.d.ts +45 -0
- package/dist/commands/workflow/instructions.js +500 -0
- package/dist/commands/workflow/new-change.d.ts +20 -0
- package/dist/commands/workflow/new-change.js +106 -0
- package/dist/commands/workflow/schemas.d.ts +10 -0
- package/dist/commands/workflow/schemas.js +34 -0
- package/dist/commands/workflow/shared.d.ts +84 -0
- package/dist/commands/workflow/shared.js +133 -0
- package/dist/commands/workflow/status.d.ts +16 -0
- package/dist/commands/workflow/status.js +92 -0
- package/dist/commands/workflow/templates.d.ts +16 -0
- package/dist/commands/workflow/templates.js +69 -0
- 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 +22 -0
- package/dist/core/archive.js +471 -0
- package/dist/core/artifact-graph/graph.d.ts +56 -0
- package/dist/core/artifact-graph/graph.js +141 -0
- package/dist/core/artifact-graph/index.d.ts +9 -0
- package/dist/core/artifact-graph/index.js +14 -0
- package/dist/core/artifact-graph/instruction-loader.d.ts +188 -0
- package/dist/core/artifact-graph/instruction-loader.js +233 -0
- package/dist/core/artifact-graph/outputs.d.ts +14 -0
- package/dist/core/artifact-graph/outputs.js +39 -0
- package/dist/core/artifact-graph/resolver.d.ts +81 -0
- package/dist/core/artifact-graph/resolver.js +257 -0
- package/dist/core/artifact-graph/schema.d.ts +13 -0
- package/dist/core/artifact-graph/schema.js +108 -0
- package/dist/core/artifact-graph/state.d.ts +12 -0
- package/dist/core/artifact-graph/state.js +31 -0
- package/dist/core/artifact-graph/types.d.ts +40 -0
- package/dist/core/artifact-graph/types.js +29 -0
- package/dist/core/available-tools.d.ts +17 -0
- package/dist/core/available-tools.js +43 -0
- package/dist/core/change-metadata/index.d.ts +2 -0
- package/dist/core/change-metadata/index.js +2 -0
- package/dist/core/change-metadata/schema.d.ts +19 -0
- package/dist/core/change-metadata/schema.js +30 -0
- package/dist/core/change-status-policy.d.ts +37 -0
- package/dist/core/change-status-policy.js +35 -0
- package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
- package/dist/core/command-generation/adapters/amazon-q.js +26 -0
- package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
- package/dist/core/command-generation/adapters/antigravity.js +26 -0
- package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
- package/dist/core/command-generation/adapters/auggie.js +27 -0
- package/dist/core/command-generation/adapters/bob.d.ts +14 -0
- package/dist/core/command-generation/adapters/bob.js +32 -0
- package/dist/core/command-generation/adapters/claude.d.ts +13 -0
- package/dist/core/command-generation/adapters/claude.js +37 -0
- package/dist/core/command-generation/adapters/cline.d.ts +14 -0
- package/dist/core/command-generation/adapters/cline.js +27 -0
- package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
- package/dist/core/command-generation/adapters/codebuddy.js +28 -0
- package/dist/core/command-generation/adapters/codex.d.ts +16 -0
- package/dist/core/command-generation/adapters/codex.js +39 -0
- package/dist/core/command-generation/adapters/continue.d.ts +13 -0
- package/dist/core/command-generation/adapters/continue.js +28 -0
- package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
- package/dist/core/command-generation/adapters/costrict.js +27 -0
- package/dist/core/command-generation/adapters/crush.d.ts +13 -0
- package/dist/core/command-generation/adapters/crush.js +30 -0
- package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
- package/dist/core/command-generation/adapters/cursor.js +31 -0
- package/dist/core/command-generation/adapters/factory.d.ts +13 -0
- package/dist/core/command-generation/adapters/factory.js +27 -0
- package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
- package/dist/core/command-generation/adapters/gemini.js +26 -0
- package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
- package/dist/core/command-generation/adapters/github-copilot.js +26 -0
- package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
- package/dist/core/command-generation/adapters/iflow.js +29 -0
- package/dist/core/command-generation/adapters/index.d.ts +32 -0
- package/dist/core/command-generation/adapters/index.js +32 -0
- package/dist/core/command-generation/adapters/junie.d.ts +13 -0
- package/dist/core/command-generation/adapters/junie.js +26 -0
- package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
- package/dist/core/command-generation/adapters/kilocode.js +23 -0
- package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
- package/dist/core/command-generation/adapters/kiro.js +26 -0
- package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
- package/dist/core/command-generation/adapters/lingma.js +30 -0
- package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
- package/dist/core/command-generation/adapters/opencode.js +29 -0
- package/dist/core/command-generation/adapters/pi.d.ts +18 -0
- package/dist/core/command-generation/adapters/pi.js +42 -0
- package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
- package/dist/core/command-generation/adapters/qoder.js +30 -0
- package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
- package/dist/core/command-generation/adapters/qwen.js +26 -0
- package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
- package/dist/core/command-generation/adapters/roocode.js +27 -0
- package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
- package/dist/core/command-generation/adapters/windsurf.js +38 -0
- package/dist/core/command-generation/generator.d.ts +21 -0
- package/dist/core/command-generation/generator.js +27 -0
- package/dist/core/command-generation/index.d.ts +22 -0
- package/dist/core/command-generation/index.js +24 -0
- package/dist/core/command-generation/registry.d.ts +36 -0
- package/dist/core/command-generation/registry.js +98 -0
- package/dist/core/command-generation/types.d.ts +56 -0
- package/dist/core/command-generation/types.js +8 -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.d.ts +3 -0
- package/dist/core/completions/command-registry.js +778 -0
- package/dist/core/completions/completion-provider.d.ts +71 -0
- package/dist/core/completions/completion-provider.js +129 -0
- package/dist/core/completions/factory.d.ts +64 -0
- package/dist/core/completions/factory.js +75 -0
- package/dist/core/completions/generators/bash-generator.d.ts +35 -0
- package/dist/core/completions/generators/bash-generator.js +230 -0
- package/dist/core/completions/generators/fish-generator.d.ts +32 -0
- package/dist/core/completions/generators/fish-generator.js +160 -0
- package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
- package/dist/core/completions/generators/powershell-generator.js +266 -0
- package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
- package/dist/core/completions/generators/zsh-generator.js +276 -0
- package/dist/core/completions/installers/bash-installer.d.ts +87 -0
- package/dist/core/completions/installers/bash-installer.js +321 -0
- package/dist/core/completions/installers/fish-installer.d.ts +43 -0
- package/dist/core/completions/installers/fish-installer.js +151 -0
- package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
- package/dist/core/completions/installers/powershell-installer.js +415 -0
- package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
- package/dist/core/completions/installers/zsh-installer.js +424 -0
- package/dist/core/completions/shared-flags.d.ts +13 -0
- package/dist/core/completions/shared-flags.js +33 -0
- package/dist/core/completions/templates/bash-templates.d.ts +6 -0
- package/dist/core/completions/templates/bash-templates.js +30 -0
- package/dist/core/completions/templates/fish-templates.d.ts +7 -0
- package/dist/core/completions/templates/fish-templates.js +45 -0
- package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
- package/dist/core/completions/templates/powershell-templates.js +34 -0
- package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
- package/dist/core/completions/templates/zsh-templates.js +45 -0
- package/dist/core/completions/types.d.ts +101 -0
- package/dist/core/completions/types.js +2 -0
- package/dist/core/comprehension/config.d.ts +20 -0
- package/dist/core/comprehension/config.js +23 -0
- package/dist/core/comprehension/fingerprint.d.ts +5 -0
- package/dist/core/comprehension/fingerprint.js +25 -0
- package/dist/core/comprehension/index.d.ts +49 -0
- package/dist/core/comprehension/index.js +78 -0
- package/dist/core/comprehension/pass-record.d.ts +29 -0
- package/dist/core/comprehension/pass-record.js +64 -0
- package/dist/core/comprehension/stats.d.ts +18 -0
- package/dist/core/comprehension/stats.js +41 -0
- package/dist/core/config-prompts.d.ts +9 -0
- package/dist/core/config-prompts.js +34 -0
- package/dist/core/config-schema.d.ts +87 -0
- package/dist/core/config-schema.js +239 -0
- package/dist/core/config.d.ts +18 -0
- package/dist/core/config.js +39 -0
- package/dist/core/converters/json-converter.d.ts +6 -0
- package/dist/core/converters/json-converter.js +51 -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 +51 -0
- package/dist/core/global-config.js +124 -0
- package/dist/core/id.d.ts +17 -0
- package/dist/core/id.js +30 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +7 -0
- package/dist/core/init.d.ts +37 -0
- package/dist/core/init.js +613 -0
- package/dist/core/legacy-cleanup.d.ts +162 -0
- package/dist/core/legacy-cleanup.js +514 -0
- package/dist/core/list.d.ts +11 -0
- package/dist/core/list.js +185 -0
- package/dist/core/migration.d.ts +23 -0
- package/dist/core/migration.js +108 -0
- 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 +192 -0
- package/dist/core/parsers/change-parser.d.ts +13 -0
- package/dist/core/parsers/change-parser.js +197 -0
- package/dist/core/parsers/markdown-parser.d.ts +26 -0
- package/dist/core/parsers/markdown-parser.js +227 -0
- package/dist/core/parsers/requirement-blocks.d.ts +37 -0
- package/dist/core/parsers/requirement-blocks.js +201 -0
- package/dist/core/parsers/spec-structure.d.ts +9 -0
- package/dist/core/parsers/spec-structure.js +88 -0
- package/dist/core/planning-home.d.ts +16 -0
- package/dist/core/planning-home.js +67 -0
- package/dist/core/profile-sync-drift.d.ts +38 -0
- package/dist/core/profile-sync-drift.js +200 -0
- package/dist/core/profiles.d.ts +26 -0
- package/dist/core/profiles.js +40 -0
- package/dist/core/project-config.d.ts +120 -0
- package/dist/core/project-config.js +406 -0
- 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.d.ts +13 -0
- package/dist/core/schemas/base.schema.js +13 -0
- package/dist/core/schemas/change.schema.d.ts +73 -0
- package/dist/core/schemas/change.schema.js +31 -0
- package/dist/core/schemas/index.d.ts +4 -0
- package/dist/core/schemas/index.js +4 -0
- package/dist/core/schemas/spec.schema.d.ts +18 -0
- package/dist/core/schemas/spec.schema.js +15 -0
- package/dist/core/shared/index.d.ts +8 -0
- package/dist/core/shared/index.js +8 -0
- package/dist/core/shared/skill-generation.d.ts +49 -0
- package/dist/core/shared/skill-generation.js +96 -0
- package/dist/core/shared/tool-detection.d.ts +71 -0
- package/dist/core/shared/tool-detection.js +158 -0
- package/dist/core/specs-apply.d.ts +78 -0
- package/dist/core/specs-apply.js +394 -0
- package/dist/core/store/errors.d.ts +20 -0
- package/dist/core/store/errors.js +22 -0
- 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/store/index.d.ts +5 -0
- package/dist/core/store/index.js +5 -0
- package/dist/core/store/operations.d.ts +114 -0
- package/dist/core/store/operations.js +783 -0
- package/dist/core/store/registry.d.ts +58 -0
- package/dist/core/store/registry.js +275 -0
- package/dist/core/styles/palette.d.ts +7 -0
- package/dist/core/styles/palette.js +8 -0
- package/dist/core/templates/index.d.ts +8 -0
- package/dist/core/templates/index.js +9 -0
- package/dist/core/templates/skill-templates.d.ts +19 -0
- package/dist/core/templates/skill-templates.js +18 -0
- package/dist/core/templates/types.d.ts +19 -0
- package/dist/core/templates/types.js +5 -0
- package/dist/core/templates/workflows/apply-change.d.ts +10 -0
- package/dist/core/templates/workflows/apply-change.js +337 -0
- package/dist/core/templates/workflows/archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/archive-change.js +278 -0
- package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/bulk-archive-change.js +493 -0
- package/dist/core/templates/workflows/comprehension-guidance.d.ts +9 -0
- package/dist/core/templates/workflows/comprehension-guidance.js +58 -0
- package/dist/core/templates/workflows/continue-change.d.ts +10 -0
- package/dist/core/templates/workflows/continue-change.js +239 -0
- package/dist/core/templates/workflows/explore.d.ts +10 -0
- package/dist/core/templates/workflows/explore.js +464 -0
- package/dist/core/templates/workflows/feedback.d.ts +9 -0
- package/dist/core/templates/workflows/feedback.js +108 -0
- package/dist/core/templates/workflows/ff-change.d.ts +10 -0
- package/dist/core/templates/workflows/ff-change.js +205 -0
- package/dist/core/templates/workflows/mcp-guidance.d.ts +13 -0
- package/dist/core/templates/workflows/mcp-guidance.js +116 -0
- package/dist/core/templates/workflows/new-change.d.ts +10 -0
- package/dist/core/templates/workflows/new-change.js +148 -0
- package/dist/core/templates/workflows/onboard.d.ts +10 -0
- package/dist/core/templates/workflows/onboard.js +566 -0
- package/dist/core/templates/workflows/propose.d.ts +10 -0
- package/dist/core/templates/workflows/propose.js +228 -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.d.ts +10 -0
- package/dist/core/templates/workflows/sync-specs.js +291 -0
- package/dist/core/templates/workflows/verify-change.d.ts +10 -0
- package/dist/core/templates/workflows/verify-change.js +346 -0
- package/dist/core/update.d.ts +82 -0
- package/dist/core/update.js +557 -0
- package/dist/core/validation/constants.d.ts +34 -0
- package/dist/core/validation/constants.js +40 -0
- package/dist/core/validation/types.d.ts +18 -0
- package/dist/core/validation/types.js +2 -0
- package/dist/core/validation/validator.d.ts +44 -0
- package/dist/core/validation/validator.js +435 -0
- package/dist/core/view.d.ts +8 -0
- package/dist/core/view.js +168 -0
- 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/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/prompts/searchable-multi-select.d.ts +28 -0
- package/dist/prompts/searchable-multi-select.js +159 -0
- package/dist/telemetry/config.d.ts +38 -0
- package/dist/telemetry/config.js +136 -0
- package/dist/telemetry/index.d.ts +31 -0
- package/dist/telemetry/index.js +164 -0
- package/dist/ui/ascii-patterns.d.ts +16 -0
- package/dist/ui/ascii-patterns.js +133 -0
- package/dist/ui/welcome-screen.d.ts +10 -0
- package/dist/ui/welcome-screen.js +146 -0
- package/dist/utils/change-metadata.d.ts +55 -0
- package/dist/utils/change-metadata.js +141 -0
- package/dist/utils/change-utils.d.ts +71 -0
- package/dist/utils/change-utils.js +138 -0
- package/dist/utils/command-references.d.ts +18 -0
- package/dist/utils/command-references.js +20 -0
- package/dist/utils/file-system.d.ts +41 -0
- package/dist/utils/file-system.js +320 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/interactive.d.ts +18 -0
- package/dist/utils/interactive.js +21 -0
- package/dist/utils/item-discovery.d.ts +4 -0
- package/dist/utils/item-discovery.js +72 -0
- package/dist/utils/match.d.ts +3 -0
- package/dist/utils/match.js +22 -0
- package/dist/utils/shell-detection.d.ts +20 -0
- package/dist/utils/shell-detection.js +41 -0
- package/dist/utils/task-progress.d.ts +8 -0
- package/dist/utils/task-progress.js +36 -0
- package/package.json +84 -0
- package/schemas/spec-driven/schema.yaml +153 -0
- package/schemas/spec-driven/templates/design.md +19 -0
- package/schemas/spec-driven/templates/proposal.md +23 -0
- package/schemas/spec-driven/templates/spec.md +8 -0
- package/schemas/spec-driven/templates/tasks.md +9 -0
- package/scripts/postinstall.js +83 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import { asErrorMessage, emitFailure, printJson } from './shared-output.js';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { COMMAND_REGISTRY } from '../core/completions/command-registry.js';
|
|
5
|
+
import { StoreError, doctorStores, listStores, prepareStoreSetup, prepareStoreCleanup, registerExistingStore, removeStore, resolveSetupGitEnabled, setupPreparedStore, unregisterStore, validateStoreId, } from '../core/store/index.js';
|
|
6
|
+
import { isInteractive } from '../utils/interactive.js';
|
|
7
|
+
function toStoreOutput(store) {
|
|
8
|
+
return {
|
|
9
|
+
id: store.id,
|
|
10
|
+
root: store.root,
|
|
11
|
+
...(store.metadataPath ? { metadata_path: store.metadataPath } : {}),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function toMutationOutput(result) {
|
|
15
|
+
return {
|
|
16
|
+
store: toStoreOutput(result.store),
|
|
17
|
+
registry: {
|
|
18
|
+
path: result.registryCommit.path,
|
|
19
|
+
registered: result.registryCommit.registered,
|
|
20
|
+
already_registered: result.registryCommit.alreadyRegistered,
|
|
21
|
+
},
|
|
22
|
+
git: {
|
|
23
|
+
is_repository: result.git.isRepository,
|
|
24
|
+
initialized: result.git.initialized,
|
|
25
|
+
committed: result.git.committed,
|
|
26
|
+
},
|
|
27
|
+
created_files: result.createdArtifacts,
|
|
28
|
+
status: result.diagnostics,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function toCleanupOutput(result) {
|
|
32
|
+
return {
|
|
33
|
+
store: toStoreOutput(result.store),
|
|
34
|
+
registry: {
|
|
35
|
+
path: result.registryCommit.path,
|
|
36
|
+
removed: result.registryCommit.removed,
|
|
37
|
+
},
|
|
38
|
+
files: {
|
|
39
|
+
deleted: result.files.deleted,
|
|
40
|
+
deleted_path: result.files.deletedPath ?? null,
|
|
41
|
+
left_on_disk: result.files.leftOnDisk ?? null,
|
|
42
|
+
},
|
|
43
|
+
status: result.diagnostics,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function toListOutput(result) {
|
|
47
|
+
return {
|
|
48
|
+
stores: result.stores.map(toStoreOutput),
|
|
49
|
+
status: [],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function toOpenSpecRootOutput(root) {
|
|
53
|
+
return {
|
|
54
|
+
present: root.present,
|
|
55
|
+
config: root.config,
|
|
56
|
+
specs: root.specs,
|
|
57
|
+
changes: root.changes,
|
|
58
|
+
archive: root.archive,
|
|
59
|
+
healthy: root.healthy,
|
|
60
|
+
status: root.diagnostics,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function toDoctorStoreOutput(store) {
|
|
64
|
+
return {
|
|
65
|
+
...toStoreOutput(store),
|
|
66
|
+
openspec_root: toOpenSpecRootOutput(store.openspecRoot),
|
|
67
|
+
metadata: store.metadata,
|
|
68
|
+
git: {
|
|
69
|
+
is_repository: store.git.isRepository,
|
|
70
|
+
has_commits: store.git.hasCommits,
|
|
71
|
+
has_uncommitted_changes: store.git.hasUncommittedChanges,
|
|
72
|
+
has_remote: store.git.hasRemote,
|
|
73
|
+
origin_url: store.git.originUrl,
|
|
74
|
+
},
|
|
75
|
+
status: store.diagnostics,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function toDoctorOutput(result) {
|
|
79
|
+
return {
|
|
80
|
+
stores: result.stores.map(toDoctorStoreOutput),
|
|
81
|
+
status: result.diagnostics,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function formatPathForHuman(targetPath) {
|
|
85
|
+
const home = os.homedir();
|
|
86
|
+
const normalizedHome = path.resolve(home);
|
|
87
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
88
|
+
if (normalizedTarget === normalizedHome)
|
|
89
|
+
return '~';
|
|
90
|
+
if (normalizedTarget.startsWith(`${normalizedHome}${path.sep}`)) {
|
|
91
|
+
return `~${path.sep}${path.relative(normalizedHome, normalizedTarget)}`;
|
|
92
|
+
}
|
|
93
|
+
return targetPath;
|
|
94
|
+
}
|
|
95
|
+
async function promptStoreId() {
|
|
96
|
+
const { input } = await import('@inquirer/prompts');
|
|
97
|
+
return input({
|
|
98
|
+
message: 'Store name',
|
|
99
|
+
required: true,
|
|
100
|
+
validate(value) {
|
|
101
|
+
try {
|
|
102
|
+
validateStoreId(value);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return asErrorMessage(error);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function promptStorePath(id) {
|
|
112
|
+
const { input } = await import('@inquirer/prompts');
|
|
113
|
+
// Suggest a visible, user-owned location — never the managed XDG data dir.
|
|
114
|
+
const defaultPath = ['~', 'openspec', id].join('/');
|
|
115
|
+
return input({
|
|
116
|
+
message: 'Where should this store live?',
|
|
117
|
+
default: defaultPath,
|
|
118
|
+
prefill: 'editable',
|
|
119
|
+
required: true,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async function resolveSetupInput(id, options) {
|
|
123
|
+
const interactive = !options.json && isInteractive();
|
|
124
|
+
if (!id && !interactive) {
|
|
125
|
+
throw new StoreError('Pass a store name.', 'store_setup_id_required', {
|
|
126
|
+
target: 'store.id',
|
|
127
|
+
fix: 'openspec store setup <id> --path ~/openspec/<id> --json',
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (options.path === undefined && !interactive) {
|
|
131
|
+
throw new StoreError('Pass --path with the folder where this store should live.', 'store_setup_path_required', {
|
|
132
|
+
target: 'store.root',
|
|
133
|
+
fix: `openspec store setup ${id ?? '<id>'} --path ~/openspec/${id ?? '<id>'}`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const resolvedId = id ? validateStoreId(id) : await promptStoreId();
|
|
137
|
+
const promptedPath = options.path === undefined
|
|
138
|
+
? await promptStorePath(resolvedId)
|
|
139
|
+
: undefined;
|
|
140
|
+
return {
|
|
141
|
+
id: resolvedId,
|
|
142
|
+
path: options.path ?? promptedPath,
|
|
143
|
+
...(options.remote !== undefined ? { remote: options.remote } : {}),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function prepareSetupInput(input, _options) {
|
|
147
|
+
return prepareStoreSetup(input);
|
|
148
|
+
}
|
|
149
|
+
async function confirmSetup(prepared, initGit) {
|
|
150
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
151
|
+
console.log('');
|
|
152
|
+
console.log('OpenSpec will create:');
|
|
153
|
+
console.log('');
|
|
154
|
+
console.log(` Store: ${prepared.id}`);
|
|
155
|
+
console.log(` Location: ${formatPathForHuman(prepared.root)}`);
|
|
156
|
+
console.log(` Git: ${initGit ? 'initialized' : 'not initialized'}`);
|
|
157
|
+
console.log('');
|
|
158
|
+
const confirmed = await confirm({
|
|
159
|
+
message: 'Create this store?',
|
|
160
|
+
default: true,
|
|
161
|
+
});
|
|
162
|
+
if (!confirmed) {
|
|
163
|
+
throw new StoreError('Store setup cancelled.', 'store_setup_cancelled', {
|
|
164
|
+
target: 'store.root',
|
|
165
|
+
fix: 'Rerun setup when you are ready.',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function confirmRemove(id, root, options) {
|
|
170
|
+
if (options.yes)
|
|
171
|
+
return;
|
|
172
|
+
if (options.json || !isInteractive()) {
|
|
173
|
+
throw new StoreError('Pass --yes to delete store files non-interactively.', 'store_remove_confirmation_required', {
|
|
174
|
+
target: 'store.root',
|
|
175
|
+
fix: `openspec store remove ${id} --yes`,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
179
|
+
const confirmed = await confirm({
|
|
180
|
+
message: `Delete local store folder ${formatPathForHuman(root)}?`,
|
|
181
|
+
default: false,
|
|
182
|
+
});
|
|
183
|
+
if (!confirmed) {
|
|
184
|
+
throw new StoreError('Store remove cancelled.', 'store_remove_cancelled', {
|
|
185
|
+
target: 'store.root',
|
|
186
|
+
fix: 'Run "openspec store unregister <id>" if you only want to forget the local registration.',
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function isRegisterIdentityConfirmationError(error) {
|
|
191
|
+
return (error instanceof StoreError &&
|
|
192
|
+
error.diagnostic.code === 'store_register_identity_confirmation_required');
|
|
193
|
+
}
|
|
194
|
+
async function confirmRegisterConversion(error) {
|
|
195
|
+
const { confirm } = await import('@inquirer/prompts');
|
|
196
|
+
const confirmed = await confirm({
|
|
197
|
+
message: asErrorMessage(error),
|
|
198
|
+
default: false,
|
|
199
|
+
});
|
|
200
|
+
if (!confirmed) {
|
|
201
|
+
throw new StoreError('Store register cancelled.', 'store_register_cancelled', {
|
|
202
|
+
target: 'store.metadata',
|
|
203
|
+
fix: 'Rerun register when you are ready to create store identity metadata.',
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function printMutationHuman(title, payload, remotes) {
|
|
208
|
+
if (!payload.store || !payload.registry || !payload.git) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
console.log(`${title}: ${payload.store.id}`);
|
|
212
|
+
console.log(`Location: ${formatPathForHuman(payload.store.root)}`);
|
|
213
|
+
console.log('OpenSpec root: ready');
|
|
214
|
+
console.log(`Registry: ${payload.registry.already_registered ? 'already registered' : 'registered'}`);
|
|
215
|
+
for (const status of payload.status) {
|
|
216
|
+
console.log(`${status.severity === 'error' ? 'Issue' : 'Note'}: ${status.message}`);
|
|
217
|
+
}
|
|
218
|
+
console.log('');
|
|
219
|
+
console.log('Next: run normal OpenSpec commands against this store, for example:');
|
|
220
|
+
console.log(` openspec new change <change-id> --store ${payload.store.id}`);
|
|
221
|
+
if (payload.git.is_repository) {
|
|
222
|
+
const shareRemote = remotes?.canonical ?? remotes?.observed;
|
|
223
|
+
console.log(shareRemote
|
|
224
|
+
? `Share it: teammates clone ${shareRemote} and run openspec store register <path>.`
|
|
225
|
+
: 'Share this store by committing and pushing it like any Git repo.');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function printCleanupHuman(title, payload) {
|
|
229
|
+
if (!payload.store || !payload.registry || !payload.files) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
console.log(`${title}: ${payload.store.id}`);
|
|
233
|
+
if (payload.files.deleted_path) {
|
|
234
|
+
console.log(`Deleted: ${formatPathForHuman(payload.files.deleted_path)}`);
|
|
235
|
+
}
|
|
236
|
+
else if (payload.files.left_on_disk) {
|
|
237
|
+
console.log(`Files kept at: ${formatPathForHuman(payload.files.left_on_disk)}`);
|
|
238
|
+
}
|
|
239
|
+
else if (!payload.files.deleted) {
|
|
240
|
+
console.log(`Files were already missing: ${formatPathForHuman(payload.store.root)}`);
|
|
241
|
+
}
|
|
242
|
+
for (const status of payload.status) {
|
|
243
|
+
console.log(`${status.severity === 'error' ? 'Issue' : 'Note'}: ${status.message}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function printListHuman(payload) {
|
|
247
|
+
if (payload.stores.length === 0) {
|
|
248
|
+
console.log('No stores registered.');
|
|
249
|
+
console.log('');
|
|
250
|
+
console.log('Next:');
|
|
251
|
+
console.log(' openspec store setup team-context --path ~/openspec/team-context');
|
|
252
|
+
console.log(' openspec store register /path/to/store');
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
console.log(`OpenSpec stores (${payload.stores.length})`);
|
|
256
|
+
console.log('');
|
|
257
|
+
console.log(`${'ID'.padEnd(16)}Location`);
|
|
258
|
+
for (const store of payload.stores) {
|
|
259
|
+
console.log(`${store.id.padEnd(16)}${store.root}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function formatMetadataHuman(store) {
|
|
263
|
+
if (store.metadata.valid)
|
|
264
|
+
return 'ok';
|
|
265
|
+
if (store.metadata.present === false)
|
|
266
|
+
return 'missing';
|
|
267
|
+
if (store.metadata.present === null)
|
|
268
|
+
return 'unknown';
|
|
269
|
+
return 'invalid';
|
|
270
|
+
}
|
|
271
|
+
function formatDoctorGitHuman(store) {
|
|
272
|
+
if (store.git.is_repository === null)
|
|
273
|
+
return 'unknown';
|
|
274
|
+
if (!store.git.is_repository)
|
|
275
|
+
return 'not detected';
|
|
276
|
+
const fact = (value, yes, no) => value === null ? 'unknown' : value ? yes : no;
|
|
277
|
+
return `repository detected (commits: ${fact(store.git.has_commits, 'yes', 'none')}, uncommitted changes: ${fact(store.git.has_uncommitted_changes, 'yes', 'no')}, remote: ${fact(store.git.has_remote, 'yes', 'none')})`;
|
|
278
|
+
}
|
|
279
|
+
function formatOpenSpecRootHuman(store) {
|
|
280
|
+
if (store.openspec_root.healthy)
|
|
281
|
+
return 'ok';
|
|
282
|
+
if (store.openspec_root.present === false)
|
|
283
|
+
return 'missing';
|
|
284
|
+
if (store.openspec_root.present === null)
|
|
285
|
+
return 'unknown';
|
|
286
|
+
return 'incomplete';
|
|
287
|
+
}
|
|
288
|
+
function printDoctorHuman(payload) {
|
|
289
|
+
if (payload.stores.length === 0) {
|
|
290
|
+
console.log('No stores registered.');
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
console.log('Store doctor');
|
|
294
|
+
for (const store of payload.stores) {
|
|
295
|
+
console.log('');
|
|
296
|
+
console.log(store.id);
|
|
297
|
+
console.log(` Location: ${store.root}`);
|
|
298
|
+
console.log(` OpenSpec root: ${formatOpenSpecRootHuman(store)}`);
|
|
299
|
+
console.log(` Metadata: ${formatMetadataHuman(store)}`);
|
|
300
|
+
const remoteLine = store.metadata.remote ?? store.git.origin_url;
|
|
301
|
+
if (remoteLine) {
|
|
302
|
+
console.log(` Remote: ${remoteLine}`);
|
|
303
|
+
}
|
|
304
|
+
console.log(` Git: ${formatDoctorGitHuman(store)}`);
|
|
305
|
+
if (store.status.length === 0) {
|
|
306
|
+
console.log(' Issues: none');
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
console.log(' Issues:');
|
|
310
|
+
for (const status of store.status) {
|
|
311
|
+
console.log(` - ${status.message}`);
|
|
312
|
+
if (status.fix) {
|
|
313
|
+
console.log(` Fix: ${status.fix}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
class StoreCommand {
|
|
319
|
+
async setup(id, options = {}) {
|
|
320
|
+
try {
|
|
321
|
+
const setupInput = await resolveSetupInput(id, options);
|
|
322
|
+
const prepared = await prepareSetupInput(setupInput, options);
|
|
323
|
+
const initGit = resolveSetupGitEnabled(prepared, options.initGit);
|
|
324
|
+
if (!options.json && isInteractive()) {
|
|
325
|
+
await confirmSetup(prepared, initGit);
|
|
326
|
+
}
|
|
327
|
+
const result = await setupPreparedStore(prepared, { initGit });
|
|
328
|
+
const payload = toMutationOutput(result);
|
|
329
|
+
if (options.json) {
|
|
330
|
+
printJson(payload);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
printMutationHuman('Store ready', payload, result.remotes);
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
this.handleFailure(options.json, { store: null, registry: null, git: null, created_files: [], status: [] }, error);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async register(inputPath, options = {}) {
|
|
340
|
+
try {
|
|
341
|
+
let result;
|
|
342
|
+
try {
|
|
343
|
+
result = await registerExistingStore({
|
|
344
|
+
path: inputPath,
|
|
345
|
+
id: options.id,
|
|
346
|
+
allowCreateIdentity: options.yes,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (!isRegisterIdentityConfirmationError(error) || options.json || !isInteractive()) {
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
await confirmRegisterConversion(error);
|
|
354
|
+
result = await registerExistingStore({
|
|
355
|
+
path: inputPath,
|
|
356
|
+
id: options.id,
|
|
357
|
+
allowCreateIdentity: true,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
const payload = toMutationOutput(result);
|
|
361
|
+
if (options.json) {
|
|
362
|
+
printJson(payload);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
printMutationHuman('Store registered', payload, result.remotes);
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
this.handleFailure(options.json, { store: null, registry: null, git: null, created_files: [], status: [] }, error);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async unregister(id, options = {}) {
|
|
372
|
+
try {
|
|
373
|
+
const payload = toCleanupOutput(await unregisterStore({ id }));
|
|
374
|
+
if (options.json) {
|
|
375
|
+
printJson(payload);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
printCleanupHuman('Unregistered store', payload);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
this.handleFailure(options.json, { store: null, registry: null, files: null, status: [] }, error);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async remove(id, options = {}) {
|
|
385
|
+
try {
|
|
386
|
+
const target = await prepareStoreCleanup({ id });
|
|
387
|
+
await confirmRemove(target.id, target.root, options);
|
|
388
|
+
const payload = toCleanupOutput(await removeStore(target));
|
|
389
|
+
if (options.json) {
|
|
390
|
+
printJson(payload);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
printCleanupHuman('Removed store', payload);
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
this.handleFailure(options.json, { store: null, registry: null, files: null, status: [] }, error);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async list(options = {}) {
|
|
400
|
+
try {
|
|
401
|
+
const payload = toListOutput(await listStores());
|
|
402
|
+
if (options.json) {
|
|
403
|
+
printJson(payload);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
printListHuman(payload);
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
this.handleFailure(options.json, { stores: [], status: [] }, error);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
async doctor(id, options = {}) {
|
|
413
|
+
try {
|
|
414
|
+
const payload = toDoctorOutput(await doctorStores(id));
|
|
415
|
+
if (options.json) {
|
|
416
|
+
printJson(payload);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
printDoctorHuman(payload);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
this.handleFailure(options.json, { stores: [], status: [] }, error);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
handleFailure(json, payload, error) {
|
|
426
|
+
emitFailure(json, payload, error, 'store_error');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
export function registerStoreCommand(program) {
|
|
430
|
+
const storeCommand = new StoreCommand();
|
|
431
|
+
// One source for the locked group one-liner: the completions registry
|
|
432
|
+
// entry, which shell completion scripts also consume.
|
|
433
|
+
const storeGroupDescription = COMMAND_REGISTRY.find((entry) => entry.name === 'store')?.description ??
|
|
434
|
+
'Create and manage stores - standalone OpenSpec repos you register on this machine';
|
|
435
|
+
const store = program.command('store').description(storeGroupDescription);
|
|
436
|
+
store
|
|
437
|
+
.command('setup [id]')
|
|
438
|
+
.description('Create and register a local store')
|
|
439
|
+
.option('--path <path>', 'Folder where the store should live (for example ~/openspec/<id>)')
|
|
440
|
+
.option('--init-git', 'Initialize a Git repository with an initial commit (default)')
|
|
441
|
+
.option('--no-init-git', 'Skip every Git action: no init, no initial commit')
|
|
442
|
+
.option('--remote <url>', 'Canonical clone source recorded in store.yaml')
|
|
443
|
+
.option('--json', 'Output as JSON')
|
|
444
|
+
.action(async (id, options) => {
|
|
445
|
+
await storeCommand.setup(id, options);
|
|
446
|
+
});
|
|
447
|
+
store
|
|
448
|
+
.command('register [path]')
|
|
449
|
+
.description('Register an existing local store')
|
|
450
|
+
.option('--id <id>', 'Store id; defaults to metadata or folder name')
|
|
451
|
+
.option('--yes', 'Confirm creating store identity metadata for a healthy OpenSpec root')
|
|
452
|
+
.option('--json', 'Output as JSON')
|
|
453
|
+
.action(async (inputPath, options) => {
|
|
454
|
+
await storeCommand.register(inputPath, options);
|
|
455
|
+
});
|
|
456
|
+
store
|
|
457
|
+
.command('unregister <id>')
|
|
458
|
+
.description('Forget a local store registration without deleting files')
|
|
459
|
+
.option('--json', 'Output as JSON')
|
|
460
|
+
.action(async (id, options) => {
|
|
461
|
+
await storeCommand.unregister(id, options);
|
|
462
|
+
});
|
|
463
|
+
store
|
|
464
|
+
.command('remove <id>')
|
|
465
|
+
.description('Forget a local store registration and delete its local folder')
|
|
466
|
+
.option('--yes', 'Confirm local store folder deletion')
|
|
467
|
+
.option('--json', 'Output as JSON')
|
|
468
|
+
.action(async (id, options) => {
|
|
469
|
+
await storeCommand.remove(id, options);
|
|
470
|
+
});
|
|
471
|
+
store
|
|
472
|
+
.command('list')
|
|
473
|
+
.alias('ls')
|
|
474
|
+
.description('List locally registered stores')
|
|
475
|
+
.option('--json', 'Output as JSON')
|
|
476
|
+
.action(async (options) => {
|
|
477
|
+
await storeCommand.list(options);
|
|
478
|
+
});
|
|
479
|
+
store
|
|
480
|
+
.command('doctor [id]')
|
|
481
|
+
.description('Check local store registration and metadata')
|
|
482
|
+
.option('--json', 'Output as JSON')
|
|
483
|
+
.action(async (id, options) => {
|
|
484
|
+
await storeCommand.doctor(id, options);
|
|
485
|
+
});
|
|
486
|
+
const lifecycleRedirects = new Set(COMMAND_REGISTRY.filter((entry) => entry.flags.some((flag) => flag.name === 'store') ||
|
|
487
|
+
(entry.subcommands ?? []).some((subcommand) => subcommand.flags.some((flag) => flag.name === 'store'))).map((entry) => entry.name));
|
|
488
|
+
const storeSubcommandsLine = store.commands
|
|
489
|
+
.map((subcommand) => {
|
|
490
|
+
const aliases = subcommand.aliases();
|
|
491
|
+
return aliases.length > 0 ? `${subcommand.name()} (${aliases.join(', ')})` : subcommand.name();
|
|
492
|
+
})
|
|
493
|
+
.join(', ');
|
|
494
|
+
// One group action owns missing AND unknown subcommands. Known
|
|
495
|
+
// subcommands dispatch above; everything else — including a bare
|
|
496
|
+
// `store --json` with no operand — lands here, so the handler owns the
|
|
497
|
+
// entire message and exit path (same text for human and --json). The
|
|
498
|
+
// permissive flags route unknown operands/options here instead of
|
|
499
|
+
// letting Commander emit a raw error before the action runs. We detect
|
|
500
|
+
// `--json` in the residual args rather than declaring a group option,
|
|
501
|
+
// which would otherwise shadow each subcommand's own `--json` flag.
|
|
502
|
+
store.allowExcessArguments(true);
|
|
503
|
+
store.allowUnknownOption(true);
|
|
504
|
+
store.action(() => {
|
|
505
|
+
const operands = store.args;
|
|
506
|
+
// Flag values are indistinguishable from operands without a full
|
|
507
|
+
// parse, so the verbatim echo only applies to plain-operand input.
|
|
508
|
+
const attempted = operands.filter((operand) => !operand.startsWith('-'));
|
|
509
|
+
const hasFlagLikeToken = operands.some((operand) => operand.startsWith('-'));
|
|
510
|
+
// The agent contract: --json failures emit one JSON document.
|
|
511
|
+
if (operands.includes('--json')) {
|
|
512
|
+
const message = attempted.length > 0
|
|
513
|
+
? `Unknown command '${attempted[0]}' for 'openspec store'. Store subcommands: ${storeSubcommandsLine}.`
|
|
514
|
+
: `Missing subcommand for 'openspec store'. Store subcommands: ${storeSubcommandsLine}.`;
|
|
515
|
+
printJson({
|
|
516
|
+
status: [
|
|
517
|
+
{
|
|
518
|
+
severity: 'error',
|
|
519
|
+
code: 'unknown_store_subcommand',
|
|
520
|
+
message,
|
|
521
|
+
fix: 'Run a store subcommand, or use the lifecycle command with --store <id>.',
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
});
|
|
525
|
+
process.exitCode = 1;
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
let example = 'openspec new change <change-id> --store <id>';
|
|
529
|
+
if (!hasFlagLikeToken && attempted.length > 0 && lifecycleRedirects.has(attempted[0])) {
|
|
530
|
+
if (attempted[0] === 'new') {
|
|
531
|
+
const changeId = attempted[1] === 'change' && attempted[2] ? attempted[2] : '<change-id>';
|
|
532
|
+
example = `openspec new change ${changeId} --store <id>`;
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
example = `openspec ${attempted.join(' ')} --store <id>`;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
console.error(attempted.length > 0
|
|
539
|
+
? `Error: unknown command '${attempted[0]}' for 'openspec store'.`
|
|
540
|
+
: "Error: missing subcommand for 'openspec store'.");
|
|
541
|
+
console.error(`Store subcommands manage store registration: ${storeSubcommandsLine}.`);
|
|
542
|
+
console.error('To create or work on a change in a store, use the normal command with --store, for example:');
|
|
543
|
+
console.error(` ${example}`);
|
|
544
|
+
process.exitCode = 1;
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface ExecuteOptions {
|
|
2
|
+
all?: boolean;
|
|
3
|
+
changes?: boolean;
|
|
4
|
+
specs?: boolean;
|
|
5
|
+
type?: string;
|
|
6
|
+
strict?: boolean;
|
|
7
|
+
json?: boolean;
|
|
8
|
+
noInteractive?: boolean;
|
|
9
|
+
interactive?: boolean;
|
|
10
|
+
concurrency?: string;
|
|
11
|
+
store?: string;
|
|
12
|
+
storePath?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ValidateCommand {
|
|
15
|
+
execute(itemName: string | undefined, options?: ExecuteOptions): Promise<void>;
|
|
16
|
+
private normalizeType;
|
|
17
|
+
private runInteractiveSelector;
|
|
18
|
+
private printNonInteractiveHint;
|
|
19
|
+
private validateDirectItem;
|
|
20
|
+
private validateByType;
|
|
21
|
+
private printReport;
|
|
22
|
+
private printNextSteps;
|
|
23
|
+
private runBulkValidation;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=validate.d.ts.map
|