@popoverai/dotrequirements 0.24.3 → 0.26.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/README.md +7 -8
- package/dist/cli.js +8 -1
- package/dist/codebase-to-spec/dispatch.d.ts +60 -14
- package/dist/codebase-to-spec/dispatch.js +381 -15
- package/dist/codebase-to-spec/pack.d.ts +7 -0
- package/dist/codebase-to-spec/pack.js +29 -8
- package/dist/codebase-to-spec/present.d.ts +9 -0
- package/dist/codebase-to-spec/present.js +23 -2
- package/dist/codebase-to-spec/prompts/editor.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/editor.js +1 -1
- package/dist/codebase-to-spec/prompts/specifier.d.ts +1 -1
- package/dist/codebase-to-spec/prompts/specifier.js +3 -2
- package/dist/codebase-to-spec/schemas.d.ts +153 -0
- package/dist/codebase-to-spec/schemas.js +111 -0
- package/dist/codebase-to-spec/skill-install.d.ts +42 -29
- package/dist/codebase-to-spec/skill-install.js +122 -112
- package/dist/codebase-to-spec/version-check.d.ts +31 -0
- package/dist/codebase-to-spec/version-check.js +56 -0
- package/dist/commands/ai-setup.d.ts +12 -1
- package/dist/commands/ai-setup.js +65 -33
- package/dist/commands/codebase-to-spec/dispatch-context.d.ts +2 -5
- package/dist/commands/codebase-to-spec/dispatch-context.js +2 -5
- package/dist/commands/codebase-to-spec/dispatch-editor.d.ts +0 -1
- package/dist/commands/codebase-to-spec/dispatch-editor.js +0 -1
- package/dist/commands/codebase-to-spec/dispatch-planner.d.ts +0 -1
- package/dist/commands/codebase-to-spec/dispatch-planner.js +0 -1
- package/dist/commands/codebase-to-spec/dispatch-spec.d.ts +3 -6
- package/dist/commands/codebase-to-spec/dispatch-spec.js +3 -6
- package/dist/commands/codebase-to-spec/index.js +3 -2
- package/dist/commands/codebase-to-spec/pack.d.ts +9 -0
- package/dist/commands/codebase-to-spec/pack.js +23 -3
- package/dist/commands/codebase-to-spec/skill-install.js +2 -9
- package/dist/commands/init.js +6 -1
- package/dist/commands/link-resolution.d.ts +79 -0
- package/dist/commands/link-resolution.js +141 -0
- package/dist/commands/link.d.ts +14 -4
- package/dist/commands/link.js +369 -16
- package/dist/commands/pull.js +19 -2
- package/dist/commands/push.js +36 -2
- package/dist/convex.d.ts +5 -3
- package/dist/convex.js +5 -3
- package/dist/harness/cache.d.ts +0 -14
- package/dist/harness/cache.js +1 -41
- package/dist/harness/finalize.js +2 -2
- package/dist/harness/prepare.js +1 -3
- package/dist/harness/requirementsLoader.d.ts +3 -3
- package/dist/harness/requirementsLoader.js +13 -8
- package/dist/mcp/handlers/authoring.d.ts +5 -5
- package/dist/mcp/handlers/authoring.js +9 -9
- package/dist/mcp/handlers/push.d.ts +2 -2
- package/dist/mcp/handlers/push.js +36 -3
- package/dist/mcp/handlers/review.d.ts +4 -4
- package/dist/mcp/handlers/review.js +4 -4
- package/dist/mcp/handlers/search.d.ts +1 -1
- package/dist/mcp/handlers/search.js +1 -1
- package/dist/mcp/index.js +29 -0
- package/dist/push/core.d.ts +18 -0
- package/dist/push/core.js +70 -3
- package/dist/push/index.d.ts +1 -1
- package/dist/push/index.js +1 -1
- package/dist/schema/parser-core.js +5 -1
- package/dist/schema/parser.js +5 -1
- package/dist/schema/run-marker.d.ts +38 -0
- package/dist/schema/run-marker.js +138 -0
- package/dist/schema/schemas.d.ts +12 -0
- package/dist/schema/schemas.js +1 -0
- package/dist/templates/agents/cts-worker.md +3 -3
- package/dist/templates/skills/codebase-to-spec/SKILL.md +56 -158
- package/dist/templates/workflows/specify-codebase.js +374 -0
- package/dist/utils/own-package.d.ts +10 -0
- package/dist/utils/own-package.js +13 -0
- package/dist/utils/project-selector.d.ts +5 -0
- package/dist/utils/project-selector.js +4 -0
- package/package.json +3 -3
- package/dist/templates/hooks/cts-worker-persona.sh +0 -76
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skill installation logic for the codebase-to-spec skill.
|
|
3
3
|
*
|
|
4
|
-
* Ships as a bundle: SKILL.md + cts-worker agent definition +
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Ships as a bundle: SKILL.md + cts-worker agent definition + the `codebase-to-spec`
|
|
5
|
+
* dynamic-workflow script. The skill body (the conversational orchestrator)
|
|
6
|
+
* launches the workflow, which dispatches cts-worker agents; both companions
|
|
7
|
+
* must be present for the skill to run. For `project` and `global` scope, all
|
|
8
|
+
* three pieces are installed in one shot (under the project's `.claude/` or the
|
|
9
|
+
* user's `~/.claude/`). Only a `custom` target dir is skill-only, because
|
|
10
|
+
* assistants do not auto-discover agents or workflows from arbitrary paths.
|
|
11
11
|
*
|
|
12
12
|
* Host portability (CTS-SKILL-5): the install logic supports any host that
|
|
13
13
|
* follows the Agent Skills format. The default target is Claude Code's
|
|
@@ -15,25 +15,28 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Requirements covered:
|
|
17
17
|
* - CTS-SKILL-1, CTS-SKILL-5
|
|
18
|
-
* - CTSO-
|
|
18
|
+
* - CTSO-INSTALL-1 (bundles the skill, the cts-worker agent, and the workflow)
|
|
19
19
|
*/
|
|
20
20
|
export type SkillInstallScope = "project" | "global" | "custom";
|
|
21
21
|
export interface SkillInstallOptions {
|
|
22
22
|
/**
|
|
23
|
-
* Where to install
|
|
24
|
-
* -
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* - `global`:
|
|
29
|
-
* - `custom`:
|
|
23
|
+
* Where to install. `project` and `global` install the full bundle (skill +
|
|
24
|
+
* cts-worker agent + specify-codebase workflow) under the corresponding
|
|
25
|
+
* `.claude/` base, so the skill can launch the workflow; `custom` installs
|
|
26
|
+
* the skill body only.
|
|
27
|
+
* - `project` (default): `<projectRoot>/.claude/{skills,agents,workflows}/`
|
|
28
|
+
* - `global`: `<globalRoot>/.claude/{skills,agents,workflows}/`
|
|
29
|
+
* - `custom`: `<targetDir>/codebase-to-spec/SKILL.md` only — Claude Code does
|
|
30
|
+
* not auto-discover agents or workflows from an arbitrary directory
|
|
30
31
|
*/
|
|
31
32
|
scope?: SkillInstallScope;
|
|
32
33
|
/** Required when `scope === 'custom'`. The skill directory will be created here. */
|
|
33
34
|
targetDir?: string;
|
|
34
35
|
/** Project root (used when scope === 'project'). Defaults to cwd. */
|
|
35
36
|
projectRoot?: string;
|
|
36
|
-
/**
|
|
37
|
+
/** Home root for `global` scope (the parent of `.claude`). Defaults to homedir(); tests inject a temp dir. */
|
|
38
|
+
globalRoot?: string;
|
|
39
|
+
/** Overwrite existing SKILL.md / agent / workflow if present. Default false. */
|
|
37
40
|
overwrite?: boolean;
|
|
38
41
|
}
|
|
39
42
|
export interface SkillInstallResult {
|
|
@@ -43,12 +46,10 @@ export interface SkillInstallResult {
|
|
|
43
46
|
installed: boolean;
|
|
44
47
|
/** True if an existing file was replaced. */
|
|
45
48
|
overwrote: boolean;
|
|
46
|
-
/** Companion files installed alongside the skill (project scope
|
|
49
|
+
/** Companion files installed alongside the skill (project + global scope). */
|
|
47
50
|
companions?: {
|
|
48
51
|
agentPath: string;
|
|
49
|
-
|
|
50
|
-
settingsPath: string;
|
|
51
|
-
hookRegistered: boolean;
|
|
52
|
+
workflowPath: string;
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
/**
|
|
@@ -58,24 +59,36 @@ export interface SkillInstallResult {
|
|
|
58
59
|
*/
|
|
59
60
|
export declare function resolveSkillDir(options: SkillInstallOptions): string;
|
|
60
61
|
/**
|
|
61
|
-
*
|
|
62
|
+
* Resolve the CLI invocation stamped into the installed artifacts
|
|
63
|
+
* (CTSO-INSTALL-5): a version-pinned `npx` invocation of this very package,
|
|
64
|
+
* so the installed bundle runs without `dotrequirements` on PATH and always
|
|
65
|
+
* shells out to the same CLI version that performed the install.
|
|
62
66
|
*/
|
|
63
|
-
export declare function
|
|
67
|
+
export declare function resolveCliInvocation(): string;
|
|
64
68
|
/**
|
|
65
|
-
* Load the bundled
|
|
69
|
+
* Load the bundled SKILL.md template, rendering `{{DOTREQ_CLI}}` to the given
|
|
70
|
+
* CLI invocation (defaults to the version-pinned npx form).
|
|
66
71
|
*/
|
|
67
|
-
export declare function
|
|
72
|
+
export declare function loadSkillTemplate(cliInvocation?: string): string;
|
|
68
73
|
/**
|
|
69
|
-
* Load the bundled
|
|
74
|
+
* Load the bundled cts-worker agent definition template, rendering
|
|
75
|
+
* `{{DOTREQ_CLI}}` to the given CLI invocation.
|
|
70
76
|
*/
|
|
71
|
-
export declare function
|
|
77
|
+
export declare function loadAgentTemplate(cliInvocation?: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Load the bundled specify-codebase dynamic-workflow script template,
|
|
80
|
+
* rendering `{{DOTREQ_CLI}}` to the given CLI invocation.
|
|
81
|
+
*/
|
|
82
|
+
export declare function loadWorkflowTemplate(cliInvocation?: string): string;
|
|
72
83
|
/**
|
|
73
84
|
* Install (or refuse to overwrite) the codebase-to-spec skill bundle.
|
|
74
85
|
*
|
|
75
|
-
* For `project` scope: installs
|
|
76
|
-
*
|
|
86
|
+
* For `project` and `global` scope: installs the full bundle — the skill body,
|
|
87
|
+
* the cts-worker agent, and the specify-codebase workflow — under the matching
|
|
88
|
+
* `.claude/` base (the project's, or the user's `~/.claude/`).
|
|
77
89
|
*
|
|
78
|
-
* For `
|
|
90
|
+
* For `custom` scope: installs only the skill body, because Claude Code does
|
|
91
|
+
* not auto-discover agents or workflows from an arbitrary directory.
|
|
79
92
|
*/
|
|
80
93
|
export declare function installSkill(options?: SkillInstallOptions): SkillInstallResult;
|
|
81
94
|
//# sourceMappingURL=skill-install.d.ts.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skill installation logic for the codebase-to-spec skill.
|
|
3
3
|
*
|
|
4
|
-
* Ships as a bundle: SKILL.md + cts-worker agent definition +
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Ships as a bundle: SKILL.md + cts-worker agent definition + the `codebase-to-spec`
|
|
5
|
+
* dynamic-workflow script. The skill body (the conversational orchestrator)
|
|
6
|
+
* launches the workflow, which dispatches cts-worker agents; both companions
|
|
7
|
+
* must be present for the skill to run. For `project` and `global` scope, all
|
|
8
|
+
* three pieces are installed in one shot (under the project's `.claude/` or the
|
|
9
|
+
* user's `~/.claude/`). Only a `custom` target dir is skill-only, because
|
|
10
|
+
* assistants do not auto-discover agents or workflows from arbitrary paths.
|
|
11
11
|
*
|
|
12
12
|
* Host portability (CTS-SKILL-5): the install logic supports any host that
|
|
13
13
|
* follows the Agent Skills format. The default target is Claude Code's
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Requirements covered:
|
|
17
17
|
* - CTS-SKILL-1, CTS-SKILL-5
|
|
18
|
-
* - CTSO-
|
|
18
|
+
* - CTSO-INSTALL-1 (bundles the skill, the cts-worker agent, and the workflow)
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
21
22
|
import { homedir } from "node:os";
|
|
22
23
|
import { dirname, join, resolve } from "node:path";
|
|
24
|
+
import { getOwnPackage } from "../utils/own-package.js";
|
|
23
25
|
import { loadTemplate } from "../utils/templates.js";
|
|
24
26
|
/**
|
|
25
27
|
* Resolve the directory in which the skill should live, given the user's
|
|
@@ -34,7 +36,7 @@ export function resolveSkillDir(options) {
|
|
|
34
36
|
return join(root, ".claude", "skills", "codebase-to-spec");
|
|
35
37
|
}
|
|
36
38
|
case "global":
|
|
37
|
-
return join(homedir(), ".claude", "skills", "codebase-to-spec");
|
|
39
|
+
return join(options.globalRoot ?? homedir(), ".claude", "skills", "codebase-to-spec");
|
|
38
40
|
case "custom":
|
|
39
41
|
if (!options.targetDir) {
|
|
40
42
|
throw new Error('targetDir is required when scope === "custom"');
|
|
@@ -45,136 +47,144 @@ export function resolveSkillDir(options) {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
|
-
*
|
|
50
|
+
* Resolve the CLI invocation stamped into the installed artifacts
|
|
51
|
+
* (CTSO-INSTALL-5): a version-pinned `npx` invocation of this very package,
|
|
52
|
+
* so the installed bundle runs without `dotrequirements` on PATH and always
|
|
53
|
+
* shells out to the same CLI version that performed the install.
|
|
49
54
|
*/
|
|
50
|
-
export function
|
|
51
|
-
|
|
55
|
+
export function resolveCliInvocation() {
|
|
56
|
+
const pkg = getOwnPackage();
|
|
57
|
+
return `npx -y ${pkg.name}@${pkg.version}`;
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
|
-
* Load the bundled
|
|
60
|
+
* Load the bundled SKILL.md template, rendering `{{DOTREQ_CLI}}` to the given
|
|
61
|
+
* CLI invocation (defaults to the version-pinned npx form).
|
|
55
62
|
*/
|
|
56
|
-
export function
|
|
57
|
-
return loadTemplate("
|
|
63
|
+
export function loadSkillTemplate(cliInvocation = resolveCliInvocation()) {
|
|
64
|
+
return loadTemplate("skills/codebase-to-spec/SKILL.md", {
|
|
65
|
+
DOTREQ_CLI: cliInvocation,
|
|
66
|
+
});
|
|
58
67
|
}
|
|
59
68
|
/**
|
|
60
|
-
* Load the bundled
|
|
69
|
+
* Load the bundled cts-worker agent definition template, rendering
|
|
70
|
+
* `{{DOTREQ_CLI}}` to the given CLI invocation.
|
|
61
71
|
*/
|
|
62
|
-
export function
|
|
63
|
-
return loadTemplate("
|
|
72
|
+
export function loadAgentTemplate(cliInvocation = resolveCliInvocation()) {
|
|
73
|
+
return loadTemplate("agents/cts-worker.md", { DOTREQ_CLI: cliInvocation });
|
|
64
74
|
}
|
|
65
75
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
76
|
+
* Load the bundled specify-codebase dynamic-workflow script template,
|
|
77
|
+
* rendering `{{DOTREQ_CLI}}` to the given CLI invocation.
|
|
68
78
|
*/
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (onDisk === templateContent) {
|
|
74
|
-
return { installed: false, overwrote: false };
|
|
75
|
-
}
|
|
76
|
-
throw new Error(`${description} already exists at ${targetPath} and differs from the bundled template. Pass --overwrite to replace it, or delete the file first.`);
|
|
77
|
-
}
|
|
78
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
79
|
-
writeFileSync(targetPath, templateContent, "utf-8");
|
|
80
|
-
return { installed: true, overwrote: exists };
|
|
79
|
+
export function loadWorkflowTemplate(cliInvocation = resolveCliInvocation()) {
|
|
80
|
+
return loadTemplate("workflows/specify-codebase.js", {
|
|
81
|
+
DOTREQ_CLI: cliInvocation,
|
|
82
|
+
});
|
|
81
83
|
}
|
|
82
84
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
85
|
+
* Manifest written next to the installed SKILL.md, recording the content hash
|
|
86
|
+
* of every file the install wrote. On a later re-run, an on-disk file whose
|
|
87
|
+
* hash still matches its manifest entry is a *stock* install (possibly from an
|
|
88
|
+
* older CLI version) and is safe to refresh without --overwrite; a mismatch
|
|
89
|
+
* means the user hand-edited it (CTSO-INSTALL-6).
|
|
87
90
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const content = readFileSync(settingsPath, "utf-8");
|
|
99
|
-
if (content.trim()) {
|
|
100
|
-
settings = JSON.parse(content);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
// Invalid JSON — refuse to clobber. Tell caller to fix manually.
|
|
105
|
-
throw new Error(`Existing ${settingsPath} contains invalid JSON. Fix it or delete it before installing the orchestrator hook.`);
|
|
106
|
-
}
|
|
91
|
+
const MANIFEST_FILENAME = ".install-manifest.json";
|
|
92
|
+
function sha256(content) {
|
|
93
|
+
return createHash("sha256").update(content, "utf-8").digest("hex");
|
|
94
|
+
}
|
|
95
|
+
function readManifest(skillDir) {
|
|
96
|
+
const manifestPath = join(skillDir, MANIFEST_FILENAME);
|
|
97
|
+
if (!existsSync(manifestPath))
|
|
98
|
+
return undefined;
|
|
99
|
+
try {
|
|
100
|
+
return JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
107
101
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
102
|
+
catch {
|
|
103
|
+
// An unreadable manifest gives no provenance; fall back to treating
|
|
104
|
+
// differing files as hand-edited (the safe direction).
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function classifyPiece(key, description, targetPath, content, manifest) {
|
|
109
|
+
if (!existsSync(targetPath)) {
|
|
110
|
+
return { key, description, targetPath, content, state: "missing" };
|
|
111
|
+
}
|
|
112
|
+
const onDisk = readFileSync(targetPath, "utf-8");
|
|
113
|
+
if (onDisk === content) {
|
|
114
|
+
return { key, description, targetPath, content, state: "current" };
|
|
115
|
+
}
|
|
116
|
+
if (manifest?.files[key] === sha256(onDisk)) {
|
|
117
|
+
return { key, description, targetPath, content, state: "stock" };
|
|
123
118
|
}
|
|
124
|
-
|
|
125
|
-
hooks.PreToolUse = preToolUse;
|
|
126
|
-
settings.hooks = hooks;
|
|
127
|
-
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
128
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
|
129
|
-
return { settingsPath, registered: true };
|
|
119
|
+
return { key, description, targetPath, content, state: "modified" };
|
|
130
120
|
}
|
|
131
121
|
/**
|
|
132
122
|
* Install (or refuse to overwrite) the codebase-to-spec skill bundle.
|
|
133
123
|
*
|
|
134
|
-
* For `project` scope: installs
|
|
135
|
-
*
|
|
124
|
+
* For `project` and `global` scope: installs the full bundle — the skill body,
|
|
125
|
+
* the cts-worker agent, and the specify-codebase workflow — under the matching
|
|
126
|
+
* `.claude/` base (the project's, or the user's `~/.claude/`).
|
|
136
127
|
*
|
|
137
|
-
* For `
|
|
128
|
+
* For `custom` scope: installs only the skill body, because Claude Code does
|
|
129
|
+
* not auto-discover agents or workflows from an arbitrary directory.
|
|
138
130
|
*/
|
|
139
131
|
export function installSkill(options = {}) {
|
|
140
132
|
const skillDir = resolveSkillDir(options);
|
|
141
133
|
const skillPath = join(skillDir, "SKILL.md");
|
|
142
|
-
const skillTemplate = loadSkillTemplate();
|
|
143
|
-
const skillResult = installTemplateFile(skillTemplate, skillPath, options.overwrite === true, "SKILL.md");
|
|
144
|
-
// Skill body only for global/custom scopes — CC reads agents and hooks
|
|
145
|
-
// per-project, so the companions don't make sense outside a project.
|
|
146
134
|
const scope = options.scope ?? "project";
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
135
|
+
const cliInvocation = resolveCliInvocation();
|
|
136
|
+
const manifest = readManifest(skillDir);
|
|
137
|
+
// Classify every piece before writing anything, so a hand-edit refusal
|
|
138
|
+
// never leaves a partially refreshed bundle (CTSO-INSTALL-6).
|
|
139
|
+
const pieces = [
|
|
140
|
+
classifyPiece("skill", "SKILL.md", skillPath, loadSkillTemplate(cliInvocation), manifest),
|
|
141
|
+
];
|
|
142
|
+
// A custom target dir is an arbitrary location CC won't read agents or
|
|
143
|
+
// workflows from, so it gets the skill body only. Project and global both
|
|
144
|
+
// install the full bundle under their `.claude/` base.
|
|
145
|
+
let companions;
|
|
146
|
+
if (scope !== "custom") {
|
|
147
|
+
const claudeBase = scope === "global"
|
|
148
|
+
? join(options.globalRoot ?? homedir(), ".claude")
|
|
149
|
+
: join(options.projectRoot ?? process.cwd(), ".claude");
|
|
150
|
+
const agentPath = join(claudeBase, "agents", "cts-worker.md");
|
|
151
|
+
const workflowPath = join(claudeBase, "workflows", "specify-codebase.js");
|
|
152
|
+
pieces.push(classifyPiece("agent", "cts-worker agent definition", agentPath, loadAgentTemplate(cliInvocation), manifest),
|
|
153
|
+
// The workflow script is discovered by name from .claude/workflows/;
|
|
154
|
+
// no settings registration needed, unlike a hook.
|
|
155
|
+
classifyPiece("workflow", "specify-codebase workflow script", workflowPath, loadWorkflowTemplate(cliInvocation), manifest));
|
|
156
|
+
companions = { agentPath, workflowPath };
|
|
153
157
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
158
|
+
// Hand-edited files block the whole refresh (named individually) unless
|
|
159
|
+
// --overwrite; unmodified-stock files from any prior version refresh freely.
|
|
160
|
+
if (options.overwrite !== true) {
|
|
161
|
+
const modified = pieces.filter((p) => p.state === "modified");
|
|
162
|
+
if (modified.length > 0) {
|
|
163
|
+
const lines = modified.map((p) => ` ${p.description}: ${p.targetPath}`);
|
|
164
|
+
throw new Error(`Refusing to replace file(s) modified since install (or installed without manifest tracking):\n${lines.join("\n")}\nPass --overwrite to replace, or delete the file(s) first.`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const skillPiece = pieces[0];
|
|
168
|
+
for (const piece of pieces) {
|
|
169
|
+
if (piece.state === "current")
|
|
170
|
+
continue;
|
|
171
|
+
mkdirSync(dirname(piece.targetPath), { recursive: true });
|
|
172
|
+
writeFileSync(piece.targetPath, piece.content, "utf-8");
|
|
173
|
+
}
|
|
174
|
+
// Record what this install wrote (or confirmed current) so the next re-run
|
|
175
|
+
// can tell stock content from hand-edits. Also adopts manifest-less installs
|
|
176
|
+
// whose content matches the current templates.
|
|
177
|
+
const manifestOut = {
|
|
178
|
+
version: getOwnPackage().version,
|
|
179
|
+
files: Object.fromEntries(pieces.map((p) => [p.key, sha256(p.content)])),
|
|
180
|
+
};
|
|
181
|
+
mkdirSync(skillDir, { recursive: true });
|
|
182
|
+
writeFileSync(join(skillDir, MANIFEST_FILENAME), `${JSON.stringify(manifestOut, null, 2)}\n`, "utf-8");
|
|
168
183
|
return {
|
|
169
184
|
installedPath: skillPath,
|
|
170
|
-
installed:
|
|
171
|
-
overwrote:
|
|
172
|
-
companions
|
|
173
|
-
agentPath,
|
|
174
|
-
hookScriptPath,
|
|
175
|
-
settingsPath,
|
|
176
|
-
hookRegistered: registered,
|
|
177
|
-
},
|
|
185
|
+
installed: skillPiece.state !== "current",
|
|
186
|
+
overwrote: skillPiece.state === "stock" || skillPiece.state === "modified",
|
|
187
|
+
companions,
|
|
178
188
|
};
|
|
179
189
|
}
|
|
180
190
|
//# sourceMappingURL=skill-install.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-soft check for a newer published CLI version (CTS-PACK-4).
|
|
3
|
+
*
|
|
4
|
+
* The skill bundle pins the CLI version it was installed with
|
|
5
|
+
* (CTSO-INSTALL-5), so a long-lived install would otherwise run stale
|
|
6
|
+
* forever without noticing. Pack — the first deterministic step of every
|
|
7
|
+
* run — surfaces staleness so the skill can offer a refresh (CTSO-CONV-7).
|
|
8
|
+
*
|
|
9
|
+
* Any failure (offline, slow or unreachable registry, malformed response)
|
|
10
|
+
* yields `undefined`: the check must never fail or delay the pack beyond a
|
|
11
|
+
* short timeout.
|
|
12
|
+
*/
|
|
13
|
+
export interface VersionCheckResult {
|
|
14
|
+
current: string;
|
|
15
|
+
latest: string;
|
|
16
|
+
stale: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_VERSION_CHECK_TIMEOUT_MS = 2000;
|
|
19
|
+
/**
|
|
20
|
+
* True when `latest` is a strictly newer release than `current`, comparing
|
|
21
|
+
* numeric segments. Prerelease suffixes are ignored; when the numeric
|
|
22
|
+
* segments tie, the versions are treated as equal (not stale).
|
|
23
|
+
*/
|
|
24
|
+
export declare function isNewerVersion(latest: string, current: string): boolean;
|
|
25
|
+
export interface VersionCheckOptions {
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
/** Injectable for tests. */
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
}
|
|
30
|
+
export declare function checkForNewerVersion(options?: VersionCheckOptions): Promise<VersionCheckResult | undefined>;
|
|
31
|
+
//# sourceMappingURL=version-check.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-soft check for a newer published CLI version (CTS-PACK-4).
|
|
3
|
+
*
|
|
4
|
+
* The skill bundle pins the CLI version it was installed with
|
|
5
|
+
* (CTSO-INSTALL-5), so a long-lived install would otherwise run stale
|
|
6
|
+
* forever without noticing. Pack — the first deterministic step of every
|
|
7
|
+
* run — surfaces staleness so the skill can offer a refresh (CTSO-CONV-7).
|
|
8
|
+
*
|
|
9
|
+
* Any failure (offline, slow or unreachable registry, malformed response)
|
|
10
|
+
* yields `undefined`: the check must never fail or delay the pack beyond a
|
|
11
|
+
* short timeout.
|
|
12
|
+
*/
|
|
13
|
+
import { getOwnPackage } from "../utils/own-package.js";
|
|
14
|
+
export const DEFAULT_VERSION_CHECK_TIMEOUT_MS = 2_000;
|
|
15
|
+
/**
|
|
16
|
+
* True when `latest` is a strictly newer release than `current`, comparing
|
|
17
|
+
* numeric segments. Prerelease suffixes are ignored; when the numeric
|
|
18
|
+
* segments tie, the versions are treated as equal (not stale).
|
|
19
|
+
*/
|
|
20
|
+
export function isNewerVersion(latest, current) {
|
|
21
|
+
const parse = (v) => v
|
|
22
|
+
.split("-")[0]
|
|
23
|
+
.split(".")
|
|
24
|
+
.map((seg) => Number.parseInt(seg, 10) || 0);
|
|
25
|
+
const a = parse(latest);
|
|
26
|
+
const b = parse(current);
|
|
27
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
28
|
+
const diff = (a[i] ?? 0) - (b[i] ?? 0);
|
|
29
|
+
if (diff !== 0)
|
|
30
|
+
return diff > 0;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
export async function checkForNewerVersion(options = {}) {
|
|
35
|
+
try {
|
|
36
|
+
const { name, version } = getOwnPackage();
|
|
37
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
38
|
+
const response = await fetchImpl(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`, {
|
|
39
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_VERSION_CHECK_TIMEOUT_MS),
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok)
|
|
42
|
+
return undefined;
|
|
43
|
+
const body = (await response.json());
|
|
44
|
+
if (typeof body.version !== "string")
|
|
45
|
+
return undefined;
|
|
46
|
+
return {
|
|
47
|
+
current: version,
|
|
48
|
+
latest: body.version,
|
|
49
|
+
stale: isNewerVersion(body.version, version),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assistant identifiers accepted by the non-interactive --assistant flag
|
|
3
|
+
* (AISETUP-1). "other" is interactive-only: it prompts for a custom path.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SUPPORTED_ASSISTANTS: readonly ["claude-code", "claude-desktop", "cursor", "antigravity", "codex", "github-copilot"];
|
|
6
|
+
export interface AiSetupOptions {
|
|
7
|
+
assistant?: string;
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* AI setup command - configures the MCP server for AI assistants
|
|
11
|
+
*
|
|
12
|
+
* AISETUP-1: with --assistant <id>, setup runs without any interactive prompt
|
|
13
|
+
* (an AI assistant configuring itself knows which assistant it is).
|
|
3
14
|
*/
|
|
4
|
-
export declare function aiSetupCommand(): Promise<void>;
|
|
15
|
+
export declare function aiSetupCommand(options?: AiSetupOptions): Promise<void>;
|
|
5
16
|
//# sourceMappingURL=ai-setup.d.ts.map
|