@superkou/openspec 1.4.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 +213 -0
- package/bin/openspec.js +5 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +544 -0
- package/dist/commands/change.d.ts +35 -0
- package/dist/commands/change.js +277 -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 +611 -0
- package/dist/commands/context-store.d.ts +3 -0
- package/dist/commands/context-store.js +475 -0
- package/dist/commands/feedback.d.ts +9 -0
- package/dist/commands/feedback.js +183 -0
- package/dist/commands/initiative.d.ts +13 -0
- package/dist/commands/initiative.js +318 -0
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/schema.js +869 -0
- package/dist/commands/show.d.ts +14 -0
- package/dist/commands/show.js +132 -0
- package/dist/commands/spec.d.ts +15 -0
- package/dist/commands/spec.js +225 -0
- package/dist/commands/validate.d.ts +24 -0
- package/dist/commands/validate.js +294 -0
- package/dist/commands/workflow/index.d.ts +19 -0
- package/dist/commands/workflow/index.js +13 -0
- package/dist/commands/workflow/initiative-link.d.ts +24 -0
- package/dist/commands/workflow/initiative-link.js +47 -0
- package/dist/commands/workflow/instructions.d.ts +29 -0
- package/dist/commands/workflow/instructions.js +344 -0
- package/dist/commands/workflow/new-change.d.ts +17 -0
- package/dist/commands/workflow/new-change.js +141 -0
- package/dist/commands/workflow/schemas.d.ts +10 -0
- package/dist/commands/workflow/schemas.js +34 -0
- package/dist/commands/workflow/set-change.d.ts +13 -0
- package/dist/commands/workflow/set-change.js +87 -0
- package/dist/commands/workflow/shared.d.ts +59 -0
- package/dist/commands/workflow/shared.js +116 -0
- package/dist/commands/workflow/status.d.ts +14 -0
- package/dist/commands/workflow/status.js +90 -0
- package/dist/commands/workflow/templates.d.ts +16 -0
- package/dist/commands/workflow/templates.js +69 -0
- package/dist/commands/workspace/context-status.d.ts +4 -0
- package/dist/commands/workspace/context-status.js +59 -0
- package/dist/commands/workspace/open-target-selection.d.ts +13 -0
- package/dist/commands/workspace/open-target-selection.js +146 -0
- package/dist/commands/workspace/open-view.d.ts +62 -0
- package/dist/commands/workspace/open-view.js +249 -0
- package/dist/commands/workspace/open.d.ts +37 -0
- package/dist/commands/workspace/open.js +110 -0
- package/dist/commands/workspace/opener-selection.d.ts +11 -0
- package/dist/commands/workspace/opener-selection.js +98 -0
- package/dist/commands/workspace/operations.d.ts +29 -0
- package/dist/commands/workspace/operations.js +543 -0
- package/dist/commands/workspace/prompt-theme.d.ts +29 -0
- package/dist/commands/workspace/prompt-theme.js +24 -0
- package/dist/commands/workspace/registration.d.ts +13 -0
- package/dist/commands/workspace/registration.js +84 -0
- package/dist/commands/workspace/selection.d.ts +8 -0
- package/dist/commands/workspace/selection.js +104 -0
- package/dist/commands/workspace/setup-prompts.d.ts +13 -0
- package/dist/commands/workspace/setup-prompts.js +121 -0
- package/dist/commands/workspace/types.d.ts +103 -0
- package/dist/commands/workspace/types.js +36 -0
- package/dist/commands/workspace.d.ts +5 -0
- package/dist/commands/workspace.js +577 -0
- package/dist/core/archive.d.ts +11 -0
- package/dist/core/archive.js +318 -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 +183 -0
- package/dist/core/artifact-graph/instruction-loader.js +256 -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 +18 -0
- package/dist/core/change-metadata/schema.js +28 -0
- package/dist/core/change-status-policy.d.ts +50 -0
- package/dist/core/change-status-policy.js +70 -0
- package/dist/core/collections/index.d.ts +3 -0
- package/dist/core/collections/index.js +3 -0
- package/dist/core/collections/initiatives/collection.d.ts +4 -0
- package/dist/core/collections/initiatives/collection.js +17 -0
- package/dist/core/collections/initiatives/index.d.ts +6 -0
- package/dist/core/collections/initiatives/index.js +6 -0
- package/dist/core/collections/initiatives/operations.d.ts +49 -0
- package/dist/core/collections/initiatives/operations.js +175 -0
- package/dist/core/collections/initiatives/resolution.d.ts +87 -0
- package/dist/core/collections/initiatives/resolution.js +374 -0
- package/dist/core/collections/initiatives/schema.d.ts +41 -0
- package/dist/core/collections/initiatives/schema.js +134 -0
- package/dist/core/collections/initiatives/templates.d.ts +12 -0
- package/dist/core/collections/initiatives/templates.js +90 -0
- package/dist/core/collections/runtime.d.ts +46 -0
- package/dist/core/collections/runtime.js +194 -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 +45 -0
- package/dist/core/command-generation/adapters/claude.d.ts +13 -0
- package/dist/core/command-generation/adapters/claude.js +50 -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 +44 -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 +55 -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 +51 -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/completions/command-registry.d.ts +3 -0
- package/dist/core/completions/command-registry.js +961 -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 +274 -0
- package/dist/core/completions/installers/bash-installer.d.ts +87 -0
- package/dist/core/completions/installers/bash-installer.js +318 -0
- package/dist/core/completions/installers/fish-installer.d.ts +43 -0
- package/dist/core/completions/installers/fish-installer.js +143 -0
- package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
- package/dist/core/completions/installers/powershell-installer.js +387 -0
- package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
- package/dist/core/completions/installers/zsh-installer.js +421 -0
- package/dist/core/completions/shared-flags.d.ts +12 -0
- package/dist/core/completions/shared-flags.js +28 -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/config-prompts.d.ts +9 -0
- package/dist/core/config-prompts.js +34 -0
- package/dist/core/config-schema.d.ts +86 -0
- package/dist/core/config-schema.js +213 -0
- package/dist/core/config.d.ts +18 -0
- package/dist/core/config.js +39 -0
- package/dist/core/context-store/binding.d.ts +53 -0
- package/dist/core/context-store/binding.js +197 -0
- package/dist/core/context-store/errors.d.ts +20 -0
- package/dist/core/context-store/errors.js +22 -0
- package/dist/core/context-store/foundation.d.ts +55 -0
- package/dist/core/context-store/foundation.js +321 -0
- package/dist/core/context-store/index.d.ts +6 -0
- package/dist/core/context-store/index.js +6 -0
- package/dist/core/context-store/operations.d.ts +85 -0
- package/dist/core/context-store/operations.js +528 -0
- package/dist/core/context-store/registry.d.ts +45 -0
- package/dist/core/context-store/registry.js +229 -0
- package/dist/core/converters/json-converter.d.ts +6 -0
- package/dist/core/converters/json-converter.js +51 -0
- package/dist/core/global-config.d.ts +49 -0
- package/dist/core/global-config.js +124 -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 +593 -0
- package/dist/core/legacy-cleanup.d.ts +162 -0
- package/dist/core/legacy-cleanup.js +514 -0
- package/dist/core/list.d.ts +9 -0
- package/dist/core/list.js +171 -0
- package/dist/core/migration.d.ts +23 -0
- package/dist/core/migration.js +108 -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 +21 -0
- package/dist/core/planning-home.js +108 -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 +64 -0
- package/dist/core/project-config.js +223 -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 +73 -0
- package/dist/core/specs-apply.js +392 -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 +314 -0
- package/dist/core/templates/workflows/archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/archive-change.js +277 -0
- package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
- package/dist/core/templates/workflows/bulk-archive-change.js +492 -0
- package/dist/core/templates/workflows/continue-change.d.ts +10 -0
- package/dist/core/templates/workflows/continue-change.js +234 -0
- package/dist/core/templates/workflows/explore.d.ts +10 -0
- package/dist/core/templates/workflows/explore.js +459 -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 +200 -0
- package/dist/core/templates/workflows/new-change.d.ts +10 -0
- package/dist/core/templates/workflows/new-change.js +143 -0
- package/dist/core/templates/workflows/onboard.d.ts +10 -0
- package/dist/core/templates/workflows/onboard.js +563 -0
- package/dist/core/templates/workflows/propose.d.ts +10 -0
- package/dist/core/templates/workflows/propose.js +218 -0
- package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
- package/dist/core/templates/workflows/sync-specs.js +290 -0
- package/dist/core/templates/workflows/verify-change.d.ts +10 -0
- package/dist/core/templates/workflows/verify-change.js +338 -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 +43 -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/workspace/foundation.d.ts +67 -0
- package/dist/core/workspace/foundation.js +295 -0
- package/dist/core/workspace/index.d.ts +8 -0
- package/dist/core/workspace/index.js +8 -0
- package/dist/core/workspace/legacy-state.d.ts +28 -0
- package/dist/core/workspace/legacy-state.js +200 -0
- package/dist/core/workspace/link-input.d.ts +9 -0
- package/dist/core/workspace/link-input.js +32 -0
- package/dist/core/workspace/open-surface.d.ts +45 -0
- package/dist/core/workspace/open-surface.js +215 -0
- package/dist/core/workspace/openers.d.ts +21 -0
- package/dist/core/workspace/openers.js +124 -0
- package/dist/core/workspace/registry.d.ts +24 -0
- package/dist/core/workspace/registry.js +146 -0
- package/dist/core/workspace/skills.d.ts +57 -0
- package/dist/core/workspace/skills.js +334 -0
- package/dist/core/workspace/state-io.d.ts +10 -0
- package/dist/core/workspace/state-io.js +121 -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 +54 -0
- package/dist/utils/change-metadata.js +141 -0
- package/dist/utils/change-utils.d.ts +71 -0
- package/dist/utils/change-utils.js +123 -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 +301 -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 +85 -0
- package/schemas/spec-driven/schema.yaml +151 -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/schemas/workspace-planning/schema.yaml +72 -0
- package/schemas/workspace-planning/templates/design.md +33 -0
- package/schemas/workspace-planning/templates/proposal.md +28 -0
- package/schemas/workspace-planning/templates/spec.md +9 -0
- package/schemas/workspace-planning/templates/tasks.md +15 -0
- package/scripts/postinstall.js +83 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instructions Command
|
|
3
|
+
*
|
|
4
|
+
* Generates enriched instructions for creating artifacts or applying tasks.
|
|
5
|
+
* Includes both artifact instructions and apply instructions.
|
|
6
|
+
*/
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { loadChangeContext, generateInstructions, resolveSchema, resolveArtifactOutputs, } from '../../core/artifact-graph/index.js';
|
|
11
|
+
import { getChangeDir, resolveCurrentPlanningHomeSync } from '../../core/planning-home.js';
|
|
12
|
+
import { validateChangeExists, validateSchemaExists, } from './shared.js';
|
|
13
|
+
// -----------------------------------------------------------------------------
|
|
14
|
+
// Artifact Instructions Command
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
export async function instructionsCommand(artifactId, options) {
|
|
17
|
+
const spinner = options.json ? undefined : ora('正在生成指令...').start();
|
|
18
|
+
try {
|
|
19
|
+
const planningHome = resolveCurrentPlanningHomeSync();
|
|
20
|
+
const projectRoot = planningHome.root;
|
|
21
|
+
const changeName = await validateChangeExists(options.change, projectRoot, planningHome.changesDir);
|
|
22
|
+
// Validate schema if explicitly provided
|
|
23
|
+
if (options.schema) {
|
|
24
|
+
validateSchemaExists(options.schema, projectRoot);
|
|
25
|
+
}
|
|
26
|
+
// loadChangeContext will auto-detect schema from metadata if not provided
|
|
27
|
+
const context = loadChangeContext(projectRoot, changeName, options.schema, {
|
|
28
|
+
changeDir: getChangeDir(planningHome, changeName),
|
|
29
|
+
planningHome,
|
|
30
|
+
});
|
|
31
|
+
if (!artifactId) {
|
|
32
|
+
spinner?.stop();
|
|
33
|
+
const validIds = context.graph.getAllArtifacts().map((a) => a.id);
|
|
34
|
+
throw new Error(`Missing required argument <artifact>. Valid artifacts:\n ${validIds.join('\n ')}`);
|
|
35
|
+
}
|
|
36
|
+
const artifact = context.graph.getArtifact(artifactId);
|
|
37
|
+
if (!artifact) {
|
|
38
|
+
spinner?.stop();
|
|
39
|
+
const validIds = context.graph.getAllArtifacts().map((a) => a.id);
|
|
40
|
+
throw new Error(`Artifact '${artifactId}' not found in schema '${context.schemaName}'. Valid artifacts:\n ${validIds.join('\n ')}`);
|
|
41
|
+
}
|
|
42
|
+
const instructions = generateInstructions(context, artifactId, projectRoot);
|
|
43
|
+
const isBlocked = instructions.dependencies.some((d) => !d.done);
|
|
44
|
+
spinner?.stop();
|
|
45
|
+
if (options.json) {
|
|
46
|
+
console.log(JSON.stringify(instructions, null, 2));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
printInstructionsText(instructions, isBlocked);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
spinner?.stop();
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function printInstructionsText(instructions, isBlocked) {
|
|
57
|
+
const { artifactId, changeName, schemaName, changeDir, initiative, resolvedOutputPath, description, instruction, context, rules, template, dependencies, unlocks, } = instructions;
|
|
58
|
+
// Opening tag
|
|
59
|
+
console.log(`<artifact id="${artifactId}" change="${changeName}" schema="${schemaName}">`);
|
|
60
|
+
console.log();
|
|
61
|
+
if (initiative) {
|
|
62
|
+
console.log(`<initiative store="${initiative.store}" id="${initiative.id}" />`);
|
|
63
|
+
console.log();
|
|
64
|
+
}
|
|
65
|
+
// Warning for blocked artifacts
|
|
66
|
+
if (isBlocked) {
|
|
67
|
+
const missing = dependencies.filter((d) => !d.done).map((d) => d.id);
|
|
68
|
+
console.log('<warning>');
|
|
69
|
+
console.log('此制品有未满足的依赖。请先完成它们,或谨慎继续。');
|
|
70
|
+
console.log(`缺失:${missing.join(', ')}`);
|
|
71
|
+
console.log('</warning>');
|
|
72
|
+
console.log();
|
|
73
|
+
}
|
|
74
|
+
// Task directive
|
|
75
|
+
console.log('<task>');
|
|
76
|
+
console.log(`为变更 "${changeName}" 创建制品 ${artifactId}。`);
|
|
77
|
+
console.log(description);
|
|
78
|
+
console.log('</task>');
|
|
79
|
+
console.log();
|
|
80
|
+
// Project context (AI constraint - do not include in output)
|
|
81
|
+
if (context) {
|
|
82
|
+
console.log('<project_context>');
|
|
83
|
+
console.log('<!-- This is background information for you. Do NOT include this in your output. -->');
|
|
84
|
+
console.log(context);
|
|
85
|
+
console.log('</project_context>');
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
// Rules (AI constraint - do not include in output)
|
|
89
|
+
if (rules && rules.length > 0) {
|
|
90
|
+
console.log('<rules>');
|
|
91
|
+
console.log('<!-- These are constraints for you to follow. Do NOT include this in your output. -->');
|
|
92
|
+
for (const rule of rules) {
|
|
93
|
+
console.log(`- ${rule}`);
|
|
94
|
+
}
|
|
95
|
+
console.log('</rules>');
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
// Dependencies (files to read for context)
|
|
99
|
+
if (dependencies.length > 0) {
|
|
100
|
+
console.log('<dependencies>');
|
|
101
|
+
console.log('在创建此制品前,请阅读以下文件以了解上下文:');
|
|
102
|
+
console.log();
|
|
103
|
+
for (const dep of dependencies) {
|
|
104
|
+
const status = dep.done ? 'done' : 'missing';
|
|
105
|
+
const fullPath = path.join(changeDir, dep.path);
|
|
106
|
+
console.log(`<dependency id="${dep.id}" status="${status}">`);
|
|
107
|
+
console.log(` <path>${fullPath}</path>`);
|
|
108
|
+
console.log(` <description>${dep.description}</description>`);
|
|
109
|
+
console.log('</dependency>');
|
|
110
|
+
}
|
|
111
|
+
console.log('</dependencies>');
|
|
112
|
+
console.log();
|
|
113
|
+
}
|
|
114
|
+
// Output location
|
|
115
|
+
console.log('<output>');
|
|
116
|
+
console.log(`写入路径:${resolvedOutputPath}`);
|
|
117
|
+
console.log('</output>');
|
|
118
|
+
console.log();
|
|
119
|
+
// Instruction (guidance)
|
|
120
|
+
if (instruction) {
|
|
121
|
+
console.log('<instruction>');
|
|
122
|
+
console.log(instruction.trim());
|
|
123
|
+
console.log('</instruction>');
|
|
124
|
+
console.log();
|
|
125
|
+
}
|
|
126
|
+
// Template
|
|
127
|
+
console.log('<template>');
|
|
128
|
+
console.log('<!-- Use this as the structure for your output file. Fill in the sections. -->');
|
|
129
|
+
console.log(template.trim());
|
|
130
|
+
console.log('</template>');
|
|
131
|
+
console.log();
|
|
132
|
+
// Success criteria placeholder
|
|
133
|
+
console.log('<success_criteria>');
|
|
134
|
+
console.log('<!-- To be defined in schema validation rules -->');
|
|
135
|
+
console.log('</success_criteria>');
|
|
136
|
+
console.log();
|
|
137
|
+
// Unlocks
|
|
138
|
+
if (unlocks.length > 0) {
|
|
139
|
+
console.log('<unlocks>');
|
|
140
|
+
console.log(`完成此制品后,将解锁:${unlocks.join(', ')}`);
|
|
141
|
+
console.log('</unlocks>');
|
|
142
|
+
console.log();
|
|
143
|
+
}
|
|
144
|
+
// Closing tag
|
|
145
|
+
console.log('</artifact>');
|
|
146
|
+
}
|
|
147
|
+
// -----------------------------------------------------------------------------
|
|
148
|
+
// Apply Instructions Command
|
|
149
|
+
// -----------------------------------------------------------------------------
|
|
150
|
+
/**
|
|
151
|
+
* Parses tasks.md content and extracts task items with their completion status.
|
|
152
|
+
*/
|
|
153
|
+
function parseTasksFile(content) {
|
|
154
|
+
const tasks = [];
|
|
155
|
+
const lines = content.split('\n');
|
|
156
|
+
let taskIndex = 0;
|
|
157
|
+
for (const line of lines) {
|
|
158
|
+
// Match checkbox patterns: - [ ] or - [x] or - [X]
|
|
159
|
+
const checkboxMatch = line.match(/^[-*]\s*\[([ xX])\]\s*(.+)\s*$/);
|
|
160
|
+
if (checkboxMatch) {
|
|
161
|
+
taskIndex++;
|
|
162
|
+
const done = checkboxMatch[1].toLowerCase() === 'x';
|
|
163
|
+
const description = checkboxMatch[2].trim();
|
|
164
|
+
tasks.push({
|
|
165
|
+
id: `${taskIndex}`,
|
|
166
|
+
description,
|
|
167
|
+
done,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return tasks;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Generates apply instructions for implementing tasks from a change.
|
|
175
|
+
* Schema-aware: reads apply phase configuration from schema to determine
|
|
176
|
+
* required artifacts, tracking file, and instruction.
|
|
177
|
+
*/
|
|
178
|
+
export async function generateApplyInstructions(projectRoot, changeName, schemaName, planningHome = resolveCurrentPlanningHomeSync({ startPath: projectRoot })) {
|
|
179
|
+
// loadChangeContext will auto-detect schema from metadata if not provided
|
|
180
|
+
const context = loadChangeContext(projectRoot, changeName, schemaName, {
|
|
181
|
+
changeDir: getChangeDir(planningHome, changeName),
|
|
182
|
+
planningHome,
|
|
183
|
+
});
|
|
184
|
+
const changeDir = context.changeDir;
|
|
185
|
+
// Get the full schema to access the apply phase configuration
|
|
186
|
+
const schema = resolveSchema(context.schemaName, projectRoot);
|
|
187
|
+
const applyConfig = schema.apply;
|
|
188
|
+
// Determine required artifacts and tracking file from schema
|
|
189
|
+
// Fallback: if no apply block, require all artifacts
|
|
190
|
+
const requiredArtifactIds = applyConfig?.requires ?? schema.artifacts.map((a) => a.id);
|
|
191
|
+
const tracksFile = applyConfig?.tracks ?? null;
|
|
192
|
+
const schemaInstruction = applyConfig?.instruction ?? null;
|
|
193
|
+
// Check which required artifacts are missing
|
|
194
|
+
const missingArtifacts = [];
|
|
195
|
+
for (const artifactId of requiredArtifactIds) {
|
|
196
|
+
const artifact = schema.artifacts.find((a) => a.id === artifactId);
|
|
197
|
+
if (artifact && resolveArtifactOutputs(changeDir, artifact.generates).length === 0) {
|
|
198
|
+
missingArtifacts.push(artifactId);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Build context files from all existing artifacts in schema
|
|
202
|
+
const contextFiles = {};
|
|
203
|
+
for (const artifact of schema.artifacts) {
|
|
204
|
+
const outputs = resolveArtifactOutputs(changeDir, artifact.generates);
|
|
205
|
+
if (outputs.length > 0) {
|
|
206
|
+
contextFiles[artifact.id] = outputs;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Parse tasks if tracking file exists
|
|
210
|
+
let tasks = [];
|
|
211
|
+
let tracksFileExists = false;
|
|
212
|
+
if (tracksFile) {
|
|
213
|
+
const tracksPath = path.join(changeDir, tracksFile);
|
|
214
|
+
tracksFileExists = fs.existsSync(tracksPath);
|
|
215
|
+
if (tracksFileExists) {
|
|
216
|
+
const tasksContent = await fs.promises.readFile(tracksPath, 'utf-8');
|
|
217
|
+
tasks = parseTasksFile(tasksContent);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Calculate progress
|
|
221
|
+
const total = tasks.length;
|
|
222
|
+
const complete = tasks.filter((t) => t.done).length;
|
|
223
|
+
const remaining = total - complete;
|
|
224
|
+
// Determine state and instruction
|
|
225
|
+
let state;
|
|
226
|
+
let instruction;
|
|
227
|
+
if (missingArtifacts.length > 0) {
|
|
228
|
+
state = 'blocked';
|
|
229
|
+
instruction = `尚无法应用此变更。缺失制品:${missingArtifacts.join(', ')}。\n请使用 openspec-continue-change 技能先创建缺失的制品。`;
|
|
230
|
+
}
|
|
231
|
+
else if (tracksFile && !tracksFileExists) {
|
|
232
|
+
// Tracking file configured but doesn't exist yet
|
|
233
|
+
const tracksFilename = path.basename(tracksFile);
|
|
234
|
+
state = 'blocked';
|
|
235
|
+
instruction = `${tracksFilename} 文件缺失,需要创建。\n请使用 openspec-continue-change 生成跟踪文件。`;
|
|
236
|
+
}
|
|
237
|
+
else if (tracksFile && tracksFileExists && total === 0) {
|
|
238
|
+
// Tracking file exists but contains no tasks
|
|
239
|
+
const tracksFilename = path.basename(tracksFile);
|
|
240
|
+
state = 'blocked';
|
|
241
|
+
instruction = `${tracksFilename} 文件存在但未包含任何任务。\n请向 ${tracksFilename} 添加任务,或使用 openspec-continue-change 重新生成。`;
|
|
242
|
+
}
|
|
243
|
+
else if (tracksFile && remaining === 0 && total > 0) {
|
|
244
|
+
state = 'all_done';
|
|
245
|
+
instruction = '所有任务已完成!此变更已可归档。\n建议在归档前运行测试并复查更改。';
|
|
246
|
+
}
|
|
247
|
+
else if (!tracksFile) {
|
|
248
|
+
// No tracking file configured in schema - ready to apply
|
|
249
|
+
state = 'ready';
|
|
250
|
+
instruction = schemaInstruction?.trim() ?? '所有必需制品已完成。继续执行实现。';
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
state = 'ready';
|
|
254
|
+
instruction = schemaInstruction?.trim() ?? '阅读上下文文件,处理待办任务,随进度标记完成。\n如遇到阻塞或需要澄清,请暂停。';
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
changeName,
|
|
258
|
+
changeDir,
|
|
259
|
+
schemaName: context.schemaName,
|
|
260
|
+
...(context.initiative ? { initiative: context.initiative } : {}),
|
|
261
|
+
contextFiles,
|
|
262
|
+
progress: { total, complete, remaining },
|
|
263
|
+
tasks,
|
|
264
|
+
state,
|
|
265
|
+
missingArtifacts: missingArtifacts.length > 0 ? missingArtifacts : undefined,
|
|
266
|
+
instruction,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
export async function applyInstructionsCommand(options) {
|
|
270
|
+
const spinner = options.json ? undefined : ora('正在生成应用指令...').start();
|
|
271
|
+
try {
|
|
272
|
+
const planningHome = resolveCurrentPlanningHomeSync();
|
|
273
|
+
const projectRoot = planningHome.root;
|
|
274
|
+
const changeName = await validateChangeExists(options.change, projectRoot, planningHome.changesDir);
|
|
275
|
+
// Validate schema if explicitly provided
|
|
276
|
+
if (options.schema) {
|
|
277
|
+
validateSchemaExists(options.schema, projectRoot);
|
|
278
|
+
}
|
|
279
|
+
// generateApplyInstructions uses loadChangeContext which auto-detects schema
|
|
280
|
+
const instructions = await generateApplyInstructions(projectRoot, changeName, options.schema, planningHome);
|
|
281
|
+
spinner?.stop();
|
|
282
|
+
if (options.json) {
|
|
283
|
+
console.log(JSON.stringify(instructions, null, 2));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
printApplyInstructionsText(instructions);
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
spinner?.stop();
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
export function printApplyInstructionsText(instructions) {
|
|
294
|
+
const { changeName, schemaName, initiative, contextFiles, progress, tasks, state, missingArtifacts, instruction } = instructions;
|
|
295
|
+
console.log(`## 应用:${changeName}`);
|
|
296
|
+
console.log(`架构:${schemaName}`);
|
|
297
|
+
if (initiative) {
|
|
298
|
+
console.log(`计划:${initiative.store}/${initiative.id}`);
|
|
299
|
+
}
|
|
300
|
+
console.log();
|
|
301
|
+
// Warning for blocked state
|
|
302
|
+
if (state === 'blocked' && missingArtifacts) {
|
|
303
|
+
console.log('### ⚠️ 已阻塞');
|
|
304
|
+
console.log();
|
|
305
|
+
console.log(`缺失制品:${missingArtifacts.join(', ')}`);
|
|
306
|
+
console.log('请使用 openspec-continue-change 技能先创建这些制品。');
|
|
307
|
+
console.log();
|
|
308
|
+
}
|
|
309
|
+
// Context files (dynamically from schema)
|
|
310
|
+
const contextFileEntries = Object.entries(contextFiles);
|
|
311
|
+
if (contextFileEntries.length > 0) {
|
|
312
|
+
console.log('### 上下文文件');
|
|
313
|
+
for (const [artifactId, filePaths] of contextFileEntries) {
|
|
314
|
+
for (const filePath of filePaths) {
|
|
315
|
+
console.log(`- ${artifactId}: ${filePath}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
console.log();
|
|
319
|
+
}
|
|
320
|
+
// Progress (only show if we have tracking)
|
|
321
|
+
if (progress.total > 0 || tasks.length > 0) {
|
|
322
|
+
console.log('### 进度');
|
|
323
|
+
if (state === 'all_done') {
|
|
324
|
+
console.log(`${progress.complete}/${progress.total} 已完成 ✓`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
console.log(`${progress.complete}/${progress.total} 已完成`);
|
|
328
|
+
}
|
|
329
|
+
console.log();
|
|
330
|
+
}
|
|
331
|
+
// Tasks
|
|
332
|
+
if (tasks.length > 0) {
|
|
333
|
+
console.log('### 任务');
|
|
334
|
+
for (const task of tasks) {
|
|
335
|
+
const checkbox = task.done ? '[x]' : '[ ]';
|
|
336
|
+
console.log(`- ${checkbox} ${task.description}`);
|
|
337
|
+
}
|
|
338
|
+
console.log();
|
|
339
|
+
}
|
|
340
|
+
// Instruction
|
|
341
|
+
console.log('### 指令');
|
|
342
|
+
console.log(instruction);
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=instructions.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New Change Command
|
|
3
|
+
*
|
|
4
|
+
* Creates a new change directory with optional description and schema.
|
|
5
|
+
*/
|
|
6
|
+
export interface NewChangeOptions {
|
|
7
|
+
description?: string;
|
|
8
|
+
goal?: string;
|
|
9
|
+
areas?: string;
|
|
10
|
+
schema?: string;
|
|
11
|
+
initiative?: string;
|
|
12
|
+
store?: string;
|
|
13
|
+
storePath?: string;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function newChangeCommand(name: string | undefined, options: NewChangeOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=new-change.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New Change Command
|
|
3
|
+
*
|
|
4
|
+
* Creates a new change directory with optional description and schema.
|
|
5
|
+
*/
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { createChange, validateChangeName } from '../../utils/change-utils.js';
|
|
9
|
+
import { formatChangeLocation, resolveCurrentPlanningHomeSync, } from '../../core/planning-home.js';
|
|
10
|
+
import { validateSchemaExists } from './shared.js';
|
|
11
|
+
import { resolveInitiativeLinkReference, } from '../../core/collections/initiatives/index.js';
|
|
12
|
+
import { assertInitiativeSelectorsHaveReference, assertRepoLocalInitiativeLinkPlanningHome, formatInitiativeLink, printJson, statusFromError, } from './initiative-link.js';
|
|
13
|
+
// -----------------------------------------------------------------------------
|
|
14
|
+
// Command Implementation
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
function parseAffectedAreas(value) {
|
|
17
|
+
return (value ?? '')
|
|
18
|
+
.split(',')
|
|
19
|
+
.map((area) => area.trim())
|
|
20
|
+
.filter((area) => area.length > 0);
|
|
21
|
+
}
|
|
22
|
+
function validateWorkspaceAffectedAreas(planningHome, affectedAreas) {
|
|
23
|
+
if (affectedAreas.length === 0) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (planningHome.kind !== 'workspace') {
|
|
27
|
+
throw new Error('--areas 只能在创建工作区范围的变更时使用');
|
|
28
|
+
}
|
|
29
|
+
const validAreas = new Set(planningHome.workspace?.links ?? []);
|
|
30
|
+
const invalidAreas = affectedAreas.filter((area) => !validAreas.has(area));
|
|
31
|
+
if (invalidAreas.length > 0) {
|
|
32
|
+
const validList = [...validAreas].sort((a, b) => a.localeCompare(b));
|
|
33
|
+
const validMessage = validList.length > 0 ? validList.join(', ') : '(no registered links)';
|
|
34
|
+
throw new Error(`无效的影响区域:${invalidAreas.join(', ')}。` +
|
|
35
|
+
`有效的工作区链接名称:${validMessage}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function outputForCreatedChange(id, changeDir, schema, initiative) {
|
|
39
|
+
return {
|
|
40
|
+
change: {
|
|
41
|
+
id,
|
|
42
|
+
path: changeDir,
|
|
43
|
+
metadataPath: path.join(changeDir, '.openspec.yaml'),
|
|
44
|
+
schema,
|
|
45
|
+
},
|
|
46
|
+
...(initiative ? { initiative } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function printCreatedChangeHuman(payload, planningHome) {
|
|
50
|
+
if (!payload.change) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const location = formatChangeLocation(planningHome, payload.change.id);
|
|
54
|
+
const scope = planningHome.kind === 'workspace' ? '工作区变更' : '变更';
|
|
55
|
+
console.log(`已创建${scope} '${payload.change.id}' 于 ${location}/`);
|
|
56
|
+
console.log(`架构:${payload.change.schema}`);
|
|
57
|
+
if (payload.initiative) {
|
|
58
|
+
console.log(`计划:${formatInitiativeLink(payload.initiative)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export async function newChangeCommand(name, options) {
|
|
62
|
+
const spinner = options.json ? undefined : ora();
|
|
63
|
+
try {
|
|
64
|
+
if (!name) {
|
|
65
|
+
throw new Error('缺少必需参数 <name>');
|
|
66
|
+
}
|
|
67
|
+
const validation = validateChangeName(name);
|
|
68
|
+
if (!validation.valid) {
|
|
69
|
+
throw new Error(validation.error);
|
|
70
|
+
}
|
|
71
|
+
assertInitiativeSelectorsHaveReference(options);
|
|
72
|
+
const planningHome = resolveCurrentPlanningHomeSync();
|
|
73
|
+
const projectRoot = planningHome.root;
|
|
74
|
+
const affectedAreas = parseAffectedAreas(options.areas);
|
|
75
|
+
validateWorkspaceAffectedAreas(planningHome, affectedAreas);
|
|
76
|
+
let initiative;
|
|
77
|
+
if (options.initiative !== undefined) {
|
|
78
|
+
assertRepoLocalInitiativeLinkPlanningHome(planningHome);
|
|
79
|
+
initiative = await resolveInitiativeLinkReference(options.initiative, {
|
|
80
|
+
store: options.store,
|
|
81
|
+
storePath: options.storePath,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Validate schema if provided
|
|
85
|
+
if (options.schema) {
|
|
86
|
+
validateSchemaExists(options.schema, projectRoot);
|
|
87
|
+
}
|
|
88
|
+
const resolvedSchema = options.schema ?? planningHome.defaultSchema;
|
|
89
|
+
if (spinner) {
|
|
90
|
+
spinner.start(`正在创建变更 '${name}'(架构:'${resolvedSchema}')...`);
|
|
91
|
+
}
|
|
92
|
+
const workspaceGoal = planningHome.kind === 'workspace'
|
|
93
|
+
? options.goal ?? options.description
|
|
94
|
+
: options.goal;
|
|
95
|
+
const result = await createChange(projectRoot, name, {
|
|
96
|
+
schema: options.schema,
|
|
97
|
+
defaultSchema: planningHome.defaultSchema,
|
|
98
|
+
changesDir: planningHome.changesDir,
|
|
99
|
+
metadata: {
|
|
100
|
+
...(workspaceGoal ? { goal: workspaceGoal } : {}),
|
|
101
|
+
...(affectedAreas.length > 0 ? { affected_areas: affectedAreas } : {}),
|
|
102
|
+
...(initiative ? { initiative } : {}),
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
// If description provided, create README.md with description
|
|
106
|
+
if (options.description) {
|
|
107
|
+
const { promises: fs } = await import('fs');
|
|
108
|
+
const readmePath = path.join(result.changeDir, 'README.md');
|
|
109
|
+
await fs.writeFile(readmePath, `# ${name}\n\n${options.description}\n`, 'utf-8');
|
|
110
|
+
}
|
|
111
|
+
const payload = outputForCreatedChange(name, result.changeDir, result.schema, initiative);
|
|
112
|
+
if (options.json) {
|
|
113
|
+
printJson(payload);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
spinner?.stop();
|
|
117
|
+
printCreatedChangeHuman(payload, planningHome);
|
|
118
|
+
if (planningHome.kind === 'workspace' && !initiative) {
|
|
119
|
+
if (affectedAreas.length > 0) {
|
|
120
|
+
console.log(`影响区域:${affectedAreas.join(', ')}`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.log('影响区域:未指定;在规划过程中通过工作区规格或任务识别。');
|
|
124
|
+
}
|
|
125
|
+
console.log('下一步:运行 openspec status --change "' + name + '" 查看工作区规划制品。');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
spinner?.stop();
|
|
130
|
+
if (options.json) {
|
|
131
|
+
printJson({
|
|
132
|
+
change: null,
|
|
133
|
+
status: [statusFromError(error)],
|
|
134
|
+
});
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=new-change.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schemas Command
|
|
3
|
+
*
|
|
4
|
+
* Lists available workflow schemas with descriptions.
|
|
5
|
+
*/
|
|
6
|
+
export interface SchemasOptions {
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function schemasCommand(options: SchemasOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schemas Command
|
|
3
|
+
*
|
|
4
|
+
* Lists available workflow schemas with descriptions.
|
|
5
|
+
*/
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { listSchemasWithInfo } from '../../core/artifact-graph/index.js';
|
|
8
|
+
// -----------------------------------------------------------------------------
|
|
9
|
+
// Command Implementation
|
|
10
|
+
// -----------------------------------------------------------------------------
|
|
11
|
+
export async function schemasCommand(options) {
|
|
12
|
+
const projectRoot = process.cwd();
|
|
13
|
+
const schemas = listSchemasWithInfo(projectRoot);
|
|
14
|
+
if (options.json) {
|
|
15
|
+
console.log(JSON.stringify(schemas, null, 2));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
console.log('可用架构:');
|
|
19
|
+
console.log();
|
|
20
|
+
for (const schema of schemas) {
|
|
21
|
+
let sourceLabel = '';
|
|
22
|
+
if (schema.source === 'project') {
|
|
23
|
+
sourceLabel = chalk.cyan('(项目)');
|
|
24
|
+
}
|
|
25
|
+
else if (schema.source === 'user') {
|
|
26
|
+
sourceLabel = chalk.dim('(用户覆盖)');
|
|
27
|
+
}
|
|
28
|
+
console.log(` ${chalk.bold(schema.name)}${sourceLabel}`);
|
|
29
|
+
console.log(` ${schema.description}`);
|
|
30
|
+
console.log(` 制品:${schema.artifacts.join(' → ')}`);
|
|
31
|
+
console.log();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set Change Command
|
|
3
|
+
*
|
|
4
|
+
* Mutates checked-in repo-local change metadata.
|
|
5
|
+
*/
|
|
6
|
+
export interface SetChangeOptions {
|
|
7
|
+
initiative?: string;
|
|
8
|
+
store?: string;
|
|
9
|
+
storePath?: string;
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function setChangeCommand(name: string | undefined, options: SetChangeOptions): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=set-change.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set Change Command
|
|
3
|
+
*
|
|
4
|
+
* Mutates checked-in repo-local change metadata.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { getChangeDir, resolveCurrentPlanningHomeSync, } from '../../core/planning-home.js';
|
|
8
|
+
import { readChangeMetadata, resolveSchemaForChange, writeChangeMetadata, } from '../../utils/change-metadata.js';
|
|
9
|
+
import { validateChangeExists } from './shared.js';
|
|
10
|
+
import { resolveInitiativeLinkReference, } from '../../core/collections/initiatives/index.js';
|
|
11
|
+
import { assertInitiativeReference, assertRepoLocalInitiativeLinkPlanningHome, formatInitiativeLink, printJson, sameInitiativeLink, statusFromError, } from './initiative-link.js';
|
|
12
|
+
function outputForSetChange(id, changeDir, schema, initiative, updated) {
|
|
13
|
+
return {
|
|
14
|
+
change: {
|
|
15
|
+
id,
|
|
16
|
+
path: changeDir,
|
|
17
|
+
metadataPath: path.join(changeDir, '.openspec.yaml'),
|
|
18
|
+
schema,
|
|
19
|
+
},
|
|
20
|
+
initiative,
|
|
21
|
+
updated,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function printSetChangeHuman(payload) {
|
|
25
|
+
if (!payload.change || !payload.initiative) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const verb = payload.updated ? 'Linked' : 'Change already linked';
|
|
29
|
+
console.log(`${verb}: ${payload.change.id}`);
|
|
30
|
+
console.log(`Initiative: ${formatInitiativeLink(payload.initiative)}`);
|
|
31
|
+
console.log(`Metadata: ${payload.change.metadataPath}`);
|
|
32
|
+
}
|
|
33
|
+
export async function setChangeCommand(name, options) {
|
|
34
|
+
try {
|
|
35
|
+
if (!name) {
|
|
36
|
+
throw new Error('Missing required argument <name>');
|
|
37
|
+
}
|
|
38
|
+
assertInitiativeReference(options.initiative);
|
|
39
|
+
const planningHome = resolveCurrentPlanningHomeSync();
|
|
40
|
+
assertRepoLocalInitiativeLinkPlanningHome(planningHome);
|
|
41
|
+
const projectRoot = planningHome.root;
|
|
42
|
+
const changeName = await validateChangeExists(name, projectRoot, planningHome.changesDir);
|
|
43
|
+
const changeDir = getChangeDir(planningHome, changeName);
|
|
44
|
+
const initiative = await resolveInitiativeLinkReference(options.initiative, {
|
|
45
|
+
store: options.store,
|
|
46
|
+
storePath: options.storePath,
|
|
47
|
+
});
|
|
48
|
+
const existingMetadata = readChangeMetadata(changeDir, projectRoot);
|
|
49
|
+
const metadata = existingMetadata ?? {
|
|
50
|
+
schema: resolveSchemaForChange(changeDir, undefined, projectRoot, { metadata: null }),
|
|
51
|
+
};
|
|
52
|
+
if (sameInitiativeLink(metadata.initiative, initiative)) {
|
|
53
|
+
const payload = outputForSetChange(changeName, changeDir, metadata.schema, initiative, false);
|
|
54
|
+
if (options.json) {
|
|
55
|
+
printJson(payload);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
printSetChangeHuman(payload);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (metadata.initiative) {
|
|
62
|
+
throw new Error(`Change '${changeName}' is already linked to initiative ${formatInitiativeLink(metadata.initiative)}.`);
|
|
63
|
+
}
|
|
64
|
+
writeChangeMetadata(changeDir, {
|
|
65
|
+
...metadata,
|
|
66
|
+
initiative,
|
|
67
|
+
}, projectRoot);
|
|
68
|
+
const payload = outputForSetChange(changeName, changeDir, metadata.schema, initiative, true);
|
|
69
|
+
if (options.json) {
|
|
70
|
+
printJson(payload);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
printSetChangeHuman(payload);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (options.json) {
|
|
77
|
+
printJson({
|
|
78
|
+
change: null,
|
|
79
|
+
status: [statusFromError(error)],
|
|
80
|
+
});
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=set-change.js.map
|