@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
package/agents/ralph/agent.md
CHANGED
|
@@ -42,7 +42,7 @@ Run once at startup:
|
|
|
42
42
|
5. Create Ralph's workspace directory: `mkdir -p .agent-cortex/ralph`
|
|
43
43
|
6. Create `.agent-cortex/ralph/state.json` with initial content:
|
|
44
44
|
```json
|
|
45
|
-
{ "
|
|
45
|
+
{ "inflight": [] }
|
|
46
46
|
```
|
|
47
47
|
Then generate the progress file:
|
|
48
48
|
```bash
|
|
@@ -59,7 +59,7 @@ Run once at startup:
|
|
|
59
59
|
b. Claim the parent bead: `bd update <parent-id> --claim`.
|
|
60
60
|
c. Create the first stage chore bead and dispatch it (see _Creating and dispatching a stage chore_ below).
|
|
61
61
|
8. Record each launched agent in `.agent-cortex/ralph/state.json` (see format below).
|
|
62
|
-
9. Hand over to the completion-detection mechanism in the polling section: it
|
|
62
|
+
9. Hand over to the completion-detection mechanism in the polling section: it blocks with `wait_for_agents` (PI) or waits for event-driven wake-ups (Claude), and proceeds to **HITL Pause** directly when no agent work was dispatched and `skills/workflow/ralph/scripts/pending-gates.mjs` reports a non-empty `pendingHumanAction` — an **unblocked** `lifecycle:feature-pr` gate or an epic tagged `awaiting-epic-pr-merge`. Gates still parked behind their own pipeline do not count (REFERENCE.md, _Gate predicate_).
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
@@ -101,7 +101,6 @@ All orchestration state is derived from beads:
|
|
|
101
101
|
|
|
102
102
|
```json
|
|
103
103
|
{
|
|
104
|
-
"timerShellId": "shell-abc",
|
|
105
104
|
"inflight": [
|
|
106
105
|
{ "choreId": "xyz-456", "parentId": "abc-123", "title": "Add auth", "agentId": "agent-xyz-456", "logLine": 4 },
|
|
107
106
|
{ "choreId": "def-789", "parentId": "ghi-101", "title": "Fix cache", "agentId": "agent-def-789", "logLine": 7 }
|
|
@@ -109,7 +108,6 @@ All orchestration state is derived from beads:
|
|
|
109
108
|
}
|
|
110
109
|
```
|
|
111
110
|
|
|
112
|
-
- **timerShellId**: the shellId of the active poll-timer bash process used for completion polling (Copilot; stays `null` on PI, which blocks with `wait_for_agents` instead, and on event-driven harnesses such as Claude).
|
|
113
111
|
- **inflight[].choreId**: the chore bead currently being worked by the subagent.
|
|
114
112
|
- **inflight[].parentId**: the parent feature task bead. Log file is `.agent-cortex/ralph/ralph-<parentId>.log`.
|
|
115
113
|
- **inflight[].logLine**: the next line number to read from the parent's log file (1-based; start at 1). Updated after every poll.
|
|
@@ -127,12 +125,12 @@ Update `.agent-cortex/ralph/state.json` after **every** agent completion or disp
|
|
|
127
125
|
|
|
128
126
|
## Event loop
|
|
129
127
|
|
|
130
|
-
After initialization, Ralph waits for background agents to complete. Completion notifications are delivered by the mechanism documented in the polling section — PI blocks with `wait_for_agents` until a worker completes and its result is returned inline;
|
|
128
|
+
After initialization, Ralph waits for background agents to complete. Completion notifications are delivered by the mechanism documented in the polling section — PI blocks with `wait_for_agents` until a worker completes and its result is returned inline; Claude is event-driven (you are re-invoked automatically when a worker completes, with its result delivered inline). On each completion notification:
|
|
131
129
|
|
|
132
130
|
### If a background agent completed
|
|
133
131
|
|
|
134
|
-
1. **Flush** that bead's log using the log-polling procedure in the polling section to pick up any final lines for the chat summary (PI: flush new log lines as part of handling the `wait_for_agents` result;
|
|
135
|
-
2. **Read** the completed agent's full output (PI: the result arrives in the `wait_for_agents` response, with `read_agent` as a fallback for a specific result;
|
|
132
|
+
1. **Flush** that bead's log using the log-polling procedure in the polling section to pick up any final lines for the chat summary (PI: flush new log lines as part of handling the `wait_for_agents` result; Claude: nothing to flush — the result is delivered with the wake-up).
|
|
133
|
+
2. **Read** the completed agent's full output (PI: the result arrives in the `wait_for_agents` response, with `read_agent` as a fallback for a specific result; Claude: the result was delivered inline).
|
|
136
134
|
3. **Re-read** `.agent-cortex/ralph/state.json` to identify the chore bead and parent for that agent ID.
|
|
137
135
|
4. **Parse** the agent's `---REPORT---` block (see report format in the `run-pipeline-stage` skill).
|
|
138
136
|
5. **Close** the completed chore bead: `bd close <chore-id>`.
|
|
@@ -142,13 +140,13 @@ After initialization, Ralph waits for background agents to complete. Completion
|
|
|
142
140
|
- **Failure paths** (verify BLOCKED, review CHANGES_REQUESTED): check loop cap (see below), then create a feedback bead per the _Feedback Beads_ section in `run-pipeline-stage`. Do **not** dispatch immediately — the feedback bead appears in `bd ready` and is picked up in step 7. Remove the inflight entry for this chore; the feedback bead will create a new entry when dispatched.
|
|
143
141
|
7. **Check for newly ready beads**: run `bd ready`. For each bead not yet tracked:
|
|
144
142
|
- **Chore bead with `stage:*` label** (a feedback bead): find its parent via `bd show <chore-id>` (follow the `parent-child` dep). Check loop cap (see below). If under cap: dispatch it via _Creating and dispatching a stage chore_. If at cap: block it (`bd update <chore-id> --status blocked --notes "<cap> cap reached"`) and record for shutdown.
|
|
145
|
-
- **Task bead, AFK, in-flight count < 5, no
|
|
143
|
+
- **Task bead, AFK, in-flight count < 5, no pending human action**: claim the parent, create its first code chore, dispatch it. Check `pendingHumanAction` with `node skills/workflow/ralph/scripts/pending-gates.mjs` — an unblocked `lifecycle:feature-pr` gate means a feature is awaiting a human merge, so hold new parent features. Gates still blocked behind their own pipeline are parked and do not count.
|
|
146
144
|
- **Task bead, AFK, in-flight count at 5**: hold in memory as Waiting.
|
|
147
145
|
- **HITL task bead**: note for **Pending Human Action** shutdown summary.
|
|
148
146
|
- **NEEDS-REFINEMENT bead**: note for **Needs Refinement** shutdown summary.
|
|
149
147
|
When a parent is removed from `inflight` (completed or failed), immediately promote the first Waiting AFK parent.
|
|
150
148
|
8. **If no tasks remain in-flight** and `bd ready` returns no chore beads with `stage:*` labels and no AFK task beads:
|
|
151
|
-
- If
|
|
149
|
+
- If `pending-gates.mjs` reports a non-empty `pendingHumanAction` (an unblocked `lifecycle:feature-pr` gate, or an epic tagged `awaiting-epic-pr-merge`), proceed to **HITL Pause** (see below).
|
|
152
150
|
- Otherwise, proceed to **Shutdown** (see below).
|
|
153
151
|
|
|
154
152
|
### Loop cap check
|
|
@@ -167,15 +165,14 @@ Block command: `bd update <parent-id> --status blocked --notes "<cap> cap reache
|
|
|
167
165
|
|
|
168
166
|
## HITL Pause
|
|
169
167
|
|
|
170
|
-
Proceed here when no chore beads are in-flight, no `stage:*` chore beads are ready, and
|
|
168
|
+
Proceed here when no chore beads are in-flight, no `stage:*` chore beads are ready, and `pending-gates.mjs` reports a non-empty `pendingHumanAction` — an **unblocked** `lifecycle:feature-pr` gate (a feature genuinely awaiting human merge) or an epic tagged `awaiting-epic-pr-merge`. Gates still parked behind their own pipeline do not count. Ralph stops rather than burning requests on idle polls.
|
|
171
169
|
|
|
172
170
|
1. Regenerate `.agent-cortex/ralph/progress.md` one final time — do not delete it.
|
|
173
171
|
2. For each **multi-feature** epic whose feature beads are all closed but not yet tagged `awaiting-epic-pr-merge`, open/update an epic PR to main, then tag the epic `awaiting-epic-pr-merge`. Skip single-feature epics — their feature branch PRs already target `main` directly.
|
|
174
172
|
3. Run `bd dolt push`.
|
|
175
|
-
4. Collect
|
|
176
|
-
- Run `
|
|
177
|
-
-
|
|
178
|
-
- For each bead, run `bd show <id>` to retrieve the PR URL from bead notes.
|
|
173
|
+
4. Collect the table rows from the script's `pendingHumanAction` list:
|
|
174
|
+
- Run `node skills/workflow/ralph/scripts/pending-gates.mjs`
|
|
175
|
+
- For each entry, run `bd show <id>` to retrieve the PR URL from bead notes. `kind: "feature-pr"` rows read "review and merge the feature PR"; `kind: "epic-pr"` rows read "review and merge the epic PR into main".
|
|
179
176
|
5. Output the **Pending Human Action** summary:
|
|
180
177
|
```
|
|
181
178
|
⏸️ Ralph is paused — human action required before work can continue.
|
|
@@ -188,7 +185,7 @@ Proceed here when no chore beads are in-flight, no `stage:*` chore beads are rea
|
|
|
188
185
|
|
|
189
186
|
When you've completed the above actions, prompt me to continue.
|
|
190
187
|
```
|
|
191
|
-
6. **Stop completely.** Stop the polling mechanism documented in the polling section (
|
|
188
|
+
6. **Stop completely.** Stop the polling mechanism documented in the polling section (PI and Claude: nothing to stop — there is no timer). Do **not** restart or schedule anything. Do **not** start any background processes. Do **not** check bead status again. Do **not** continue the event loop. Output **nothing further** after the summary above. Ralph is now fully idle — it must not act again until the user explicitly re-prompts.
|
|
192
189
|
|
|
193
190
|
---
|
|
194
191
|
|
|
@@ -258,5 +255,4 @@ All beads complete.
|
|
|
258
255
|
- **Never** auto-merge feature or epic PRs — merge decisions are human-controlled.
|
|
259
256
|
- **Never** continue past feature completion until PR `feature/<parent-id> -> epic/<epic-id>` is merged and the child HITL PR gate bead is closed by a human.
|
|
260
257
|
- **Never** continue past epic completion until PR `epic/<epic-id> -> main` is merged.
|
|
261
|
-
- **When a feature hits the HITL PR gate, push and open the PR immediately and report the URL — do not wait for explicit approval to push or create the PR.**
|
|
262
|
-
- **Always** bump the patch version in `plugin.json` as part of any commit that changes agent or skill files.
|
|
258
|
+
- **When a feature hits the HITL PR gate, push and open the PR immediately and report the URL — do not wait for explicit approval to push or create the PR.**
|
|
@@ -20,7 +20,7 @@ Rules:
|
|
|
20
20
|
|
|
21
21
|
Claude Code **re-invokes you automatically when a background worker completes** — the worker's result is delivered to you inline on the wake-up. **Do not poll and do not `sleep`.** React to completions as they arrive.
|
|
22
22
|
|
|
23
|
-
- There is **no poll timer
|
|
23
|
+
- There is **no poll timer anywhere in this pipeline**: nothing in initialization starts one, and there is nothing to kill in **HITL Pause** — when you stop, you simply stop. The harness wakes you again when the user re-invokes you.
|
|
24
24
|
- There is **no log tailing on Claude**: workers' progress lines (`.agent-cortex/ralph/ralph-<parentId>.log`) are written by the workers themselves and surfaced by the harness with the completion — nothing to flush, nothing to poll. Produce the shared chat summaries from the delivered result instead.
|
|
25
25
|
- On each completion, apply the shared handling in the **Event loop** section of agent.md (steps 3–8: correlate the task ID to its bead via `state.json`, parse the REPORT, close the chore, advance the parent, check for newly ready beads, run the shutdown check). `state.json` `logLine` tracking is not used on Claude.
|
|
26
26
|
|
package/agents-native/ralph.md
CHANGED
|
@@ -35,7 +35,8 @@ created, so by the time a bead reaches `bd ready` here it should already carry a
|
|
|
35
35
|
`classify-bead` from the ralph loop:
|
|
36
36
|
|
|
37
37
|
- `implementation-type:afk` present → **AFK**. Done.
|
|
38
|
-
- `implementation-type:hitl` present → **HITL**. Skip; record for the
|
|
38
|
+
- `execution:hitl` (or the legacy `implementation-type:hitl`) present → **HITL**. Skip; record for the
|
|
39
|
+
pending-action summary.
|
|
39
40
|
- Neither present → treat as **NEEDS-REFINEMENT**: skip; record for the summary. A missing label
|
|
40
41
|
here means the bead skipped planning-stage classification — flag it, don't classify inline.
|
|
41
42
|
|
|
@@ -52,8 +53,8 @@ Run once at startup:
|
|
|
52
53
|
5. Read `maxFixRounds` from `${CLAUDE_PLUGIN_ROOT}/skills/create-task/pipeline.json` if present;
|
|
53
54
|
otherwise default to **4**.
|
|
54
55
|
6. Dispatch up to 5 AFK features (see below). Then end your turn — you will be woken on the
|
|
55
|
-
first completion. If there are zero AFK features but
|
|
56
|
-
to **Idle**.
|
|
56
|
+
first completion. If there are zero AFK features but an open `lifecycle:feature-pr` gate is
|
|
57
|
+
pending (see **Idle**), go straight to **Idle**.
|
|
57
58
|
|
|
58
59
|
## Dispatching a feature
|
|
59
60
|
|
|
@@ -105,10 +106,19 @@ beads per **Classifying a bead**, and promote AFK features into free slots.
|
|
|
105
106
|
|
|
106
107
|
When no workers are running and no AFK features remain:
|
|
107
108
|
|
|
108
|
-
- **PR gates pending** (open `lifecycle:feature-pr` beads
|
|
109
|
+
- **PR gates pending** (open `lifecycle:feature-pr` beads on either HITL axis):
|
|
110
|
+
`bd list -l lifecycle:feature-pr --label-any execution:hitl,implementation-type:hitl --limit 0`.
|
|
111
|
+
This harness keys the pause on a gate being **open**, not unblocked, because its gates stay
|
|
112
|
+
blocked for their whole life: `create-task` blocks each gate behind the feature's `document`
|
|
113
|
+
chore, which no Claude ralph claims or closes, and the native route in _When a reviewer
|
|
114
|
+
worker completes_ step 2 deps the gate onto the still-open feature bead. So never assume a gate
|
|
115
|
+
here is blocked only by its own pipeline, and never treat "no unblocked gate" as "no human
|
|
116
|
+
action owed" — that clears the loop with PRs unmerged. Run `bd dolt push`, then print a
|
|
109
117
|
**Pending Human Action** table (bead id, title, PR URL, "review & merge, then `bd close <gate>`"),
|
|
110
118
|
and **stop completely** — output nothing further. Do not poll. The user re-invokes you after
|
|
111
|
-
merging; you will resume from `bd ready`.
|
|
119
|
+
merging; you will resume from `bd ready`. The pi harness uses the unblocked-gate predicate
|
|
120
|
+
(`skills/workflow/ralph/scripts/pending-gates.mjs`); F10 (agnt-ctx-s5xd.10) unifies ralph's
|
|
121
|
+
agent files — reconcile the two predicates there rather than half-migrating this one.
|
|
112
122
|
- **Nothing pending**: run `bd dolt push`, print any recorded HITL / needs-refinement / blocked
|
|
113
123
|
beads as tables, then print **All beads complete.**
|
|
114
124
|
|
package/bin/agent-cortex.mjs
CHANGED
|
@@ -112,22 +112,6 @@ if (parsed.command === "install") {
|
|
|
112
112
|
process.exit(1);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
|
|
116
|
-
// copilot regenerates the flat agents/*.agent.md files the Copilot plugin
|
|
117
|
-
// loads via plugin.json ("agents": "agents/") — the same code path
|
|
118
|
-
// `pnpm build:copilot` runs.
|
|
119
|
-
if (parsed.harness === "copilot") {
|
|
120
|
-
const { installCopilot } = await import("./installers/copilot.mjs");
|
|
121
|
-
try {
|
|
122
|
-
await installCopilot({ output: parsed.output, dryRun: parsed.dryRun });
|
|
123
|
-
process.exit(0);
|
|
124
|
-
} catch (err) {
|
|
125
|
-
process.stderr.write(`Install failed: ${err.message}\n`);
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
process.exit(0);
|
|
131
115
|
}
|
|
132
116
|
|
|
133
117
|
function printPiSweep({ removed }) {
|
|
@@ -79,6 +79,14 @@ const DEFAULT_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
|
79
79
|
// The committed user-settings template.
|
|
80
80
|
const SETTINGS_TEMPLATE = "claude/settings.json";
|
|
81
81
|
|
|
82
|
+
// Claude user memory — the global prompt. The installer owns only the marked
|
|
83
|
+
// section; everything outside the markers is the user's own text.
|
|
84
|
+
const DEFAULT_INSTRUCTIONS_PATH = join(homedir(), ".claude", "CLAUDE.md");
|
|
85
|
+
const INSTRUCTIONS_BEGIN = "<!-- BEGIN agent-cortex:output-style -->";
|
|
86
|
+
const INSTRUCTIONS_END = "<!-- END agent-cortex:output-style -->";
|
|
87
|
+
// Canonical prose, shared with the pi extension (extensions/output-style).
|
|
88
|
+
const INSTRUCTIONS_SOURCE = join("extensions", "output-style", "output-style.md");
|
|
89
|
+
|
|
82
90
|
// The only keys the installer owns outright: everything else in the live file
|
|
83
91
|
// is personal config the merge must preserve.
|
|
84
92
|
const SETTINGS_OWNED_KEYS = ["enabledPlugins", "extraKnownMarketplaces"];
|
|
@@ -97,8 +105,8 @@ const DEFAULT_WARN = (msg) => console.warn(`[claude-installer] ${msg}`);
|
|
|
97
105
|
// section composition from the poll-loop sources.
|
|
98
106
|
const DEFER = new Set(["ralph"]);
|
|
99
107
|
|
|
100
|
-
// Ralph-coupled
|
|
101
|
-
//
|
|
108
|
+
// Ralph-coupled pipeline skills that don't apply to the lean Claude Ralph (its completion
|
|
109
|
+
// handling is event-driven, not the pi orchestrator's). Not copied into the Claude plugin.
|
|
102
110
|
const SKILL_EXCLUDE = new Set(["ralph", "run-pipeline-stage"]);
|
|
103
111
|
|
|
104
112
|
const NAME_PREFIX = "agent-cortex:";
|
|
@@ -324,7 +332,7 @@ async function installSettings({ root, target, dryRun, warn }) {
|
|
|
324
332
|
}
|
|
325
333
|
|
|
326
334
|
const content = `${JSON.stringify(merged, null, 2)}\n`;
|
|
327
|
-
return
|
|
335
|
+
return writeManagedFile({ target, content, dryRun });
|
|
328
336
|
}
|
|
329
337
|
|
|
330
338
|
/**
|
|
@@ -350,12 +358,12 @@ function mergeSettings(template, existing) {
|
|
|
350
358
|
}
|
|
351
359
|
|
|
352
360
|
/**
|
|
353
|
-
* Write
|
|
354
|
-
*
|
|
355
|
-
*
|
|
361
|
+
* Write a managed file. A legacy symlink is replaced with a real file by writing
|
|
362
|
+
* a sibling temp file and renaming it over the target — rename replaces the link
|
|
363
|
+
* itself, so a committed template is never written through.
|
|
356
364
|
* Returns the action taken so the CLI can report the plan (dry-run included).
|
|
357
365
|
*/
|
|
358
|
-
async function
|
|
366
|
+
async function writeManagedFile({ target, content, dryRun }) {
|
|
359
367
|
const symlink = await isSymlink(target);
|
|
360
368
|
const current = await readFileMaybe(target);
|
|
361
369
|
|
|
@@ -382,6 +390,52 @@ async function writeManagedJson({ target, content, dryRun }) {
|
|
|
382
390
|
return { path: target, action: symlink ? "removed-symlink" : "written", removedSymlink: symlink };
|
|
383
391
|
}
|
|
384
392
|
|
|
393
|
+
// ─── Claude user memory (CLAUDE.md) ──────────
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Materialise the output-style block into the managed section of ~/.claude/CLAUDE.md.
|
|
397
|
+
*
|
|
398
|
+
* The section is delimited by HTML comments, so a re-install replaces only the
|
|
399
|
+
* text between them and every other line of the user's memory file survives. A
|
|
400
|
+
* file with exactly one marker (hand-edited or truncated) is left untouched with
|
|
401
|
+
* a warning, never guessed at.
|
|
402
|
+
*/
|
|
403
|
+
async function installInstructions({ root, target, dryRun, warn }) {
|
|
404
|
+
const block = await readFileMaybe(join(root, INSTRUCTIONS_SOURCE));
|
|
405
|
+
if (block === null) {
|
|
406
|
+
warn(`no ${INSTRUCTIONS_SOURCE} source in the package — skipping CLAUDE.md`);
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
const content = mergeManagedSection(await readFileMaybe(target), block);
|
|
410
|
+
if (content === null) {
|
|
411
|
+
warn(`${target} has an unterminated agent-cortex section — left unchanged; fix the markers by hand`);
|
|
412
|
+
return { path: target, action: "skipped-unmanaged", removedSymlink: false };
|
|
413
|
+
}
|
|
414
|
+
return writeManagedFile({ target, content, dryRun });
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Return `existing` with the managed section replaced by `block`, or null when
|
|
419
|
+
* the file carries unmatched markers. A file without markers gets the section
|
|
420
|
+
* appended, so personal memory text is never disturbed.
|
|
421
|
+
*/
|
|
422
|
+
function mergeManagedSection(existing, block) {
|
|
423
|
+
const managed = `${INSTRUCTIONS_BEGIN}\n${block.trimEnd()}\n${INSTRUCTIONS_END}`;
|
|
424
|
+
if (existing === null) return `${managed}\n`;
|
|
425
|
+
|
|
426
|
+
const start = existing.indexOf(INSTRUCTIONS_BEGIN);
|
|
427
|
+
const end = existing.indexOf(INSTRUCTIONS_END);
|
|
428
|
+
if (start === -1 && end === -1) {
|
|
429
|
+
const head = existing.replace(/\s*$/, "");
|
|
430
|
+
return head === "" ? `${managed}\n` : `${head}\n\n${managed}\n`;
|
|
431
|
+
}
|
|
432
|
+
if (start === -1 || end === -1 || end < start) return null;
|
|
433
|
+
|
|
434
|
+
const before = existing.slice(0, start).replace(/\s*$/, "");
|
|
435
|
+
const after = existing.slice(end + INSTRUCTIONS_END.length).replace(/^\s*/, "").replace(/\s*$/, "");
|
|
436
|
+
return `${[before, managed, after].filter((part) => part !== "").join("\n\n")}\n`;
|
|
437
|
+
}
|
|
438
|
+
|
|
385
439
|
async function readTemplateJson(filePath, warn) {
|
|
386
440
|
const raw = await readFileMaybe(filePath);
|
|
387
441
|
if (raw === null) {
|
|
@@ -450,15 +504,20 @@ async function isSymlink(filePath) {
|
|
|
450
504
|
* (default ~/.claude/settings.json). Passing it
|
|
451
505
|
* explicitly materialises settings even with
|
|
452
506
|
* --output — the test/CI seam.
|
|
507
|
+
* @param {string} [options.instructionsPath] Claude user-memory target
|
|
508
|
+
* (default ~/.claude/CLAUDE.md). Passing it
|
|
509
|
+
* explicitly materialises the section even
|
|
510
|
+
* with --output — the test/CI seam.
|
|
453
511
|
* @param {(msg: string) => void} [options.warn] Warning sink, also collected in `warnings`.
|
|
454
512
|
* @returns {{ output: string, marketplaceRoot: string|null, manifestPath: string|null,
|
|
455
513
|
* marketplaceManifest: object|null, agents: string[], natives: string[],
|
|
456
514
|
* skills: {names: string[], md: number, files: number, dir: string},
|
|
457
515
|
* hooks: boolean, hookFiles: string[], handAuthored: string[],
|
|
458
516
|
* settings: {path: string, action: string, removedSymlink: boolean}|null,
|
|
517
|
+
* instructions: {path: string, action: string, removedSymlink: boolean}|null,
|
|
459
518
|
* warnings: string[], dryRun: boolean }}
|
|
460
519
|
*/
|
|
461
|
-
export async function installClaude({ root = PACKAGE_ROOT, output, dryRun = false, pluginRoot, settingsPath, warn = DEFAULT_WARN } = {}) {
|
|
520
|
+
export async function installClaude({ root = PACKAGE_ROOT, output, dryRun = false, pluginRoot, settingsPath, instructionsPath, warn = DEFAULT_WARN } = {}) {
|
|
462
521
|
const tokenMap = await loadTokenMap(root);
|
|
463
522
|
if (typeof tokenMap.version === "number" && tokenMap.version > CONTRACT_VERSION) {
|
|
464
523
|
throw new Error(
|
|
@@ -498,15 +557,22 @@ export async function installClaude({ root = PACKAGE_ROOT, output, dryRun = fals
|
|
|
498
557
|
await mkdir(out, { recursive: true });
|
|
499
558
|
}
|
|
500
559
|
|
|
501
|
-
// The default install owns ~/.claude/settings.json
|
|
502
|
-
// generate-only form and leaves the
|
|
503
|
-
//
|
|
560
|
+
// The default install owns ~/.claude/settings.json and the managed section of
|
|
561
|
+
// ~/.claude/CLAUDE.md; --output is the generate-only form and leaves the
|
|
562
|
+
// user's Claude config alone. Explicit paths request the write regardless
|
|
563
|
+
// (the test/CI seam).
|
|
504
564
|
const settingsTarget = settingsPath ?? DEFAULT_SETTINGS_PATH;
|
|
505
565
|
const settings =
|
|
506
566
|
isDefaultInstall || settingsPath !== undefined
|
|
507
567
|
? await installSettings({ root, target: settingsTarget, dryRun, warn: warnSink })
|
|
508
568
|
: null;
|
|
509
569
|
|
|
570
|
+
const instructionsTarget = instructionsPath ?? DEFAULT_INSTRUCTIONS_PATH;
|
|
571
|
+
const instructions =
|
|
572
|
+
isDefaultInstall || instructionsPath !== undefined
|
|
573
|
+
? await installInstructions({ root, target: instructionsTarget, dryRun, warn: warnSink })
|
|
574
|
+
: null;
|
|
575
|
+
|
|
510
576
|
const agents = await buildAgents(root);
|
|
511
577
|
const natives = await buildNatives(root, join(root, "agents-native"));
|
|
512
578
|
const skillOut = join(out, "skills");
|
|
@@ -530,6 +596,7 @@ export async function installClaude({ root = PACKAGE_ROOT, output, dryRun = fals
|
|
|
530
596
|
hookFiles: hookFiles.map((f) => f.rel),
|
|
531
597
|
handAuthored: handAuthored.map((f) => f.rel),
|
|
532
598
|
settings,
|
|
599
|
+
instructions,
|
|
533
600
|
warnings,
|
|
534
601
|
dryRun,
|
|
535
602
|
};
|
|
@@ -551,11 +618,15 @@ export async function installClaude({ root = PACKAGE_ROOT, output, dryRun = fals
|
|
|
551
618
|
if (summary.handAuthored.length)
|
|
552
619
|
console.log(` hand-authored files: ${summary.handAuthored.join(", ")} (copied from repo claude-extras/)`);
|
|
553
620
|
if (summary.settings) console.log(` settings → ${summary.settings.path} (${summary.settings.action})`);
|
|
621
|
+
if (summary.instructions)
|
|
622
|
+
console.log(` CLAUDE.md → ${summary.instructions.path} (${summary.instructions.action})`);
|
|
554
623
|
return summary;
|
|
555
624
|
}
|
|
556
625
|
|
|
557
626
|
// Write phase — the cleanup before buildSkills already cleared stale children.
|
|
558
627
|
if (settings) console.log(`Materialised Claude settings → ${settings.path} (${settings.action})`);
|
|
628
|
+
if (instructions && instructions.action !== "skipped-unmanaged")
|
|
629
|
+
console.log(`Materialised CLAUDE.md section → ${instructions.path} (${instructions.action})`);
|
|
559
630
|
const agentOut = join(out, "agents");
|
|
560
631
|
await mkdir(agentOut, { recursive: true });
|
|
561
632
|
for (const { file, content } of [...agents.files, ...natives]) {
|
package/docs/claude-hooks.md
CHANGED
|
@@ -17,6 +17,7 @@ UI surface. Each decision below is grounded in the Claude Code hooks reference.
|
|
|
17
17
|
| `session-start/` | `SessionStart` hook commands | **Port** (extended) |
|
|
18
18
|
| `auto-name.ts` | — | **Reject** — built-in |
|
|
19
19
|
| `agent-guardrails/` | — | **Reject** — pi-only (no system-prompt hook) |
|
|
20
|
+
| `output-style/` | managed `CLAUDE.md` section | **Port** — user memory, not a hook |
|
|
20
21
|
| `notify/` | `Notification` hook + `scripts/notify.mjs` | **Port** |
|
|
21
22
|
| `skill-stats/` | — | **Reject** — no equivalent |
|
|
22
23
|
| `subagent/` | — | **Reject** — native |
|
|
@@ -89,6 +90,21 @@ context rather than system instructions. The rules are harness-agnostic prose, s
|
|
|
89
90
|
a future port could append them to the existing ported SessionStart hook — out of
|
|
90
91
|
scope for this pi-first slice.
|
|
91
92
|
|
|
93
|
+
## `output-style/` → Port (managed CLAUDE.md section)
|
|
94
|
+
|
|
95
|
+
pi appends the reply shape (action first, Simplified Technical English, restated
|
|
96
|
+
context) to the system prompt through `before_agent_start`. Claude Code cannot
|
|
97
|
+
modify the system prompt from a hook, so the installer writes the same block into
|
|
98
|
+
the managed section of `~/.claude/CLAUDE.md` — Claude's user memory, loaded every
|
|
99
|
+
session.
|
|
100
|
+
|
|
101
|
+
The content is not copied into a Claude-side template: `extensions/output-style/
|
|
102
|
+
output-style.md` is the single source, read by the pi extension at load and by the
|
|
103
|
+
installer at install time. Re-running the install replaces only the text between
|
|
104
|
+
the markers; personal memory text survives untouched. The installer never writes
|
|
105
|
+
the block by appending to a `SessionStart` hook — memory is the right surface
|
|
106
|
+
because the rules must hold for every turn, not just the first.
|
|
107
|
+
|
|
92
108
|
## `skill-stats/` → Reject (no equivalent)
|
|
93
109
|
|
|
94
110
|
pi tracks skills loaded into the system prompt, `/skill:` invocations, SKILL.md
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Idea: Improve PI System Prompt
|
|
2
2
|
|
|
3
3
|
## Status
|
|
4
|
-
Backlog idea (not implementation-ready) —
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Backlog idea (not implementation-ready) — two slices implemented as pi extensions:
|
|
5
|
+
`agent-guardrails` (circuit-breakers, check-in triggers, atomic-change discipline) and
|
|
6
|
+
`output-style` (action-first reply shape, Simplified Technical English, restated context,
|
|
7
|
+
shipped to pi via the system prompt and to Claude via a managed `CLAUDE.md` section).
|
|
8
|
+
The rest of the idea is unscoped.
|
|
7
9
|
|
|
8
10
|
## Why it might be useful
|
|
9
11
|
PI's current system prompt is weak. Agents consistently get off track, spend excessive tokens spinning their wheels or going off on tangents, fail to check in when problems are hit, and generally behave like inexperienced code goblins. This wastes tokens, slows down task completion, and forces the user to constantly redirect the agent. A stronger system prompt would produce more focused, disciplined agents that know when to stop and ask.
|
|
@@ -30,6 +32,10 @@ High — after current work lands. Directly impacts daily productivity and token
|
|
|
30
32
|
- Which guardrails from the Gemini starter are genuinely useful vs redundant with existing skills (e.g. `git-workflow` already covers destructive commands, `style-code` covers scope discipline)?
|
|
31
33
|
|
|
32
34
|
## Notes
|
|
35
|
+
- **Second slice (settled)**: reply shape is a separate extension from task discipline.
|
|
36
|
+
`agent-guardrails` decides whether work continues; `output-style` decides how the result
|
|
37
|
+
is reported (STE per ASD-STE100, action first, context restated — never a bead or phase
|
|
38
|
+
ID cited alone). Both are stable constants appended on `before_agent_start`.
|
|
33
39
|
- **Precedence (settled by the first slice)**: the generic circuit-breakers yield to a structured
|
|
34
40
|
workflow — a skill or pipeline stage with its own explicit retry and check-in rules wins.
|
|
35
41
|
- **Gemini starter prompt** exists (see conversation from 2026-08-05) covering loop prevention, action scope, context management, execution workflow order, and working state maintenance. Useful starting material but needs heavy customisation.
|
|
@@ -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.
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
@@ -9,13 +9,15 @@ Required fields:
|
|
|
9
9
|
- `name`: kebab-case skill identifier.
|
|
10
10
|
- `description`: max 1024 characters.
|
|
11
11
|
|
|
12
|
+
Frontmatter is machine-validated: `pnpm lint` runs `check:skills`, which fails on a
|
|
13
|
+
frontmatter block that would make pi silently drop the skill.
|
|
14
|
+
|
|
12
15
|
Optional fields:
|
|
13
16
|
- `argument-hint`: input prompt shown to users at invocation.
|
|
14
17
|
- `disable-model-invocation`: hides the skill from automatic model routing; explicit
|
|
15
18
|
`/skill-name` invocation still works. Set it when the danger is a fuzzy description
|
|
16
19
|
match, e.g. a skill whose steps are destructive. Preserved and honoured by pi and
|
|
17
|
-
Claude Code
|
|
18
|
-
through its model-facing tool. See `docs/research/disable-model-invocation.md`.
|
|
20
|
+
Claude Code. See `docs/research/disable-model-invocation.md`.
|
|
19
21
|
|
|
20
22
|
## Description format rules
|
|
21
23
|
|
|
@@ -35,7 +37,7 @@ Optional fields:
|
|
|
35
37
|
|
|
36
38
|
## Tool references
|
|
37
39
|
|
|
38
|
-
Reference agent tools by `{{TOOL:name}}` token (canonical
|
|
40
|
+
Reference agent tools by `{{TOOL:name}}` token (canonical authoring name), never a
|
|
39
41
|
hardcoded harness-specific name such as `bash`, `task`, or `read_agent` — installers
|
|
40
42
|
substitute the per-harness name from `token-map.json` at install time. Add any new tool
|
|
41
43
|
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
|
|
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
|
|
28
|
-
Code
|
|
29
|
-
|
|
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
|
|
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);
|
package/docs/user-preferences.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# User Preferences
|
|
2
2
|
|
|
3
3
|
This file records personal development preferences for the author (**jaybeeuu**).
|
|
4
|
-
Both
|
|
5
|
-
|
|
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 —
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|