@jaybeeuu/agent-cortex 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +387 -0
- package/README.md +33 -13
- package/agents/README.md +22 -10
- package/agents/plan/agent.md +2 -2
- package/agents/ralph/agent.md +126 -88
- package/agents/ralph/claude/frontmatter.json +3 -3
- package/agents/ralph/claude/wake.md +46 -0
- package/agents/ralph/pi/{polling.md → wake.md} +35 -20
- package/agents/ralph-plan/agent.md +23 -11
- package/bin/agent-cortex.mjs +66 -4
- package/bin/installers/claude.mjs +182 -68
- package/bin/installers/pi.mjs +200 -24
- package/extensions/agent-guardrails/README.md +1 -1
- package/extensions/agent-guardrails/guardrails.ts +1 -1
- package/extensions/agent-guardrails/index.ts +1 -1
- package/extensions/agent-modes/discover.test.ts +2 -2
- package/hooks/claude/scripts/notify.mjs +8 -1
- package/lib/cli.mjs +91 -2
- package/package.json +27 -3
- package/scripts/check-changeset.mjs +4 -0
- package/scripts/check-no-sync.mjs +5 -1
- package/scripts/lib/compose-agent.mjs +69 -9
- package/scripts/lib/fs.mjs +10 -2
- package/scripts/lib/migrate.mjs +736 -0
- package/scripts/lib/release-gates.mjs +21 -1
- package/scripts/lib/skill-frontmatter.mjs +23 -6
- package/scripts/lib/skill-links.mjs +52 -0
- package/scripts/lib/verify-worker-tree.mjs +25 -0
- package/scripts/resolve-publish-command.mjs +4 -0
- package/skills/engineering/design-an-interface/SKILL.md +3 -3
- package/skills/engineering/grill-with-docs/SKILL.md +3 -5
- package/skills/engineering/improve-codebase-architecture/SKILL.md +5 -4
- package/skills/engineering/tdd/SKILL.md +5 -7
- package/skills/engineering/technical-direction/SKILL.md +5 -5
- package/skills/planning/classify-bead/REFERENCE.md +3 -3
- package/skills/planning/classify-bead/SKILL.md +14 -9
- package/skills/planning/classify-bead/scripts/classify-bead.mjs +5 -4
- package/skills/planning/create-task/REFERENCE.md +52 -3
- package/skills/planning/create-task/SKILL.md +70 -26
- package/skills/planning/create-task/scripts/{create-chores.ts → create-chores.mjs} +48 -23
- package/skills/planning/flesh-out-idea/REFERENCE.md +116 -0
- package/skills/planning/flesh-out-idea/SKILL.md +146 -0
- package/skills/planning/prd-to-tasks/REFERENCE.md +54 -5
- package/skills/planning/prd-to-tasks/SKILL.md +22 -16
- package/skills/planning/record-idea/FORMAT.md +66 -17
- package/skills/planning/record-idea/SKILL.md +48 -24
- package/skills/planning/request-refactor-plan/SKILL.md +4 -4
- package/skills/planning/spec-to-tickets/SKILL.md +5 -5
- package/skills/planning/write-a-prd/SKILL.md +8 -9
- package/skills/planning/write-a-ticket/SKILL.md +4 -6
- package/skills/productivity/bd-tool/SKILL.md +15 -10
- package/skills/productivity/grill-me/SKILL.md +5 -0
- package/skills/productivity/init-beads/SKILL.md +3 -3
- package/skills/productivity/migration/REFERENCE.md +227 -0
- package/skills/productivity/migration/SKILL.md +188 -0
- package/skills/productivity/validate-agent-dir/scripts/{validate-agent-dir.ts → validate-agent-dir.mjs} +49 -28
- package/skills/productivity/write-a-skill/SKILL.md +5 -5
- package/skills/review/maintain-agent-docs/SKILL.md +5 -7
- package/skills/review/refactor-skill/SKILL.md +4 -3
- package/skills/review/review-security/SKILL.md +3 -5
- package/skills/style/style-code/SKILL.md +5 -10
- package/skills/style/style-comms/SKILL.md +5 -7
- package/skills/style/style-documentation/SKILL.md +5 -6
- package/skills/style/style-tests/SKILL.md +5 -7
- package/skills/workflow/git-workflow/SKILL.md +28 -4
- package/skills/workflow/hitl-collab/SKILL.md +4 -6
- package/skills/workflow/plan/SKILL.md +41 -30
- package/skills/workflow/ralph/REFERENCE.md +182 -51
- package/skills/workflow/ralph/SKILL.md +89 -50
- package/skills/workflow/run-pipeline-stage/SKILL.md +72 -71
- package/skills/workflow/run-pipeline-stage/playbooks/code.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/document.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/fix.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/review.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/verify.md +13 -0
- package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +73 -1
- package/token-map.README.md +9 -4
- package/token-map.json +13 -6
- package/.agents/skills/style-versioning/SKILL.md +0 -172
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.github/workflows/ci.yml +0 -302
- package/.junie/guidelines.md +0 -87
- package/.junie/mcp/mcp.json +0 -10
- package/AGENTS.md +0 -153
- package/agents/ralph/claude/polling.md +0 -31
- package/agents-native/ralph.md +0 -203
- package/docs/claude-hooks.md +0 -144
- package/docs/commit-signing.md +0 -231
- package/docs/ideas/auto-model-selection.md +0 -75
- package/docs/ideas/ban-content-assertion-tests.md +0 -75
- package/docs/ideas/bead-progress-notes-for-session-resumption.md +0 -75
- package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +0 -70
- package/docs/ideas/ctx-alias-version-and-update-commands.md +0 -65
- package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +0 -67
- package/docs/ideas/dedicated-review-tests-skill.md +0 -71
- package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +0 -36
- package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +0 -99
- package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +0 -42
- package/docs/ideas/extension-manifests.md +0 -121
- package/docs/ideas/improve-pi-system-prompt.md +0 -43
- package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +0 -95
- package/docs/ideas/model-selector.md +0 -40
- package/docs/ideas/pi-task-memory.md +0 -34
- package/docs/ideas/qa-extension.md +0 -43
- package/docs/ideas/record-idea-implementation-questions.md +0 -68
- package/docs/ideas/record-ideas-as-beads.md +0 -115
- package/docs/ideas/self-flushing-session.md +0 -72
- package/docs/ideas/state-in-beads-not-md.md +0 -69
- package/docs/ideas/subagent-visibility.md +0 -72
- package/docs/ideas/task-session-context.local.md +0 -95
- package/docs/ideas/task-session-context.md +0 -89
- package/docs/ideas/test-data-creation-helpers.md +0 -92
- package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +0 -68
- package/docs/ideas/unified-ci-pipeline.md +0 -28
- package/docs/ideas/unify-the-ticket-and-task-decomposition-workflows.md +0 -71
- package/docs/ideas/worktree-housekeeping-for-closed-beads.md +0 -39
- package/docs/inspirations.md +0 -33
- package/docs/research/disable-model-invocation.md +0 -82
- package/docs/research/gas-city-research.md +0 -256
- package/docs/research/skill-design-research.md +0 -286
- package/docs/research/skill-improvements-analysis.md +0 -117
- package/docs/research/skill-patterns-research.md +0 -24
- package/docs/skills/skill-anatomy.md +0 -200
- package/docs/technical-direction/harness-config.md +0 -177
- package/docs/technical-direction/migration-execution-labels.md +0 -177
- package/docs/user-preferences.md +0 -17
- package/extensions/agent-guardrails/tsconfig.json +0 -12
- package/extensions/agent-modes/tsconfig.json +0 -12
- package/extensions/output-style/tsconfig.json +0 -12
- package/extensions/session-start/tsconfig.json +0 -12
- package/extensions/skill-stats/pnpm-lock.yaml +0 -329
- package/extensions/skill-stats/tsconfig.json +0 -12
- package/extensions/subagent/agents/planner.md +0 -37
- package/extensions/subagent/agents/reviewer.md +0 -35
- package/extensions/subagent/agents/scout.md +0 -50
- package/extensions/subagent/agents/worker.md +0 -24
- package/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/extensions/subagent/prompts/implement.md +0 -10
- package/extensions/subagent/prompts/scout-and-plan.md +0 -9
- package/extensions/subagent/tsconfig.json +0 -12
- package/pi/keybindings.json +0 -3
- package/pi/settings.json +0 -34
- package/pnpm-workspace.yaml +0 -14
- package/skills/planning/create-task/scripts/package.json +0 -14
- package/skills/planning/create-task/scripts/pnpm-lock.yaml +0 -342
- package/skills/planning/create-task/scripts/tsconfig.json +0 -12
- package/skills/planning/record-idea/scripts/new-idea.sh +0 -89
- package/skills/productivity/validate-agent-dir/scripts/package.json +0 -15
- package/skills/productivity/validate-agent-dir/scripts/pnpm-lock.yaml +0 -329
- package/skills/productivity/validate-agent-dir/scripts/pnpm-workspace.yaml +0 -2
- package/skills/productivity/validate-agent-dir/scripts/tsconfig.json +0 -19
- package/skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts +0 -317
- package/skills/workflow/run-pipeline-stage/REFERENCE.md +0 -22
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +0 -682
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.ts +0 -588
- package/skills/workflow/run-pipeline-stage/scripts/package.json +0 -15
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-lock.yaml +0 -342
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-workspace.yaml +0 -2
- package/skills/workflow/run-pipeline-stage/scripts/tsconfig.json +0 -12
- package/test/classify-bead.test.mjs +0 -277
- package/test/claude-installer.test.mjs +0 -308
- package/test/cli.test.mjs +0 -314
- package/test/create-chores.test.mjs +0 -85
- package/test/fake-bd.test.mjs +0 -72
- package/test/fs.test.mjs +0 -76
- package/test/helpers/fake-bd.mjs +0 -87
- package/test/helpers/fake-claude.mjs +0 -152
- package/test/helpers/fake-pi.mjs +0 -132
- package/test/installer.test.mjs +0 -806
- package/test/notify-hook.test.mjs +0 -63
- package/test/pending-gates.test.mjs +0 -147
- package/test/pi-installer.test.mjs +0 -785
- package/test/pi-register.test.mjs +0 -342
- package/test/pi-sweep.test.mjs +0 -619
- package/test/release-gates.test.mjs +0 -190
- package/test/skill-frontmatter.test.mjs +0 -137
- package/test/verify-worker-tree.test.mjs +0 -120
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
// Tests for the Claude Code Notification hook script (hooks/claude/scripts/notify.mjs).
|
|
2
|
-
// The script reads the Notification hook JSON payload from stdin and prints a
|
|
3
|
-
// `{ "terminalSequence": "..." }` JSON response that Claude Code emits for us
|
|
4
|
-
// (hooks run without a controlling terminal, so OSC sequences must go through
|
|
5
|
-
// terminalSequence — see the Claude Code hooks reference).
|
|
6
|
-
|
|
7
|
-
import { describe, it } from "node:test";
|
|
8
|
-
import assert from "node:assert/strict";
|
|
9
|
-
import { execFile } from "node:child_process";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { dirname, join } from "node:path";
|
|
12
|
-
|
|
13
|
-
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
-
const SCRIPT = join(ROOT, "hooks", "claude", "scripts", "notify.mjs");
|
|
15
|
-
|
|
16
|
-
/** Run the hook script with the given payload on stdin and a controlled env. */
|
|
17
|
-
function runNotify(payload, env = {}) {
|
|
18
|
-
return new Promise((resolve) => {
|
|
19
|
-
const child = execFile(
|
|
20
|
-
process.execPath,
|
|
21
|
-
[SCRIPT],
|
|
22
|
-
{ env, timeout: 10_000 },
|
|
23
|
-
(error, stdout, stderr) => {
|
|
24
|
-
resolve({ exitCode: error ? error.code ?? 1 : 0, stdout, stderr });
|
|
25
|
-
},
|
|
26
|
-
);
|
|
27
|
-
child.stdin.end(JSON.stringify(payload));
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
describe("notify.mjs (Claude Notification hook)", () => {
|
|
32
|
-
it("emits an OSC 777 desktop notification on a bare-terminal agent_completed payload", async () => {
|
|
33
|
-
const { exitCode, stdout } = await runNotify(
|
|
34
|
-
{ notification_type: "agent_completed", title: "task done", message: "all tests pass" },
|
|
35
|
-
{ PATH: process.env.PATH },
|
|
36
|
-
);
|
|
37
|
-
assert.equal(exitCode, 0);
|
|
38
|
-
const out = JSON.parse(stdout);
|
|
39
|
-
assert.ok(out.terminalSequence.startsWith("\u001b]777;notify;"));
|
|
40
|
-
assert.match(out.terminalSequence, /task done/);
|
|
41
|
-
assert.match(out.terminalSequence, /all tests pass/);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("switches to OSC 99 when running inside Kitty", async () => {
|
|
45
|
-
const { exitCode, stdout } = await runNotify(
|
|
46
|
-
{ notification_type: "agent_needs_input", title: "input needed", message: "build broke" },
|
|
47
|
-
{ PATH: process.env.PATH, KITTY_WINDOW_ID: "0" },
|
|
48
|
-
);
|
|
49
|
-
assert.equal(exitCode, 0);
|
|
50
|
-
const out = JSON.parse(stdout);
|
|
51
|
-
assert.ok(out.terminalSequence.startsWith("\u001b]99;"));
|
|
52
|
-
assert.match(out.terminalSequence, /build broke/);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("stays silent (no output, exit 0) when the payload has no message", async () => {
|
|
56
|
-
const { exitCode, stdout } = await runNotify(
|
|
57
|
-
{ notification_type: "permission_prompt" },
|
|
58
|
-
{ PATH: process.env.PATH },
|
|
59
|
-
);
|
|
60
|
-
assert.equal(exitCode, 0);
|
|
61
|
-
assert.equal(stdout, "");
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
EPIC_GATE_LABEL,
|
|
6
|
-
FEATURE_GATE_LABEL,
|
|
7
|
-
HITL_GATE_LABELS,
|
|
8
|
-
fetchGateState,
|
|
9
|
-
resolveGateState,
|
|
10
|
-
runCli,
|
|
11
|
-
} from '../skills/workflow/ralph/scripts/pending-gates.mjs';
|
|
12
|
-
|
|
13
|
-
function createBead({ id, title = `${id} title` }) {
|
|
14
|
-
return { id, title };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Fake `bd` for the query-contract tests: answers the three queries ralph makes
|
|
19
|
-
* and refuses anything else, so an unexpected query fails loudly.
|
|
20
|
-
*/
|
|
21
|
-
function makeExec({ ready = [], open = [], epics = [] } = {}) {
|
|
22
|
-
const calls = [];
|
|
23
|
-
|
|
24
|
-
const exec = async (args) => {
|
|
25
|
-
calls.push(args);
|
|
26
|
-
if (args[0] === 'ready') return JSON.stringify(ready);
|
|
27
|
-
if (args[0] === 'list' && args.includes(EPIC_GATE_LABEL)) return JSON.stringify(epics);
|
|
28
|
-
if (args[0] === 'list') return JSON.stringify(open);
|
|
29
|
-
throw new Error(`unexpected bd call: ${args.join(' ')}`);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return { exec, calls };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function capture() {
|
|
36
|
-
let output = '';
|
|
37
|
-
return { write: (chunk) => { output += chunk; }, read: () => JSON.parse(output) };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
describe('resolveGateState', () => {
|
|
41
|
-
it('leaves dispatch unblocked while every gate is still parked behind its own pipeline', () => {
|
|
42
|
-
const state = resolveGateState({
|
|
43
|
-
readyGates: [],
|
|
44
|
-
openGates: [
|
|
45
|
-
createBead({ id: 'proj-1.5' }),
|
|
46
|
-
createBead({ id: 'proj-2.5' }),
|
|
47
|
-
createBead({ id: 'proj-3.5' }),
|
|
48
|
-
createBead({ id: 'proj-4.5' }),
|
|
49
|
-
],
|
|
50
|
-
epicsAwaitingMerge: [],
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
assert.deepEqual(state.pendingHumanAction, []);
|
|
54
|
-
assert.deepEqual(state.parked, [
|
|
55
|
-
{ id: 'proj-1.5', title: 'proj-1.5 title' },
|
|
56
|
-
{ id: 'proj-2.5', title: 'proj-2.5 title' },
|
|
57
|
-
{ id: 'proj-3.5', title: 'proj-3.5 title' },
|
|
58
|
-
{ id: 'proj-4.5', title: 'proj-4.5 title' },
|
|
59
|
-
]);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('reports an unblocked gate as pending human action', () => {
|
|
63
|
-
const state = resolveGateState({
|
|
64
|
-
readyGates: [createBead({ id: 'proj-1.5', title: 'PR Review and Merge' })],
|
|
65
|
-
openGates: [createBead({ id: 'proj-1.5', title: 'PR Review and Merge' })],
|
|
66
|
-
epicsAwaitingMerge: [],
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
assert.deepEqual(state.pendingHumanAction, [
|
|
70
|
-
{ id: 'proj-1.5', title: 'PR Review and Merge', kind: 'feature-pr' },
|
|
71
|
-
]);
|
|
72
|
-
assert.deepEqual(state.parked, []);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('separates an unblocked gate from gates that are still parked', () => {
|
|
76
|
-
const state = resolveGateState({
|
|
77
|
-
readyGates: [createBead({ id: 'proj-1.5' })],
|
|
78
|
-
openGates: [createBead({ id: 'proj-1.5' }), createBead({ id: 'proj-2.5' })],
|
|
79
|
-
epicsAwaitingMerge: [],
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
assert.deepEqual(state.pendingHumanAction.map((gate) => gate.id), ['proj-1.5']);
|
|
83
|
-
assert.deepEqual(state.parked.map((gate) => gate.id), ['proj-2.5']);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('reports an epic awaiting merge as pending human action alongside feature gates', () => {
|
|
87
|
-
const state = resolveGateState({
|
|
88
|
-
readyGates: [],
|
|
89
|
-
openGates: [],
|
|
90
|
-
epicsAwaitingMerge: [createBead({ id: 'epic-9', title: 'Merge epic into main' })],
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
assert.deepEqual(state.pendingHumanAction, [
|
|
94
|
-
{ id: 'epic-9', title: 'Merge epic into main', kind: 'epic-pr' },
|
|
95
|
-
]);
|
|
96
|
-
assert.deepEqual(state.parked, []);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe('fetchGateState', () => {
|
|
101
|
-
it('asks bd for unblocked gates, all gates, and epics awaiting merge on either HITL axis', async () => {
|
|
102
|
-
const { exec, calls } = makeExec();
|
|
103
|
-
|
|
104
|
-
await fetchGateState({ exec });
|
|
105
|
-
|
|
106
|
-
assert.deepEqual(calls, [
|
|
107
|
-
['ready', '--json', '-l', FEATURE_GATE_LABEL, '--label-any', HITL_GATE_LABELS.join(',')],
|
|
108
|
-
['list', '--json', '--limit', '0', '-l', FEATURE_GATE_LABEL, '--label-any', HITL_GATE_LABELS.join(',')],
|
|
109
|
-
['list', '--json', '--limit', '0', '-l', EPIC_GATE_LABEL],
|
|
110
|
-
]);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('covers both the current and the legacy HITL label axis', () => {
|
|
114
|
-
assert.deepEqual(HITL_GATE_LABELS, ['execution:hitl', 'implementation-type:hitl']);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('treats a gate that only the list query returns as parked', async () => {
|
|
118
|
-
const { exec } = makeExec({ ready: [], open: [createBead({ id: 'proj-1.5' })] });
|
|
119
|
-
|
|
120
|
-
const state = await fetchGateState({ exec });
|
|
121
|
-
|
|
122
|
-
assert.deepEqual(state.pendingHumanAction, []);
|
|
123
|
-
assert.deepEqual(state.parked, [{ id: 'proj-1.5', title: 'proj-1.5 title' }]);
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
describe('pending-gates CLI', () => {
|
|
128
|
-
it('prints the resolved gate state as JSON', async () => {
|
|
129
|
-
const { exec } = makeExec({
|
|
130
|
-
ready: [createBead({ id: 'proj-1.5' })],
|
|
131
|
-
open: [createBead({ id: 'proj-1.5' }), createBead({ id: 'proj-2.5' })],
|
|
132
|
-
epics: [createBead({ id: 'epic-9' })],
|
|
133
|
-
});
|
|
134
|
-
const out = capture();
|
|
135
|
-
|
|
136
|
-
const code = await runCli({ argv: [], exec, write: out.write });
|
|
137
|
-
|
|
138
|
-
assert.equal(code, 0);
|
|
139
|
-
assert.deepEqual(out.read(), {
|
|
140
|
-
pendingHumanAction: [
|
|
141
|
-
{ id: 'proj-1.5', title: 'proj-1.5 title', kind: 'feature-pr' },
|
|
142
|
-
{ id: 'epic-9', title: 'epic-9 title', kind: 'epic-pr' },
|
|
143
|
-
],
|
|
144
|
-
parked: [{ id: 'proj-2.5', title: 'proj-2.5 title' }],
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|