specky-sdd 3.7.2 → 3.8.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/.apm/agents/{design-architect.agent.md → specky-design-architect.agent.md} +2 -2
- package/.apm/agents/{implementer.agent.md → specky-implementer.agent.md} +2 -2
- package/.apm/agents/specky-onboarding.agent.md +1 -1
- package/.apm/agents/specky-orchestrator.agent.md +10 -10
- package/.apm/agents/{quality-reviewer.agent.md → specky-quality-reviewer.agent.md} +2 -2
- package/.apm/agents/{release-engineer.agent.md → specky-release-engineer.agent.md} +4 -4
- package/.apm/agents/{requirements-engineer.agent.md → specky-requirements-engineer.agent.md} +2 -2
- package/.apm/agents/{research-analyst.agent.md → specky-research-analyst.agent.md} +2 -2
- package/.apm/agents/{sdd-clarify.agent.md → specky-sdd-clarify.agent.md} +2 -2
- package/.apm/agents/{sdd-init.agent.md → specky-sdd-init.agent.md} +3 -3
- package/.apm/agents/{spec-engineer.agent.md → specky-spec-engineer.agent.md} +2 -2
- package/.apm/agents/{task-planner.agent.md → specky-task-planner.agent.md} +2 -2
- package/.apm/agents/{test-verifier.agent.md → specky-test-verifier.agent.md} +2 -2
- package/.apm/hooks/scripts/{artifact-validator.sh → specky-artifact-validator.sh} +11 -11
- package/.apm/hooks/scripts/{auto-checkpoint.sh → specky-auto-checkpoint.sh} +1 -1
- package/.apm/hooks/scripts/{branch-validator.sh → specky-branch-validator.sh} +3 -3
- package/.apm/hooks/scripts/{cognitive-debt-alert.sh → specky-cognitive-debt-alert.sh} +1 -1
- package/.apm/hooks/scripts/{drift-monitor.sh → specky-drift-monitor.sh} +1 -1
- package/.apm/hooks/scripts/{ears-validator.sh → specky-ears-validator.sh} +1 -1
- package/.apm/hooks/scripts/{lgtm-gate.sh → specky-lgtm-gate.sh} +1 -1
- package/.apm/hooks/scripts/{metrics-dashboard.sh → specky-metrics-dashboard.sh} +2 -2
- package/.apm/hooks/scripts/{phase-gate.sh → specky-phase-gate.sh} +1 -1
- package/.apm/hooks/scripts/{pipeline-guard.sh → specky-pipeline-guard.sh} +3 -3
- package/.apm/hooks/scripts/{release-gate.sh → specky-release-gate.sh} +1 -1
- package/.apm/hooks/scripts/{security-scan.sh → specky-security-scan.sh} +2 -2
- package/.apm/hooks/scripts/{session-banner.sh → specky-session-banner.sh} +4 -4
- package/.apm/hooks/scripts/{spec-quality.sh → specky-spec-quality.sh} +1 -1
- package/.apm/hooks/scripts/{spec-sync.sh → specky-spec-sync.sh} +2 -2
- package/.apm/hooks/scripts/{task-tracer.sh → specky-task-tracer.sh} +1 -1
- package/.apm/hooks/sdd-hooks.json +51 -51
- package/.apm/instructions/copilot-instructions.instructions.md +17 -17
- package/.apm/prompts/specky-api.prompt.md +2 -2
- package/.apm/prompts/specky-brownfield.prompt.md +2 -2
- package/.apm/prompts/specky-clarify.prompt.md +1 -1
- package/.apm/prompts/specky-debug-hook.prompt.md +1 -1
- package/.apm/prompts/specky-deploy.prompt.md +1 -1
- package/.apm/prompts/specky-design.prompt.md +1 -1
- package/.apm/prompts/specky-from-meeting.prompt.md +1 -1
- package/.apm/prompts/specky-greenfield.prompt.md +2 -2
- package/.apm/prompts/specky-implement.prompt.md +1 -1
- package/.apm/prompts/specky-migration.prompt.md +3 -3
- package/.apm/prompts/specky-release.prompt.md +1 -1
- package/.apm/prompts/specky-research.prompt.md +1 -1
- package/.apm/prompts/specky-specify.prompt.md +1 -1
- package/.apm/prompts/specky-tasks.prompt.md +1 -1
- package/.apm/prompts/specky-verify.prompt.md +1 -1
- package/.apm/skills/{implementer → specky-implementer}/SKILL.md +3 -3
- package/.apm/skills/specky-onboarding/SKILL.md +29 -29
- package/.apm/skills/specky-orchestrator/SKILL.md +28 -28
- package/.apm/skills/{release-engineer → specky-release-engineer}/SKILL.md +7 -7
- package/.apm/skills/{research-analyst → specky-research-analyst}/SKILL.md +2 -2
- package/.apm/skills/{sdd-markdown-standard → specky-sdd-markdown-standard}/SKILL.md +2 -2
- package/.apm/skills/{sdd-pipeline → specky-sdd-pipeline}/SKILL.md +30 -30
- package/.apm/skills/{test-verifier → specky-test-verifier}/SKILL.md +2 -2
- package/CHANGELOG.md +76 -0
- package/README.md +24 -17
- package/apm-policy.yml +53 -0
- package/apm.lock.yaml +71 -0
- package/apm.yml +32 -2
- package/config.yml +31 -31
- package/dist/claude-hooks.json +51 -51
- package/dist/cli/commands/apm.d.ts +2 -0
- package/dist/cli/commands/apm.d.ts.map +1 -0
- package/dist/cli/commands/apm.js +139 -0
- package/dist/cli/commands/apm.js.map +1 -0
- package/dist/cli/commands/compile.d.ts +7 -0
- package/dist/cli/commands/compile.d.ts.map +1 -0
- package/dist/cli/commands/compile.js +106 -0
- package/dist/cli/commands/compile.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +35 -13
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +114 -15
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts.map +1 -1
- package/dist/cli/commands/upgrade.js +5 -2
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/index.js +30 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/apm/lock.d.ts +23 -0
- package/dist/cli/lib/apm/lock.d.ts.map +1 -0
- package/dist/cli/lib/apm/lock.js +90 -0
- package/dist/cli/lib/apm/lock.js.map +1 -0
- package/dist/cli/lib/apm/manifest.d.ts +31 -0
- package/dist/cli/lib/apm/manifest.d.ts.map +1 -0
- package/dist/cli/lib/apm/manifest.js +65 -0
- package/dist/cli/lib/apm/manifest.js.map +1 -0
- package/dist/cli/lib/apm/policy.d.ts +23 -0
- package/dist/cli/lib/apm/policy.d.ts.map +1 -0
- package/dist/cli/lib/apm/policy.js +99 -0
- package/dist/cli/lib/apm/policy.js.map +1 -0
- package/dist/cli/lib/asset-copier.d.ts +13 -0
- package/dist/cli/lib/asset-copier.d.ts.map +1 -1
- package/dist/cli/lib/asset-copier.js +46 -126
- package/dist/cli/lib/asset-copier.js.map +1 -1
- package/dist/cli/lib/gitignore-writer.d.ts.map +1 -1
- package/dist/cli/lib/gitignore-writer.js +10 -0
- package/dist/cli/lib/gitignore-writer.js.map +1 -1
- package/dist/cli/lib/harness/compilers/agent-skills.d.ts +7 -0
- package/dist/cli/lib/harness/compilers/agent-skills.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/agent-skills.js +23 -0
- package/dist/cli/lib/harness/compilers/agent-skills.js.map +1 -0
- package/dist/cli/lib/harness/compilers/claude.d.ts +10 -0
- package/dist/cli/lib/harness/compilers/claude.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/claude.js +29 -0
- package/dist/cli/lib/harness/compilers/claude.js.map +1 -0
- package/dist/cli/lib/harness/compilers/common.d.ts +14 -0
- package/dist/cli/lib/harness/compilers/common.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/common.js +43 -0
- package/dist/cli/lib/harness/compilers/common.js.map +1 -0
- package/dist/cli/lib/harness/compilers/copilot.d.ts +10 -0
- package/dist/cli/lib/harness/compilers/copilot.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/copilot.js +32 -0
- package/dist/cli/lib/harness/compilers/copilot.js.map +1 -0
- package/dist/cli/lib/harness/compilers/cursor.d.ts +8 -0
- package/dist/cli/lib/harness/compilers/cursor.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/cursor.js +27 -0
- package/dist/cli/lib/harness/compilers/cursor.js.map +1 -0
- package/dist/cli/lib/harness/compilers/opencode.d.ts +7 -0
- package/dist/cli/lib/harness/compilers/opencode.d.ts.map +1 -0
- package/dist/cli/lib/harness/compilers/opencode.js +26 -0
- package/dist/cli/lib/harness/compilers/opencode.js.map +1 -0
- package/dist/cli/lib/harness/index.d.ts +12 -0
- package/dist/cli/lib/harness/index.d.ts.map +1 -0
- package/dist/cli/lib/harness/index.js +24 -0
- package/dist/cli/lib/harness/index.js.map +1 -0
- package/dist/cli/lib/harness/tool-map.d.ts +15 -0
- package/dist/cli/lib/harness/tool-map.d.ts.map +1 -0
- package/dist/cli/lib/harness/tool-map.js +114 -0
- package/dist/cli/lib/harness/tool-map.js.map +1 -0
- package/dist/cli/lib/harness/types.d.ts +42 -0
- package/dist/cli/lib/harness/types.d.ts.map +1 -0
- package/dist/cli/lib/harness/types.js +12 -0
- package/dist/cli/lib/harness/types.js.map +1 -0
- package/dist/cli/lib/mcp-writer.d.ts +1 -0
- package/dist/cli/lib/mcp-writer.d.ts.map +1 -1
- package/dist/cli/lib/mcp-writer.js +5 -1
- package/dist/cli/lib/mcp-writer.js.map +1 -1
- package/dist/cli/lib/paths.d.ts +16 -0
- package/dist/cli/lib/paths.d.ts.map +1 -1
- package/dist/cli/lib/paths.js +18 -0
- package/dist/cli/lib/paths.js.map +1 -1
- package/dist/copilot-hooks.json +46 -46
- package/dist/services/state-machine.d.ts +4 -3
- package/dist/services/state-machine.d.ts.map +1 -1
- package/dist/services/state-machine.js +17 -9
- package/dist/services/state-machine.js.map +1 -1
- package/package.json +6 -4
- /package/.apm/skills/{sdd-pipeline → specky-sdd-pipeline}/references/ears-notation.md +0 -0
- /package/.apm/skills/{sdd-pipeline → specky-sdd-pipeline}/references/model-routing.md +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/apm.ts — `specky apm <subcommand>` governance surface.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* validate Validate apm.yml against on-disk primitives + package.json.
|
|
6
|
+
* lock Write apm.lock.yaml with a sha256 for every primitive.
|
|
7
|
+
* verify-lock Recompute hashes and diff against apm.lock.yaml.
|
|
8
|
+
* policy Enforce apm-policy.yml (MCP allowlist, hooks, tool isolation).
|
|
9
|
+
* audit Run the primitive frontmatter audit.
|
|
10
|
+
* sbom Emit a CycloneDX SBOM of the packaged primitives.
|
|
11
|
+
*/
|
|
12
|
+
import { writeFileSync } from "node:fs";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
import { resolve } from "node:path";
|
|
15
|
+
import { packageRoot } from "../lib/paths.js";
|
|
16
|
+
import { validateManifest, loadManifest } from "../lib/apm/manifest.js";
|
|
17
|
+
import { generateLock, serializeLock, lockPath, verifyLock, } from "../lib/apm/lock.js";
|
|
18
|
+
import { checkPolicy } from "../lib/apm/policy.js";
|
|
19
|
+
function print(result) {
|
|
20
|
+
for (const w of result.warnings)
|
|
21
|
+
console.warn(` ⚠️ ${w}`);
|
|
22
|
+
for (const e of result.errors)
|
|
23
|
+
console.error(` ❌ ${e}`);
|
|
24
|
+
}
|
|
25
|
+
function runValidate(pkgRoot) {
|
|
26
|
+
const result = validateManifest(pkgRoot);
|
|
27
|
+
print(result);
|
|
28
|
+
if (result.ok) {
|
|
29
|
+
const m = loadManifest(pkgRoot);
|
|
30
|
+
console.log(`✅ apm.yml valid — ${m.name}@${m.version}, targets: ${m.targets.join(", ")}`);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
return 2;
|
|
34
|
+
}
|
|
35
|
+
function runLock(pkgRoot, dryRun) {
|
|
36
|
+
const lock = generateLock(pkgRoot);
|
|
37
|
+
const count = Object.keys(lock.primitives).length;
|
|
38
|
+
if (dryRun) {
|
|
39
|
+
console.log(`ℹ️ apm lock (dry-run): ${count} primitives would be hashed`);
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
writeFileSync(lockPath(pkgRoot), serializeLock(lock), "utf8");
|
|
43
|
+
console.log(`✅ Wrote apm.lock.yaml — ${count} primitives (${lock.package.name}@${lock.package.version})`);
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
function runVerifyLock(pkgRoot) {
|
|
47
|
+
const result = verifyLock(pkgRoot);
|
|
48
|
+
if (result.error) {
|
|
49
|
+
console.error(` ❌ ${result.error}`);
|
|
50
|
+
return 2;
|
|
51
|
+
}
|
|
52
|
+
if (result.ok) {
|
|
53
|
+
console.log("✅ apm.lock.yaml matches the primitive source");
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
for (const f of result.changed)
|
|
57
|
+
console.error(` ✏️ changed: ${f}`);
|
|
58
|
+
for (const f of result.missing)
|
|
59
|
+
console.error(` ➖ missing: ${f}`);
|
|
60
|
+
for (const f of result.extra)
|
|
61
|
+
console.error(` ➕ untracked: ${f}`);
|
|
62
|
+
console.error("❌ Lock verification failed — run `specky apm lock` to update");
|
|
63
|
+
return 2;
|
|
64
|
+
}
|
|
65
|
+
function runPolicy(pkgRoot) {
|
|
66
|
+
const result = checkPolicy(pkgRoot);
|
|
67
|
+
print(result);
|
|
68
|
+
if (result.ok) {
|
|
69
|
+
console.log("✅ apm-policy.yml checks passed");
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
return 2;
|
|
73
|
+
}
|
|
74
|
+
function runAudit(pkgRoot) {
|
|
75
|
+
const res = spawnSync(process.execPath, [resolve(pkgRoot, "scripts/audit-agent-frontmatter.mjs")], { stdio: "inherit", cwd: pkgRoot });
|
|
76
|
+
return res.status ?? 1;
|
|
77
|
+
}
|
|
78
|
+
function runSbom(pkgRoot) {
|
|
79
|
+
const lock = generateLock(pkgRoot);
|
|
80
|
+
const sbom = {
|
|
81
|
+
bomFormat: "CycloneDX",
|
|
82
|
+
specVersion: "1.5",
|
|
83
|
+
version: 1,
|
|
84
|
+
metadata: {
|
|
85
|
+
timestamp: new Date().toISOString(),
|
|
86
|
+
component: {
|
|
87
|
+
type: "application",
|
|
88
|
+
name: lock.package.name,
|
|
89
|
+
version: lock.package.version,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
components: Object.entries(lock.primitives).map(([path, hash]) => ({
|
|
93
|
+
type: "file",
|
|
94
|
+
name: path,
|
|
95
|
+
hashes: [{ alg: "SHA-256", content: hash.replace(/^sha256:/, "") }],
|
|
96
|
+
})),
|
|
97
|
+
};
|
|
98
|
+
console.log(JSON.stringify(sbom, null, 2));
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
export function apmCommand(argv) {
|
|
102
|
+
const pkgRoot = packageRoot();
|
|
103
|
+
const sub = argv[0];
|
|
104
|
+
const rest = argv.slice(1);
|
|
105
|
+
const dryRun = rest.includes("--dry-run");
|
|
106
|
+
switch (sub) {
|
|
107
|
+
case "validate":
|
|
108
|
+
return runValidate(pkgRoot);
|
|
109
|
+
case "lock":
|
|
110
|
+
return runLock(pkgRoot, dryRun);
|
|
111
|
+
case "verify-lock":
|
|
112
|
+
return runVerifyLock(pkgRoot);
|
|
113
|
+
case "policy":
|
|
114
|
+
// `specky apm policy` or `specky apm policy check`
|
|
115
|
+
return runPolicy(pkgRoot);
|
|
116
|
+
case "audit":
|
|
117
|
+
return runAudit(pkgRoot);
|
|
118
|
+
case "sbom":
|
|
119
|
+
return runSbom(pkgRoot);
|
|
120
|
+
case "help":
|
|
121
|
+
case undefined:
|
|
122
|
+
console.log([
|
|
123
|
+
"specky apm <subcommand>",
|
|
124
|
+
"",
|
|
125
|
+
" validate Validate apm.yml against primitives + package.json",
|
|
126
|
+
" lock Write apm.lock.yaml (sha256 per primitive)",
|
|
127
|
+
" verify-lock Diff the primitive source against apm.lock.yaml",
|
|
128
|
+
" policy Enforce apm-policy.yml (MCP, hooks, tool isolation)",
|
|
129
|
+
" audit Run the primitive frontmatter audit",
|
|
130
|
+
" sbom Emit a CycloneDX SBOM of packaged primitives",
|
|
131
|
+
].join("\n"));
|
|
132
|
+
return 0;
|
|
133
|
+
default:
|
|
134
|
+
console.error(`Unknown apm subcommand: ${sub}`);
|
|
135
|
+
console.error("Run `specky apm help` for usage.");
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=apm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apm.js","sourceRoot":"","sources":["../../../src/cli/commands/apm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAoED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAmCtE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compile.ts — `specky compile` — compile instruction primitives into root
|
|
3
|
+
* context files for target harnesses.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { dirname, resolve } from "node:path";
|
|
7
|
+
import { getCompiler, SUPPORTED_TARGETS } from "../lib/harness/index.js";
|
|
8
|
+
import { packageRoot, sourcePaths } from "../lib/paths.js";
|
|
9
|
+
const TARGET_ALIASES = {
|
|
10
|
+
"github-copilot": "copilot",
|
|
11
|
+
vscode: "copilot",
|
|
12
|
+
"claude-code": "claude",
|
|
13
|
+
both: "both",
|
|
14
|
+
all: "all",
|
|
15
|
+
};
|
|
16
|
+
function uniqueTargets(targets) {
|
|
17
|
+
return [...new Set(targets)];
|
|
18
|
+
}
|
|
19
|
+
function parseTargetToken(token) {
|
|
20
|
+
const normalized = token.trim().toLowerCase();
|
|
21
|
+
const aliased = TARGET_ALIASES[normalized] ?? normalized;
|
|
22
|
+
if (aliased === "both")
|
|
23
|
+
return ["claude", "copilot"];
|
|
24
|
+
if (aliased === "all")
|
|
25
|
+
return SUPPORTED_TARGETS.filter((target) => target !== "agent-skills");
|
|
26
|
+
if (SUPPORTED_TARGETS.includes(aliased))
|
|
27
|
+
return [aliased];
|
|
28
|
+
throw new Error(`[specky compile] Unknown target "${token}". Supported targets: ${SUPPORTED_TARGETS.join(", ")}, both, all`);
|
|
29
|
+
}
|
|
30
|
+
function resolveTargets(target) {
|
|
31
|
+
if (!target || target === "auto")
|
|
32
|
+
return ["copilot"];
|
|
33
|
+
return uniqueTargets(target.split(",").flatMap(parseTargetToken));
|
|
34
|
+
}
|
|
35
|
+
function stripFrontmatter(content) {
|
|
36
|
+
if (!content.startsWith("---\n"))
|
|
37
|
+
return content;
|
|
38
|
+
const end = content.indexOf("\n---\n", 4);
|
|
39
|
+
if (end < 0)
|
|
40
|
+
return content;
|
|
41
|
+
return content.slice(end + "\n---\n".length).trimStart();
|
|
42
|
+
}
|
|
43
|
+
function readInstructions(instructionsDir) {
|
|
44
|
+
if (!existsSync(instructionsDir))
|
|
45
|
+
return [];
|
|
46
|
+
const contents = [];
|
|
47
|
+
for (const entry of readdirSync(instructionsDir).sort()) {
|
|
48
|
+
const path = resolve(instructionsDir, entry);
|
|
49
|
+
if (!statSync(path).isFile() || !entry.endsWith(".md"))
|
|
50
|
+
continue;
|
|
51
|
+
contents.push(readFileSync(path, "utf8"));
|
|
52
|
+
}
|
|
53
|
+
return contents;
|
|
54
|
+
}
|
|
55
|
+
function outputPathForTarget(workspace, target) {
|
|
56
|
+
switch (target) {
|
|
57
|
+
case "copilot":
|
|
58
|
+
return resolve(workspace, ".github/copilot-instructions.md");
|
|
59
|
+
case "claude":
|
|
60
|
+
return resolve(workspace, "CLAUDE.md");
|
|
61
|
+
case "cursor":
|
|
62
|
+
case "opencode":
|
|
63
|
+
return resolve(workspace, "AGENTS.md");
|
|
64
|
+
case "agent-skills":
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function writeCompiled(path, content, dryRun) {
|
|
69
|
+
if (dryRun)
|
|
70
|
+
return;
|
|
71
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
72
|
+
writeFileSync(path, content, "utf8");
|
|
73
|
+
}
|
|
74
|
+
export async function runCompile(opts) {
|
|
75
|
+
const workspace = opts.workspace ?? process.cwd();
|
|
76
|
+
const pkg = packageRoot();
|
|
77
|
+
const src = sourcePaths(pkg);
|
|
78
|
+
const targets = resolveTargets(opts.target);
|
|
79
|
+
const instructions = readInstructions(src.instructionsDir);
|
|
80
|
+
if (instructions.length === 0) {
|
|
81
|
+
console.error(`[specky compile] No instruction primitives found at ${src.instructionsDir}`);
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
const written = new Set();
|
|
85
|
+
for (const target of targets) {
|
|
86
|
+
const out = outputPathForTarget(workspace, target);
|
|
87
|
+
if (!out) {
|
|
88
|
+
console.log(`[specky compile] ${target}: no root context output`);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (written.has(out)) {
|
|
92
|
+
console.log(`[specky compile] ${target}: already covered by ${out}`);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const compiler = getCompiler(target);
|
|
96
|
+
const body = instructions
|
|
97
|
+
.map((content) => stripFrontmatter(compiler.compileInstruction(content)))
|
|
98
|
+
.join("\n\n---\n\n");
|
|
99
|
+
const compiled = `<!-- Generated by Specky CLI from .apm/instructions -->\n\n${body}`;
|
|
100
|
+
writeCompiled(out, compiled, opts.dryRun);
|
|
101
|
+
written.add(out);
|
|
102
|
+
console.log(`[specky compile] ${target}: ${opts.dryRun ? "would write" : "wrote"} ${out}`);
|
|
103
|
+
}
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8OD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAkEpE"}
|
|
@@ -92,7 +92,9 @@ function checkMcpRegistration(path, label) {
|
|
|
92
92
|
const cfg = readJsonSafe(path);
|
|
93
93
|
if (!cfg)
|
|
94
94
|
return { name: label, pass: false, detail: "file missing" };
|
|
95
|
-
const hasServer = Boolean(cfg.mcpServers?.["specky"]) ||
|
|
95
|
+
const hasServer = Boolean(cfg.mcpServers?.["specky"]) ||
|
|
96
|
+
Boolean(cfg.servers?.["specky"]) ||
|
|
97
|
+
Boolean(cfg.mcp?.["specky"]);
|
|
96
98
|
return {
|
|
97
99
|
name: label,
|
|
98
100
|
pass: hasServer,
|
|
@@ -102,38 +104,58 @@ function checkMcpRegistration(path, label) {
|
|
|
102
104
|
function loadInstallMeta(path) {
|
|
103
105
|
return readJsonSafe(path);
|
|
104
106
|
}
|
|
105
|
-
function
|
|
107
|
+
function targetsFromIde(ide) {
|
|
108
|
+
if (ide === "claude")
|
|
109
|
+
return ["claude"];
|
|
110
|
+
if (ide === "copilot")
|
|
111
|
+
return ["copilot"];
|
|
112
|
+
return ["claude", "copilot"];
|
|
113
|
+
}
|
|
114
|
+
function resolveInstalledTargets(installMeta, workspace) {
|
|
115
|
+
if (Array.isArray(installMeta?.targets) && installMeta.targets.length > 0) {
|
|
116
|
+
return {
|
|
117
|
+
targets: installMeta.targets,
|
|
118
|
+
source: "install.json",
|
|
119
|
+
detail: "recorded as targets in .specky/install.json",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
106
122
|
if (installMeta?.ide) {
|
|
107
123
|
return {
|
|
108
|
-
|
|
124
|
+
targets: targetsFromIde(installMeta.ide),
|
|
109
125
|
source: "install.json",
|
|
110
|
-
detail:
|
|
126
|
+
detail: `recorded as legacy ide=${installMeta.ide} in .specky/install.json`,
|
|
111
127
|
};
|
|
112
128
|
}
|
|
113
129
|
const detected = detectIde(workspace);
|
|
114
130
|
if (detected.signals.length > 0) {
|
|
115
131
|
return {
|
|
116
|
-
|
|
132
|
+
targets: targetsFromIde(detected.recommendation),
|
|
117
133
|
source: "workspace-signals",
|
|
118
134
|
detail: `inferred from workspace signals: ${detected.signals.join(", ")}`,
|
|
119
135
|
};
|
|
120
136
|
}
|
|
121
137
|
return {
|
|
122
|
-
|
|
138
|
+
targets: ["claude", "copilot"],
|
|
123
139
|
source: "default",
|
|
124
140
|
detail: "no install metadata or IDE signals found; validating shared defaults only",
|
|
125
141
|
};
|
|
126
142
|
}
|
|
127
|
-
function runConfigChecks(targets, workspace,
|
|
143
|
+
function runConfigChecks(targets, workspace, installTargets) {
|
|
128
144
|
const checks = [];
|
|
129
|
-
if (
|
|
145
|
+
if (installTargets.includes("claude")) {
|
|
130
146
|
checks.push(checkClaudePermissions(targets));
|
|
131
147
|
checks.push(checkMcpRegistration(targets.shared.claudeMcp, ".mcp.json"));
|
|
132
148
|
}
|
|
133
|
-
if (
|
|
149
|
+
if (installTargets.includes("copilot")) {
|
|
134
150
|
checks.push(checkMcpRegistration(targets.shared.vscodeMcp, ".vscode/mcp.json"));
|
|
135
151
|
checks.push(checkVscodeSettings(workspace));
|
|
136
152
|
}
|
|
153
|
+
if (installTargets.includes("cursor")) {
|
|
154
|
+
checks.push(checkMcpRegistration(targets.cursor.mcp, ".cursor/mcp.json"));
|
|
155
|
+
}
|
|
156
|
+
if (installTargets.includes("opencode")) {
|
|
157
|
+
checks.push(checkMcpRegistration(targets.opencode.mcp, "opencode.json"));
|
|
158
|
+
}
|
|
137
159
|
return checks;
|
|
138
160
|
}
|
|
139
161
|
function printIntegrity(report, verbose) {
|
|
@@ -178,17 +200,17 @@ export async function runDoctor(opts) {
|
|
|
178
200
|
}
|
|
179
201
|
const lock = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
180
202
|
const installMeta = loadInstallMeta(installJsonPath);
|
|
181
|
-
const
|
|
203
|
+
const resolvedTargets = resolveInstalledTargets(installMeta, workspace);
|
|
182
204
|
console.log(`[specky doctor] Lock version: ${lock.version} (generated ${lock.generated_at})`);
|
|
183
205
|
console.log(`[specky doctor] Files tracked: ${Object.keys(lock.files).length}`);
|
|
184
|
-
console.log(`[specky doctor]
|
|
206
|
+
console.log(`[specky doctor] Target scope: ${resolvedTargets.targets.join(", ")} (${resolvedTargets.detail})`);
|
|
185
207
|
// Version-drift advisory (zero network): installed assets vs running CLI.
|
|
186
208
|
if (installMeta?.version && installMeta.version !== VERSION) {
|
|
187
209
|
console.log(`[specky doctor] ⚠️ Version drift: installed assets are v${installMeta.version} but this CLI is v${VERSION} — run \`specky upgrade\` to refresh.`);
|
|
188
210
|
}
|
|
189
211
|
const integrity = verifyIntegrity(lock, targets.shared.specky);
|
|
190
212
|
printIntegrity(integrity, opts.verbose);
|
|
191
|
-
const checks = runConfigChecks(targets, workspace,
|
|
213
|
+
const checks = runConfigChecks(targets, workspace, resolvedTargets.targets);
|
|
192
214
|
printChecks(checks);
|
|
193
215
|
const integrityOk = integrity.missing.length === 0 && integrity.modified.length === 0;
|
|
194
216
|
const configOk = checks.every((c) => c.pass);
|
|
@@ -204,7 +226,7 @@ export async function runDoctor(opts) {
|
|
|
204
226
|
return init.runInit({
|
|
205
227
|
force: true,
|
|
206
228
|
dryRun: false,
|
|
207
|
-
|
|
229
|
+
target: resolvedTargets.targets.join(","),
|
|
208
230
|
workspace,
|
|
209
231
|
});
|
|
210
232
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjE,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoND,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAgEhE"}
|
|
@@ -4,13 +4,62 @@
|
|
|
4
4
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
6
|
import { VERSION } from "../../constants.js";
|
|
7
|
-
import { copyToClaude, copyToCopilot, summarizeCopy, writeInstallLock, } from "../lib/asset-copier.js";
|
|
7
|
+
import { copyToAgentSkills, copyToClaude, copyToCopilot, copyToCursor, copyToOpenCode, summarizeCopy, writeInstallLock, } from "../lib/asset-copier.js";
|
|
8
8
|
import { detectIde } from "../lib/ide-detect.js";
|
|
9
|
+
import { SUPPORTED_TARGETS } from "../lib/harness/index.js";
|
|
9
10
|
import { packageRoot, sourcePaths, targetPaths } from "../lib/paths.js";
|
|
10
11
|
import { loadClaudeHooksManifest, mergeClaudeHooks } from "../lib/settings-merger.js";
|
|
11
12
|
import { writeMcpRegistration } from "../lib/mcp-writer.js";
|
|
12
13
|
import { writeVscodeSettings } from "../lib/vscode-settings-writer.js";
|
|
13
14
|
import { writeGitignoreBlock } from "../lib/gitignore-writer.js";
|
|
15
|
+
const TARGET_ALIASES = {
|
|
16
|
+
"github-copilot": "copilot",
|
|
17
|
+
vscode: "copilot",
|
|
18
|
+
"claude-code": "claude",
|
|
19
|
+
both: "both",
|
|
20
|
+
all: "all",
|
|
21
|
+
auto: "auto",
|
|
22
|
+
};
|
|
23
|
+
function uniqueTargets(targets) {
|
|
24
|
+
return [...new Set(targets)];
|
|
25
|
+
}
|
|
26
|
+
function targetsFromLegacyIde(ide, detected) {
|
|
27
|
+
const resolved = ide === "auto" ? detected.recommendation : ide;
|
|
28
|
+
if (resolved === "both")
|
|
29
|
+
return ["claude", "copilot"];
|
|
30
|
+
return [resolved];
|
|
31
|
+
}
|
|
32
|
+
function parseTargetToken(token, detected) {
|
|
33
|
+
const normalized = token.trim().toLowerCase();
|
|
34
|
+
const aliased = TARGET_ALIASES[normalized] ?? normalized;
|
|
35
|
+
if (aliased === "auto")
|
|
36
|
+
return targetsFromLegacyIde("auto", detected);
|
|
37
|
+
if (aliased === "both")
|
|
38
|
+
return ["claude", "copilot"];
|
|
39
|
+
if (aliased === "all")
|
|
40
|
+
return SUPPORTED_TARGETS.filter((target) => target !== "agent-skills");
|
|
41
|
+
if (SUPPORTED_TARGETS.includes(aliased))
|
|
42
|
+
return [aliased];
|
|
43
|
+
throw new Error(`[specky init] Unknown target "${token}". Supported targets: ${SUPPORTED_TARGETS.join(", ")}, both, all`);
|
|
44
|
+
}
|
|
45
|
+
function resolveInstallTargets(opts, detected) {
|
|
46
|
+
if (opts.target) {
|
|
47
|
+
return uniqueTargets(opts.target
|
|
48
|
+
.split(",")
|
|
49
|
+
.flatMap((token) => parseTargetToken(token, detected)));
|
|
50
|
+
}
|
|
51
|
+
return targetsFromLegacyIde(opts.ide ?? "auto", detected);
|
|
52
|
+
}
|
|
53
|
+
function legacyIdeFromTargets(targets) {
|
|
54
|
+
const set = new Set(targets);
|
|
55
|
+
if (set.size === 1 && set.has("claude"))
|
|
56
|
+
return "claude";
|
|
57
|
+
if (set.size === 1 && set.has("copilot"))
|
|
58
|
+
return "copilot";
|
|
59
|
+
if (set.size === 2 && set.has("claude") && set.has("copilot"))
|
|
60
|
+
return "both";
|
|
61
|
+
return "auto";
|
|
62
|
+
}
|
|
14
63
|
function installClaude(ctx) {
|
|
15
64
|
console.log("[specky init] Installing to .claude/ …");
|
|
16
65
|
const r = copyToClaude(ctx.pkg, ctx.targets, ctx.copyOpts);
|
|
@@ -56,7 +105,41 @@ function installCopilot(ctx) {
|
|
|
56
105
|
console.log("");
|
|
57
106
|
return r;
|
|
58
107
|
}
|
|
59
|
-
function
|
|
108
|
+
function installCursor(ctx) {
|
|
109
|
+
console.log("[specky init] Installing to .cursor/ …");
|
|
110
|
+
const r = copyToCursor(ctx.pkg, ctx.targets, ctx.copyOpts);
|
|
111
|
+
console.log(summarizeCopy(".cursor", r));
|
|
112
|
+
const mcp = writeMcpRegistration(ctx.targets.cursor.mcp, {
|
|
113
|
+
dryRun: ctx.dryRun,
|
|
114
|
+
serverName: "specky",
|
|
115
|
+
});
|
|
116
|
+
console.log(` .cursor/mcp.json: ${mcp.action}`);
|
|
117
|
+
console.log(" hooks: skipped (Cursor hook schema support is not enabled yet)");
|
|
118
|
+
console.log("");
|
|
119
|
+
return r;
|
|
120
|
+
}
|
|
121
|
+
function installOpenCode(ctx) {
|
|
122
|
+
console.log("[specky init] Installing to .opencode/ …");
|
|
123
|
+
const r = copyToOpenCode(ctx.pkg, ctx.targets, ctx.copyOpts);
|
|
124
|
+
console.log(summarizeCopy(".opencode", r));
|
|
125
|
+
const mcp = writeMcpRegistration(ctx.targets.opencode.mcp, {
|
|
126
|
+
dryRun: ctx.dryRun,
|
|
127
|
+
serverName: "specky",
|
|
128
|
+
useOpenCodeSchema: true,
|
|
129
|
+
});
|
|
130
|
+
console.log(` opencode.json: ${mcp.action}`);
|
|
131
|
+
console.log(" hooks: skipped (OpenCode has no hooks concept)");
|
|
132
|
+
console.log("");
|
|
133
|
+
return r;
|
|
134
|
+
}
|
|
135
|
+
function installAgentSkills(ctx) {
|
|
136
|
+
console.log("[specky init] Installing to .agents/skills/ …");
|
|
137
|
+
const r = copyToAgentSkills(ctx.pkg, ctx.targets, ctx.copyOpts);
|
|
138
|
+
console.log(summarizeCopy(".agents/skills", r));
|
|
139
|
+
console.log("");
|
|
140
|
+
return r;
|
|
141
|
+
}
|
|
142
|
+
function writeSpeckyMeta(ctx, resolvedIde, resolvedTargets) {
|
|
60
143
|
if (ctx.dryRun)
|
|
61
144
|
return;
|
|
62
145
|
mkdirSync(ctx.targets.shared.specky, { recursive: true });
|
|
@@ -68,6 +151,7 @@ function writeSpeckyMeta(ctx, resolvedIde) {
|
|
|
68
151
|
const meta = {
|
|
69
152
|
version: VERSION,
|
|
70
153
|
ide: resolvedIde,
|
|
154
|
+
targets: resolvedTargets,
|
|
71
155
|
installed_at: new Date().toISOString(),
|
|
72
156
|
};
|
|
73
157
|
writeFileSync(resolve(ctx.targets.shared.specky, "install.json"), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
@@ -88,11 +172,16 @@ function ensureGitignore(ctx) {
|
|
|
88
172
|
const suffix = r.linesAdded > 0 ? `+${r.linesAdded} lines` : "no changes";
|
|
89
173
|
console.log(`[specky init] .gitignore: ${verb} (${suffix})`);
|
|
90
174
|
}
|
|
91
|
-
function printHeader(opts, workspace, resolvedIde, detected) {
|
|
92
|
-
const autoNote = opts.ide === "auto" || !opts.ide ? " (auto-detected)" : "";
|
|
175
|
+
function printHeader(opts, workspace, resolvedTargets, resolvedIde, detected) {
|
|
176
|
+
const autoNote = !opts.target && (opts.ide === "auto" || !opts.ide) ? " (auto-detected)" : "";
|
|
93
177
|
console.log(`[specky init] Version ${VERSION}`);
|
|
94
178
|
console.log(`[specky init] Workspace: ${workspace}`);
|
|
95
|
-
console.log(`[specky init]
|
|
179
|
+
console.log(`[specky init] Target(s): ${resolvedTargets.join(", ")}${autoNote}`);
|
|
180
|
+
if (opts.ide && opts.ide !== "auto") {
|
|
181
|
+
console.log(`[specky init] --ide is deprecated; prefer --target=${resolvedTargets.join(",")}`);
|
|
182
|
+
}
|
|
183
|
+
if (resolvedIde !== "auto")
|
|
184
|
+
console.log(`[specky init] Legacy IDE metadata: ${resolvedIde}`);
|
|
96
185
|
if (detected.signals.length) {
|
|
97
186
|
console.log(`[specky init] Detected signals: ${detected.signals.join(", ")}`);
|
|
98
187
|
}
|
|
@@ -119,20 +208,30 @@ export async function runInit(opts) {
|
|
|
119
208
|
dryRun: opts.dryRun,
|
|
120
209
|
};
|
|
121
210
|
const detected = detectIde(workspace);
|
|
122
|
-
const
|
|
123
|
-
|
|
211
|
+
const resolvedTargets = resolveInstallTargets(opts, detected);
|
|
212
|
+
const resolvedIde = legacyIdeFromTargets(resolvedTargets);
|
|
213
|
+
printHeader(opts, workspace, resolvedTargets, resolvedIde, detected);
|
|
124
214
|
const results = [];
|
|
125
|
-
if (
|
|
215
|
+
if (resolvedTargets.includes("claude")) {
|
|
126
216
|
results.push(installClaude(ctx));
|
|
127
217
|
}
|
|
128
|
-
if (
|
|
218
|
+
if (resolvedTargets.includes("copilot")) {
|
|
129
219
|
results.push(installCopilot(ctx));
|
|
130
220
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
221
|
+
if (resolvedTargets.includes("cursor")) {
|
|
222
|
+
results.push(installCursor(ctx));
|
|
223
|
+
}
|
|
224
|
+
if (resolvedTargets.includes("opencode")) {
|
|
225
|
+
results.push(installOpenCode(ctx));
|
|
226
|
+
}
|
|
227
|
+
if (resolvedTargets.includes("agent-skills")) {
|
|
228
|
+
results.push(installAgentSkills(ctx));
|
|
229
|
+
}
|
|
230
|
+
// rc.14+: When Copilot is installed in this workspace, strip hooks from
|
|
231
|
+
// .claude/settings.json to prevent Copilot from cross-reading Claude Code
|
|
232
|
+
// lifecycle hooks. Users that need Claude hooks should run a Claude-only
|
|
233
|
+
// install in a separate workspace.
|
|
234
|
+
if (resolvedTargets.includes("copilot") && !ctx.dryRun) {
|
|
136
235
|
const claudeSettings = ctx.targets.claude.settingsJson;
|
|
137
236
|
if (existsSync(claudeSettings)) {
|
|
138
237
|
try {
|
|
@@ -149,7 +248,7 @@ export async function runInit(opts) {
|
|
|
149
248
|
}
|
|
150
249
|
}
|
|
151
250
|
}
|
|
152
|
-
writeSpeckyMeta(ctx, resolvedIde);
|
|
251
|
+
writeSpeckyMeta(ctx, resolvedIde, resolvedTargets);
|
|
153
252
|
ensureGitignore(ctx);
|
|
154
253
|
const lockPath = writeInstallLock(ctx.targets, results, VERSION, ctx.copyOpts);
|
|
155
254
|
console.log(`[specky init] Integrity manifest: ${lockPath}`);
|