@iceinvein/agent-skills 0.10.1 → 0.11.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/package.json +1 -1
- package/skills/index.json +2 -2
- package/skills/magpie/README.md +1 -1
- package/skills/magpie/SKILL.md +13 -12
- package/skills/magpie/package.json +1 -1
- package/skills/magpie/references/scout.md +31 -16
- package/skills/magpie/references/specialists.md +71 -11
- package/skills/magpie/scripts/__tests__/skill-lint.test.ts +101 -19
- package/skills/magpie/skill.json +1 -1
- package/skills/sluice/references/status.md +5 -3
- package/skills/sluice/scripts/status.sh +15 -3
- package/skills/sluice/skill.json +1 -1
package/package.json
CHANGED
package/skills/index.json
CHANGED
|
@@ -221,7 +221,7 @@
|
|
|
221
221
|
"name": "magpie",
|
|
222
222
|
"description": "Interactive PR review pipeline. Runs five parallel specialist subagents (security, bugs, performance, code-smells, architecture), dedupes findings, applies a critic rubric, peer-reviews via codex exec (falling back to a Claude second opinion when codex is unavailable), and serves an interactive HTML report for selecting findings to post via gh. Bundles a Bun CLI installed onto PATH via the skill's postinstall step. Use when the user asks to review a GitHub pull request. Splits oversized diffs into budgeted shards and rebuilds the diff from the local clone when gh pr diff refuses it.",
|
|
223
223
|
"type": "prompt",
|
|
224
|
-
"version": "0.
|
|
224
|
+
"version": "0.11.0"
|
|
225
225
|
},
|
|
226
226
|
{
|
|
227
227
|
"name": "migrate",
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
"name": "sluice",
|
|
284
284
|
"description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment and one status command can answer where the run is, and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
|
|
285
285
|
"type": "prompt",
|
|
286
|
-
"version": "0.12.
|
|
286
|
+
"version": "0.12.2"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
289
|
"name": "temporal-coupling-detector",
|
package/skills/magpie/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Given a GitHub PR number, dispatches five specialist subagents in parallel (secu
|
|
|
12
12
|
- `gh` on PATH, authenticated (`gh auth status`)
|
|
13
13
|
- `git` on PATH
|
|
14
14
|
- `codex` on PATH, authenticated (optional; if absent the peer-review stage falls back to a Claude second-opinion subagent)
|
|
15
|
-
-
|
|
15
|
+
- code intelligence, with a completed index for the repo under review (optional; if absent the specialists review from the diff and worktree alone). Either interface works: the `code-intel` CLI on PATH, which is preferred because it takes `--repo` per call and needs no session binding, or the code-intelligence MCP server
|
|
16
16
|
|
|
17
17
|
## Install
|
|
18
18
|
|
package/skills/magpie/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ description: Use when the user asks to review a GitHub pull request (a PR number
|
|
|
7
7
|
|
|
8
8
|
## Prerequisites
|
|
9
9
|
|
|
10
|
-
The skill pre-flights `bun`, `gh`, `git` (required) and `codex` (optional). A missing required binary aborts the run with a single install hint line. Without `codex` the run continues and peer review falls back to a Claude second-opinion subagent (setup prints a one-line notice and logs `{stage: preflight, status: done, missingOptional: ["codex"]}`).
|
|
10
|
+
The skill pre-flights `bun`, `gh`, `git` (required) and `codex` (optional). A missing required binary aborts the run with a single install hint line. Code intelligence is not pre-flighted: stage 3 probes for it, over either the `code-intel` CLI or the code-intelligence MCP server, and the run continues without it. Without `codex` the run continues and peer review falls back to a Claude second-opinion subagent (setup prints a one-line notice and logs `{stage: preflight, status: done, missingOptional: ["codex"]}`).
|
|
11
11
|
|
|
12
12
|
## Stage walkthrough
|
|
13
13
|
|
|
@@ -85,16 +85,17 @@ magpie render "$RUN_DIR" progress
|
|
|
85
85
|
|
|
86
86
|
Append `{stage: context, status: running}` to `$RUN_DIR/log.jsonl` and re-render progress. This stage has two steps and never aborts the run.
|
|
87
87
|
|
|
88
|
-
**
|
|
88
|
+
**Probe.** Code intelligence reaches the same on-device daemon through two interfaces. Prefer the `code-intel` CLI: it takes `--repo` on every call, so it holds no session binding to leak past cleanup and the specialists can query in parallel without clobbering each other's workspace. `$RUN_DIR/worktree` is a linked git worktree either way, so an already-indexed base repo seeds its index instead of re-indexing.
|
|
89
89
|
|
|
90
|
-
- `
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
|
|
90
|
+
- **CLI**, when `command -v code-intel` succeeds. Run `code-intel index status --repo "$RUN_DIR/worktree" --json` and read `.status`: `ok` sets `CODE_INTELLIGENCE=cli`. `indexing_started` or `indexing_in_progress` means the seed took, so poll the same command every 5s for at most 60s and set `CODE_INTELLIGENCE=cli` either way. Exit 3 is a stopped daemon: run `code-intel start`, re-probe once. **Never run `code-intel index approve`.**
|
|
91
|
+
- **MCP**, when the CLI is absent but `mcp__code-intelligence__*` tools are in your tool list. Call `bind_workspace` with `$RUN_DIR/worktree` and apply the same rules, polling `get_index_stats` instead, to set `CODE_INTELLIGENCE=mcp`. **Never call `approve_indexing`.**
|
|
92
|
+
- `consent_required` on either interface means the base repo has never completed an index, and starting one is a full GPU pass the user did not ask for. That, no interface at all, or any other error that survives one retry, sets `CODE_INTELLIGENCE=unavailable`; print one line: "Code intelligence is unavailable (<reason>); specialists will review from the diff alone."
|
|
93
|
+
|
|
94
|
+
Never block the pipeline on a still-running index. The scout and specialist contracts both handle a tool that is not ready yet.
|
|
94
95
|
|
|
95
96
|
**Scout.** Read `references/scout.md` and dispatch one subagent (Agent tool, `general-purpose`) carrying the `magpie-scout` block with `<<RUN_DIR>>`, `<<PR_NUMBER>>`, and `<<CODE_INTELLIGENCE>>` substituted. It writes `$RUN_DIR/brief.json`.
|
|
96
97
|
|
|
97
|
-
Append `{stage: context, status: done, codeIntelligence: true|false}` and re-render progress. If the scout returned without writing `brief.json`, append `{stage: context, status: skipped, codeIntelligence: true|false}` instead and continue: the brief is optional everywhere it is read. Both entries carry the probe's result, which is known whatever the scout did.
|
|
98
|
+
Append `{stage: context, status: done, codeIntelligence: true|false, interface: "cli"|"mcp"|"none"}` and re-render progress. If the scout returned without writing `brief.json`, append `{stage: context, status: skipped, codeIntelligence: true|false, interface: ...}` instead and continue: the brief is optional everywhere it is read. Both entries carry the probe's result, which is known whatever the scout did, and `interface` is what stage 10 reads to decide whether there is a session to rebind.
|
|
98
99
|
|
|
99
100
|
### 4. Specialists
|
|
100
101
|
|
|
@@ -147,8 +148,8 @@ gate is expected to have none. `magpie dedupe` re-checks this against the manife
|
|
|
147
148
|
names every missing pair on stdout, as a backstop rather than a substitute.
|
|
148
149
|
|
|
149
150
|
If every specialist fails (no findings files written), log
|
|
150
|
-
`{stage: specialists, status: error}`, rebind code intelligence to `$REPO` if
|
|
151
|
-
(stage 10), and stop. Otherwise mark `{stage: specialists, status: done}`.
|
|
151
|
+
`{stage: specialists, status: error}`, rebind code intelligence to `$REPO` if
|
|
152
|
+
`CODE_INTELLIGENCE=mcp` (stage 10), and stop. Otherwise mark `{stage: specialists, status: done}`.
|
|
152
153
|
|
|
153
154
|
### 5. Dedupe
|
|
154
155
|
|
|
@@ -240,7 +241,7 @@ magpie render "$RUN_DIR" findings
|
|
|
240
241
|
magpie cleanup "$RUN_DIR" --repo "$REPO"
|
|
241
242
|
```
|
|
242
243
|
|
|
243
|
-
If the context stage
|
|
244
|
+
If the context stage set `CODE_INTELLIGENCE=mcp`, rebind the session now: call `bind_workspace` with `$REPO`. MCP binding is per session with no per-call override, so ending a run without this leaves the session pointed at a worktree `cleanup` just deleted. A `cli` run has nothing to rebind, because `--repo` names the workspace on every call. Either way the daemon prunes the seeded index once the worktree is gone.
|
|
244
245
|
|
|
245
246
|
The run directory is renamed to `<run-dir>.archived-<timestamp>` and the worktree is removed. The CLI prints two lines on success: `archived to <path>` and `view later: magpie open <archived-id>`. Surface that second line verbatim so the user has a one-command path back to the report.
|
|
246
247
|
|
|
@@ -261,7 +262,7 @@ magpie status "$RUN_DIR"
|
|
|
261
262
|
|
|
262
263
|
The JSON output tells you `lastCompleted` and `next`. Resume from `next`:
|
|
263
264
|
|
|
264
|
-
- `context` re-runs by redoing the
|
|
265
|
+
- `context` re-runs by redoing the probe, then dispatching the scout only if `$RUN_DIR/brief.json` is missing. The seeded index survives a crash, so the rebind is near-instant.
|
|
265
266
|
- Any other stage: run it as written in the walkthrough.
|
|
266
267
|
- If a specialist focus has no findings file but its sibling stages are done,
|
|
267
268
|
re-dispatch only that focus. On a sharded run the unit is the `(focus, shard)` pair:
|
|
@@ -274,4 +275,4 @@ The original server is gone. Restart it with `magpie serve "$RUN_DIR"` (step 2)
|
|
|
274
275
|
|
|
275
276
|
## Aborting
|
|
276
277
|
|
|
277
|
-
If the user types `abort` mid-run, rebind code intelligence to `$REPO` if
|
|
278
|
+
If the user types `abort` mid-run, rebind code intelligence to `$REPO` if `CODE_INTELLIGENCE=mcp` (stage 10), then run `magpie cleanup` and exit.
|
|
@@ -6,9 +6,10 @@ with `<<RUN_DIR>>` and `<<PR_NUMBER>>` replaced by the real values first. The
|
|
|
6
6
|
subagent has no shell variables from your session, so an unexpanded path means it
|
|
7
7
|
writes the brief where nothing will read it.
|
|
8
8
|
|
|
9
|
-
Substitute `<<CODE_INTELLIGENCE>>` with
|
|
10
|
-
`
|
|
11
|
-
|
|
9
|
+
Substitute `<<CODE_INTELLIGENCE>>` with the value stage 3's probe assigned: `cli` for
|
|
10
|
+
the `code-intel` CLI, `mcp` for the code-intelligence MCP tools, `unavailable` for
|
|
11
|
+
neither. The scout still runs when code intelligence is unavailable; only the
|
|
12
|
+
subsystem map degrades.
|
|
12
13
|
|
|
13
14
|
```magpie-scout
|
|
14
15
|
You are a senior engineer building the orienting brief that five specialist
|
|
@@ -30,19 +31,33 @@ Code intelligence: <<CODE_INTELLIGENCE>>
|
|
|
30
31
|
|
|
31
32
|
## Code intelligence
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
Unless the line above says `unavailable`, an index of `<<RUN_DIR>>/worktree`, seeded
|
|
35
|
+
from the base repository, is queryable. Use it for two things only: name the subsystem
|
|
36
|
+
each touched directory belongs to and what it is responsible for, then say what depends
|
|
37
|
+
on those modules.
|
|
38
|
+
|
|
39
|
+
When the line says `cli`, run the `code-intel` CLI. Every call names the workspace, so
|
|
40
|
+
there is nothing to bind first:
|
|
41
|
+
|
|
42
|
+
code-intel investigate --repo <<RUN_DIR>>/worktree --mode module --file-path <dir> \
|
|
43
|
+
--json "what is this module responsible for"
|
|
44
|
+
code-intel dependency-graph --repo <<RUN_DIR>>/worktree --json <symbol>
|
|
45
|
+
|
|
46
|
+
`code-intel repo-map --repo <<RUN_DIR>>/worktree --json` is the cheaper first look when
|
|
47
|
+
you do not yet know which directories matter. Exit 5 means no results, which is an
|
|
48
|
+
answer. Exit 3 means the daemon is down: stop querying and write `"subsystems": []`.
|
|
49
|
+
|
|
50
|
+
When the line says `mcp`, call `bind_workspace` with `<<RUN_DIR>>/worktree` before your
|
|
51
|
+
first query, then `get_module_summary` on each touched directory and
|
|
52
|
+
`explore_dependency_graph` on the touched modules.
|
|
53
|
+
|
|
54
|
+
If a query reports `indexing_in_progress` (the CLI returns
|
|
55
|
+
`error.code: workspace_unavailable` with that prefix), finish reading the diff and retry
|
|
56
|
+
once. If it still is not ready, or the line above says `unavailable`, write
|
|
57
|
+
`"subsystems": []` and carry on. Never call `approve_indexing` and never run
|
|
58
|
+
`code-intel index approve`; never call `refresh_index` and never run
|
|
59
|
+
`code-intel index refresh`. Triggering a full index is a consent-gated operation that
|
|
60
|
+
is not yours to start.
|
|
46
61
|
|
|
47
62
|
## How to reason
|
|
48
63
|
|
|
@@ -41,9 +41,11 @@ in an excluded file (a migration implies a model snapshot, a schema change impli
|
|
|
41
41
|
generated types), open it and cross-check rather than treating it as out of scope.
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
5.
|
|
45
|
-
stage logged `codeIntelligence: true
|
|
46
|
-
|
|
44
|
+
5. One `magpie-codebase-intelligence-*` block below, verbatim, **only** when the
|
|
45
|
+
context stage logged `codeIntelligence: true`: the `-cli` block for
|
|
46
|
+
`interface: "cli"`, the `-mcp` block for `interface: "mcp"`. Omit it entirely
|
|
47
|
+
otherwise, and never send both: telling a specialist to use tools it does not have
|
|
48
|
+
wastes a turn per specialist on discovery.
|
|
47
49
|
6. The brief, when `<RUN_DIR>/brief.json` exists, rendered as:
|
|
48
50
|
|
|
49
51
|
```
|
|
@@ -130,7 +132,7 @@ Good:
|
|
|
130
132
|
- `Observation: <one idea, what the diff actually does and where>`
|
|
131
133
|
- `Why it matters: <impact at realistic scale or on a real user path>`
|
|
132
134
|
- `Suggested direction: <one concrete next step, optional if the fix isn't obvious>`
|
|
133
|
-
- `Needs verification: <what you couldn't confirm from the bundle, optional, low/medium severity only>` This labelled paragraph is the only channel for uncertainty: never hedge inside another section, and never raise `severity` to compensate for what you couldn't verify (a blocker/high you cannot stand behind is not a blocker/high). Use the exact `Needs verification:` prefix, not inline phrasing. When
|
|
135
|
+
- `Needs verification: <what you couldn't confirm from the bundle, optional, low/medium severity only>` This labelled paragraph is the only channel for uncertainty: never hedge inside another section, and never raise `severity` to compensate for what you couldn't verify (a blocker/high you cannot stand behind is not a blocker/high). Use the exact `Needs verification:` prefix, not inline phrasing. When codebase intelligence is available, over either interface, and one query could answer the question, look before you hedge. A question you resolved is not a `Needs verification:` paragraph, it is evidence: cite the file:line you found under `Observation:` and omit the paragraph entirely.
|
|
134
136
|
|
|
135
137
|
One idea per paragraph. Do not collapse them into a single wall of text. Do not invent extra labels. If a section doesn't apply, omit it. The interactive report and the GitHub comment both parse these labels and render them as section headers, so missing labels degrade the output.
|
|
136
138
|
|
|
@@ -145,9 +147,67 @@ If you have no findings, write []. Return as your final tool result a single lin
|
|
|
145
147
|
|
|
146
148
|
## Codebase intelligence
|
|
147
149
|
|
|
148
|
-
Include
|
|
150
|
+
Include one of these blocks as part 5 when the context stage logged
|
|
151
|
+
`codeIntelligence: true`: the `-cli` block when it logged `interface: "cli"`, the
|
|
152
|
+
`-mcp` block when it logged `interface: "mcp"`. Both reach the same index. Never send
|
|
153
|
+
both: a specialist told about a verb it cannot invoke wastes turns discovering that.
|
|
149
154
|
|
|
150
|
-
```magpie-codebase-intelligence
|
|
155
|
+
```magpie-codebase-intelligence-cli
|
|
156
|
+
## Codebase intelligence
|
|
157
|
+
|
|
158
|
+
The `code-intel` CLI queries an index of this exact worktree, including the PR's own
|
|
159
|
+
changes. Every invocation names the workspace with `--repo <RUN_DIR>/worktree`, so
|
|
160
|
+
there is nothing to bind and nothing another agent can change under you. Always pass
|
|
161
|
+
`--json`.
|
|
162
|
+
|
|
163
|
+
These answer the cross-file questions a diff cannot:
|
|
164
|
+
|
|
165
|
+
code-intel ask --repo <RUN_DIR>/worktree --json "<question>"
|
|
166
|
+
A natural-language question answered with grounded evidence. Start here when you
|
|
167
|
+
do not yet know which symbol to pivot on.
|
|
168
|
+
code-intel search --repo <RUN_DIR>/worktree --context snippets --json "<query>"
|
|
169
|
+
Hybrid semantic and literal search. Use to check whether something already
|
|
170
|
+
exists before claiming the PR should add it. Hits carry `id`s.
|
|
171
|
+
code-intel hydrate --repo <RUN_DIR>/worktree --ids <id,id> --json
|
|
172
|
+
The exact bodies behind ids a search returned, without re-reading whole files.
|
|
173
|
+
code-intel definition --repo <RUN_DIR>/worktree --json <symbol>
|
|
174
|
+
The body of a symbol the diff calls but does not show.
|
|
175
|
+
code-intel references --repo <RUN_DIR>/worktree --json <symbol>
|
|
176
|
+
code-intel call-hierarchy --repo <RUN_DIR>/worktree --json <symbol>
|
|
177
|
+
Who calls this, and what does it call. Use for reachability: is the path you are
|
|
178
|
+
worried about actually reachable. Add `--direction callers|callees`, `--depth N`.
|
|
179
|
+
code-intel investigate --repo <RUN_DIR>/worktree --mode impact --target <symbol> --json "<question>"
|
|
180
|
+
The reverse-dependency set for a symbol. Use for blast radius before claiming a
|
|
181
|
+
change is safe or unsafe.
|
|
182
|
+
code-intel investigate --repo <RUN_DIR>/worktree --mode data --target <symbol> --json "<question>"
|
|
183
|
+
Follow a value from its origin to where it is used. Use to confirm that
|
|
184
|
+
untrusted input actually reaches the sink you are worried about.
|
|
185
|
+
code-intel dependency-graph --repo <RUN_DIR>/worktree --json <symbol>
|
|
186
|
+
Module-level edges. Use for cycles and boundaries.
|
|
187
|
+
|
|
188
|
+
There is no test-coverage command: to find out whether the symbol you are flagging is
|
|
189
|
+
covered, run `references` on it and read the paths for test files.
|
|
190
|
+
|
|
191
|
+
Exit codes are the contract, not the prose: 5 means no results, which is an answer and
|
|
192
|
+
not a reason to fall back to grep. 3 means the daemon is down and 4 means the workspace
|
|
193
|
+
is not queryable; either way, stop querying and review from the diff and worktree.
|
|
194
|
+
|
|
195
|
+
Rules:
|
|
196
|
+
|
|
197
|
+
- Cite what you find as ordinary `file:line` evidence under `Observation:`. Do not
|
|
198
|
+
say "code intelligence told me"; the location is the evidence.
|
|
199
|
+
- Verify before you report. A finding you could have refuted with one query and did
|
|
200
|
+
not is worse than no finding: it costs the author trust and the critic a slot.
|
|
201
|
+
- Verify before you hedge. If a query can answer the question, a `Needs verification:`
|
|
202
|
+
paragraph is a failure to look, not honest uncertainty.
|
|
203
|
+
- If a command fails with `error.code: workspace_unavailable` and an
|
|
204
|
+
`indexing_in_progress` message, finish reading the diff and retry once. If it is
|
|
205
|
+
still not ready, review from the diff and worktree alone. Do not block.
|
|
206
|
+
- Never run `code-intel index approve`. Never run `code-intel index refresh`. Starting
|
|
207
|
+
a full index is a consent-gated operation that is not yours to start.
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```magpie-codebase-intelligence-mcp
|
|
151
211
|
## Codebase intelligence
|
|
152
212
|
|
|
153
213
|
You have code-intelligence MCP tools against an index of this exact worktree,
|
|
@@ -237,7 +297,7 @@ For each potential finding:
|
|
|
237
297
|
2. Identify the trust boundary: is this crossing from untrusted to trusted context?
|
|
238
298
|
3. Assess exploitability: can an attacker realistically trigger this?
|
|
239
299
|
4. Evaluate impact: what's the blast radius if exploited?
|
|
240
|
-
5. Confirm the flow
|
|
300
|
+
5. Confirm the flow from the entry point to the sink before reporting, with `code-intel investigate --mode data --target <symbol>` or `trace_data_flow` depending on which interface your intelligence block describes. A taint path you asserted but did not trace is a guess.
|
|
241
301
|
|
|
242
302
|
**Risk guide:**
|
|
243
303
|
- blocker: Realistic path to remote code execution, auth bypass, data breach, or privilege escalation
|
|
@@ -302,7 +362,7 @@ For each potential bug:
|
|
|
302
362
|
3. What's the consequence: crash, data corruption, silent wrong behavior?
|
|
303
363
|
4. Is there an existing guard I'm not seeing?
|
|
304
364
|
|
|
305
|
-
Question 4 is answerable:
|
|
365
|
+
Question 4 is answerable: a call hierarchy on the changed symbol shows every caller, and its references show where the guard would have to live (`code-intel call-hierarchy` / `code-intel references`, or `get_call_hierarchy` / `find_references` on MCP). Check before you file.
|
|
306
366
|
|
|
307
367
|
**Risk guide:**
|
|
308
368
|
- blocker: Data loss, data corruption, broken auth/session behavior, or consistently crashing a major workflow
|
|
@@ -362,7 +422,7 @@ For each potential issue:
|
|
|
362
422
|
2. How often does this code path execute? (once on init vs. every keystroke)
|
|
363
423
|
3. What's the measurable impact? (milliseconds vs. seconds)
|
|
364
424
|
4. Is the optimization worth the complexity cost?
|
|
365
|
-
5. Establish the call frequency
|
|
425
|
+
5. Establish the call frequency before claiming a path is hot, with `code-intel investigate --mode impact --target <symbol>` or `find_affected_code`. "Called from one cold init path" and "called per keystroke" are different findings.
|
|
366
426
|
|
|
367
427
|
**Risk guide:**
|
|
368
428
|
- blocker: Change can make a major workflow unusable or cause unbounded production resource exhaustion
|
|
@@ -424,7 +484,7 @@ For each potential smell:
|
|
|
424
484
|
2. Confirm the smell is introduced or materially worsened by this PR, not merely pre-existing nearby code.
|
|
425
485
|
3. Suggest the smallest refactor that fits the surrounding codebase patterns.
|
|
426
486
|
4. Weigh the cost: do not ask for a new abstraction unless it reduces real duplication, coupling, or reasoning burden now.
|
|
427
|
-
5. Before claiming the PR duplicates something or should reuse an existing helper, find it
|
|
487
|
+
5. Before claiming the PR duplicates something or should reuse an existing helper, find it: `code-intel search --context snippets` or `search_code`. Name the file:line of the thing it should have reused, or do not make the claim.
|
|
428
488
|
|
|
429
489
|
**Risk guide:**
|
|
430
490
|
- blocker: Smell creates a high-risk maintenance trap likely to cause defects across modules soon
|
|
@@ -483,7 +543,7 @@ For each potential issue:
|
|
|
483
543
|
2. Is this coupling necessary or incidental?
|
|
484
544
|
3. Would a new team member understand where to make changes?
|
|
485
545
|
4. Is this over-engineered for the current requirements, or appropriately future-proofed?
|
|
486
|
-
5. Confirm boundary and cycle claims
|
|
546
|
+
5. Confirm boundary and cycle claims on the touched modules with `code-intel dependency-graph` or `explore_dependency_graph`. A cycle you inferred from import statements in the diff may already be broken by an interface you cannot see.
|
|
487
547
|
|
|
488
548
|
**Risk guide:**
|
|
489
549
|
- blocker: Change introduces a serious boundary violation or contract break likely to cascade across subsystems
|
|
@@ -117,16 +117,63 @@ test('SKILL.md no longer inlines the prompt bodies it moved out', async () => {
|
|
|
117
117
|
expect(text).not.toContain(`\`\`\`${tag}`)
|
|
118
118
|
}
|
|
119
119
|
// The walkthrough is the always-read part; keep it small enough to be cheap.
|
|
120
|
-
// Raised from 2600 when the sharded-dispatch and fallback-diff prose was added
|
|
121
|
-
// that's real,
|
|
122
|
-
|
|
120
|
+
// Raised from 2600 when the sharded-dispatch and fallback-diff prose was added,
|
|
121
|
+
// then from 3000 for the two code-intelligence interfaces: that's real,
|
|
122
|
+
// load-bearing procedure, not bloat.
|
|
123
|
+
expect(text.split(/\s+/).length).toBeLessThan(3250)
|
|
123
124
|
})
|
|
124
125
|
|
|
125
126
|
test('SKILL.md never instructs the agent to approve indexing', async () => {
|
|
126
127
|
const text = await readFile(SKILL, 'utf8')
|
|
127
128
|
// A full index is a consent-gated GPU pass. The context stage degrades instead.
|
|
129
|
+
// Both interfaces expose the same footgun under different names, so both are named.
|
|
128
130
|
expect(text).toContain('approve_indexing')
|
|
129
131
|
expect(text).toMatch(/never call `approve_indexing`|do not call `approve_indexing`/i)
|
|
132
|
+
expect(text).toMatch(
|
|
133
|
+
/never run `code-intel index approve`|do not run `code-intel index approve`/i,
|
|
134
|
+
)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('SKILL.md stage 3 probes the code-intel CLI before the MCP tools', async () => {
|
|
138
|
+
const text = await readFile(SKILL, 'utf8')
|
|
139
|
+
const start = text.indexOf('### 3. Context')
|
|
140
|
+
expect(start).toBeGreaterThan(-1)
|
|
141
|
+
const section = text.slice(start, text.indexOf('\n### 4.', start))
|
|
142
|
+
// Both interfaces drive the same daemon, but the CLI names the workspace on every
|
|
143
|
+
// call, so it carries no session binding to leak past cleanup. Prefer it.
|
|
144
|
+
expect(section).toContain('command -v code-intel')
|
|
145
|
+
expect(section).toContain('mcp__code-intelligence__')
|
|
146
|
+
expect(section.indexOf('code-intel')).toBeLessThan(section.indexOf('mcp__code-intelligence__'))
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('SKILL.md gives CODE_INTELLIGENCE a value per interface', async () => {
|
|
150
|
+
const text = await readFile(SKILL, 'utf8')
|
|
151
|
+
// The scout and specialist prompts branch on this, so all three values must be
|
|
152
|
+
// spelled out where the probe assigns them.
|
|
153
|
+
for (const value of [
|
|
154
|
+
'CODE_INTELLIGENCE=cli',
|
|
155
|
+
'CODE_INTELLIGENCE=mcp',
|
|
156
|
+
'CODE_INTELLIGENCE=unavailable',
|
|
157
|
+
]) {
|
|
158
|
+
expect(text).toContain(value)
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('the rebind instruction is scoped to the MCP interface everywhere it appears', async () => {
|
|
163
|
+
const text = await readFile(SKILL, 'utf8')
|
|
164
|
+
// A CLI run holds no session binding, so an unconditional rebind sends the agent
|
|
165
|
+
// after an MCP tool that is not in its tool list.
|
|
166
|
+
const spans: ReadonlyArray<readonly [string, string]> = [
|
|
167
|
+
['### 4. Specialists', '\n### 5.'],
|
|
168
|
+
['### 10. Cleanup', '\n## '],
|
|
169
|
+
['## Aborting', ''],
|
|
170
|
+
]
|
|
171
|
+
for (const [from, to] of spans) {
|
|
172
|
+
const start = text.indexOf(from)
|
|
173
|
+
expect(start).toBeGreaterThan(-1)
|
|
174
|
+
const section = to ? text.slice(start, text.indexOf(to, start)) : text.slice(start)
|
|
175
|
+
expect(section).toMatch(/CODE_INTELLIGENCE=mcp|MCP path/)
|
|
176
|
+
}
|
|
130
177
|
})
|
|
131
178
|
|
|
132
179
|
test('SKILL.md logs codeIntelligence on both the done and skipped context outcomes', async () => {
|
|
@@ -295,34 +342,69 @@ test('SKILL.md has the stage walkthrough', async () => {
|
|
|
295
342
|
expect(text).toMatch(/magpie cleanup/)
|
|
296
343
|
})
|
|
297
344
|
|
|
298
|
-
|
|
345
|
+
const intelligenceBlock = (text: string, iface: 'cli' | 'mcp') => {
|
|
346
|
+
const fence = `\`\`\`magpie-codebase-intelligence-${iface}`
|
|
347
|
+
const start = text.indexOf(fence)
|
|
348
|
+
expect(start).toBeGreaterThan(-1)
|
|
349
|
+
return text.slice(start, text.indexOf('\n```', start + fence.length))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
test('references/specialists.md carries a codebase-intelligence block per interface', async () => {
|
|
353
|
+
const text = await readFile(ref('specialists.md'), 'utf8')
|
|
354
|
+
for (const iface of ['cli', 'mcp'] as const) {
|
|
355
|
+
const block = intelligenceBlock(text, iface)
|
|
356
|
+
expect(block).toContain('indexing_in_progress')
|
|
357
|
+
// The one operation a specialist must never perform, under either name.
|
|
358
|
+
expect(block).toMatch(/never (call `approve_indexing`|run `code-intel index approve`)/i)
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
test('the CLI intelligence block names the workspace per call instead of binding', async () => {
|
|
363
|
+
const text = await readFile(ref('specialists.md'), 'utf8')
|
|
364
|
+
const block = intelligenceBlock(text, 'cli')
|
|
365
|
+
// The CLI has no bind_workspace: every invocation carries --repo, which is what
|
|
366
|
+
// lets the five specialists query the same worktree in parallel without a
|
|
367
|
+
// session binding they could clobber for each other.
|
|
368
|
+
expect(block).not.toContain('bind_workspace')
|
|
369
|
+
expect(block).toContain('--repo')
|
|
370
|
+
expect(block).toContain('--json')
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
test('the MCP intelligence block still binds the workspace first', async () => {
|
|
299
374
|
const text = await readFile(ref('specialists.md'), 'utf8')
|
|
300
|
-
expect(text).toContain('
|
|
301
|
-
const start = text.indexOf('```magpie-codebase-intelligence')
|
|
302
|
-
const block = text.slice(start, text.indexOf('```', start + 32))
|
|
303
|
-
expect(block).toContain('bind_workspace')
|
|
304
|
-
expect(block).toContain('indexing_in_progress')
|
|
305
|
-
// The one operation a specialist must never perform.
|
|
306
|
-
expect(block).toMatch(/never call `approve_indexing`|do not call `approve_indexing`/i)
|
|
375
|
+
expect(intelligenceBlock(text, 'mcp')).toContain('bind_workspace')
|
|
307
376
|
})
|
|
308
377
|
|
|
309
|
-
test('every focus block names
|
|
378
|
+
test('every focus block names its intelligence capability on both interfaces', async () => {
|
|
310
379
|
const text = await readFile(ref('specialists.md'), 'utf8')
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
'code-
|
|
316
|
-
|
|
380
|
+
// A focus block reaches whichever interface the probe found, so naming only the
|
|
381
|
+
// MCP tool leaves a CLI specialist with a verb it cannot invoke.
|
|
382
|
+
const tools: Record<(typeof FOCUSES)[number], readonly [string, string]> = {
|
|
383
|
+
security: ['trace_data_flow', 'investigate --mode data'],
|
|
384
|
+
bugs: ['get_call_hierarchy', 'code-intel call-hierarchy'],
|
|
385
|
+
performance: ['find_affected_code', 'investigate --mode impact'],
|
|
386
|
+
'code-smells': ['search_code', 'code-intel search'],
|
|
387
|
+
architecture: ['explore_dependency_graph', 'code-intel dependency-graph'],
|
|
317
388
|
}
|
|
318
389
|
for (const focus of FOCUSES) {
|
|
319
390
|
const fence = `\`\`\`magpie-specialist-${focus}`
|
|
320
391
|
const start = text.indexOf(fence)
|
|
321
392
|
const block = text.slice(start, text.indexOf('```', start + fence.length))
|
|
322
|
-
expect(block).toContain(
|
|
393
|
+
for (const tool of tools[focus]) expect(block).toContain(tool)
|
|
323
394
|
}
|
|
324
395
|
})
|
|
325
396
|
|
|
397
|
+
test('references/scout.md documents both intelligence interfaces', async () => {
|
|
398
|
+
const text = await readFile(ref('scout.md'), 'utf8')
|
|
399
|
+
// The scout is dispatched with the same <<CODE_INTELLIGENCE>> value the
|
|
400
|
+
// specialists get, so it has to know what `cli` and `mcp` each mean.
|
|
401
|
+
expect(text).toContain('`cli`')
|
|
402
|
+
expect(text).toContain('`mcp`')
|
|
403
|
+
expect(text).toContain('code-intel ')
|
|
404
|
+
expect(text).toContain('bind_workspace')
|
|
405
|
+
expect(text).toMatch(/never (call `approve_indexing`|run `code-intel index approve`)/i)
|
|
406
|
+
})
|
|
407
|
+
|
|
326
408
|
test('the output contract tells specialists to look before they hedge', async () => {
|
|
327
409
|
const text = await readFile(ref('specialists.md'), 'utf8')
|
|
328
410
|
const contract = text.slice(0, text.indexOf('```magpie-specialist-'))
|
package/skills/magpie/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magpie",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Interactive PR review pipeline. Runs five parallel specialist subagents (security, bugs, performance, code-smells, architecture), dedupes findings, applies a critic rubric, peer-reviews via codex exec (falling back to a Claude second opinion when codex is unavailable), and serves an interactive HTML report for selecting findings to post via gh. Bundles a Bun CLI installed onto PATH via the skill's postinstall step. Use when the user asks to review a GitHub pull request. Splits oversized diffs into budgeted shards and rebuilds the diff from the local clone when gh pr diff refuses it.",
|
|
5
5
|
"author": "iceinvein",
|
|
6
6
|
"type": "prompt",
|
|
@@ -36,9 +36,11 @@ follow from that being worth guaranteeing: a value beginning with `--` is
|
|
|
36
36
|
rejected rather than accepted as a value, and a flag with no value at all is
|
|
37
37
|
rejected rather than taking the next flag as one.
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
The directory ignores itself: `init` drops a `.gitignore` holding `*` next to
|
|
40
|
+
the state, so no project has to add a line of its own. It is working state, and
|
|
41
|
+
everything durable in it lands somewhere else anyway: the commits are in git and
|
|
42
|
+
the reasons are in the record, which is the file that does get committed. Delete
|
|
43
|
+
that `.gitignore` if you want a run tracked; it is only written when absent.
|
|
42
44
|
|
|
43
45
|
Open it with `init` when you open the run record, at the same point and for the
|
|
44
46
|
same reason, then seed the rows with `plan.sh import <plan>` rather than a
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
# status.sh close
|
|
20
20
|
#
|
|
21
21
|
# --dir <path> selects the tree to read (default: $PWD). State lives at
|
|
22
|
-
# <dir>/.sluice/run.json and closed runs at <dir>/.sluice/archive/.
|
|
22
|
+
# <dir>/.sluice/run.json and closed runs at <dir>/.sluice/archive/. The
|
|
23
|
+
# directory ignores itself, so no project needs a .gitignore line for it.
|
|
23
24
|
#
|
|
24
25
|
# Exit: 0 ok, 1 the state could not be written, 2 no live run, 3 a run is
|
|
25
26
|
# already live, 4 bad arguments, 5 jq missing, 6 the state file is unreadable.
|
|
@@ -220,6 +221,17 @@ require_readable() {
|
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
|
|
224
|
+
# The run state is working state, not history: the run record is what gets
|
|
225
|
+
# committed. So the directory ignores itself, rather than every repo sluice ever
|
|
226
|
+
# runs in having to add a line to its own .gitignore. `*` matches the .gitignore
|
|
227
|
+
# file too, so the whole directory drops out of `git status`. An existing file is
|
|
228
|
+
# left alone, and a tree that refuses the write still gets its run.
|
|
229
|
+
mk_dir() { # <directory to create under .sluice>
|
|
230
|
+
mkdir -p "$1" || { err "could not create $1"; exit 1; }
|
|
231
|
+
local ignore="$DIR/.sluice/.gitignore"
|
|
232
|
+
[ -e "$ignore" ] || printf '*\n' >"$ignore" 2>/dev/null || true
|
|
233
|
+
}
|
|
234
|
+
|
|
223
235
|
# Written through a temporary file so an interrupted write cannot leave the
|
|
224
236
|
# run state half-serialised, which would read as a corrupted run rather than
|
|
225
237
|
# as a failed command.
|
|
@@ -263,7 +275,7 @@ case "$SUB" in
|
|
|
263
275
|
exit 3
|
|
264
276
|
fi
|
|
265
277
|
|
|
266
|
-
|
|
278
|
+
mk_dir "$DIR/.sluice"
|
|
267
279
|
jq -n \
|
|
268
280
|
--arg topic "$TOPIC" \
|
|
269
281
|
--arg channel "$CHANNEL" \
|
|
@@ -526,7 +538,7 @@ case "$SUB" in
|
|
|
526
538
|
stamp="$(printf '%s' "$started" | tr -cd '0-9TZ')"
|
|
527
539
|
slug="$(printf '%s' "${topic:-run}" | tr -cs 'A-Za-z0-9._-' '-')"
|
|
528
540
|
[ -n "$stamp" ] || stamp="unknown"
|
|
529
|
-
|
|
541
|
+
mk_dir "$ARCHIVE"
|
|
530
542
|
|
|
531
543
|
# The archive holds the only copy of a closed run, and two runs sharing a
|
|
532
544
|
# start second and a topic name the same file. mv would leave one of them,
|
package/skills/sluice/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sluice",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment and one status command can answer where the run is, and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
|
|
5
5
|
"author": "iceinvein",
|
|
6
6
|
"type": "prompt",
|