claude-dev-env 1.94.0 → 1.95.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/_shared/advisor/CLAUDE.md +2 -2
- package/_shared/advisor/advisor-protocol.md +35 -27
- package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +3 -2
- package/_shared/advisor/scripts/model_tier_run_validator.py +23 -15
- package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +81 -17
- package/bin/CLAUDE.md +10 -1
- package/bin/ever-shipped-skills.mjs +70 -0
- package/bin/install.mjs +136 -6
- package/bin/install.prune.test.mjs +457 -0
- package/docs/CODE_RULES.md +1 -1
- package/hooks/blocking/code_rules_enforcer.py +4 -0
- package/hooks/blocking/code_rules_shared.py +82 -0
- package/hooks/blocking/code_rules_test_layout.py +9 -3
- package/hooks/blocking/plain_language_blocker.py +138 -4
- package/hooks/blocking/sensitive_file_protector.py +114 -48
- package/hooks/blocking/tdd_enforcer.py +9 -2
- package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +105 -0
- package/hooks/blocking/test_code_rules_shared.py +181 -0
- package/hooks/blocking/test_plain_language_blocker_allowlist.py +184 -0
- package/hooks/blocking/test_sensitive_file_protector.py +185 -0
- package/hooks/blocking/test_tdd_enforcer_scratchpad.py +105 -0
- package/hooks/hooks_constants/CLAUDE.md +2 -0
- package/hooks/hooks_constants/harness_scratchpad_constants.py +17 -0
- package/hooks/hooks_constants/plain_language_blocker_constants.py +5 -0
- package/hooks/hooks_constants/sensitive_file_protector_constants.py +42 -0
- package/hooks/pyproject.toml +75 -4
- package/hooks/validators/CLAUDE.md +1 -1
- package/hooks/validators/README.md +2 -0
- package/hooks/validators/python_style_checks.py +114 -136
- package/hooks/validators/python_style_helpers.py +95 -0
- package/hooks/validators/test_python_style_checks.py +0 -164
- package/hooks/validators/test_python_style_checks_decorator_gap.py +119 -0
- package/hooks/validators/test_python_style_fixes.py +251 -0
- package/hooks/validators/test_python_style_helpers.py +125 -0
- package/package.json +1 -1
- package/rules/CLAUDE.md +1 -0
- package/rules/anti-corollary-tests.md +69 -0
- package/rules/bdd.md +1 -3
- package/rules/code-reviews.md +1 -1
- package/rules/gh-paginate.md +1 -1
- package/rules/plain-language.md +2 -0
- package/skills/CLAUDE.md +4 -3
- package/skills/autoconverge/workflow/converge.mjs +2 -2
- package/skills/bugteam/reference/README.md +2 -3
- package/skills/closeout/SKILL.md +153 -0
- package/skills/closeout/reference/handoff-prompt-template.md +72 -0
- package/skills/closeout/reference/issue-body-templates.md +108 -0
- package/skills/closeout/reference/pii-redaction-checklist.md +36 -0
- package/skills/orchestrator/SKILL.md +27 -21
- package/skills/orchestrator-refresh/SKILL.md +12 -8
- package/skills/pr-converge/CLAUDE.md +1 -1
- package/skills/pr-fix-protocol/SKILL.md +65 -0
- package/skills/skill-builder/references/skill-modularity.md +1 -1
- package/skills/team-advisor/SKILL.md +15 -11
- package/system-prompts/software-engineer.xml +7 -6
- package/hooks/validators/test_verify_paths.py +0 -32
- package/hooks/validators/verify_paths.py +0 -57
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Tests for the shared source-line and function-discovery helpers."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
|
|
5
|
+
from .python_style_helpers import (
|
|
6
|
+
blank_line_for_source,
|
|
7
|
+
function_start_line,
|
|
8
|
+
gap_is_blank_only,
|
|
9
|
+
iter_function_definitions,
|
|
10
|
+
real_newline_lines,
|
|
11
|
+
top_level_functions,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
TWO_FUNCTIONS = """def foo() -> None:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def bar() -> None:
|
|
19
|
+
pass
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
DECORATED_FUNCTION = """@decorator
|
|
23
|
+
def decorated() -> None:
|
|
24
|
+
pass
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
CRLF_SOURCE = "def foo() -> None:\r\n pass\r\n"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestIterFunctionDefinitions:
|
|
31
|
+
"""Discovery of every function definition in a tree."""
|
|
32
|
+
|
|
33
|
+
def test_yields_each_function(self) -> None:
|
|
34
|
+
"""Every top-level function is yielded."""
|
|
35
|
+
tree = ast.parse(TWO_FUNCTIONS)
|
|
36
|
+
names = [each.name for each in iter_function_definitions(tree)]
|
|
37
|
+
assert names == ["foo", "bar"]
|
|
38
|
+
|
|
39
|
+
def test_yields_nested_functions(self) -> None:
|
|
40
|
+
"""A nested function is discovered alongside its enclosing function."""
|
|
41
|
+
tree = ast.parse("def outer() -> None:\n def inner() -> None:\n pass\n")
|
|
42
|
+
names = {each.name for each in iter_function_definitions(tree)}
|
|
43
|
+
assert names == {"outer", "inner"}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TestTopLevelFunctions:
|
|
47
|
+
"""Ordered listing of a module's top-level functions."""
|
|
48
|
+
|
|
49
|
+
def test_returns_functions_in_line_order(self) -> None:
|
|
50
|
+
"""Top-level functions are returned ordered by line."""
|
|
51
|
+
ordered = top_level_functions(TWO_FUNCTIONS)
|
|
52
|
+
assert [each.name for each in ordered] == ["foo", "bar"]
|
|
53
|
+
|
|
54
|
+
def test_ignores_nested_functions(self) -> None:
|
|
55
|
+
"""A function nested inside another is not top-level."""
|
|
56
|
+
ordered = top_level_functions(
|
|
57
|
+
"def outer() -> None:\n def inner() -> None:\n pass\n"
|
|
58
|
+
)
|
|
59
|
+
assert [each.name for each in ordered] == ["outer"]
|
|
60
|
+
|
|
61
|
+
def test_syntax_error_returns_empty(self) -> None:
|
|
62
|
+
"""Unparseable source yields no functions."""
|
|
63
|
+
assert top_level_functions("def foo(") == []
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TestFunctionStartLine:
|
|
67
|
+
"""First source line of a function, counting decorators."""
|
|
68
|
+
|
|
69
|
+
def test_undecorated_uses_def_line(self) -> None:
|
|
70
|
+
"""An undecorated function starts on its def line."""
|
|
71
|
+
function_node = top_level_functions(TWO_FUNCTIONS)[0]
|
|
72
|
+
assert function_start_line(function_node) == 1
|
|
73
|
+
|
|
74
|
+
def test_decorated_uses_first_decorator_line(self) -> None:
|
|
75
|
+
"""A decorated function starts on its first decorator line."""
|
|
76
|
+
function_node = top_level_functions(DECORATED_FUNCTION)[0]
|
|
77
|
+
assert function_start_line(function_node) == 1
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class TestGapIsBlankOnly:
|
|
81
|
+
"""Whether a run of lines between functions is entirely blank."""
|
|
82
|
+
|
|
83
|
+
def test_all_blank_lines_true(self) -> None:
|
|
84
|
+
"""A gap of blank lines reports blank-only."""
|
|
85
|
+
assert gap_is_blank_only(["\n", " \n", ""]) is True
|
|
86
|
+
|
|
87
|
+
def test_non_blank_line_false(self) -> None:
|
|
88
|
+
"""A gap holding any content is not blank-only."""
|
|
89
|
+
assert gap_is_blank_only(["\n", "# comment\n"]) is False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TestRealNewlineLines:
|
|
93
|
+
"""Line splitting aligned with ast line numbers."""
|
|
94
|
+
|
|
95
|
+
def test_splits_on_lf(self) -> None:
|
|
96
|
+
"""LF-separated source splits into its lines with endings kept."""
|
|
97
|
+
assert real_newline_lines("a\nb\n") == ["a\n", "b\n"]
|
|
98
|
+
|
|
99
|
+
def test_splits_on_crlf(self) -> None:
|
|
100
|
+
"""CRLF pairs count as a single line ending."""
|
|
101
|
+
assert real_newline_lines("a\r\nb\r\n") == ["a\r\n", "b\r\n"]
|
|
102
|
+
|
|
103
|
+
def test_form_feed_stays_in_line(self) -> None:
|
|
104
|
+
"""A form feed does not start a new line, matching ast line numbers."""
|
|
105
|
+
assert real_newline_lines("a\x0cb\n") == ["a\x0cb\n"]
|
|
106
|
+
|
|
107
|
+
def test_trailing_partial_line_kept(self) -> None:
|
|
108
|
+
"""A final line with no ending is preserved."""
|
|
109
|
+
assert real_newline_lines("a\nb") == ["a\n", "b"]
|
|
110
|
+
|
|
111
|
+
def test_empty_source_returns_no_lines(self) -> None:
|
|
112
|
+
"""Empty source yields an empty list of lines."""
|
|
113
|
+
assert real_newline_lines("") == []
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class TestBlankLineForSource:
|
|
117
|
+
"""Blank-line string matching the source newline convention."""
|
|
118
|
+
|
|
119
|
+
def test_lf_source_returns_lf(self) -> None:
|
|
120
|
+
"""LF source yields an LF blank line."""
|
|
121
|
+
assert blank_line_for_source("a\nb\n") == "\n"
|
|
122
|
+
|
|
123
|
+
def test_crlf_source_returns_crlf(self) -> None:
|
|
124
|
+
"""CRLF source yields a CRLF blank line."""
|
|
125
|
+
assert blank_line_for_source(CRLF_SOURCE) == "\r\n"
|
package/package.json
CHANGED
package/rules/CLAUDE.md
CHANGED
|
@@ -12,6 +12,7 @@ Rule files installed into `~/.claude/rules/` by `bin/install.mjs`. Claude Code l
|
|
|
12
12
|
| File | Rule |
|
|
13
13
|
|---|---|
|
|
14
14
|
| `agent-spawn-protocol.md` | Protocol for spawning subagents: context sufficiency check, prompt generation via `/prompt-generator`, then spawn |
|
|
15
|
+
| `anti-corollary-tests.md` | Tests must carry information: no corollary matrices over canonical reductions, no suite that only matches a dead-implementation default, stated mutation in the audit lane |
|
|
15
16
|
| `ask-user-question-required.md` | Every user-directed question goes through the `AskUserQuestion` tool — no plain-text questions |
|
|
16
17
|
| `bdd.md` | BDD discovery-driven development workflow and Example Mapping reference |
|
|
17
18
|
| `claude-md-orphan-file.md` | Every backticked bare filename in a per-directory `CLAUDE.md` table's first column names a file in that directory's subtree |
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/test_*.py"
|
|
4
|
+
- "**/*_test.py"
|
|
5
|
+
- "**/*.test.*"
|
|
6
|
+
- "**/*.spec.*"
|
|
7
|
+
- "**/conftest.py"
|
|
8
|
+
- "**/tests/**"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Anti-Corollary Tests
|
|
12
|
+
|
|
13
|
+
**When this applies:** Any Write or Edit that adds or changes tests.
|
|
14
|
+
|
|
15
|
+
## Rule
|
|
16
|
+
|
|
17
|
+
A large green suite can prove almost nothing. Before you keep a case, answer three questions. If any answer fails, cut the case or replace it with one that carries information.
|
|
18
|
+
|
|
19
|
+
## The three questions
|
|
20
|
+
|
|
21
|
+
### 1. Is this a corollary?
|
|
22
|
+
|
|
23
|
+
When the code reduces each input to a canonical form and then compares the forms, every pairwise combination of input spellings follows once the reduction is proven canonical. Walking the full N×N matrix restates that fact. It adds cases and runtime, and it buries the few cases that carry information.
|
|
24
|
+
|
|
25
|
+
**Do this:** test the reduction once. Test the comparison with a few discriminating cases. Do not walk the cross product of spellings.
|
|
26
|
+
|
|
27
|
+
### 2. Could this test pass if the mechanism were dead?
|
|
28
|
+
|
|
29
|
+
Name the degenerate value a dead implementation would return — empty string, `None`, `False`, a blanket refusal, an empty collection. When the test's expected value equals that default, the test passes whether the mechanism works or not. On its own it proves nothing.
|
|
30
|
+
|
|
31
|
+
**Do this:** keep at least one case that expects the **non-default** answer, and drive the real code path — not a mock that only records that a call happened.
|
|
32
|
+
|
|
33
|
+
### 3. What single change to the code would make this test fail?
|
|
34
|
+
|
|
35
|
+
When the honest answer is "none," or "only a change that also breaks everything else," the test is decoration. Drop it or rewrite it so one named mutation kills it.
|
|
36
|
+
|
|
37
|
+
## What a mechanism with a degenerate failure mode needs
|
|
38
|
+
|
|
39
|
+
1. **At least one non-default case** that exercises the live path and expects the non-default answer.
|
|
40
|
+
2. **A stated mutation (audit lane):** name one specific change to the code and record how many tests it kills. A mutation that kills zero tests means the suite proves nothing. A reviewer or an audit skill checks this; a hook does not compute it.
|
|
41
|
+
3. **A few discriminating cases** in place of a large matrix.
|
|
42
|
+
|
|
43
|
+
## Worked shape (sanitized)
|
|
44
|
+
|
|
45
|
+
A write guard decides whether a write is about to hit a production database. It reduces each database URL to a canonical endpoint identity, then compares identities.
|
|
46
|
+
|
|
47
|
+
Two independent mutations show the two halves of a useful suite:
|
|
48
|
+
|
|
49
|
+
- Gut the reduction so it always returns the empty string: the guard fails **closed** and refuses everything. Only the *allow*-expecting cases die.
|
|
50
|
+
- Abandon the reduction and compare raw hostnames: the guard fails **open** and allows a production write. Only the *refuse*-expecting cases die.
|
|
51
|
+
|
|
52
|
+
Opposite breaks kill opposite halves. A suite with only one half cannot see one of those breaks. Build both halves; skip the spelling matrix once the reduction is covered.
|
|
53
|
+
|
|
54
|
+
## What this is not
|
|
55
|
+
|
|
56
|
+
A structural hook is the wrong tool here. "Is this a corollary?" and "would this pass against a dead implementation?" need the intent of the code under test. A hook that pattern-matches `parametrize` breadth or counts assertions fires on correct suites and trains people to ignore it. A false-positive gate on a judgment call is worse than no gate. This rule stays judgment-only, with the stated-mutation check in the audit lane — the same pattern as other judgment rules in this package that have no Write/Edit blocker.
|
|
57
|
+
|
|
58
|
+
## Sibling rules
|
|
59
|
+
|
|
60
|
+
| Rule | Role |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `tdd.md` | Write a failing test before production code |
|
|
63
|
+
| `testing.md` | Mocks and test infrastructure standards |
|
|
64
|
+
| `paired-test-coverage.md` | Every public function in an established suite gets a behavioral test |
|
|
65
|
+
| `anti-corollary-tests.md` | Each test carries information; no corollary matrices; no suite that only matches the dead default |
|
|
66
|
+
|
|
67
|
+
## Enforcement
|
|
68
|
+
|
|
69
|
+
The AI review lane and audit skills carry this rule: an agent applies it to the test lines a PR changes. No blocking hook backs it, because corollary and dead-default judgments need meaning a regex cannot read.
|
package/rules/bdd.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
**Canonical detail:** `~/.claude/system-prompts/software-engineer.xml` → `<behavior_protocol>`.
|
|
4
4
|
|
|
5
|
-
**On-demand depth:** `@~/.claude/skills/bdd-protocol/SKILL.md` (Example Mapping §6.4, §7.6 catalog, solo patterns). Tracking design: [jl-cmd/claude-dev-env#82](https://github.com/jl-cmd/claude-dev-env/issues/82).
|
|
6
|
-
|
|
7
5
|
**Optional long-form references (load when needed):**
|
|
8
6
|
|
|
9
7
|
- `@~/.claude/docs/BDD_SCENARIO_QUALITY.md` — seven scenario quality patterns (§7.6-style)
|
|
@@ -21,7 +19,7 @@ Conversation is the essential practice: if discovery is skipped, structured form
|
|
|
21
19
|
|
|
22
20
|
## Solo developer
|
|
23
21
|
|
|
24
|
-
You are often the stakeholder. Use **Example Mapping** in chat ("the one where …", probes, parking lot).
|
|
22
|
+
You are often the stakeholder. Use **Example Mapping** in chat ("the one where …", probes, parking lot). See the optional long-form references above for the full algorithm and anti-pattern list.
|
|
25
23
|
|
|
26
24
|
## Naming
|
|
27
25
|
|
package/rules/code-reviews.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**When this applies:** GitHub PR review feedback on a branch you are fixing.
|
|
4
4
|
|
|
5
|
-
**MANDATORY PROTOCOL
|
|
5
|
+
**MANDATORY PROTOCOL:**
|
|
6
6
|
|
|
7
7
|
1. Fetch ALL reviewer comments BEFORE any fixes
|
|
8
8
|
2. Create TodoWrite checklist - One item per comment
|
package/rules/gh-paginate.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# gh API Pagination
|
|
2
2
|
|
|
3
|
-
Every `gh api` read of a paginated GitHub list endpoint (PR `reviews`/`comments`/`files`, issue `comments`, `pulls`, `issues`) uses `--paginate --slurp` piped to **external** `jq` — `gh`'s built-in `--jq` runs per page, so cross-page operations like `sort_by | last` give wrong-but-confident results. Single-object endpoints (`pulls/<n>`, `issues/<n>`) skip pagination and may use `--jq` directly.
|
|
3
|
+
Every `gh api` read of a paginated GitHub list endpoint (PR `reviews`/`comments`/`files`, issue `comments`, `pulls`, `issues`) uses `--paginate --slurp` piped to **external** `jq` — `gh`'s built-in `--jq` runs per page, so cross-page operations like `sort_by | last` give wrong-but-confident results. Single-object endpoints (`pulls/<n>`, `issues/<n>`) skip pagination and may use `--jq` directly. For a newest-first walk, sort the slurped array and take the last element; for single-page bounds, cap with a `per_page` query parameter.
|
package/rules/plain-language.md
CHANGED
|
@@ -3,3 +3,5 @@
|
|
|
3
3
|
All prose a person reads (chat, `AskUserQuestion`, docs, PR/issue bodies, commits): everyday words, short active sentences, lead with the answer, define jargon on first use, and give only the detail the reader needs to act (progressive disclosure). Aim for first-pass readability by a non-specialist. Exact identifiers, file paths, and API names stay exact; code is out of scope.
|
|
4
4
|
|
|
5
5
|
The `plain_language_blocker` PreToolUse hook (AskUserQuestion + `.md` Write/Edit/MultiEdit) blocks a heavy word and names the everyday swap; code fences, inline code, blockquotes, URLs, and file paths are skipped.
|
|
6
|
+
|
|
7
|
+
A project can keep its own domain words out of the check with a `.claude/plain-language-allow.json` file: a JSON array of terms. An exact, case-insensitive, whole-word match on any term passes. The hook reads this file only from inside the project tree, up to the repository root, so each project's allowlist stays with its own code.
|
package/skills/CLAUDE.md
CHANGED
|
@@ -23,9 +23,9 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
|
|
|
23
23
|
|
|
24
24
|
**Planning and implementation**
|
|
25
25
|
- `anthropic-plan` — creates a source-grounded plan packet before any code changes
|
|
26
|
-
- `orchestrator` — turns the session into the orchestrator: it spawns executor subagents to do the code edits and test runs; hard decisions go to a shared advisor (Claude warm `session-advisor` via SendMessage; Grok
|
|
27
|
-
- `orchestrator-refresh` — sub-skill fired by the `/orchestrator` loop to re-assert the host-matched shared-advisor discipline mid-run (Claude SendMessage; Grok
|
|
28
|
-
- `team-advisor` — binds one advisor at the strongest reachable tier (Claude warm agent; Grok
|
|
26
|
+
- `orchestrator` — turns the session into the orchestrator: it spawns executor subagents to do the code edits and test runs; hard decisions go to a shared advisor (Claude warm `session-advisor` via SendMessage; Grok: max-tier Claude via CLI Claude-chain)
|
|
27
|
+
- `orchestrator-refresh` — sub-skill fired by the `/orchestrator` loop to re-assert the host-matched shared-advisor discipline mid-run (Claude SendMessage; Grok Claude CLI chain, no Agent-tool advisor spawn)
|
|
28
|
+
- `team-advisor` — binds one advisor at the strongest reachable tier (Claude warm agent; Grok max-tier Claude via CLI Claude-chain, fail closed when unreachable) and consults it for a second opinion before a big decision, at completion, when stuck, or when reconsidering the approach
|
|
29
29
|
|
|
30
30
|
**PR review and convergence**
|
|
31
31
|
- `autoconverge` — autonomous single-run workflow that drives a PR to ready
|
|
@@ -34,6 +34,7 @@ Skills install to `~/.claude/skills/<skill-name>/` via `packages/claude-dev-env/
|
|
|
34
34
|
- `copilot-review` — requests and polls a GitHub Copilot review
|
|
35
35
|
- `copilot-finding-triage` — tiers each Copilot gate finding, verifies each code concern with an executed check, then routes it (auto-fix a confirmed defect, resolve a refuted one, page the user only for an inconclusive one)
|
|
36
36
|
- `reviewer-gates` — availability gates for external reviewers (opt-out parse, Copilot quota, Bugbot trigger/detect)
|
|
37
|
+
- `pr-fix-protocol` — applies reviewer findings as verified fixes and drives unresolved review threads to zero
|
|
37
38
|
- `pr-loop-lifecycle` — opens and closes a PR-loop run (grant, teardown, PR description, revoke, report)
|
|
38
39
|
- `pr-loop-cloud-transport` — six-step transport workflow that lets any PR-loop skill run in a session whose `gh` CLI is absent or cannot act on the PR (MCP schema load, origin/HEAD fix, identity rules, the gh-to-MCP substitution matrix, the Copilot status rule, and the post self-check)
|
|
39
40
|
|
|
@@ -1722,7 +1722,7 @@ function runAuditLens(head, preflightResult) {
|
|
|
1722
1722
|
* Self-review lens: the semantic pre-catch parity pass over the full diff. It
|
|
1723
1723
|
* covers the doc-vs-code parity, test-assertion completeness, and
|
|
1724
1724
|
* PR-description-vs-diff lanes that sit outside the A-P bug categories, reusing
|
|
1725
|
-
* the pr-consistency-audit
|
|
1725
|
+
* the pr-consistency-audit prompt's canonical-source cross-reference method. It
|
|
1726
1726
|
* stays on opus because line-citation accuracy, symbol attribution, and
|
|
1727
1727
|
* inventory or count claims are semantic judgments a cheaper tier misreads. It
|
|
1728
1728
|
* reports findings without editing.
|
|
@@ -1735,7 +1735,7 @@ function runSelfReviewLens(head, preflightResult) {
|
|
|
1735
1735
|
`You are the self-review parity lens for ${prCoordinates}, HEAD ${head}. Review the FULL origin/main...HEAD diff — every file the PR touches. Do NOT edit, commit, or push.\n\n` +
|
|
1736
1736
|
renderLensDiffContext(preflightResult) +
|
|
1737
1737
|
`Read the pre-catch rubric at ${CONFIG.precatchRubric} for the three lane checklists, and cover each lane:\n` +
|
|
1738
|
-
`1. Doc-vs-code parity: reuse the pr-consistency-audit
|
|
1738
|
+
`1. Doc-vs-code parity: reuse the pr-consistency-audit prompt's canonical-source cross-reference method ($HOME/.claude/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml) and the drift rubric at $HOME/.claude/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md. Verify every line citation resolves, every referenced file or script path exists, every symbol is attributed to the file that defines it, and every inventory, count, and ordering claim matches the code.\n` +
|
|
1739
1739
|
`2. Test-assertion completeness: every changed or new production path has a paired test that calls it and asserts on its behavior, and a changed test pins behavior rather than hiding it behind a mock.\n` +
|
|
1740
1740
|
`3. PR-description-vs-diff two-way parity: fetch the PR body read-only, then confirm every PR-body claim maps to a hunk in the diff and every hunk maps to a claim; flag invented paths, invented counts, and out-of-scope changes.\n\n` +
|
|
1741
1741
|
`Before returning clean, state one proof-of-absence line per lane naming what you checked. Return strictly the schema: clean=true with empty findings when all three lanes pass, otherwise one entry per finding (severity P0/P1/P2; category 'code-standard' for a pure doc or style parity gap with no behavioral impact, 'bug' otherwise; replyToCommentId=null). Set sha=${'`'}${head}${'`'}, down=false.`,
|
|
@@ -22,8 +22,7 @@ The `pre-push-review` skill was retired. Its mechanical checks are now covered a
|
|
|
22
22
|
|
|
23
23
|
- **`/qbug`** — a full PR audit-fix cycle that spawns subagents, runs multiple audit loops, and produces a structured report. It is NOT a lightweight pre-push gate. Do not use `/qbug` as a substitute for `git push` (the hook fires automatically). Use `/qbug` when you want a thorough multi-loop review of a PR before requesting human review.
|
|
24
24
|
|
|
25
|
-
References
|
|
26
|
-
- `
|
|
27
|
-
- `commands/plan.md` — Phase 5 step 10 updated to reference the git pre-push hook
|
|
25
|
+
References:
|
|
26
|
+
- `hooks/git-hooks/pre_push.py` — the git pre-push hook that runs the CODE_RULES gate over the commits about to be pushed
|
|
28
27
|
- `hooks/github-action/pre-push-review.yml` — deleted (workflow no longer needed)
|
|
29
28
|
- `hooks/github-action/test_workflow.py` — deleted alongside the workflow
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: closeout
|
|
3
|
+
description: >-
|
|
4
|
+
Harvests session obstacles into GitHub issues backed by quoted evidence at
|
|
5
|
+
session end, validates each draft with the user, dedupes against open and
|
|
6
|
+
closed issues, routes each to its repo, files children then a parent
|
|
7
|
+
checklist, and prints a computed cloud handoff prompt. Triggers: /closeout,
|
|
8
|
+
close out this session, close out the session, file the session obstacles,
|
|
9
|
+
session closeout, harvest session obstacles, end-of-session issue filing.
|
|
10
|
+
Near-miss: not session-log, which journals the session to the vault; closeout
|
|
11
|
+
files GitHub issues and prints a handoff prompt, and writes no session
|
|
12
|
+
journal.
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Closeout
|
|
16
|
+
|
|
17
|
+
**Core principle:** At the end of a working session, turn the obstacles the session hit into user-approved GitHub issues — each backed by a quoted line — plus a computed cloud handoff prompt, never guessing, never filing without approval, never touching the host repo's live pipeline.
|
|
18
|
+
|
|
19
|
+
## Gotchas
|
|
20
|
+
|
|
21
|
+
Highest-signal content. Append a bullet each time a run fails in a new way.
|
|
22
|
+
|
|
23
|
+
- An obstacle stated from memory drifts. File only what the session can quote word for word — the actual error text, the exact command, the exact log line. A candidate that cannot be quoted goes under "Unverified candidates" for the user to judge, never into a filed issue as fact.
|
|
24
|
+
- Skipping the confirmation gate files noise to a shared server that other people read. Every parent and child draft passes the AskUserQuestion gate before any write.
|
|
25
|
+
- A body that leans on chat context reads as a puzzle to anyone who opens the issue cold. Write each body so a reader with zero session context acts on it: name the failure, the count, and the quoted line.
|
|
26
|
+
- A `--body` string mangles backticks on GitHub — they land as literal `\``. Every `gh` create and comment uses `--body-file <path>`.
|
|
27
|
+
- A dedupe search that skips closed issues re-files a twin the team already resolved. The search covers `--state all`.
|
|
28
|
+
- A volatile path in an issue body breaks the moment the job scratch is cleaned. Keep temp dirs, worktrees, and `$CLAUDE_JOB_DIR` out of every body.
|
|
29
|
+
|
|
30
|
+
## When this skill applies
|
|
31
|
+
|
|
32
|
+
Run this skill **at the end** of a working session, from inside that same session, when the session hit obstacles worth filing — hook blocks, gates that fired wrongly, tools that failed, forced workarounds, dead ends.
|
|
33
|
+
|
|
34
|
+
Triggers: `/closeout`, "close out this session", "file the session obstacles", "session closeout", "harvest session obstacles", "end-of-session issue filing".
|
|
35
|
+
|
|
36
|
+
**Refusal cases — first match wins:**
|
|
37
|
+
|
|
38
|
+
- **Mid-session, work still open.** Respond: `Closeout runs at session end. Keep working, and run /closeout once the session's work is done.`
|
|
39
|
+
- **Asked to journal the session.** Respond: `Closeout files GitHub issues; it does not write a session journal. For a session report to the vault, use /session-log.`
|
|
40
|
+
- **No obstacles this session.** Respond: `No obstacles to file — the session hit no hook blocks, tool failures, or dead ends worth an issue. Nothing to close out.`
|
|
41
|
+
|
|
42
|
+
## The process
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
- [ ] Phase 1 — Harvest obstacles from the three sources; quote verbatim evidence
|
|
46
|
+
- [ ] Phase 1 — Run the PII pass over every candidate
|
|
47
|
+
- [ ] Phase 2 — Draft the parent + children set
|
|
48
|
+
- [ ] Phase 2 — Confirmation gate: AskUserQuestion, file only on approval
|
|
49
|
+
- [ ] Phase 3 — Dedupe each candidate against open and closed issues
|
|
50
|
+
- [ ] Phase 4 — Route each issue to its repo
|
|
51
|
+
- [ ] Phase 5 — File children, then the parent checklist
|
|
52
|
+
- [ ] Phase 6 — Print the computed cloud handoff prompt in chat
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Track the phases on the task list
|
|
56
|
+
|
|
57
|
+
At invocation, copy the six phases onto the session task list — one task each via TaskCreate: harvest, draft + user validation, dedupe, repo routing, filing, handoff prompt. Mark a task `in_progress` with TaskUpdate when its phase starts and `completed` when the phase finishes.
|
|
58
|
+
|
|
59
|
+
Hold one line on the filing task: never mark it `completed` while any planned issue is still uncreated. A filing phase that lands fewer issues than the approved set keeps the filing task open, with the missing issues named on it.
|
|
60
|
+
|
|
61
|
+
### Phase 1 — Harvest obstacles
|
|
62
|
+
|
|
63
|
+
Read three sources, in order:
|
|
64
|
+
|
|
65
|
+
1. **This session's conversation** — the chat log visible in context.
|
|
66
|
+
2. **The session task list** — TaskCreate/TaskUpdate records read through TaskList and TaskGet.
|
|
67
|
+
3. **Tool results still in the context window** — hook denials, command output, log tails.
|
|
68
|
+
|
|
69
|
+
An obstacle is a hook block, a gate that fired wrongly, a tool that failed, a forced workaround, or a dead end.
|
|
70
|
+
|
|
71
|
+
**Non-negotiable evidence rule:** every filed issue quotes verbatim evidence captured this session — the actual error text, the exact command, the exact log line. An obstacle you cannot quote is dropped, or listed under a "Unverified candidates" section of the drafts for the user to decide. It is never filed as fact.
|
|
72
|
+
|
|
73
|
+
**PII pass (runs on every run):** strip personal data from every issue body and from the handoff prompt — emails, real names, home paths, private hosts and IPs, account ids, tokens. The pass runs whether the target repo is public or private; repository visibility changes only how aggressive the redaction is (public repos get the strictest pass), never whether the pass runs. Checklist and swaps: [reference/pii-redaction-checklist.md](reference/pii-redaction-checklist.md).
|
|
74
|
+
|
|
75
|
+
### Phase 2 — Draft and validate with the user
|
|
76
|
+
|
|
77
|
+
Build the parent → children issue set as drafts. Body shapes and worked examples: [reference/issue-body-templates.md](reference/issue-body-templates.md).
|
|
78
|
+
|
|
79
|
+
Then the **mandatory confirmation gate**. Present through AskUserQuestion:
|
|
80
|
+
|
|
81
|
+
- Each drafted parent and child — title, target repo, one line of scope each.
|
|
82
|
+
- Any PII concern the pass found.
|
|
83
|
+
- Any closed twin a dedupe search surfaced (see Phase 3), as a reopen/comment/file-new choice.
|
|
84
|
+
|
|
85
|
+
Filing to GitHub is an irreversible write to a shared server that other people read. File only on explicit user approval. The user validates every finding before anything is posted.
|
|
86
|
+
|
|
87
|
+
### Phase 3 — Dedupe
|
|
88
|
+
|
|
89
|
+
Before filing each candidate, search open and closed issues on the target repo:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
gh issue list --search "<terms>" --state all
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- **Open twin exists** → comment on it, rather than filing a new issue.
|
|
96
|
+
- **Closed twin exists** → do not silently file or comment. Surface it in the Phase 2 gate as "previously closed twin — reopen, comment, or file new" for the user to decide.
|
|
97
|
+
|
|
98
|
+
`gh issue list` needs no pagination flags. If you show a `gh api` read of a paginated list endpoint anywhere, show `--paginate --slurp` piped to external `jq` — `gh`'s built-in `--jq` runs per page and gives wrong cross-page results.
|
|
99
|
+
|
|
100
|
+
### Phase 4 — Repo routing
|
|
101
|
+
|
|
102
|
+
Route each issue by a deterministic rule:
|
|
103
|
+
|
|
104
|
+
- The evidence names a file under the dev-env tree — `packages/claude-dev-env/hooks/`, `rules/`, `skills/`, `commands/`, `agents/`, `bin/`, or `docs/` — or an installed copy of those under `~/.claude/` (hooks, rules, skills, commands, agents) → file against **claude-dev-env**.
|
|
105
|
+
- Otherwise → the **working repo**, read live:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
gh repo view --json nameWithOwner
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **Cross-repo case** — a hook shipped by repo B blocked work in repo A → file against **B** and reference A in the body.
|
|
112
|
+
|
|
113
|
+
### Phase 5 — File
|
|
114
|
+
|
|
115
|
+
File **children first**, then the parent. The parent body is a checklist of `- [ ] owner/repo#N` lines, one per child created.
|
|
116
|
+
|
|
117
|
+
- Every `gh issue create` and `gh issue comment` uses `--body-file <path>`, never `--body`.
|
|
118
|
+
- No volatile paths in any body: no temp dirs, no worktrees, no `$CLAUDE_JOB_DIR`, no `.claude-editor/jobs` or `.claude/worktrees` paths.
|
|
119
|
+
- Bodies are self-contained and specific: the failure mode, the count, and the quoted line — not "improve error handling".
|
|
120
|
+
|
|
121
|
+
### Phase 6 — Computed handoff prompt
|
|
122
|
+
|
|
123
|
+
Print **in chat** (not a file) a prompt the user pastes into a cloud session that opens PRs for the filed issues and drives them to convergence. Template and worked example: [reference/handoff-prompt-template.md](reference/handoff-prompt-template.md).
|
|
124
|
+
|
|
125
|
+
The prompt is computed, not a bare list. It carries:
|
|
126
|
+
|
|
127
|
+
1. **Safety boundaries** — what must never be run, merged, deployed, or synced. The working repo's pipeline is live in production.
|
|
128
|
+
2. **Base branch and verification commands** — read the base branch and the per-package verification commands from the target repo's CLAUDE.md and docs at runtime.
|
|
129
|
+
3. **Dependency order** — which issue must land before which, and which issues touch the same files and so must stack on one branch rather than run in parallel.
|
|
130
|
+
|
|
131
|
+
If any issue cannot be done from a cloud session — it needs a local environment, physical devices, or a private network — the prompt says so per issue and scopes the cloud work to what a cloud session can reach.
|
|
132
|
+
|
|
133
|
+
## Skill boundaries
|
|
134
|
+
|
|
135
|
+
This skill runs inside a repo whose pipeline is live in production. Hold these lines:
|
|
136
|
+
|
|
137
|
+
- It never runs that pipeline, never merges, never deploys, never syncs.
|
|
138
|
+
- It never runs the host repo's automations.
|
|
139
|
+
- It creates issues and comments and prints text. Nothing else.
|
|
140
|
+
|
|
141
|
+
## File index
|
|
142
|
+
|
|
143
|
+
| File | Purpose |
|
|
144
|
+
|------|---------|
|
|
145
|
+
| `SKILL.md` | This hub — core principle, gotchas, refusal cases, six-phase process, boundaries |
|
|
146
|
+
| `reference/issue-body-templates.md` | Parent and child issue body shapes with worked examples |
|
|
147
|
+
| `reference/pii-redaction-checklist.md` | The PII pass: categories, swaps, public-versus-private aggression |
|
|
148
|
+
| `reference/handoff-prompt-template.md` | The computed cloud handoff prompt shape with a worked example |
|
|
149
|
+
|
|
150
|
+
## Folder map
|
|
151
|
+
|
|
152
|
+
- `SKILL.md` — hub: principle, gotchas, refusal, six-phase process, boundaries.
|
|
153
|
+
- `reference/` — issue body templates, PII redaction checklist, handoff prompt template.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Handoff prompt template
|
|
2
|
+
|
|
3
|
+
The closing session prints this prompt in chat. The user pastes it into a cloud session that opens PRs for the filed issues and drives them to convergence. The prompt is computed from the filed set — the safety lines, base branch, verification commands, and dependency order are read at runtime, not guessed.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Shape](#shape)
|
|
8
|
+
- [How to compute each block](#how-to-compute-each-block)
|
|
9
|
+
- [Worked example](#worked-example)
|
|
10
|
+
|
|
11
|
+
## Shape
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
# Cloud handoff — <parent issue owner/repo#N>
|
|
15
|
+
|
|
16
|
+
## Task
|
|
17
|
+
Open a PR per filed issue below and drive each to convergence.
|
|
18
|
+
|
|
19
|
+
## Safety — never do these
|
|
20
|
+
- Never run, merge, deploy, or sync the <working repo> pipeline. It is live in production.
|
|
21
|
+
- Never run the host repo's automations.
|
|
22
|
+
- <any repo-specific never line read from the target CLAUDE.md>
|
|
23
|
+
|
|
24
|
+
## Base branch and verification
|
|
25
|
+
- Base branch: <base>
|
|
26
|
+
- Per-package verification commands:
|
|
27
|
+
- <package A>: <command>
|
|
28
|
+
- <package B>: <command>
|
|
29
|
+
|
|
30
|
+
## Issues, in dependency order
|
|
31
|
+
1. owner/repo#<N> — <title>. <cloud-doable? yes / no + why>.
|
|
32
|
+
2. owner/repo#<N> — <title>. Depends on #<N> landing first.
|
|
33
|
+
3. owner/repo#<N> — <title>. Touches the same files as #<N>; stack on one branch, do not run in parallel.
|
|
34
|
+
|
|
35
|
+
## Cannot be done from a cloud session
|
|
36
|
+
- owner/repo#<N> — needs <local environment / physical device / private network>. Scope the cloud work to <what a cloud session can reach>.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## How to compute each block
|
|
40
|
+
|
|
41
|
+
- **Safety lines** — read the working repo's CLAUDE.md and docs for the pipeline, deploy, and sync commands the cloud session must never run. Name each one.
|
|
42
|
+
- **Base branch** — read it live from the target repo (its default branch), not from memory.
|
|
43
|
+
- **Verification commands** — read the per-package test and check commands from the target repo's CLAUDE.md or docs. List one line per package a filed issue touches.
|
|
44
|
+
- **Dependency order** — for each pair of issues, decide: does one need the other's change to land first? Do they touch the same files? Same-file issues stack on one branch; independent issues run in parallel.
|
|
45
|
+
- **Cloud reachability** — for each issue, decide whether a cloud session can do the work. An issue needing a local environment, physical devices, or a private network is marked, and the cloud work is scoped to the reachable part.
|
|
46
|
+
|
|
47
|
+
## Worked example
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
# Cloud handoff — jl-cmd/claude-dev-env#100
|
|
51
|
+
|
|
52
|
+
## Task
|
|
53
|
+
Open a PR per filed issue below and drive each to convergence.
|
|
54
|
+
|
|
55
|
+
## Safety — never do these
|
|
56
|
+
- Never run, merge, deploy, or sync the claude-dev-env publish pipeline. It is live in production (publishes to npm).
|
|
57
|
+
- Never run the host repo's automations.
|
|
58
|
+
- Never hand-edit .cursor/BUGBOT.md; it is generated from AGENTS.md.
|
|
59
|
+
|
|
60
|
+
## Base branch and verification
|
|
61
|
+
- Base branch: main
|
|
62
|
+
- Per-package verification commands:
|
|
63
|
+
- claude-dev-env (JS): cd packages/claude-dev-env && npm test
|
|
64
|
+
- claude-dev-env (Python): python -m pytest packages/claude-dev-env
|
|
65
|
+
|
|
66
|
+
## Issues, in dependency order
|
|
67
|
+
1. jl-cmd/claude-dev-env#101 — inline-collection gate fires in exempt test files. Cloud-doable: yes.
|
|
68
|
+
2. jl-cmd/claude-dev-env#102 — boolean-naming gate flags a fixture variable. Touches the same file as #101 (code_rules_enforcer.py); stack on one branch with #101, do not run in parallel.
|
|
69
|
+
|
|
70
|
+
## Cannot be done from a cloud session
|
|
71
|
+
- None. Both issues are pure hook-logic changes with local pytest coverage a cloud session can run.
|
|
72
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Issue body templates
|
|
2
|
+
|
|
3
|
+
Body shapes for the parent tracking issue and its child issues, plus a worked example. Every body is self-contained: a reader with zero session context understands it. Every body carries a quoted line of evidence captured this session. Write each body to a temp file and pass it with `gh issue create --body-file <path>`.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Child issue body](#child-issue-body)
|
|
8
|
+
- [Parent tracking issue body](#parent-tracking-issue-body)
|
|
9
|
+
- [Worked example — child](#worked-example--child)
|
|
10
|
+
- [Worked example — parent](#worked-example--parent)
|
|
11
|
+
- [Body rules](#body-rules)
|
|
12
|
+
|
|
13
|
+
## Child issue body
|
|
14
|
+
|
|
15
|
+
One obstacle per child. Fill every section:
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
## What happened
|
|
19
|
+
|
|
20
|
+
<One sentence: the failure mode, in plain terms.>
|
|
21
|
+
|
|
22
|
+
## Evidence
|
|
23
|
+
|
|
24
|
+
<The verbatim line captured this session — error text, command, or log line — in a fenced block.>
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
<exact quoted text>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Where
|
|
31
|
+
|
|
32
|
+
<The file, hook, gate, or tool the evidence names. Path relative to the repo root.>
|
|
33
|
+
|
|
34
|
+
## Impact
|
|
35
|
+
|
|
36
|
+
<What the obstacle cost: work blocked, count of times hit, workaround forced.>
|
|
37
|
+
|
|
38
|
+
## Proposed fix
|
|
39
|
+
|
|
40
|
+
<The specific change. Name the failure mode and the condition, not "improve error handling".>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Parent tracking issue body
|
|
44
|
+
|
|
45
|
+
The parent gathers the children. Its body is a checklist, one line per child created:
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
## Session closeout — <short session label>
|
|
49
|
+
|
|
50
|
+
Obstacles this session, filed as child issues:
|
|
51
|
+
|
|
52
|
+
- [ ] owner/repo#<N> — <child title>
|
|
53
|
+
- [ ] owner/repo#<N> — <child title>
|
|
54
|
+
- [ ] owner/repo#<N> — <child title>
|
|
55
|
+
|
|
56
|
+
## Handoff
|
|
57
|
+
|
|
58
|
+
A cloud handoff prompt for these issues was printed in the closing session. It carries the safety boundaries, base branch, per-package verification commands, and the dependency order among the children.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Worked example — child
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
## What happened
|
|
65
|
+
|
|
66
|
+
The code_rules_enforcer hook blocked a valid list literal in a test file, where test files are exempt from the magic-value gate.
|
|
67
|
+
|
|
68
|
+
## Evidence
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
BLOCKED: [MAGIC_VALUE] Inline list literal [200, 404, 500] in a function body -- extract to a named constant in config/.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Where
|
|
75
|
+
|
|
76
|
+
packages/claude-dev-env/hooks/blocking/code_rules_enforcer.py — the inline-collection check.
|
|
77
|
+
|
|
78
|
+
## Impact
|
|
79
|
+
|
|
80
|
+
Hit 3 times in one session on three test files. Forced a workaround: moving each literal to a module constant the test did not need.
|
|
81
|
+
|
|
82
|
+
## Proposed fix
|
|
83
|
+
|
|
84
|
+
Extend the test-file exemption that already covers the magic-value gate to also cover the inline-collection check, so list and set literals in test bodies pass.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Worked example — parent
|
|
88
|
+
|
|
89
|
+
```markdown
|
|
90
|
+
## Session closeout — hook exemptions for test files
|
|
91
|
+
|
|
92
|
+
Obstacles this session, filed as child issues:
|
|
93
|
+
|
|
94
|
+
- [ ] jl-cmd/claude-dev-env#101 — inline-collection gate fires in exempt test files
|
|
95
|
+
- [ ] jl-cmd/claude-dev-env#102 — boolean-naming gate flags a fixture variable
|
|
96
|
+
|
|
97
|
+
## Handoff
|
|
98
|
+
|
|
99
|
+
A cloud handoff prompt for these issues was printed in the closing session. It carries the safety boundaries, base branch, per-package verification commands, and the dependency order among the children.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Body rules
|
|
103
|
+
|
|
104
|
+
- **Quoted evidence is required.** No child ships without a fenced block holding a line captured this session.
|
|
105
|
+
- **No volatile paths.** No temp dirs, worktrees, `$CLAUDE_JOB_DIR`, `.claude-editor/jobs`, or `.claude/worktrees` paths in any body. Paste text inline; for a binary artifact, upload it to a durable release and link that URL.
|
|
106
|
+
- **No chat references.** Drop "as discussed" and "the choice we picked". State each fact on its own.
|
|
107
|
+
- **Specific over vague.** "The gate fires on `[200, 404, 500]` in a test body" beats "the gate is too strict".
|
|
108
|
+
- **PII stripped.** Run the PII pass (see the PII redaction checklist) over every body before it reaches the confirmation gate.
|