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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:confirm-open
|
|
3
|
+
description: Step 1 of issue-address — confirm a named GitHub issue on the current project's repo is genuinely OPEN and not already claimed/fixed by another PR or duplicate issue, before any work starts. Returns a clear go/no-go.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:confirm-open
|
|
7
|
+
|
|
8
|
+
Called with one issue number `<N>`. Produces a go/no-go verdict before any code work begins.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Fetch the issue.**
|
|
13
|
+
```bash
|
|
14
|
+
gh issue view <N> --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --json state,title,body,comments,url
|
|
15
|
+
```
|
|
16
|
+
If `state` is not `OPEN` — **stop, no-go.** Report the actual state (closed/merged
|
|
17
|
+
reference) and why. Do not proceed to reproduce or fix a closed issue.
|
|
18
|
+
|
|
19
|
+
2. **Search for an existing open PR that already covers it** — check both explicit links
|
|
20
|
+
and subject-matter overlap, since a PR can fix the bug without a formal `Closes #N`:
|
|
21
|
+
```bash
|
|
22
|
+
gh pr list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --state open --search "<N> in:body"
|
|
23
|
+
gh api search/issues -f q='repo:$(gh repo view --json nameWithOwner -q .nameWithOwner) is:pr is:open <N>'
|
|
24
|
+
```
|
|
25
|
+
Also skim open PR titles for matching subject matter (same file area, same symptom).
|
|
26
|
+
If found — **stop, no-go.** Report which PR number and why it looks like a match; don't
|
|
27
|
+
duplicate work already in flight.
|
|
28
|
+
|
|
29
|
+
3. **Search for a duplicate open issue** covering the same underlying bug (different
|
|
30
|
+
number, same root cause) — `gh issue list --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --state open --search
|
|
31
|
+
"<keywords>"`. If a duplicate exists and is a better-established report, flag it — the
|
|
32
|
+
caller decides which one to actually work.
|
|
33
|
+
|
|
34
|
+
4. **Verdict.** Return one of:
|
|
35
|
+
- **GO** — issue is open, unclaimed, no duplicate blocking it. Include the issue title,
|
|
36
|
+
body, and any repro steps mentioned in comments, so the next step doesn't have to
|
|
37
|
+
re-fetch them.
|
|
38
|
+
- **NO-GO** — state why (closed / already covered by PR #X / duplicate of #Y), and stop
|
|
39
|
+
the whole `issue-address` sequence here. Do not continue to reproduce/fix.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:claim
|
|
3
|
+
description: Step 2 of issue-address — claim a confirmed-open, confirmed-unclaimed issue on the current project's repo before reproducing/fixing it, by self-assigning and posting a claim comment via the gh CLI (no dedicated GitHub MCP server is connected in this environment — gh is the actual mechanism). Closes the race condition where two runs could pick the same issue.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:claim
|
|
7
|
+
|
|
8
|
+
Runs immediately after `issue-address:confirm-open` returns GO, and before
|
|
9
|
+
`issue-address:reproduce` starts any work. Exists because confirming an issue is
|
|
10
|
+
open/unclaimed and then *starting work on it* are two different moments in time — without
|
|
11
|
+
an explicit claim in between, a second concurrent run of this same skill (or a human
|
|
12
|
+
contributor) could pick the same issue, and nothing in `issue-address:select`'s
|
|
13
|
+
`reject-claimed` check would have caught it, since that check only looks for assignees and
|
|
14
|
+
existing claim-language comments — which don't exist yet for an issue nobody has started.
|
|
15
|
+
|
|
16
|
+
**No dedicated GitHub/issue-tracking MCP server is connected in this environment** — every
|
|
17
|
+
GitHub interaction in this whole skill chain (and everywhere else this session) goes
|
|
18
|
+
through the `gh` CLI via Bash. If a GitHub MCP server becomes available later, swap the
|
|
19
|
+
commands below for its equivalent calls; until then, `gh` is the actual mechanism, not a
|
|
20
|
+
gap to work around.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. **Self-assign**, so the issue shows a claim to anyone else's `select:reject-claimed`
|
|
25
|
+
pass or manual look:
|
|
26
|
+
```bash
|
|
27
|
+
gh issue edit <N> --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --add-assignee "@me"
|
|
28
|
+
```
|
|
29
|
+
If self-assignment fails (e.g. insufficient repo permissions — a common case for
|
|
30
|
+
external contributors on a repo they don't have write access to), don't halt the
|
|
31
|
+
sequence on that alone; fall back to step 2's comment as the claim signal, and note in
|
|
32
|
+
the report that assignment wasn't possible so a human knows to check.
|
|
33
|
+
|
|
34
|
+
2. **Post a claim comment** — visible even to someone who doesn't check assignees,
|
|
35
|
+
and consistent with the claim-language `select:reject-claimed` already scans for
|
|
36
|
+
("I'll pick this up", "working on this"; a project with a non-English contributor base,
|
|
37
|
+
e.g. `midt-bg/sigma`'s Bulgarian-speaking reviewers, may localize this string — check
|
|
38
|
+
the project's own `AGENTS.md`/`CLAUDE.local.md` for a house phrase before defaulting to
|
|
39
|
+
English):
|
|
40
|
+
```bash
|
|
41
|
+
gh issue comment <N> --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --body "Working on this issue (issue-address skill chain). Will link the PR here after fix + verify."
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
3. **Re-confirm the claim actually landed** before proceeding — read the issue back and
|
|
45
|
+
check the assignee list and/or the posted comment are present:
|
|
46
|
+
```bash
|
|
47
|
+
gh issue view <N> --repo "$(gh repo view --json nameWithOwner -q .nameWithOwner)" --json assignees,comments
|
|
48
|
+
```
|
|
49
|
+
If neither the assignment nor the comment is visible, don't silently proceed as if
|
|
50
|
+
claimed — report the failure; a claim that didn't actually post protects nobody.
|
|
51
|
+
|
|
52
|
+
## Output
|
|
53
|
+
|
|
54
|
+
Hand off to `issue-address:reproduce` — same issue number, now with a real claim on
|
|
55
|
+
record. If this step's own re-confirmation fails (step 3), stop the sequence and report,
|
|
56
|
+
same severity as a `confirm-open` NO-GO — proceeding to reproduce/fix on an issue that
|
|
57
|
+
isn't actually marked claimed defeats the point of adding this step.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:reproduce
|
|
3
|
+
description: Step 2 of issue-address — reproduce a confirmed-open issue locally with a failing test (red), using hypothesis-driven debugging. Stops and reports if the issue doesn't actually reproduce.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:reproduce
|
|
7
|
+
|
|
8
|
+
Called after `issue-address:confirm-open` returns GO, with the issue's title/body/repro
|
|
9
|
+
steps in hand. Leans on `systematic-debugging` and `test-driven-development`.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. **Form an explicit hypothesis** for what's actually broken, grounded in the issue's
|
|
14
|
+
description — name the file/function you expect is at fault and why, before touching
|
|
15
|
+
anything.
|
|
16
|
+
|
|
17
|
+
2. **Locate the relevant code path** — search for the function/route/query the issue
|
|
18
|
+
describes; read it fully before writing a test against it.
|
|
19
|
+
|
|
20
|
+
3. **Write a test that captures the reported bug.** It must exercise the exact scenario
|
|
21
|
+
the issue describes (same inputs, same expected-vs-actual mismatch), using this repo's
|
|
22
|
+
existing test patterns/helpers for that area (reuse fixtures, don't invent parallel
|
|
23
|
+
ones).
|
|
24
|
+
|
|
25
|
+
4. **Run it and confirm it fails (red)** — this is the proof the bug is real, not just
|
|
26
|
+
assumed from the issue text. Capture the actual failure output.
|
|
27
|
+
|
|
28
|
+
5. **If it does NOT fail** (test passes immediately): the issue may already be fixed,
|
|
29
|
+
stale, or a misunderstanding. **Stop and report this** rather than fabricating a fix for
|
|
30
|
+
a bug that doesn't reproduce — this is a valid, useful outcome, not a failure of the
|
|
31
|
+
skill.
|
|
32
|
+
|
|
33
|
+
6. **If reproduction is hard**, bisect rather than guess repeatedly: halve the input or
|
|
34
|
+
code path, or check `git log` on the relevant files for a recent change that lines up
|
|
35
|
+
with when the bug was reported. Record each bisection step.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
Hand off to `issue-address:fix`: the failing test (file:line), the confirmed root-cause
|
|
40
|
+
hypothesis, and the actual red-phase failure output as evidence.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:fix
|
|
3
|
+
description: Step 3 of issue-address — root-cause and implement the fix for a reproduced issue, given the failing test from issue-address-reproduce. Does not run the broader verification pass — that's issue-address-verify.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:fix
|
|
7
|
+
|
|
8
|
+
Called after `issue-address:reproduce` hands off a failing test + root-cause hypothesis.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Confirm the root cause**, not just the symptom the test exercises — read the
|
|
13
|
+
surrounding code for the actual invariant being violated. A fix that makes the specific
|
|
14
|
+
test pass without addressing the underlying cause will resurface as a different bug
|
|
15
|
+
later.
|
|
16
|
+
|
|
17
|
+
2. **Check for an existing helper/pattern before writing new logic** (API-reuse standard):
|
|
18
|
+
search the codebase for a similar computation/validation/formatting already
|
|
19
|
+
implemented elsewhere. Extend or reuse it rather than forking a parallel
|
|
20
|
+
implementation.
|
|
21
|
+
|
|
22
|
+
3. **Implement the fix** — the smallest correct change that addresses the root cause, in
|
|
23
|
+
the style/conventions of the surrounding code.
|
|
24
|
+
|
|
25
|
+
4. **Run the reproduction test from step 2 only** (not the full suite yet — that's the
|
|
26
|
+
next skill) to confirm it now passes. If it still fails, iterate on the fix, not the
|
|
27
|
+
test.
|
|
28
|
+
|
|
29
|
+
## Output
|
|
30
|
+
|
|
31
|
+
Hand off to `issue-address:verify`: the diff, the now-passing reproduction test, and a
|
|
32
|
+
one-line statement of the actual root cause fixed (for the eventual commit message and
|
|
33
|
+
review).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address:verify
|
|
3
|
+
description: Step 4 of issue-address — prove the new reproduction test passes AND the full existing test suite/typecheck still pass (no regressions), given a fix from issue-address-fix. The gate before requesting-code-review.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address:verify
|
|
7
|
+
|
|
8
|
+
Called after `issue-address:fix` lands a fix and confirms the single reproduction test is
|
|
9
|
+
green. This step's job is the broader safety net.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. **Re-run the reproduction test** on its own once more — confirm green (belt-and-braces,
|
|
14
|
+
in case an intervening change touched it).
|
|
15
|
+
|
|
16
|
+
2. **Run the project's full relevant test suite** — not a hand-picked subset:
|
|
17
|
+
```bash
|
|
18
|
+
pnpm --filter <affected-package> test
|
|
19
|
+
```
|
|
20
|
+
and if the fix touches more than one workspace package, run each affected package's
|
|
21
|
+
suite. Report the actual pass count (e.g. "419/419 passed"), not just "tests pass."
|
|
22
|
+
|
|
23
|
+
3. **Run typecheck**:
|
|
24
|
+
```bash
|
|
25
|
+
pnpm --filter <affected-package> typecheck
|
|
26
|
+
```
|
|
27
|
+
A green test suite with a broken typecheck is not done.
|
|
28
|
+
|
|
29
|
+
4. **If anything besides the target reproduction test is red**, fix it before proceeding —
|
|
30
|
+
never report this step as passed on a partially red suite. Identify whether the new
|
|
31
|
+
failure is a genuine regression from this fix or a pre-existing flake (check if it
|
|
32
|
+
fails on the base branch too, via stash/checkout if needed) before deciding how to
|
|
33
|
+
handle it.
|
|
34
|
+
|
|
35
|
+
## Output
|
|
36
|
+
|
|
37
|
+
A clean verification report (suite name → pass count, typecheck status) to hand to
|
|
38
|
+
`requesting-code-review` (existing skill, not nested here) for the independent review
|
|
39
|
+
pass — call that skill synchronously and read its result before considering the issue
|
|
40
|
+
resolved.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-address
|
|
3
|
+
description: Take ONE GitHub issue on the current project's repo from selection (or a named issue number) to a verified, reviewed fix — orchestrates 6 nested sub-skills (issue-address:select, :confirm-open, :claim, :reproduce, :fix, :verify) plus the existing requesting-code-review skill, so each step is independently invokable and monitorable. Use when the user wants a real issue picked and actually resolved, not just triaged.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# issue-address (orchestrator)
|
|
7
|
+
|
|
8
|
+
Global, project-agnostic issue-to-fix pipeline — works against whatever repo the current
|
|
9
|
+
project's `gh` remote points to. Fires exactly one issue through a fixed sequence of nested
|
|
10
|
+
skills — each a real, independently-invokable `SKILL.md`, not just a section header, so the
|
|
11
|
+
sequence's progress can be watched step by step instead of as one opaque pass. Codified from
|
|
12
|
+
`midt-bg/sigma`'s workflow; a project's own `AGENTS.md`/`CLAUDE.local.md` may add repo-specific
|
|
13
|
+
conventions (branch naming, claim-comment language, commit style) that this skill should read
|
|
14
|
+
and respect if present.
|
|
15
|
+
|
|
16
|
+
**Naming convention (see a project's own `AGENTS.md` if it documents one; otherwise this
|
|
17
|
+
convention still applies as the plugin's own standard):** sub-skill directories are prefixed
|
|
18
|
+
`0-`, `1-`, `2-`... in execution order, so a plain directory listing sorts in DAG order
|
|
19
|
+
without needing to open any file. Never rely on prose order alone — a reader (or an
|
|
20
|
+
alphabetically-sorted file browser) should see the sequence from the folder names
|
|
21
|
+
themselves. The invocable `name:` field stays a clean colon-scoped identifier
|
|
22
|
+
(`issue-address:select`) without the numeric prefix — the prefix is a filesystem/ordering
|
|
23
|
+
aid, not part of the skill's name.
|
|
24
|
+
|
|
25
|
+
## Pipeline DAG
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌─────────────────────┐
|
|
29
|
+
no issue # ──────▶ 0. issue-address:select │──▶ issue number
|
|
30
|
+
└─────────────────────┘ │
|
|
31
|
+
issue # given ─────────────────────────────────────┘
|
|
32
|
+
▼
|
|
33
|
+
┌───────────────────────────┐
|
|
34
|
+
│ 1. issue-address:confirm-open │
|
|
35
|
+
└───────────────────────────┘
|
|
36
|
+
GO │ │ NO-GO
|
|
37
|
+
▼ ▼
|
|
38
|
+
┌─────────────────────┐ STOP — report why
|
|
39
|
+
│ 2. issue-address:claim │
|
|
40
|
+
└─────────────────────┘
|
|
41
|
+
claimed │ │ claim failed to land
|
|
42
|
+
▼ ▼
|
|
43
|
+
┌─────────────────────┐ STOP — report (don't proceed
|
|
44
|
+
│ 3. issue-address:reproduce│ unclaimed)
|
|
45
|
+
└─────────────────────┘
|
|
46
|
+
reproduces │ │ doesn't reproduce
|
|
47
|
+
▼ ▼
|
|
48
|
+
┌─────────────────┐ STOP — report (valid outcome,
|
|
49
|
+
│ 4. issue-address:fix │ not a failure)
|
|
50
|
+
└─────────────────┘
|
|
51
|
+
│
|
|
52
|
+
▼
|
|
53
|
+
┌────────────────────┐
|
|
54
|
+
│ 5. issue-address:verify│──── red ────┐
|
|
55
|
+
└────────────────────┘ │
|
|
56
|
+
│ green │
|
|
57
|
+
▼ │
|
|
58
|
+
┌────────────────────┐ │
|
|
59
|
+
│ 6. requesting-code-review│ │
|
|
60
|
+
└────────────────────┘ │
|
|
61
|
+
│ │
|
|
62
|
+
▼ ▼
|
|
63
|
+
land per conventions loop back to step 4
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Step | Input | Output | On failure |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| 0. `issue-address:select` | open-issue pool (implicit — repo-wide) | one issue number + justification | n/a (always produces one, or explicitly reports the pool is empty) |
|
|
69
|
+
| 1. `issue-address:confirm-open` | one issue number | GO (+ title/body/repro steps) or NO-GO (+ reason) | **STOP** — do not proceed |
|
|
70
|
+
| 2. `issue-address:claim` | one confirmed-open issue number | self-assignment + claim comment, re-confirmed as landed | **STOP** — report if the claim didn't actually post; don't proceed unclaimed |
|
|
71
|
+
| 3. `issue-address:reproduce` | issue title/body/repro steps | failing test (file:line) + root-cause hypothesis + red-phase output | **STOP** — report "does not reproduce" (valid, not a failure) |
|
|
72
|
+
| 4. `issue-address:fix` | failing test + root-cause hypothesis | diff + the one test now green | loops internally until its one test is green |
|
|
73
|
+
| 5. `issue-address:verify` | diff + green reproduction test | full-suite pass counts + typecheck result | **loop back to step 4** — do not proceed to review on red |
|
|
74
|
+
| 6. `requesting-code-review` | the verified diff | Critical/Important findings addressed | fix findings, do not mark resolved until clean |
|
|
75
|
+
|
|
76
|
+
Called either with **no issue number** (enters at step 0) or with **one specific issue
|
|
77
|
+
number already named** (enters at step 1, skipping step 0 entirely).
|
|
78
|
+
|
|
79
|
+
**Why claim is its own step, not folded into confirm-open:** confirming an issue is
|
|
80
|
+
open/unclaimed and actually claiming it are two different moments in time — a gap where a
|
|
81
|
+
second concurrent run (or a human) could pick the same issue between the two. `select`'s
|
|
82
|
+
`reject-claimed` check only catches claims that already exist (an assignee, a "working on
|
|
83
|
+
this" comment); nothing marks the issue claimed *for this run* until `claim` actually
|
|
84
|
+
posts one. No dedicated GitHub/issue-tracking MCP server is connected in this environment
|
|
85
|
+
— `claim` uses the `gh` CLI directly (self-assign + comment), same as every other GitHub
|
|
86
|
+
interaction in this skill chain.
|
|
87
|
+
|
|
88
|
+
## After the sequence completes clean
|
|
89
|
+
|
|
90
|
+
- Commit with a conventional-commit message (`fix(scope): subject`, no trailing period, no
|
|
91
|
+
`Co-Authored-By` trailer unless the project's own convention says otherwise), on a branch
|
|
92
|
+
following the project's own `<type>/<slug>` convention if it documents one.
|
|
93
|
+
- **Only push / open a PR when explicitly asked** — per the project's own `AGENTS.md` PR
|
|
94
|
+
section if it has one, don't do it unprompted. Report the sequence as complete and ready,
|
|
95
|
+
and wait.
|
|
96
|
+
- If a PR does get opened (once asked), post a short comment on the originating issue
|
|
97
|
+
linking it — closes the loop from report to fix.
|
|
98
|
+
- Never contact a reviewer (no request/re-request/nudge) without the user's fresh,
|
|
99
|
+
explicit, per-instance approval — same hard constant as everywhere else in this workflow.
|
|
100
|
+
|
|
101
|
+
## Why nested skills instead of one inline sequence
|
|
102
|
+
|
|
103
|
+
Each step is its own file so it shows up as its own invocation in whatever surface tracks
|
|
104
|
+
skill/tool calls — you can see "select ran, chose #N over 4 rejected candidates" and
|
|
105
|
+
"confirm-open ran, returned GO" as distinct, inspectable events before "reproduce" even
|
|
106
|
+
starts, rather than one long undifferentiated pass. If a step needs to change (e.g. the
|
|
107
|
+
verify step's test-runner command, or select's ranking weights), it's a one-file edit that
|
|
108
|
+
doesn't touch the others. When a step needs more depth or clarity, decompose it further
|
|
109
|
+
the same way `issue-address:select` was (see `0-select/SKILL.md` for its own nested DAG)
|
|
110
|
+
— continuously, wherever a single file is doing too much to inspect as one unit.
|
|
111
|
+
|
|
112
|
+
## What this skill is not
|
|
113
|
+
|
|
114
|
+
- Not a pure triage/backlog tool — that's `find-opportunity` (ranks what to work on next
|
|
115
|
+
without opening/fixing anything, and never opens/fixes on its own). `issue-address:select`
|
|
116
|
+
overlaps with it in spirit (both rank by impact and check for claims) but exists
|
|
117
|
+
specifically to feed straight into actually fixing one issue in the same run, not just
|
|
118
|
+
to produce a shortlist for a human to review.
|
|
119
|
+
- Not for PR review comments — that's a different data source entirely (see
|
|
120
|
+
`pr-review-sweep` for the unresolved-review-thread workflow on already-open PRs).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review-sweep:fetch
|
|
3
|
+
description: Step 0 of pr-review-sweep — fetch every unresolved review thread on one or more of the current project's PRs, fully paginated. Never trust file names, a prior status report, or a reply's own claim about what's outstanding.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pr-review-sweep:fetch
|
|
7
|
+
|
|
8
|
+
Query GitHub's GraphQL API directly for each PR. Resolve `$owner`/`$name` from the current
|
|
9
|
+
project's own remote — `gh repo view --json owner,name -q '.owner.login,.name'` — never
|
|
10
|
+
hardcode a repo.
|
|
11
|
+
|
|
12
|
+
```graphql
|
|
13
|
+
query($owner: String!, $name: String!, $n: Int!) {
|
|
14
|
+
repository(owner: $owner, name: $name) {
|
|
15
|
+
pullRequest(number: $n) {
|
|
16
|
+
reviewThreads(first: 100) {
|
|
17
|
+
totalCount
|
|
18
|
+
nodes {
|
|
19
|
+
isResolved
|
|
20
|
+
path
|
|
21
|
+
line
|
|
22
|
+
comments(first: 3) { nodes { author { login } body createdAt } }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Filter to `isResolved: false`. **`first: 100` is load-bearing** — `first: 50` silently
|
|
31
|
+
truncates on any PR that has grown past 50 threads (two real PRs hit this: one had 64
|
|
32
|
+
threads, another had 55; the truncated queries under-reported unresolved counts and caused
|
|
33
|
+
genuinely-missed comments). Always compare `totalCount` to how many nodes you actually
|
|
34
|
+
paged through, and keep paginating (`after:` cursor) until they match — never report a
|
|
35
|
+
count you haven't verified is complete.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
One unresolved-thread list per PR, each entry carrying: the PR number, thread id, file
|
|
40
|
+
path + line, and full comment text/author/timestamp — everything `pr-review-sweep:classify`
|
|
41
|
+
needs to decide disposition and type without a second round-trip to GitHub.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review-sweep:classify
|
|
3
|
+
description: Step 1 of pr-review-sweep — classify each unresolved review thread on two independent axes — disposition (accept-as-is / policy-override / needs-my-decision) and type (bug / feature) — so downstream steps can route and template correctly.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pr-review-sweep:classify
|
|
7
|
+
|
|
8
|
+
Decided per-thread, never per-PR — a single PR routinely mixes threads that need very
|
|
9
|
+
different handling.
|
|
10
|
+
|
|
11
|
+
## Axis 1 — disposition
|
|
12
|
+
|
|
13
|
+
- **Accept-as-is** — the reviewer's ask is valid, no repo-policy reason not to do it. The
|
|
14
|
+
default bucket.
|
|
15
|
+
- **Policy-override** — the comment conflicts with something the repo's own `AGENTS.md` /
|
|
16
|
+
`CLAUDE.local.md` already decided (a staged-rollout convention, an intentional
|
|
17
|
+
trade-off). Policy wins silently — no need to escalate to the user — but still reply
|
|
18
|
+
explaining why, so the reviewer isn't left wondering. Verify the policy text actually
|
|
19
|
+
says what you think it says before invoking this bucket; don't assume.
|
|
20
|
+
- **Needs-my-decision** — a genuine judgment call with no clear answer from repo policy
|
|
21
|
+
alone. Stop, surface the question verbatim to the user, never guess. This bucket blocks
|
|
22
|
+
only that one thread — every other thread on the PR keeps moving. A needs-my-decision
|
|
23
|
+
thread never gets a type tag (axis 2 is moot until it's decided to do the work at all).
|
|
24
|
+
|
|
25
|
+
## Axis 2 — type (accept-as-is and policy-override threads only)
|
|
26
|
+
|
|
27
|
+
- **Bug** — the reviewer flagged something objectively broken: wrong output, a crash, a
|
|
28
|
+
security issue, an off-by-one, a missed edge case. Anything where "what should happen
|
|
29
|
+
instead" is unambiguous from the current code being wrong.
|
|
30
|
+
- **Feature** — the reviewer asked for additional behavior, a refactor, or a
|
|
31
|
+
consistency/style improvement that isn't fixing broken behavior. If the current code does
|
|
32
|
+
what it currently does *on purpose* and the ask is to make it do something more or
|
|
33
|
+
different, it's a feature, not a bug — even when phrased urgently.
|
|
34
|
+
|
|
35
|
+
When genuinely ambiguous between the two (e.g. "this should also handle nulls" — is null
|
|
36
|
+
input a bug the code should already handle, or new scope?), default to **bug** only if
|
|
37
|
+
there's a concrete failing case (a real input that breaks today); otherwise **feature**.
|
|
38
|
+
Record the reasoning either way — `pr-review-sweep:queue` uses it to pick the PRD template,
|
|
39
|
+
and a future reader should be able to see why a borderline call went the way it did.
|
|
40
|
+
|
|
41
|
+
## Output
|
|
42
|
+
|
|
43
|
+
Per thread: `{disposition, type | null, reasoning}`. Needs-my-decision threads carry the
|
|
44
|
+
open question verbatim, collected for the final report rather than blocking the other
|
|
45
|
+
threads.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review-sweep:check-fixed
|
|
3
|
+
description: Step 2 of pr-review-sweep — before queuing anything, triage every accept-as-is / policy-override thread into already-fixed, reply-only (no code change needed), or genuinely-open. Mandatory for every survivor, including policy-override threads — skipping it on the assumption "policy-override never needs a code check" is what caused a real wrong reply (see below).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pr-review-sweep:check-fixed
|
|
7
|
+
|
|
8
|
+
Read the current file content at the cited location, and check recent git log/commits on
|
|
9
|
+
the PR's actual branch, for **every** accept-as-is/policy-override thread — no exceptions
|
|
10
|
+
for threads that look like a pure confirmation ask. **This step is mandatory before posting
|
|
11
|
+
any reply, not optional for policy-override threads.**
|
|
12
|
+
|
|
13
|
+
**Incident that made this mandatory:** on sigma PR #206, a policy-override thread (empty-
|
|
14
|
+
string EIK display) was replied to with "leaving as-is, test locks in current behavior"
|
|
15
|
+
without re-checking the code first — but the thread had *already been fixed* two commits
|
|
16
|
+
earlier by a different session. The wrong reply had to be corrected with a follow-up
|
|
17
|
+
comment. The cause wasn't a broken tool, it was skipping this step because the thread's
|
|
18
|
+
disposition (policy-override) felt like it obviously needed no verification. It didn't
|
|
19
|
+
obviously need verification — but it needed it anyway, and every thread does.
|
|
20
|
+
|
|
21
|
+
## Triage into three outcomes, not two
|
|
22
|
+
|
|
23
|
+
1. **Already-fixed** — the code (or a recent commit on the PR's branch) already does what
|
|
24
|
+
the thread asks. Routes straight to `pr-review-sweep:land-and-resolve`, citing the
|
|
25
|
+
fixing commit SHA. Skips `:queue` entirely.
|
|
26
|
+
2. **Reply-only, no code change needed** — the thread is fully answered by information
|
|
27
|
+
that already exists (a repo convention, an intentional design documented elsewhere, a
|
|
28
|
+
fact about the code the reviewer didn't have) and genuinely requires zero code change to
|
|
29
|
+
resolve — not "a trivial one-line fix," but literally nothing to write. Common for
|
|
30
|
+
policy-override threads whose reviewer ask was really a question ("confirm X is
|
|
31
|
+
intentional") rather than a change request. Routes straight to
|
|
32
|
+
`pr-review-sweep:land-and-resolve`, citing the evidence/reasoning instead of a SHA.
|
|
33
|
+
**Do not send these to `:queue`** — queuing a PRD to "fix" a thread that needs no fix
|
|
34
|
+
wastes a scheduler run and produces a PRD with no real acceptance criteria to execute.
|
|
35
|
+
3. **Genuinely open** — needs an actual code change that doesn't exist yet. Goes to
|
|
36
|
+
`pr-review-sweep:queue` as before, carrying its `{disposition, type}` tags.
|
|
37
|
+
|
|
38
|
+
The dividing line between outcomes 2 and 3: if you can point to the exact existing
|
|
39
|
+
line/paragraph that answers the reviewer's ask, it's outcome 2. If satisfying the ask
|
|
40
|
+
requires writing or changing any code, however small, it's outcome 3 — don't downgrade a
|
|
41
|
+
real fix to "reply-only" just because it's tiny; that's what `:queue`'s bug/feature
|
|
42
|
+
templates are for, sized appropriately.
|
|
43
|
+
|
|
44
|
+
## Output
|
|
45
|
+
|
|
46
|
+
Three lists per PR:
|
|
47
|
+
- **already-fixed** (thread id + the commit/line that fixed it) → `:land-and-resolve`
|
|
48
|
+
- **reply-only** (thread id + the evidence/reasoning to cite) → `:land-and-resolve`
|
|
49
|
+
- **survives** (thread id, disposition, type) → `:queue`
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review-sweep:queue
|
|
3
|
+
description: Step 3 of pr-review-sweep — bundle surviving accept-as-is/policy-override threads by (PR, type) and queue one /develop PRD per bundle. Never fixes inline; the scheduler is the only place code changes happen.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pr-review-sweep:queue
|
|
7
|
+
|
|
8
|
+
Only ever receives the **survives** list from `pr-review-sweep:check-fixed` — threads that
|
|
9
|
+
genuinely need a code change that doesn't exist yet. `check-fixed` has already routed
|
|
10
|
+
already-fixed and reply-only threads straight to `land-and-resolve`, so if you're looking
|
|
11
|
+
at a thread here, it needs real code written; don't second-guess that by trying to answer
|
|
12
|
+
it with a reply instead of a PRD.
|
|
13
|
+
|
|
14
|
+
Group `survives` threads by **(PR number, type)** — up to two bundles per PR, one `bug` and
|
|
15
|
+
one `feature`. Queue each bundle as its own `/develop` PRD. Never write the fix in this
|
|
16
|
+
session; this step's own actions are read-only except for the act of queuing.
|
|
17
|
+
|
|
18
|
+
## Duplicate-PRD guard (idempotency)
|
|
19
|
+
|
|
20
|
+
Before queuing a bundle, check the scheduler queue for an existing queued/in-flight PRD for
|
|
21
|
+
that same (PR, type). If one exists, skip queuing and report the existing PRD id instead —
|
|
22
|
+
re-running `pr-review-sweep` must never double-queue the same bundle. If a thread newly
|
|
23
|
+
qualifies for a bundle that already has an in-flight PRD (e.g. a fresh review comment
|
|
24
|
+
landed after the PRD was queued but before it completed), do not silently fold it in —
|
|
25
|
+
queue a follow-up PRD once the first completes, so each PRD's diff stays traceable to a
|
|
26
|
+
known snapshot of threads.
|
|
27
|
+
|
|
28
|
+
## PRD acceptance criteria, by type
|
|
29
|
+
|
|
30
|
+
Every PRD, regardless of type, ends with: commit + push to the fork branch that owns the
|
|
31
|
+
PR (never `origin`, never force-push, never a new PR to carry a review fix — land on the
|
|
32
|
+
existing PR's branch), and the standard two independent verification passes before commit.
|
|
33
|
+
|
|
34
|
+
- **`bug` bundle** — additionally require: reproduce each defect described in the bundled
|
|
35
|
+
threads, write a regression test per defect that fails before the fix and passes after,
|
|
36
|
+
then fix. The PRD body should quote the reviewer's exact wording per thread so the
|
|
37
|
+
executor root-causes the actual reported defect, not a guessed one.
|
|
38
|
+
- **`feature` bundle** — additionally require: scope the change to exactly what each
|
|
39
|
+
bundled thread asked for (no piggybacked scope creep across threads even though they're
|
|
40
|
+
bundled together), match existing patterns/conventions in the touched files, and add a
|
|
41
|
+
test only if the ask itself introduces new testable behavior.
|
|
42
|
+
|
|
43
|
+
Neither template authorizes a description edit or a reviewer request — those stay
|
|
44
|
+
`pr-review-sweep:land-and-resolve`'s and `pr-signal`'s jobs respectively, so a PR's
|
|
45
|
+
description reflects the *final* landed state, not a snapshot mid-fix.
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
Per (PR, type) bundle: a queued PRD id (new or pre-existing), or — if `survives` was empty
|
|
50
|
+
for that PR — nothing to queue, reported as such rather than silently skipped.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review-sweep:land-and-resolve
|
|
3
|
+
description: Step 4 of pr-review-sweep — reply on the GitHub thread and resolve it, via one of three entry points from check-fixed/queue (already-fixed, reply-only, or a completed PRD). Runs async relative to steps 0-3 for the PRD path, typically triggered by a later project-status-local pass noticing a completed PRD.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pr-review-sweep:land-and-resolve
|
|
7
|
+
|
|
8
|
+
Three entry points:
|
|
9
|
+
|
|
10
|
+
1. **Already-fixed threads** from `pr-review-sweep:check-fixed` — no PRD to wait on, act
|
|
11
|
+
immediately, citing the commit that step already identified.
|
|
12
|
+
2. **Reply-only threads** from `pr-review-sweep:check-fixed` — no PRD, no commit; act
|
|
13
|
+
immediately, citing the evidence/reasoning `check-fixed` already worked out (a repo
|
|
14
|
+
convention, an intentional-design confirmation, a fact about the code the reviewer
|
|
15
|
+
didn't have). **Re-verify that reasoning is still accurate right now, not just at
|
|
16
|
+
classify time** — code moves between when a thread was classified and when you're about
|
|
17
|
+
to reply; don't post a stale "confirmed" against code that's since changed.
|
|
18
|
+
3. **Queued PRDs** from `pr-review-sweep:queue` that the scheduler now reports
|
|
19
|
+
`completed` — this is where this step actually waits on external state; a fresh
|
|
20
|
+
`/project-status` (or manual) run is what notices the PRD finished and re-enters here.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. **For the PRD entry point only:** confirm the PRD actually ran its required
|
|
25
|
+
verification — both independent passes, and (for a `bug` bundle) that the regression
|
|
26
|
+
test genuinely exists and is green, not just claimed in the PRD's own summary. A PRD
|
|
27
|
+
marked `completed` without evidence of the ACs having run is `needs_review`, not landed —
|
|
28
|
+
report it as stuck, don't proceed to reply/resolve. (Already-fixed and reply-only
|
|
29
|
+
entries have no PRD to verify — skip to step 2.)
|
|
30
|
+
2. **Confirm CI is green** on the PR (for the PRD entry point, after the PRD's commit
|
|
31
|
+
landed; for already-fixed/reply-only, CI state is whatever it already is).
|
|
32
|
+
3. **Reply** on each thread — naming the specific fixing commit SHA for already-fixed/PRD
|
|
33
|
+
entries, or the evidence/reasoning for reply-only entries — so the reviewer can verify
|
|
34
|
+
without re-reading the whole diff or re-asking the question.
|
|
35
|
+
4. **Resolve** the thread via GraphQL `resolveReviewThread`. Order matters: reply first,
|
|
36
|
+
resolve second, so there's a paper trail explaining why a thread closed before it drops
|
|
37
|
+
off the unresolved list.
|
|
38
|
+
|
|
39
|
+
Needs-my-decision threads (set aside back in `pr-review-sweep:classify`), and any
|
|
40
|
+
policy-override thread where convention says the reviewer should be the one to close it,
|
|
41
|
+
are deliberately left unresolved after the reply — that is correct behavior, not an
|
|
42
|
+
oversight.
|
|
43
|
+
|
|
44
|
+
## Stuck PRDs
|
|
45
|
+
|
|
46
|
+
A `failed` or `needs_review` PRD is reported to the user as a stuck bundle, never silently
|
|
47
|
+
retried and never silently downgraded to an inline fix — re-queuing or fixing it directly
|
|
48
|
+
both require the user's decision, since either implies the original PRD's scope or ACs
|
|
49
|
+
were wrong.
|
|
50
|
+
|
|
51
|
+
## Hard constant
|
|
52
|
+
|
|
53
|
+
**Never contact a reviewer** at any point in this step — replying to a thread and
|
|
54
|
+
resolving it are not reviewer contact; requesting/re-requesting one is `pr-signal`'s job
|
|
55
|
+
alone, gated separately.
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
|
|
59
|
+
Per thread: resolved (+ the SHA it was resolved against), or reported as blocked (PRD
|
|
60
|
+
still in flight, or stuck) — loops back to `project-status-local`'s rollup either way.
|