claude-dev-env 4.3.0 → 7.0.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 (293) hide show
  1. package/.agents/agents/pr-description-writer.md +2 -2
  2. package/.agents/agents/test_agent_frontmatter.py +2 -2
  3. package/.agents/agents/test_pr_description_writer_style.py +1 -3
  4. package/.agents/skills/e-code-review/SKILL.md +12 -12
  5. package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
  6. package/.agents/skills/e-code-review/reference/fix.md +15 -17
  7. package/.agents/skills/e-code-review/reference/loop.md +35 -39
  8. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
  9. package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
  10. package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
  11. package/.agents/skills/issue-tracker/SKILL.md +5 -4
  12. package/.agents/skills/pull-request/SKILL.md +11 -13
  13. package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
  14. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
  15. package/.agents/skills/pull-request/scripts/pull_request.py +33 -44
  16. package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
  17. package/.agents/skills/pull-request/scripts/test_pull_request.py +1 -3
  18. package/.agents/skills/skill-builder/SKILL.md +3 -196
  19. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  20. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  21. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  22. package/bin/install.agents-home.test.mjs +15 -13
  23. package/bin/install.mjs +28 -0
  24. package/bin/install.policy-lint.test.mjs +78 -0
  25. package/bin/install.prune.test.mjs +59 -20
  26. package/bin/install.pstack-plugin.test.mjs +114 -0
  27. package/bin/install.test.mjs +37 -0
  28. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  29. package/hooks/advisory/pr_done_reminder.py +342 -0
  30. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  31. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  32. package/hooks/blocking/code_rules_paired_test.py +22 -15
  33. package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
  34. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  35. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  36. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  37. package/hooks/blocking/test_pre_tool_use_dispatcher.py +68 -133
  38. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  39. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +18 -18
  40. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  41. package/hooks/git-hooks/pre_commit.py +52 -11
  42. package/hooks/git-hooks/test_installed_policy_lint.py +159 -0
  43. package/hooks/git-hooks/test_native_policy_commit.py +87 -0
  44. package/hooks/git-hooks/test_pre_commit.py +246 -0
  45. package/hooks/hooks.json +1 -1
  46. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
  47. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  48. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -43
  49. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
  50. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  51. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +20 -32
  52. package/package.json +2 -2
  53. package/rules/durable-post-artifacts.md +2 -1
  54. package/rules/git-workflow.md +6 -6
  55. package/scripts/check.ps1 +0 -1
  56. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  57. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  58. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  59. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  60. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +5 -41
  61. package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +0 -10
  62. package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +1 -1
  63. package/scripts/policy_lint/adapter_detectors.py +13 -6
  64. package/scripts/policy_lint/adapters.py +7 -4
  65. package/scripts/policy_lint/config/constants.py +5 -0
  66. package/scripts/policy_lint/engine.py +48 -4
  67. package/scripts/policy_lint/model.py +1 -0
  68. package/scripts/policy_lint/registry.py +1 -1
  69. package/scripts/policy_lint/selection.py +2 -1
  70. package/scripts/policy_lint/selection_git.py +2 -0
  71. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  72. package/scripts/shared_tree_paths.py +32 -3
  73. package/scripts/test_shared_tree_paths.py +33 -0
  74. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  75. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  76. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  77. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  78. package/scripts/tests/test_policy_lint_selection.py +25 -2
  79. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  80. package/scripts/tests/test_rules.py +3 -7
  81. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  82. package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -1
  83. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  84. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  85. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  86. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  87. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  88. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  89. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  90. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  91. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  92. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  93. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  94. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  95. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  96. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  97. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  98. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  99. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  100. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  101. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  102. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  103. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  104. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  105. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  106. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  107. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  108. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  109. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  110. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  111. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  112. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  113. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  114. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  115. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  116. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  117. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  118. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  119. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  120. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  121. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  122. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  123. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  124. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  125. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  126. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  127. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  128. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  129. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  130. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  131. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  132. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  133. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  134. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  135. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  136. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  137. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  138. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  139. package/.agents/skills/autoconverge/SKILL.md +0 -431
  140. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  141. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  142. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  143. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  144. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  145. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  146. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  147. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  148. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  149. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  150. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  151. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  152. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  153. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  154. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  155. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  156. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  157. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  158. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  159. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  160. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  161. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  162. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  163. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  164. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  165. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  166. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  167. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  168. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  169. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  170. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  171. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  172. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  173. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  174. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  175. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  176. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  177. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  178. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  179. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  180. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  181. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  182. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  183. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  184. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  185. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  186. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  187. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  188. package/.agents/skills/hitl/SKILL.md +0 -45
  189. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  190. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  191. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  192. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  193. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  194. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  195. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  196. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  197. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  198. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  199. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  200. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  201. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  202. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  203. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  204. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  205. package/.agents/skills/prototype/SKILL.md +0 -85
  206. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  207. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  208. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  209. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  210. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  211. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  212. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  213. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  214. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  215. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  216. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  217. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  218. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  219. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  220. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  221. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  222. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  223. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  224. package/.agents/skills/rebase/AGENTS.md +0 -1
  225. package/.agents/skills/rebase/SKILL.md +0 -178
  226. package/.agents/skills/review-router/SKILL.md +0 -51
  227. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  228. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  229. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  230. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  231. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  232. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  233. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  234. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  235. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  236. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  237. package/.agents/skills/review-tier/SKILL.md +0 -56
  238. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  239. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  240. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  241. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  242. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  243. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  244. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  245. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  246. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  247. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  248. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  249. package/.agents/skills/session-log/AGENTS.md +0 -1
  250. package/.agents/skills/session-log/SKILL.md +0 -170
  251. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  252. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  253. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  254. package/.agents/skills/session-tidy/SKILL.md +0 -191
  255. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  256. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  257. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  258. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  259. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  260. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  261. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  262. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  263. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  264. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  265. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  266. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  267. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  268. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  269. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  270. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  271. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  272. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  273. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  274. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  275. package/.agents/skills/update/AGENTS.md +0 -1
  276. package/.agents/skills/update/SKILL.md +0 -190
  277. package/_shared/pr-loop/AGENTS.md +0 -1
  278. package/_shared/pr-loop/CLAUDE.md +0 -1
  279. package/_shared/pr-loop/audit-contract.md +0 -183
  280. package/_shared/pr-loop/audit-reply-template.md +0 -151
  281. package/_shared/pr-loop/code-rules-gate.md +0 -65
  282. package/_shared/pr-loop/fix-protocol.md +0 -60
  283. package/_shared/pr-loop/gh-payloads.md +0 -75
  284. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  285. package/_shared/pr-loop/precatch-rubric.md +0 -66
  286. package/_shared/pr-loop/preflight-proposal.md +0 -56
  287. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  288. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  289. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  290. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  291. package/_shared/pr-loop/state-schema.md +0 -45
  292. package/_shared/pr-loop/worker-spawn.md +0 -189
  293. /package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +0 -0
@@ -1,312 +0,0 @@
1
- """Tests for the sandbox safety-hook probe.
2
-
3
- The block-detection unit tests drive fixture hook scripts, and the
4
- integration tests point a settings file at the real installed safety hooks
5
- to prove they block their probe payloads end to end.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import importlib.util
11
- import json
12
- import sys
13
- from pathlib import Path
14
- from types import ModuleType
15
-
16
- from prototype_scripts_constants.config.build_sandbox_settings_constants import (
17
- ALL_SAFETY_HOOK_SCRIPT_BASENAMES,
18
- COMMAND_KEY,
19
- HOOKS_KEY,
20
- MATCHER_KEY,
21
- PRE_TOOL_USE_KEY,
22
- )
23
- from prototype_scripts_constants.config.probe_sandbox_safety_constants import (
24
- DESTRUCTIVE_PROBE_COMMAND,
25
- ENVELOPE_TOOL_INPUT_KEY,
26
- ENVELOPE_TOOL_NAME_KEY,
27
- PII_PROBE_TOKEN_PREFIX,
28
- PII_PROBE_TOOL_NAME,
29
- PROBE_FAILURE_EXIT_CODE,
30
- PROBE_SUCCESS_EXIT_CODE,
31
- TOOL_INPUT_COMMAND_KEY,
32
- TOOL_INPUT_CONTENT_KEY,
33
- )
34
-
35
- SCRIPTS_DIRECTORY = Path(__file__).resolve().parent
36
- BUILDER_PATH = SCRIPTS_DIRECTORY / "build_sandbox_settings.py"
37
- PROBE_PATH = SCRIPTS_DIRECTORY / "probe_sandbox_safety.py"
38
- HOOKS_BLOCKING_DIRECTORY = SCRIPTS_DIRECTORY.parents[3] / "hooks" / "blocking"
39
-
40
- PII_HOOK_BASENAME = ALL_SAFETY_HOOK_SCRIPT_BASENAMES[0]
41
- DESTRUCTIVE_HOOK_BASENAME = ALL_SAFETY_HOOK_SCRIPT_BASENAMES[1]
42
-
43
- DENY_HOOK_SOURCE = (
44
- "import json, sys\n"
45
- "sys.stdout.write(json.dumps("
46
- '{"hookSpecificOutput": {"permissionDecision": "deny"}}))\n'
47
- )
48
- ASK_HOOK_SOURCE = (
49
- "import json, sys\n"
50
- "sys.stdout.write(json.dumps("
51
- '{"hookSpecificOutput": {"permissionDecision": "ask"}}))\n'
52
- )
53
- ALLOW_HOOK_SOURCE = "import sys\nsys.exit(0)\n"
54
-
55
-
56
- def load_module_from_path(module_name: str, module_path: Path) -> ModuleType:
57
- spec = importlib.util.spec_from_file_location(module_name, module_path)
58
- assert spec is not None
59
- assert spec.loader is not None
60
- loaded_module = importlib.util.module_from_spec(spec)
61
- spec.loader.exec_module(loaded_module)
62
- return loaded_module
63
-
64
-
65
- def load_probe_module() -> ModuleType:
66
- return load_module_from_path("probe_sandbox_safety", PROBE_PATH)
67
-
68
-
69
- def load_builder_module() -> ModuleType:
70
- return load_module_from_path("build_sandbox_settings", BUILDER_PATH)
71
-
72
-
73
- def quoted_command(script_path: Path) -> str:
74
- return f'"{sys.executable}" "{script_path}"'
75
-
76
-
77
- def real_hook_settings_document() -> dict:
78
- pii_hook_path = HOOKS_BLOCKING_DIRECTORY / PII_HOOK_BASENAME
79
- destructive_hook_path = HOOKS_BLOCKING_DIRECTORY / DESTRUCTIVE_HOOK_BASENAME
80
- return {
81
- HOOKS_KEY: {
82
- PRE_TOOL_USE_KEY: [
83
- {
84
- MATCHER_KEY: "Write",
85
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(pii_hook_path)}],
86
- },
87
- {
88
- MATCHER_KEY: "Bash",
89
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(destructive_hook_path)}],
90
- },
91
- ]
92
- }
93
- }
94
-
95
-
96
- def real_hook_deny_mode_settings_document() -> dict:
97
- settings_document = real_hook_settings_document()
98
- settings_document["env"] = {"CLAUDE_DESTRUCTIVE_DENY_MODE": "1"}
99
- return settings_document
100
-
101
-
102
- def write_settings_file(tmp_path: Path, settings_document: dict) -> Path:
103
- settings_path = tmp_path / "sandbox-settings.json"
104
- settings_path.write_text(json.dumps(settings_document), encoding="utf-8")
105
- return settings_path
106
-
107
-
108
- def test_settings_environment_overrides_reads_the_env_block() -> None:
109
- probe = load_probe_module()
110
- environment_overrides = probe.settings_environment_overrides(
111
- real_hook_deny_mode_settings_document()
112
- )
113
- assert environment_overrides == {"CLAUDE_DESTRUCTIVE_DENY_MODE": "1"}
114
-
115
-
116
- def test_settings_environment_overrides_empty_without_an_env_block() -> None:
117
- probe = load_probe_module()
118
- environment_overrides = probe.settings_environment_overrides(
119
- real_hook_settings_document()
120
- )
121
- assert environment_overrides == {}
122
-
123
-
124
- def test_main_exits_zero_when_the_real_destructive_hook_denies_in_deny_mode(
125
- tmp_path: Path,
126
- ) -> None:
127
- probe = load_probe_module()
128
- settings_path = write_settings_file(
129
- tmp_path, real_hook_deny_mode_settings_document()
130
- )
131
- exit_code = probe.main(["--settings", str(settings_path)])
132
- assert exit_code == PROBE_SUCCESS_EXIT_CODE
133
-
134
-
135
- def test_built_deny_environment_denies_real_destructive_hook() -> None:
136
- builder_module = load_builder_module()
137
- settings_document = builder_module.build_minimal_settings(
138
- builder_module.resolve_safety_hook_entries(real_hook_settings_document())
139
- )
140
- probe_module = load_probe_module()
141
- probe_payload = probe_module.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
142
- destructive_hook_path = HOOKS_BLOCKING_DIRECTORY / DESTRUCTIVE_HOOK_BASENAME
143
- destructive_hook_tokens = probe_module.parse_command_argv(
144
- quoted_command(destructive_hook_path)
145
- )
146
- is_hook_blocking = probe_module.hook_blocks_probe(
147
- destructive_hook_tokens,
148
- probe_payload,
149
- settings_document["env"],
150
- )
151
- assert is_hook_blocking is True
152
-
153
-
154
- def test_pii_basename_probe_payload_carries_the_secret() -> None:
155
- probe = load_probe_module()
156
- probe_payload = probe.build_probe_payload_for_basename(PII_HOOK_BASENAME)
157
- assert probe_payload[ENVELOPE_TOOL_NAME_KEY] == PII_PROBE_TOOL_NAME
158
- content = probe_payload[ENVELOPE_TOOL_INPUT_KEY][TOOL_INPUT_CONTENT_KEY]
159
- assert PII_PROBE_TOKEN_PREFIX in content
160
-
161
-
162
- def test_destructive_basename_probe_payload_carries_the_command() -> None:
163
- probe = load_probe_module()
164
- probe_payload = probe.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
165
- command = probe_payload[ENVELOPE_TOOL_INPUT_KEY][TOOL_INPUT_COMMAND_KEY]
166
- assert command == DESTRUCTIVE_PROBE_COMMAND
167
-
168
-
169
- def test_find_hook_command_for_basename_returns_the_matching_command() -> None:
170
- probe = load_probe_module()
171
- settings_document = real_hook_settings_document()
172
- command = probe.find_hook_command_for_basename(settings_document, PII_HOOK_BASENAME)
173
- assert command is not None
174
- assert PII_HOOK_BASENAME in command
175
- assert probe.find_hook_command_for_basename(settings_document, "absent.py") is None
176
-
177
-
178
- def test_parse_command_argv_splits_and_unquotes_the_command() -> None:
179
- probe = load_probe_module()
180
- command_argv = probe.parse_command_argv('"/usr/bin/python" "/a/b hook.py"')
181
- assert command_argv == ["/usr/bin/python", "/a/b hook.py"]
182
-
183
-
184
- def test_hook_blocks_probe_reports_true_for_a_deny_hook(tmp_path: Path) -> None:
185
- probe = load_probe_module()
186
- deny_hook_path = tmp_path / "deny_hook.py"
187
- deny_hook_path.write_text(DENY_HOOK_SOURCE, encoding="utf-8")
188
- command_argv = [sys.executable, str(deny_hook_path)]
189
- probe_payload = probe.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
190
- assert probe.hook_blocks_probe(command_argv, probe_payload, {}) is True
191
-
192
-
193
- def test_hook_blocks_probe_reports_false_for_an_ask_hook(tmp_path: Path) -> None:
194
- probe = load_probe_module()
195
- ask_hook_path = tmp_path / "ask_hook.py"
196
- ask_hook_path.write_text(ASK_HOOK_SOURCE, encoding="utf-8")
197
- command_argv = [sys.executable, str(ask_hook_path)]
198
- probe_payload = probe.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
199
- assert probe.hook_blocks_probe(command_argv, probe_payload, {}) is False
200
-
201
-
202
- def test_hook_blocks_probe_reports_false_for_an_allow_hook(tmp_path: Path) -> None:
203
- probe = load_probe_module()
204
- allow_hook_path = tmp_path / "allow_hook.py"
205
- allow_hook_path.write_text(ALLOW_HOOK_SOURCE, encoding="utf-8")
206
- command_argv = [sys.executable, str(allow_hook_path)]
207
- probe_payload = probe.build_probe_payload_for_basename(DESTRUCTIVE_HOOK_BASENAME)
208
- assert probe.hook_blocks_probe(command_argv, probe_payload, {}) is False
209
-
210
-
211
- def test_probe_safety_hook_blocks_against_the_real_pii_hook() -> None:
212
- probe = load_probe_module()
213
- settings_document = real_hook_settings_document()
214
- assert probe.probe_safety_hook(settings_document, PII_HOOK_BASENAME) is True
215
-
216
-
217
- def test_main_exits_three_when_the_real_destructive_hook_only_asks(
218
- tmp_path: Path,
219
- ) -> None:
220
- probe = load_probe_module()
221
- settings_path = write_settings_file(tmp_path, real_hook_settings_document())
222
- exit_code = probe.main(["--settings", str(settings_path)])
223
- assert exit_code == PROBE_FAILURE_EXIT_CODE
224
-
225
-
226
- def test_main_exits_zero_when_both_real_hooks_hard_deny(tmp_path: Path) -> None:
227
- probe = load_probe_module()
228
- deny_pii_hook_path = tmp_path / PII_HOOK_BASENAME
229
- deny_pii_hook_path.write_text(DENY_HOOK_SOURCE, encoding="utf-8")
230
- deny_destructive_hook_path = tmp_path / DESTRUCTIVE_HOOK_BASENAME
231
- deny_destructive_hook_path.write_text(DENY_HOOK_SOURCE, encoding="utf-8")
232
- settings_document = {
233
- HOOKS_KEY: {
234
- PRE_TOOL_USE_KEY: [
235
- {
236
- MATCHER_KEY: "Write",
237
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(deny_pii_hook_path)}],
238
- },
239
- {
240
- MATCHER_KEY: "Bash",
241
- HOOKS_KEY: [
242
- {COMMAND_KEY: quoted_command(deny_destructive_hook_path)}
243
- ],
244
- },
245
- ]
246
- }
247
- }
248
- settings_path = write_settings_file(tmp_path, settings_document)
249
- exit_code = probe.main(["--settings", str(settings_path)])
250
- assert exit_code == PROBE_SUCCESS_EXIT_CODE
251
-
252
-
253
- def test_main_exits_three_when_a_hook_allows(tmp_path: Path) -> None:
254
- probe = load_probe_module()
255
- allow_pii_hook_path = tmp_path / PII_HOOK_BASENAME
256
- allow_pii_hook_path.write_text(ALLOW_HOOK_SOURCE, encoding="utf-8")
257
- destructive_hook_path = HOOKS_BLOCKING_DIRECTORY / DESTRUCTIVE_HOOK_BASENAME
258
- settings_document = {
259
- HOOKS_KEY: {
260
- PRE_TOOL_USE_KEY: [
261
- {
262
- MATCHER_KEY: "Write",
263
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(allow_pii_hook_path)}],
264
- },
265
- {
266
- MATCHER_KEY: "Bash",
267
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(destructive_hook_path)}],
268
- },
269
- ]
270
- }
271
- }
272
- settings_path = write_settings_file(tmp_path, settings_document)
273
- exit_code = probe.main(["--settings", str(settings_path)])
274
- assert exit_code == PROBE_FAILURE_EXIT_CODE
275
-
276
-
277
- def test_main_exits_three_when_the_settings_file_is_absent(tmp_path: Path) -> None:
278
- probe = load_probe_module()
279
- absent_settings_path = tmp_path / "does-not-exist.json"
280
- exit_code = probe.main(["--settings", str(absent_settings_path)])
281
- assert exit_code == PROBE_FAILURE_EXIT_CODE
282
-
283
-
284
- def test_main_exits_three_when_the_settings_file_is_invalid_json(tmp_path: Path) -> None:
285
- probe = load_probe_module()
286
- settings_path = tmp_path / "sandbox-settings.json"
287
- settings_path.write_text("{not valid json", encoding="utf-8")
288
- exit_code = probe.main(["--settings", str(settings_path)])
289
- assert exit_code == PROBE_FAILURE_EXIT_CODE
290
-
291
-
292
- def test_main_exits_three_when_a_hook_script_is_bogus(tmp_path: Path) -> None:
293
- probe = load_probe_module()
294
- bogus_pii_hook_path = tmp_path / PII_HOOK_BASENAME
295
- destructive_hook_path = HOOKS_BLOCKING_DIRECTORY / DESTRUCTIVE_HOOK_BASENAME
296
- settings_document = {
297
- HOOKS_KEY: {
298
- PRE_TOOL_USE_KEY: [
299
- {
300
- MATCHER_KEY: "Write",
301
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(bogus_pii_hook_path)}],
302
- },
303
- {
304
- MATCHER_KEY: "Bash",
305
- HOOKS_KEY: [{COMMAND_KEY: quoted_command(destructive_hook_path)}],
306
- },
307
- ]
308
- }
309
- }
310
- settings_path = write_settings_file(tmp_path, settings_document)
311
- exit_code = probe.main(["--settings", str(settings_path)])
312
- assert exit_code == PROBE_FAILURE_EXIT_CODE
@@ -1,25 +0,0 @@
1
- # Promotion workflow (Phase 2)
2
-
3
- Turn a successful proof-of-concept into a real, verified change. Run every step in the normal, fully-hooked session — never inside the `--bare` sandbox. The sandbox produced a reference build; promotion re-verifies it to standard and often rewrites parts of it.
4
-
5
- ## Seed the task list first
6
-
7
- Register every item in `reference/promotion-tasks.md` as a session task (`TaskCreate`, or `TodoWrite` if that is the host tool). Work only from the task list. Mark each complete with evidence — a command result, a path, a review record, or a skill's return.
8
-
9
- ## The clean-room protocol
10
-
11
- The task seeds carry the full ordered detail. The shape:
12
-
13
- 1. **Confirm** the POC is worth promoting and the user wants it shipped.
14
- 2. **Fresh branch** off freshly-fetched `origin/main` via `fresh-branch` — clean history, based on live upstream.
15
- 3. **Bring content as an uncommitted diff.** Copy the POC's file changes into the new branch's working tree. Do not cherry-pick or merge the sandbox commits; the sandbox history stays behind.
16
- 4. **Cleanup.** Remove scratch files, debug dumps, and temp helpers the POC created (`cleanup-temp-files` rule).
17
- 5. **Privacy sweep** via `privacy-hygiene` over the diff.
18
- 6. **Review and verify** the real diff against the [review guide](../../skills-archived/reviews/SKILL.md#review-workflow). Record the checks run and repair every required finding.
19
- 7. **Commit and PR.** After the review and verification record is complete, commit by hand per the `git-workflow` rule, then open a draft PR.
20
- 8. **State the honest limitations** from `reference/honest-limitations.md` in the PR body or to the user.
21
- 9. **Converge** by handing the PR to `autoconverge` by default; use `pr-converge` for paced ticks or `bugteam` for an open-loop audit.
22
-
23
- ## Why the clean room, not a push
24
-
25
- `code_rules_enforcer` is a write-time Write/Edit gate. Content that lands through `git apply`, `git checkout`, or cherry-pick receives the clean-room controls in steps 4–6: cleanup, privacy review, and review and verification under the [review guide](../../skills-archived/reviews/SKILL.md#review-workflow). The promotion record states the checks run and the remaining TDD limitation.
@@ -1,35 +0,0 @@
1
- # Sandbox workflow (Phase 1)
2
-
3
- Stand up an isolated worktree where a hookless agent builds a proof-of-concept with zero standards friction. Only two safety gates stay live: personal-data blocking and destructive-command blocking.
4
-
5
- ## Step 1 — Isolated worktree
6
-
7
- Invoke the `fresh-branch` skill to create a worktree off `origin/main`. Keep the returned `worktree_path` and `base_commit` for the promotion phase. If `fresh-branch` is not installed, stop with the refusal line from `SKILL.md`.
8
-
9
- ## Step 2 — Minimal safety settings
10
-
11
- Run `scripts/build_sandbox_settings.py --out <worktree>/.prototype-sandbox-settings.json`.
12
-
13
- It reads the live `~/.claude/settings.json`, resolves each safety hook's command (the correct interpreter and absolute path for this machine), and registers it on the matchers the sandbox needs — personal-data on Write, Edit, MultiEdit, and Bash; destructive-command on Bash. The write file carries only those two gates, plus an `env` block that sets `CLAUDE_DESTRUCTIVE_DENY_MODE`, so the destructive gate hard-denies a match. A hard deny holds under `--dangerously-skip-permissions`; an `ask` there is auto-resolved.
14
-
15
- - Exit 0 → continue with the printed settings path.
16
- - Exit 2 → one of the two safety hooks could not be resolved from the live settings. Stop; the sandbox cannot be contained without both. Report which one is missing.
17
-
18
- ## Step 3 — Prove containment
19
-
20
- Run `scripts/probe_sandbox_safety.py --settings <settings path>`.
21
-
22
- It feeds each safety hook a payload the hook is proven to block and confirms a hard-deny decision — the block that holds even under `--dangerously-skip-permissions`, unlike an `ask` prompt the flag auto-resolves. It runs each hook under the settings' `env` block, so the destructive gate runs in deny mode, the same way the launched session runs it.
23
-
24
- - Exit 0 → both gates hard-deny their probe; the sandbox is contained.
25
- - Exit 3 → a gate allowed its probe, returned an `ask`, or errored. Stop; do not launch an uncontained sandbox. This is a runtime check, not a code read (verify-runtime-state) — do not skip it.
26
-
27
- ## Step 4 — Launch the hookless session
28
-
29
- Run `scripts/launch_sandbox.py --worktree <worktree_path> --settings <settings path> --task-file <task file>`.
30
-
31
- It starts a headless `claude -p --bare --dangerously-skip-permissions --settings <settings path>` session in the worktree, so every standards gate is skipped and the two safety gates from the settings file are the only containment. Write the proof-of-concept task to the task file first; the sandbox agent cannot invoke other skills, so the task must be self-contained.
32
-
33
- ## Step 5 — Judge the result
34
-
35
- Read what the sandbox built and decide whether the proof-of-concept proves the idea. On success, move to `promotion.md`. To discard, remove the worktree with `git worktree remove --force <worktree_path>`.
@@ -1 +0,0 @@
1
- @../AGENTS.md
@@ -1 +0,0 @@
1
-
@@ -1,178 +0,0 @@
1
- ---
2
- name: rebase
3
- description: >-
4
- Rebases a branch onto its base ref with the verification gates that catch
5
- logically broken results before pushing. Use when the user invokes `/rebase`,
6
- says 'rebase this branch', 'PR has merge conflicts', or 'rebase onto main', or
7
- asks for a force-push to update a remote branch's history.
8
- ---
9
-
10
- # /rebase
11
-
12
- Rebase the current branch (or a named branch's worktree) onto its correct base ref. Resolve conflicts. Verify the result is **logically correct**, not just textually clean. Push only after explicit authorization.
13
-
14
- The default failure mode is shipping a rebase that compiled but doesn't run. This skill exists to prevent that.
15
-
16
- ## When to rebase vs. merge
17
-
18
- > **Decision thresholds**
19
- >
20
- > | Threshold | Value |
21
- > |---|---|
22
- > | Maximum commits for solo rebase | 5 |
23
- > | Divergence age that triggers merge-instead | 2 weeks |
24
-
25
- **Default to rebase** when:
26
-
27
- - Solo branch (you are the only author of the commits being rebased).
28
- - 1–5 commits ahead of base (see Decision thresholds above).
29
- - Stacked PR whose base just merged via squash.
30
-
31
- **Default to merge** when:
32
-
33
- - Branch has multiple authors (force-push would clobber their state).
34
- - More than 5 commits or more than 2 weeks of divergence (see Decision thresholds above; rebase complexity grows non-linearly).
35
- - The user said "merge", not "rebase".
36
- - Open PR with approving reviews already on the current SHA (force-push invalidates them).
37
-
38
- When in doubt, ask. Both work; the choice affects history shape, not correctness.
39
-
40
- ## Phase 1 — Pre-rebase analysis
41
-
42
- 1. **Resolve the canonical base.** Stacked-PR base refs change when the base PR merges. Always re-resolve:
43
-
44
- ```
45
- gh pr view <N> --json baseRefName,mergeable,mergeStateStatus
46
- ```
47
-
48
- Trust GitHub's `baseRefName`, not whatever the local branch was originally based on.
49
-
50
- 2. **Identify the rebase scenario.** Three playbooks:
51
-
52
- | Scenario | Signal | Approach |
53
- |---|---|---|
54
- | Stacked PR, base merged via squash | base PR `state: MERGED`, base ref redirected to main | Rebase onto main; expect to `--skip` the squash-absorbed commit |
55
- | Stacked PR, base still open | base PR `state: OPEN` | Rebase onto base PR's tip, not main |
56
- | Long-lived feature branch | many commits, no stacking | Straight `rebase origin/main` |
57
-
58
- 3. **Fetch fresh.** `git fetch origin <base-ref> <head-ref>` before starting. Stale local refs cause false conflicts.
59
-
60
- 4. **Read every rebased commit's message.** Author intent lives in commit messages ("removes orphan constants X, Y, Z"). For every named symbol mentioned as deleted or renamed, scan `origin/main` for new consumers — if main has new uses of those symbols, the rebase will produce broken state without conflicting at the textual level.
61
-
62
- **Tool preference for symbol scans** (in order):
63
-
64
- | Tool | Use when | Example |
65
- |---|---|---|
66
- | `mcp__serena__find_symbol` / `find_referencing_symbols` | Symbol-aware language server is available — definition vs. reference distinction matters, and you want call-site context | `find_referencing_symbols(symbol_name)` returns every caller with file/line and surrounding code |
67
- | `Grep` tool (ripgrep) | Local single-repo plain-text scan; no symbol awareness needed | `Grep(pattern, type="py")` — much faster than shell `grep` and respects `.gitignore` |
68
- | `grep -rn` | Last resort; only when the above are unavailable | — |
69
-
70
- The Grep tool is the default for plain-text scans (faster than shell grep, respects gitignore). Reach for serena when you need to distinguish "this name is defined here" from "this name is referenced here," which catches false positives from comments, docstrings, and string literals.
71
-
72
- This is the bug that hides best. Don't skip it.
73
-
74
- ## Phase 2 — During rebase
75
-
76
- 5. **`--skip` only after verifying content overlap.** When a commit fails to apply because main already has its content (squash-merge case), confirm the content is actually equivalent:
77
-
78
- ```
79
- git diff <skipped-commit> origin/<base> -- <files-touched-by-skipped-commit>
80
- ```
81
-
82
- Skip only after that diff shows the equivalent content lives in main. Don't skip on the heuristic "main is downstream."
83
-
84
- 6. **Audit auto-merged files.** Files that git merged without conflict markers are not automatically correct. After each commit applies, run:
85
-
86
- ```
87
- git diff --name-only --diff-filter=M ORIG_HEAD
88
- ```
89
-
90
- Use `ORIG_HEAD`, which git sets at rebase start; the reflog index `HEAD@{1}` shifts as each rebase step runs and is unreliable mid-rebase. For each modified file with no conflict markers, eyeball the changes — auto-merge can produce duplicate blocks (when both sides added similar content) or silently drop content (when both sides removed adjacent lines). Pay extra attention to `config/`, `constants.*`, and `__init__.py` files where additions often sit near each other.
91
-
92
- 7. **At every conflict, take both sides' intent seriously.** Read both, then decide based on the post-rebase logical state. Do not reflex-pick HEAD or `origin/main`. Document the resolution reasoning in the commit message if it is non-obvious.
93
-
94
- ## Phase 3 — Verification gates (mandatory before push)
95
-
96
- `py_compile`, `tsc --noEmit`, `cargo check`, etc. validate **syntax and types**, not **import resolution and runtime correctness**. Run real checks.
97
-
98
- Before each gate command, state in one line which gate it is and why it applies to this rebase ("post-rebase gate: `pkg_x` carried a conflict resolution, running its suite").
99
-
100
- 8. **Real import check.** For Python:
101
-
102
- ```
103
- python -m compileall -q <package>
104
- ```
105
-
106
- Follow immediately with the test-collection step below. `compileall` catches import-time failures across every module file; combined with `--collect-only` it surfaces `NameError`, `AttributeError`, and `ImportError` cases that a syntax-only check misses.
107
-
108
- 9. **Test collection.** `pytest --collect-only -q` on the changed packages catches NameError, AttributeError, and ImportError surfaces beyond plain imports.
109
-
110
- 10. **Targeted test run — scoped by content diff.** First check, per candidate package, whether the rebase changed its content at all:
111
-
112
- ```
113
- git diff <pre-rebase-tip> HEAD -- <package>
114
- ```
115
-
116
- - **Empty diff:** the package's files are byte-for-byte what the branch already carried before the rebase, and that state was verified pre-rebase. The compile and collect-only gates (steps 8–9) cover the remaining import-level risk; skip the package's full suite.
117
- - **Non-empty diff, a conflict resolution, or an auto-merged file (step 6) in the package:** run its full suite. Do not push a rebase that dropped or broke test coverage that was passing pre-rebase.
118
-
119
- Capture the pre-rebase tip SHA before the rebase begins; step 15 pins the force-with-lease to that same SHA.
120
-
121
- 11. **Reference scan for removals/renames.** For every symbol the rebase deleted or renamed (per the commit messages from step 4), scan the post-rebase tree using the same tool-preference order as step 4:
122
-
123
- - **Preferred:** `mcp__serena__find_referencing_symbols` (symbol-aware; ignores false matches in comments and string literals).
124
- - **Then:** the `Grep` tool (e.g., `Grep(pattern="<symbol>", type="py")`) for fast in-repo scans.
125
- - **Last resort:** `grep -rn "<symbol>" .` (let ripgrep defaults and `.gitignore` handle scoping)
126
-
127
- Any reference outside the rebased commits' own changes is a stale reference. Either update it (with user authorization) or surface it and refuse to push.
128
-
129
- 12. **"Unchanged" files are not safe.** A rebase can break files it never textually modified if their imports depend on something the rebase removed or renamed. List `git diff --name-only origin/<base>..HEAD`, then for every file NOT in that list but that imports from a file IN that list, manually verify the imports still resolve.
130
-
131
- ## Phase 4 — Push
132
-
133
- 13. **Force-push requires explicit authorization.** Auto mode does not bypass this. Before any `git push --force` or `--force-with-lease`:
134
-
135
- - State the rewrite scope: "this rewrites N commits of remote history on branch `<name>`".
136
- - State the branch's PR state: "PR #M is OPEN with K approving reviews on the current SHA" (force-push invalidates approvals).
137
- - Ask for explicit authorization.
138
- - If denied: leave the rebase result locally, report merge-instead as the alternative, stop.
139
-
140
- 14. **Refuse to force-push** `main`, `master`, `release/*`, `production`, or any branch with more than one unique author. Count unique authors in a cross-platform way: `git log --format='%ae' origin/<branch> | python -c "import sys; print(len(set(sys.stdin)))"`. This form works on both Windows (PowerShell) and Unix without shell pipeline extensions. Surface the refusal; do not ask for authorization on these.
141
-
142
- 15. **Always `--force-with-lease=<branch>:<sha>`**, never bare `--force`. Pin the lease to the SHA you started from so concurrent pushes are detected as a lease mismatch instead of clobbered.
143
-
144
- 16. **Confirm mergeability** post-push:
145
-
146
- ```
147
- gh pr view <N> --json mergeable,mergeStateStatus,headRefOid
148
- ```
149
-
150
- Expect `mergeable: MERGEABLE`, `mergeStateStatus: CLEAN`. Anything else means the rebase didn't actually unblock the PR — investigate before declaring done.
151
-
152
- ## Anti-patterns (the failure modes this skill prevents)
153
-
154
- - **`py_compile` exit 0 → "verified"**. Wrong. Syntax-clean is not import-clean. Always run a real `import` check.
155
- - **Skipping squash-absorbed commits without diff verification.** Heuristically usually right, occasionally wrong, never confirmed without the diff.
156
- - **Auditing only `git diff --name-only`.** Files unchanged by the rebase can still break if their imports depended on what the rebase removed.
157
- - **Force-pushing under "the user asked me to fix the conflicts" interpretation.** Force-push is a separate authorization from "fix this." Ask.
158
- - **Bare `--force` instead of `--force-with-lease=<branch>:<sha>`.** Loses the safety net against concurrent pushes.
159
- - **Running full suites for packages the rebase left byte-for-byte the same.** The step-10 content diff settles it in seconds; a long suite on unchanged content stalls the session.
160
-
161
- ## Quick decision flowchart
162
-
163
- ```
164
- Branch shared with others? ──► merge instead
165
- Stacked PR, base merged? ──► rebase onto main, expect --skip
166
- Stacked PR, base open? ──► rebase onto base PR tip
167
- Solo, ≤5 commits ahead? ──► straight rebase
168
-
169
- After rebase, BEFORE push:
170
- python -c "import …" ──► must succeed
171
- pytest --collect-only ──► must succeed
172
- pytest, packages w/ diff ──► must pass
173
- symbol scan (serena → Grep) ──► no stale references
174
-
175
- Push:
176
- not main/master/release ──► force-with-lease, ask first
177
- main/master/release ──► refuse
178
- ```
@@ -1,51 +0,0 @@
1
- ---
2
- name: review-router
3
- description: >-
4
- Resolve and arm one supported `route_review_config` route through the registered Agent|Task gate. Triggers: /review-router and guarded reviewer spawn.
5
- ---
6
-
7
- # Review Router
8
-
9
- Resolve and arm the supported `e-simplify` route. The registered `PreToolUse Agent|Task` hook enforces the exact armed spawn payload.
10
-
11
- ## When this applies
12
-
13
- Use for `/review-router` and route execution after `/review-tier`. Return `UNSUPPORTED_ROUTE` for `e-code-review`; preserve `/e-code-review` behavior.
14
-
15
- ## Operations
16
-
17
- 1. Register `reference/task-seeds.md` with the host task tool.
18
- 2. Call `scripts/review_router_cli.py resolve` for the current `route_policy_hash` decision and optional tier override.
19
- 3. Call `arm` for the exact selected slot and dispatch the returned Agent|Task payload.
20
- 4. Let the registered hook enforce the payload, then call `close`.
21
-
22
- The route topology is fixed: T1 uses one Luna High slot, T2 uses one Luna Max slot, and T3 uses six ordered Luna High slots.
23
-
24
- ## Composition
25
-
26
- | Peer | When | Produces | Missing behavior |
27
- |---|---|---|---|
28
- | `/review-tier` | Before routing | Current tier decision | Return the route request to `/review-tier`. |
29
- | `/e-simplify` | When cleanup review is requested | Cleanup review request | Return `UNSUPPORTED_ROUTE`. |
30
-
31
- ## File index
32
-
33
- | File | Purpose |
34
- |---|---|
35
- | `SKILL.md` | Route contract and operations |
36
- | `reference/route-policy.json` | Supported route topology |
37
- | `reference/task-seeds.md` | Current route task seeds |
38
- | `scripts/review_router.py` | `route_policy_hash` input and route resolution |
39
- | `scripts/review_router_cli.py` | Resolve, arm, and close operations |
40
- | `scripts/test_review_router.py` | Route policy tests |
41
- | `scripts/test_review_router_cli.py` | CLI rejection tests |
42
- | `scripts/test_review_router_integration.py` | CLI and registered-hook tests |
43
- | `scripts/review_router_constants/config/constants.py` | Portable route constants |
44
- | `scripts/review_router_constants/config/__init__.py` | Runtime configuration package |
45
- | `scripts/review_router_constants/__init__.py` | Constants package |
46
- | `scripts/conftest.py` | Test import setup |
47
-
48
- ## Folder map
49
-
50
- - `reference/` — route policy and task seeds.
51
- - `scripts/` — route resolution, CLI operations, and tests.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 1,
3
- "routes": {
4
- "e-simplify": {"status": "SUPPORTED", "skill": "e-simplify", "tiers": ["T1", "T2", "T3"], "models": {"T1": {"role": "executor", "model": "gpt-5.6-luna", "effort": "high", "pass_ids": ["simplify-01"]}, "T2": {"role": "executor", "model": "gpt-5.6-luna", "effort": "max", "pass_ids": ["simplify-01"]}, "T3": {"role": "executor", "model": "gpt-5.6-luna", "effort": "high", "pass_ids": ["simplify-01", "simplify-02", "simplify-03", "simplify-04", "simplify-05", "simplify-06"]}}},
5
- "e-code-review": {"status": "UNSUPPORTED_ROUTE", "skill": "e-code-review", "tiers": []}
6
- }
7
- }
@@ -1 +0,0 @@
1
- Register resolve e-simplify, apply override, arm exact slot, enforce through the registered Agent|Task hook, close the decision, and report unsupported e-code-review as host tasks. Complete each with command output or the current decision/armed record.
@@ -1,4 +0,0 @@
1
- from pathlib import Path
2
- import sys
3
-
4
- sys.path.insert(0, str(Path(__file__).resolve().parent))