@jaybeeuu/agent-cortex 1.43.0 → 2.1.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/.agents/skills/style-versioning/SKILL.md +5 -6
- package/.github/workflows/ci.yml +4 -11
- package/AGENTS.md +13 -17
- package/CHANGELOG.md +66 -0
- package/README.md +57 -57
- package/agents/README.md +9 -23
- package/agents/ralph/agent.md +13 -17
- package/agents/ralph/claude/polling.md +1 -1
- package/agents-native/ralph.md +15 -5
- package/bin/agent-cortex.mjs +0 -16
- package/bin/installers/claude.mjs +82 -11
- package/docs/claude-hooks.md +16 -0
- package/docs/ideas/improve-pi-system-prompt.md +9 -3
- package/docs/research/disable-model-invocation.md +5 -26
- package/docs/skills/skill-anatomy.md +5 -3
- package/docs/technical-direction/harness-config.md +6 -14
- package/docs/user-preferences.md +2 -2
- package/extensions/agent-modes/README.md +3 -3
- package/extensions/agent-modes/discover.ts +6 -6
- package/extensions/output-style/README.md +58 -0
- package/extensions/output-style/index.ts +23 -0
- package/extensions/output-style/output-style.md +43 -0
- package/extensions/output-style/output-style.test.ts +50 -0
- package/extensions/output-style/output-style.ts +32 -0
- package/extensions/output-style/package.json +19 -0
- package/extensions/output-style/tsconfig.json +12 -0
- package/extensions/subagent/README.md +2 -2
- package/extensions/subagent/agents.ts +1 -2
- package/lib/cli.mjs +5 -7
- package/package.json +5 -6
- package/scripts/check-skill-frontmatter.mjs +21 -0
- package/scripts/lib/compose-agent.mjs +10 -10
- package/scripts/lib/skill-frontmatter.mjs +135 -0
- package/skills/workflow/ralph/REFERENCE.md +34 -11
- package/skills/workflow/ralph/SKILL.md +10 -10
- package/skills/workflow/ralph/scripts/pending-gates.mjs +134 -0
- package/test/cli.test.mjs +11 -10
- package/test/installer.test.mjs +143 -1
- package/test/pending-gates.test.mjs +147 -0
- package/test/skill-frontmatter.test.mjs +137 -0
- package/token-map.README.md +9 -12
- package/token-map.json +26 -31
- package/agents/plan/copilot/frontmatter.json +0 -6
- package/agents/plan.agent.md +0 -59
- package/agents/ralph/copilot/frontmatter.json +0 -6
- package/agents/ralph/copilot/polling.md +0 -62
- package/agents/ralph-plan/copilot/frontmatter.json +0 -6
- package/agents/ralph-plan.agent.md +0 -126
- package/agents/ralph.agent.md +0 -331
- package/agents/strategy/copilot/frontmatter.json +0 -6
- package/agents/strategy.agent.md +0 -112
- package/bin/installers/copilot.mjs +0 -124
- package/hooks.json +0 -10
- package/plugin.json +0 -35
- package/scripts/build-copilot-agents.mjs +0 -30
- package/scripts/install-instructions.sh +0 -82
- package/scripts/sync-plugin-version.sh +0 -17
- package/test/copilot-installer.test.mjs +0 -308
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Behaviour tests for scripts/lib/skill-frontmatter.mjs — the SKILL.md
|
|
2
|
+
// frontmatter check that `pnpm lint` runs. Each case proves one failure mode
|
|
3
|
+
// the check must catch: unparseable YAML, a missing name/description field, and
|
|
4
|
+
// a description longer than the limit.
|
|
5
|
+
|
|
6
|
+
import { describe, it } from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import {
|
|
13
|
+
MAX_DESCRIPTION_LENGTH,
|
|
14
|
+
checkSkills,
|
|
15
|
+
validateSkillFrontmatter,
|
|
16
|
+
} from "../scripts/lib/skill-frontmatter.mjs";
|
|
17
|
+
|
|
18
|
+
const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
19
|
+
|
|
20
|
+
/** Wrap frontmatter lines in a SKILL.md-shaped document. */
|
|
21
|
+
function skillDocument(frontmatter) {
|
|
22
|
+
return `---\n${frontmatter}\n---\n\n# Skill body\n`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Throwaway directory to lay out a fake skills tree in. */
|
|
26
|
+
async function makeFixtureRoot() {
|
|
27
|
+
return await mkdtemp(join(tmpdir(), "agent-cortex-skill-frontmatter-"));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Write a SKILL.md at `<root>/<relativeSkillDir>/SKILL.md`. */
|
|
31
|
+
async function writeSkill(root, relativeSkillDir, content) {
|
|
32
|
+
const dir = join(root, relativeSkillDir);
|
|
33
|
+
await mkdir(dir, { recursive: true });
|
|
34
|
+
await writeFile(join(dir, "SKILL.md"), content);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("validateSkillFrontmatter", () => {
|
|
38
|
+
it("accepts frontmatter with a name and a description", () => {
|
|
39
|
+
const errors = validateSkillFrontmatter(
|
|
40
|
+
skillDocument("name: example-skill\ndescription: Does a thing. Use when a thing needs doing."),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
assert.deepEqual(errors, []);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("reports unparseable YAML", () => {
|
|
47
|
+
const errors = validateSkillFrontmatter(
|
|
48
|
+
skillDocument("name: example-skill\ndescription: Use when the plan: breaks"),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
assert.equal(errors.length, 1);
|
|
52
|
+
assert.match(errors[0], /not valid YAML/);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("reports a missing name", () => {
|
|
56
|
+
const errors = validateSkillFrontmatter(skillDocument("description: Does a thing."));
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(errors, ["frontmatter is missing a non-empty name"]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("reports a missing description", () => {
|
|
62
|
+
const errors = validateSkillFrontmatter(skillDocument("name: example-skill"));
|
|
63
|
+
|
|
64
|
+
assert.deepEqual(errors, ["frontmatter is missing a non-empty description"]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("reports a description over the length limit", () => {
|
|
68
|
+
const errors = validateSkillFrontmatter(
|
|
69
|
+
skillDocument(`name: example-skill\ndescription: ${"a".repeat(MAX_DESCRIPTION_LENGTH + 1)}`),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
assert.equal(errors.length, 1);
|
|
73
|
+
assert.match(errors[0], /description exceeds 1024 characters \(1025\)/);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("accepts a description exactly at the length limit", () => {
|
|
77
|
+
const errors = validateSkillFrontmatter(
|
|
78
|
+
skillDocument(`name: example-skill\ndescription: ${"a".repeat(MAX_DESCRIPTION_LENGTH)}`),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(errors, []);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("reports a file with no frontmatter block", () => {
|
|
85
|
+
const errors = validateSkillFrontmatter("# Skill body\n\nNo frontmatter here.\n");
|
|
86
|
+
|
|
87
|
+
assert.deepEqual(errors, ["frontmatter block is missing (expected '---' delimiters)"]);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("checkSkills", () => {
|
|
92
|
+
it("reports each failing SKILL.md and counts every file it checked", async () => {
|
|
93
|
+
const root = await makeFixtureRoot();
|
|
94
|
+
try {
|
|
95
|
+
await writeSkill(
|
|
96
|
+
root,
|
|
97
|
+
"skills/good",
|
|
98
|
+
skillDocument("name: good-skill\ndescription: Does a thing. Use when testing the checker."),
|
|
99
|
+
);
|
|
100
|
+
await writeSkill(
|
|
101
|
+
root,
|
|
102
|
+
"skills/broken",
|
|
103
|
+
skillDocument("name: broken-skill\ndescription: Use when the plan: breaks"),
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const result = await checkSkills({ root });
|
|
107
|
+
|
|
108
|
+
assert.equal(result.checked, 2);
|
|
109
|
+
assert.equal(result.failures.length, 1);
|
|
110
|
+
assert.equal(result.failures[0].file, join("skills", "broken", "SKILL.md"));
|
|
111
|
+
} finally {
|
|
112
|
+
await rm(root, { recursive: true, force: true });
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("ignores markdown files that are not SKILL.md", async () => {
|
|
117
|
+
const root = await makeFixtureRoot();
|
|
118
|
+
try {
|
|
119
|
+
await writeSkill(root, "skills/good", skillDocument("name: good-skill\ndescription: Does a thing."));
|
|
120
|
+
await writeFile(join(root, "skills", "good", "REFERENCE.md"), "---\nnot: a skill\n---\n");
|
|
121
|
+
|
|
122
|
+
const result = await checkSkills({ root });
|
|
123
|
+
|
|
124
|
+
assert.equal(result.checked, 1);
|
|
125
|
+
assert.deepEqual(result.failures, []);
|
|
126
|
+
} finally {
|
|
127
|
+
await rm(root, { recursive: true, force: true });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("passes on this repository's own skills tree", async () => {
|
|
132
|
+
const result = await checkSkills({ root: REPO_ROOT });
|
|
133
|
+
|
|
134
|
+
assert.deepEqual(result.failures, []);
|
|
135
|
+
assert.ok(result.checked > 0, "expected the check to find SKILL.md files");
|
|
136
|
+
});
|
|
137
|
+
});
|
package/token-map.README.md
CHANGED
|
@@ -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
|
|
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
|
-
(
|
|
48
|
-
|
|
49
|
-
|
|
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 (`
|
|
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
|
|
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/
|
|
129
|
-
|
|
130
|
-
`
|
|
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
|
package/token-map.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-cortex token map",
|
|
3
|
-
"description": "Central mapping of tool names, paths, and agent naming conventions across the
|
|
3
|
+
"description": "Central mapping of tool names, paths, and agent naming conventions across the claude and pi harnesses. Single source of truth for install-time token substitution. See token-map.README.md for the design rationale.",
|
|
4
4
|
"version": 1,
|
|
5
|
-
"harnesses": ["
|
|
5
|
+
"harnesses": ["claude", "pi"],
|
|
6
6
|
"token_format": {
|
|
7
7
|
"convention": "{{TYPE:NAME}}",
|
|
8
8
|
"decision": "Adopt the {{TOOL:name}} / {{PATH:name}} / {{SECTION:name}} grammar already standardised by ADR #63 (agents/README.md) rather than a dotted {{tool.name}} form. The uppercase type prefix disambiguates token kinds at a glance, keeps tool/path/section names in one namespace collision-free, and matches the token grammar skills are already written against.",
|
|
@@ -13,40 +13,36 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"tools": {
|
|
16
|
-
"bash": { "
|
|
17
|
-
"view": { "
|
|
18
|
-
"edit": { "
|
|
19
|
-
"create": { "
|
|
20
|
-
"grep": { "
|
|
21
|
-
"rg": { "
|
|
22
|
-
"glob": { "
|
|
23
|
-
"ask_user": { "
|
|
24
|
-
"web_fetch": { "
|
|
25
|
-
"skill": { "
|
|
26
|
-
"task": { "
|
|
27
|
-
"read_agent": { "
|
|
28
|
-
"wait_for_agents": { "
|
|
16
|
+
"bash": { "claude": "Bash", "pi": "bash" },
|
|
17
|
+
"view": { "claude": "Read", "pi": "read" },
|
|
18
|
+
"edit": { "claude": "Edit", "pi": "edit" },
|
|
19
|
+
"create": { "claude": "Write", "pi": "write" },
|
|
20
|
+
"grep": { "claude": "Grep", "pi": "grep" },
|
|
21
|
+
"rg": { "claude": "Grep", "pi": "grep" },
|
|
22
|
+
"glob": { "claude": "Glob", "pi": "find" },
|
|
23
|
+
"ask_user": { "claude": "AskUserQuestion", "pi": "ask_questions" },
|
|
24
|
+
"web_fetch": { "claude": "WebFetch", "pi": "fetch_content" },
|
|
25
|
+
"skill": { "claude": "Skill", "pi": "read" },
|
|
26
|
+
"task": { "claude": "Task", "pi": "task" },
|
|
27
|
+
"read_agent": { "claude": null, "pi": "read_agent" },
|
|
28
|
+
"wait_for_agents": { "claude": null, "pi": "wait_for_agents" }
|
|
29
29
|
},
|
|
30
30
|
"paths": {
|
|
31
31
|
"plugin_root": {
|
|
32
|
-
"copilot": "~/.copilot/installed-plugins/_direct/agent-cortex",
|
|
33
32
|
"claude": "${CLAUDE_PLUGIN_ROOT}",
|
|
34
33
|
"pi": "~/.agent-cortex/pi"
|
|
35
34
|
},
|
|
36
35
|
"agents_dir": {
|
|
37
|
-
"copilot": { "base": "plugin_root", "relative": "agents" },
|
|
38
36
|
"claude": { "base": "plugin_root", "relative": "agents" },
|
|
39
37
|
"pi": { "base": "plugin_root", "relative": "agents" }
|
|
40
38
|
},
|
|
41
39
|
"skills_dir": {
|
|
42
|
-
"copilot": { "base": "plugin_root", "relative": "skills" },
|
|
43
40
|
"claude": { "base": "plugin_root", "relative": "skills" },
|
|
44
41
|
"pi": { "base": "plugin_root", "relative": "skills" }
|
|
45
42
|
}
|
|
46
43
|
},
|
|
47
44
|
"agents": {
|
|
48
45
|
"prefix": {
|
|
49
|
-
"copilot": "agent-cortex:",
|
|
50
46
|
"claude": "",
|
|
51
47
|
"pi": "agent-cortex:"
|
|
52
48
|
},
|
|
@@ -54,41 +50,40 @@
|
|
|
54
50
|
"ralph": ["claude"]
|
|
55
51
|
},
|
|
56
52
|
"sources": {
|
|
57
|
-
"copilot": "agents/<name>/ composable dirs (canonical) — composed to agents/*.agent.md by scripts/build-copilot-agents.mjs",
|
|
58
53
|
"pi": "agents/<name>/ composable dirs (canonical) — composed at runtime by the agent-modes extension",
|
|
59
54
|
"claude": "agents/<name>/ composable dirs (canonical) — composed by bin/installers/claude.mjs (install-time generator, the only generator — the generated claude/ plugin subtree is not committed), plus agents-native/*.md for deferred agents"
|
|
60
55
|
}
|
|
61
56
|
},
|
|
62
57
|
"notes": {
|
|
63
58
|
"tools": {
|
|
64
|
-
"rg": "
|
|
59
|
+
"rg": "Canonical alias for grep. Claude and pi collapse it onto their single search tool (Grep / grep).",
|
|
65
60
|
"glob": "Claude has a dedicated Glob tool. pi's built-in pattern-search tool is find (hypa_find when the pi-hypa extension is installed).",
|
|
66
|
-
"ask_user": "
|
|
61
|
+
"ask_user": "Claude (AskUserQuestion) prompts the user mid-run. pi's equivalent is ask_questions, provided by the pi-questions package (an ordinary runtime dependency of this package that `agent-cortex install pi` bundles into the staged package's node_modules) — the genuine interactive-questioning tool, restoring grilling in plan/ralph-plan/strategy modes. Like fetch_content (pi-web-access), it is only present when its package is installed, so the mapping depends on that package (see the extension-manifests idea). pi still intentionally ships no permission popups; ask_questions is the interactive mid-run question tool, not a popup.",
|
|
67
62
|
"web_fetch": "pi's fetch_content comes from the pi-web-access package (an ordinary runtime dependency of this package that `agent-cortex install pi` bundles into the staged package's node_modules).",
|
|
68
|
-
"skill": "
|
|
69
|
-
"read_agent": "Claude's Task returns results inline — there is no separate read step, so read_agent drops on claude (null).
|
|
70
|
-
"task": "
|
|
71
|
-
"wait_for_agents": "PI-only blocking wait over background subagent runs (the task tool): returns the results of completed agents and STILL RUNNING for the rest.
|
|
63
|
+
"skill": "Claude (Skill) exposes skills as a tool. pi has no dedicated skill tool — skills are surfaced in the always-present 'Available skills' context block and loaded by reading the listed SKILL.md path ({{PATH:<skill>/SKILL.md}}). The pi mapping is read, the tool used to load a skill's file; a dedicated skill tool is a follow-on design candidate if prompting proves insufficient.",
|
|
64
|
+
"read_agent": "Claude's Task returns results inline — there is no separate read step, so read_agent drops on claude (null). pi exposes read_agent as a fallback to wait_for_agents.",
|
|
65
|
+
"task": "Claude provides a subagent tool natively. On pi it is supplied by this repo's own extensions/subagent extension (which also registers read_agent and wait_for_agents), not by pi itself — a pi session started before that extension was installed has no dispatch tool at all. Skills must therefore stop and report a missing subagent tool rather than improvising a backgrounded CLI run, which has no completion signal.",
|
|
66
|
+
"wait_for_agents": "PI-only blocking wait over background subagent runs (the task tool): returns the results of completed agents and STILL RUNNING for the rest. Claude's Task delivers results inline with no wait step — null on claude."
|
|
72
67
|
},
|
|
73
68
|
"paths": {
|
|
74
69
|
"pi": "plugin_root is the staged package `agent-cortex install pi` materialises at ~/.agent-cortex/pi; pi loads that directory by path and the shipped extensions resolve their own resources relative to it (agent-modes computes plugin_root from its actual install location). A checkout or symlinked install differs — installers compute plugin_root from the actual resolution and can override it (--plugin-root).",
|
|
75
70
|
"claude": "plugin_root stays ${CLAUDE_PLUGIN_ROOT} (env var) for the materialised plugin — never a literal ~/.agent-cortex/claude. Claude Code copies marketplace-installed plugins (including local directory sources like ~/.agent-cortex/claude) into its own cache and expands the env var per context, so a literal home path in substituted files would break under cache-copy; the installer passes the env form through verbatim."
|
|
76
71
|
},
|
|
77
72
|
"agents": {
|
|
78
|
-
"prefix": "Claude strips the agent-cortex: name prefix during conversion (NAME_PREFIX in bin/installers/claude.mjs):
|
|
79
|
-
"deferred": "ralph has no generated claude counterpart — it is authored natively as agents-native/ralph.md (its event-driven orchestration cannot be produced by section composition from the polling
|
|
73
|
+
"prefix": "Claude strips the agent-cortex: name prefix during conversion (NAME_PREFIX in bin/installers/claude.mjs): pi agents are agent-cortex:<slug>, claude agents are <slug>.",
|
|
74
|
+
"deferred": "ralph has no generated claude counterpart — it is authored natively as agents-native/ralph.md (its event-driven orchestration cannot be produced by section composition from the polling pi source)."
|
|
80
75
|
}
|
|
81
76
|
},
|
|
82
77
|
"contract": {
|
|
83
78
|
"version": 1,
|
|
84
79
|
"summary": "Installers substitute {{TOOL:...}}, {{PATH:...}}, and {{SECTION:...}} tokens in generated harness files using this map. This contract is the single reference installers must implement; token-map.json is the data those rules operate on.",
|
|
85
|
-
"harness_ids": ["
|
|
80
|
+
"harness_ids": ["claude", "pi"],
|
|
86
81
|
"binding": "The harness id is the same value the installer is invoked with (agent-cortex install <harness>). Each harness reads its own column from the tools, paths, and agents sections.",
|
|
87
82
|
"substitution_order": ["SECTION", "TOOL", "PATH"],
|
|
88
83
|
"rules": [
|
|
89
|
-
"TOOL: replace {{TOOL:<key>}} with tools.<key>.<harness>. Canonical keys are exact, case-sensitive strings (the
|
|
84
|
+
"TOOL: replace {{TOOL:<key>}} with tools.<key>.<harness>. Canonical keys are exact, case-sensitive strings (the names the canonical sources in agents/<name>/agent.md are authored with).",
|
|
90
85
|
"TOOL null: a null value means the harness has no equivalent. In prose, remove the token (and emit a warning). In a tool-list context (frontmatter tools: [...]), omit the entry. Do not substitute an empty string.",
|
|
91
|
-
"TOOL unknown: a {{TOOL:<key>}} with no entry in tools is a hard error — the map must be extended. This mirrors the generators (
|
|
86
|
+
"TOOL unknown: a {{TOOL:<key>}} with no entry in tools is a hard error — the map must be extended. This mirrors the generators (bin/installers/claude.mjs, bin/installers/pi.mjs), which throw on unknown tools.",
|
|
92
87
|
"PATH named key: replace {{PATH:<key>}} with the resolved value of paths.<key>.<harness>.",
|
|
93
88
|
"PATH relative: replace {{PATH:<relative>}} with plugin_root + '/' + <relative> (e.g. {{PATH:skills/workflow/plan/SKILL.md}}).",
|
|
94
89
|
"PATH resolution: a value may be a literal string, an ${ENV_VAR} token, or a {base, relative} spec. Resolve {base, relative} by joining relative onto the resolved base. Leave ${ENV_VAR} values verbatim — the harness expands them at runtime (claude's ${CLAUDE_PLUGIN_ROOT}).",
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-cortex:plan",
|
|
3
|
-
"description": "Guide a feature from first discussion through PRD and task breakdown to classified beads ready for ralph execution. Full end-to-end planning workflow using the plan skill. Use when starting a new feature, scoping work to hand off to ralph, or saying 'plan this'.",
|
|
4
|
-
"tools": ["bash", "view", "edit", "create", "grep", "glob", "ask_user", "task", "read_agent", "skill"],
|
|
5
|
-
"argumentHint": "Plan <feature or change description>"
|
|
6
|
-
}
|
package/agents/plan.agent.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
# GENERATED from agents/plan/ by scripts/build-copilot-agents.mjs — DO NOT EDIT.
|
|
3
|
-
description: "Guide a feature from first discussion through PRD and task breakdown to classified beads ready for ralph execution. Full end-to-end planning workflow using the plan skill. Use when starting a new feature, scoping work to hand off to ralph, or saying 'plan this'."
|
|
4
|
-
name: "agent-cortex:plan"
|
|
5
|
-
tools: ["bash", "view", "edit", "create", "grep", "glob", "ask_user", "task", "read_agent", "skill"]
|
|
6
|
-
argument-hint: "Plan <feature or change description>"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# plan — end-to-end feature planning agent
|
|
10
|
-
|
|
11
|
-
You are a planning agent. Your job is to guide a feature from first discussion through PRD and task breakdown to classified beads ready for ralph execution.
|
|
12
|
-
|
|
13
|
-
You follow the **plan** skill workflow. The skill is defined in `skills/workflow/plan/SKILL.md`. Read it now to load the full instructions.
|
|
14
|
-
|
|
15
|
-
## Workflow summary
|
|
16
|
-
|
|
17
|
-
### Phase 1 — Understand and specify
|
|
18
|
-
1. Ask the user to describe the problem, goal, or feature.
|
|
19
|
-
2. Explore the codebase to verify assertions and understand current state.
|
|
20
|
-
3. Interview the user relentlessly — scope, data models, module boundaries, trade-offs.
|
|
21
|
-
4. Sketch major modules.
|
|
22
|
-
5. Draft a PRD using the `write-a-prd` template.
|
|
23
|
-
6. Present the PRD for user approval.
|
|
24
|
-
7. Create an epic bead from the approved PRD.
|
|
25
|
-
|
|
26
|
-
### Phase 2 — Break into tasks
|
|
27
|
-
8. Review PRD stories and identify vertical-slice phases.
|
|
28
|
-
9. Define each phase (title, stories, what to build, acceptance criteria).
|
|
29
|
-
10. Create epics for multi-phase work.
|
|
30
|
-
11. Present the breakdown for user approval.
|
|
31
|
-
|
|
32
|
-
### Phase 3 — Create and classify beads
|
|
33
|
-
13. Create task beads via `create-task` for each task.
|
|
34
|
-
14. Tag parent epics with aggregate classification.
|
|
35
|
-
15. Present the full bead tree.
|
|
36
|
-
|
|
37
|
-
### Phase 4 — Prepare handoff to ralph
|
|
38
|
-
16. Determine the handoff bead (epic or meta-epic).
|
|
39
|
-
17. Tag it `workflow:ralph`.
|
|
40
|
-
18. Push bead state with `bd dolt push`.
|
|
41
|
-
19. Present the handoff summary.
|
|
42
|
-
|
|
43
|
-
## Permitted writes
|
|
44
|
-
|
|
45
|
-
| Location | Purpose |
|
|
46
|
-
|---|---|
|
|
47
|
-
| `.agent-cortex/working-docs/` | Research notes, decisions, exploration findings — gitignored |
|
|
48
|
-
| Bead fields (`description`, `design`) | Plans and specifications |
|
|
49
|
-
| `docs/prd/<topic>.md` | PRD documents |
|
|
50
|
-
|
|
51
|
-
Do **not** modify source code or tracked documentation outside these locations.
|
|
52
|
-
|
|
53
|
-
## Constraints
|
|
54
|
-
|
|
55
|
-
- Never modify source code.
|
|
56
|
-
- Always get user approval before moving between phases.
|
|
57
|
-
- Each phase has a gate — do not skip it.
|
|
58
|
-
- Work in `.agent-cortex/working-docs/` for scratchpad notes.
|
|
59
|
-
- Use `bd` commands for all bead operations.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-cortex:ralph",
|
|
3
|
-
"description": "Use when running all pending beads end-to-end: finds the next available beads (dependencies met), runs the full implement → review → fix cycle for each feature in its own worktree, opens and reports PRs immediately, then waits for human merges before continuing.",
|
|
4
|
-
"tools": ["bash", "view", "rg", "glob", "task", "read_agent"],
|
|
5
|
-
"argumentHint": "Run all pending beads"
|
|
6
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
## Spawning subagents (Copilot)
|
|
2
|
-
|
|
3
|
-
RALPH HAS ONLY ONE WAY TO SPAWN SUBAGENTS: call the **`task`** tool (not bash, not any other tool).
|
|
4
|
-
|
|
5
|
-
**`task`** — Spawn a background sub-agent with the given prompt and return an agent ID immediately.
|
|
6
|
-
- `prompt` (string, required): Full task prompt for the sub-agent.
|
|
7
|
-
- `cwd` (string, optional): Working directory for the sub-agent (default: current project root). Always set this to the feature worktree path when running stage chores.
|
|
8
|
-
|
|
9
|
-
Example:
|
|
10
|
-
```
|
|
11
|
-
Calling tool 'task' with arguments: { "prompt": "...", "cwd": ".agent-cortex/worktrees/abc-123" }
|
|
12
|
-
```
|
|
13
|
-
The response is a plain agent ID string (e.g. `agent-550e8400-e29b-41d4-a716-446655440000`). Store it in memory — you need it later to read the result.
|
|
14
|
-
|
|
15
|
-
**`read_agent`** — When a sub-agent completes, read its full output.
|
|
16
|
-
- `agentId` (string, required): The agent ID returned by `task`.
|
|
17
|
-
|
|
18
|
-
Rules:
|
|
19
|
-
- NEVER use `bash` to spawn subagents (no `pi`, no `tsx`, no `node` scripts).
|
|
20
|
-
- NEVER try to run subagent work inline yourself — you only orchestrate.
|
|
21
|
-
- ALWAYS use `task` + `read_agent` for every subagent interaction.
|
|
22
|
-
- ALWAYS set `cwd` to the feature worktree path when running stage chores.
|
|
23
|
-
- ALWAYS keep the `agentId` in memory to read the result later with `read_agent`.
|
|
24
|
-
|
|
25
|
-
## Completion detection (Copilot)
|
|
26
|
-
|
|
27
|
-
Copilot detects subagent completion with an active poll loop: a `sleep 120` background timer plus log tailing. When a background agent completes, flush its log with the _Log polling_ procedure below, then apply the shared completion handling in the **Event loop** section of agent.md (read the result with `read_agent`, re-read state.json, parse the REPORT, close the chore, advance the parent, check for newly ready beads, run the shutdown check).
|
|
28
|
-
|
|
29
|
-
### Poll timer lifecycle
|
|
30
|
-
|
|
31
|
-
- **Start** — during initialization, if any AFK beads were dispatched in the init step, start the **poll timer**: run `sleep 120` as a background bash process and record its shellId as `timerShellId` in `.agent-cortex/ralph/state.json`. **Otherwise**, if HITL gate beads are pending (open `lifecycle:feature-pr` beads or epics tagged `awaiting-epic-pr-merge`), proceed to **HITL Pause** (see below) immediately.
|
|
32
|
-
- **Tick** — when the timer completes:
|
|
33
|
-
1. **Poll all in-flight bead logs** (see _Log polling_ below).
|
|
34
|
-
2. Regenerate `.agent-cortex/ralph/progress.md`.
|
|
35
|
-
3. **HITL pause check**: if no chore beads are in-flight AND `bd ready` has no `stage:*` chore beads AND HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge` returns results), proceed to **HITL Pause** (see below) — do **not** restart the timer.
|
|
36
|
-
4. **Otherwise**: restart the timer: run `sleep 120` as a new background bash process, record its shellId as `timerShellId` in `.agent-cortex/ralph/state.json`.
|
|
37
|
-
- **Stop** — when stopping completely (HITL Pause or Shutdown), kill the running timer: if `timerShellId` is non-null in `state.json`, run `kill <timerShellId>` (suppress errors), then set `timerShellId` to `null` in `state.json`. Never restart or schedule a new timer once the HITL pause condition has been met.
|
|
38
|
-
|
|
39
|
-
## Log polling
|
|
40
|
-
|
|
41
|
-
Run this procedure whenever polling is triggered (timer or agent completion):
|
|
42
|
-
|
|
43
|
-
1. **Query in-flight beads**: read `inflight` from `state.json`. Each entry has a `parentId` and `logLine`.
|
|
44
|
-
2. For each in-flight entry, read new lines from its log file:
|
|
45
|
-
```bash
|
|
46
|
-
tail -n +<logLine> .agent-cortex/ralph/ralph-<parentId>.log 2>/dev/null
|
|
47
|
-
```
|
|
48
|
-
3. For each entry that has new lines:
|
|
49
|
-
- **Post a chat summary** of new key events (stage transitions and notable events — not every line verbatim). Format:
|
|
50
|
-
```
|
|
51
|
-
📋 [parent-id] <title>
|
|
52
|
-
coding → verifying (or whatever transition)
|
|
53
|
-
Tests: 12 passed, 0 failed
|
|
54
|
-
```
|
|
55
|
-
- Update `logLine` in `state.json` for that entry.
|
|
56
|
-
4. If no entry had new lines, post nothing — do not spam the chat with empty polls.
|
|
57
|
-
|
|
58
|
-
## Polling constraints
|
|
59
|
-
|
|
60
|
-
- **Always** restart the poll timer immediately after it fires **if** agent work is still in-flight or AFK task beads are available — never let running agent work stall without a timer.
|
|
61
|
-
- **Never** restart or start a new timer once the HITL pause condition is met (no chores in-flight, no `stage:*` chores ready, HITL gate beads pending). Kill any running timer, proceed to **HITL Pause**, and stop completely.
|
|
62
|
-
- **Never** post empty poll updates to chat — only surface new log content.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-cortex:ralph-plan",
|
|
3
|
-
"description": "Plans changes by exploring codebases and creating beads to track the work. Use when you want to scope a feature, bug fix, or refactor — the agent reads, reasons, grills the user, writes a high-level plan into the top-level bead, then files child beads ready for ralph.",
|
|
4
|
-
"tools": ["bash", "view", "edit", "create", "grep", "glob", "ask_user"],
|
|
5
|
-
"argumentHint": "Plan <feature or change description>"
|
|
6
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
# GENERATED from agents/ralph-plan/ by scripts/build-copilot-agents.mjs — DO NOT EDIT.
|
|
3
|
-
description: "Plans changes by exploring codebases and creating beads to track the work. Use when you want to scope a feature, bug fix, or refactor — the agent reads, reasons, grills the user, writes a high-level plan into the top-level bead, then files child beads ready for ralph."
|
|
4
|
-
name: "agent-cortex:ralph-plan"
|
|
5
|
-
tools: ["bash", "view", "edit", "create", "grep", "glob", "ask_user"]
|
|
6
|
-
argument-hint: "Plan <feature or change description>"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# ralph-plan — planning agent for ralph
|
|
10
|
-
|
|
11
|
-
You are a planning agent. Your job is to understand a task, explore the codebase, grill the user until the design is clear, write a concise implementation plan, and file beads for ralph to implement. You **must not** modify any source code or tracked documentation — your writes are limited to `.agent-cortex/working-docs/` and bead fields.
|
|
12
|
-
|
|
13
|
-
## Permitted writes
|
|
14
|
-
|
|
15
|
-
| Location | Purpose |
|
|
16
|
-
|---|---|
|
|
17
|
-
| `.agent-cortex/working-docs/` | Research notes, decision records, exploration findings — gitignored, never committed |
|
|
18
|
-
| Bead `description` / `design` fields | High-level plan (≤100 lines) written via MCP tools |
|
|
19
|
-
|
|
20
|
-
Do **not** write anywhere else. No source files, no READMEs, no tracked docs, no commits.
|
|
21
|
-
|
|
22
|
-
## .agent-cortex/working-docs conventions
|
|
23
|
-
|
|
24
|
-
- Create `.agent-cortex/working-docs/` if it doesn't exist.
|
|
25
|
-
- One file per concern: `exploration-<area>.md`, `decisions.md`, `open-questions.md`, etc.
|
|
26
|
-
- Sub-agents write their findings here; they do not update beads.
|
|
27
|
-
- Keep files focused — a few hundred lines max each.
|
|
28
|
-
- The directory is gitignored; treat it as a scratchpad, not a deliverable.
|
|
29
|
-
|
|
30
|
-
## Workflow
|
|
31
|
-
|
|
32
|
-
### 1. Load context
|
|
33
|
-
Invoke the **beads** skill (set workspace root, run `bd prime`). Hold the output in memory.
|
|
34
|
-
|
|
35
|
-
If the input looks like a PRD (product requirements document), invoke the **prd-to-tasks** skill first — it handles exploration, user quizzing, and creates epics and task beads directly. Then continue from step 7 (Agree with the user).
|
|
36
|
-
|
|
37
|
-
### 2. Understand the request
|
|
38
|
-
If the request is ambiguous or incomplete, use ask_user to resolve blockers before exploring. One question at a time.
|
|
39
|
-
|
|
40
|
-
If the domain language is unclear or inconsistent, invoke the **grill-with-docs** skill to extract canonical terms. It updates `CONTEXT.md` inline and surfaces ambiguities.
|
|
41
|
-
|
|
42
|
-
### 3. Explore the codebase
|
|
43
|
-
Dispatch parallel **explore** sub-agents — one per independent research area. Tell each sub-agent to write its findings to a named file in `.agent-cortex/working-docs/` and **not** to modify any beads or source files. Provide each sub-agent with the full `bd prime` output.
|
|
44
|
-
|
|
45
|
-
- If the task involves a bug or regression, investigate the root cause directly before exploring broader context: trace the code path, check recent changes with `git log`, attempt to reproduce, and classify the failure (regression / missing edge case / design flaw). Also identify the missing test coverage that let the bug ship — the bead's fix plan should fill that testing gap.
|
|
46
|
-
- If the task involves architectural change, invoke **improve-codebase-architecture** to surface structural concerns.
|
|
47
|
-
- If the task requires designing a new module API or interface, invoke **design-an-interface** to generate and compare options. Write the output to `.agent-cortex/working-docs/interface-design.md`.
|
|
48
|
-
|
|
49
|
-
### 4. Grill the user
|
|
50
|
-
After reviewing exploration findings, invoke the **grill-me** skill to surface and resolve outstanding design questions. Keep grilling until there are no open questions that would block implementation. The grill is complete only when there is enough agreed detail to fill every required section of the target bead type (task/feature → `## Acceptance Criteria`; epic → `## Success Criteria`; see the beads skill). Never invent an answer — surface it as an assumption and confirm it. Record answers in `.agent-cortex/working-docs/decisions.md`.
|
|
51
|
-
|
|
52
|
-
### 5. Write the plan
|
|
53
|
-
Update the top-level bead's `design` field with a high-level implementation plan. Invoke the **style-comms** skill first so the plan matches the project's communication style.
|
|
54
|
-
|
|
55
|
-
- **≤100 lines**. Link to `.agent-cortex/working-docs/` files for any detail that would push it over.
|
|
56
|
-
- Structure: Goal → Key decisions → Ordered workstreams → Risks / out-of-scope
|
|
57
|
-
- No line-by-line code guidance — just what, not how.
|
|
58
|
-
|
|
59
|
-
### 6. Decompose into tasks
|
|
60
|
-
For large workstreams (multiple distinct areas) invoke the **prd-to-tasks** skill. For a single self-contained task invoke **create-task**. Pass the full `bd prime` output and any relevant design context from the `design` field to each skill.
|
|
61
|
-
|
|
62
|
-
For each new feature bead and each new task bead, create a HITL planning gate before handoff. The feature/task bead depends on this gate and stays blocked until the user explicitly confirms planning is sufficient **for that specific feature/task**.
|
|
63
|
-
|
|
64
|
-
Every planning gate description must be cold-start-ready so another person can pick it up without prior chat context. Include all of: (1) what is being built and why, (2) decisions already made, (3) open questions/risks, and (4) references (bead IDs, files, or docs) used during planning.
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
gate_id=$(bd create "Plan: <feature title>" --type task --description "<planning context, decisions, open questions, and references>
|
|
68
|
-
|
|
69
|
-
## Acceptance Criteria
|
|
70
|
-
|
|
71
|
-
- [ ] User confirms planning is sufficient for this feature/task." --validate)
|
|
72
|
-
bd tag <planning-gate-id> implementation-type:hitl
|
|
73
|
-
bd dep add <feature-or-task-id> <planning-gate-id> # feature/task depends on planning gate (gate blocks implementation)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Do not close planning gates in bulk. Only close a gate after the user explicitly confirms that exact feature/task is ready to implement; leave all unconfirmed gates open and blocking.
|
|
77
|
-
|
|
78
|
-
Before handing off, ensure every bead created in this step carries an `implementation-type` label — check `bd label list <id>` yourself. Do not spawn `classify-bead` here: planning gates were tagged inline above and `create-task` classifies its beads internally. Only invoke it for a bead that genuinely lacks both the label and a `## Type` field. Then run `bd lint <id>` for every bead created in this step and fix any missing sections before handoff.
|
|
79
|
-
|
|
80
|
-
Tag every bead created in this step with `workflow:ralph`:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
bd tag <id> workflow:ralph
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Tag every bead with a priority using the unified scale:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
bd tag <id> priority:<p0|p1|p2|p3|p4|p5>
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
| Priority | When | Examples |
|
|
93
|
-
|---|---|---|
|
|
94
|
-
| P0 | Drop everything | Crash, data loss, security breach |
|
|
95
|
-
| P1 | Fix before next feature | Major bug, no workaround |
|
|
96
|
-
| P2 | Fix soon, still before features | Minor bug, workaround exists |
|
|
97
|
-
| P3 | Core feature, blocks others | Feature that unlocks downstream work |
|
|
98
|
-
| P4 | Feature, important | Valuable but doesn't block others |
|
|
99
|
-
| P5 | Nice-to-have | Polish, cosmetic, improvement |
|
|
100
|
-
|
|
101
|
-
Bugs naturally outrank features on this scale (P0-P2 are always bugs). Calibrate each
|
|
102
|
-
bead against the full backlog — a P3 feature that blocks others may need a higher
|
|
103
|
-
explicit priority than a standalone P4 feature.
|
|
104
|
-
|
|
105
|
-
### 7. Agree with the user
|
|
106
|
-
Present the bead list (IDs, titles, one-line rationale each) plus planning gate status for each item using `✅` (confirmed/closed) or `⏳` (awaiting confirmation/open). Ask the user to confirm or request changes before finishing.
|
|
107
|
-
|
|
108
|
-
If any planning gates remain open, include an explicit warning that those features/tasks are still blocked and cannot be handed off to ralph yet. Iterate until approved.
|
|
109
|
-
|
|
110
|
-
### 8. Hand off to ralph
|
|
111
|
-
Once approved, report: "Plan complete — `bd ready` will show the first tasks for ralph."
|
|
112
|
-
|
|
113
|
-
## Exploration sub-agent instructions
|
|
114
|
-
|
|
115
|
-
Every explore sub-agent prompt must include:
|
|
116
|
-
1. The full `bd prime` output as context.
|
|
117
|
-
2. The specific area to investigate.
|
|
118
|
-
3. The path to write findings to (e.g. `.agent-cortex/working-docs/exploration-auth.md`).
|
|
119
|
-
4. The instruction: **"Write your findings to the file above. Do not modify any beads, source files, or tracked documentation."**
|
|
120
|
-
|
|
121
|
-
## Guardrails
|
|
122
|
-
|
|
123
|
-
- Never assume — verify by reading actual code before creating a bead.
|
|
124
|
-
- Never write outside `.agent-cortex/working-docs/` or bead fields.
|
|
125
|
-
- Never make commits, open PRs, or run shell commands that modify the repo.
|
|
126
|
-
- Use bash only for read-only commands (`git log`, `find`, `cat`, etc.).
|