@jaybeeuu/agent-cortex 1.38.1 → 1.39.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.
Files changed (62) hide show
  1. package/AGENTS.md +3 -1
  2. package/CHANGELOG.md +30 -0
  3. package/README.md +34 -16
  4. package/agents/README.md +7 -5
  5. package/agents/ralph-plan/agent.md +1 -1
  6. package/agents/ralph-plan.agent.md +1 -1
  7. package/bin/agent-cortex.mjs +13 -5
  8. package/bin/installers/claude.mjs +129 -15
  9. package/claude/.claude-plugin/plugin.json +1 -1
  10. package/claude/agents/ralph-plan.md +1 -1
  11. package/docs/ideas/extension-manifests.md +75 -0
  12. package/docs/ideas/record-ideas-as-beads.md +115 -0
  13. package/docs/ideas/subagent-visibility.md +72 -0
  14. package/docs/ideas/task-session-context.md +89 -0
  15. package/docs/research/skill-design-research.md +4 -4
  16. package/docs/research/skill-improvements-analysis.md +1 -1
  17. package/docs/skills/skill-anatomy.md +38 -2
  18. package/docs/technical-direction/migration-execution-labels.md +132 -0
  19. package/lib/cli.mjs +9 -3
  20. package/package.json +2 -2
  21. package/plugin.json +1 -1
  22. package/pnpm-workspace.yaml +1 -1
  23. package/skills/engineering/design-an-interface/SKILL.md +78 -58
  24. package/skills/engineering/grill-with-docs/REFERENCE.md +78 -0
  25. package/skills/engineering/grill-with-docs/SKILL.md +66 -63
  26. package/skills/engineering/improve-codebase-architecture/SKILL.md +66 -48
  27. package/skills/engineering/technical-direction/FORMAT.md +38 -0
  28. package/skills/engineering/technical-direction/SKILL.md +70 -77
  29. package/skills/planning/classify-bead/SKILL.md +59 -35
  30. package/skills/planning/create-task/REFERENCE.md +40 -0
  31. package/skills/planning/create-task/SKILL.md +70 -66
  32. package/skills/planning/create-task/scripts/create-chores.ts +6 -1
  33. package/skills/planning/create-task/scripts/node_modules/.bin/tsc +21 -0
  34. package/skills/planning/create-task/scripts/node_modules/.bin/tsserver +21 -0
  35. package/skills/planning/create-task/scripts/node_modules/.bin/tsx +21 -0
  36. package/skills/planning/prd-to-tasks/REFERENCE.md +66 -0
  37. package/skills/planning/prd-to-tasks/SKILL.md +86 -170
  38. package/skills/planning/record-idea/FORMAT.md +44 -0
  39. package/skills/planning/record-idea/SKILL.md +70 -53
  40. package/skills/planning/request-refactor-plan/FORMAT.md +45 -0
  41. package/skills/planning/request-refactor-plan/SKILL.md +57 -46
  42. package/skills/planning/write-a-prd/FORMAT.md +54 -0
  43. package/skills/planning/write-a-prd/SKILL.md +49 -48
  44. package/skills/planning/write-a-ticket/SKILL.md +68 -53
  45. package/skills/productivity/handoff/SKILL.md +12 -0
  46. package/skills/productivity/init-beads/SKILL.md +48 -40
  47. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsc +21 -0
  48. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsserver +21 -0
  49. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsx +21 -0
  50. package/skills/productivity/write-a-skill/SKILL.md +2 -1
  51. package/skills/review/maintain-agent-docs/SKILL.md +71 -51
  52. package/skills/workflow/hitl-collab/SKILL.md +86 -17
  53. package/skills/workflow/ralph/REFERENCE.md +22 -17
  54. package/skills/workflow/ralph/SKILL.md +88 -74
  55. package/skills/workflow/run-pipeline-stage/REFERENCE.md +22 -0
  56. package/skills/workflow/run-pipeline-stage/SKILL.md +91 -93
  57. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +6 -107
  58. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsc +21 -0
  59. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsserver +21 -0
  60. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsx +21 -0
  61. package/test/claude-installer.test.mjs +248 -0
  62. package/token-map.README.md +5 -3
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/tsx@4.22.4/node_modules/tsx/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/tsx@4.22.4/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/tsx@4.22.4/node_modules/tsx/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/tsx@4.22.4/node_modules:/home/runner/work/agent-cortex/agent-cortex/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../tsx/dist/cli.mjs" "$@"
19
+ else
20
+ exec node "$basedir/../tsx/dist/cli.mjs" "$@"
21
+ fi
@@ -0,0 +1,248 @@
1
+ // Tests for `agent-cortex install claude` runtime registration: after
2
+ // regenerating the claude/ subtree, the plain install registers the plugin
3
+ // with Claude Code by driving the `claude plugin` CLI (marketplace add →
4
+ // install → marketplace update → plugin update). The real CLI is a genuine
5
+ // external system, so these tests drive a fake `claudeBin` script that records
6
+ // every invocation; the real repo's marketplace.json supplies the manifest.
7
+
8
+ import { describe, it } from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { execFile } from "node:child_process";
11
+ import {
12
+ mkdtempSync,
13
+ mkdirSync,
14
+ writeFileSync,
15
+ rmSync,
16
+ readFileSync,
17
+ chmodSync,
18
+ existsSync,
19
+ } from "node:fs";
20
+ import { tmpdir } from "node:os";
21
+ import { fileURLToPath } from "node:url";
22
+ import { dirname, join } from "node:path";
23
+ import { registerClaude } from "../bin/installers/claude.mjs";
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+ const ROOT = join(__dirname, "..");
27
+ const CLI_PATH = join(ROOT, "bin", "agent-cortex.mjs");
28
+
29
+ function runCli(args) {
30
+ return new Promise((resolve) => {
31
+ execFile(process.execPath, [CLI_PATH, ...args], (error, stdout, stderr) => {
32
+ resolve({ exitCode: error ? error.code ?? 1 : 0, stdout, stderr });
33
+ });
34
+ });
35
+ }
36
+
37
+ // ─── Fake claude CLI ─────────────────────────────────────────────────────────
38
+
39
+ /**
40
+ * A fake `claude` binary recording every argv line to `log` (one line per
41
+ * invocation, space-joined). Set `failWhen` to a substring: any invocation
42
+ * whose argv contains it exits 1. Exits 0 otherwise.
43
+ */
44
+ function makeFakeClaude(dir, { failWhen = null } = {}) {
45
+ const bin = join(dir, "claude");
46
+ const log = join(dir, "calls.log");
47
+ const script = [
48
+ "#!/bin/sh",
49
+ `echo "$*" >> "${log}"`,
50
+ ...(failWhen
51
+ ? [`if printf '%s' "$*" | grep -q -- "${failWhen}"; then exit 1; fi`]
52
+ : []),
53
+ "exit 0",
54
+ ].join("\n");
55
+ writeFileSync(bin, `${script}\n`);
56
+ chmodSync(bin, 0o755);
57
+ return { bin, log };
58
+ }
59
+
60
+ function makeTmp() {
61
+ return mkdtempSync(join(tmpdir(), "agent-cortex-claude-installer-"));
62
+ }
63
+
64
+ /** A minimal marketplace tree (as seen in the real repo) at a scratch path. */
65
+ function makeMarketplaceRoot({ name = "jaybeeuu", plugin = "agent-cortex" } = {}) {
66
+ const root = mkdtempSync(join(tmpdir(), "agent-cortex-marketplace-"));
67
+ mkdirSync(join(root, ".claude-plugin"), { recursive: true });
68
+ writeFileSync(
69
+ join(root, ".claude-plugin", "marketplace.json"),
70
+ JSON.stringify({
71
+ name,
72
+ owner: { name: "tester" },
73
+ plugins: [{ name: plugin, source: "./claude", description: "test plugin" }],
74
+ }),
75
+ );
76
+ return root;
77
+ }
78
+
79
+ // ─── registerClaude ──────────────────────────────────────────────────────────
80
+
81
+ describe("registerClaude", () => {
82
+ it("drives claude plugin marketplace add → install → marketplace update → plugin update", () => {
83
+ const tmp = makeTmp();
84
+ const root = makeMarketplaceRoot();
85
+ const fake = makeFakeClaude(tmp);
86
+ try {
87
+ const result = registerClaude({ root, claudeBin: fake.bin });
88
+ assert.equal(result.marketplace, "jaybeeuu");
89
+ assert.equal(result.plugin, "agent-cortex");
90
+ assert.equal(result.dryRun, false);
91
+
92
+ const calls = readFileSync(fake.log, "utf-8").trim().split("\n");
93
+ // The availability probe (`plugin --help`) is a spawn, but the registration
94
+ // surface is the four commands below — assert those, in order.
95
+ const registration = calls.filter((c) => !c.startsWith("plugin --help"));
96
+ assert.deepEqual(registration, [
97
+ `plugin marketplace add ${root}`,
98
+ "plugin install agent-cortex@jaybeeuu -y",
99
+ "plugin marketplace update jaybeeuu",
100
+ "plugin update agent-cortex -y",
101
+ ]);
102
+ } finally {
103
+ rmSync(tmp, { recursive: true, force: true });
104
+ rmSync(root, { recursive: true, force: true });
105
+ }
106
+ });
107
+
108
+ it("derives marketplace and plugin names from the manifest", () => {
109
+ const tmp = makeTmp();
110
+ const root = makeMarketplaceRoot({ name: "scratchmkt", plugin: "scratchplug" });
111
+ const fake = makeFakeClaude(tmp);
112
+ try {
113
+ const result = registerClaude({ root, claudeBin: fake.bin });
114
+ assert.equal(result.marketplace, "scratchmkt");
115
+ assert.equal(result.plugin, "scratchplug");
116
+ const calls = readFileSync(fake.log, "utf-8").trim().split("\n");
117
+ const registration = calls.filter((c) => !c.startsWith("plugin --help"));
118
+ assert.ok(registration.some((c) => c === "plugin install scratchplug@scratchmkt -y"));
119
+ assert.ok(registration.some((c) => c === "plugin update scratchplug -y"));
120
+ } finally {
121
+ rmSync(tmp, { recursive: true, force: true });
122
+ rmSync(root, { recursive: true, force: true });
123
+ }
124
+ });
125
+
126
+ it("--dry-run plans the commands without spawning claude at all", () => {
127
+ const tmp = makeTmp();
128
+ const root = makeMarketplaceRoot();
129
+ const fake = makeFakeClaude(tmp);
130
+ try {
131
+ const result = registerClaude({ root, claudeBin: fake.bin, dryRun: true });
132
+ assert.equal(result.dryRun, true);
133
+ assert.deepEqual(
134
+ result.commands,
135
+ [
136
+ ["plugin", "marketplace", "add", root],
137
+ ["plugin", "install", "agent-cortex@jaybeeuu", "-y"],
138
+ ["plugin", "marketplace", "update", "jaybeeuu"],
139
+ ["plugin", "update", "agent-cortex", "-y"],
140
+ ],
141
+ );
142
+ // No registration spawns happened at all in dry-run mode.
143
+ assert.equal(existsSync(fake.log), false);
144
+ } finally {
145
+ rmSync(tmp, { recursive: true, force: true });
146
+ rmSync(root, { recursive: true, force: true });
147
+ }
148
+ });
149
+
150
+ it("defaults the claude binary to `claude` from PATH (dry-run only — no spawn)", () => {
151
+ const root = makeMarketplaceRoot();
152
+ try {
153
+ const result = registerClaude({ root, dryRun: true });
154
+ assert.equal(result.commands.length, 4);
155
+ assert.ok(result.commands[0][0] === "plugin");
156
+ } finally {
157
+ rmSync(root, { recursive: true, force: true });
158
+ }
159
+ });
160
+
161
+ it("fails with upgrade guidance when the claude binary lacks the plugin subcommand", () => {
162
+ const tmp = makeTmp();
163
+ const root = makeMarketplaceRoot();
164
+ const fake = makeFakeClaude(tmp, { failWhen: "plugin --help" });
165
+ try {
166
+ assert.throws(
167
+ () => registerClaude({ root, claudeBin: fake.bin }),
168
+ /plugin.*subcommand.*update/i,
169
+ );
170
+ } finally {
171
+ rmSync(tmp, { recursive: true, force: true });
172
+ rmSync(root, { recursive: true, force: true });
173
+ }
174
+ });
175
+
176
+ it("fails, naming the failing command, when a claude plugin command errors", () => {
177
+ const tmp = makeTmp();
178
+ const root = makeMarketplaceRoot();
179
+ const fake = makeFakeClaude(tmp, { failWhen: "plugin install" });
180
+ try {
181
+ assert.throws(
182
+ () => registerClaude({ root, claudeBin: fake.bin }),
183
+ /claude plugin install agent-cortex@jaybeeuu -y/,
184
+ );
185
+ } finally {
186
+ rmSync(tmp, { recursive: true, force: true });
187
+ rmSync(root, { recursive: true, force: true });
188
+ }
189
+ });
190
+
191
+ it("fails when the checkout has no marketplace manifest", () => {
192
+ const tmp = makeTmp();
193
+ const root = mkdtempSync(join(tmpdir(), "agent-cortex-no-market-"));
194
+ const fake = makeFakeClaude(tmp);
195
+ try {
196
+ assert.throws(
197
+ () => registerClaude({ root, claudeBin: fake.bin }),
198
+ /marketplace\.json/,
199
+ );
200
+ // The failed manifest read happens before any claude invocation.
201
+ assert.equal(existsSync(fake.log), false);
202
+ } finally {
203
+ rmSync(tmp, { recursive: true, force: true });
204
+ rmSync(root, { recursive: true, force: true });
205
+ }
206
+ });
207
+
208
+ it("works against the real repo checkout and its marketplace manifest", () => {
209
+ const tmp = makeTmp();
210
+ const fake = makeFakeClaude(tmp);
211
+ try {
212
+ const result = registerClaude({ root: ROOT, claudeBin: fake.bin });
213
+ assert.equal(result.marketplace, "jaybeeuu");
214
+ assert.equal(result.plugin, "agent-cortex");
215
+ const calls = readFileSync(fake.log, "utf-8").trim().split("\n");
216
+ const registration = calls.filter((c) => !c.startsWith("plugin --help"));
217
+ assert.equal(registration.length, 4);
218
+ } finally {
219
+ rmSync(tmp, { recursive: true, force: true });
220
+ }
221
+ });
222
+ });
223
+
224
+ // ─── CLI wiring ───────────────────────────────────────────────────────────────
225
+
226
+ describe("install claude CLI: registration", () => {
227
+ it("--dry-run without --output prints the registration plan and writes nothing", async () => {
228
+ const { exitCode, stdout } = await runCli(["install", "claude", "--dry-run"]);
229
+ assert.equal(exitCode, 0);
230
+ assert.ok(stdout.includes("would run: claude plugin marketplace add"));
231
+ assert.ok(stdout.includes("claude plugin install agent-cortex@jaybeeuu"));
232
+ assert.ok(stdout.includes("claude plugin marketplace update jaybeeuu"));
233
+ assert.ok(stdout.includes("claude plugin update agent-cortex"));
234
+ assert.ok(/dry-run/i.test(stdout));
235
+ });
236
+
237
+ it("--output <dir> generates only — no registration plan is printed", async () => {
238
+ const out = mkdtempSync(join(tmpdir(), "agent-cortex-cli-out-"));
239
+ try {
240
+ const { exitCode, stdout } = await runCli(["install", "claude", "--output", out]);
241
+ assert.equal(exitCode, 0);
242
+ assert.doesNotMatch(stdout, /claude plugin/);
243
+ assert.ok(stdout.includes("Generated"));
244
+ } finally {
245
+ rmSync(out, { recursive: true, force: true });
246
+ }
247
+ });
248
+ });
@@ -119,9 +119,11 @@ The full contract is embedded in `token-map.json` under `contract`. In summary,
119
119
  `{{PATH:...}}` against the map and `{{SECTION:...}}` from the per-harness section
120
120
  files; `bin/installers/copilot.mjs` is the shared generator both `pnpm build:copilot`
121
121
  and `agent-cortex install copilot` run.
122
- - `bin/installers/claude.mjs` — the single Claude generator, behind both
123
- `agent-cortex install claude` and the `pnpm build:claude` alias (no build-time
124
- counterpart; the committed `claude/` subtree is regenerated by it and drift-checked).
122
+ - `bin/installers/claude.mjs` — the single Claude generator, behind plain
123
+ `agent-cortex install claude` (which also registers the plugin with Claude Code) and
124
+ its generate-only `pnpm build:claude` alias (`install claude --output claude`; no
125
+ build-time counterpart — the committed `claude/` subtree is regenerated by it and
126
+ drift-checked).
125
127
  - `bin/installers/pi.mjs` — the pi harness installer (`agent-cortex install pi`), an
126
128
  install-time consumer of the map's contract.
127
129
  - `lib/cli.mjs` — `SUPPORTED_HARNESSES`, the install command surface the harness ids come