gmc-openspec 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +207 -0
- package/bin/openspec.js +3 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +494 -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/feedback.d.ts +9 -0
- package/dist/commands/feedback.js +183 -0
- package/dist/commands/jira.d.ts +3 -0
- package/dist/commands/jira.js +249 -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 +17 -0
- package/dist/commands/workflow/index.js +12 -0
- package/dist/commands/workflow/instructions.d.ts +29 -0
- package/dist/commands/workflow/instructions.js +336 -0
- package/dist/commands/workflow/new-change.d.ts +13 -0
- package/dist/commands/workflow/new-change.js +92 -0
- package/dist/commands/workflow/schemas.d.ts +10 -0
- package/dist/commands/workflow/schemas.js +34 -0
- package/dist/commands/workflow/shared.d.ts +57 -0
- package/dist/commands/workflow/shared.js +116 -0
- package/dist/commands/workflow/status.d.ts +14 -0
- package/dist/commands/workflow/status.js +87 -0
- package/dist/commands/workflow/templates.d.ts +16 -0
- package/dist/commands/workflow/templates.js +69 -0
- package/dist/commands/workspace/open.d.ts +29 -0
- package/dist/commands/workspace/open.js +84 -0
- package/dist/commands/workspace/operations.d.ts +23 -0
- package/dist/commands/workspace/operations.js +475 -0
- package/dist/commands/workspace/selection.d.ts +6 -0
- package/dist/commands/workspace/selection.js +113 -0
- package/dist/commands/workspace/types.d.ts +88 -0
- package/dist/commands/workspace/types.js +36 -0
- package/dist/commands/workspace.d.ts +6 -0
- package/dist/commands/workspace.js +868 -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 +8 -0
- package/dist/core/artifact-graph/index.js +14 -0
- package/dist/core/artifact-graph/instruction-loader.d.ts +196 -0
- package/dist/core/artifact-graph/instruction-loader.js +317 -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 +47 -0
- package/dist/core/artifact-graph/types.js +48 -0
- package/dist/core/available-tools.d.ts +17 -0
- package/dist/core/available-tools.js +43 -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 +7 -0
- package/dist/core/completions/command-registry.js +626 -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/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 +38 -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 +5 -0
- package/dist/core/index.js +6 -0
- package/dist/core/init.d.ts +37 -0
- package/dist/core/init.js +593 -0
- package/dist/core/jira/config.d.ts +35 -0
- package/dist/core/jira/config.js +151 -0
- package/dist/core/jira/constants.d.ts +20 -0
- package/dist/core/jira/constants.js +49 -0
- package/dist/core/jira/doctor.d.ts +19 -0
- package/dist/core/jira/doctor.js +173 -0
- package/dist/core/jira/hash.d.ts +3 -0
- package/dist/core/jira/hash.js +9 -0
- package/dist/core/jira/index.d.ts +11 -0
- package/dist/core/jira/index.js +11 -0
- package/dist/core/jira/intake.d.ts +40 -0
- package/dist/core/jira/intake.js +54 -0
- package/dist/core/jira/mcp-config.d.ts +13 -0
- package/dist/core/jira/mcp-config.js +259 -0
- package/dist/core/jira/paths.d.ts +12 -0
- package/dist/core/jira/paths.js +66 -0
- package/dist/core/jira/setup.d.ts +30 -0
- package/dist/core/jira/setup.js +99 -0
- package/dist/core/jira/templates.d.ts +12 -0
- package/dist/core/jira/templates.js +204 -0
- package/dist/core/jira/validation.d.ts +17 -0
- package/dist/core/jira/validation.js +341 -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 +124 -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 +83 -0
- package/dist/core/update.js +573 -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 +33 -0
- package/dist/core/validation/validator.js +418 -0
- package/dist/core/view.d.ts +8 -0
- package/dist/core/view.js +168 -0
- package/dist/core/workspace/foundation.d.ts +87 -0
- package/dist/core/workspace/foundation.js +379 -0
- package/dist/core/workspace/index.d.ts +6 -0
- package/dist/core/workspace/index.js +6 -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 +24 -0
- package/dist/core/workspace/open-surface.js +137 -0
- package/dist/core/workspace/openers.d.ts +21 -0
- package/dist/core/workspace/openers.js +119 -0
- package/dist/core/workspace/skills.d.ts +55 -0
- package/dist/core/workspace/skills.js +334 -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 +51 -0
- package/dist/utils/change-metadata.js +147 -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 +79 -0
- package/schemas/spec-driven/schema.yaml +153 -0
- package/schemas/spec-driven/templates/design.md +19 -0
- package/schemas/spec-driven/templates/proposal.md +23 -0
- package/schemas/spec-driven/templates/spec.md +8 -0
- package/schemas/spec-driven/templates/tasks.md +9 -0
- package/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,124 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { getWorkspaceChangesDir, getWorkspaceSharedStatePath, parseWorkspaceSharedState, } from './workspace/index.js';
|
|
4
|
+
import { FileSystemUtils } from '../utils/file-system.js';
|
|
5
|
+
const REPO_DEFAULT_SCHEMA = 'spec-driven';
|
|
6
|
+
const WORKSPACE_DEFAULT_SCHEMA = 'workspace-planning';
|
|
7
|
+
function pathExistsAsDirectory(candidatePath) {
|
|
8
|
+
try {
|
|
9
|
+
return fs.statSync(candidatePath).isDirectory();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function pathExistsAsFile(candidatePath) {
|
|
16
|
+
try {
|
|
17
|
+
return fs.statSync(candidatePath).isFile();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function getSearchStartDirectory(startPath) {
|
|
24
|
+
const resolved = path.resolve(startPath);
|
|
25
|
+
try {
|
|
26
|
+
const stats = fs.statSync(resolved);
|
|
27
|
+
const searchStart = stats.isDirectory() ? resolved : path.dirname(resolved);
|
|
28
|
+
return FileSystemUtils.canonicalizeExistingPath(searchStart);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function findNearestAncestor(startPath, predicate) {
|
|
35
|
+
let currentDir = getSearchStartDirectory(startPath);
|
|
36
|
+
while (true) {
|
|
37
|
+
if (predicate(currentDir)) {
|
|
38
|
+
return FileSystemUtils.canonicalizeExistingPath(currentDir);
|
|
39
|
+
}
|
|
40
|
+
const parentDir = path.dirname(currentDir);
|
|
41
|
+
if (parentDir === currentDir) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
currentDir = parentDir;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function findWorkspacePlanningRootSync(startPath = process.cwd()) {
|
|
48
|
+
return findNearestAncestor(startPath, (dirPath) => pathExistsAsFile(getWorkspaceSharedStatePath(dirPath)));
|
|
49
|
+
}
|
|
50
|
+
export function findRepoPlanningRootSync(startPath = process.cwd()) {
|
|
51
|
+
return findNearestAncestor(startPath, (dirPath) => pathExistsAsDirectory(path.join(dirPath, 'openspec')));
|
|
52
|
+
}
|
|
53
|
+
function isSameOrDescendant(rootPath, candidatePath) {
|
|
54
|
+
const relative = path.relative(rootPath, candidatePath);
|
|
55
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
56
|
+
}
|
|
57
|
+
function countPathSegments(candidatePath) {
|
|
58
|
+
return path.resolve(candidatePath).split(path.sep).filter(Boolean).length;
|
|
59
|
+
}
|
|
60
|
+
function isWindowsLikePath(candidatePath) {
|
|
61
|
+
return /^[A-Za-z]:[\\/]/.test(candidatePath) || candidatePath.startsWith('\\\\');
|
|
62
|
+
}
|
|
63
|
+
function relativePlanningPath(fromPath, toPath) {
|
|
64
|
+
if (isWindowsLikePath(fromPath) || isWindowsLikePath(toPath)) {
|
|
65
|
+
return path.win32.relative(path.win32.normalize(fromPath), path.win32.normalize(toPath));
|
|
66
|
+
}
|
|
67
|
+
return path.posix.relative(fromPath.replace(/\\/g, '/'), toPath.replace(/\\/g, '/'));
|
|
68
|
+
}
|
|
69
|
+
function readWorkspaceSharedStateSync(workspaceRoot) {
|
|
70
|
+
try {
|
|
71
|
+
return parseWorkspaceSharedState(fs.readFileSync(getWorkspaceSharedStatePath(workspaceRoot), 'utf-8'));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function workspacePlanningHome(workspaceRoot) {
|
|
78
|
+
const sharedState = readWorkspaceSharedStateSync(workspaceRoot);
|
|
79
|
+
return {
|
|
80
|
+
kind: 'workspace',
|
|
81
|
+
root: workspaceRoot,
|
|
82
|
+
changesDir: getWorkspaceChangesDir(workspaceRoot),
|
|
83
|
+
defaultSchema: WORKSPACE_DEFAULT_SCHEMA,
|
|
84
|
+
workspace: {
|
|
85
|
+
name: sharedState?.name ?? path.basename(workspaceRoot),
|
|
86
|
+
links: Object.keys(sharedState?.links ?? {}).sort((a, b) => a.localeCompare(b)),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function repoPlanningHome(repoRoot) {
|
|
91
|
+
return {
|
|
92
|
+
kind: 'repo',
|
|
93
|
+
root: repoRoot,
|
|
94
|
+
changesDir: path.join(repoRoot, 'openspec', 'changes'),
|
|
95
|
+
defaultSchema: REPO_DEFAULT_SCHEMA,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function resolveCurrentPlanningHomeSync(options = {}) {
|
|
99
|
+
const startPath = options.startPath ?? process.cwd();
|
|
100
|
+
const searchStart = getSearchStartDirectory(startPath);
|
|
101
|
+
const workspaceRoot = findWorkspacePlanningRootSync(searchStart);
|
|
102
|
+
const repoRoot = findRepoPlanningRootSync(searchStart);
|
|
103
|
+
if (workspaceRoot && isSameOrDescendant(workspaceRoot, searchStart)) {
|
|
104
|
+
if (!repoRoot || countPathSegments(workspaceRoot) >= countPathSegments(repoRoot)) {
|
|
105
|
+
return workspacePlanningHome(workspaceRoot);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (repoRoot) {
|
|
109
|
+
return repoPlanningHome(repoRoot);
|
|
110
|
+
}
|
|
111
|
+
if (options.allowImplicitRepoRoot === false) {
|
|
112
|
+
throw new Error('No OpenSpec planning home found from the current directory.');
|
|
113
|
+
}
|
|
114
|
+
return repoPlanningHome(FileSystemUtils.canonicalizeExistingPath(searchStart));
|
|
115
|
+
}
|
|
116
|
+
export function getChangeDir(planningHome, changeName) {
|
|
117
|
+
return FileSystemUtils.joinPath(planningHome.changesDir, changeName);
|
|
118
|
+
}
|
|
119
|
+
export function formatChangeLocation(planningHome, changeName) {
|
|
120
|
+
const changeDir = getChangeDir(planningHome, changeName);
|
|
121
|
+
const relative = relativePlanningPath(planningHome.root, changeDir);
|
|
122
|
+
return relative.length > 0 ? relative : changeDir;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=planning-home.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Delivery } from './global-config.js';
|
|
2
|
+
import { ALL_WORKFLOWS } from './profiles.js';
|
|
3
|
+
type WorkflowId = (typeof ALL_WORKFLOWS)[number];
|
|
4
|
+
/**
|
|
5
|
+
* Maps workflow IDs to their skill directory names.
|
|
6
|
+
*/
|
|
7
|
+
export declare const WORKFLOW_TO_SKILL_DIR: Record<WorkflowId, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Checks whether a tool has at least one generated OpenSpec command file.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toolHasAnyConfiguredCommand(projectPath: string, toolId: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Returns tools with at least one generated command file on disk.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getCommandConfiguredTools(projectPath: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Returns tools that are configured via either skills or commands.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getConfiguredToolsForProfileSync(projectPath: string): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Detects if a single tool has profile/delivery drift against the desired state.
|
|
22
|
+
*
|
|
23
|
+
* This function covers:
|
|
24
|
+
* - required artifacts missing for selected workflows
|
|
25
|
+
* - artifacts that should not exist for the selected delivery mode
|
|
26
|
+
* - artifacts for workflows that were deselected from the current profile
|
|
27
|
+
*/
|
|
28
|
+
export declare function hasToolProfileOrDeliveryDrift(projectPath: string, toolId: string, desiredWorkflows: readonly string[], delivery: Delivery): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Returns configured tools that currently need a profile/delivery sync.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getToolsNeedingProfileSync(projectPath: string, desiredWorkflows: readonly string[], delivery: Delivery, configuredTools?: readonly string[]): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Detects whether the current project has any profile/delivery drift.
|
|
35
|
+
*/
|
|
36
|
+
export declare function hasProjectConfigDrift(projectPath: string, desiredWorkflows: readonly string[], delivery: Delivery): boolean;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=profile-sync-drift.d.ts.map
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { AI_TOOLS } from './config.js';
|
|
4
|
+
import { ALL_WORKFLOWS } from './profiles.js';
|
|
5
|
+
import { CommandAdapterRegistry } from './command-generation/index.js';
|
|
6
|
+
import { COMMAND_IDS, getConfiguredTools } from './shared/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Maps workflow IDs to their skill directory names.
|
|
9
|
+
*/
|
|
10
|
+
export const WORKFLOW_TO_SKILL_DIR = {
|
|
11
|
+
'explore': 'openspec-explore',
|
|
12
|
+
'new': 'openspec-new-change',
|
|
13
|
+
'continue': 'openspec-continue-change',
|
|
14
|
+
'apply': 'openspec-apply-change',
|
|
15
|
+
'ff': 'openspec-ff-change',
|
|
16
|
+
'sync': 'openspec-sync-specs',
|
|
17
|
+
'archive': 'openspec-archive-change',
|
|
18
|
+
'bulk-archive': 'openspec-bulk-archive-change',
|
|
19
|
+
'verify': 'openspec-verify-change',
|
|
20
|
+
'onboard': 'openspec-onboard',
|
|
21
|
+
'propose': 'openspec-propose',
|
|
22
|
+
};
|
|
23
|
+
function toKnownWorkflows(workflows) {
|
|
24
|
+
return workflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Checks whether a tool has at least one generated OpenSpec command file.
|
|
28
|
+
*/
|
|
29
|
+
export function toolHasAnyConfiguredCommand(projectPath, toolId) {
|
|
30
|
+
const adapter = CommandAdapterRegistry.get(toolId);
|
|
31
|
+
if (!adapter)
|
|
32
|
+
return false;
|
|
33
|
+
for (const commandId of COMMAND_IDS) {
|
|
34
|
+
const cmdPath = adapter.getFilePath(commandId);
|
|
35
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
36
|
+
if (fs.existsSync(fullPath)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns tools with at least one generated command file on disk.
|
|
44
|
+
*/
|
|
45
|
+
export function getCommandConfiguredTools(projectPath) {
|
|
46
|
+
return AI_TOOLS
|
|
47
|
+
.filter((tool) => {
|
|
48
|
+
if (!tool.skillsDir)
|
|
49
|
+
return false;
|
|
50
|
+
const toolDir = path.join(projectPath, tool.skillsDir);
|
|
51
|
+
try {
|
|
52
|
+
return fs.statSync(toolDir).isDirectory();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
.map((tool) => tool.value)
|
|
59
|
+
.filter((toolId) => toolHasAnyConfiguredCommand(projectPath, toolId));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns tools that are configured via either skills or commands.
|
|
63
|
+
*/
|
|
64
|
+
export function getConfiguredToolsForProfileSync(projectPath) {
|
|
65
|
+
const skillConfigured = getConfiguredTools(projectPath);
|
|
66
|
+
const commandConfigured = getCommandConfiguredTools(projectPath);
|
|
67
|
+
return [...new Set([...skillConfigured, ...commandConfigured])];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Detects if a single tool has profile/delivery drift against the desired state.
|
|
71
|
+
*
|
|
72
|
+
* This function covers:
|
|
73
|
+
* - required artifacts missing for selected workflows
|
|
74
|
+
* - artifacts that should not exist for the selected delivery mode
|
|
75
|
+
* - artifacts for workflows that were deselected from the current profile
|
|
76
|
+
*/
|
|
77
|
+
export function hasToolProfileOrDeliveryDrift(projectPath, toolId, desiredWorkflows, delivery) {
|
|
78
|
+
const tool = AI_TOOLS.find((t) => t.value === toolId);
|
|
79
|
+
if (!tool?.skillsDir)
|
|
80
|
+
return false;
|
|
81
|
+
const knownDesiredWorkflows = toKnownWorkflows(desiredWorkflows);
|
|
82
|
+
const desiredWorkflowSet = new Set(knownDesiredWorkflows);
|
|
83
|
+
const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
|
|
84
|
+
const adapter = CommandAdapterRegistry.get(toolId);
|
|
85
|
+
const shouldGenerateSkills = delivery !== 'commands';
|
|
86
|
+
const shouldGenerateCommands = delivery !== 'skills';
|
|
87
|
+
if (shouldGenerateSkills) {
|
|
88
|
+
for (const workflow of knownDesiredWorkflows) {
|
|
89
|
+
const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
|
|
90
|
+
const skillFile = path.join(skillsDir, dirName, 'SKILL.md');
|
|
91
|
+
if (!fs.existsSync(skillFile)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Deselecting workflows in a profile should trigger sync.
|
|
96
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
97
|
+
if (desiredWorkflowSet.has(workflow))
|
|
98
|
+
continue;
|
|
99
|
+
const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
|
|
100
|
+
const skillDir = path.join(skillsDir, dirName);
|
|
101
|
+
if (fs.existsSync(skillDir)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
108
|
+
const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
|
|
109
|
+
const skillDir = path.join(skillsDir, dirName);
|
|
110
|
+
if (fs.existsSync(skillDir)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (shouldGenerateCommands && adapter) {
|
|
116
|
+
for (const workflow of knownDesiredWorkflows) {
|
|
117
|
+
const cmdPath = adapter.getFilePath(workflow);
|
|
118
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
119
|
+
if (!fs.existsSync(fullPath)) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Deselecting workflows in a profile should trigger sync.
|
|
124
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
125
|
+
if (desiredWorkflowSet.has(workflow))
|
|
126
|
+
continue;
|
|
127
|
+
const cmdPath = adapter.getFilePath(workflow);
|
|
128
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
129
|
+
if (fs.existsSync(fullPath)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (!shouldGenerateCommands && adapter) {
|
|
135
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
136
|
+
const cmdPath = adapter.getFilePath(workflow);
|
|
137
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
138
|
+
if (fs.existsSync(fullPath)) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Returns configured tools that currently need a profile/delivery sync.
|
|
147
|
+
*/
|
|
148
|
+
export function getToolsNeedingProfileSync(projectPath, desiredWorkflows, delivery, configuredTools) {
|
|
149
|
+
const tools = configuredTools ? [...new Set(configuredTools)] : getConfiguredToolsForProfileSync(projectPath);
|
|
150
|
+
return tools.filter((toolId) => hasToolProfileOrDeliveryDrift(projectPath, toolId, desiredWorkflows, delivery));
|
|
151
|
+
}
|
|
152
|
+
function getInstalledWorkflowsForTool(projectPath, toolId, options) {
|
|
153
|
+
const tool = AI_TOOLS.find((t) => t.value === toolId);
|
|
154
|
+
if (!tool?.skillsDir)
|
|
155
|
+
return [];
|
|
156
|
+
const installed = new Set();
|
|
157
|
+
const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
|
|
158
|
+
if (options.includeSkills) {
|
|
159
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
160
|
+
const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
|
|
161
|
+
const skillFile = path.join(skillsDir, dirName, 'SKILL.md');
|
|
162
|
+
if (fs.existsSync(skillFile)) {
|
|
163
|
+
installed.add(workflow);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (options.includeCommands) {
|
|
168
|
+
const adapter = CommandAdapterRegistry.get(toolId);
|
|
169
|
+
if (adapter) {
|
|
170
|
+
for (const workflow of ALL_WORKFLOWS) {
|
|
171
|
+
const cmdPath = adapter.getFilePath(workflow);
|
|
172
|
+
const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
|
|
173
|
+
if (fs.existsSync(fullPath)) {
|
|
174
|
+
installed.add(workflow);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [...installed];
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Detects whether the current project has any profile/delivery drift.
|
|
183
|
+
*/
|
|
184
|
+
export function hasProjectConfigDrift(projectPath, desiredWorkflows, delivery) {
|
|
185
|
+
const configuredTools = getConfiguredToolsForProfileSync(projectPath);
|
|
186
|
+
if (getToolsNeedingProfileSync(projectPath, desiredWorkflows, delivery, configuredTools).length > 0) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
const desiredSet = new Set(toKnownWorkflows(desiredWorkflows));
|
|
190
|
+
const includeSkills = delivery !== 'commands';
|
|
191
|
+
const includeCommands = delivery !== 'skills';
|
|
192
|
+
for (const toolId of configuredTools) {
|
|
193
|
+
const installed = getInstalledWorkflowsForTool(projectPath, toolId, { includeSkills, includeCommands });
|
|
194
|
+
if (installed.some((workflow) => !desiredSet.has(workflow))) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=profile-sync-drift.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile System
|
|
3
|
+
*
|
|
4
|
+
* Defines workflow profiles that control which workflows are installed.
|
|
5
|
+
* Profiles determine WHICH workflows; delivery (in global config) determines HOW.
|
|
6
|
+
*/
|
|
7
|
+
import type { Profile } from './global-config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Core workflows included in the 'core' profile.
|
|
10
|
+
* These provide the streamlined experience for new users.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CORE_WORKFLOWS: readonly ["propose", "explore", "apply", "sync", "archive"];
|
|
13
|
+
/**
|
|
14
|
+
* All available workflows in the system.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "new", "continue", "apply", "ff", "sync", "archive", "bulk-archive", "verify", "onboard"];
|
|
17
|
+
export type WorkflowId = (typeof ALL_WORKFLOWS)[number];
|
|
18
|
+
export type CoreWorkflowId = (typeof CORE_WORKFLOWS)[number];
|
|
19
|
+
/**
|
|
20
|
+
* Resolves which workflows should be active for a given profile configuration.
|
|
21
|
+
*
|
|
22
|
+
* - 'core' profile always returns CORE_WORKFLOWS
|
|
23
|
+
* - 'custom' profile returns the provided customWorkflows, or empty array if not provided
|
|
24
|
+
*/
|
|
25
|
+
export declare function getProfileWorkflows(profile: Profile, customWorkflows?: string[]): readonly string[];
|
|
26
|
+
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile System
|
|
3
|
+
*
|
|
4
|
+
* Defines workflow profiles that control which workflows are installed.
|
|
5
|
+
* Profiles determine WHICH workflows; delivery (in global config) determines HOW.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Core workflows included in the 'core' profile.
|
|
9
|
+
* These provide the streamlined experience for new users.
|
|
10
|
+
*/
|
|
11
|
+
export const CORE_WORKFLOWS = ['propose', 'explore', 'apply', 'sync', 'archive'];
|
|
12
|
+
/**
|
|
13
|
+
* All available workflows in the system.
|
|
14
|
+
*/
|
|
15
|
+
export const ALL_WORKFLOWS = [
|
|
16
|
+
'propose',
|
|
17
|
+
'explore',
|
|
18
|
+
'new',
|
|
19
|
+
'continue',
|
|
20
|
+
'apply',
|
|
21
|
+
'ff',
|
|
22
|
+
'sync',
|
|
23
|
+
'archive',
|
|
24
|
+
'bulk-archive',
|
|
25
|
+
'verify',
|
|
26
|
+
'onboard',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Resolves which workflows should be active for a given profile configuration.
|
|
30
|
+
*
|
|
31
|
+
* - 'core' profile always returns CORE_WORKFLOWS
|
|
32
|
+
* - 'custom' profile returns the provided customWorkflows, or empty array if not provided
|
|
33
|
+
*/
|
|
34
|
+
export function getProfileWorkflows(profile, customWorkflows) {
|
|
35
|
+
if (profile === 'custom') {
|
|
36
|
+
return customWorkflows ?? [];
|
|
37
|
+
}
|
|
38
|
+
return CORE_WORKFLOWS;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for project configuration.
|
|
4
|
+
*
|
|
5
|
+
* Purpose:
|
|
6
|
+
* 1. Documentation - clearly defines the config file structure
|
|
7
|
+
* 2. Type safety - TypeScript infers ProjectConfig type from schema
|
|
8
|
+
* 3. Runtime validation - uses safeParse() for resilient field-by-field validation
|
|
9
|
+
*
|
|
10
|
+
* Why Zod over manual validation:
|
|
11
|
+
* - Helps understand OpenSpec's data interfaces at a glance
|
|
12
|
+
* - Single source of truth for type and validation
|
|
13
|
+
* - Consistent with other OpenSpec schemas
|
|
14
|
+
*/
|
|
15
|
+
export declare const ProjectConfigSchema: z.ZodObject<{
|
|
16
|
+
schema: z.ZodString;
|
|
17
|
+
context: z.ZodOptional<z.ZodString>;
|
|
18
|
+
rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type ProjectConfig = z.infer<typeof ProjectConfigSchema>;
|
|
21
|
+
/**
|
|
22
|
+
* Read and parse openspec/config.yaml from project root.
|
|
23
|
+
* Uses resilient parsing - validates each field independently using Zod safeParse.
|
|
24
|
+
* Returns null if file doesn't exist.
|
|
25
|
+
* Returns partial config if some fields are invalid (with warnings).
|
|
26
|
+
*
|
|
27
|
+
* Performance note (Jan 2025):
|
|
28
|
+
* Benchmarks showed direct file reads are fast enough without caching:
|
|
29
|
+
* - Typical config (1KB): ~0.5ms per read
|
|
30
|
+
* - Large config (50KB): ~1.6ms per read
|
|
31
|
+
* - Missing config: ~0.01ms per read
|
|
32
|
+
* Config is read 1-2 times per command (schema resolution + instruction loading),
|
|
33
|
+
* adding ~1-3ms total overhead. Caching would add complexity (mtime checks,
|
|
34
|
+
* invalidation logic) for negligible benefit. Direct reads also ensure config
|
|
35
|
+
* changes are reflected immediately without stale cache issues.
|
|
36
|
+
*
|
|
37
|
+
* @param projectRoot - The root directory of the project (where `openspec/` lives)
|
|
38
|
+
* @returns Parsed config or null if file doesn't exist
|
|
39
|
+
*/
|
|
40
|
+
export declare function readProjectConfig(projectRoot: string): ProjectConfig | null;
|
|
41
|
+
/**
|
|
42
|
+
* Validate artifact IDs in rules against a schema's artifacts.
|
|
43
|
+
* Called during instruction loading (when schema is known).
|
|
44
|
+
* Returns warnings for unknown artifact IDs.
|
|
45
|
+
*
|
|
46
|
+
* @param rules - The rules object from config
|
|
47
|
+
* @param validArtifactIds - Set of valid artifact IDs from the schema
|
|
48
|
+
* @param schemaName - Name of the schema for error messages
|
|
49
|
+
* @returns Array of warning messages for unknown artifact IDs
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateConfigRules(rules: Record<string, string[]>, validArtifactIds: Set<string>, schemaName: string): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Suggest valid schema names when user provides invalid schema.
|
|
54
|
+
* Uses fuzzy matching to find similar names.
|
|
55
|
+
*
|
|
56
|
+
* @param invalidSchemaName - The invalid schema name from config
|
|
57
|
+
* @param availableSchemas - List of available schemas with their type (built-in or project-local)
|
|
58
|
+
* @returns Error message with suggestions and available schemas
|
|
59
|
+
*/
|
|
60
|
+
export declare function suggestSchemas(invalidSchemaName: string, availableSchemas: {
|
|
61
|
+
name: string;
|
|
62
|
+
isBuiltIn: boolean;
|
|
63
|
+
}[]): string;
|
|
64
|
+
//# sourceMappingURL=project-config.d.ts.map
|