@jaybeeuu/agent-cortex 2.1.0 → 2.2.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/CHANGELOG.md +387 -0
- package/README.md +33 -13
- package/agents/README.md +22 -10
- package/agents/plan/agent.md +2 -2
- package/agents/ralph/agent.md +126 -88
- package/agents/ralph/claude/frontmatter.json +3 -3
- package/agents/ralph/claude/wake.md +46 -0
- package/agents/ralph/pi/{polling.md → wake.md} +35 -20
- package/agents/ralph-plan/agent.md +23 -11
- package/bin/agent-cortex.mjs +66 -4
- package/bin/installers/claude.mjs +182 -68
- package/bin/installers/pi.mjs +200 -24
- package/extensions/agent-guardrails/README.md +1 -1
- package/extensions/agent-guardrails/guardrails.ts +1 -1
- package/extensions/agent-guardrails/index.ts +1 -1
- package/extensions/agent-modes/discover.test.ts +2 -2
- package/hooks/claude/scripts/notify.mjs +8 -1
- package/lib/cli.mjs +91 -2
- package/package.json +27 -3
- package/scripts/check-changeset.mjs +4 -0
- package/scripts/check-no-sync.mjs +5 -1
- package/scripts/lib/compose-agent.mjs +69 -9
- package/scripts/lib/fs.mjs +10 -2
- package/scripts/lib/migrate.mjs +736 -0
- package/scripts/lib/release-gates.mjs +21 -1
- package/scripts/lib/skill-frontmatter.mjs +23 -6
- package/scripts/lib/skill-links.mjs +52 -0
- package/scripts/lib/verify-worker-tree.mjs +25 -0
- package/scripts/resolve-publish-command.mjs +4 -0
- package/skills/engineering/design-an-interface/SKILL.md +3 -3
- package/skills/engineering/grill-with-docs/SKILL.md +3 -5
- package/skills/engineering/improve-codebase-architecture/SKILL.md +5 -4
- package/skills/engineering/tdd/SKILL.md +5 -7
- package/skills/engineering/technical-direction/SKILL.md +5 -5
- package/skills/planning/classify-bead/REFERENCE.md +3 -3
- package/skills/planning/classify-bead/SKILL.md +14 -9
- package/skills/planning/classify-bead/scripts/classify-bead.mjs +5 -4
- package/skills/planning/create-task/REFERENCE.md +52 -3
- package/skills/planning/create-task/SKILL.md +70 -26
- package/skills/planning/create-task/scripts/{create-chores.ts → create-chores.mjs} +48 -23
- package/skills/planning/flesh-out-idea/REFERENCE.md +116 -0
- package/skills/planning/flesh-out-idea/SKILL.md +146 -0
- package/skills/planning/prd-to-tasks/REFERENCE.md +54 -5
- package/skills/planning/prd-to-tasks/SKILL.md +22 -16
- package/skills/planning/record-idea/FORMAT.md +66 -17
- package/skills/planning/record-idea/SKILL.md +48 -24
- package/skills/planning/request-refactor-plan/SKILL.md +4 -4
- package/skills/planning/spec-to-tickets/SKILL.md +5 -5
- package/skills/planning/write-a-prd/SKILL.md +8 -9
- package/skills/planning/write-a-ticket/SKILL.md +4 -6
- package/skills/productivity/bd-tool/SKILL.md +15 -10
- package/skills/productivity/grill-me/SKILL.md +5 -0
- package/skills/productivity/init-beads/SKILL.md +3 -3
- package/skills/productivity/migration/REFERENCE.md +227 -0
- package/skills/productivity/migration/SKILL.md +188 -0
- package/skills/productivity/validate-agent-dir/scripts/{validate-agent-dir.ts → validate-agent-dir.mjs} +49 -28
- package/skills/productivity/write-a-skill/SKILL.md +5 -5
- package/skills/review/maintain-agent-docs/SKILL.md +5 -7
- package/skills/review/refactor-skill/SKILL.md +4 -3
- package/skills/review/review-security/SKILL.md +3 -5
- package/skills/style/style-code/SKILL.md +5 -10
- package/skills/style/style-comms/SKILL.md +5 -7
- package/skills/style/style-documentation/SKILL.md +5 -6
- package/skills/style/style-tests/SKILL.md +5 -7
- package/skills/workflow/git-workflow/SKILL.md +28 -4
- package/skills/workflow/hitl-collab/SKILL.md +4 -6
- package/skills/workflow/plan/SKILL.md +41 -30
- package/skills/workflow/ralph/REFERENCE.md +182 -51
- package/skills/workflow/ralph/SKILL.md +89 -50
- package/skills/workflow/run-pipeline-stage/SKILL.md +72 -71
- package/skills/workflow/run-pipeline-stage/playbooks/code.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/document.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/fix.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/review.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/verify.md +13 -0
- package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +73 -1
- package/token-map.README.md +9 -4
- package/token-map.json +13 -6
- package/.agents/skills/style-versioning/SKILL.md +0 -172
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.github/workflows/ci.yml +0 -302
- package/.junie/guidelines.md +0 -87
- package/.junie/mcp/mcp.json +0 -10
- package/AGENTS.md +0 -153
- package/agents/ralph/claude/polling.md +0 -31
- package/agents-native/ralph.md +0 -203
- package/docs/claude-hooks.md +0 -144
- package/docs/commit-signing.md +0 -231
- package/docs/ideas/auto-model-selection.md +0 -75
- package/docs/ideas/ban-content-assertion-tests.md +0 -75
- package/docs/ideas/bead-progress-notes-for-session-resumption.md +0 -75
- package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +0 -70
- package/docs/ideas/ctx-alias-version-and-update-commands.md +0 -65
- package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +0 -67
- package/docs/ideas/dedicated-review-tests-skill.md +0 -71
- package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +0 -36
- package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +0 -99
- package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +0 -42
- package/docs/ideas/extension-manifests.md +0 -121
- package/docs/ideas/improve-pi-system-prompt.md +0 -43
- package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +0 -95
- package/docs/ideas/model-selector.md +0 -40
- package/docs/ideas/pi-task-memory.md +0 -34
- package/docs/ideas/qa-extension.md +0 -43
- package/docs/ideas/record-idea-implementation-questions.md +0 -68
- package/docs/ideas/record-ideas-as-beads.md +0 -115
- package/docs/ideas/self-flushing-session.md +0 -72
- package/docs/ideas/state-in-beads-not-md.md +0 -69
- package/docs/ideas/subagent-visibility.md +0 -72
- package/docs/ideas/task-session-context.local.md +0 -95
- package/docs/ideas/task-session-context.md +0 -89
- package/docs/ideas/test-data-creation-helpers.md +0 -92
- package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +0 -68
- package/docs/ideas/unified-ci-pipeline.md +0 -28
- package/docs/ideas/unify-the-ticket-and-task-decomposition-workflows.md +0 -71
- package/docs/ideas/worktree-housekeeping-for-closed-beads.md +0 -39
- package/docs/inspirations.md +0 -33
- package/docs/research/disable-model-invocation.md +0 -82
- package/docs/research/gas-city-research.md +0 -256
- package/docs/research/skill-design-research.md +0 -286
- package/docs/research/skill-improvements-analysis.md +0 -117
- package/docs/research/skill-patterns-research.md +0 -24
- package/docs/skills/skill-anatomy.md +0 -200
- package/docs/technical-direction/harness-config.md +0 -177
- package/docs/technical-direction/migration-execution-labels.md +0 -177
- package/docs/user-preferences.md +0 -17
- package/extensions/agent-guardrails/tsconfig.json +0 -12
- package/extensions/agent-modes/tsconfig.json +0 -12
- package/extensions/output-style/tsconfig.json +0 -12
- package/extensions/session-start/tsconfig.json +0 -12
- package/extensions/skill-stats/pnpm-lock.yaml +0 -329
- package/extensions/skill-stats/tsconfig.json +0 -12
- package/extensions/subagent/agents/planner.md +0 -37
- package/extensions/subagent/agents/reviewer.md +0 -35
- package/extensions/subagent/agents/scout.md +0 -50
- package/extensions/subagent/agents/worker.md +0 -24
- package/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/extensions/subagent/prompts/implement.md +0 -10
- package/extensions/subagent/prompts/scout-and-plan.md +0 -9
- package/extensions/subagent/tsconfig.json +0 -12
- package/pi/keybindings.json +0 -3
- package/pi/settings.json +0 -34
- package/pnpm-workspace.yaml +0 -14
- package/skills/planning/create-task/scripts/package.json +0 -14
- package/skills/planning/create-task/scripts/pnpm-lock.yaml +0 -342
- package/skills/planning/create-task/scripts/tsconfig.json +0 -12
- package/skills/planning/record-idea/scripts/new-idea.sh +0 -89
- package/skills/productivity/validate-agent-dir/scripts/package.json +0 -15
- package/skills/productivity/validate-agent-dir/scripts/pnpm-lock.yaml +0 -329
- package/skills/productivity/validate-agent-dir/scripts/pnpm-workspace.yaml +0 -2
- package/skills/productivity/validate-agent-dir/scripts/tsconfig.json +0 -19
- package/skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts +0 -317
- package/skills/workflow/run-pipeline-stage/REFERENCE.md +0 -22
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +0 -682
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.ts +0 -588
- package/skills/workflow/run-pipeline-stage/scripts/package.json +0 -15
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-lock.yaml +0 -342
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-workspace.yaml +0 -2
- package/skills/workflow/run-pipeline-stage/scripts/tsconfig.json +0 -12
- package/test/classify-bead.test.mjs +0 -277
- package/test/claude-installer.test.mjs +0 -308
- package/test/cli.test.mjs +0 -314
- package/test/create-chores.test.mjs +0 -85
- package/test/fake-bd.test.mjs +0 -72
- package/test/fs.test.mjs +0 -76
- package/test/helpers/fake-bd.mjs +0 -87
- package/test/helpers/fake-claude.mjs +0 -152
- package/test/helpers/fake-pi.mjs +0 -132
- package/test/installer.test.mjs +0 -806
- package/test/notify-hook.test.mjs +0 -63
- package/test/pending-gates.test.mjs +0 -147
- package/test/pi-installer.test.mjs +0 -785
- package/test/pi-register.test.mjs +0 -342
- package/test/pi-sweep.test.mjs +0 -619
- package/test/release-gates.test.mjs +0 -190
- package/test/skill-frontmatter.test.mjs +0 -137
- package/test/verify-worker-tree.test.mjs +0 -120
package/lib/cli.mjs
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of parsing the CLI argv. Every branch returns `command`; the rest are
|
|
3
|
+
* populated only for the commands that accept them.
|
|
4
|
+
* @typedef {object} ParsedArgs
|
|
5
|
+
* @property {"help" | "version" | "install" | "migrate" | "unknown"} command
|
|
6
|
+
* @property {string | null} [harness]
|
|
7
|
+
* @property {string} [name]
|
|
8
|
+
* @property {string} [optionError]
|
|
9
|
+
* @property {boolean} [dryRun]
|
|
10
|
+
* @property {string} [output]
|
|
11
|
+
* @property {string} [pluginRoot]
|
|
12
|
+
* @property {boolean} [requireRegister]
|
|
13
|
+
* @property {boolean} [apply]
|
|
14
|
+
* @property {string} [dir]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** @typedef {{ key: string, boolean?: boolean }} OptionSpec */
|
|
18
|
+
|
|
1
19
|
const SUPPORTED_HARNESSES = ["claude", "pi"];
|
|
2
20
|
|
|
3
21
|
// Options accepted by `install <harness>`. `--output`/`--dry-run` are shared by
|
|
4
22
|
// the claude and pi installers; `--plugin-root` is pi-specific. Unknown or
|
|
5
23
|
// malformed options surface as `optionError` on the parsed result; the CLI
|
|
6
24
|
// prints them and exits 1.
|
|
25
|
+
/** @type {Record<string, OptionSpec>} */
|
|
7
26
|
const INSTALL_OPTIONS = {
|
|
8
27
|
"--dry-run": { key: "dryRun", boolean: true },
|
|
9
28
|
"--output": { key: "output" },
|
|
@@ -11,11 +30,22 @@ const INSTALL_OPTIONS = {
|
|
|
11
30
|
"--require-register": { key: "requireRegister", boolean: true },
|
|
12
31
|
};
|
|
13
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Parse the CLI argv.
|
|
35
|
+
* @param {string[]} argv
|
|
36
|
+
* @returns {ParsedArgs}
|
|
37
|
+
*/
|
|
14
38
|
export function parseArgs(argv) {
|
|
15
39
|
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
16
40
|
return { command: "help" };
|
|
17
41
|
}
|
|
18
42
|
|
|
43
|
+
// Like `--help`, the version flags are only recognised as the first argument,
|
|
44
|
+
// so they never shadow a command's own options.
|
|
45
|
+
if (argv[0] === "--version" || argv[0] === "-V") {
|
|
46
|
+
return { command: "version" };
|
|
47
|
+
}
|
|
48
|
+
|
|
19
49
|
const [command, ...rest] = argv;
|
|
20
50
|
|
|
21
51
|
if (command === "install") {
|
|
@@ -26,6 +56,7 @@ export function parseArgs(argv) {
|
|
|
26
56
|
i = 1;
|
|
27
57
|
}
|
|
28
58
|
|
|
59
|
+
/** @type {Record<string, string | true>} */
|
|
29
60
|
const options = {};
|
|
30
61
|
for (; i < rest.length; i++) {
|
|
31
62
|
const arg = rest[i];
|
|
@@ -57,9 +88,54 @@ export function parseArgs(argv) {
|
|
|
57
88
|
return { command: "install", harness, ...options };
|
|
58
89
|
}
|
|
59
90
|
|
|
91
|
+
if (command === "migrate") {
|
|
92
|
+
// Dry run is the default, so `--apply` is the only state-changing flag;
|
|
93
|
+
// `--dry-run` stays accepted for scripts that pass it explicitly. `--dir`
|
|
94
|
+
// points the ideas step at a workspace that keeps its idea files elsewhere.
|
|
95
|
+
let sawApply = false;
|
|
96
|
+
let sawDryRun = false;
|
|
97
|
+
/** @type {string | undefined} */
|
|
98
|
+
let dir;
|
|
99
|
+
for (let i = 0; i < rest.length; i++) {
|
|
100
|
+
const arg = rest[i];
|
|
101
|
+
if (arg === "--help" || arg === "-h") return { command: "help" };
|
|
102
|
+
if (arg === "--apply") {
|
|
103
|
+
sawApply = true;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (arg === "--dry-run") {
|
|
107
|
+
sawDryRun = true;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
// Support both `--dir=<path>` and `--dir <path>`, like install's `--output`.
|
|
111
|
+
const inlineDir = arg.startsWith("--dir=") ? arg.slice("--dir=".length) : null;
|
|
112
|
+
if (inlineDir !== null && inlineDir !== "") {
|
|
113
|
+
dir = inlineDir;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (arg === "--dir" || inlineDir !== null) {
|
|
117
|
+
const value = rest[i + 1];
|
|
118
|
+
if (inlineDir !== null || value == null || value.startsWith("--")) {
|
|
119
|
+
return { command: "migrate", optionError: `Missing value for "--dir". Run "agent-cortex --help" for usage.` };
|
|
120
|
+
}
|
|
121
|
+
dir = value;
|
|
122
|
+
i += 1;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
return { command: "migrate", optionError: `Unknown option "${arg}". Run "agent-cortex --help" for usage.` };
|
|
126
|
+
}
|
|
127
|
+
if (sawApply && sawDryRun) {
|
|
128
|
+
return { command: "migrate", optionError: '"--apply" and "--dry-run" are mutually exclusive.' };
|
|
129
|
+
}
|
|
130
|
+
return dir === undefined ? { command: "migrate", apply: sawApply } : { command: "migrate", apply: sawApply, dir };
|
|
131
|
+
}
|
|
132
|
+
|
|
60
133
|
return { command: "unknown", name: command };
|
|
61
134
|
}
|
|
62
135
|
|
|
136
|
+
/**
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
63
139
|
export function buildHelpText() {
|
|
64
140
|
return `Usage: agent-cortex <command> [options]
|
|
65
141
|
|
|
@@ -125,11 +201,24 @@ Commands:
|
|
|
125
201
|
cannot register the staged package
|
|
126
202
|
(missing from PATH); default warns and
|
|
127
203
|
prints the manual commands
|
|
128
|
-
|
|
204
|
+
migrate Migrate the current beads workspace to the latest
|
|
205
|
+
agent-cortex migration version, applying versioned steps
|
|
206
|
+
in order (repo-agnostic — works in any beads workspace)
|
|
207
|
+
Options:
|
|
208
|
+
(no option) Dry run — print the pending plan, write nothing
|
|
209
|
+
--apply Apply every pending step, verifying each
|
|
210
|
+
--dir <path> Read idea files from <path> instead of
|
|
211
|
+
docs/ideas (step v2's source)
|
|
212
|
+
--help, -h Show this help text
|
|
213
|
+
--version, -V Print the package version`;
|
|
129
214
|
}
|
|
130
215
|
|
|
216
|
+
/**
|
|
217
|
+
* @param {string | null | undefined} harness
|
|
218
|
+
* @returns {{ ok: true } | { ok: false, error: string }}
|
|
219
|
+
*/
|
|
131
220
|
export function validateHarness(harness) {
|
|
132
|
-
if (harness === null) {
|
|
221
|
+
if (harness === null || harness === undefined) {
|
|
133
222
|
return {
|
|
134
223
|
ok: false,
|
|
135
224
|
error: `Missing harness argument. Supported harnesses: ${SUPPORTED_HARNESSES.join(", ")}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaybeeuu/agent-cortex",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Personal PI package with custom agents, skills, and extensions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -13,12 +13,35 @@
|
|
|
13
13
|
"bin": {
|
|
14
14
|
"agent-cortex": "./bin/agent-cortex.mjs"
|
|
15
15
|
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/",
|
|
18
|
+
"lib/",
|
|
19
|
+
"scripts/",
|
|
20
|
+
"skills/",
|
|
21
|
+
"agents/",
|
|
22
|
+
"extensions/*.ts",
|
|
23
|
+
"extensions/lib/",
|
|
24
|
+
"extensions/*/*.ts",
|
|
25
|
+
"extensions/*/*.md",
|
|
26
|
+
"extensions/*/package.json",
|
|
27
|
+
"extensions/*/agents/",
|
|
28
|
+
"extensions/*/prompts/",
|
|
29
|
+
"hooks/",
|
|
30
|
+
"claude/",
|
|
31
|
+
"claude-extras/",
|
|
32
|
+
"token-map.json",
|
|
33
|
+
"token-map.README.md",
|
|
34
|
+
"README.md",
|
|
35
|
+
"CHANGELOG.md"
|
|
36
|
+
],
|
|
16
37
|
"publishConfig": {
|
|
17
38
|
"access": "public"
|
|
18
39
|
},
|
|
19
40
|
"devDependencies": {
|
|
20
41
|
"@changesets/cli": "^2.31.1",
|
|
42
|
+
"@types/node": "^22.20.1",
|
|
21
43
|
"tsx": "^4.0.0",
|
|
44
|
+
"typescript": "^5.9.3",
|
|
22
45
|
"yaml": "^2.0.0"
|
|
23
46
|
},
|
|
24
47
|
"pi": {
|
|
@@ -39,10 +62,11 @@
|
|
|
39
62
|
"check:sync": "node scripts/check-no-sync.mjs",
|
|
40
63
|
"check:skills": "node scripts/check-skill-frontmatter.mjs",
|
|
41
64
|
"test": "node --test test/*.test.mjs && pnpm -r test",
|
|
42
|
-
"typecheck": "pnpm -r typecheck",
|
|
65
|
+
"typecheck": "tsc --noEmit -p tsconfig.json && pnpm -r typecheck",
|
|
66
|
+
"verify": "pnpm typecheck && pnpm test",
|
|
43
67
|
"changeset": "changeset",
|
|
44
68
|
"version-packages": "changeset version",
|
|
45
|
-
"publish-package": "TARBALL=$(pnpm pack | tail -n 1) && npm publish \"$TARBALL\" --provenance --access public",
|
|
69
|
+
"publish-package": "pnpm verify && TARBALL=$(pnpm pack | tail -n 1) && npm publish \"$TARBALL\" --provenance --access public",
|
|
46
70
|
"publish-noop": "echo 'No publish: the merged PR carries the no-publish label.'",
|
|
47
71
|
"release": "changeset publish"
|
|
48
72
|
}
|
|
@@ -14,7 +14,11 @@ const SELF = "scripts/check-no-sync.mjs";
|
|
|
14
14
|
|
|
15
15
|
const SYNC_CALL = /\b\w*Sync\s*\(/;
|
|
16
16
|
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Recursively collect files under dir, skipping this script and node_modules.
|
|
19
|
+
* @param {string} dir
|
|
20
|
+
* @returns {Promise<string[]>}
|
|
21
|
+
*/
|
|
18
22
|
async function collect(dir) {
|
|
19
23
|
const out = [];
|
|
20
24
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
@@ -32,7 +32,49 @@
|
|
|
32
32
|
import { readFile, stat } from "node:fs/promises";
|
|
33
33
|
import { join } from "node:path";
|
|
34
34
|
|
|
35
|
-
/**
|
|
35
|
+
/** @typedef {{ base: string, relative: string }} PathSpec */
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Parsed token-map.json. `tools` maps a canonical tool key to its per-harness
|
|
39
|
+
* name (null = the harness has no equivalent); `paths` maps a path key to its
|
|
40
|
+
* per-harness spec (a literal string, or a {base, relative} pair resolved
|
|
41
|
+
* recursively through the same table).
|
|
42
|
+
* @typedef {object} TokenMap
|
|
43
|
+
* @property {number} [version]
|
|
44
|
+
* @property {Record<string, Record<string, string | null>>} tools
|
|
45
|
+
* @property {Record<string, Record<string, string | PathSpec>>} paths
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Options shared by the composer entry points.
|
|
50
|
+
* @typedef {object} ComposeOptions
|
|
51
|
+
* @property {boolean} [dropNullTools]
|
|
52
|
+
* @property {string} [pluginRoot]
|
|
53
|
+
* @property {boolean} [resolveRelativePaths]
|
|
54
|
+
* @property {(message: string) => void} [warn]
|
|
55
|
+
* @property {string} [context]
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Parsed and schema-checked harness frontmatter.json.
|
|
60
|
+
* @typedef {object} AgentFrontmatter
|
|
61
|
+
* @property {string} name
|
|
62
|
+
* @property {string} description
|
|
63
|
+
* @property {string[]} tools
|
|
64
|
+
* @property {string} [model]
|
|
65
|
+
* @property {string} [argumentHint]
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A composed agent: its frontmatter plus the substituted body.
|
|
70
|
+
* @typedef {AgentFrontmatter & { body: string }} ComposedAgent
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* True when a path exists (stat succeeds).
|
|
75
|
+
* @param {string} p
|
|
76
|
+
* @returns {Promise<boolean>}
|
|
77
|
+
*/
|
|
36
78
|
async function pathExists(p) {
|
|
37
79
|
try {
|
|
38
80
|
await stat(p);
|
|
@@ -47,6 +89,7 @@ async function pathExists(p) {
|
|
|
47
89
|
const TOOL_RE = /\{\{TOOL:([^}]+)\}\}/g;
|
|
48
90
|
const PATH_RE = /\{\{PATH:([^}]+)\}\}/g;
|
|
49
91
|
|
|
92
|
+
/** @returns {void} */
|
|
50
93
|
function noop() {}
|
|
51
94
|
|
|
52
95
|
/**
|
|
@@ -62,8 +105,8 @@ function noop() {}
|
|
|
62
105
|
*
|
|
63
106
|
* @param {string} content Source text containing {{TOOL:...}}/{{PATH:...}} tokens
|
|
64
107
|
* @param {string} harness Harness id: "claude" | "pi"
|
|
65
|
-
* @param {
|
|
66
|
-
* @param {
|
|
108
|
+
* @param {TokenMap} tokenMap Parsed token-map.json (from loadTokenMap)
|
|
109
|
+
* @param {ComposeOptions} [options] { dropNullTools, pluginRoot, resolveRelativePaths, warn, context }
|
|
67
110
|
* @returns {string}
|
|
68
111
|
*/
|
|
69
112
|
export function substituteTokens(content, harness, tokenMap, options = {}) {
|
|
@@ -100,7 +143,8 @@ export function substituteTokens(content, harness, tokenMap, options = {}) {
|
|
|
100
143
|
* @param {string} root Package root (contains agents/ and token-map.json)
|
|
101
144
|
* @param {string} name Agent directory name (e.g. "ralph", "plan")
|
|
102
145
|
* @param {string} harness Harness id: "claude" | "pi"
|
|
103
|
-
* @
|
|
146
|
+
* @param {ComposeOptions} [options]
|
|
147
|
+
* @returns {Promise<ComposedAgent>}
|
|
104
148
|
*/
|
|
105
149
|
export async function composeAgent(root, name, harness, options = {}) {
|
|
106
150
|
const { dropNullTools = false, pluginRoot, resolveRelativePaths = false, warn = noop } = options;
|
|
@@ -144,14 +188,21 @@ export async function composeAgent(root, name, harness, options = {}) {
|
|
|
144
188
|
const REQUIRED_FIELDS = ["name", "description", "tools"];
|
|
145
189
|
const KNOWN_OPTIONAL_FIELDS = ["model", "argumentHint"];
|
|
146
190
|
|
|
147
|
-
/**
|
|
191
|
+
/**
|
|
192
|
+
* Parse and schema-check a harness frontmatter.json (strict, per agents/README.md).
|
|
193
|
+
* @param {string} path
|
|
194
|
+
* @param {string} name
|
|
195
|
+
* @param {string} harness
|
|
196
|
+
* @returns {Promise<AgentFrontmatter>}
|
|
197
|
+
*/
|
|
148
198
|
async function parseFrontmatter(path, name, harness) {
|
|
149
199
|
const raw = await readFile(path, "utf-8");
|
|
200
|
+
/** @type {Record<string, unknown>} */
|
|
150
201
|
let fm;
|
|
151
202
|
try {
|
|
152
203
|
fm = JSON.parse(raw);
|
|
153
204
|
} catch (err) {
|
|
154
|
-
throw new Error(`agent "${name}": invalid JSON in ${path}: ${err.message}`);
|
|
205
|
+
throw new Error(`agent "${name}": invalid JSON in ${path}: ${/** @type {Error} */ (err).message}`);
|
|
155
206
|
}
|
|
156
207
|
if (typeof fm !== "object" || fm === null) {
|
|
157
208
|
throw new Error(`agent "${name}": ${path} must be a JSON object`);
|
|
@@ -188,6 +239,11 @@ async function parseFrontmatter(path, name, harness) {
|
|
|
188
239
|
* With the installer options (`pluginRoot`, `resolveRelativePaths`) the
|
|
189
240
|
* plugin_root base and bare relative paths resolve against the actual install
|
|
190
241
|
* layout instead.
|
|
242
|
+
* @param {string} arg
|
|
243
|
+
* @param {string} harness
|
|
244
|
+
* @param {TokenMap} tokenMap
|
|
245
|
+
* @param {ComposeOptions} [opts]
|
|
246
|
+
* @returns {string}
|
|
191
247
|
*/
|
|
192
248
|
function resolvePath(arg, harness, tokenMap, opts = {}) {
|
|
193
249
|
const entry = tokenMap.paths?.[arg];
|
|
@@ -217,9 +273,9 @@ function resolvePath(arg, harness, tokenMap, opts = {}) {
|
|
|
217
273
|
* translation in extensions/agent-modes/discover.ts.
|
|
218
274
|
*
|
|
219
275
|
* @param {string[]} tools Canonical tool names from a harness frontmatter.json
|
|
220
|
-
* @param {
|
|
276
|
+
* @param {TokenMap} tokenMap Parsed token-map.json (from loadTokenMap)
|
|
221
277
|
* @param {string} harness Harness id: "claude" | "pi"
|
|
222
|
-
* @param {
|
|
278
|
+
* @param {ComposeOptions} [options] { warn }
|
|
223
279
|
* @returns {string[]}
|
|
224
280
|
*/
|
|
225
281
|
export function translateToolList(tools, tokenMap, harness, { warn = noop } = {}) {
|
|
@@ -242,7 +298,11 @@ export function translateToolList(tools, tokenMap, harness, { warn = noop } = {}
|
|
|
242
298
|
|
|
243
299
|
// ─── Token map ───────────────────────────────────────────────────────────────
|
|
244
300
|
|
|
245
|
-
/**
|
|
301
|
+
/**
|
|
302
|
+
* Load token-map.json from the package root; missing/incomplete maps hard-fail.
|
|
303
|
+
* @param {string} root
|
|
304
|
+
* @returns {Promise<TokenMap>}
|
|
305
|
+
*/
|
|
246
306
|
export async function loadTokenMap(root) {
|
|
247
307
|
const path = join(root, "token-map.json");
|
|
248
308
|
let raw;
|
package/scripts/lib/fs.mjs
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
import { stat } from "node:fs/promises";
|
|
14
14
|
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* True when `p` exists and is a regular file; false on any error.
|
|
17
|
+
* @param {string} p
|
|
18
|
+
* @returns {Promise<boolean>}
|
|
19
|
+
*/
|
|
16
20
|
export async function isFile(p) {
|
|
17
21
|
try {
|
|
18
22
|
return (await stat(p)).isFile();
|
|
@@ -21,7 +25,11 @@ export async function isFile(p) {
|
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* True when `p` exists and is a directory; false on any error.
|
|
30
|
+
* @param {string} p
|
|
31
|
+
* @returns {Promise<boolean>}
|
|
32
|
+
*/
|
|
25
33
|
export async function isDirectory(p) {
|
|
26
34
|
try {
|
|
27
35
|
return (await stat(p)).isDirectory();
|