@jaybeeuu/agent-cortex 2.1.0 → 2.3.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 +411 -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/extensions/output-style/README.md +1 -1
- package/extensions/output-style/index.ts +2 -2
- package/extensions/output-style/output-style.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 +52 -26
- 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,342 +0,0 @@
|
|
|
1
|
-
// Tests for the pi package registration step of `agent-cortex install pi`:
|
|
2
|
-
// once the package is staged, the plain install registers the staged directory
|
|
3
|
-
// with pi by driving pi's own `pi install` / `pi remove` commands, so pi loads
|
|
4
|
-
// agents, skills, and extensions from ~/.agent-cortex/pi instead of from a raw
|
|
5
|
-
// repo checkout. Registration is idempotent by STATE (pi's configured package
|
|
6
|
-
// sources decide install-vs-no-op) and drops any stale raw-repo source so there
|
|
7
|
-
// is exactly one agent-cortex source.
|
|
8
|
-
//
|
|
9
|
-
// The real `pi` CLI is a genuine external system (and its user settings must
|
|
10
|
-
// never be touched), so these tests drive the stateful fake from
|
|
11
|
-
// test/helpers/fake-pi.mjs against a throwaway directory tree.
|
|
12
|
-
|
|
13
|
-
import { describe, it } from "node:test";
|
|
14
|
-
import assert from "node:assert/strict";
|
|
15
|
-
import { execFile } from "node:child_process";
|
|
16
|
-
import { mkdtemp, mkdir, writeFile, rm, readFile, stat } from "node:fs/promises";
|
|
17
|
-
import { tmpdir } from "node:os";
|
|
18
|
-
import { dirname, join } from "node:path";
|
|
19
|
-
import { fileURLToPath } from "node:url";
|
|
20
|
-
import { registerPi } from "../bin/installers/pi.mjs";
|
|
21
|
-
import { makeFakePi } from "./helpers/fake-pi.mjs";
|
|
22
|
-
|
|
23
|
-
const CLI_PATH = join(dirname(fileURLToPath(import.meta.url)), "..", "bin", "agent-cortex.mjs");
|
|
24
|
-
|
|
25
|
-
// The name of this repo's published package — the identity that marks a
|
|
26
|
-
// configured local source as a raw agent-cortex checkout (the staged package is
|
|
27
|
-
// named @jaybeeuu/agent-cortex-pi).
|
|
28
|
-
const RAW_PACKAGE_NAME = "@jaybeeuu/agent-cortex";
|
|
29
|
-
|
|
30
|
-
function runCli(args, env = {}) {
|
|
31
|
-
return new Promise((resolve) => {
|
|
32
|
-
execFile(
|
|
33
|
-
process.execPath,
|
|
34
|
-
[CLI_PATH, ...args],
|
|
35
|
-
{ env: { ...process.env, ...env } },
|
|
36
|
-
(error, stdout, stderr) => resolve({ exitCode: error ? (error.code ?? 1) : 0, stdout, stderr }),
|
|
37
|
-
);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function pathExists(p) {
|
|
42
|
-
try {
|
|
43
|
-
await stat(p);
|
|
44
|
-
return true;
|
|
45
|
-
} catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* A throwaway install tree: the repo root that owns the raw package name, a
|
|
52
|
-
* raw-repo checkout (a worktree of it) configured as a pi package source, a
|
|
53
|
-
* fake pi (whose own directory is pi's settings dir), and the staged output.
|
|
54
|
-
*/
|
|
55
|
-
async function makeInstallTree() {
|
|
56
|
-
const root = await mkdtemp(join(tmpdir(), "pi-register-"));
|
|
57
|
-
const rawRepo = join(root, "checkout");
|
|
58
|
-
const staged = join(root, "out");
|
|
59
|
-
|
|
60
|
-
await writeFile(join(root, "package.json"), JSON.stringify({ name: RAW_PACKAGE_NAME, version: "1.42.0" }));
|
|
61
|
-
await mkdir(rawRepo, { recursive: true });
|
|
62
|
-
await writeFile(join(rawRepo, "package.json"), JSON.stringify({ name: RAW_PACKAGE_NAME, version: "1.42.0" }));
|
|
63
|
-
await mkdir(staged, { recursive: true });
|
|
64
|
-
await writeFile(join(staged, "package.json"), JSON.stringify({ name: "@jaybeeuu/agent-cortex-pi", private: true }));
|
|
65
|
-
|
|
66
|
-
const piDir = join(root, "pi");
|
|
67
|
-
await mkdir(piDir, { recursive: true });
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
root,
|
|
71
|
-
rawRepo,
|
|
72
|
-
staged,
|
|
73
|
-
piDir,
|
|
74
|
-
cleanup: () => rm(root, { recursive: true, force: true }),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Start the fake `pi` for a tree, seeding pi's configured package sources. */
|
|
79
|
-
async function makePi(tree, { packages = [], failWhen = null } = {}) {
|
|
80
|
-
const pi = await makeFakePi(tree.piDir, { packages, failWhen });
|
|
81
|
-
return {
|
|
82
|
-
...tree,
|
|
83
|
-
pi,
|
|
84
|
-
/** Settings path handed to registerPi (the fake's own settings file). */
|
|
85
|
-
settingsPath: pi.settingsPath,
|
|
86
|
-
/** Absolute paths of the local package sources pi has configured. */
|
|
87
|
-
localSources: async () => {
|
|
88
|
-
const { packages: configured = [] } = JSON.parse(await readFile(pi.settingsPath, "utf-8"));
|
|
89
|
-
return configured
|
|
90
|
-
.map((entry) => (typeof entry === "string" ? entry : entry.source))
|
|
91
|
-
.filter((source) => !source.startsWith("npm:"))
|
|
92
|
-
.map((source) => join(dirname(pi.settingsPath), source));
|
|
93
|
-
},
|
|
94
|
-
/** Raw argv lines pi was invoked with. */
|
|
95
|
-
calls: async () =>
|
|
96
|
-
(await readFile(pi.log, "utf-8").catch(() => "")).split("\n").filter(Boolean),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ─── registerPi ──────────────────────────────────────────────────────────────
|
|
101
|
-
|
|
102
|
-
describe("registerPi", () => {
|
|
103
|
-
it("registers the staged package and replaces the raw-repo source, leaving one agent-cortex source", async () => {
|
|
104
|
-
const tree = await makeInstallTree();
|
|
105
|
-
try {
|
|
106
|
-
const fx = await makePi(tree, { packages: [{ source: "../checkout", skills: [] }, "npm:context-mode"] });
|
|
107
|
-
|
|
108
|
-
const summary = await registerPi({
|
|
109
|
-
root: fx.root,
|
|
110
|
-
output: fx.staged,
|
|
111
|
-
settingsPath: fx.settingsPath,
|
|
112
|
-
piBin: fx.pi.bin,
|
|
113
|
-
warn: () => {},
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
assert.deepEqual(summary.commands, [
|
|
117
|
-
["remove", fx.rawRepo],
|
|
118
|
-
["install", fx.staged],
|
|
119
|
-
]);
|
|
120
|
-
assert.deepEqual(summary.removed, [fx.rawRepo]);
|
|
121
|
-
assert.deepEqual(await fx.calls(), [`--version`, `remove ${fx.rawRepo}`, `install ${fx.staged}`]);
|
|
122
|
-
assert.deepEqual(await fx.localSources(), [fx.staged], "the raw repo source is gone, the staged one added");
|
|
123
|
-
assert.ok((await readFile(fx.settingsPath, "utf-8")).includes("npm:context-mode"), "other package sources untouched");
|
|
124
|
-
} finally {
|
|
125
|
-
await tree.cleanup();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("is idempotent: a second run spawns nothing and leaves pi's settings unchanged", async () => {
|
|
130
|
-
const tree = await makeInstallTree();
|
|
131
|
-
try {
|
|
132
|
-
const fx = await makePi(tree, { packages: [{ source: "../checkout", skills: [] }] });
|
|
133
|
-
const options = { root: fx.root, output: fx.staged, settingsPath: fx.settingsPath, piBin: fx.pi.bin, warn: () => {} };
|
|
134
|
-
await registerPi(options);
|
|
135
|
-
const callsAfterFirstRun = await fx.calls();
|
|
136
|
-
const settingsAfterFirstRun = await readFile(fx.settingsPath, "utf-8");
|
|
137
|
-
|
|
138
|
-
const second = await registerPi(options);
|
|
139
|
-
|
|
140
|
-
assert.deepEqual(second.commands, []);
|
|
141
|
-
assert.deepEqual((await fx.calls()).slice(callsAfterFirstRun.length), [], "no further pi invocation");
|
|
142
|
-
assert.equal(await readFile(fx.settingsPath, "utf-8"), settingsAfterFirstRun);
|
|
143
|
-
} finally {
|
|
144
|
-
await tree.cleanup();
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("registers into an unconfigured pi without touching anything else", async () => {
|
|
149
|
-
const tree = await makeInstallTree();
|
|
150
|
-
try {
|
|
151
|
-
const fx = await makePi(tree);
|
|
152
|
-
|
|
153
|
-
const summary = await registerPi({
|
|
154
|
-
root: fx.root,
|
|
155
|
-
output: fx.staged,
|
|
156
|
-
settingsPath: fx.settingsPath,
|
|
157
|
-
piBin: fx.pi.bin,
|
|
158
|
-
warn: () => {},
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
assert.deepEqual(summary.commands, [["install", fx.staged]]);
|
|
162
|
-
assert.deepEqual(await fx.localSources(), [fx.staged]);
|
|
163
|
-
} finally {
|
|
164
|
-
await tree.cleanup();
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it("removes a stale raw-repo source when the staged package is already registered", async () => {
|
|
169
|
-
const tree = await makeInstallTree();
|
|
170
|
-
try {
|
|
171
|
-
const fx = await makePi(tree, { packages: ["../out", "../checkout"] });
|
|
172
|
-
|
|
173
|
-
const summary = await registerPi({
|
|
174
|
-
root: fx.root,
|
|
175
|
-
output: fx.staged,
|
|
176
|
-
settingsPath: fx.settingsPath,
|
|
177
|
-
piBin: fx.pi.bin,
|
|
178
|
-
warn: () => {},
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
assert.deepEqual(summary.commands, [["remove", fx.rawRepo]], "no re-install of the staged source");
|
|
182
|
-
assert.deepEqual(
|
|
183
|
-
await fx.calls(),
|
|
184
|
-
["--version", `remove ${fx.rawRepo}`],
|
|
185
|
-
"the plan and the commands that ran agree: no install of an already-configured source",
|
|
186
|
-
);
|
|
187
|
-
assert.deepEqual(await fx.localSources(), [fx.staged]);
|
|
188
|
-
} finally {
|
|
189
|
-
await tree.cleanup();
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("fails the run when a superseded source cannot be removed, naming the source left configured", async () => {
|
|
194
|
-
const tree = await makeInstallTree();
|
|
195
|
-
try {
|
|
196
|
-
const fx = await makePi(tree, { packages: [{ source: "../checkout", skills: [] }], failWhen: "remove" });
|
|
197
|
-
|
|
198
|
-
const error = await registerPi({
|
|
199
|
-
root: fx.root,
|
|
200
|
-
output: fx.staged,
|
|
201
|
-
settingsPath: fx.settingsPath,
|
|
202
|
-
piBin: fx.pi.bin,
|
|
203
|
-
warn: () => {},
|
|
204
|
-
}).then(
|
|
205
|
-
() => null,
|
|
206
|
-
(err) => err,
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
assert.ok(error, "the registration fails instead of reporting success");
|
|
210
|
-
assert.ok(error.message.includes(fx.rawRepo), `names the source still configured: ${error.message}`);
|
|
211
|
-
assert.deepEqual(await fx.calls(), ["--version", `remove ${fx.rawRepo}`], "the install never runs");
|
|
212
|
-
assert.deepEqual(await fx.localSources(), [fx.rawRepo], "no second agent-cortex source is added");
|
|
213
|
-
} finally {
|
|
214
|
-
await tree.cleanup();
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("--dry-run plans the registration without spawning pi or writing settings", async () => {
|
|
219
|
-
const tree = await makeInstallTree();
|
|
220
|
-
try {
|
|
221
|
-
const fx = await makePi(tree, { packages: [{ source: "../checkout", skills: [] }, "npm:context-mode"] });
|
|
222
|
-
const settingsBefore = await readFile(fx.settingsPath, "utf-8");
|
|
223
|
-
|
|
224
|
-
const summary = await registerPi({
|
|
225
|
-
root: fx.root,
|
|
226
|
-
output: fx.staged,
|
|
227
|
-
settingsPath: fx.settingsPath,
|
|
228
|
-
piBin: fx.pi.bin,
|
|
229
|
-
dryRun: true,
|
|
230
|
-
warn: () => {},
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
assert.deepEqual(summary.commands, [
|
|
234
|
-
["remove", fx.rawRepo],
|
|
235
|
-
["install", fx.staged],
|
|
236
|
-
]);
|
|
237
|
-
assert.deepEqual(await fx.calls(), [], "nothing spawned");
|
|
238
|
-
assert.equal(await readFile(fx.settingsPath, "utf-8"), settingsBefore, "settings untouched");
|
|
239
|
-
} finally {
|
|
240
|
-
await tree.cleanup();
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("warns with the manual commands when the pi CLI is unavailable, changing nothing", async () => {
|
|
245
|
-
const tree = await makeInstallTree();
|
|
246
|
-
try {
|
|
247
|
-
const fx = await makePi(tree, { packages: [{ source: "../checkout", skills: [] }] });
|
|
248
|
-
const settingsBefore = await readFile(fx.settingsPath, "utf-8");
|
|
249
|
-
const warnings = [];
|
|
250
|
-
|
|
251
|
-
const summary = await registerPi({
|
|
252
|
-
root: fx.root,
|
|
253
|
-
output: fx.staged,
|
|
254
|
-
settingsPath: fx.settingsPath,
|
|
255
|
-
piBin: join(fx.root, "no-such-pi"),
|
|
256
|
-
warn: (message) => warnings.push(message),
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
assert.equal(summary.registered, false);
|
|
260
|
-
const warning = warnings.join("\n");
|
|
261
|
-
assert.ok(warning.includes(`pi remove ${fx.rawRepo}`), "prints the manual remove command");
|
|
262
|
-
assert.ok(warning.includes(`pi install ${fx.staged}`), "prints the manual install command");
|
|
263
|
-
assert.equal(await readFile(fx.settingsPath, "utf-8"), settingsBefore, "settings untouched");
|
|
264
|
-
} finally {
|
|
265
|
-
await tree.cleanup();
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("fails the run on an unavailable pi CLI when --require-register is set", async () => {
|
|
270
|
-
const tree = await makeInstallTree();
|
|
271
|
-
try {
|
|
272
|
-
const fx = await makePi(tree);
|
|
273
|
-
|
|
274
|
-
await assert.rejects(
|
|
275
|
-
registerPi({
|
|
276
|
-
root: fx.root,
|
|
277
|
-
output: fx.staged,
|
|
278
|
-
settingsPath: fx.settingsPath,
|
|
279
|
-
piBin: join(fx.root, "no-such-pi"),
|
|
280
|
-
requireRegister: true,
|
|
281
|
-
warn: () => {},
|
|
282
|
-
}),
|
|
283
|
-
/registration/,
|
|
284
|
-
);
|
|
285
|
-
} finally {
|
|
286
|
-
await tree.cleanup();
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it("refuses to register a staged package that does not exist", async () => {
|
|
291
|
-
const tree = await makeInstallTree();
|
|
292
|
-
try {
|
|
293
|
-
const fx = await makePi(tree);
|
|
294
|
-
|
|
295
|
-
await assert.rejects(
|
|
296
|
-
registerPi({
|
|
297
|
-
root: fx.root,
|
|
298
|
-
output: join(fx.root, "never-staged"),
|
|
299
|
-
settingsPath: fx.settingsPath,
|
|
300
|
-
piBin: fx.pi.bin,
|
|
301
|
-
warn: () => {},
|
|
302
|
-
}),
|
|
303
|
-
/never-staged/,
|
|
304
|
-
);
|
|
305
|
-
} finally {
|
|
306
|
-
await tree.cleanup();
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
// ─── CLI wiring ──────────────────────────────────────────────────────────────
|
|
312
|
-
|
|
313
|
-
describe("install pi CLI: registration", () => {
|
|
314
|
-
it("--dry-run without --output prints the registration plan and writes nothing", async () => {
|
|
315
|
-
const home = await mkdtemp(join(tmpdir(), "cli-pi-register-home-"));
|
|
316
|
-
try {
|
|
317
|
-
const { exitCode, stdout } = await runCli(["install", "pi", "--dry-run"], { HOME: home });
|
|
318
|
-
|
|
319
|
-
assert.equal(exitCode, 0);
|
|
320
|
-
assert.ok(stdout.includes(`would run: pi install ${join(home, ".agent-cortex", "pi")}`));
|
|
321
|
-
assert.equal(await pathExists(join(home, ".pi")), false, "pi's settings dir untouched");
|
|
322
|
-
} finally {
|
|
323
|
-
await rm(home, { recursive: true, force: true });
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
it("--output <dir> stages only — no registration is attempted", async () => {
|
|
328
|
-
const home = await mkdtemp(join(tmpdir(), "cli-pi-register-out-home-"));
|
|
329
|
-
const out = await mkdtemp(join(tmpdir(), "cli-pi-register-out-"));
|
|
330
|
-
try {
|
|
331
|
-
const { exitCode, stdout } = await runCli(["install", "pi", "--output", out], { HOME: home });
|
|
332
|
-
|
|
333
|
-
assert.equal(exitCode, 0);
|
|
334
|
-
assert.doesNotMatch(stdout, /Registering the staged pi package/);
|
|
335
|
-
assert.ok(stdout.includes(`pi install ${out}`), "prints the manual registration hint");
|
|
336
|
-
assert.equal(await pathExists(join(home, ".pi")), false, "pi's settings dir untouched");
|
|
337
|
-
} finally {
|
|
338
|
-
await rm(home, { recursive: true, force: true });
|
|
339
|
-
await rm(out, { recursive: true, force: true });
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
});
|