claude-dev-env 2.18.0 → 2.20.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.
Files changed (133) hide show
  1. package/.agents/skills/AGENTS.md +4 -4
  2. package/.agents/skills/_shared/AGENTS.md +1 -0
  3. package/.agents/skills/_shared/pr-loop/AGENTS.md +1 -0
  4. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +119 -0
  5. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +5 -0
  6. package/.agents/skills/e-code-review/SKILL.md +12 -1
  7. package/.agents/skills/e-code-review/reference/fix.md +5 -1
  8. package/.agents/skills/e-code-review/reference/loop.md +4 -0
  9. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +66 -0
  10. package/.agents/skills/e-code-review/reference/preflight-proposal.md +40 -0
  11. package/.agents/skills/e-code-review/reference/runner-selection.md +1 -0
  12. package/.agents/skills/pr-cleanup/SKILL.md +105 -75
  13. package/.agents/skills/pr-cleanup/reference/process-inventory.md +15 -0
  14. package/.agents/skills/pr-cleanup/reference/task-seeds.md +20 -0
  15. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/SKILL.md +18 -12
  16. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/offense-examples.md +1 -1
  17. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/task-seeds.md +3 -2
  18. package/.agents/skills/pr-refinement/SKILL.md +31 -0
  19. package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/SKILL.md +24 -7
  20. package/.agents/skills/{small-cl → pr-small-cl}/SKILL.md +1 -1
  21. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +33 -5
  22. package/.agents/skills/skill-builder/SKILL.md +1 -0
  23. package/.agents/skills-archived/bugteam/SKILL.md +1 -1
  24. package/.agents/skills-archived/bugteam/test_skill_additions.py +1 -1
  25. package/.agents/skills-archived/comments/SKILL.md +1 -1
  26. package/.agents/skills-archived/descriptions/SKILL.md +1 -1
  27. package/.agents/skills-archived/reviews/SKILL.md +1 -1
  28. package/AGENTS.md +1 -1
  29. package/_shared/pr-loop/AGENTS.md +2 -1
  30. package/_shared/pr-loop/preflight-proposal.md +56 -0
  31. package/_shared/pr-loop/scripts/code_rules_gate.py +29 -6
  32. package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_arguments.py +15 -3
  33. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +47 -4
  34. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +4 -0
  35. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +47 -0
  36. package/bin/ever-shipped-skills.mjs +14 -0
  37. package/bin/install-constants.mjs +5 -0
  38. package/bin/install.agents-home.test.mjs +23 -0
  39. package/bin/install.codex-rules.test.mjs +61 -6
  40. package/bin/install.mjs +57 -9
  41. package/bin/install.prune.test.mjs +65 -3
  42. package/bin/install.test.mjs +202 -2
  43. package/docs/CODE_RULES.md +6 -0
  44. package/hooks/advisory/conftest.py +10 -0
  45. package/hooks/advisory/migration_safety_advisor.py +14 -14
  46. package/hooks/advisory/refactor_guard.py +250 -144
  47. package/hooks/advisory/refactor_guard_test_support.py +46 -0
  48. package/hooks/advisory/test_migration_safety_advisor.py +120 -0
  49. package/hooks/advisory/test_refactor_guard_advisory.py +171 -0
  50. package/hooks/advisory/test_refactor_guard_eligibility.py +166 -0
  51. package/hooks/atomic_file_writer.py +81 -0
  52. package/hooks/blocking/AGENTS.md +2 -1
  53. package/hooks/blocking/block_main_commit.py +66 -33
  54. package/hooks/blocking/code_rules_banned_identifiers.py +55 -4
  55. package/hooks/blocking/code_rules_blast_radius.py +194 -0
  56. package/hooks/blocking/code_rules_enforcer.py +12 -0
  57. package/hooks/blocking/code_rules_enforcer_test_support.py +92 -0
  58. package/hooks/blocking/destructive_command_blocker.py +8 -7
  59. package/hooks/blocking/pre_tool_use_dispatcher.py +11 -7
  60. package/hooks/blocking/precommit_code_rules_gate.py +14 -139
  61. package/hooks/blocking/sensitive_file_protector.py +8 -6
  62. package/hooks/blocking/session_edit_stage_gate.py +31 -1
  63. package/hooks/blocking/test_block_main_commit.py +145 -0
  64. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +171 -1
  65. package/hooks/blocking/test_code_rules_blast_radius.py +161 -0
  66. package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +37 -12
  67. package/hooks/blocking/test_code_rules_enforcer_banned_noun_word.py +54 -0
  68. package/hooks/blocking/test_code_rules_enforcer_duplicate_body_hook_routing.py +15 -53
  69. package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +13 -62
  70. package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +309 -0
  71. package/hooks/blocking/test_code_rules_enforcer_precheck_forecast.py +14 -71
  72. package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +14 -16
  73. package/hooks/blocking/test_code_rules_enforcer_split_entry_2.py +31 -46
  74. package/hooks/blocking/test_code_rules_enforcer_stage.py +192 -0
  75. package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +13 -59
  76. package/hooks/blocking/test_destructive_command_blocker.py +154 -138
  77. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +85 -25
  78. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +58 -38
  79. package/hooks/blocking/test_destructive_command_blocker_patterns.py +133 -0
  80. package/hooks/blocking/test_docstring_rule_gate_count_blocker.py +113 -1
  81. package/hooks/blocking/test_env_var_table_code_drift_blocker.py +70 -3
  82. package/hooks/blocking/test_hook_subprocess_support.py +296 -0
  83. package/hooks/blocking/test_package_inventory_stale_blocker.py +1 -1
  84. package/hooks/blocking/test_pii_scanner.py +81 -0
  85. package/hooks/blocking/test_pre_tool_use_dispatcher.py +32 -3
  86. package/hooks/blocking/test_precommit_code_rules_gate.py +11 -16
  87. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +234 -0
  88. package/hooks/blocking/test_pytest_testpaths_orphan_blocker.py +25 -18
  89. package/hooks/blocking/test_sensitive_file_protector.py +145 -5
  90. package/hooks/blocking/test_session_edit_stage_gate_staging.py +64 -0
  91. package/hooks/blocking/test_session_edit_stage_gate_support.py +204 -0
  92. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +116 -0
  93. package/hooks/blocking/test_shared_stdin_adoption.py +31 -20
  94. package/hooks/blocking/test_test_preflight_check.py +80 -0
  95. package/hooks/git-hooks/AGENTS.md +1 -1
  96. package/hooks/git-hooks/git_hooks_constants/__init__.py +1 -0
  97. package/hooks/git-hooks/post_commit.py +160 -51
  98. package/hooks/git-hooks/pre_commit.py +9 -5
  99. package/hooks/git-hooks/test_post_commit.py +203 -0
  100. package/hooks/git-hooks/test_pre_commit.py +2 -2
  101. package/hooks/git-hooks/test_pre_push.py +57 -0
  102. package/hooks/hooks_constants/AGENTS.md +3 -1
  103. package/hooks/hooks_constants/atomic_file_writer_constants.py +4 -0
  104. package/hooks/hooks_constants/banned_identifiers_constants.py +1 -0
  105. package/hooks/hooks_constants/blast_radius_constants.py +14 -0
  106. package/hooks/hooks_constants/destructive_command_environment_constants.py +18 -0
  107. package/hooks/hooks_constants/destructive_command_segment_constants.py +1 -11
  108. package/hooks/hooks_constants/hardcoded_user_path_constants.py +9 -3
  109. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +1 -1
  110. package/hooks/hooks_constants/refactor_guard_constants.py +75 -0
  111. package/hooks/hooks_constants/sensitive_file_protector_constants.py +2 -4
  112. package/hooks/hooks_constants/test_refactor_guard_constants.py +21 -0
  113. package/hooks/json_file_reader.py +22 -0
  114. package/hooks/observability/test_instructions_loaded_logger.py +54 -0
  115. package/hooks/pending_sidecars.py +33 -0
  116. package/hooks/session/test_plugin_data_dir_cleanup.py +70 -0
  117. package/hooks/session/test_session_edit_tracker_cleanup.py +16 -3
  118. package/hooks/test_atomic_file_writer.py +73 -0
  119. package/hooks/test_json_file_reader.py +24 -0
  120. package/hooks/test_pending_sidecars.py +25 -0
  121. package/hooks/validation/mypy_validator.py +213 -80
  122. package/hooks/validation/test_mypy_validator.py +288 -13
  123. package/hooks/workflow/auto_formatter.py +225 -93
  124. package/hooks/workflow/investigation_tracker_reset.py +2 -0
  125. package/hooks/workflow/test_auto_formatter.py +261 -12
  126. package/hooks/workflow/test_investigation_tracker_reset.py +90 -0
  127. package/package.json +1 -1
  128. package/rules/failure-blast-radius.md +126 -0
  129. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/fetch-commands.md +0 -0
  130. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/report-template.md +0 -0
  131. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/rule-checklist.md +0 -0
  132. /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/examples.md +0 -0
  133. /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/offense-taxonomy.md +0 -0
@@ -35,15 +35,15 @@ contracts, runtime scripts). Map: `skills/_shared/.claude/CLAUDE.md`. End-of-run
35
35
 
36
36
  **PR review and convergence**
37
37
 
38
- - `shared-extraction-audit` — audits workflow packages for helpers that belong in shared libraries; extracts in small tested CLs
39
- - `name-by-capability-audit` — audits PR paths/titles for driver/motive words on reusable capability code
38
+ - `pr-shared-extraction` — audits workflow packages for helpers that belong in shared libraries; extracts in small tested CLs
39
+ - `pr-name-by-capability` — audits PR paths/titles for driver/motive words on reusable capability code
40
40
  - `review-tier` — classifies `review_tier_constants` from change axes, hard triggers, and user overrides
41
41
  - `review-router` — resolves and arms one supported `route_review_config` route through the registered Agent|Task gate
42
- - `pr-cleanup` — one-agent end-to-end PR cleanup: extraction → naming → sr-loop → small-cl; apply and validate fixes as they return
42
+ - `pr-cleanup` — one-agent end-to-end PR cleanup: extraction → naming → sr-loop → pr-small-cl; apply and validate fixes as they return
43
43
  - `autoconverge` — autonomous single-run workflow that drives a PR to ready
44
44
  - `e-code-review` — max-recall code review at a selectable effort level
45
45
  - `e-simplify` — cleanup-only pass on the current diff
46
- - `small-cl` — the Small CLs guide for scope and split decisions
46
+ - `pr-small-cl` — the Small CLs guide for scope and split decisions
47
47
 
48
48
  **Research and discovery**
49
49
  - `everything-search` — file-system search via the Everything `es.exe` CLI on Windows
@@ -37,6 +37,7 @@
37
37
  | `pr-loop/gh-payloads.md` | `@~/.claude/_shared/pr-loop/gh-payloads.md` |
38
38
  | `pr-loop/post-audit-thread-contract.md` | `@~/.claude/_shared/pr-loop/post-audit-thread-contract.md` |
39
39
  | `pr-loop/precatch-rubric.md` | `@~/.claude/_shared/pr-loop/precatch-rubric.md` |
40
+ | `pr-loop/preflight-proposal.md` | `@~/.claude/_shared/pr-loop/preflight-proposal.md` |
40
41
  | `pr-loop/state-schema.md` | `@~/.claude/_shared/pr-loop/state-schema.md` |
41
42
  | `pr-loop/worker-spawn.md` | `@~/.claude/_shared/pr-loop/worker-spawn.md` |
42
43
  | `pr-loop/scripts/RUNTIME_SCRIPTS.md` | `@~/.claude/_shared/pr-loop/scripts/` |
@@ -26,6 +26,7 @@ Open a stub, then load the `@` target:
26
26
  | `gh-payloads.md` | `@~/.claude/_shared/pr-loop/gh-payloads.md` |
27
27
  | `post-audit-thread-contract.md` | `@~/.claude/_shared/pr-loop/post-audit-thread-contract.md` |
28
28
  | `precatch-rubric.md` | `@~/.claude/_shared/pr-loop/precatch-rubric.md` |
29
+ | `preflight-proposal.md` | `@~/.claude/_shared/pr-loop/preflight-proposal.md` |
29
30
  | `state-schema.md` | `@~/.claude/_shared/pr-loop/state-schema.md` |
30
31
  | `worker-spawn.md` | `@~/.claude/_shared/pr-loop/worker-spawn.md` |
31
32
  | `scripts/RUNTIME_SCRIPTS.md` | `@~/.claude/_shared/pr-loop/scripts/` |
@@ -0,0 +1,119 @@
1
+ import assert from 'node:assert/strict'
2
+ import { readFileSync } from 'node:fs'
3
+ import { dirname, resolve } from 'node:path'
4
+ import test from 'node:test'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const THIS_DIRECTORY = dirname(fileURLToPath(import.meta.url))
8
+ const canonicalContractSource = readFileSync(
9
+ resolve(THIS_DIRECTORY, '../../../../_shared/pr-loop/preflight-proposal.md'),
10
+ 'utf8',
11
+ )
12
+ const sharedSkillSource = readFileSync(
13
+ resolve(THIS_DIRECTORY, '../../pr-shared-extraction/SKILL.md'),
14
+ 'utf8',
15
+ )
16
+ const capabilitySkillSource = readFileSync(
17
+ resolve(THIS_DIRECTORY, '../../pr-name-by-capability/SKILL.md'),
18
+ 'utf8',
19
+ )
20
+ const capabilityTaskSeedsSource = readFileSync(
21
+ resolve(THIS_DIRECTORY, '../../pr-name-by-capability/reference/task-seeds.md'),
22
+ 'utf8',
23
+ )
24
+ const reviewSkillSource = readFileSync(
25
+ resolve(THIS_DIRECTORY, '../../e-code-review/SKILL.md'),
26
+ 'utf8',
27
+ )
28
+ const reviewProposalSource = readFileSync(
29
+ resolve(THIS_DIRECTORY, '../../e-code-review/reference/preflight-proposal.md'),
30
+ 'utf8',
31
+ )
32
+
33
+ const allSkillContracts = [
34
+ {
35
+ name: 'shared extraction audit',
36
+ skillSource: sharedSkillSource,
37
+ invocationPattern: /pr-shared-extraction preflight-proposal/,
38
+ classificationPattern: /priority and target/,
39
+ expectedDefaultBehavior: 'applies the prioritized fix band by default',
40
+ },
41
+ {
42
+ name: 'name by capability audit',
43
+ skillSource: capabilitySkillSource,
44
+ invocationPattern: /pr-name-by-capability preflight-proposal/,
45
+ classificationPattern: /violation or OK-driver classification/,
46
+ expectedDefaultBehavior: 'applies the suggested rename direction by default',
47
+ },
48
+ ]
49
+
50
+ function assertProposalAdapter(skillContract) {
51
+ const preflightRoutingOffset = skillContract.skillSource.indexOf('`preflight-proposal`')
52
+ const reportOnlyRoutingOffset = skillContract.skillSource.indexOf('`audit-only`')
53
+
54
+ assert.ok(preflightRoutingOffset >= 0, `${skillContract.name} selects proposal mode`)
55
+ assert.ok(preflightRoutingOffset < reportOnlyRoutingOffset, `${skillContract.name} routes proposal mode first`)
56
+ assert.match(skillContract.skillSource, skillContract.invocationPattern)
57
+ assert.match(skillContract.skillSource, skillContract.classificationPattern)
58
+ assert.match(skillContract.skillSource, new RegExp(skillContract.expectedDefaultBehavior))
59
+ }
60
+
61
+ function assertTaskRoutingAndNormalMode() {
62
+ assert.match(sharedSkillSource, /Register this checklist with `update_plan`/)
63
+ assert.match(capabilitySkillSource, /Register every bullet from `reference\/task-seeds\.md` with `update_plan`/)
64
+ assert.match(capabilityTaskSeedsSource, /Register each item with `update_plan`/)
65
+ assert.doesNotMatch(sharedSkillSource, /TodoWrite|TaskCreate/)
66
+ assert.doesNotMatch(capabilitySkillSource, /TodoWrite|TaskCreate/)
67
+ assert.doesNotMatch(capabilityTaskSeedsSource, /TodoWrite|TaskCreate/)
68
+ assert.match(sharedSkillSource, /audit-only` is report-only/)
69
+ assert.match(capabilitySkillSource, /audit-only` is report-only/)
70
+ }
71
+
72
+ function assertSharedProposalContract(contractSource) {
73
+ assert.match(contractSource, /caller-supplied isolated worktree/)
74
+ assert.match(contractSource, /resolved PR number/)
75
+ assert.match(contractSource, /immutable base SHA/)
76
+ assert.match(contractSource, /immutable head SHA/)
77
+ assert.match(contractSource, /exact `base_sha\.\.\.head_sha` range/)
78
+ assert.match(contractSource, /require exact equality with the head SHA/)
79
+ assert.match(contractSource, /immutable proposal identity/)
80
+ assert.match(contractSource, /deterministic diff hash/)
81
+ assert.match(contractSource, /changed paths/)
82
+ assert.match(contractSource, /exact tests and outcomes/)
83
+ assert.match(contractSource, /selected-candidate-ready proposal evidence/)
84
+ assert.match(contractSource, /selected or dispositioned proposal collection/)
85
+ assert.match(contractSource, /Reapplication uses exactly the selected records/)
86
+ }
87
+
88
+ function assertReviewProposalAdapter() {
89
+ const preflightRoutingOffset = reviewSkillSource.indexOf('`preflight-proposal`')
90
+ const refusalRoutingOffset = reviewSkillSource.indexOf('**Refusal — first match wins:**')
91
+ const allProposalEntryMatches = reviewSkillSource.match(
92
+ /Route the selected mode through \[reference\/preflight-proposal.md\]\(reference\/preflight-proposal.md\) to establish proposal context/g,
93
+ ) ?? []
94
+
95
+ assert.ok(preflightRoutingOffset >= 0)
96
+ assert.ok(preflightRoutingOffset < refusalRoutingOffset)
97
+ assert.equal(allProposalEntryMatches.length, 1)
98
+ assert.match(reviewSkillSource, /e-code-review preflight-proposal/)
99
+ assert.match(reviewSkillSource, /`--level <low\|medium\|xhigh>`/)
100
+ assert.match(reviewSkillSource, /@~\/.claude\/_shared\/pr-loop\/preflight-proposal.md/)
101
+ assert.match(reviewSkillSource, /Normal mode follows the current level/)
102
+ assert.match(reviewProposalSource, /Keep Gate 1, Gate 2, the bare code-rules gate, and exact required tests/)
103
+ assert.match(reviewProposalSource, /review_level: low \| medium \| xhigh/)
104
+ assert.match(reviewProposalSource, /severity: blocker \| high \| medium \| low \| nit/)
105
+ assert.match(reviewProposalSource, /verdict: CONFIRMED \| PLAUSIBLE/)
106
+ assert.match(reviewProposalSource, /outcome: fixed \| no_change_needed \| skipped/)
107
+ }
108
+
109
+ test('audit modes retain their normal routing behavior', () => {
110
+ assertTaskRoutingAndNormalMode()
111
+ })
112
+
113
+ test('one shared contract defines proposal evidence for audit and review skills', () => {
114
+ for (const eachSkillContract of allSkillContracts) {
115
+ assertProposalAdapter(eachSkillContract)
116
+ }
117
+ assertReviewProposalAdapter()
118
+ assertSharedProposalContract(canonicalContractSource)
119
+ })
@@ -0,0 +1,5 @@
1
+ # Preflight proposal contract
2
+
3
+ **Canonical home:**
4
+
5
+ @~/.claude/_shared/pr-loop/preflight-proposal.md
@@ -4,13 +4,23 @@ description: >-
4
4
  Max-recall code review at a selectable effort level (low, medium, xhigh), with
5
5
  optional auto-fix and an auto-execute loop for any level. Triggers:
6
6
  /e-code-review, /e-code-review low, /e-code-review medium, /e-code-review
7
- xhigh, /e-code-review <level> --fix, /e-code-review <level> loop.
7
+ xhigh, /e-code-review <level> --fix, /e-code-review <level> loop,
8
+ /e-code-review preflight-proposal.
8
9
  ---
9
10
 
10
11
  # e-code-review
11
12
 
12
13
  **Pick a level, run that review, optionally fix and loop.** Each level has its own procedure file. Fix application lives in `reference/fix.md`; repeat-until-clean lives in `reference/loop.md`.
13
14
 
15
+ ## Mode routing
16
+
17
+ Resolve the first matching invocation before the normal refusal and loop rules:
18
+
19
+ 1. `preflight-proposal` requires `<pr_number>`, `--level <low|medium|xhigh>`, `--base-sha <immutable SHA>`, `--head-sha <immutable SHA>`, and `--worktree <isolated path>`. The caller supplies `low` as the default level; `medium` and `xhigh` are valid selections. Route the selected mode through [reference/preflight-proposal.md](reference/preflight-proposal.md) to establish proposal context. The mode runs `<review_level> --fix loop` locally and returns selected-candidate-ready proposal evidence.
20
+ 2. Normal mode follows the current level, `--fix`, and `loop` behavior.
21
+
22
+ The proposal mode applies the canonical proposal contract at `@~/.claude/_shared/pr-loop/preflight-proposal.md`. The local extension selects the review level and records finding outcomes. The downstream owner records selected proposal IDs before reapplication; each new finding receives a new ID.
23
+
14
24
  ## Gotchas
15
25
 
16
26
  - **`low` stays single-pass.** No subagents, no full-file reads: one read pass per target item, one findings pass.
@@ -61,6 +71,7 @@ Detail: `reference/effort-evaluation.md`.
61
71
  | `reference/xhigh.md` | xhigh review procedure — 10 angles, 1-vote verify, gap sweep |
62
72
  | `reference/fix.md` | Fix application, code-rules gate, skip logging, outcome reporting |
63
73
  | `reference/loop.md` | Repeat review/fix rounds until clean |
74
+ | `reference/preflight-proposal.md` | Isolated local review, immutable SHAs, proposal evidence, and mutation boundary |
64
75
  | `reference/effort-evaluation.md` | Effort evaluation fixtures, evidence, and skill defaults |
65
76
  | `reference/runner-selection.md` | Runner selection map |
66
77
  | `scripts/finding_pipeline.py` | Collect every real finding; filter severity only later |
@@ -2,6 +2,10 @@
2
2
 
3
3
  When `--fix` is passed, apply the reviewed findings to the working tree.
4
4
 
5
+ ## Preflight-proposal mode
6
+
7
+ When the hub selects `preflight-proposal`, consume the established proposal context, selected review level, and current pull-request head.
8
+
5
9
  ## Resume the finding agent
6
10
 
7
11
  For each finding, resume the same Agent-tool agent instance that originally
@@ -73,4 +77,4 @@ the fix, or later work fixes it incidentally — call the structured
73
77
  findings-report call again with the same findings, each carrying an
74
78
  `outcome` (`fixed`, `no_change_needed`, or `skipped`). Do not repeat the
75
79
  findings as text. Make that call immediately after the fixes land, before any
76
- prose summary.
80
+ prose summary.
@@ -1,5 +1,9 @@
1
1
  # Loop until clean
2
2
 
3
+ ## Preflight-proposal mode
4
+
5
+ When the hub selects `preflight-proposal`, continue the review loop with the established proposal context. Proposal mode ends with proposal evidence. Normal mode keeps its GitHub disclosure and Ready actions.
6
+
3
7
  ## Act
4
8
 
5
9
  `loop` on the hub command authorizes the full cycle. After the effort level procedure returns findings, run the gate sequence below immediately.
@@ -0,0 +1,66 @@
1
+ import assert from 'node:assert/strict'
2
+ import { readFileSync } from 'node:fs'
3
+ import test from 'node:test'
4
+
5
+ const proposalSource = readFileSync(new URL('./preflight-proposal.md', import.meta.url), 'utf8')
6
+ const fixSource = readFileSync(new URL('./fix.md', import.meta.url), 'utf8')
7
+ const loopSource = readFileSync(new URL('./loop.md', import.meta.url), 'utf8')
8
+
9
+ function sourceBetweenHeadings(source, fromHeading, toHeading) {
10
+ const fromOffset = source.indexOf(fromHeading)
11
+ const toOffset = source.indexOf(toHeading, fromOffset)
12
+
13
+ assert.ok(fromOffset >= 0)
14
+ assert.ok(toOffset > fromOffset)
15
+
16
+ return source.slice(fromOffset, toOffset)
17
+ }
18
+
19
+ function assertReviewLevelExtension() {
20
+ assert.match(proposalSource, /<review_level> --fix loop/)
21
+ const allReviewLevelMappings = [
22
+ ['Omitted override', 'low'],
23
+ ['`low`', 'low'],
24
+ ['`medium`', 'medium'],
25
+ ['`xhigh`', 'xhigh'],
26
+ ]
27
+
28
+ for (const [eachCallerSelection, eachLevel] of allReviewLevelMappings) {
29
+ const expectedRow = `| ${eachCallerSelection} | \`${eachLevel}\` |`
30
+ assert.match(proposalSource, new RegExp(expectedRow.replaceAll('|', '\\|')))
31
+ }
32
+ assert.match(proposalSource, /`review_level` evidence mirrors the resolved `--level` value/)
33
+ }
34
+
35
+ function assertProposalHandoffs() {
36
+ assert.match(proposalSource, /canonical contract owns the immutable range/)
37
+ const fixModeSource = sourceBetweenHeadings(
38
+ fixSource,
39
+ '## Preflight-proposal mode',
40
+ '## Resume the finding agent',
41
+ )
42
+ assert.match(fixModeSource, /consume the established proposal context/)
43
+ assert.doesNotMatch(fixModeSource, /follow \[preflight-proposal.md\]/)
44
+ const proposalModeSource = sourceBetweenHeadings(
45
+ loopSource,
46
+ '## Preflight-proposal mode',
47
+ '## Act',
48
+ )
49
+ assert.match(proposalModeSource, /continue the review loop with the established proposal context/)
50
+ assert.doesNotMatch(proposalModeSource, /follow \[preflight-proposal.md\]/)
51
+ assert.match(proposalModeSource, /Proposal mode ends with proposal evidence/)
52
+ assert.doesNotMatch(proposalModeSource, /proof-of-work PR comment|gh pr ready/)
53
+ assert.doesNotMatch(proposalSource, /proof-of-work PR comment|gh pr ready/)
54
+ }
55
+
56
+ function assertNormalTerminationContract() {
57
+ const normalTerminalSource = loopSource.slice(loopSource.indexOf('## Terminal outcomes'))
58
+ assert.match(normalTerminalSource, /proof-of-work PR comment/)
59
+ assert.match(normalTerminalSource, /gh pr ready/)
60
+ }
61
+
62
+ test('preflight proposal mode isolates review loops and preserves normal termination behavior', () => {
63
+ assertReviewLevelExtension()
64
+ assertProposalHandoffs()
65
+ assertNormalTerminationContract()
66
+ })
@@ -0,0 +1,40 @@
1
+ # Review preflight proposal mode
2
+
3
+ Apply the canonical proposal contract at:
4
+
5
+ ```text
6
+ @~/.claude/_shared/pr-loop/preflight-proposal.md
7
+ ```
8
+
9
+ Use this review extension when the caller selects `preflight-proposal`:
10
+
11
+ ```text
12
+ /e-code-review preflight-proposal <pr_number> --level low --base-sha <base_sha> --head-sha <head_sha> --worktree <isolated_worktree>
13
+ ```
14
+
15
+ ## Review extension
16
+
17
+ The caller resolves the review level before invocation and always passes `--level`. Use this mapping:
18
+
19
+ | Caller selection | Resolved `--level` |
20
+ |---|---|
21
+ | Omitted override | `low` |
22
+ | `low` | `low` |
23
+ | `medium` | `medium` |
24
+ | `xhigh` | `xhigh` |
25
+
26
+ The `review_level` evidence mirrors the resolved `--level` value.
27
+
28
+ Run the selected level as `<review_level> --fix loop`. The selected level owns its normal finding and fix rules. Require `HEAD` to equal the supplied head SHA before each round.
29
+
30
+ Keep Gate 1, Gate 2, the bare code-rules gate, and exact required tests. Extend the canonical evidence record with:
31
+
32
+ ```yaml
33
+ review_level: low | medium | xhigh
34
+ findings:
35
+ - severity: blocker | high | medium | low | nit
36
+ verdict: CONFIRMED | PLAUSIBLE
37
+ outcome: fixed | no_change_needed | skipped
38
+ ```
39
+
40
+ The canonical contract owns the immutable range, worktree boundary, proposal identity, changed paths, exact tests and outcomes, mutation boundary, and downstream selection.
@@ -35,6 +35,7 @@ Open issue for implementation work should link this file and keep PRs small
35
35
  ## Related always-on docs
36
36
 
37
37
  - Skill hub: `../SKILL.md` (levels, fix, loop — not runner internals).
38
+ - Preflight proposal: `preflight-proposal.md` (immutable range, local runner, proposal evidence).
38
39
  - Medium procedure: `medium.md`.
39
40
  - Shared worker spawn (when applicable):
40
41
  `packages/claude-dev-env/_shared/pr-loop/worker-spawn.md` in the package tree.
@@ -1,99 +1,129 @@
1
1
  ---
2
2
  name: pr-cleanup
3
3
  description: >-
4
- Clean a PR end-to-end with one coding agent: shared-extraction-audit,
5
- name-by-capability-audit, sr-loop, then small-cl apply and validate fixes
6
- as they return. Use when the user asks for /pr-cleanup or full PR cleanup
7
- (place, name, converge, then shrink).
4
+ Refine pull requests through parallel placement and capability-name audits,
5
+ focused delivery sizing, and a final simplify and code-review loop. Triggers:
6
+ /pr-cleanup, run PR cleanup, full PR cleanup, extraction audit, capability
7
+ naming audit, simplify and review a PR, and split a cleaned PR.
8
8
  ---
9
9
 
10
10
  # PR cleanup
11
11
 
12
- One coding agent cleans a pull request end-to-end: put code in the right place,
13
- name it for what it does, run the converging cleanup loop, then shrink the
14
- change into a reviewable size.
12
+ ## Contents
15
13
 
16
- This skill is host-neutral. Any coding agent that can edit the PR head, run
17
- scoped tests, and invoke the composed skills may run it.
14
+ - [Principle](#principle)
15
+ - [When this applies](#when-this-applies)
16
+ - [Composition](#composition)
17
+ - [Task seeding](#task-seeding)
18
+ - [Process](#process)
19
+ - [Promotion gates](#promotion-gates)
20
+ - [Finish report](#finish-report)
21
+ - [File index](#file-index)
18
22
 
19
- ## When to use
23
+ ## Principle
20
24
 
21
- - `/pr-cleanup <PR>` or “run pr-cleanup on this PR”
22
- - A PR needs extraction + naming + sr-loop + a smaller reviewable slice in one pass
25
+ One coding agent owns the cleanup outcome. `pr-refinement` coordinates parallel
26
+ preflight audits and produces findings, tested proposals, a combined change map,
27
+ and a delivery decision for the cleanup owner. Parent-to-child promotion uses
28
+ exact commit ancestry and fresh child-head checks.
23
29
 
24
- ## Inputs
30
+ ## When this applies
25
31
 
26
- - Target: PR URL, number, or branch (required). Missing ask:
27
- `Give a GitHub PR number or URL for pr-cleanup.`
28
- - Repo: take from the PR URL when given; otherwise the user’s default monitored repo
32
+ Use this skill for a pull request that needs placement review, capability
33
+ naming, cleanup convergence, and a focused delivery boundary.
29
34
 
30
- ## Composition (run in this order)
35
+ Required input: a pull request URL, number, or branch. If the target is missing,
36
+ respond exactly: `Give a GitHub PR number, URL, or branch for pr-cleanup.`
31
37
 
32
- | Step | Skill | Role |
33
- |------|--------|------|
34
- | 1 | `shared-extraction-audit` | Wrong *place* (workflow package vs shared library) |
35
- | 2 | `name-by-capability-audit` | Wrong *name* (driver word on reusable capability) |
36
- | 3 | `sr-loop` / `e-simplify` then `e-code-review` | Converging simplify + high-effort review with `--fix` |
37
- | 4 | `small-cl` | Split / shrink into a focused reviewable PR |
38
+ Use the repository that owns the target pull request. Keep every pull request in
39
+ draft state until its applicable Ready gate is complete. Keep merge authority
40
+ with the user.
38
41
 
39
- All four run under **one coding agent session** on the same worktree / PR head.
40
- For sr-loop advisor consults, bind `team-advisor` as a second session at equal
41
- tier when the host supports it (see `team-advisor` and the advisor docs).
42
+ ## Composition
42
43
 
43
- ## Fix-as-you-go (required)
44
+ | Skill | Role | Evidence |
45
+ |---|---|---|
46
+ | `pr-refinement` | Run the parallel audits, combine findings, and coordinate implementation shape | Change map and delivery decision |
47
+ | `pr-shared-extraction` | Find reusable behavior that belongs in `shared_utils` | Placement findings and tested proposal |
48
+ | `pr-name-by-capability` | Find driver or motive words on reusable capability surfaces | Naming findings and rename directions |
49
+ | `pr-small-cl` | Choose one coherent pull request or an ordered replacement stack | Focused boundary and dependencies |
50
+ | `source-command-sr-loop` | Run `e-simplify`, then `e-code-review low --fix` until clean | Review passes, fixes, and validation |
44
51
 
45
- Some of these skills can report without changing code. For **pr-cleanup**, that
46
- is not enough:
52
+ ## Task seeding
47
53
 
48
- 1. **Stream findings** as each audit/loop returns an item (offense, rename,
49
- simplify fix, review finding), treat it as work to do now, not a backlog.
50
- 2. **Apply the fix** on the PR head (or the first small-cl increment if already
51
- splitting) before moving on to the next item when practical.
52
- 3. **Validate** after each applied fix: scoped tests beside touched files (or
53
- `py_compile` / package tests when there is no adjacent suite). No test theater.
54
- 4. **Commit + push** after each validated changing pass (one concern per commit
55
- when possible; keep the PR draft).
56
- 5. **Do not** finish with an audit-only report while known P0/P1 fixes sit
57
- unapplied — either fix them or hard-block with why.
58
-
59
- If the user says **audit-only**, stop after reports and skip apply / small-cl.
54
+ At skill start, register every item in `reference/task-seeds.md` as a session
55
+ task through `TaskCreate`, `TodoWrite`, or the host task equivalent. Work from
56
+ that task list. Mark each task complete with `PASS`, `FAIL` plus file and line
57
+ evidence, or `N/A` plus the reason.
60
58
 
61
59
  ## Process
62
60
 
63
- 1. Resolve PR → convert to draft if needed; clean worktree of the PR head;
64
- never mark ready for review.
65
- 2. Run the four composed skills in order on that head:
66
- - `shared-extraction-audit` in the **implement** band (not audit-only)
67
- - `name-by-capability-audit`; apply clear rename directions (or ones the user
68
- already approved), noting rename direction in the commit message
69
- - `sr-loop`: Phase A `e-simplify`, Phase B `e-code-review` at **xhigh** with
70
- `--fix` (not the default low); consult `team-advisor` before the first
71
- write and after writes + validation
72
- - Apply fixes as each pass returns findings; validate → commit → push
73
- 3. After the loop converges (or nits-only stop): run **small-cl** — identify the
74
- first coherent reviewable increment; if the PR is still too wide, split or
75
- retitle/scope per small-cl (do not invent extra PRs unless the user asked).
76
- 4. Return the finish report below. Merge-ready email / chat delivery is owned by
77
- the caller (for example a PR monitor host), not this skill.
78
-
79
- ## Hard rules
80
-
81
- - No test theater.
82
- - Real spawn/behavior validation when the PR claims an external binary path.
83
- - Prefer cleanup; functional only for correctness. Label each commit
84
- `cleanup` vs `functional`.
85
- - Keep the PR draft. Never mark ready for review during this skill.
86
- - Extraction before rename when both apply to the same symbol (move, then name
87
- the new home).
88
- - small-cl last — shrink only after place / name / cleanup are settled enough
89
- that the slice is honest.
61
+ ### 1. Resolve the target
62
+
63
+ Resolve the pull request, repository, parent head SHA, and intended child
64
+ boundary. Record the immutable parent preflight SHA before creating worktrees.
65
+
66
+ ### 2. Run `pr-refinement`
67
+
68
+ Run [pr-refinement](../pr-refinement/SKILL.md). Record its combined change map,
69
+ audit findings, locations, priorities, destinations or rename directions,
70
+ validation evidence, and worker worktrees.
71
+
72
+ ### 3. Choose the delivery shape
73
+
74
+ Use [pr-small-cl](../pr-small-cl/SKILL.md) after the audit findings are
75
+ combined. Record the first pull request boundary, dependencies, tests, and
76
+ follow-up work.
77
+
78
+ ### 4. Implement the selected shape
79
+
80
+ Apply every actionable finding in dependency order. Keep preflight parent scope
81
+ read-only until the cleanup owner selects and reapplies tested proposals.
82
+ Validate each changed surface with its production-path tests. Commit each
83
+ validated concern and keep the resulting pull request in draft state.
84
+
85
+ ### 5. Run `source-command-sr-loop`
86
+
87
+ Run [source-command-sr-loop](../source-command-sr-loop/SKILL.md). Record the
88
+ review passes, fixes, skips, tests, and commit SHAs.
89
+
90
+ ### 6. Promote and report
91
+
92
+ After the applicable gate passes, complete the [Finish report](#finish-report).
93
+
94
+ ## Promotion gates
95
+
96
+ Run preflight work in isolated worktrees from the recorded parent SHA. Apply
97
+ selected changes in the parent cleanup worktree after the owner selects the
98
+ tested proposals.
99
+
100
+ Promote the parent only after every actionable finding has an applied fix or an
101
+ exact disposition. Record the remote parent Ready state and exact
102
+ `parent_ready_sha`.
103
+
104
+ Create the child from its intended pre-parent base and merge the exact
105
+ `parent_ready_sha`. Prove that SHA is an ancestor of the child head with
106
+ `git merge-base --is-ancestor <parent_ready_sha> <child_head>` and record exit
107
+ code `0`.
108
+
109
+ Reapply every relevant fix to the child. Rerun child tests, `e-simplify`, and
110
+ `e-code-review` after the merge. Record the new child head and every validation
111
+ result before promoting the child to Ready.
112
+
113
+ Use `reference/task-seeds.md` and `reference/process-inventory.md` to record promotion evidence.
90
114
 
91
115
  ## Finish report
92
116
 
93
- - PR / repo / starting_sha / ending_sha
94
- - Per step: extraction findings applied, naming violations applied, sr-loop
95
- passes + commits, small-cl outcome (kept / split plan)
96
- - `commits_pushed` with cleanup|functional labels
97
- - `validation_ran` + outcomes
98
- - `hard_block` or null
99
- - `draft_still: true`
117
+ - Pull request or stack URLs.
118
+ - `pr-refinement` outcome.
119
+ - `source-command-sr-loop` passes, commits, and validation results.
120
+ - Parent-ready and child-ready SHAs when a child is promoted.
121
+ - Remaining hard block, or `null`.
122
+
123
+ ## File index
124
+
125
+ | Path | Purpose |
126
+ |---|---|
127
+ | `SKILL.md` | Hub for refinement, cleanup convergence, promotion gates, and reporting |
128
+ | `reference/task-seeds.md` | Ordered session tasks for audits, delivery, validation, and promotion |
129
+ | `reference/process-inventory.md` | Process classes, evidence homes, and paired task checks |
@@ -0,0 +1,15 @@
1
+ # PR cleanup process inventory
2
+
3
+ | Step | Class | Home | Evidence | Paired test |
4
+ |---|---|---|---|---|
5
+ | Resolve PR and immutable parent SHA | deterministic | `task-seed:reference/task-seeds.md` | Target record and parent SHA | task-tool |
6
+ | Create isolated preflight worktrees | deterministic | `task-seed:reference/task-seeds.md` | Worktree paths and base SHA | task-tool |
7
+ | Run parallel preflight streams | borderline | `SKILL.md` and `task-seed:reference/task-seeds.md` | Stream reports and worker availability | task-tool |
8
+ | Apply or disposition findings | judgment | `SKILL.md` and `task-seed:reference/task-seeds.md` | Changed diff or exact disposition | task-tool |
9
+ | Validate parent head | deterministic | `task-seed:reference/task-seeds.md` | Scoped test and confirmation results | task-tool |
10
+ | Promote parent and record exact Ready SHA | deterministic | `task-seed:reference/task-seeds.md` | Remote parent Ready state and SHA | task-tool |
11
+ | Merge exact parent SHA into child | deterministic | `task-seed:reference/task-seeds.md` | Child merge commit and parent SHA | task-tool |
12
+ | Prove parent SHA ancestry | deterministic | `task-seed:reference/task-seeds.md` | `git merge-base --is-ancestor` exit code `0` | task-tool |
13
+ | Reapply relevant fixes to child | judgment | `SKILL.md` and `task-seed:reference/task-seeds.md` | Child diff and reapplication record | task-tool |
14
+ | Validate child and rerun confirmations | deterministic | `task-seed:reference/task-seeds.md` | New child-head tests, simplify, and review results | task-tool |
15
+ | Promote child and report | deterministic | `task-seed:reference/task-seeds.md` | Child Ready state and finish report | task-tool |
@@ -0,0 +1,20 @@
1
+ # PR cleanup task seeds
2
+
3
+ Register each numbered item as one session task before work starts. Complete
4
+ each task with evidence from the stated gate.
5
+
6
+ 1. Resolve the target PR, repository, parent head SHA, and child boundary.
7
+ 2. Create isolated preflight worktrees from the immutable parent preflight SHA.
8
+ 3. Run the shared-extraction, capability-name, `e-simplify`, and `e-code-review` preflight streams in parallel when available.
9
+ 4. Record each stream's worktree, base SHA, findings, proposed patch, and validation evidence.
10
+ 5. Keep parent merge, rebase, push, and Ready operations unavailable during preflight.
11
+ 6. Select, apply, validate, or exactly disposition every actionable preflight finding in the one-agent parent cleanup worktree.
12
+ 7. Run parent scoped tests and cleanup/review confirmation checks.
13
+ 8. Promote the parent to Ready and record the exact remote `parent_ready_sha`.
14
+ 9. Create the child from its intended pre-parent base and merge the exact `parent_ready_sha`.
15
+ 10. Prove `parent_ready_sha` is an ancestor of the child head and record the exit code.
16
+ 11. Reapply every relevant preflight fix to the child.
17
+ 12. Run child scoped tests on the new child head.
18
+ 13. Rerun `e-simplify` and `e-code-review` on the new child head.
19
+ 14. Promote the child to Ready after all child evidence passes.
20
+ 15. Write the finish report with SHAs, evidence, states, and hard blocks.