@codewalla_india/openspec 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -22
- package/README.md +272 -191
- package/bin/openspec.js +5 -5
- package/dist/cli/index.js +99 -62
- package/dist/commands/change.d.ts +0 -2
- package/dist/commands/change.js +107 -86
- package/dist/commands/config.js +14 -16
- package/dist/commands/doctor.js +9 -4
- package/dist/commands/feedback.js +79 -30
- package/dist/commands/modify.d.ts +26 -0
- package/dist/commands/modify.js +147 -0
- package/dist/commands/schema.js +170 -91
- package/dist/commands/show.js +5 -2
- package/dist/commands/spec.js +49 -29
- package/dist/commands/store.js +15 -21
- package/dist/commands/validate.d.ts +8 -0
- package/dist/commands/validate.js +43 -20
- package/dist/commands/workflow/index.d.ts +2 -2
- package/dist/commands/workflow/index.js +1 -1
- package/dist/commands/workflow/instructions.d.ts +6 -26
- package/dist/commands/workflow/instructions.js +183 -376
- package/dist/commands/workflow/new-change.d.ts +0 -4
- package/dist/commands/workflow/new-change.js +10 -28
- package/dist/commands/workflow/shared.d.ts +34 -19
- package/dist/commands/workflow/shared.js +34 -4
- package/dist/commands/workflow/status.js +10 -32
- package/dist/commands/workflow/templates.js +15 -5
- package/dist/commands/workset.d.ts +2 -2
- package/dist/commands/workset.js +19 -22
- package/dist/comprehension-quiz/fingerprint.d.ts +39 -0
- package/dist/comprehension-quiz/fingerprint.js +84 -0
- package/dist/comprehension-quiz/index.d.ts +42 -0
- package/dist/comprehension-quiz/index.js +47 -0
- package/dist/comprehension-quiz/pass-record.d.ts +44 -0
- package/dist/comprehension-quiz/pass-record.js +98 -0
- package/dist/comprehension-quiz/providers/anthropic.d.ts +34 -0
- package/dist/comprehension-quiz/providers/anthropic.js +53 -0
- package/dist/comprehension-quiz/providers/factory.d.ts +44 -0
- package/dist/comprehension-quiz/providers/factory.js +174 -0
- package/dist/comprehension-quiz/providers/interface.d.ts +59 -0
- package/dist/comprehension-quiz/providers/interface.js +63 -0
- package/dist/comprehension-quiz/providers/local.d.ts +34 -0
- package/dist/comprehension-quiz/providers/local.js +53 -0
- package/dist/comprehension-quiz/providers/ollama.d.ts +34 -0
- package/dist/comprehension-quiz/providers/ollama.js +53 -0
- package/dist/comprehension-quiz/providers/openai.d.ts +34 -0
- package/dist/comprehension-quiz/providers/openai.js +53 -0
- package/dist/comprehension-quiz/question-generator.d.ts +69 -0
- package/dist/comprehension-quiz/question-generator.js +141 -0
- package/dist/comprehension-quiz/quiz-executor.d.ts +70 -0
- package/dist/comprehension-quiz/quiz-executor.js +165 -0
- package/dist/comprehension-quiz/types.d.ts +115 -0
- package/dist/comprehension-quiz/types.js +11 -0
- package/dist/core/archive.d.ts +14 -1
- package/dist/core/archive.js +1350 -190
- package/dist/core/artifact-graph/graph.d.ts +28 -9
- package/dist/core/artifact-graph/graph.js +94 -43
- package/dist/core/artifact-graph/index.d.ts +1 -1
- package/dist/core/artifact-graph/index.js +1 -1
- package/dist/core/artifact-graph/instruction-loader.d.ts +30 -3
- package/dist/core/artifact-graph/instruction-loader.js +70 -12
- package/dist/core/artifact-graph/outputs.d.ts +1 -0
- package/dist/core/artifact-graph/outputs.js +67 -5
- package/dist/core/artifact-graph/resolver.d.ts +14 -0
- package/dist/core/artifact-graph/resolver.js +69 -15
- package/dist/core/artifact-graph/types.js +21 -3
- package/dist/core/available-tools.d.ts +2 -2
- package/dist/core/available-tools.js +14 -3
- package/dist/core/change-metadata/schema.d.ts +2 -0
- package/dist/core/change-metadata/schema.js +13 -0
- package/dist/core/change-status-policy.d.ts +10 -1
- package/dist/core/change-status-policy.js +30 -2
- package/dist/core/command-generation/adapters/amazon-q.d.ts +4 -0
- package/dist/core/command-generation/adapters/amazon-q.js +11 -5
- package/dist/core/command-generation/adapters/antigravity.js +6 -5
- package/dist/core/command-generation/adapters/auggie.js +7 -6
- package/dist/core/command-generation/adapters/bob.d.ts +5 -1
- package/dist/core/command-generation/adapters/bob.js +11 -10
- package/dist/core/command-generation/adapters/claude.d.ts +1 -1
- package/dist/core/command-generation/adapters/claude.js +12 -17
- package/dist/core/command-generation/adapters/cline.js +5 -5
- package/dist/core/command-generation/adapters/codebuddy.js +8 -7
- package/dist/core/command-generation/adapters/continue.js +8 -7
- package/dist/core/command-generation/adapters/costrict.js +7 -6
- package/dist/core/command-generation/adapters/crush.js +9 -9
- package/dist/core/command-generation/adapters/cursor.js +8 -8
- package/dist/core/command-generation/adapters/devin.d.ts +19 -0
- package/dist/core/command-generation/adapters/devin.js +36 -0
- package/dist/core/command-generation/adapters/factory.js +7 -6
- package/dist/core/command-generation/adapters/gemini.js +40 -5
- package/dist/core/command-generation/adapters/github-copilot.js +6 -5
- package/dist/core/command-generation/adapters/iflow.js +9 -8
- package/dist/core/command-generation/adapters/index.d.ts +4 -2
- package/dist/core/command-generation/adapters/index.js +4 -2
- package/dist/core/command-generation/adapters/junie.js +6 -5
- package/dist/core/command-generation/adapters/kilocode.js +1 -1
- package/dist/core/command-generation/adapters/kiro.js +6 -5
- package/dist/core/command-generation/adapters/lingma.js +9 -9
- package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
- package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
- package/dist/core/command-generation/adapters/opencode.js +6 -8
- package/dist/core/command-generation/adapters/pi.d.ts +2 -2
- package/dist/core/command-generation/adapters/pi.js +7 -10
- package/dist/core/command-generation/adapters/qoder.js +9 -9
- package/dist/core/command-generation/adapters/qwen.d.ts +7 -3
- package/dist/core/command-generation/adapters/qwen.js +14 -9
- package/dist/core/command-generation/adapters/roocode.d.ts +4 -4
- package/dist/core/command-generation/adapters/roocode.js +9 -9
- package/dist/core/command-generation/adapters/trae.d.ts +13 -0
- package/dist/core/command-generation/adapters/trae.js +28 -0
- package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
- package/dist/core/command-generation/adapters/zcode.js +33 -0
- package/dist/core/command-generation/generator.d.ts +8 -0
- package/dist/core/command-generation/generator.js +15 -1
- package/dist/core/command-generation/index.d.ts +1 -1
- package/dist/core/command-generation/index.js +1 -1
- package/dist/core/command-generation/invocation.d.ts +73 -0
- package/dist/core/command-generation/invocation.js +77 -0
- package/dist/core/command-generation/registry.js +8 -4
- package/dist/core/command-generation/types.d.ts +9 -2
- package/dist/core/command-generation/yaml.d.ts +20 -6
- package/dist/core/command-generation/yaml.js +31 -21
- package/dist/core/command-surface.d.ts +15 -0
- package/dist/core/command-surface.js +33 -0
- package/dist/core/completions/command-registry.js +16 -61
- package/dist/core/completions/generators/bash-generator.js +41 -41
- package/dist/core/completions/generators/fish-generator.js +7 -7
- package/dist/core/completions/generators/powershell-generator.js +44 -37
- package/dist/core/completions/generators/zsh-generator.js +33 -33
- package/dist/core/completions/installers/zsh-installer.d.ts +9 -0
- package/dist/core/completions/installers/zsh-installer.js +20 -4
- package/dist/core/completions/templates/bash-templates.js +24 -24
- package/dist/core/completions/templates/fish-templates.js +38 -38
- package/dist/core/completions/templates/powershell-templates.js +28 -28
- package/dist/core/completions/templates/zsh-templates.js +39 -39
- package/dist/core/config-prompts.d.ts +1 -1
- package/dist/core/config-prompts.js +14 -1
- package/dist/core/config-schema.d.ts +10 -1
- package/dist/core/config-schema.js +67 -1
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.js +46 -5
- package/dist/core/file-state.js +56 -24
- package/dist/core/github-copilot/cloud-agent.d.ts +95 -0
- package/dist/core/github-copilot/cloud-agent.js +497 -0
- package/dist/core/global-config.d.ts +16 -0
- package/dist/core/init.d.ts +58 -0
- package/dist/core/init.js +474 -73
- package/dist/core/legacy-cleanup.d.ts +59 -0
- package/dist/core/legacy-cleanup.js +253 -24
- package/dist/core/list.js +23 -16
- package/dist/core/migration.d.ts +73 -1
- package/dist/core/migration.js +360 -11
- package/dist/core/modify/conflict-detector.d.ts +26 -0
- package/dist/core/modify/conflict-detector.js +62 -0
- package/dist/core/modify/dependency-propagator.d.ts +38 -0
- package/dist/core/modify/dependency-propagator.js +103 -0
- package/dist/core/modify/history-tracker.d.ts +34 -0
- package/dist/core/modify/history-tracker.js +114 -0
- package/dist/core/modify/index.d.ts +7 -0
- package/dist/core/modify/index.js +7 -0
- package/dist/core/onboarding-commands.d.ts +30 -0
- package/dist/core/onboarding-commands.js +38 -0
- package/dist/core/openspec-root.js +18 -15
- package/dist/core/parsers/change-parser.d.ts +17 -2
- package/dist/core/parsers/change-parser.js +35 -21
- package/dist/core/parsers/code-fence.d.ts +15 -0
- package/dist/core/parsers/code-fence.js +49 -0
- package/dist/core/parsers/markdown-parser.d.ts +0 -3
- package/dist/core/parsers/markdown-parser.js +7 -60
- package/dist/core/parsers/requirement-blocks.d.ts +29 -0
- package/dist/core/parsers/requirement-blocks.js +150 -31
- package/dist/core/parsers/requirement-text.d.ts +48 -0
- package/dist/core/parsers/requirement-text.js +98 -0
- package/dist/core/parsers/spec-structure.d.ts +1 -1
- package/dist/core/parsers/spec-structure.js +20 -30
- package/dist/core/profile-sync-drift.d.ts +0 -8
- package/dist/core/profile-sync-drift.js +49 -50
- package/dist/core/profiles.d.ts +2 -2
- package/dist/core/profiles.js +2 -2
- package/dist/core/project-config.d.ts +27 -18
- package/dist/core/project-config.js +101 -34
- package/dist/core/references.js +42 -4
- package/dist/core/relationship-health.d.ts +8 -0
- package/dist/core/relationship-health.js +13 -0
- package/dist/core/root-selection.d.ts +9 -6
- package/dist/core/root-selection.js +42 -5
- package/dist/core/schemas/base.schema.js +7 -2
- package/dist/core/shared/allowed-tools.d.ts +12 -0
- package/dist/core/shared/allowed-tools.js +12 -0
- package/dist/core/shared/index.d.ts +1 -0
- package/dist/core/shared/index.js +1 -0
- package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
- package/dist/core/shared/skill-content-equivalence.js +41 -0
- package/dist/core/shared/skill-generation.js +17 -13
- package/dist/core/shared/skill-paths.d.ts +13 -0
- package/dist/core/shared/skill-paths.js +23 -0
- package/dist/core/shared/tool-detection.d.ts +27 -7
- package/dist/core/shared/tool-detection.js +167 -37
- package/dist/core/shared-skill-target.d.ts +16 -0
- package/dist/core/shared-skill-target.js +156 -0
- package/dist/core/specs-apply.d.ts +80 -33
- package/dist/core/specs-apply.js +667 -145
- package/dist/core/store/git.d.ts +13 -0
- package/dist/core/store/git.js +24 -0
- package/dist/core/store/operations.js +20 -0
- package/dist/core/templates/skill-templates.d.ts +3 -2
- package/dist/core/templates/skill-templates.js +3 -2
- package/dist/core/templates/workflows/apply-change.d.ts +10 -0
- package/dist/core/templates/workflows/apply-change.js +186 -224
- package/dist/core/templates/workflows/archive-change.js +387 -260
- package/dist/core/templates/workflows/bulk-archive-change.js +655 -475
- package/dist/core/templates/workflows/continue-change.js +210 -219
- package/dist/core/templates/workflows/explore.js +479 -443
- package/dist/core/templates/workflows/feedback.js +97 -97
- package/dist/core/templates/workflows/ff-change.js +200 -191
- package/dist/core/templates/workflows/modify-change.d.ts +4 -1
- package/dist/core/templates/workflows/modify-change.js +237 -115
- package/dist/core/templates/workflows/new-change.js +127 -134
- package/dist/core/templates/workflows/onboard.js +548 -542
- package/dist/core/templates/workflows/propose.js +273 -217
- package/dist/core/templates/workflows/store-selection.d.ts +1 -1
- package/dist/core/templates/workflows/store-selection.js +1 -1
- package/dist/core/templates/workflows/sync-specs.js +500 -273
- package/dist/core/templates/workflows/update-change.d.ts +10 -0
- package/dist/core/templates/workflows/update-change.js +177 -0
- package/dist/core/templates/workflows/verify-change.js +324 -326
- package/dist/core/update.d.ts +40 -5
- package/dist/core/update.js +411 -96
- package/dist/core/validation/constants.d.ts +4 -1
- package/dist/core/validation/constants.js +4 -1
- package/dist/core/validation/plan-validator.d.ts +8 -0
- package/dist/core/validation/plan-validator.js +45 -0
- package/dist/core/validation/task-numbering.d.ts +16 -0
- package/dist/core/validation/task-numbering.js +57 -0
- package/dist/core/validation/validator.d.ts +27 -3
- package/dist/core/validation/validator.js +337 -48
- package/dist/core/version-check.d.ts +152 -0
- package/dist/core/version-check.js +731 -0
- package/dist/core/view.js +13 -18
- package/dist/prompts/searchable-multi-select.js +1 -1
- package/dist/telemetry/caller-detection.d.ts +27 -0
- package/dist/telemetry/caller-detection.js +85 -0
- package/dist/telemetry/caller-detection.test.d.ts +5 -0
- package/dist/telemetry/config.d.ts +48 -2
- package/dist/telemetry/config.js +113 -11
- package/dist/telemetry/config.test.d.ts +5 -0
- package/dist/telemetry/deduplication.d.ts +35 -0
- package/dist/telemetry/deduplication.js +82 -0
- package/dist/telemetry/deduplication.test.d.ts +5 -0
- package/dist/telemetry/identity.d.ts +62 -22
- package/dist/telemetry/identity.js +147 -102
- package/dist/telemetry/index.d.ts +126 -15
- package/dist/telemetry/index.js +569 -37
- package/dist/telemetry/sanitization.d.ts +40 -0
- package/dist/telemetry/sanitization.js +114 -0
- package/dist/telemetry/sanitization.test.d.ts +5 -0
- package/dist/telemetry/throttling.d.ts +20 -0
- package/dist/telemetry/throttling.js +70 -0
- package/dist/ui/welcome-screen.d.ts +9 -1
- package/dist/ui/welcome-screen.js +91 -38
- package/dist/utils/change-metadata.d.ts +43 -0
- package/dist/utils/change-metadata.js +123 -7
- package/dist/utils/change-utils.d.ts +10 -4
- package/dist/utils/change-utils.js +20 -13
- package/dist/utils/ci.d.ts +12 -0
- package/dist/utils/ci.js +16 -0
- package/dist/utils/command-references.d.ts +92 -6
- package/dist/utils/command-references.js +180 -7
- package/dist/utils/date.d.ts +8 -0
- package/dist/utils/date.js +13 -0
- package/dist/utils/file-system.d.ts +10 -0
- package/dist/utils/file-system.js +70 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/interactive.d.ts +23 -0
- package/dist/utils/interactive.js +32 -0
- package/dist/utils/item-discovery.d.ts +19 -0
- package/dist/utils/item-discovery.js +30 -48
- package/dist/utils/shell-detection.d.ts +1 -1
- package/dist/utils/shell-detection.js +64 -11
- package/dist/utils/spec-discovery.d.ts +40 -0
- package/dist/utils/spec-discovery.js +115 -0
- package/dist/utils/task-progress.d.ts +29 -1
- package/dist/utils/task-progress.js +109 -15
- package/package.json +96 -84
- package/schemas/spec-driven/schema.yaml +252 -184
- package/schemas/spec-driven/templates/design.md +19 -19
- package/schemas/spec-driven/templates/plan-template.md +91 -0
- package/schemas/spec-driven/templates/proposal.md +29 -24
- package/schemas/spec-driven/templates/spec.md +11 -8
- package/schemas/spec-driven/templates/tasks.md +9 -9
- package/scripts/postinstall.js +83 -83
- package/dist/core/command-generation/adapters/codex.d.ts +0 -16
- package/dist/core/command-generation/adapters/codex.js +0 -39
- package/dist/core/command-generation/adapters/windsurf.d.ts +0 -14
- package/dist/core/command-generation/adapters/windsurf.js +0 -38
- package/dist/core/comprehension/config.d.ts +0 -20
- package/dist/core/comprehension/config.js +0 -23
- package/dist/core/comprehension/fingerprint.d.ts +0 -14
- package/dist/core/comprehension/fingerprint.js +0 -33
- package/dist/core/comprehension/index.d.ts +0 -57
- package/dist/core/comprehension/index.js +0 -87
- package/dist/core/comprehension/pass-record.d.ts +0 -29
- package/dist/core/comprehension/pass-record.js +0 -64
- package/dist/core/comprehension/stats.d.ts +0 -35
- package/dist/core/comprehension/stats.js +0 -133
- package/dist/core/templates/workflows/comprehension-guidance.d.ts +0 -9
- package/dist/core/templates/workflows/comprehension-guidance.js +0 -73
- package/dist/core/templates/workflows/mcp-guidance.d.ts +0 -13
- package/dist/core/templates/workflows/mcp-guidance.js +0 -131
- package/dist/core/templates/workflows/user-prompt-guidance.d.ts +0 -16
- package/dist/core/templates/workflows/user-prompt-guidance.js +0 -48
- package/dist/telemetry/caller.d.ts +0 -5
- package/dist/telemetry/caller.js +0 -29
- package/dist/telemetry/client.d.ts +0 -27
- package/dist/telemetry/client.js +0 -127
- package/dist/telemetry/command-context.d.ts +0 -13
- package/dist/telemetry/command-context.js +0 -59
- package/dist/telemetry/comprehension.d.ts +0 -44
- package/dist/telemetry/comprehension.js +0 -105
- package/dist/telemetry/content.d.ts +0 -10
- package/dist/telemetry/content.js +0 -56
- package/dist/telemetry/git-stats.d.ts +0 -12
- package/dist/telemetry/git-stats.js +0 -69
- package/dist/telemetry/identify-cache.d.ts +0 -7
- package/dist/telemetry/identify-cache.js +0 -47
- package/dist/telemetry/input.d.ts +0 -17
- package/dist/telemetry/input.js +0 -68
- package/dist/telemetry/marker.d.ts +0 -37
- package/dist/telemetry/marker.js +0 -67
- package/dist/telemetry/workflow.d.ts +0 -85
- package/dist/telemetry/workflow.js +0 -318
- package/schemas/spec-driven/templates/plan.md +0 -19
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
1
2
|
import type { SchemaYaml } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Error thrown when loading a schema fails.
|
|
@@ -22,6 +23,19 @@ export declare function getUserSchemasDir(): string;
|
|
|
22
23
|
* @returns The path to the project's schemas directory
|
|
23
24
|
*/
|
|
24
25
|
export declare function getProjectSchemasDir(projectRoot: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Determines whether a directory entry represents a schema directory candidate.
|
|
28
|
+
*
|
|
29
|
+
* Returns true for real directories and for symlinks whose target is a
|
|
30
|
+
* directory. `fs.Dirent.isDirectory()` reports the raw entry type, so a symlink
|
|
31
|
+
* (even one pointing at a directory) has `isDirectory() === false`; we
|
|
32
|
+
* dereference such entries via `fs.statSync` to admit symlinked schema dirs
|
|
33
|
+
* while still rejecting symlinks-to-files and broken/dangling symlinks.
|
|
34
|
+
*
|
|
35
|
+
* @param parentDir - The directory containing the entry
|
|
36
|
+
* @param entry - The directory entry from `fs.readdirSync(..., { withFileTypes: true })`
|
|
37
|
+
*/
|
|
38
|
+
export declare function isSchemaDir(parentDir: string, entry: fs.Dirent): boolean;
|
|
25
39
|
/**
|
|
26
40
|
* Resolves a schema name to its directory path.
|
|
27
41
|
*
|
|
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { getGlobalDataDir } from '../global-config.js';
|
|
5
|
+
import { FileSystemUtils } from '../../utils/file-system.js';
|
|
5
6
|
import { parseSchema, SchemaValidationError } from './schema.js';
|
|
6
7
|
/**
|
|
7
8
|
* Error thrown when loading a schema fails.
|
|
@@ -39,6 +40,53 @@ export function getUserSchemasDir() {
|
|
|
39
40
|
export function getProjectSchemasDir(projectRoot) {
|
|
40
41
|
return path.join(projectRoot, 'openspec', 'schemas');
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Determines whether a directory entry represents a schema directory candidate.
|
|
45
|
+
*
|
|
46
|
+
* Returns true for real directories and for symlinks whose target is a
|
|
47
|
+
* directory. `fs.Dirent.isDirectory()` reports the raw entry type, so a symlink
|
|
48
|
+
* (even one pointing at a directory) has `isDirectory() === false`; we
|
|
49
|
+
* dereference such entries via `fs.statSync` to admit symlinked schema dirs
|
|
50
|
+
* while still rejecting symlinks-to-files and broken/dangling symlinks.
|
|
51
|
+
*
|
|
52
|
+
* @param parentDir - The directory containing the entry
|
|
53
|
+
* @param entry - The directory entry from `fs.readdirSync(..., { withFileTypes: true })`
|
|
54
|
+
*/
|
|
55
|
+
export function isSchemaDir(parentDir, entry) {
|
|
56
|
+
if (entry.isDirectory()) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (entry.isSymbolicLink()) {
|
|
60
|
+
try {
|
|
61
|
+
// statSync follows the link; isDirectory() reflects the target type.
|
|
62
|
+
return fs.statSync(path.join(parentDir, entry.name)).isDirectory();
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Broken symlink (dangling target) — statSync throws; treat as non-dir.
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns a schema directory only when its schema file stays within that
|
|
73
|
+
* directory's canonical trust boundary. The directory itself may be a symlink;
|
|
74
|
+
* external user schema links are an intentionally supported workflow.
|
|
75
|
+
*/
|
|
76
|
+
function getSchemaCandidateDir(schemasDir, name) {
|
|
77
|
+
const schemaDir = path.join(schemasDir, name);
|
|
78
|
+
const schemaPath = path.join(schemaDir, 'schema.yaml');
|
|
79
|
+
if (!fs.existsSync(schemaPath)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
FileSystemUtils.assertPathWithin(schemaDir, schemaPath);
|
|
84
|
+
return schemaDir;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
42
90
|
/**
|
|
43
91
|
* Resolves a schema name to its directory path.
|
|
44
92
|
*
|
|
@@ -55,24 +103,30 @@ export function getProjectSchemasDir(projectRoot) {
|
|
|
55
103
|
* @returns The path to the schema directory, or null if not found
|
|
56
104
|
*/
|
|
57
105
|
export function getSchemaDir(name, projectRoot) {
|
|
106
|
+
if (name.length === 0 ||
|
|
107
|
+
name === '.' ||
|
|
108
|
+
name === '..' ||
|
|
109
|
+
/[\\/]/u.test(name) ||
|
|
110
|
+
/^[A-Za-z]:/u.test(name) ||
|
|
111
|
+
path.posix.isAbsolute(name) ||
|
|
112
|
+
path.win32.isAbsolute(name)) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
58
115
|
// 1. Check project-local directory (if projectRoot provided)
|
|
59
116
|
if (projectRoot) {
|
|
60
|
-
const projectDir =
|
|
61
|
-
|
|
62
|
-
if (fs.existsSync(projectSchemaPath)) {
|
|
117
|
+
const projectDir = getSchemaCandidateDir(getProjectSchemasDir(projectRoot), name);
|
|
118
|
+
if (projectDir) {
|
|
63
119
|
return projectDir;
|
|
64
120
|
}
|
|
65
121
|
}
|
|
66
122
|
// 2. Check user override directory
|
|
67
|
-
const userDir =
|
|
68
|
-
|
|
69
|
-
if (fs.existsSync(userSchemaPath)) {
|
|
123
|
+
const userDir = getSchemaCandidateDir(getUserSchemasDir(), name);
|
|
124
|
+
if (userDir) {
|
|
70
125
|
return userDir;
|
|
71
126
|
}
|
|
72
127
|
// 3. Check package built-in directory
|
|
73
|
-
const packageDir =
|
|
74
|
-
|
|
75
|
-
if (fs.existsSync(packageSchemaPath)) {
|
|
128
|
+
const packageDir = getSchemaCandidateDir(getPackageSchemasDir(), name);
|
|
129
|
+
if (packageDir) {
|
|
76
130
|
return packageDir;
|
|
77
131
|
}
|
|
78
132
|
return null;
|
|
@@ -134,7 +188,7 @@ export function listSchemas(projectRoot) {
|
|
|
134
188
|
const packageDir = getPackageSchemasDir();
|
|
135
189
|
if (fs.existsSync(packageDir)) {
|
|
136
190
|
for (const entry of fs.readdirSync(packageDir, { withFileTypes: true })) {
|
|
137
|
-
if (entry
|
|
191
|
+
if (isSchemaDir(packageDir, entry)) {
|
|
138
192
|
const schemaPath = path.join(packageDir, entry.name, 'schema.yaml');
|
|
139
193
|
if (fs.existsSync(schemaPath)) {
|
|
140
194
|
schemas.add(entry.name);
|
|
@@ -146,7 +200,7 @@ export function listSchemas(projectRoot) {
|
|
|
146
200
|
const userDir = getUserSchemasDir();
|
|
147
201
|
if (fs.existsSync(userDir)) {
|
|
148
202
|
for (const entry of fs.readdirSync(userDir, { withFileTypes: true })) {
|
|
149
|
-
if (entry
|
|
203
|
+
if (isSchemaDir(userDir, entry)) {
|
|
150
204
|
const schemaPath = path.join(userDir, entry.name, 'schema.yaml');
|
|
151
205
|
if (fs.existsSync(schemaPath)) {
|
|
152
206
|
schemas.add(entry.name);
|
|
@@ -159,7 +213,7 @@ export function listSchemas(projectRoot) {
|
|
|
159
213
|
const projectDir = getProjectSchemasDir(projectRoot);
|
|
160
214
|
if (fs.existsSync(projectDir)) {
|
|
161
215
|
for (const entry of fs.readdirSync(projectDir, { withFileTypes: true })) {
|
|
162
|
-
if (entry
|
|
216
|
+
if (isSchemaDir(projectDir, entry)) {
|
|
163
217
|
const schemaPath = path.join(projectDir, entry.name, 'schema.yaml');
|
|
164
218
|
if (fs.existsSync(schemaPath)) {
|
|
165
219
|
schemas.add(entry.name);
|
|
@@ -184,7 +238,7 @@ export function listSchemasWithInfo(projectRoot) {
|
|
|
184
238
|
const projectDir = getProjectSchemasDir(projectRoot);
|
|
185
239
|
if (fs.existsSync(projectDir)) {
|
|
186
240
|
for (const entry of fs.readdirSync(projectDir, { withFileTypes: true })) {
|
|
187
|
-
if (entry
|
|
241
|
+
if (isSchemaDir(projectDir, entry)) {
|
|
188
242
|
const schemaPath = path.join(projectDir, entry.name, 'schema.yaml');
|
|
189
243
|
if (fs.existsSync(schemaPath)) {
|
|
190
244
|
try {
|
|
@@ -209,7 +263,7 @@ export function listSchemasWithInfo(projectRoot) {
|
|
|
209
263
|
const userDir = getUserSchemasDir();
|
|
210
264
|
if (fs.existsSync(userDir)) {
|
|
211
265
|
for (const entry of fs.readdirSync(userDir, { withFileTypes: true })) {
|
|
212
|
-
if (entry
|
|
266
|
+
if (isSchemaDir(userDir, entry) && !seenNames.has(entry.name)) {
|
|
213
267
|
const schemaPath = path.join(userDir, entry.name, 'schema.yaml');
|
|
214
268
|
if (fs.existsSync(schemaPath)) {
|
|
215
269
|
try {
|
|
@@ -233,7 +287,7 @@ export function listSchemasWithInfo(projectRoot) {
|
|
|
233
287
|
const packageDir = getPackageSchemasDir();
|
|
234
288
|
if (fs.existsSync(packageDir)) {
|
|
235
289
|
for (const entry of fs.readdirSync(packageDir, { withFileTypes: true })) {
|
|
236
|
-
if (entry
|
|
290
|
+
if (isSchemaDir(packageDir, entry) && !seenNames.has(entry.name)) {
|
|
237
291
|
const schemaPath = path.join(packageDir, entry.name, 'schema.yaml');
|
|
238
292
|
if (fs.existsSync(schemaPath)) {
|
|
239
293
|
try {
|
|
@@ -1,10 +1,28 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
1
2
|
import { z } from 'zod';
|
|
3
|
+
function relativePathSchema(fieldName) {
|
|
4
|
+
return z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1, { error: `${fieldName} is required` })
|
|
7
|
+
.superRefine((value, ctx) => {
|
|
8
|
+
const segments = value.split(/[\\/]+/u);
|
|
9
|
+
const isDrivePath = /^[A-Za-z]:/u.test(value);
|
|
10
|
+
const isAbsolute = path.posix.isAbsolute(value) || path.win32.isAbsolute(value) || isDrivePath;
|
|
11
|
+
const escapes = segments.includes('..');
|
|
12
|
+
if (isAbsolute || escapes || value.includes('\0')) {
|
|
13
|
+
ctx.addIssue({
|
|
14
|
+
code: 'custom',
|
|
15
|
+
message: `${fieldName} must be a relative path inside its allowed directory`,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
2
20
|
// Artifact definition schema
|
|
3
21
|
export const ArtifactSchema = z.object({
|
|
4
22
|
id: z.string().min(1, { error: 'Artifact ID is required' }),
|
|
5
|
-
generates:
|
|
23
|
+
generates: relativePathSchema('generates field'),
|
|
6
24
|
description: z.string(),
|
|
7
|
-
template:
|
|
25
|
+
template: relativePathSchema('template field'),
|
|
8
26
|
instruction: z.string().optional(),
|
|
9
27
|
requires: z.array(z.string()).default([]),
|
|
10
28
|
});
|
|
@@ -13,7 +31,7 @@ export const ApplyPhaseSchema = z.object({
|
|
|
13
31
|
// Artifact IDs that must exist before apply is available
|
|
14
32
|
requires: z.array(z.string()).min(1, { error: 'At least one required artifact' }),
|
|
15
33
|
// Path to file with checkboxes for progress (relative to change dir), or null if no tracking
|
|
16
|
-
tracks:
|
|
34
|
+
tracks: relativePathSchema('apply.tracks').nullable().optional(),
|
|
17
35
|
// Custom guidance for the apply phase
|
|
18
36
|
instruction: z.string().optional(),
|
|
19
37
|
});
|
|
@@ -10,8 +10,8 @@ import { type AIToolOption } from './config.js';
|
|
|
10
10
|
* the tools that are present.
|
|
11
11
|
*
|
|
12
12
|
* For tools with `detectionPaths`, checks those specific paths (files or
|
|
13
|
-
* directories). Otherwise checks
|
|
14
|
-
* the
|
|
13
|
+
* directories). Otherwise checks the project's `skillsDir`, or managed skill
|
|
14
|
+
* files in the user's home directory for a global skill target.
|
|
15
15
|
*/
|
|
16
16
|
export declare function getAvailableTools(projectPath: string): AIToolOption[];
|
|
17
17
|
//# sourceMappingURL=available-tools.d.ts.map
|
|
@@ -7,16 +7,25 @@
|
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import * as fs from 'fs';
|
|
9
9
|
import { AI_TOOLS } from './config.js';
|
|
10
|
+
import { reconcileSharedSkillTargets } from './shared-skill-target.js';
|
|
11
|
+
import { SKILL_NAMES } from './shared/tool-detection.js';
|
|
12
|
+
import { resolveToolSkillsDir, toolSupportsSkills } from './shared/skill-paths.js';
|
|
10
13
|
/**
|
|
11
14
|
* Scans the project path for AI tool configuration directories and returns
|
|
12
15
|
* the tools that are present.
|
|
13
16
|
*
|
|
14
17
|
* For tools with `detectionPaths`, checks those specific paths (files or
|
|
15
|
-
* directories). Otherwise checks
|
|
16
|
-
* the
|
|
18
|
+
* directories). Otherwise checks the project's `skillsDir`, or managed skill
|
|
19
|
+
* files in the user's home directory for a global skill target.
|
|
17
20
|
*/
|
|
18
21
|
export function getAvailableTools(projectPath) {
|
|
19
|
-
|
|
22
|
+
const available = AI_TOOLS.filter((tool) => {
|
|
23
|
+
if (!toolSupportsSkills(tool))
|
|
24
|
+
return false;
|
|
25
|
+
if (tool.globalSkillsDir) {
|
|
26
|
+
const skillsDir = resolveToolSkillsDir(projectPath, tool);
|
|
27
|
+
return SKILL_NAMES.some((skillName) => fs.existsSync(path.join(skillsDir, skillName, 'SKILL.md')));
|
|
28
|
+
}
|
|
20
29
|
if (!tool.skillsDir)
|
|
21
30
|
return false;
|
|
22
31
|
if (tool.detectionPaths && tool.detectionPaths.length > 0) {
|
|
@@ -39,5 +48,7 @@ export function getAvailableTools(projectPath) {
|
|
|
39
48
|
return false;
|
|
40
49
|
}
|
|
41
50
|
});
|
|
51
|
+
const activeProjectTools = new Set(reconcileSharedSkillTargets(projectPath, available.filter((tool) => tool.skillsDir)).map((tool) => tool.value));
|
|
52
|
+
return available.filter((tool) => tool.globalSkillsDir || activeProjectTools.has(tool.value));
|
|
42
53
|
}
|
|
43
54
|
//# sourceMappingURL=available-tools.js.map
|
|
@@ -14,6 +14,8 @@ export declare const ChangeMetadataSchema: z.ZodObject<{
|
|
|
14
14
|
store: z.ZodString;
|
|
15
15
|
id: z.ZodString;
|
|
16
16
|
}, z.core.$strict>>;
|
|
17
|
+
skip_specs: z.ZodOptional<z.ZodBoolean>;
|
|
18
|
+
retire_capabilities: z.ZodOptional<z.ZodBoolean>;
|
|
17
19
|
}, z.core.$strip>;
|
|
18
20
|
export type ChangeMetadata = z.infer<typeof ChangeMetadataSchema>;
|
|
19
21
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -26,5 +26,18 @@ export const ChangeMetadataSchema = z.object({
|
|
|
26
26
|
goal: z.string().min(1).optional(),
|
|
27
27
|
affected_areas: z.array(z.string().min(1)).optional(),
|
|
28
28
|
initiative: InitiativeLinkSchema.optional(),
|
|
29
|
+
// Declares that this change intentionally has no spec deltas (pure refactor,
|
|
30
|
+
// tooling, or docs work). Validation accepts zero deltas, and the artifact
|
|
31
|
+
// graph counts artifacts whose `generates` path lives under specs/ as
|
|
32
|
+
// complete - that path prefix, not the artifact id, is the contract custom
|
|
33
|
+
// schemas inherit.
|
|
34
|
+
skip_specs: z.boolean().optional(),
|
|
35
|
+
// Declares that this change may retire a capability: when its REMOVED entries
|
|
36
|
+
// take the last requirement a capability has, archive deletes that
|
|
37
|
+
// capability's main spec instead of aborting on a spec it could not write
|
|
38
|
+
// (#1302). Required because the deletion is not recoverable from the working
|
|
39
|
+
// tree - only from git - so it is the author's call, not an inference from the
|
|
40
|
+
// shape of a delta.
|
|
41
|
+
retire_capabilities: z.boolean().optional(),
|
|
29
42
|
});
|
|
30
43
|
//# sourceMappingURL=schema.js.map
|
|
@@ -18,7 +18,7 @@ export interface ActionContext {
|
|
|
18
18
|
}
|
|
19
19
|
export interface ChangeStatusPolicyArtifact {
|
|
20
20
|
id: string;
|
|
21
|
-
status: 'done' | 'ready' | 'blocked';
|
|
21
|
+
status: 'done' | 'skipped' | 'ready' | 'blocked';
|
|
22
22
|
}
|
|
23
23
|
export interface ChangeNextStepsInput {
|
|
24
24
|
changeName: string;
|
|
@@ -31,7 +31,16 @@ export interface ActionContextInput {
|
|
|
31
31
|
projectRoot: string;
|
|
32
32
|
artifactIds: string[];
|
|
33
33
|
}
|
|
34
|
+
export interface CanModifyResult {
|
|
35
|
+
canModify: boolean;
|
|
36
|
+
reason?: string;
|
|
37
|
+
}
|
|
34
38
|
export declare function summarizePlanningHome(planningHome: PlanningHome | undefined): PlanningHomeSummary | undefined;
|
|
35
39
|
export declare function buildActionContext(input: ActionContextInput): ActionContext;
|
|
36
40
|
export declare function buildNextSteps(input: ChangeNextStepsInput): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a change can be modified (pre-apply validation).
|
|
43
|
+
* Returns false if implementation has started (any tasks are checked off).
|
|
44
|
+
*/
|
|
45
|
+
export declare function canModify(changeName: string, changesDir: string): Promise<CanModifyResult>;
|
|
37
46
|
//# sourceMappingURL=change-status-policy.d.ts.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
1
3
|
export function summarizePlanningHome(planningHome) {
|
|
2
4
|
if (!planningHome) {
|
|
3
5
|
return undefined;
|
|
@@ -23,13 +25,39 @@ export function buildActionContext(input) {
|
|
|
23
25
|
export function buildNextSteps(input) {
|
|
24
26
|
const readyArtifact = input.artifactStatuses.find((artifact) => artifact.status === 'ready');
|
|
25
27
|
const steps = [];
|
|
28
|
+
const storeFlag = input.storeId ? ` --store ${input.storeId}` : '';
|
|
26
29
|
if (readyArtifact) {
|
|
27
|
-
const storeFlag = input.storeId ? ` --store ${input.storeId}` : '';
|
|
28
30
|
steps.push(`Run openspec instructions ${readyArtifact.id} --change "${input.changeName}"${storeFlag} --json before writing that artifact.`);
|
|
29
31
|
}
|
|
30
32
|
else if (input.allArtifactsComplete) {
|
|
31
|
-
steps.push(
|
|
33
|
+
steps.push(`All planning artifacts are complete. Run openspec instructions apply --change "${input.changeName}"${storeFlag} --json to inspect implementation progress.`);
|
|
32
34
|
}
|
|
33
35
|
return steps;
|
|
34
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Checks if a change can be modified (pre-apply validation).
|
|
39
|
+
* Returns false if implementation has started (any tasks are checked off).
|
|
40
|
+
*/
|
|
41
|
+
export async function canModify(changeName, changesDir) {
|
|
42
|
+
const tasksPath = join(changesDir, changeName, 'tasks.md');
|
|
43
|
+
try {
|
|
44
|
+
const tasksContent = await readFile(tasksPath, 'utf-8');
|
|
45
|
+
// Check if any tasks are checked off (marked with - [x])
|
|
46
|
+
const hasCompletedTasks = /- \[x\]/.test(tasksContent);
|
|
47
|
+
if (hasCompletedTasks) {
|
|
48
|
+
return {
|
|
49
|
+
canModify: false,
|
|
50
|
+
reason: 'Modification is blocked because implementation has started (tasks have been completed). Use /opsx:modify only before /opsx:apply begins.',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { canModify: true };
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
// If tasks.md doesn't exist, allow modification (change hasn't been fully set up yet)
|
|
57
|
+
if (error.code === 'ENOENT') {
|
|
58
|
+
return { canModify: true };
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
35
63
|
//# sourceMappingURL=change-status-policy.js.map
|
|
@@ -8,6 +8,10 @@ import type { ToolCommandAdapter } from '../types.js';
|
|
|
8
8
|
* Amazon Q adapter for command generation.
|
|
9
9
|
* File path: .amazonq/prompts/opsx-<id>.md
|
|
10
10
|
* Frontmatter: description
|
|
11
|
+
*
|
|
12
|
+
* Amazon Q surfaces these files as its prompt library rather than as slash
|
|
13
|
+
* commands: the user types `@opsx-propose`, not `/opsx-propose`.
|
|
14
|
+
* https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-prompts.html
|
|
11
15
|
*/
|
|
12
16
|
export declare const amazonQAdapter: ToolCommandAdapter;
|
|
13
17
|
//# sourceMappingURL=amazon-q.d.ts.map
|
|
@@ -4,22 +4,28 @@
|
|
|
4
4
|
* Formats commands for Amazon Q Developer following its frontmatter specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
7
8
|
/**
|
|
8
9
|
* Amazon Q adapter for command generation.
|
|
9
10
|
* File path: .amazonq/prompts/opsx-<id>.md
|
|
10
11
|
* Frontmatter: description
|
|
12
|
+
*
|
|
13
|
+
* Amazon Q surfaces these files as its prompt library rather than as slash
|
|
14
|
+
* commands: the user types `@opsx-propose`, not `/opsx-propose`.
|
|
15
|
+
* https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-prompts.html
|
|
11
16
|
*/
|
|
12
17
|
export const amazonQAdapter = {
|
|
13
18
|
toolId: 'amazon-q',
|
|
14
19
|
getFilePath(commandId) {
|
|
15
20
|
return path.join('.amazonq', 'prompts', `opsx-${commandId}.md`);
|
|
16
21
|
},
|
|
22
|
+
invocationPrefix: '@',
|
|
17
23
|
formatFile(content) {
|
|
18
|
-
return `---
|
|
19
|
-
description: ${content.description}
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
${content.body}
|
|
24
|
+
return `---
|
|
25
|
+
description: ${escapeYamlValue(content.description)}
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
${content.body}
|
|
23
29
|
`;
|
|
24
30
|
},
|
|
25
31
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Formats commands for Antigravity following its frontmatter specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
7
8
|
/**
|
|
8
9
|
* Antigravity adapter for command generation.
|
|
9
10
|
* File path: .agent/workflows/opsx-<id>.md
|
|
@@ -15,11 +16,11 @@ export const antigravityAdapter = {
|
|
|
15
16
|
return path.join('.agent', 'workflows', `opsx-${commandId}.md`);
|
|
16
17
|
},
|
|
17
18
|
formatFile(content) {
|
|
18
|
-
return `---
|
|
19
|
-
description: ${content.description}
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
${content.body}
|
|
19
|
+
return `---
|
|
20
|
+
description: ${escapeYamlValue(content.description)}
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
${content.body}
|
|
23
24
|
`;
|
|
24
25
|
},
|
|
25
26
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Formats commands for Auggie following its frontmatter specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
7
8
|
/**
|
|
8
9
|
* Auggie adapter for command generation.
|
|
9
10
|
* File path: .augment/commands/opsx-<id>.md
|
|
@@ -15,12 +16,12 @@ export const auggieAdapter = {
|
|
|
15
16
|
return path.join('.augment', 'commands', `opsx-${commandId}.md`);
|
|
16
17
|
},
|
|
17
18
|
formatFile(content) {
|
|
18
|
-
return `---
|
|
19
|
-
description: ${content.description}
|
|
20
|
-
argument-hint: command arguments
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
${content.body}
|
|
19
|
+
return `---
|
|
20
|
+
description: ${escapeYamlValue(content.description)}
|
|
21
|
+
argument-hint: command arguments
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
${content.body}
|
|
24
25
|
`;
|
|
25
26
|
},
|
|
26
27
|
};
|
|
@@ -8,7 +8,11 @@ import type { ToolCommandAdapter } from '../types.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Bob Shell adapter for command generation.
|
|
10
10
|
* File path: .bob/commands/opsx-<id>.md
|
|
11
|
-
* Frontmatter: description
|
|
11
|
+
* Frontmatter: description
|
|
12
|
+
*
|
|
13
|
+
* Bob uses the filename (minus .md) as the slash command name, so
|
|
14
|
+
* opsx-propose.md → /opsx-propose. generateCommand rewrites the body's
|
|
15
|
+
* command references to that form before this adapter formats it.
|
|
12
16
|
*/
|
|
13
17
|
export declare const bobAdapter: ToolCommandAdapter;
|
|
14
18
|
//# sourceMappingURL=bob.d.ts.map
|
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
* Commands are stored in .bob/commands/ directory.
|
|
6
6
|
*/
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import { transformToHyphenCommands } from '../../../utils/command-references.js';
|
|
9
8
|
import { escapeYamlValue } from '../yaml.js';
|
|
10
9
|
/**
|
|
11
10
|
* Bob Shell adapter for command generation.
|
|
12
11
|
* File path: .bob/commands/opsx-<id>.md
|
|
13
|
-
* Frontmatter: description
|
|
12
|
+
* Frontmatter: description
|
|
13
|
+
*
|
|
14
|
+
* Bob uses the filename (minus .md) as the slash command name, so
|
|
15
|
+
* opsx-propose.md → /opsx-propose. generateCommand rewrites the body's
|
|
16
|
+
* command references to that form before this adapter formats it.
|
|
14
17
|
*/
|
|
15
18
|
export const bobAdapter = {
|
|
16
19
|
toolId: 'bob',
|
|
@@ -18,14 +21,12 @@ export const bobAdapter = {
|
|
|
18
21
|
return path.join('.bob', 'commands', `opsx-${commandId}.md`);
|
|
19
22
|
},
|
|
20
23
|
formatFile(content) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
${transformedBody}
|
|
24
|
+
return `---
|
|
25
|
+
description: ${escapeYamlValue(content.description)}
|
|
26
|
+
argument-hint: command arguments
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
${content.body}
|
|
29
30
|
`;
|
|
30
31
|
},
|
|
31
32
|
};
|
|
@@ -7,7 +7,7 @@ import type { ToolCommandAdapter } from '../types.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* Claude Code adapter for command generation.
|
|
9
9
|
* File path: .claude/commands/opsx/<id>.md
|
|
10
|
-
* Frontmatter: name, description, category, tags
|
|
10
|
+
* Frontmatter: name, description, allowed-tools, category, tags
|
|
11
11
|
*/
|
|
12
12
|
export declare const claudeAdapter: ToolCommandAdapter;
|
|
13
13
|
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -4,18 +4,12 @@
|
|
|
4
4
|
* Formats commands for Claude Code following its frontmatter specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
-
import { escapeYamlValue } from '../yaml.js';
|
|
8
|
-
|
|
9
|
-
* Formats a tags array as a YAML array with proper escaping.
|
|
10
|
-
*/
|
|
11
|
-
function formatTagsArray(tags) {
|
|
12
|
-
const escapedTags = tags.map((tag) => escapeYamlValue(tag));
|
|
13
|
-
return `[${escapedTags.join(', ')}]`;
|
|
14
|
-
}
|
|
7
|
+
import { escapeYamlValue, formatTagsArray } from '../yaml.js';
|
|
8
|
+
import { OPENSPEC_CLI_ALLOWED_TOOLS } from '../../shared/allowed-tools.js';
|
|
15
9
|
/**
|
|
16
10
|
* Claude Code adapter for command generation.
|
|
17
11
|
* File path: .claude/commands/opsx/<id>.md
|
|
18
|
-
* Frontmatter: name, description, category, tags
|
|
12
|
+
* Frontmatter: name, description, allowed-tools, category, tags
|
|
19
13
|
*/
|
|
20
14
|
export const claudeAdapter = {
|
|
21
15
|
toolId: 'claude',
|
|
@@ -23,14 +17,15 @@ export const claudeAdapter = {
|
|
|
23
17
|
return path.join('.claude', 'commands', 'opsx', `${commandId}.md`);
|
|
24
18
|
},
|
|
25
19
|
formatFile(content) {
|
|
26
|
-
return `---
|
|
27
|
-
name: ${escapeYamlValue(content.name)}
|
|
28
|
-
description: ${escapeYamlValue(content.description)}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
return `---
|
|
21
|
+
name: ${escapeYamlValue(content.name)}
|
|
22
|
+
description: ${escapeYamlValue(content.description)}
|
|
23
|
+
allowed-tools: ${OPENSPEC_CLI_ALLOWED_TOOLS}
|
|
24
|
+
category: ${escapeYamlValue(content.category)}
|
|
25
|
+
tags: ${formatTagsArray(content.tags)}
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
${content.body}
|
|
34
29
|
`;
|
|
35
30
|
},
|
|
36
31
|
};
|
|
@@ -16,11 +16,11 @@ export const clineAdapter = {
|
|
|
16
16
|
return path.join('.clinerules', 'workflows', `opsx-${commandId}.md`);
|
|
17
17
|
},
|
|
18
18
|
formatFile(content) {
|
|
19
|
-
return `# ${content.name}
|
|
20
|
-
|
|
21
|
-
${content.description}
|
|
22
|
-
|
|
23
|
-
${content.body}
|
|
19
|
+
return `# ${content.name}
|
|
20
|
+
|
|
21
|
+
${content.description}
|
|
22
|
+
|
|
23
|
+
${content.body}
|
|
24
24
|
`;
|
|
25
25
|
},
|
|
26
26
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Formats commands for CodeBuddy following its frontmatter specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
7
8
|
/**
|
|
8
9
|
* CodeBuddy adapter for command generation.
|
|
9
10
|
* File path: .codebuddy/commands/opsx/<id>.md
|
|
@@ -15,13 +16,13 @@ export const codebuddyAdapter = {
|
|
|
15
16
|
return path.join('.codebuddy', 'commands', 'opsx', `${commandId}.md`);
|
|
16
17
|
},
|
|
17
18
|
formatFile(content) {
|
|
18
|
-
return `---
|
|
19
|
-
name: ${content.name}
|
|
20
|
-
description:
|
|
21
|
-
argument-hint: "[command arguments]"
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
${content.body}
|
|
19
|
+
return `---
|
|
20
|
+
name: ${escapeYamlValue(content.name)}
|
|
21
|
+
description: ${escapeYamlValue(content.description)}
|
|
22
|
+
argument-hint: "[command arguments]"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
${content.body}
|
|
25
26
|
`;
|
|
26
27
|
},
|
|
27
28
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Formats commands for Continue following its .prompt specification.
|
|
5
5
|
*/
|
|
6
6
|
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
7
8
|
/**
|
|
8
9
|
* Continue adapter for command generation.
|
|
9
10
|
* File path: .continue/prompts/opsx-<id>.prompt
|
|
@@ -15,13 +16,13 @@ export const continueAdapter = {
|
|
|
15
16
|
return path.join('.continue', 'prompts', `opsx-${commandId}.prompt`);
|
|
16
17
|
},
|
|
17
18
|
formatFile(content) {
|
|
18
|
-
return `---
|
|
19
|
-
name: opsx-${content.id}
|
|
20
|
-
description: ${content.description}
|
|
21
|
-
invokable: true
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
${content.body}
|
|
19
|
+
return `---
|
|
20
|
+
name: ${escapeYamlValue(`opsx-${content.id}`)}
|
|
21
|
+
description: ${escapeYamlValue(content.description)}
|
|
22
|
+
invokable: true
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
${content.body}
|
|
25
26
|
`;
|
|
26
27
|
},
|
|
27
28
|
};
|