@jaybeeuu/agent-cortex 1.43.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.agents/skills/style-versioning/SKILL.md +5 -6
  2. package/.github/workflows/ci.yml +4 -11
  3. package/AGENTS.md +10 -16
  4. package/CHANGELOG.md +16 -0
  5. package/README.md +44 -55
  6. package/agents/README.md +9 -23
  7. package/agents/ralph/agent.md +7 -10
  8. package/agents/ralph/claude/polling.md +1 -1
  9. package/bin/agent-cortex.mjs +0 -16
  10. package/bin/installers/claude.mjs +2 -2
  11. package/docs/research/disable-model-invocation.md +5 -26
  12. package/docs/skills/skill-anatomy.md +2 -3
  13. package/docs/technical-direction/harness-config.md +6 -14
  14. package/docs/user-preferences.md +2 -2
  15. package/extensions/agent-modes/README.md +3 -3
  16. package/extensions/agent-modes/discover.ts +6 -6
  17. package/extensions/subagent/README.md +2 -2
  18. package/extensions/subagent/agents.ts +1 -2
  19. package/lib/cli.mjs +5 -7
  20. package/package.json +3 -5
  21. package/scripts/lib/compose-agent.mjs +10 -10
  22. package/skills/workflow/ralph/REFERENCE.md +3 -3
  23. package/skills/workflow/ralph/SKILL.md +5 -5
  24. package/test/cli.test.mjs +11 -10
  25. package/token-map.README.md +9 -12
  26. package/token-map.json +26 -31
  27. package/agents/plan/copilot/frontmatter.json +0 -6
  28. package/agents/plan.agent.md +0 -59
  29. package/agents/ralph/copilot/frontmatter.json +0 -6
  30. package/agents/ralph/copilot/polling.md +0 -62
  31. package/agents/ralph-plan/copilot/frontmatter.json +0 -6
  32. package/agents/ralph-plan.agent.md +0 -126
  33. package/agents/ralph.agent.md +0 -331
  34. package/agents/strategy/copilot/frontmatter.json +0 -6
  35. package/agents/strategy.agent.md +0 -112
  36. package/bin/installers/copilot.mjs +0 -124
  37. package/hooks.json +0 -10
  38. package/plugin.json +0 -35
  39. package/scripts/build-copilot-agents.mjs +0 -30
  40. package/scripts/install-instructions.sh +0 -82
  41. package/scripts/sync-plugin-version.sh +0 -17
  42. package/test/copilot-installer.test.mjs +0 -308
@@ -3,8 +3,7 @@
3
3
  Decision record for the frontmatter field this repo uses to keep rare or destructive
4
4
  skills out of automatic model routing (bead `agnt-ctx-yf24`).
5
5
 
6
- **Verdict:** rely on it for pi and Claude Code. Do not rely on it in Copilot CLI as
7
- "invoke-only" — there it means "unreachable through the model-facing skill tool".
6
+ **Verdict:** rely on it for pi and Claude Code.
8
7
 
9
8
  ## What the field does
10
9
 
@@ -19,11 +18,10 @@ previously implied.
19
18
  | --- | --- | --- | --- |
20
19
  | pi 1.4.0 | Yes — byte-identical copy | Yes — hidden from the prompt, `/skill:name` still works | `bin/installers/pi.mjs:182-204`, `scripts/lib/compose-agent.mjs:69-95`; `dist/core/skills.js:262` (parse) and `:279` (filter); `docs/skills.md:53` |
21
20
  | Claude Code 2.1.294 | Yes — byte-identical copy | Yes — Claude cannot invoke it, `/skill-name` still works | `bin/installers/claude.mjs:160-201`, same token helper; [Claude Code skills docs](https://code.claude.com/docs/en/skills) ("Control who invokes a skill") |
22
- | Copilot CLI (1.0.55 locally, 1.0.80/1.0.83 upstream) | N/A — no copy; `plugin.json` `"skills": "skills/"` serves the repo tree in place | Auto-invocation suppressed, but explicit model invocation fails; `/skill-name` works | `plugin.json:12`; [github/copilot-cli#4438](https://github.com/github/copilot-cli/issues/4438) (open, retested 1.0.83) |
23
21
 
24
22
  Both materialisers copy `SKILL.md` as text and rewrite only `{{TOOL:...}}` /
25
23
  `{{PATH:...}}` tokens, so frontmatter keys they do not know pass through untouched —
26
- nothing re-serialises YAML. Verified by installing all three harnesses into
24
+ nothing re-serialises YAML. Verified by installing both harnesses into
27
25
  `/var/tmp/dmi-check` and diffing `skills/productivity/teach/SKILL.md` (the repo's
28
26
  only current user of the field): both copies are byte-identical to the source.
29
27
  `claude plugin validate /var/tmp/dmi-check/claude/skills` passes, i.e. Claude Code's
@@ -58,46 +56,27 @@ Two Claude-specific caveats:
58
56
  frontmatter field itself still applies there — only that settings-based alternative
59
57
  is unavailable.
60
58
 
61
- **Copilot CLI.** The field is not in GitHub's skill documentation, which lists only
62
- `name`, `description`, `license`, and `allowed-tools`. In practice the CLI filters
63
- flagged skills out of the `skill()` tool's resolution list, so the model cannot call
64
- them even when the user names one: `Skill not found`. Only the interactive
65
- `/skill-name` slash command reaches a flagged skill, and `-p` mode has no slash path.
66
- Upstream issue #4438 is open.
67
-
68
- Local probing was not possible: the installed CLI is 1.0.55 (no `copilot skill`
69
- subcommand), and prompt runs are refused by this machine's org policy. The upstream
70
- report is the evidence for Copilot, tested on 1.0.80 and 1.0.83 — newer than 1.0.55,
71
- so this may differ locally, in either direction.
72
-
73
59
  ## Options for "explicit invocation only", evaluated
74
60
 
75
61
  | Option | Portable? | Enforced? | Verdict |
76
62
  | --- | --- | --- | --- |
77
- | `disable-model-invocation: true` | pi + Claude Code yes; Copilot suppresses but breaks tool-based invocation | Yes on pi/Claude | **Recommended** where suppressing auto-routing is the point and the explicit path is a human typing `/name` |
63
+ | `disable-model-invocation: true` | pi + Claude Code yes | Yes | **Recommended** where suppressing auto-routing is the point and the explicit path is a human typing `/name` |
78
64
  | Naming convention (e.g. `manual-*`) | Yes | No — no harness reads names | Rejected: a human signal we already get from the body |
79
- | `metadata:` block | Yes (spec-legal) | No — pi and Claude read top-level keys only, Copilot undefined | Rejected: documentation that looks like enforcement |
65
+ | `metadata:` block | Yes (spec-legal) | No — pi and Claude read top-level keys only | Rejected: documentation that looks like enforcement |
80
66
  | Keep such skills out of `skills/` | Yes | Yes, by not shipping the skill | Rejected: gives up the per-harness install entirely |
81
67
 
82
68
  ## Recommendation
83
69
 
84
70
  Use the field when the danger is fuzzy automatic matching and the intended explicit
85
71
  path is a human typing `/skill-name`: that is the case for a migration skill whose
86
- `--apply` renames labels workspace-wide. Accept, and document, that on Copilot CLI it
87
- also blocks model-mediated invocation, including `-p` runs — if a workflow needs
88
- non-interactive access to such a skill, do not set the field and instead disable the
89
- skill in that user's Copilot config (`copilot skill disable <name>`, or the `/skills`
90
- toggle), which is harness-native and per-user.
72
+ `--apply` renames labels workspace-wide.
91
73
 
92
74
  ## Reproducing
93
75
 
94
76
  ```sh
95
77
  node bin/agent-cortex.mjs install claude --output /var/tmp/dmi-check/claude
96
78
  node bin/agent-cortex.mjs install pi --output /var/tmp/dmi-check/pi
97
- node bin/agent-cortex.mjs install copilot --output /var/tmp/dmi-check/copilot
98
79
  diff skills/productivity/teach/SKILL.md /var/tmp/dmi-check/claude/skills/teach/SKILL.md
99
80
  diff skills/productivity/teach/SKILL.md /var/tmp/dmi-check/pi/skills/productivity/teach/SKILL.md
100
81
  claude plugin validate /var/tmp/dmi-check/claude/skills
101
82
  ```
102
-
103
- The Copilot run writes only composed agent files — there is no skill copy to inspect.
@@ -14,8 +14,7 @@ Optional fields:
14
14
  - `disable-model-invocation`: hides the skill from automatic model routing; explicit
15
15
  `/skill-name` invocation still works. Set it when the danger is a fuzzy description
16
16
  match, e.g. a skill whose steps are destructive. Preserved and honoured by pi and
17
- Claude Code; Copilot CLI suppresses auto-routing but then cannot reach the skill
18
- through its model-facing tool. See `docs/research/disable-model-invocation.md`.
17
+ Claude Code. See `docs/research/disable-model-invocation.md`.
19
18
 
20
19
  ## Description format rules
21
20
 
@@ -35,7 +34,7 @@ Optional fields:
35
34
 
36
35
  ## Tool references
37
36
 
38
- Reference agent tools by `{{TOOL:name}}` token (canonical copilot name), never a
37
+ Reference agent tools by `{{TOOL:name}}` token (canonical authoring name), never a
39
38
  hardcoded harness-specific name such as `bash`, `task`, or `read_agent` — installers
40
39
  substitute the per-harness name from `token-map.json` at install time. Add any new tool
41
40
  to the map's `tools` section in the same change; unknown tokens are hard errors. See
@@ -20,13 +20,14 @@ below no longer hold:
20
20
  that both load.
21
21
 
22
22
  `pi.packages` and `lib/pi-packages.mjs` are deleted, so the bespoke-pi-mechanism problem this
23
- memo was written to settle is closed. The Claude and Copilot analysis stands.
23
+ memo was written to settle is closed. The Claude analysis stands; Copilot CLI is no longer a
24
+ deploy target (`agnt-ctx-2rl`).
24
25
 
25
26
  ## Problem and target outcome
26
27
 
27
- - **What we are solving.** agent-cortex ships agents and skills to three harnesses (pi, Claude
28
- Code, Copilot CLI) and needs a declared, reproducible set of *third-party* extensions those
29
- agents depend on (pi packages / Claude plugins). Two bespoke mechanisms currently exist and
28
+ - **What we are solving.** agent-cortex ships agents and skills to two harnesses (pi, Claude
29
+ Code) and needs a declared, reproducible set of *third-party* extensions those agents depend
30
+ on (pi packages / Claude plugins). Two bespoke mechanisms currently exist and
30
31
  disagree: `main` declares packages in `package.json` → `pi.packages` and provisions them from
31
32
  `lib/pi-packages.mjs`; the unmerged pi-harness epic (`agnt-ctx-dfq3`) declares them in
32
33
  `pi.extensions.json` / `claude.extensions.json` and provisions them via `agent-cortex ext
@@ -51,9 +52,6 @@ memo was written to settle is closed. The Claude and Copilot analysis stands.
51
52
  - **Claude is idiomatic two ways.** Machine state is `~/.claude/settings.json` → `enabledPlugins`
52
53
  + `extraKnownMarketplaces`. A plugin declares other plugins in `.claude-plugin/plugin.json` →
53
54
  `dependencies`, which Claude Code resolves and auto-installs.
54
- - **Copilot has no dependency mechanism.** `copilot plugin install/list/uninstall` exists, but its
55
- state is auto-managed `~/.copilot/config.json` (not committable) and `plugin.json` declares no
56
- dependencies.
57
55
  - **The epic already built two-thirds of the target.** Unmerged commit `afab2c6` (F3) materialises
58
56
  `pi/settings.json` + `pi/keybindings.json` from committed templates with merge-keep-personal and
59
57
  the CLI owning `packages`; `1ff212d` (F4) makes bundled pi extensions load via package
@@ -86,7 +84,7 @@ memo was written to settle is closed. The Claude and Copilot analysis stands.
86
84
  --json` are the exact machine-state comparison; drift self-heals on install.
87
85
  - **Cons.** pi bundling shifts update cadence to agent-cortex releases and grows the tarball;
88
86
  Claude cross-marketplace deps need an allowlist; the committed template also carries personal
89
- settings; Copilot gets nothing.
87
+ settings.
90
88
  - **Risks.** Loading TS extensions from bundled `node_modules/`; maintaining the Claude
91
89
  cross-marketplace allowlist.
92
90
 
@@ -128,8 +126,6 @@ the epic, and delete `pi.packages` + `lib/pi-packages.mjs` from `main`.
128
126
  - **Committed personal settings.** `pi/settings.json` already carries models/theme; the template
129
127
  model makes the repo own the whole pi settings surface. Accepted; F3's merge preserves personal
130
128
  keys and only `packages` is CLI-owned.
131
- - **Copilot gets no mechanism.** Documented exception — the README says `copilot plugin install`.
132
- Accepted because Copilot has no dependency field and no committable config.
133
129
  - **No dedicated diff command.** A read-only `status` is deferred until drift is shown to hurt.
134
130
 
135
131
  ## Validation plan
@@ -160,8 +156,6 @@ pi extension loads from `node_modules/` and an optional one is materialised from
160
156
  speculative and should be dropped rather than maintained.
161
157
  - Bundling `pi-web-access`'s native-ish dependency tree (unpdf, linkedom) proves brittle or
162
158
  unacceptable on a fresh machine.
163
- - Copilot gains a committable config or a plugin dependency field — revisit the documented
164
- exception.
165
159
  - Drift between the committed template and the machine becomes a recurring annoyance — add the
166
160
  deferred read-only `status`.
167
161
 
@@ -175,8 +169,6 @@ pi extension loads from `node_modules/` and an optional one is materialised from
175
169
  (auto-install, cross-marketplace allowlist, tag naming).
176
170
  - Claude Code, *Settings* — https://code.claude.com/docs/en/settings (`enabledPlugins`,
177
171
  `extraKnownMarketplaces`).
178
- - GitHub Copilot CLI, *Plugin reference* — https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference
179
- and *Configuration directory* — https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-config-dir-reference
180
172
  - Code evidence (as of 2026-09 — `pi.packages` and `lib/pi-packages.mjs` were removed in
181
173
  `agnt-ctx-7kru.1`, see Status): `package.json` (`pi.packages`), `lib/pi-packages.mjs` (main's
182
174
  provisioner);
@@ -1,8 +1,8 @@
1
1
  # User Preferences
2
2
 
3
3
  This file records personal development preferences for the author (**jaybeeuu**).
4
- Both Copilot CLI agents and PI coding agents should read this file for user-level
5
- context when making tooling and workflow decisions.
4
+ Both pi and Claude Code agents should read this file for user-level context when
5
+ making tooling and workflow decisions.
6
6
 
7
7
  ## Package manager
8
8
 
@@ -39,9 +39,9 @@ contract:
39
39
  from the tool set with a warning.
40
40
 
41
41
  Flat `agents/*.agent.md` files are parsed as a fallback when an agent has no
42
- composable directory — they are generated output (scripts/build-copilot-agents.mjs)
43
- but may exist for non-migrated agents. A composable directory always wins over its
44
- flat counterpart for the same agent id.
42
+ composable directory — a staged pi package carries flat renders, and a hand-written
43
+ agent may be a single flat file. A composable directory always wins over its flat
44
+ counterpart for the same agent id.
45
45
 
46
46
  ## Development
47
47
 
@@ -18,9 +18,9 @@ import type { ThemeColor } from "@earendil-works/pi-coding-agent";
18
18
  * and symlinked installs).
19
19
  *
20
20
  * Flat `agents/*.agent.md` files are parsed as a fallback for agents that have
21
- * no composable directory (they are generated output for Copilot, so they may
22
- * exist for any agent). A composable directory always wins over its flat
23
- * counterpart.
21
+ * no composable directory (a staged pi package ships flat renders, and a
22
+ * hand-written agent may be a single flat file). A composable directory always
23
+ * wins over its flat counterpart.
24
24
  */
25
25
 
26
26
  // ─── Types ───────────────────────────────────────────────────────────────────
@@ -40,7 +40,7 @@ export interface AgentDef {
40
40
  prompt: string;
41
41
  }
42
42
 
43
- export type HarnessId = "copilot" | "claude" | "pi";
43
+ export type HarnessId = "claude" | "pi";
44
44
 
45
45
  export interface PathSpec {
46
46
  base: string;
@@ -431,8 +431,8 @@ function readFlatAgent(filePath: string, tokenMap: TokenMap | null): AgentDef |
431
431
  * Discover agents from the agents directory.
432
432
  *
433
433
  * Composable directories (`<name>/agent.md` + `<name>/pi/frontmatter.json`) are
434
- * the primary source. Flat `*.agent.md` files (generated output for Copilot) are
435
- * read only when no composable directory exists for that agent id. When
434
+ * the primary source. Flat `*.agent.md` files (a staged package's renders, or a
435
+ * hand-written agent) are read only when no composable directory exists for that agent id. When
436
436
  * `tokenMap` is omitted, token-map.json is loaded from the package root;
437
437
  * missing/unreadable maps fall back to the built-in copilot→pi translation.
438
438
  */
@@ -111,8 +111,8 @@ fire-and-forget orchestration:
111
111
  - **`read_agent`** — fallback: read one specific agent's output once you know it has
112
112
  finished (or query its `STILL RUNNING` state directly).
113
113
 
114
- These mirror Copilot CLI's `task`/`read_agent` model; `wait_for_agents` adds the
115
- blocking wait that Copilot's poll loop does manually. Abort (Ctrl+C) propagates: a
114
+ These mirror the `task`/`read_agent` model the skills are authored against;
115
+ `wait_for_agents` adds the blocking wait that a `read_agent` poll loop does manually. Abort (Ctrl+C) propagates: a
116
116
  pending `wait_for_agents` returns immediately with whatever is known so far.
117
117
 
118
118
  ## Output Display
@@ -155,8 +155,7 @@ function isRenderedAgentsTree(agentsDir: string): boolean {
155
155
  * renders the flat pi agents into `<package>/agents`.
156
156
  *
157
157
  * A source checkout contributes nothing: its `agents/` tree is the composable
158
- * source (composed at runtime by the agent-modes extension) alongside flat
159
- * renders for other harnesses — Copilot's, whose tool names pi does not have.
158
+ * source, composed at runtime by the agent-modes extension.
160
159
  */
161
160
  export function resolveUserAgentDirs(packageRoot: string = PACKAGE_ROOT): string[] {
162
161
  const dirs: string[] = [];
package/lib/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- const SUPPORTED_HARNESSES = ["copilot", "claude", "pi"];
1
+ const SUPPORTED_HARNESSES = ["claude", "pi"];
2
2
 
3
3
  // Options accepted by `install <harness>`. `--output`/`--dry-run` are shared by
4
4
  // the claude and pi installers; `--plugin-root` is pi-specific. Unknown or
@@ -87,11 +87,6 @@ Commands:
87
87
  registration cannot run (missing CLI,
88
88
  pre-v2 build); default warns and prints
89
89
  the manual registration commands
90
- Options (copilot):
91
- --output <dir> Write the flat *.agent.md files to <dir>
92
- (default: <package root>/agents — the dir
93
- plugin.json "agents" scans)
94
- --dry-run Print what would be generated without writing
95
90
  Options (pi):
96
91
  (no --output) Materialise the pi package into
97
92
  ~/.agent-cortex/pi: package.json,
@@ -135,7 +130,10 @@ Commands:
135
130
 
136
131
  export function validateHarness(harness) {
137
132
  if (harness === null) {
138
- return { ok: false, error: "Missing harness argument. Supported harnesses: copilot, claude, pi" };
133
+ return {
134
+ ok: false,
135
+ error: `Missing harness argument. Supported harnesses: ${SUPPORTED_HARNESSES.join(", ")}`,
136
+ };
139
137
  }
140
138
  if (!SUPPORTED_HARNESSES.includes(harness)) {
141
139
  return { ok: false, error: `Unknown harness "${harness}". Supported harnesses: ${SUPPORTED_HARNESSES.join(", ")}` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaybeeuu/agent-cortex",
3
- "version": "1.43.0",
3
+ "version": "2.0.0",
4
4
  "description": "Personal PI package with custom agents, skills, and extensions",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -39,12 +39,10 @@
39
39
  "check:sync": "node scripts/check-no-sync.mjs",
40
40
  "test": "node --test test/*.test.mjs && pnpm -r test",
41
41
  "typecheck": "pnpm -r typecheck",
42
- "build:copilot": "node scripts/build-copilot-agents.mjs",
43
42
  "changeset": "changeset",
44
- "version-packages": "changeset version && bash scripts/sync-plugin-version.sh && pnpm build:copilot",
43
+ "version-packages": "changeset version",
45
44
  "publish-package": "TARBALL=$(pnpm pack | tail -n 1) && npm publish \"$TARBALL\" --provenance --access public",
46
45
  "publish-noop": "echo 'No publish: the merged PR carries the no-publish label.'",
47
- "release": "changeset publish",
48
- "postinstall": "bash scripts/install-instructions.sh"
46
+ "release": "changeset publish"
49
47
  }
50
48
  }
@@ -1,8 +1,8 @@
1
1
  // Shared composer: reads a composable agent directory (agents/<name>/) and emits
2
- // the harness-specific agent content defined by agents/README.md. The Copilot
3
- // generator (scripts/build-copilot-agents.mjs) and the Claude install-time generator
4
- // (bin/installers/claude.mjs) compose from here, so the composable dirs are
5
- // the single source of truth and the flat/generated files stay in lockstep.
2
+ // the harness-specific agent content defined by agents/README.md. The Claude and pi
3
+ // install-time generators (bin/installers/claude.mjs, bin/installers/pi.mjs) compose
4
+ // from here, so the composable dirs are the single source of truth and the generated
5
+ // files stay in lockstep.
6
6
  //
7
7
  // Composition per the agents/README.md contract:
8
8
  // 1. {{SECTION:name}} is replaced with <dir>/<harness>/<name>.md content.
@@ -15,15 +15,15 @@
15
15
  // silently dropped section.
16
16
  //
17
17
  // Options (the pi installer passes `dropNullTools`, `pluginRoot` and
18
- // `resolveRelativePaths`; the copilot generator and claude installer use the strict defaults):
18
+ // `resolveRelativePaths`; the claude installer uses the strict defaults):
19
19
  // dropNullTools replace null-mapped tool tokens with an empty string and
20
20
  // warn instead of throwing (pi's prose rule per the
21
21
  // token-map contract)
22
22
  // pluginRoot override the plugin_root used for resolved paths
23
23
  // (installers compute it from the actual install layout)
24
24
  // resolveRelativePaths non-keyed {{PATH:...}} args resolve to pluginRoot/arg
25
- // instead of staying verbatim (install time; the build
26
- // scripts leave them bare for Copilot CLI resolution)
25
+ // instead of staying verbatim (install time; without it
26
+ // they stay bare for runtime resolution)
27
27
  // warn callback for drop/omit warnings (default: no-op; the
28
28
  // pi installer collects them into its result)
29
29
  //
@@ -61,7 +61,7 @@ function noop() {}
61
61
  * the harness's section files before calling this.
62
62
  *
63
63
  * @param {string} content Source text containing {{TOOL:...}}/{{PATH:...}} tokens
64
- * @param {string} harness Harness id: "copilot" | "claude" | "pi"
64
+ * @param {string} harness Harness id: "claude" | "pi"
65
65
  * @param {object} tokenMap Parsed token-map.json (from loadTokenMap)
66
66
  * @param {object} options { dropNullTools, pluginRoot, resolveRelativePaths, warn, context }
67
67
  * @returns {string}
@@ -99,7 +99,7 @@ export function substituteTokens(content, harness, tokenMap, options = {}) {
99
99
  *
100
100
  * @param {string} root Package root (contains agents/ and token-map.json)
101
101
  * @param {string} name Agent directory name (e.g. "ralph", "plan")
102
- * @param {string} harness Harness id: "copilot" | "claude" | "pi"
102
+ * @param {string} harness Harness id: "claude" | "pi"
103
103
  * @returns {{ name: string, description: string, tools: string[], model?: string, argumentHint?: string, body: string }}
104
104
  */
105
105
  export async function composeAgent(root, name, harness, options = {}) {
@@ -218,7 +218,7 @@ function resolvePath(arg, harness, tokenMap, opts = {}) {
218
218
  *
219
219
  * @param {string[]} tools Canonical tool names from a harness frontmatter.json
220
220
  * @param {object} tokenMap Parsed token-map.json (from loadTokenMap)
221
- * @param {string} harness Harness id: "copilot" | "claude" | "pi"
221
+ * @param {string} harness Harness id: "claude" | "pi"
222
222
  * @param {object} options { warn }
223
223
  * @returns {string[]}
224
224
  */
@@ -116,7 +116,7 @@ When a verify or review stage fails:
116
116
 
117
117
  ## Log Polling
118
118
 
119
- Run whenever polling is triggered (timer or agent completion):
119
+ Run whenever completion handling is triggered (an agent completion):
120
120
 
121
121
  1. **Query in-flight beads**: `bd list --status=in_progress --type=chore`. Extract each bead's ID and title.
122
122
  2. For each in-flight bead, read new lines from its **parent's** log file — logs are keyed by **parent** bead ID, so all stages of a feature share one file. Track the next unread line number per parent in memory, starting at 1:
@@ -167,7 +167,7 @@ Proceed here when no chore beads are in-flight, no `stage:*` chore beads are rea
167
167
 
168
168
  When you've completed the above, prompt me to continue.
169
169
  ```
170
- 6. **Stop completely.** Do not restart the poll timer. Do not continue the event loop. Wait for the user to re-prompt before doing any further work.
170
+ 6. **Stop completely.** Do not continue the event loop. Wait for the user to re-prompt before doing any further work.
171
171
 
172
172
  ---
173
173
 
@@ -209,7 +209,7 @@ When `bd list --status=in_progress --type=chore` returns no results AND `bd read
209
209
  | File | Purpose |
210
210
  |------|---------|
211
211
  | `.agent-cortex/ralph/progress.md` | Human-readable snapshot. Regenerate: `workspace="/abs/path"; pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace" > "$workspace/.agent-cortex/ralph/progress.md"`. `workspace` must be an **absolute** path — never `.` or `$(pwd)`. **Never hand-edit.** |
212
- | `.agent-cortex/ralph/state.json` | Runtime bookkeeping only: the poll-timer shellId (Copilot) and the in-flight agent-ID→bead mapping. Shape: `{ "timerShellId": null, "inflight": [ { "choreId": "...", "parentId": "...", "title": "...", "agentId": "...", "logLine": 1 } ] }`. Initialise at startup with `{ "timerShellId": null, "inflight": [] }`. Update after every dispatch and every agent completion. **Never hand-edit.** |
212
+ | `.agent-cortex/ralph/state.json` | Runtime bookkeeping only: the in-flight agent-ID→bead mapping. Shape: `{ "inflight": [ { "choreId": "...", "parentId": "...", "title": "...", "agentId": "...", "logLine": 1 } ] }`. Initialise at startup with `{ "inflight": [] }`. Update after every dispatch and every agent completion. **Never hand-edit.** |
213
213
  | `.agent-cortex/ralph/ralph-*.log` | Per-parent log files written by subagents — every stage chore of a feature appends to `.agent-cortex/ralph/ralph-<parent-id>.log` (e.g. `ralph-abc-123.log`). |
214
214
 
215
215
  All task state is derived from beads; `state.json` holds only runtime bookkeeping:
@@ -7,7 +7,7 @@ description: "Run all pending beads end-to-end with up to 5 concurrent pipeline-
7
7
 
8
8
  Ralph is a parallel orchestration loop. It advances AFK task beads through pipeline-stage chores (`code` → `verify` → `review` → `document`), dispatching each stage as a background subagent in the feature's worktree, then opens review-gated feature and epic PRs and pauses for human merges. Ralph never writes code itself — it dispatches, tracks, and reports.
9
9
 
10
- State model: task state lives in beads (ready/in_progress via `bd`); the only local file is `.agent-cortex/ralph/state.json`, holding the poll-timer shellId and the agent-ID→bead mapping. Pipeline configuration comes from `skills/planning/create-task/pipeline.json`, and stage execution belongs to the `run-pipeline-stage` skill.
10
+ State model: task state lives in beads (ready/in_progress via `bd`); the only local file is `.agent-cortex/ralph/state.json`, holding the agent-ID→bead mapping. Pipeline configuration comes from `skills/planning/create-task/pipeline.json`, and stage execution belongs to the `run-pipeline-stage` skill.
11
11
 
12
12
  ## When to use
13
13
 
@@ -28,14 +28,14 @@ State model: task state lives in beads (ready/in_progress via `bd`); the only lo
28
28
  1. Run `bd prime` and hold the output verbatim in memory.
29
29
  2. Ensure `.agent-cortex/` and `.agent-cortex/worktrees/` are in the project's `.gitignore` (append any that are missing).
30
30
  3. Create the workspace: `mkdir -p .agent-cortex/ralph`.
31
- 4. Initialize state: write `.agent-cortex/ralph/state.json` with `{ "timerShellId": null, "inflight": [] }`.
31
+ 4. Initialize state: write `.agent-cortex/ralph/state.json` with `{ "inflight": [] }`.
32
32
  5. Read `skills/planning/create-task/pipeline.json` and hold it in memory — you need its `maxFixRounds` for the fix loop.
33
33
  6. Run `bd ready` and classify each available bead:
34
34
  - **Chore with a `stage:*` label**: pipeline stage bead — eligible for dispatch.
35
35
  - **Task or other type without an `implementation-type:*` label**: unexpected here — classification happens at planning time via `create-task`. Do not invoke `classify-bead`; treat as needs-refinement and note it for the shutdown summary.
36
36
  - **Task labelled `implementation-type:hitl`**: skip — record the ID for the Pending Human Action summary at shutdown.
37
37
  7. For each ready chore bead (up to 5), dispatch it from its parent's feature worktree (see _Dispatching a chore bead_ in REFERENCE.md — create branches/worktrees first).
38
- 8. Hand over to your harness's completion-detection mechanism: Copilot keeps a `sleep 120` poll timer running in the background; PI keeps a {{TOOL:wait_for_agents}} call outstanding over every in-flight agent ID. If no chore was dispatched and HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge`), go straight to HITL Pause (REFERENCE.md).
38
+ 8. Hand over to your harness's completion-detection mechanism: PI keeps a {{TOOL:wait_for_agents}} call outstanding over every in-flight agent ID. If no chore was dispatched and HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge`), go straight to HITL Pause (REFERENCE.md).
39
39
  9. Regenerate `.agent-cortex/ralph/progress.md`:
40
40
  ```bash
41
41
  # workspace must be the absolute path you cd'd into — never . or $(pwd)
@@ -45,7 +45,7 @@ State model: task state lives in beads (ready/in_progress via `bd`); the only lo
45
45
 
46
46
  ### 2. Event loop
47
47
 
48
- On each completion notification (background agent finished, or the poll timer fired):
48
+ On each completion notification (a background agent finished):
49
49
 
50
50
  1. Poll that parent's log for new lines — `tail -n +<nextLine> .agent-cortex/ralph/ralph-<parent-id>.log` (logs are keyed by parent bead ID, so every stage of a feature shares one file) — and post only new key events (stage transitions, test/lint results), never empty updates.
51
51
  2. Read the completed agent's output with {{TOOL:read_agent}} and parse its `---REPORT---` block for `BEAD_ID`, `STAGE_COMPLETED`, and the outcome.
@@ -97,7 +97,7 @@ On each completion notification (background agent finished, or the poll timer fi
97
97
 
98
98
  ## Philosophy / rationale
99
99
 
100
- - Orchestration state derives from beads so a crash loses nothing but an in-memory ID mapping: `state.json` holds only the poll-timer shellId and the agent-ID→bead mapping, never task state.
100
+ - Orchestration state derives from beads so a crash loses nothing but an in-memory ID mapping: `state.json` holds only the agent-ID→bead mapping, never task state.
101
101
  - Classification happens up-front at planning time (`create-task`), so the loop can trust `bd ready` instead of re-interpreting each bead's intent.
102
102
  - Human review gates are non-negotiable because agent-authored changes still need a person to merge them.
103
103
 
package/test/cli.test.mjs CHANGED
@@ -54,11 +54,6 @@ describe("parseArgs", () => {
54
54
  assert.deepStrictEqual(result, { command: "help" });
55
55
  });
56
56
 
57
- it("returns { command: 'install', harness: 'copilot' } for install copilot", async () => {
58
- const result = parseArgs(["install", "copilot"]);
59
- assert.deepStrictEqual(result, { command: "install", harness: "copilot" });
60
- });
61
-
62
57
  it("returns { command: 'install', harness: 'claude' } for install claude", async () => {
63
58
  const result = parseArgs(["install", "claude"]);
64
59
  assert.deepStrictEqual(result, { command: "install", harness: "claude" });
@@ -169,11 +164,17 @@ describe("buildHelpText", () => {
169
164
 
170
165
  describe("validateHarness", () => {
171
166
  it("returns ok for supported harnesses", async () => {
172
- for (const h of ["copilot", "claude", "pi"]) {
167
+ for (const h of ["claude", "pi"]) {
173
168
  assert.deepStrictEqual(validateHarness(h), { ok: true });
174
169
  }
175
170
  });
176
171
 
172
+ it("returns error for copilot, which is no longer a deploy target", async () => {
173
+ const result = validateHarness("copilot");
174
+ assert.equal(result.ok, false);
175
+ assert.ok(result.error.includes("Unknown harness"));
176
+ });
177
+
177
178
  it("returns error when harness is null", async () => {
178
179
  const result = validateHarness(null);
179
180
  assert.equal(result.ok, false);
@@ -207,10 +208,10 @@ describe("CLI integration", () => {
207
208
  assert.ok(stdout.includes("Usage:"));
208
209
  });
209
210
 
210
- it("exits 0 for install copilot", async () => {
211
- const { exitCode, stdout } = await runCli(["install", "copilot"]);
212
- assert.equal(exitCode, 0);
213
- assert.ok(stdout.includes("copilot"));
211
+ it("exits 1 for install copilot, which is no longer a deploy target", async () => {
212
+ const { exitCode, stderr } = await runCli(["install", "copilot"]);
213
+ assert.equal(exitCode, 1);
214
+ assert.ok(stderr.includes("Unknown harness"));
214
215
  });
215
216
 
216
217
  it("exits 0 for install claude (into a temp output dir)", async () => {
@@ -1,7 +1,7 @@
1
1
  # token-map.json — multi-harness token substitution
2
2
 
3
3
  `token-map.json` is the central, single-source mapping of **tool names**, **paths**, and
4
- **agent naming conventions** across the three harnesses this repo ships to. It is the
4
+ **agent naming conventions** across the two harnesses this repo ships to. It is the
5
5
  foundation for the install-time generation system: each harness installer (`agent-cortex
6
6
  install <harness>`) reads the map and substitutes `{{TOOL:...}}` / `{{PATH:...}}` tokens in
7
7
  the files it generates.
@@ -14,7 +14,6 @@ decisions behind the map.
14
14
 
15
15
  | id | Platform | Agent format | Plugin root |
16
16
  |---|---|---|---|
17
- | `copilot` | GitHub Copilot CLI | `agents/<name>/` composable dirs → generated `agents/*.agent.md` | `~/.copilot/installed-plugins/_direct/agent-cortex` |
18
17
  | `pi` | pi coding agent | `agents/<name>/` composable dirs (composed at runtime by agent-modes, or rendered install-time by `agent-cortex install pi`) | `~/.agent-cortex/pi` |
19
18
  | `claude` | Claude Code | `~/.agent-cortex/claude/agents/*.md` (materialised home install) | `${CLAUDE_PLUGIN_ROOT}` (env var) |
20
19
 
@@ -44,9 +43,9 @@ rather than inventing a dotted form:
44
43
  ### 2. What is mapped
45
44
 
46
45
  - **`tools`** — the twelve canonical tool names as authored in `agents/<name>/agent.md`
47
- (copilot names are the authoring names). Each row gives the equivalent tool name per
48
- harness. Source of truth for the copilot → claude half is `token-map.json`'s own claude
49
- column, consumed by `bin/installers/claude.mjs` (the install-time generator — PR #91, #92); the pi column is grounded
46
+ (the canonical authoring names). Each row gives the equivalent tool name per harness.
47
+ The claude column is consumed by `bin/installers/claude.mjs` (the install-time
48
+ generator — PR #91, #92); the pi column is grounded
50
49
  in pi's documented built-in tool surface (`read`, `bash`, `edit`, `write`, `grep`, `find`,
51
50
  `ls`) plus `ask_questions` — added by the pi-questions package (mapped from
52
51
  `ask_user`) — and `task` / `read_agent` / `wait_for_agents` subagent tools, the last three
@@ -101,7 +100,7 @@ so the warn-and-omit path applies only to future null entries. See
101
100
 
102
101
  The full contract is embedded in `token-map.json` under `contract`. In summary, installers:
103
102
 
104
- 1. Bind a harness id (`copilot` | `claude` | `pi`).
103
+ 1. Bind a harness id (`claude` | `pi`).
105
104
  2. Substitute in order: `SECTION` (left for the composer), then `TOOL`, then `PATH`.
106
105
  3. For `TOOL`: look up the canonical key, replace with the harness name; null → drop/omit;
107
106
  unknown → throw.
@@ -111,7 +110,7 @@ The full contract is embedded in `token-map.json` under `contract`. In summary,
111
110
 
112
111
  ## Authoring guidance
113
112
 
114
- - Write tokens with the **canonical (copilot) names**: `Use {{TOOL:task}} to spawn
113
+ - Write tokens with the **canonical authoring names**: `Use {{TOOL:task}} to spawn
115
114
  subagents`, `Read {{PATH:skills/workflow/plan/SKILL.md}}`.
116
115
  - Never embed a harness-specific name in the canonical sources (`agents/<name>/agent.md`,
117
116
  `skills/**/SKILL.md`) — that defeats the map. The materialised Claude plugin
@@ -125,11 +124,9 @@ The full contract is embedded in `token-map.json` under `contract`. In summary,
125
124
 
126
125
  - `agents/README.md` — composable agent directory format (ADR #63), defines the token
127
126
  grammar the map implements.
128
- - `scripts/build-copilot-agents.mjs` / `bin/installers/copilot.mjs` — the copilot
129
- harness token composer (scripts/lib/compose-agent.mjs) resolves `{{TOOL:...}}` /
130
- `{{PATH:...}}` against the map and `{{SECTION:...}}` from the per-harness section
131
- files; `bin/installers/copilot.mjs` is the shared generator both `pnpm build:copilot`
132
- and `agent-cortex install copilot` run.
127
+ - `scripts/lib/compose-agent.mjs` — the shared token composer: resolves `{{TOOL:...}}` /
128
+ `{{PATH:...}}` against the map and `{{SECTION:...}}` from the per-harness section files
129
+ for `bin/installers/claude.mjs` and `bin/installers/pi.mjs`.
133
130
  - `bin/installers/claude.mjs` — the single Claude generator: plain
134
131
  `agent-cortex install claude` materialises the plugin into `~/.agent-cortex/claude`
135
132
  with token-substituted skills, merges the committed `claude/settings.json` into