claude-dev-env 1.87.0 → 1.88.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/CLAUDE.md +4 -0
- package/agents/CLAUDE.md +1 -1
- package/agents/pr-description-writer.md +1 -1
- package/bin/install.mjs +1 -0
- package/hooks/blocking/CLAUDE.md +1 -1
- package/hooks/blocking/pr_description_enforcer.py +1 -1
- package/hooks/blocking/pr_description_readability.py +22 -24
- package/package.json +1 -1
- package/skills/CLAUDE.md +2 -0
- package/skills/advisor/SKILL.md +137 -0
- package/skills/advisor-refresh/SKILL.md +25 -0
- package/skills/bugteam/CONSTRAINTS.md +1 -1
- package/skills/bugteam/SKILL.md +1 -1
- package/skills/pr-loop-lifecycle/SKILL.md +2 -2
- package/skills/pr-loop-lifecycle/reference/teardown-publish-permissions.md +3 -16
- package/skills/qbug/SKILL.md +1 -1
package/CLAUDE.md
CHANGED
|
@@ -21,6 +21,10 @@ Every Markdown file I write or edit describes the system's **current** state onl
|
|
|
21
21
|
Full banned-pattern set + enforcement: `~/.claude/rules/no-historical-clutter.md` (hook `state-description-blocker`) and `~/.claude/rules/self-contained-docs.md`.
|
|
22
22
|
|
|
23
23
|
## GOTCHAS
|
|
24
|
+
ALWAYS base new worktrees off of UPSTREAM origin main. Assume local is out of date.
|
|
25
|
+
|
|
26
|
+
ALWAYS start each session with a /loop 15m populate or update the task list based on remaining todos.
|
|
27
|
+
|
|
24
28
|
When making code changes, make sure you are working in the proper worktree path for the task at hand.
|
|
25
29
|
|
|
26
30
|
## Choosing Edit vs Write
|
package/agents/CLAUDE.md
CHANGED
|
@@ -16,7 +16,7 @@ Agent definition files installed into `~/.claude/agents/` by `bin/install.mjs`.
|
|
|
16
16
|
| `docs-agent.md` | Docs Agent | Documentation authoring and maintenance |
|
|
17
17
|
| `git-commit-crafter.md` | Git Commit Crafter | Stages changes, writes conventional commit messages, creates commits |
|
|
18
18
|
| `plan-packet-validator.md` | Plan Packet Validator | Fresh-context validator for workflow-generated plan packets under `docs/plans/` |
|
|
19
|
-
| `pr-description-writer.md` | PR Description Writer | Authors PR descriptions in Anthropic-style shapes
|
|
19
|
+
| `pr-description-writer.md` | PR Description Writer | Authors PR descriptions in Anthropic-style shapes that pass the `pr_description_enforcer` hook's body audit |
|
|
20
20
|
|
|
21
21
|
## Format
|
|
22
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pr-description-writer
|
|
3
|
-
description: "
|
|
3
|
+
description: "Optional agent for PR descriptions and PR comments. Authors bodies in one of three Anthropic-derived shapes (Trivial / Standard / Heavy) so PRs match merged-PR style in `anthropics/claude-code`, `anthropics/claude-code-action`, and `anthropics/claude-code-sdk-python`, and pass the `pr_description_enforcer` PreToolUse hook's body audit on `gh pr create`, `gh pr edit`, and `gh pr comment`."
|
|
4
4
|
tools: Read,Grep,Glob,Bash
|
|
5
5
|
model: haiku
|
|
6
6
|
---
|
package/bin/install.mjs
CHANGED
|
@@ -147,6 +147,7 @@ const INSTALL_GROUPS = {
|
|
|
147
147
|
core: {
|
|
148
148
|
description: 'Development standards, hooks, agents, commands',
|
|
149
149
|
skills: [
|
|
150
|
+
'advisor', 'advisor-refresh',
|
|
150
151
|
'anthropic-plan', 'everything-search',
|
|
151
152
|
'pr-review-responder',
|
|
152
153
|
'recall', 'remember', 'task-build', 'verified-build'
|
package/hooks/blocking/CLAUDE.md
CHANGED
|
@@ -81,7 +81,7 @@ The check modules it calls are the `code_rules_<concern>.py` files below.
|
|
|
81
81
|
| `package_inventory_stale_blocker.py` | PreToolUse (Write) | A new production code file created in a directory whose `README.md`/`CLAUDE.md` inventory (or a parent skill's `SKILL.md` Layout table mapping the `scripts/` subdirectory) names two or more sibling files but no entry for the new file |
|
|
82
82
|
| `plain_language_blocker.py` | PreToolUse (Write/Edit/AskUserQuestion) | Heavy or jargon words in user-facing prose |
|
|
83
83
|
| `pr_converge_bugteam_enforcer.py` | PreToolUse | Enforces that bugteam runs in parallel with bugbot in pr-converge loops |
|
|
84
|
-
| `pr_description_enforcer.py` | PreToolUse (Bash) | `gh pr create`/`edit`
|
|
84
|
+
| `pr_description_enforcer.py` | PreToolUse (Bash) | `gh pr create`/`edit`/`comment` bodies that fail the Anthropic claude-code style audit |
|
|
85
85
|
| `precommit_code_rules_gate.py` | PreToolUse (Bash) | Staged changes that fail the CODE_RULES gate at commit time |
|
|
86
86
|
| `pytest_testpaths_orphan_blocker.py` | PreToolUse (Write/Edit/MultiEdit) | New `test_*.py` files created under a directory absent from a package's explicit pytest `testpaths` allowlist |
|
|
87
87
|
| `question_to_user_enforcer.py` | Stop | User-directed questions not routed through `AskUserQuestion` |
|
|
@@ -178,7 +178,7 @@ def main() -> None:
|
|
|
178
178
|
pr_guide_reference = f" @{PR_GUIDE_PATH}" if os.path.exists(PR_GUIDE_PATH) else ""
|
|
179
179
|
denial_reason = (
|
|
180
180
|
f"BLOCKED: [PR_DESCRIPTION] {violation_list}. "
|
|
181
|
-
f"
|
|
181
|
+
f"Rewrite the body yourself in Anthropic claude-code style. "
|
|
182
182
|
f"Guide:{pr_guide_reference}"
|
|
183
183
|
)
|
|
184
184
|
denial_payload = {
|
|
@@ -76,8 +76,10 @@ def _read_strike_count() -> int:
|
|
|
76
76
|
def _increment_strike_count() -> int:
|
|
77
77
|
payload = _read_json_or_default(READABILITY_STATE_FILE, {"strikes": 0})
|
|
78
78
|
raw_count = payload.get("strikes", 0)
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
if isinstance(raw_count, int) and not isinstance(raw_count, bool):
|
|
80
|
+
starting_count = max(raw_count, 0)
|
|
81
|
+
else:
|
|
82
|
+
starting_count = 0
|
|
81
83
|
new_count = starting_count + 1
|
|
82
84
|
_atomic_write_json(READABILITY_STATE_FILE, {"strikes": new_count})
|
|
83
85
|
return new_count
|
|
@@ -87,31 +89,27 @@ def _reset_strike_count() -> None:
|
|
|
87
89
|
_atomic_write_json(READABILITY_STATE_FILE, {"strikes": 0})
|
|
88
90
|
|
|
89
91
|
|
|
92
|
+
def _resolve_integer_field(
|
|
93
|
+
all_payload_fields: dict[str, object], field_name: str, default_value: int
|
|
94
|
+
) -> int:
|
|
95
|
+
raw_value = all_payload_fields.get(field_name, default_value)
|
|
96
|
+
if isinstance(raw_value, int) and not isinstance(raw_value, bool):
|
|
97
|
+
return raw_value
|
|
98
|
+
return default_value
|
|
99
|
+
|
|
100
|
+
|
|
90
101
|
def _load_readability_thresholds() -> ReadabilityThresholds:
|
|
91
102
|
payload = _read_json_or_default(READABILITY_THRESHOLD_OVERRIDE_FILE, {})
|
|
92
|
-
flesch_min_value = payload.get("flesch_min", DEFAULT_READABILITY_THRESHOLDS.flesch_min)
|
|
93
|
-
max_sentence_value = payload.get(
|
|
94
|
-
"max_sentence_words", DEFAULT_READABILITY_THRESHOLDS.max_sentence_words
|
|
95
|
-
)
|
|
96
|
-
avg_sentence_value = payload.get(
|
|
97
|
-
"avg_sentence_words", DEFAULT_READABILITY_THRESHOLDS.avg_sentence_words
|
|
98
|
-
)
|
|
99
|
-
flesch_is_int = isinstance(flesch_min_value, int) and not isinstance(flesch_min_value, bool)
|
|
100
|
-
max_is_int = isinstance(max_sentence_value, int) and not isinstance(max_sentence_value, bool)
|
|
101
|
-
avg_is_int = isinstance(avg_sentence_value, int) and not isinstance(avg_sentence_value, bool)
|
|
102
|
-
resolved_flesch = (
|
|
103
|
-
flesch_min_value if flesch_is_int else DEFAULT_READABILITY_THRESHOLDS.flesch_min
|
|
104
|
-
)
|
|
105
|
-
resolved_max = (
|
|
106
|
-
max_sentence_value if max_is_int else DEFAULT_READABILITY_THRESHOLDS.max_sentence_words
|
|
107
|
-
)
|
|
108
|
-
resolved_avg = (
|
|
109
|
-
avg_sentence_value if avg_is_int else DEFAULT_READABILITY_THRESHOLDS.avg_sentence_words
|
|
110
|
-
)
|
|
111
103
|
return ReadabilityThresholds(
|
|
112
|
-
flesch_min=
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
flesch_min=_resolve_integer_field(
|
|
105
|
+
payload, "flesch_min", DEFAULT_READABILITY_THRESHOLDS.flesch_min
|
|
106
|
+
),
|
|
107
|
+
max_sentence_words=_resolve_integer_field(
|
|
108
|
+
payload, "max_sentence_words", DEFAULT_READABILITY_THRESHOLDS.max_sentence_words
|
|
109
|
+
),
|
|
110
|
+
avg_sentence_words=_resolve_integer_field(
|
|
111
|
+
payload, "avg_sentence_words", DEFAULT_READABILITY_THRESHOLDS.avg_sentence_words
|
|
112
|
+
),
|
|
115
113
|
)
|
|
116
114
|
|
|
117
115
|
|
package/package.json
CHANGED
package/skills/CLAUDE.md
CHANGED
|
@@ -26,6 +26,8 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
|
|
|
26
26
|
- `implement` — structured implementation from an existing plan packet
|
|
27
27
|
- `bdd-protocol` — BDD depth: Example Mapping, scenario quality, outside-in layout
|
|
28
28
|
- `verified-build` — build + test loop that gates on a verifier verdict
|
|
29
|
+
- `advisor` — turns the session into the advisor-orchestrator: it spawns executor subagents to do the code edits and test runs, and answers a blocked executor with a plan, correction, or stop
|
|
30
|
+
- `advisor-refresh` — sub-skill fired by the `/advisor` loop to re-assert the executor-advisor discipline mid-run
|
|
29
31
|
|
|
30
32
|
**PR review and convergence**
|
|
31
33
|
- `autoconverge` — autonomous single-run workflow that drives a PR to ready
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: advisor
|
|
3
|
+
description: >-
|
|
4
|
+
Turns the session into the advisor-orchestrator — the user's sole interface,
|
|
5
|
+
which spawns and resumes executor subagents (clean-coder and the like) to do
|
|
6
|
+
all the code editing and every build or test run. When an executor hits a
|
|
7
|
+
blocker it consults the advisor, which replies with one of three brief
|
|
8
|
+
signals — a plan, a correction, or a stop. The advisor orchestrates and
|
|
9
|
+
advises but never edits code or runs tests itself. Caps consultations per
|
|
10
|
+
task (default 5), reuses warm agents before spawning new ones, and
|
|
11
|
+
re-asserts the discipline every 20 minutes through the /advisor-refresh
|
|
12
|
+
loop. Adapts Anthropic's advisor strategy to Claude Code. Triggers:
|
|
13
|
+
'/advisor', 'advisor strategy', 'run with an advisor', 'executor-advisor
|
|
14
|
+
mode'.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Advisor Strategy
|
|
18
|
+
|
|
19
|
+
## Principle
|
|
20
|
+
|
|
21
|
+
A cost-effective executor runs the primary work — it calls tools, reads
|
|
22
|
+
results, and iterates — while a stronger model advises only at the hard
|
|
23
|
+
decisions. Source: Anthropic's advisor strategy,
|
|
24
|
+
https://claude.com/blog/the-advisor-strategy.
|
|
25
|
+
|
|
26
|
+
Under this skill the session is the advisor-orchestrator. In Claude Code the
|
|
27
|
+
user always talks to the session and never to a subagent, so the session is
|
|
28
|
+
the user's sole interface: all user-facing communication flows through it. It
|
|
29
|
+
spawns and resumes executor subagents — `clean-coder` and the like — and those
|
|
30
|
+
executors do every bit of the execution: the code edits, the build runs, the
|
|
31
|
+
test runs. The advisor drives the plan and answers the executors when they get
|
|
32
|
+
stuck.
|
|
33
|
+
|
|
34
|
+
This is the advisor-lite shape: the blog's pure pairing keeps the advisor
|
|
35
|
+
tool-less and hidden from the user, but Claude Code routes every user message
|
|
36
|
+
through the session, so the advisor here stays the user's interface while
|
|
37
|
+
keeping execution out of its own hands. Consultations are capped (default 5
|
|
38
|
+
per task) — the same guard the API's `max_uses` gives a tool.
|
|
39
|
+
|
|
40
|
+
## Gotchas
|
|
41
|
+
|
|
42
|
+
- **Double invocation duplicates the reminder loop.** A second `/advisor` in
|
|
43
|
+
the same session schedules a second refresh loop. Check whether the loop is
|
|
44
|
+
already running before you schedule one (see the invocation guard in
|
|
45
|
+
Process step 1).
|
|
46
|
+
- **The advisor never executes.** The moment it edits a file or runs the tests
|
|
47
|
+
itself, the pairing breaks and the executor's warm context is wasted. Hand
|
|
48
|
+
every code edit and every build or test run to an executor; keep the
|
|
49
|
+
advisor's own tool use to orchestration and light verification reads.
|
|
50
|
+
- **Resuming an unnamed background agent needs its agentId.** A background
|
|
51
|
+
spawn returns an `agentId` (format `a...-...`); keep it so `SendMessage` can
|
|
52
|
+
reach that agent later. A named agent is reachable by name.
|
|
53
|
+
- **Consultations past the cap signal a scoping problem.** When five
|
|
54
|
+
consultations do not clear the blocker, the task needs re-scoping or a
|
|
55
|
+
hand-off to the user — not a sixth round of advice.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Process
|
|
59
|
+
|
|
60
|
+
1. **Invocation guard (once per session).** Before scheduling anything, check
|
|
61
|
+
whether the refresh loop is already running this session. If it is, skip
|
|
62
|
+
straight to orchestration — do not schedule a second loop.
|
|
63
|
+
|
|
64
|
+
2. **Register the discipline reminder.** By default, schedule it with
|
|
65
|
+
`ScheduleWakeup` at `delaySeconds: 1200`, prompt `/advisor-refresh`, where
|
|
66
|
+
each refresh re-schedules the next one — a 1200-second wakeup costs one
|
|
67
|
+
prompt-cache miss per firing and nothing more (see Gotchas). The loop
|
|
68
|
+
mechanism (`/loop 20m /advisor-refresh`) is the escape hatch when
|
|
69
|
+
`ScheduleWakeup` is not available. Either way the reminder is the
|
|
70
|
+
enforcement surface: each firing re-asserts the discipline while the run is
|
|
71
|
+
in flight.
|
|
72
|
+
|
|
73
|
+
3. **Orchestrate the task.** Hold the plan and the user conversation. Spawn or
|
|
74
|
+
resume executor subagents (for example `clean-coder`) to do every code edit
|
|
75
|
+
and every build or test run, and keep driving while they work. Your own
|
|
76
|
+
tool use stays orchestration and light verification reads. Keep your task list updated religiously.
|
|
77
|
+
|
|
78
|
+
4. **Executors consult at a hard decision.** Each executor's spawn prompt tells
|
|
79
|
+
it to stop and message you — with the task, what it tried, and the exact
|
|
80
|
+
blocker (plus any short code excerpt that helps) — when one of these holds:
|
|
81
|
+
- It has tried the same problem twice or more and it still fails.
|
|
82
|
+
- A decision changes the deliverable's scope or a contract that is hard to
|
|
83
|
+
reverse.
|
|
84
|
+
- Two constraints conflict and it cannot satisfy both.
|
|
85
|
+
- It is unsure whether to stop or keep going.
|
|
86
|
+
|
|
87
|
+
5. **Answer with one signal.** On a consultation, reply with exactly one
|
|
88
|
+
signal, brief (about 400 to 700 tokens):
|
|
89
|
+
- **PLAN** — a different approach, as concrete ordered steps the executor
|
|
90
|
+
can run. When a warm agent fits the plan, name which one to resume.
|
|
91
|
+
- **CORRECTION** — the executor's approach is right, one thing is wrong;
|
|
92
|
+
name the wrong step and the fix.
|
|
93
|
+
- **STOP** — no path satisfies the task as assigned; say why so it can be
|
|
94
|
+
reported upward.
|
|
95
|
+
The executor resumes the moment your reply lands.
|
|
96
|
+
|
|
97
|
+
A worked consultation:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Executor → advisor
|
|
101
|
+
Task: add a retry to the upload client.
|
|
102
|
+
Tried: wrapped upload() in a three-attempt loop; the second attempt
|
|
103
|
+
double-posts.
|
|
104
|
+
Blocker: the server takes no idempotency key, so a retry after a timeout
|
|
105
|
+
creates a duplicate record.
|
|
106
|
+
|
|
107
|
+
Advisor → executor
|
|
108
|
+
CORRECTION — the retry loop is right; the missing piece is a stable request
|
|
109
|
+
id. Generate one client-side on the first attempt and send the same id on
|
|
110
|
+
every retry, so the server treats the retries as one request.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For a decision the advisor itself cannot settle, it may spawn the tool-less
|
|
114
|
+
`code-advisor` agent for a second opinion — an optional escalation, not a
|
|
115
|
+
required step.
|
|
116
|
+
|
|
117
|
+
## Agent reuse (non-negotiable)
|
|
118
|
+
|
|
119
|
+
- **Resume before you spawn, always.** A warm agent carries its context and
|
|
120
|
+
cached tokens; a fresh spawn starts cold and pays to rebuild both.
|
|
121
|
+
`SendMessage` with an agent's name or `agentId` resumes a running or a
|
|
122
|
+
completed agent with its context intact — verified live in this environment.
|
|
123
|
+
Prefer that path every time an existing agent holds relevant context.
|
|
124
|
+
- **Spawn a fresh agent only when** no existing agent holds relevant context,
|
|
125
|
+
or a genuine task switch needs a clean context.
|
|
126
|
+
- **Name the agent to resume.** When you answer with a PLAN and a warm agent
|
|
127
|
+
fits, say which agent to resume and where.
|
|
128
|
+
|
|
129
|
+
## Constraints
|
|
130
|
+
|
|
131
|
+
- One `/advisor` per session; the invocation guard blocks a second reminder
|
|
132
|
+
loop.
|
|
133
|
+
- The advisor orchestrates and advises but never edits code or runs a build or
|
|
134
|
+
test itself — executors do that.
|
|
135
|
+
- Consultations are capped at five per task by default. At the cap, re-scope
|
|
136
|
+
or hand off; do not keep answering.
|
|
137
|
+
- Reuse a warm agent over a cold spawn whenever one holds relevant context.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: advisor-refresh
|
|
3
|
+
description: >-
|
|
4
|
+
Fired by the /advisor loop reminder about every 20 minutes to re-assert the
|
|
5
|
+
advisor discipline mid-run. A compressed restatement of /advisor: orchestrate
|
|
6
|
+
rather than execute, answer a blocked executor with a plan, correction, or
|
|
7
|
+
stop, and reuse warm agents before spawning new ones. Triggers:
|
|
8
|
+
'/advisor-refresh'.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Advisor Refresh
|
|
12
|
+
|
|
13
|
+
1. **You are the advisor.** Orchestrate and hold the user conversation; spawn
|
|
14
|
+
executor subagents to do all the work — every code edit and build or test
|
|
15
|
+
run.
|
|
16
|
+
2. **An executor blocked twice on the same thing?** Answer it with one signal
|
|
17
|
+
— a plan, a correction, or a stop — brief. Never take over the edit or the
|
|
18
|
+
tests yourself.
|
|
19
|
+
3. **Resume before you spawn.** `SendMessage` an existing agent by name or
|
|
20
|
+
`agentId` to reuse its warm context; prefer that over a cold spawn.
|
|
21
|
+
4. **Fresh spawn only for a genuine task switch.** No tool compacts or clears a
|
|
22
|
+
subagent's context, so a clean context comes from a fresh spawn — never tell
|
|
23
|
+
an agent to compact.
|
|
24
|
+
5. **Re-schedule the next refresh** (about 1200 seconds out) when the loop
|
|
25
|
+
mechanism needs each firing to queue the following one.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- **Clean-room audits, every loop.** Each bugfind subagent's spawn prompt contains only the PR scope, audit rubric, and the current loop number. Prior loop history stays in the lead.
|
|
13
13
|
- **Targeted fixes.** Each fix subagent sees ONLY the most recent audit's findings. Prior loops are invisible to the fix subagent.
|
|
14
14
|
- **Fix subagent receives the latest audit as its input contract.** Each loop's fix run operates on the current audit's output and only that.
|
|
15
|
-
- **Lead owns the final PR description rewrite only** (Step 4.5),
|
|
15
|
+
- **Lead owns the final PR description rewrite only** (Step 4.5), composed directly against `docs/PR_DESCRIPTION_GUIDE.md`.
|
|
16
16
|
|
|
17
17
|
## Why this design
|
|
18
18
|
|
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -98,7 +98,7 @@ end-to-end mental model before starting Step 0.
|
|
|
98
98
|
| FIX action and verify-push semantics | [reference/audit-and-teammates.md](reference/audit-and-teammates.md) |
|
|
99
99
|
| Posting the end-of-pass audit review (APPROVE on CLEAN, REQUEST_CHANGES with inline anchored comments on DIRTY) | [§ Audit posting](#audit-posting), which applies [../post-audit-findings/SKILL.md](../post-audit-findings/SKILL.md) |
|
|
100
100
|
| Posting per-finding fix replies via GitHub MCP `add_reply_to_pull_request_comment` (rendered with the unified template at [`_shared/pr-loop/audit-reply-template.md`](../../_shared/pr-loop/audit-reply-template.md)) | [reference/github-pr-reviews.md](reference/github-pr-reviews.md) |
|
|
101
|
-
| Teardown, PR description rewrite
|
|
101
|
+
| Teardown, PR description rewrite composed by the lead, permission revoke, final report | [../pr-loop-lifecycle/reference/teardown-publish-permissions.md](../pr-loop-lifecycle/reference/teardown-publish-permissions.md) |
|
|
102
102
|
| Spawn-prompt XML, A–P category bindings, outcome XML schemas | [PROMPTS.md](PROMPTS.md) |
|
|
103
103
|
| Per-category audit content (sub-buckets, decision criteria, ready-to-send Variant C templates) | `$HOME/.claude/audit-rubrics/{category_rubrics,prompts}/` |
|
|
104
104
|
| Invariants and design rationale | [CONSTRAINTS.md](CONSTRAINTS.md), [reference/design-rationale.md](reference/design-rationale.md) |
|
|
@@ -5,7 +5,7 @@ description: >-
|
|
|
5
5
|
auto-mode AskUserQuestion escalation when the classifier blocks it),
|
|
6
6
|
worktree preflight and cwd routing, then the ordered close — conditional
|
|
7
7
|
TeamDelete for team callers, worktree teardown, working-tree clean, PR
|
|
8
|
-
description rewrite
|
|
8
|
+
description rewrite composed by the lead, the always-run permission
|
|
9
9
|
revoke, and the caller-parameterized final report. Invoked by PR-loop
|
|
10
10
|
orchestrators (bugteam, pr-converge, autoconverge, qbug) at run start and
|
|
11
11
|
run end, including error exits; not for general git cleanup or permission
|
|
@@ -48,7 +48,7 @@ Run these in order from the lead session on EVERY exit — converged, cap reache
|
|
|
48
48
|
```
|
|
49
49
|
Tolerates already-removed worktrees and missing directories; removal is Windows-safe per `~/.claude/rules/windows-filesystem-safe.md`.
|
|
50
50
|
3. **Clean the working tree.** Return to the session worktree, remove run-scoped scratch files, and leave `git status` clean of run artifacts.
|
|
51
|
-
4. **Rewrite the PR description.** Follow [`reference/teardown-publish-permissions.md` § Publish the final PR description](reference/teardown-publish-permissions.md): capture the cumulative diff and original body,
|
|
51
|
+
4. **Rewrite the PR description.** Follow [`reference/teardown-publish-permissions.md` § Publish the final PR description](reference/teardown-publish-permissions.md): capture the cumulative diff and original body, compose the new body directly against `docs/PR_DESCRIPTION_GUIDE.md`, publish via `update_pull_request`, remove the scratch files. On failure, report it and continue — the revoke still runs.
|
|
52
52
|
5. **Revoke project permissions (always):**
|
|
53
53
|
`python "$HOME/.claude/_shared/pr-loop/scripts/revoke_project_claude_permissions.py"`
|
|
54
54
|
Non-negotiable, including on error exits: leaving the grant in place lets future sessions inherit elevated `.claude/**` access without an explicit opt-in. Run revoke even when earlier close steps partially failed; log cleanup errors separately.
|
|
@@ -35,26 +35,13 @@ When the run exits (any reason), run these steps in order from **this** session
|
|
|
35
35
|
|
|
36
36
|
After teardown and before permission revoke, the lead rewrites the PR body to the PR's **final cumulative state** — what the change delivers, not the loop's process. This is the **only** PR-write the lead performs (audit and fix comments stay with the agents that produced them).
|
|
37
37
|
|
|
38
|
-
The lead
|
|
39
|
-
|
|
40
|
-
`pr-description-writer` comes from the global git-workflow rule in `claude-code-config`. Invoke with `Agent`:
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
Agent(
|
|
44
|
-
subagent_type="pr-description-writer",
|
|
45
|
-
mode="bypassPermissions",
|
|
46
|
-
description="Rewrite PR <number> body from cumulative diff",
|
|
47
|
-
prompt="<brief from steps below>"
|
|
48
|
-
)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
If that subagent is missing, fall back to `general-purpose` with the same brief — the hook treats agent-authored bodies the same. If neither exists, log a warning and skip this step.
|
|
38
|
+
The lead composes the body text directly against `docs/PR_DESCRIPTION_GUIDE.md` — no agent spawn — so the body passes the `pr_description_enforcer` hook's style audit on the `gh pr edit` that follows.
|
|
52
39
|
|
|
53
40
|
**Steps:**
|
|
54
41
|
|
|
55
42
|
1. Capture cumulative diff: `pull_request_read(method="get_diff", pullNumber=N, owner=O, repo=R)` → write the response text to `.<caller>-final.diff` using the `Write` tool.
|
|
56
43
|
2. Capture original body: `pull_request_read(method="get", pullNumber=N, owner=O, repo=R)` → extract `.body` from the response, write it to `.<caller>-original-body.md` using the `Write` tool.
|
|
57
|
-
3.
|
|
44
|
+
3. Compose the new body from those inputs:
|
|
58
45
|
- **Inputs:** diff path, original body path, head branch, base branch.
|
|
59
46
|
- **Constraint:** describe what the PR delivers from the cumulative diff — behavior, user-visible effect, merge rationale. Process metadata (loops, fix counts, findings) stays in review comments.
|
|
60
47
|
- **Preservation rule:** if the original body has manually curated sections (linked issues, screenshots, test plan, "Risk Assessment", etc.), preserve them verbatim and only rewrite narrative around them.
|
|
@@ -63,7 +50,7 @@ If that subagent is missing, fall back to `general-purpose` with the same brief
|
|
|
63
50
|
5. Publish the new body: `update_pull_request(pullNumber=N, owner=O, repo=R, body=<contents of .<caller>-final-body.md>)`.
|
|
64
51
|
6. Remove `.<caller>-final.diff`, `.<caller>-original-body.md`, `.<caller>-final-body.md`.
|
|
65
52
|
|
|
66
|
-
If this step fails (
|
|
53
|
+
If this step fails (hook block, network), report in the final report and continue to the revoke. The original PR body remains; commits and comments are unaffected.
|
|
67
54
|
|
|
68
55
|
## Revoke project permissions (mandatory, always)
|
|
69
56
|
|
package/skills/qbug/SKILL.md
CHANGED
|
@@ -326,7 +326,7 @@ comment body via `INLINE_COMMENT_BODY_TEMPLATE`):
|
|
|
326
326
|
|
|
327
327
|
## Step 3: PR description refresh (lead)
|
|
328
328
|
|
|
329
|
-
|
|
329
|
+
Compose the body directly against `docs/PR_DESCRIPTION_GUIDE.md` — no agent spawn — from the final PR diff and the original body. Apply via `update_pull_request(pullNumber=<number>, owner=<owner>, repo=<repo>, body=<new_body>)`.
|
|
330
330
|
|
|
331
331
|
On error exit paths: best-effort; log the failure in the final report and continue.
|
|
332
332
|
|