claude-code-session-manager 0.37.1 → 0.38.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/bin/cli.cjs +12 -1
- package/dist/assets/{TiptapBody-DXQDiOUx.js → TiptapBody-GMk5LS9Y.js} +1 -1
- package/dist/assets/index-CD_LuJZF.css +32 -0
- package/dist/assets/{index--a8m5_ET.js → index-CQqSHpIq.js} +444 -436
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/plugins/session-manager-dev/skills/develop/SKILL.md +134 -36
- package/plugins/session-manager-dev/skills/develop/standards.md +25 -0
- package/plugins/session-manager-dev/skills/issue-address/0-select/0-fetch-pool/SKILL.md +38 -0
- package/plugins/session-manager-dev/skills/issue-address/0-select/1-reject-fixed/SKILL.md +64 -0
- package/plugins/session-manager-dev/skills/issue-address/0-select/2-reject-claimed/SKILL.md +71 -0
- package/plugins/session-manager-dev/skills/issue-address/0-select/3-rank-impact/SKILL.md +39 -0
- package/plugins/session-manager-dev/skills/issue-address/0-select/SKILL.md +75 -0
- package/plugins/session-manager-dev/skills/issue-address/1-confirm-open/SKILL.md +39 -0
- package/plugins/session-manager-dev/skills/issue-address/2-claim/SKILL.md +57 -0
- package/plugins/session-manager-dev/skills/issue-address/3-reproduce/SKILL.md +40 -0
- package/plugins/session-manager-dev/skills/issue-address/4-fix/SKILL.md +33 -0
- package/plugins/session-manager-dev/skills/issue-address/5-verify/SKILL.md +40 -0
- package/plugins/session-manager-dev/skills/issue-address/SKILL.md +120 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/0-fetch/SKILL.md +41 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/1-classify/SKILL.md +45 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/2-check-fixed/SKILL.md +49 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/3-queue/SKILL.md +50 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/4-land-and-resolve/SKILL.md +60 -0
- package/plugins/session-manager-dev/skills/pr-review-sweep/SKILL.md +124 -0
- package/plugins/session-manager-dev/skills/pr-signal/SKILL.md +67 -0
- package/plugins/session-manager-dev/skills/requesting-code-review/SKILL.md +20 -17
- package/scripts/lib/watchdogHelpers.cjs +296 -166
- package/src/main/__tests__/chat-cancel-terminal.test.cjs +31 -0
- package/src/main/__tests__/chat-exit-close-race.test.cjs +140 -0
- package/src/main/__tests__/classifyTranscriptLine.test.cjs +90 -0
- package/src/main/__tests__/docEdit.test.cjs +164 -2
- package/src/main/__tests__/prdCreate.test.cjs +265 -25
- package/src/main/__tests__/scheduler-admin-routes.test.cjs +150 -0
- package/src/main/__tests__/scheduler-boot-orphans.test.cjs +172 -0
- package/src/main/__tests__/scheduler-committed-in-window.test.cjs +64 -0
- package/src/main/browserAgentServer.cjs +11 -10
- package/src/main/chatRunner.cjs +58 -14
- package/src/main/docEdit.cjs +125 -5
- package/src/main/health.cjs +15 -0
- package/src/main/index.cjs +12 -6
- package/src/main/ipcSchemas.cjs +16 -3
- package/src/main/lib/__tests__/localAdminHttp.test.cjs +120 -0
- package/src/main/lib/classifyTranscriptLine.cjs +89 -0
- package/src/main/lib/localAdminHttp.cjs +157 -0
- package/src/main/lib/personaImportHealth.cjs +161 -0
- package/src/main/lib/prdCreate.cjs +107 -17
- package/src/main/lib/rcaFeedbackHook.cjs +2 -2
- package/src/main/lib/singleInstanceGuard.cjs +20 -0
- package/src/main/scheduler.cjs +223 -56
- package/src/main/sessionsStore.cjs +4 -5
- package/src/main/templates/PRD_AUTHORING.md +4 -4
- package/src/main/transcripts.cjs +1 -85
- package/src/main/webRemote.cjs +3 -3
- package/src/preload/api.d.ts +16 -6
- package/src/preload/index.cjs +9 -2
- package/dist/assets/index-CTTjT08J.css +0 -32
- package/plugins/session-manager-dev/skills/security-review/SKILL.md +0 -105
- package/src/main/__tests__/adminServer.test.cjs +0 -380
- package/src/main/adminServer.cjs +0 -242
package/dist/index.html
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400&family=Geist:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
-
<script type="module" crossorigin src="./assets/index
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-CQqSHpIq.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CD_LuJZF.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body class="bg-bg text-fg font-sans antialiased">
|
|
16
16
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Local cockpit for the Claude Code CLI — multi-tab terminal, full config surface, scheduler, voice dictation, and live observability.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/main/index.cjs",
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
name: develop
|
|
3
3
|
description: >-
|
|
4
4
|
Lead a software-development task by decomposing a feature/refactor/bugfix prompt into a
|
|
5
|
-
series of self-contained PRDs queued for the session-manager scheduler, each
|
|
6
|
-
engineering standards
|
|
7
|
-
to completion, verify them against their acceptance criteria, and report back. Use whenever
|
|
5
|
+
series of self-contained PRDs queued for the session-manager scheduler, each pointing the
|
|
6
|
+
headless executor at the engineering standards file to read at runtime — then track those
|
|
7
|
+
PRDs to completion, verify them against their acceptance criteria, and report back. Use whenever
|
|
8
8
|
the user says "/develop", "develop X", "build me X", "implement X", "let's code X", or
|
|
9
9
|
otherwise starts dev work that should run as scheduled PRDs rather than inline now. This
|
|
10
10
|
skill is the home for the developer-only guidance (performance, debugging, API-reuse, TDD)
|
|
@@ -41,16 +41,18 @@ The engineering standards (Performance, Debugging, API reuse / single source of
|
|
|
41
41
|
and the executor-facing Execution discipline) live in **`standards.md`** beside this file, in
|
|
42
42
|
the same skill directory (`.../skills/develop/standards.md` — NOT `~/.claude/skills/develop/`,
|
|
43
43
|
which is a different, non-existent path; resolve it relative to wherever this SKILL.md itself
|
|
44
|
-
was loaded from).
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
was loaded from).
|
|
45
|
+
|
|
46
|
+
**Reference it, don't embed it.** The headless executor (`claude -p`) runs on the same
|
|
47
|
+
filesystem this authoring session does, with full tool access — so a PRD only needs to name
|
|
48
|
+
`standards.md`'s absolute path (resolved once, at authoring time, the same way this file already
|
|
49
|
+
resolves it) and instruct the executor to `Read` it before starting. There is now exactly one
|
|
50
|
+
copy of this text on disk, ever — no pasted snapshot to go stale, and nothing to re-read fresh
|
|
51
|
+
before writing (an earlier version of this skill pasted the full contents into every PRD and had
|
|
52
|
+
to warn authors to re-read it fresh each time to avoid shipping a stale in-context copy — PRDs
|
|
53
|
+
467/468 did exactly that and repeated an anti-pattern a guard added earlier the same session was
|
|
54
|
+
meant to prevent. Referencing by path removes the failure mode instead of warning against it).
|
|
55
|
+
Never restate or fork its content — one concept, one implementation, one location.
|
|
54
56
|
|
|
55
57
|
For interactive dev work, also apply the `test-driven-development` and `systematic-debugging`
|
|
56
58
|
skills; the headless PRDs get the distilled core from `standards.md` instead, since they
|
|
@@ -64,21 +66,85 @@ can't load skills.
|
|
|
64
66
|
caller is `/process-feedback`, scope is already established by its evaluation — don't
|
|
65
67
|
re-ask; build from the brief it hands you.)
|
|
66
68
|
|
|
67
|
-
2. **Explore the target repo
|
|
68
|
-
reuse (per the API-reuse standard — search before
|
|
69
|
-
any constraints. Capture exact file paths and
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
2. **Explore the target repo — broadly, not just the obvious file.** Identify the absolute
|
|
70
|
+
`cwd`, existing patterns/utilities to reuse (per the API-reuse standard — search before
|
|
71
|
+
writing new code), the test command, and any constraints. Capture exact file paths and
|
|
72
|
+
signatures; they go straight into the PRDs. Don't stop at the first component that looks
|
|
73
|
+
relevant — check its siblings too (does the same pattern appear in 2-3 similar components?
|
|
74
|
+
do they actually share the same shape, or only look similar — confirm by reading, don't
|
|
75
|
+
assume: a wrong assumption here means an inaccurate PRD, discovered only after the executor
|
|
76
|
+
runs it), check existing tests for the area, and check whether a prior PRD already touched
|
|
77
|
+
this subsystem (`ls ~/.claude/session-manager/scheduled-plans/prds/` for related slugs) —
|
|
78
|
+
duplicating or contradicting a still-queued PRD is a real failure mode, not a hypothetical one.
|
|
79
|
+
|
|
80
|
+
3. **Draft a candidate decomposition, then run a completeness pass before finalizing it.** This
|
|
81
|
+
step exists because small, bounded individual PRDs (step 4) are correct and non-negotiable —
|
|
82
|
+
but a *set* of small PRDs can still be incomplete if the upfront decomposition missed
|
|
83
|
+
something. Keeping PRDs small is not a substitute for getting the decomposition right; it's a
|
|
84
|
+
separate concern, and this step is where decomposition quality gets checked.
|
|
85
|
+
- For a **genuinely trivial ask** (one obvious PRD, no cross-file consequences) — skip
|
|
86
|
+
straight to step 4, no ceremony needed.
|
|
87
|
+
- For anything **larger than one or two obvious PRDs, or touching more than one
|
|
88
|
+
component/subsystem** — before finalizing, dispatch a second, independent agent (the Agent
|
|
89
|
+
tool, `subagent_type: "Explore"` or `"general-purpose"` — this is a single extra dispatch,
|
|
90
|
+
not the full multi-agent Workflow tool, and needs no special opt-in) with: the original ask
|
|
91
|
+
verbatim, your draft PRD list (titles + one-line goals), and the instruction to find what's
|
|
92
|
+
missing — uncovered edge cases, error-handling paths, tests, cross-file consequences,
|
|
93
|
+
components that share the same pattern but weren't included, anything the draft assumed
|
|
94
|
+
without verifying. Treat its findings as a second opinion to weigh, not an automatic
|
|
95
|
+
addition — fold real, concrete gaps into the PRD set (add, split, or adjust a PRD); dismiss
|
|
96
|
+
vague or speculative ones. For a large, multi-subsystem ask, it's fine to repeat this once
|
|
97
|
+
more after folding in the first round's findings (a second completeness pass on the revised
|
|
98
|
+
set) — stop once a pass turns up nothing new, don't loop indefinitely.
|
|
99
|
+
- **Check each drafted PRD against explicit concern dimensions, not just "does the feature
|
|
100
|
+
work"**: missing features/edge cases beyond the happy path, tests, security, and quality
|
|
101
|
+
(perf, error handling). This is where depth actually comes from — a decomposition that only
|
|
102
|
+
ever asks "what file does this touch" produces exactly the narrow, single-concern PRDs this
|
|
103
|
+
step exists to catch.
|
|
104
|
+
- **Tests and security are NOT separate follow-up PRDs — they are mandatory AC lines inside
|
|
105
|
+
the SAME PRD as the feature they belong to.** This is non-negotiable: `standards.md`'s TDD
|
|
106
|
+
rule requires the test before/with the implementation, not after, and a security concern
|
|
107
|
+
(input validation at a boundary, auth checks, no string-built queries) is a decision made
|
|
108
|
+
while writing the code — a later "security review PRD" would just end up re-touching the
|
|
109
|
+
same lines, doubling work and leaving the shipped code insecure in the meantime. Every
|
|
110
|
+
feature PRD's own Acceptance Criteria must include its test command AND, when it touches
|
|
111
|
+
input/auth/data, the relevant security checks — don't spin these out.
|
|
112
|
+
- **Genuinely separable work MAY become its own sibling PRD**: deeper edge-case coverage
|
|
113
|
+
beyond what the core AC needs to prove correctness, performance/observability hardening,
|
|
114
|
+
docs. Splitting these out is exactly the "more isolated, narrower PRDs" instinct — apply
|
|
115
|
+
it here, where a dedicated PRD adds real value, not to tests/security where it subtracts
|
|
116
|
+
from correctness.
|
|
117
|
+
- This is a planning-quality step, not an execution step — it happens entirely in the
|
|
118
|
+
interactive main-loop session, before anything gets written to disk or queued.
|
|
119
|
+
|
|
120
|
+
4. **Decompose into a series of SMALL, bounded PRDs.** Split the (now completeness-checked)
|
|
121
|
+
decomposition into individually small PRDs and sequence them.
|
|
122
|
+
|
|
123
|
+
**Prefer creating each PRD via the `scheduler_create_prd` MCP tool**
|
|
124
|
+
(`mcp__session-manager-scheduler__scheduler_create_prd`) over hand-writing the file. Its input
|
|
125
|
+
(`title`, `cwd`, `estimateMinutes`, `goal`, `acceptanceCriteria[]`, `implementationNotes`,
|
|
126
|
+
`outOfScope[]`) maps directly onto the sections below — pass them straight through. It
|
|
127
|
+
allocates the parallel-group `NN` atomically (no read-then-write race against another
|
|
128
|
+
concurrent `/develop`/`/process-feedback` invocation), derives and collision-checks the slug,
|
|
129
|
+
and embeds the standards pointer for you. Set `parallelGroup` explicitly only when this PRD
|
|
130
|
+
must share an existing sibling's `NN` (a logically independent PRD that can run in parallel
|
|
131
|
+
with one already queued); omit it to get the next free `NN` atomically.
|
|
132
|
+
|
|
133
|
+
**Fallback — only when the tool errors with "app not running" / admin API unreachable**
|
|
134
|
+
(the session-manager Electron app must be running for this MCP tool to work; if it isn't,
|
|
135
|
+
don't block on it): compute the highest in-use number deterministically yourself — never
|
|
136
|
+
eyeball or narrow-grep the `ls` (a narrowed pattern like `'^10[0-9]'` silently misses `110+`
|
|
137
|
+
and collides):
|
|
75
138
|
```bash
|
|
76
139
|
ls ~/.claude/session-manager/scheduled-plans/prds/ | grep -oE '^[0-9]+' | sort -n | uniq | tail -5
|
|
77
140
|
```
|
|
78
141
|
The last line is the current max. Then: same `NN` as a logically independent sibling that
|
|
79
142
|
can run in parallel; **next free `NN` = max+1** when this PRD hard-depends on prior work or
|
|
80
|
-
is unrelated to every existing group.
|
|
81
|
-
|
|
143
|
+
is unrelated to every existing group. This manual path has a small, accepted race (two
|
|
144
|
+
concurrent authors could compute the same "next free" `NN`) — cosmetic (two unrelated groups
|
|
145
|
+
end up sharing a number) rather than destructive, and only reachable when the atomic tool
|
|
146
|
+
path above isn't available. Record each cross-PRD dependency in the dependent PRD's notes
|
|
147
|
+
either way.
|
|
82
148
|
|
|
83
149
|
### PRD structure and location
|
|
84
150
|
|
|
@@ -166,12 +232,24 @@ can't load skills.
|
|
|
166
232
|
failure** — it's the scheduler's designed auto-pause; the job auto-resumes at the next
|
|
167
233
|
window reset. Don't add retry logic for it.
|
|
168
234
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
235
|
+
5. **Emit each PRD.** If you used `scheduler_create_prd`, this step is already done — the tool
|
|
236
|
+
wrote the file to the canonical path with the standards pointer included; skip to step 5.
|
|
237
|
+
**Fallback path only:** write to the canonical path and structure above, then **append `##
|
|
238
|
+
Engineering standards` with a one-line pointer**, not the file's contents:
|
|
239
|
+
```markdown
|
|
240
|
+
## Engineering standards
|
|
241
|
+
|
|
242
|
+
Before writing any code, read `<absolute path to standards.md, resolved above>` — it has the
|
|
243
|
+
Performance, Debugging, API-reuse, TDD, and Execution-discipline rules that apply to this PRD.
|
|
244
|
+
Every rule in it is mandatory, especially Execution discipline (bounded commands, verify
|
|
245
|
+
before done, the finish-protocol sentinel).
|
|
246
|
+
```
|
|
247
|
+
This is the load-bearing step — it's the only way the standards (incl. Execution discipline)
|
|
248
|
+
reach the headless run, and it now stays current automatically since the executor reads the
|
|
249
|
+
live file rather than a snapshot taken at authoring time. Honor the `PRD_AUTHORING.md` §10
|
|
250
|
+
pre-queue checklist.
|
|
173
251
|
|
|
174
|
-
|
|
252
|
+
6. **Confirm to the user**, per emitted PRD: filename, chosen `NN` + rationale
|
|
175
253
|
(parallel-with-X / serial-after-Y), `cwd`, and an ETA + token-cost ballpark. Note they can
|
|
176
254
|
"Run now" in the SchedulePanel or wait for `when-available` polling.
|
|
177
255
|
|
|
@@ -181,7 +259,7 @@ The queued PRDs run headlessly and can take a while. Don't fire-and-forget, and
|
|
|
181
259
|
hand off to a recurring check. `/process-feedback` delegates to this exact phase, so it is the
|
|
182
260
|
single definition of "tracked to done" for both entry paths.
|
|
183
261
|
|
|
184
|
-
|
|
262
|
+
7. **Watch the scheduler every ~30 min.** Start a 30-minute monitoring loop (`/loop 30m` over
|
|
185
263
|
this watch step, or a `ScheduleWakeup` at 1800s if self-pacing) scoped to the PRD ids you
|
|
186
264
|
emitted. On each tick, read the scheduler's job status (queue + run history under
|
|
187
265
|
`~/.claude/session-manager/scheduled-plans/`, or the SchedulePanel) and branch:
|
|
@@ -195,22 +273,42 @@ single definition of "tracked to done" for both entry paths.
|
|
|
195
273
|
your report rather than re-deriving the analysis, and let `/process-feedback` fold its
|
|
196
274
|
prevention hint back into future PRD authoring. A `rateLimited` exit-1 is the
|
|
197
275
|
scheduler's benign auto-pause (auto-resumes next window) — keep waiting, don't escalate.
|
|
198
|
-
- **All PRDs completed successfully** — go to step
|
|
276
|
+
- **All PRDs completed successfully** — go to step 8.
|
|
199
277
|
|
|
200
|
-
|
|
278
|
+
8. **Gate: definition of done** (same for both entry paths). Once the code has landed:
|
|
201
279
|
- **Verify live against each PRD's acceptance criteria** — run the health check, hit the
|
|
202
280
|
endpoint, show before/after. The headless run asserted its own test command; this is the
|
|
203
281
|
interactive confirmation it actually does what was asked.
|
|
204
|
-
-
|
|
205
|
-
|
|
206
|
-
|
|
282
|
+
- **Route to the specialist that actually matches what changed** — not always the generic
|
|
283
|
+
reviewer. This environment has dedicated agents that sit unused unless explicitly called;
|
|
284
|
+
match the PRD's surface to the right one before calling a major/risky change done:
|
|
285
|
+
- Touches an API's request/response shape, REST/GraphQL contract, or endpoint design →
|
|
286
|
+
dispatch `api-designer` (Agent tool).
|
|
287
|
+
- Touches auth, input handling, secrets, or data storage → dispatch `security-auditor` in
|
|
288
|
+
addition to the mandatory security AC the PRD's own execution already required — the
|
|
289
|
+
auditor catches what the executor's self-check might miss.
|
|
290
|
+
- Is a structural refactor (no behavior change intended) → dispatch `refactorer`.
|
|
291
|
+
- Is performance-sensitive or touches a hot path → dispatch `perf-profiler`.
|
|
292
|
+
- Adds or updates a dependency → dispatch `dependency-auditor`.
|
|
293
|
+
- Touches a database schema, migration, or table design → **no specialist exists for this
|
|
294
|
+
in this environment today.** Don't silently let the generic code-reviewer stand in for a
|
|
295
|
+
schema review it isn't specialized for — say so explicitly in your report ("schema change,
|
|
296
|
+
no dedicated reviewer available, manual review recommended") rather than implying coverage
|
|
297
|
+
that isn't there.
|
|
298
|
+
- Anything else, or a **major feature/risky change** not covered above — dispatch the
|
|
299
|
+
generic `requesting-code-review` skill (`code-reviewer` agent) as the default.
|
|
300
|
+
Fix Critical/Important findings from whichever specialist(s) ran before calling it done.
|
|
301
|
+
- **Report back**: what landed, PRD/commit refs, which specialist(s) reviewed it (or the
|
|
302
|
+
explicit "no specialist available" note), verification result, anything left open.
|
|
207
303
|
|
|
208
304
|
## References (reuse, don't duplicate)
|
|
209
305
|
|
|
210
306
|
- `~/.claude/session-manager/scheduled-plans/PRD_AUTHORING.md` — the §1–§10 safety rules.
|
|
211
|
-
- `standards.md` beside this file — the engineering + execution-discipline rules
|
|
307
|
+
- `standards.md` beside this file — the engineering + execution-discipline rules. Every PRD points the executor at its absolute path (see "Standards" above) rather than embedding a copy.
|
|
212
308
|
- `test-driven-development`, `systematic-debugging` — interactive dev sessions.
|
|
213
|
-
- `requesting-code-review` — the Phase-2 review gate
|
|
309
|
+
- `requesting-code-review` — the Phase-2 default review gate; `api-designer`, `security-auditor`,
|
|
310
|
+
`refactorer`, `perf-profiler`, `dependency-auditor` — specialist agents routed to by surface
|
|
311
|
+
area (see step 8) rather than always defaulting to the generic reviewer.
|
|
214
312
|
|
|
215
313
|
## Notes
|
|
216
314
|
|
|
@@ -50,6 +50,30 @@
|
|
|
50
50
|
- (Interactive sessions: the `test-driven-development` skill has the full red-green-refactor
|
|
51
51
|
workflow. Headless PRD runs can't load it — the three rules above are the load-bearing core.)
|
|
52
52
|
|
|
53
|
+
## Visual design (UI/visual acceptance criteria)
|
|
54
|
+
|
|
55
|
+
When a PRD's acceptance criteria touch UI or visual output and no design brief is given,
|
|
56
|
+
resolve the visual direction in this priority order — never substitute a generic default when
|
|
57
|
+
a higher-priority source exists:
|
|
58
|
+
|
|
59
|
+
1. **User-supplied design.** If the PRD or the conversation that spawned it includes a design
|
|
60
|
+
brief, mockup, brand palette, or explicit visual direction, use it verbatim.
|
|
61
|
+
2. **Existing project design system.** Before reaching for any external skill, check the repo
|
|
62
|
+
itself for an existing theme — CSS custom-property blocks, `tailwind.config.js`, a
|
|
63
|
+
design-tokens file, a component library already in use. Reuse and extend what's there
|
|
64
|
+
rather than introducing a second visual language into the same project.
|
|
65
|
+
3. **Only if neither exists**, invoke a design-oriented skill rather than eyeballing colors
|
|
66
|
+
from memory or hand-picking hex values (e.g. the bundled `dataviz` skill for
|
|
67
|
+
chart/table/dashboard work, or a `frontend-design`-class skill for overall aesthetic
|
|
68
|
+
direction) — and **render + screenshot both light and dark color-scheme modes** before
|
|
69
|
+
calling the work done. A palette validator that checks categorical/series colors does not
|
|
70
|
+
cover surrounding chrome tokens (panel/page/border) — those need their own contrast check
|
|
71
|
+
(WCAG relative luminance) and a visual look in each mode. "I checked light mode" is not "I
|
|
72
|
+
checked dark mode"; verify both, don't assume palette-reference hex values are safe by
|
|
73
|
+
construction. (Incident: a dashboard shipped with panel/page background contrast of
|
|
74
|
+
1.12:1 and a border at 1.34:1 in dark mode — both invisible — because only light mode was
|
|
75
|
+
ever rendered before the work was marked done.)
|
|
76
|
+
|
|
53
77
|
## Execution discipline (headless runs)
|
|
54
78
|
|
|
55
79
|
Data-driven from 400+ scheduler runs: long hangs (not bad code) are the dominant real failure, and "exited clean but left a red test" is the top verifier downgrade. These rules run at execution time — they are inlined into every PRD because the headless executor reads nothing else.
|
|
@@ -64,6 +88,7 @@ Data-driven from 400+ scheduler runs: long hangs (not bad code) are the dominant
|
|
|
64
88
|
- **Negative-assertion checks must exit 0 when clean.** A check that verifies the *absence* of something (a `grep` that should find nothing, "no leftover X", `diff` expecting no change) must return exit 0 on the clean case. A bare `grep` exits **1 on no-match** — so the *success* path surfaces as `is_error=true` and the verifier downgrades a perfect run to `needs_review`. Always invert: `if <detector>; then echo "HALT: <what was found>"; exit 1; fi; echo clean`. Never let the no-match/empty path carry the non-zero exit.
|
|
65
89
|
- **Recover or annotate every error — don't strand a Traceback in the transcript.** The verifier downgrades an otherwise-perfect run to `needs_review` when a `Traceback`/`Error` appears with *no visible recovery within ~10 lines* (the `transcript_errors` heuristic — the single most common false-positive on green deliverables). Two executor habits cause it: (1) **throwaway probes that error** — an inline `python -c` with a quoting/f-string slip, a wrong kwarg, a bad path. When a probe errors, immediately re-run the corrected version *or* print one line `# expected/handled: <why>` right after, so recovery is adjacent. Don't move on leaving a bare error as the last thing in that step. Prefer a small temp `.py` file over a fragile multi-quote `python -c` one-liner (inline f-string errors are the top source of stranded tracebacks). (2) See the timeout rule below.
|
|
66
90
|
- **An *expected* bounded-timeout (exit 124) must be annotated, not bare.** `timeout`-capping a genuinely long task you expect to hit the cap (a full-universe ingest, a long scan) is correct — but a bare `Exit code 124` reads as a failure to the verifier. Wrap it so the cap is a success-with-note: `timeout 120 <cmd> || { rc=$?; [ $rc -eq 124 ] && echo "hit time cap — idempotent/partial, rows persist incrementally; OK" || { echo "HALT: <cmd> failed rc=$rc"; exit 1; }; }`. (Distinguish 124 = expected cap from a real non-zero.) For work that legitimately needs longer than a safe cap, run it in the background and poll a bounded number of times rather than capping the foreground command.
|
|
91
|
+
- **Polling remote CI/job status: never `sleep N && <cmd>`, and annotate the pending exit code.** The harness hard-blocks a `sleep` chained to another command (`Blocked: sleep 90 followed by: gh pr checks ...`) and that block lands in the transcript as a bare `is_error=true` — usually in the last 20% of the run, right where the verifier weighs errors most. To wait for a remote run, use the tool's own blocking watcher under a hard cap: `timeout 600 gh run watch <run-id> --repo <owner>/<repo> --exit-status`. Also note `gh pr checks` is a **negative-assertion-shaped command**: it exits `8` while checks are pending and `1` when a check failed or none are reported — so the ordinary "still running" path is non-zero. Wrap it so the expected cases print a clean token rather than a bare error: `if out=$(timeout 60 gh pr checks <n> --repo <r> 2>&1); then echo "CI GREEN"; else rc=$?; echo "gh pr checks rc=$rc (8=pending, 1=fail/none) — expected/handled"; fi`. (Incident: PRD 745 fixed PR #188's Lint + Docs-integrity failures, pushed, and CI went fully green — but its `sleep 20 && gh pr checks` (exit 8) and `sleep 90 && gh pr checks` (harness-blocked) sat unannotated at the very end of the transcript and the run was flagged despite a truthful PASS and a landed commit.)
|
|
67
92
|
- **Finish so the verifier auto-clears you.** The scheduler appends a finish protocol that requires you to COMMIT your work and emit `SCHEDULER_VERDICT: PASS` (or `FAIL <reason>` + `exit 1`) as the literal last line. Honor it exactly: a *truthful* PASS plus a commit that landed during the run is what lets the verifier override incidental transcript noise (a grep hit containing "Error", a TDD red-phase run, a debug Traceback) instead of parking the job in `needs_review` for a human. A job that exits 0 with **uncommitted** changes, or with no PASS sentinel, is the #1 cause of needless `needs_review`. Never print PASS on a red gate — a lying PASS turns the verifier into a silent-failure shipper.
|
|
68
93
|
- **Don't leak expected-error text into tool output.** The verifier pattern-matches transcript content for `Traceback`/`FAIL`/`Error:`. When a step is *expected* to error (a TDD red-phase test, an availability/existence probe, a "should raise" assertion), don't let the raw exception land verbatim — capture it and surface a clean token instead: `if python -c '…' 2>/dev/null; then echo PROBE_OK; else echo PROBE_ABSENT; fi`, or pipe the noisy run through a matcher that prints only `RED (expected)` / `GREEN`. When you retry a transient failure, re-run the **same command with the same description** — the verifier's self-recovery detector pairs a failed call with a later identical-description call that succeeds and clears it.
|
|
69
94
|
- **End green: run the acceptance/test gate LAST, and let nothing error after it.** The post-run verifier scans the transcript and downgrades to `needs_review` on error markers — and weighs the *final* portion of the run most heavily (a tool error in the last ~20% trips it even if everything actually passed). So order the run so the last command is the green AC gate: do any intentionally-failing step (e.g. a TDD red test, an expected-nonzero probe) **early**, never after the gate. If you must demonstrate a failure late, capture it so it doesn't surface as a raw `is_error`/`Traceback` (`… 2>&1 | tail` inside a conditional, or assert on the captured text) rather than letting it hit the transcript bare.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:select:fetch-pool
|
|
3
|
+
description: Fetch the FULL open-issue pool on the current project's repo with bodies, with verified completeness (not just a fixed --limit guess). First sub-step of issue-address:select.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:select:fetch-pool
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Fetch with a generous limit, then verify nothing was truncated** — don't trust a
|
|
11
|
+
single fixed `--limit` the way an earlier version of this skill (and, separately,
|
|
12
|
+
`pr-review-sweep`'s original GraphQL query) did; both silently truncated real data on
|
|
13
|
+
this repo before. Converge instead of guessing:
|
|
14
|
+
```bash
|
|
15
|
+
LIMIT=100
|
|
16
|
+
while true; do
|
|
17
|
+
COUNT=$(gh issue list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --state open --limit "$LIMIT" --json number --jq 'length')
|
|
18
|
+
if [ "$COUNT" -lt "$LIMIT" ]; then break; fi # got everything — count came in under the cap
|
|
19
|
+
LIMIT=$((LIMIT * 2)) # cap was hit exactly — double and re-check
|
|
20
|
+
done
|
|
21
|
+
gh issue list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --state open --limit "$LIMIT" \
|
|
22
|
+
--json number,title,body,labels,assignees,comments,createdAt,reactionGroups
|
|
23
|
+
```
|
|
24
|
+
`COUNT == LIMIT` is the tell that you hit the ceiling, not the true end of the list —
|
|
25
|
+
never treat that as "done." Only stop once a fetch returns fewer results than it was
|
|
26
|
+
capped at.
|
|
27
|
+
|
|
28
|
+
2. **Fetch bodies, not just titles.** Title-only scanning is what let issue #180 get
|
|
29
|
+
picked without anyone reading its file/line citations first. `body` and `comments` are
|
|
30
|
+
required output fields, not optional — the next sub-steps depend on them.
|
|
31
|
+
|
|
32
|
+
3. **Also fetch `reactionGroups`** (👍/👎 counts) — a real, if imperfect, community-signal
|
|
33
|
+
input for `issue-address:select:rank-impact` later, beyond just label text.
|
|
34
|
+
|
|
35
|
+
## Output
|
|
36
|
+
|
|
37
|
+
The full, verified-complete list of open issues with bodies, labels, assignees, comments,
|
|
38
|
+
and reaction counts — handed to `issue-address:select:reject-fixed` next.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:select:reject-fixed
|
|
3
|
+
description: Reject candidates from issue-address:select:fetch-pool's pool that are already fixed in current code, by checking the actual file/behavior each issue cites against a freshly-fetched origin/main — semantically, not just a literal string grep. Second sub-step of issue-address:select.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:select:reject-fixed
|
|
7
|
+
|
|
8
|
+
The check that would have caught issue #180 before any other work started — its body
|
|
9
|
+
cited `apps/web/app/app.css` around specific line numbers, and the current code already
|
|
10
|
+
had the exact fix (`min-width: 0`) the issue was reporting the absence of.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
0. **Fetch fresh before checking anything.** `git fetch origin main` first, and read
|
|
15
|
+
against `origin/main`, not a local branch — a local checkout can be stale or on an
|
|
16
|
+
unrelated feature branch, and a stale read produces a false "still broken" verdict.
|
|
17
|
+
(Found live: `#194` looked unfixed against a stale local branch, but `origin/main` had
|
|
18
|
+
merged the fix days earlier.)
|
|
19
|
+
|
|
20
|
+
1. **For each candidate whose body cites a specific file, line, function, or CSS
|
|
21
|
+
selector/rule**, read the actual current code at that location:
|
|
22
|
+
```bash
|
|
23
|
+
git show origin/main:<cited-path> | sed -n '<start>,<end>p'
|
|
24
|
+
```
|
|
25
|
+
or grep for the cited selector/function name if line numbers have drifted (files get
|
|
26
|
+
reorganized — issue #180's citation was for `apps/web/app/app.css`, which had since
|
|
27
|
+
been split into `apps/web/app/styles/*.css`; searching by class/function name across
|
|
28
|
+
the styles directory found the real current location).
|
|
29
|
+
|
|
30
|
+
2. **Check the behavior semantically, not just for the literal string the issue used.** A
|
|
31
|
+
fix can land in a different code *shape* than the issue's own words. (Found live: `#57`
|
|
32
|
+
asked for a `<link rel="canonical">` tag; a literal grep for `rel="canonical"` found
|
|
33
|
+
nothing, so the naive check would have called it unfixed — but the actual fix was a
|
|
34
|
+
data-driven React Router `meta()` descriptor, `{ tagName: 'link', rel: 'canonical', href
|
|
35
|
+
}`, which produces the same tag at render time without ever containing that literal
|
|
36
|
+
string in source.) Before concluding "not fixed" on a bare grep miss:
|
|
37
|
+
- Search one level broader — the surrounding directory/module, a shared
|
|
38
|
+
helper/util file, a `meta.ts`/`config.ts`-style indirection layer — for the *behavior*
|
|
39
|
+
the issue describes, not just its exact wording.
|
|
40
|
+
- If the issue names a concrete symptom (a missing tag, a wrong computed value, a
|
|
41
|
+
missing gate), look for whatever code *produces* that output, however it's
|
|
42
|
+
structured, before deciding the symptom is still present.
|
|
43
|
+
|
|
44
|
+
3. **Compare what the issue describes as broken against what the code currently does.**
|
|
45
|
+
If the issue's own hypothesized fix (or an equivalent one, per step 2) is already
|
|
46
|
+
present — reject, log as `already-fixed`, cite the exact current file:line as evidence.
|
|
47
|
+
Don't spend a full `issue-address:reproduce` pass confirming what a direct code read
|
|
48
|
+
already answered.
|
|
49
|
+
|
|
50
|
+
4. **If the citation is vague, or the file has moved/renamed and a reasonably broadened
|
|
51
|
+
search (step 2) still finds nothing**, don't reject on inconclusive evidence — mark the
|
|
52
|
+
candidate `unconfirmed` and let it pass through to the next sub-step. This step only
|
|
53
|
+
rejects on positive evidence of an existing fix, never on failure-to-locate.
|
|
54
|
+
|
|
55
|
+
5. **If the git history around that file shows the fix landed suspiciously close to the
|
|
56
|
+
issue's `createdAt`** (within a day or two, either direction), note that explicitly —
|
|
57
|
+
it's a strong signal the report and the fix crossed in flight (exactly what happened
|
|
58
|
+
with #180: fix committed 2026-06-29, issue filed 2026-06-30).
|
|
59
|
+
|
|
60
|
+
## Output
|
|
61
|
+
|
|
62
|
+
Two lists: `already-fixed` (rejected, with evidence) and `survives` (candidates to pass to
|
|
63
|
+
`issue-address:select:reject-claimed` next, tagged `unconfirmed` where this step couldn't
|
|
64
|
+
conclusively check).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:select:reject-claimed
|
|
3
|
+
description: Reject candidates already covered by a PR (open, OR closed-but-superseded-by-a-merged-successor) or already claimed by an assignee/comment/supersede-note — with every text-search hit manually confirmed before being trusted. Third sub-step of issue-address:select.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:select:reject-claimed
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Search for a PR that might already cover each surviving candidate — open AND
|
|
11
|
+
closed, not just open:**
|
|
12
|
+
```bash
|
|
13
|
+
gh pr list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --state all --search "<N> in:body"
|
|
14
|
+
gh api search/issues -f q='repo:$(gh repo view --json nameWithOwner -q .nameWithOwner) is:pr <N>'
|
|
15
|
+
```
|
|
16
|
+
Also skim PR titles for matching subject matter (same file area, same symptom) — a PR
|
|
17
|
+
can fix an issue's bug without a formal `Closes #N` link. Searching only `state:open`
|
|
18
|
+
misses the real case found live: `#194` had two closed (not merged) PRs, `#203`/`#215`,
|
|
19
|
+
each superseded — but the actual fix landed in a *third*, later PR (`#251`) that neither
|
|
20
|
+
text-search-by-issue-number pass would find unless the closed ones are read first and
|
|
21
|
+
followed to what replaced them (step 3).
|
|
22
|
+
|
|
23
|
+
2. **Never trust a text-search hit without reading it.** This already produced a false
|
|
24
|
+
positive once: searching `"180 in:body"` matched PR #239 ("add automated price-anomaly
|
|
25
|
+
screen"), which had nothing to do with issue #180 — the digit string almost certainly
|
|
26
|
+
matched a line number or unrelated number elsewhere in that PR's body. For every
|
|
27
|
+
text-search hit:
|
|
28
|
+
- Open the matched PR's actual title + description.
|
|
29
|
+
- Confirm it genuinely addresses the same file area / same symptom the issue describes
|
|
30
|
+
— not just that the issue number appears somewhere in the text.
|
|
31
|
+
- If it's a false positive (number coincidence, unrelated context), **discard the match
|
|
32
|
+
and keep the candidate as unclaimed** — don't reject on a search artifact.
|
|
33
|
+
|
|
34
|
+
3. **For every closed-but-not-merged PR found in step 1, read its closing comment before
|
|
35
|
+
deciding the candidate survives.** A PR closed without merging is not automatically
|
|
36
|
+
"unclaimed again" — read why it closed:
|
|
37
|
+
```bash
|
|
38
|
+
gh pr view <PR#> --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --json state,mergedAt,closedAt,comments
|
|
39
|
+
```
|
|
40
|
+
- If the closing comment says the work was split/replaced ("затварям... но не защото
|
|
41
|
+
работата е отпаднала", "closing in favor of #N", "superseded by #N", "merged into
|
|
42
|
+
#N"), **follow the chain to whatever PR(s) it names**, and check *their* merge state
|
|
43
|
+
the same way. Keep following until you reach a terminal state (merged = reject as
|
|
44
|
+
already-fixed; still open = reject as already-covered; abandoned with no successor =
|
|
45
|
+
candidate survives).
|
|
46
|
+
- This chain can be more than one hop deep (found live: `#194`'s PR `#203` was split
|
|
47
|
+
into `#251`/`#252`/`#253`; a sibling PR `#215` was independently closed in favor of
|
|
48
|
+
the same `#251`) — don't stop at the first successor if its own comments point
|
|
49
|
+
further.
|
|
50
|
+
|
|
51
|
+
4. **Reject candidates already claimed by a person, or already noted as superseded in the
|
|
52
|
+
issue's OWN comments** (not just a linked PR's). Check `assignees` (non-empty =
|
|
53
|
+
explicit claim) and skim the issue's `comments` for:
|
|
54
|
+
- Claim language: "работя по това", "assigned to me", "I'll pick this up".
|
|
55
|
+
- Supersede/decompose language: "предлагам да се затвори в полза на", "closing in
|
|
56
|
+
favor of", "split into #N / #M / #P", "superseded by". (Found live: `#154`'s own
|
|
57
|
+
comment thread explicitly proposed closing it in favor of child issues `#156`/`#158`/
|
|
58
|
+
`#163` — a signal that lives in the issue's comments, not in any PR search at all.)
|
|
59
|
+
Reject on either signal — don't take work someone else already started or already
|
|
60
|
+
restructured, even informally.
|
|
61
|
+
|
|
62
|
+
5. **Search for a duplicate open issue** describing the same underlying bug under a
|
|
63
|
+
different number — `gh issue list --state open --search "<keywords>"`, same
|
|
64
|
+
confirm-before-trusting rule as step 2 applies here too. If a better-established
|
|
65
|
+
duplicate exists, flag it rather than silently picking one.
|
|
66
|
+
|
|
67
|
+
## Output
|
|
68
|
+
|
|
69
|
+
`survives` list (candidates cleared of PR/claim/supersede/duplicate overlap — including
|
|
70
|
+
resolved multi-hop PR chains — with any false-positive search hits explicitly noted as
|
|
71
|
+
discarded) handed to `issue-address:select:rank-impact`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:select:rank-impact
|
|
3
|
+
description: Rank surviving candidates by a composite impact signal (priority label + community reactions + cross-references + repro quality), not label text alone, and output exactly one issue number. Final sub-step of issue-address:select.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:select:rank-impact
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Score each surviving candidate on multiple signals, not just its `priority:` label**
|
|
11
|
+
(a label-only heuristic silently mis-ranks an unlabeled-but-severe issue below a
|
|
12
|
+
labeled-but-minor one):
|
|
13
|
+
- **Priority label**: `high` > `medium` > `low` > none (weakest single signal alone).
|
|
14
|
+
- **Category label**: `bug`/`security`/`data-quality` outrank `enhancement`/
|
|
15
|
+
`discussion`/`docs` for this skill's purpose (fixing something broken, not building
|
|
16
|
+
something new).
|
|
17
|
+
- **Community reaction count** (from `fetch-pool`'s `reactionGroups`) — more 👍 reactions
|
|
18
|
+
is a real signal of user-felt impact independent of whatever label was applied at
|
|
19
|
+
triage time.
|
|
20
|
+
- **Cross-references** — check `gh issue view <N> --json timelineItems` (or equivalent)
|
|
21
|
+
for how many other issues/PRs reference this one; a heavily-cross-referenced issue is
|
|
22
|
+
blocking or informing other work, raising its effective priority above its label.
|
|
23
|
+
- **Repro quality** — concrete repro steps / cited file-line locations beat a vague
|
|
24
|
+
report; cheaper to reproduce reliably, lower risk of another #180-style dead end.
|
|
25
|
+
|
|
26
|
+
2. **Combine into a ranked order** — no single signal should override all others (e.g.
|
|
27
|
+
don't let one 👍 reaction alone outrank an explicit `priority: high` label; use
|
|
28
|
+
priority + category as the primary sort, reaction count + cross-references as
|
|
29
|
+
tie-breakers within a tier, repro quality as the final tie-breaker).
|
|
30
|
+
|
|
31
|
+
3. **Output exactly one issue number** — the top of the ranked list — with a one-line
|
|
32
|
+
justification citing which signals won, plus the full ranked list (not just the
|
|
33
|
+
winner) and the rejected list from the earlier two sub-steps, so the whole selection
|
|
34
|
+
is auditable, not just its conclusion.
|
|
35
|
+
|
|
36
|
+
## Output
|
|
37
|
+
|
|
38
|
+
Hand off the single selected issue number to `issue-address:confirm-open`, which
|
|
39
|
+
re-verifies it fresh (state, PR/duplicate claims) immediately before work starts.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:select
|
|
3
|
+
description: Step 0 of issue-address — select exactly ONE open issue on the current project's repo to work, by orchestrating 4 nested sub-skills (fetch-pool, reject-fixed, reject-claimed, rank-impact) in sequence. Only invoked when the caller hasn't already named a specific issue number.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:select (sub-orchestrator)
|
|
7
|
+
|
|
8
|
+
Only runs when `issue-address` is invoked without a specific issue number already named
|
|
9
|
+
(if the caller already has one, skip straight to `issue-address:confirm-open` — that step
|
|
10
|
+
re-verifies the single chosen issue right before work starts, as a freshness guard; this
|
|
11
|
+
skill's job is choosing which issue out of many, cheaply and verifiably, across the whole
|
|
12
|
+
pool).
|
|
13
|
+
|
|
14
|
+
Exists because of a real incident: issue #180 was picked by title/label alone, and 2 full
|
|
15
|
+
`issue-address` steps ran before discovering — only once `issue-address:reproduce`
|
|
16
|
+
actually tried to reproduce it — that the fix had already shipped a day before the issue
|
|
17
|
+
was even filed. The information needed to catch that (the issue's own cited file/line + a
|
|
18
|
+
grep of current code) was available for free at selection time and simply wasn't checked.
|
|
19
|
+
|
|
20
|
+
This skill is itself further decomposed into 4 nested sub-skills, for the same reason
|
|
21
|
+
`issue-address` is decomposed: so each check is independently invokable and its result
|
|
22
|
+
inspectable, instead of one opaque scan-and-pick pass. It also closes two gaps found after
|
|
23
|
+
the first version shipped: an unverified fetch limit (the same class of silent-truncation
|
|
24
|
+
bug that hit `pr-review-sweep`), and an unconfirmed PR-search false positive (seen live in
|
|
25
|
+
the #180 trial — a text search on "180" matched an unrelated PR by number coincidence).
|
|
26
|
+
|
|
27
|
+
**Naming convention:** sub-directories are prefixed `0-`, `1-`, `2-`, `3-` in execution
|
|
28
|
+
order (see `issue-address/SKILL.md` for the repo-wide rule) — a plain directory listing of
|
|
29
|
+
this folder sorts in DAG order without opening any file.
|
|
30
|
+
|
|
31
|
+
## Pipeline DAG
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
open-issue pool
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
┌─────────────────────────────┐
|
|
38
|
+
│ 0. select:fetch-pool │ verified-complete fetch (no silent truncation)
|
|
39
|
+
└─────────────────────────────┘
|
|
40
|
+
│ full pool w/ bodies, labels, assignees, comments, reactions
|
|
41
|
+
▼
|
|
42
|
+
┌─────────────────────────────┐
|
|
43
|
+
│ 1. select:reject-fixed │ grep current code at each cited file/line
|
|
44
|
+
└─────────────────────────────┘
|
|
45
|
+
│ survives (already-fixed candidates dropped, evidence logged)
|
|
46
|
+
▼
|
|
47
|
+
┌─────────────────────────────┐
|
|
48
|
+
│ 2. select:reject-claimed │ PR-search hits confirmed, not trusted blind
|
|
49
|
+
└─────────────────────────────┘
|
|
50
|
+
│ survives (PR'd/claimed/duplicate candidates dropped, evidence logged)
|
|
51
|
+
▼
|
|
52
|
+
┌─────────────────────────────┐
|
|
53
|
+
│ 3. select:rank-impact │ composite score, not label text alone
|
|
54
|
+
└─────────────────────────────┘
|
|
55
|
+
│
|
|
56
|
+
▼
|
|
57
|
+
one issue number + full audit trail (ranked list, rejected list, why)
|
|
58
|
+
│
|
|
59
|
+
▼
|
|
60
|
+
issue-address:confirm-open (next skill up the chain, outside this sub-orchestrator)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| Step | Input | Output | On failure/empty |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| 0. `select:fetch-pool` | none (repo-wide `gh issue list`) | full open-issue pool, verified-complete | n/a — loops its own fetch until verified complete |
|
|
66
|
+
| 1. `select:reject-fixed` | full pool | `already-fixed` list (w/ evidence) + `survives` list | if pool empties out here, report "no candidates, all already fixed" |
|
|
67
|
+
| 2. `select:reject-claimed` | `survives` from step 1 | `already-claimed` list (w/ evidence) + `survives` list | if pool empties out here, report "no candidates, all claimed/PR'd" |
|
|
68
|
+
| 3. `select:rank-impact` | `survives` from step 2 | one issue number + ranked list + justification | if `survives` was already empty, report the empty pool rather than fabricating a pick |
|
|
69
|
+
|
|
70
|
+
## Output
|
|
71
|
+
|
|
72
|
+
Hand off the single selected issue number to `issue-address:confirm-open`, which
|
|
73
|
+
re-verifies it fresh (state, PR/duplicate claims) immediately before work starts — this
|
|
74
|
+
skill's checks are about narrowing a big pool cheaply and verifiably; confirm-open's
|
|
75
|
+
checks are about not acting on stale information for the one issue actually chosen.
|