claude-dev-env 4.3.0 → 7.1.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 (480) 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 +35 -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 +35 -3
  18. package/.agents/skills/session-continuity/README.md +189 -0
  19. package/.agents/skills/session-continuity/SKILL.md +114 -0
  20. package/.agents/skills/session-continuity/continuity.mjs +375 -0
  21. package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
  22. package/.agents/skills/skill-builder/SKILL.md +3 -196
  23. package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
  24. package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
  25. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  26. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  27. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  28. package/bin/cde.mjs +36 -8
  29. package/bin/cde.test.mjs +48 -0
  30. package/bin/ever-shipped-skills.mjs +2 -20
  31. package/bin/ever-shipped-skills.test.mjs +8 -0
  32. package/bin/expand_home_directory_tokens.mjs +4 -5
  33. package/bin/expand_home_directory_tokens.test.mjs +128 -0
  34. package/bin/git_hooks_installer.mjs +22 -3
  35. package/bin/git_hooks_installer.test.mjs +159 -5
  36. package/bin/install-session-continuity.mjs +78 -0
  37. package/bin/install-session-continuity.test.mjs +42 -0
  38. package/bin/install.agents-home.test.mjs +15 -13
  39. package/bin/install.codex-rules.test.mjs +5 -2
  40. package/bin/install.cursor-rules.test.mjs +5 -2
  41. package/bin/install.mjs +506 -63
  42. package/bin/install.policy-lint.test.mjs +130 -0
  43. package/bin/install.profiles.test.mjs +10 -0
  44. package/bin/install.prune.test.mjs +286 -37
  45. package/bin/install.pstack-plugin.test.mjs +114 -0
  46. package/bin/install.test.mjs +537 -120
  47. package/bin/install.transaction.test.mjs +3 -3
  48. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  49. package/docs/CODE_RULES.md +1 -1
  50. package/hooks/advisory/pr_done_reminder.py +342 -0
  51. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  52. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  53. package/hooks/blocking/code_rules_banned_identifiers.py +3 -0
  54. package/hooks/blocking/code_rules_paired_test.py +22 -15
  55. package/hooks/blocking/precommit_code_rules_gate.py +5 -8
  56. package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
  57. package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
  58. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
  59. package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
  60. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  61. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  62. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  63. package/hooks/blocking/test_pre_tool_use_dispatcher.py +43 -342
  64. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  65. package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
  66. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  67. package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
  68. package/hooks/git-hooks/post_commit.py +33 -0
  69. package/hooks/git-hooks/pre_commit.py +18 -49
  70. package/hooks/git-hooks/pre_push.py +45 -541
  71. package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
  72. package/hooks/git-hooks/test_native_hook_support.py +129 -0
  73. package/hooks/git-hooks/test_native_policy_commit.py +120 -0
  74. package/hooks/git-hooks/test_post_commit.py +43 -0
  75. package/hooks/git-hooks/test_pre_commit.py +38 -148
  76. package/hooks/git-hooks/test_pre_push.py +48 -1631
  77. package/hooks/git-hooks/test_verification_notice.py +60 -0
  78. package/hooks/git-hooks/test_verification_start.py +173 -0
  79. package/hooks/git-hooks/verification_notice.py +192 -0
  80. package/hooks/git-hooks/verification_notice_context.py +253 -0
  81. package/hooks/git-hooks/verification_notice_state.py +237 -0
  82. package/hooks/git-hooks/verification_start.py +100 -0
  83. package/hooks/hooks.json +1 -120
  84. package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
  85. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
  86. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
  87. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
  88. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  89. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
  90. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
  91. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
  92. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
  93. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  94. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
  95. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
  96. package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
  97. package/hooks/validators/run_all_validators.py +5 -1
  98. package/hooks/validators/security_checks.py +57 -2
  99. package/hooks/validators/test_hook_timing_harness.py +2 -5
  100. package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
  101. package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
  102. package/hooks/validators/test_security_checks.py +57 -0
  103. package/package.json +2 -2
  104. package/rules/confirm-implementation-forks.md +2 -0
  105. package/rules/durable-post-artifacts.md +2 -1
  106. package/rules/git-workflow.md +18 -6
  107. package/rules/pstack-host-mapping.md +48 -0
  108. package/rules/vault-context.md +3 -5
  109. package/rules/verify-runtime-state.md +7 -0
  110. package/scripts/audit-hooks-cli.mjs +5 -0
  111. package/scripts/audit-hooks.mjs +72 -16
  112. package/scripts/automatic_advisory/__init__.py +1 -0
  113. package/scripts/automatic_advisory/checkout.py +51 -0
  114. package/scripts/automatic_advisory/cli.py +334 -0
  115. package/scripts/automatic_advisory/config/__init__.py +1 -0
  116. package/scripts/automatic_advisory/config/constants.py +93 -0
  117. package/scripts/automatic_advisory/config/timing.py +4 -0
  118. package/scripts/automatic_advisory/configuration.py +197 -0
  119. package/scripts/automatic_advisory/execution.py +350 -0
  120. package/scripts/automatic_advisory/git.py +69 -0
  121. package/scripts/automatic_advisory/model.py +107 -0
  122. package/scripts/automatic_advisory/process_host.py +32 -0
  123. package/scripts/automatic_advisory/publisher.py +84 -0
  124. package/scripts/automatic_advisory/runner.py +399 -0
  125. package/scripts/automatic_advisory/state.py +116 -0
  126. package/scripts/automatic_advisory/window_flags.py +41 -0
  127. package/scripts/automatic_advisory/windows_job.py +122 -0
  128. package/scripts/check.ps1 +0 -1
  129. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  130. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  131. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  132. package/scripts/codex_compat_materializer.py +99 -13
  133. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  134. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
  135. package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
  136. package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
  137. package/scripts/local_report_cli.py +184 -0
  138. package/scripts/local_report_core.py +247 -0
  139. package/scripts/local_report_publisher.py +12 -0
  140. package/scripts/local_report_validation.py +357 -0
  141. package/scripts/local_verification/__init__.py +23 -0
  142. package/scripts/local_verification/check_runner.py +364 -0
  143. package/scripts/local_verification/check_support.py +99 -0
  144. package/scripts/local_verification/cli.py +158 -0
  145. package/scripts/local_verification/command_runner.py +84 -0
  146. package/scripts/local_verification/config/__init__.py +1 -0
  147. package/scripts/local_verification/config/constants.py +89 -0
  148. package/scripts/local_verification/config/timing.py +1 -0
  149. package/scripts/local_verification/git_state.py +146 -0
  150. package/scripts/local_verification/manifest.py +224 -0
  151. package/scripts/local_verification/model.py +174 -0
  152. package/scripts/local_verification/runner.py +234 -0
  153. package/scripts/policy_lint/adapter_detectors.py +13 -6
  154. package/scripts/policy_lint/adapter_pairing.py +58 -3
  155. package/scripts/policy_lint/adapters.py +7 -4
  156. package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
  157. package/scripts/policy_lint/config/constants.py +5 -0
  158. package/scripts/policy_lint/engine.py +48 -4
  159. package/scripts/policy_lint/model.py +1 -0
  160. package/scripts/policy_lint/registry.py +1 -1
  161. package/scripts/policy_lint/selection.py +2 -1
  162. package/scripts/policy_lint/selection_git.py +2 -0
  163. package/scripts/pr_verification/__init__.py +1 -0
  164. package/scripts/pr_verification/branch_refs.py +114 -0
  165. package/scripts/pr_verification/config/__init__.py +1 -0
  166. package/scripts/pr_verification/config/constants.py +84 -0
  167. package/scripts/pr_verification/config/timing.py +5 -0
  168. package/scripts/pr_verification/github.py +137 -0
  169. package/scripts/pr_verification/github_api.py +376 -0
  170. package/scripts/pr_verification/github_labels.py +88 -0
  171. package/scripts/pr_verification/github_parsing.py +182 -0
  172. package/scripts/pr_verification/github_transport.py +91 -0
  173. package/scripts/pr_verification/lock.py +122 -0
  174. package/scripts/pr_verification/model.py +43 -0
  175. package/scripts/pr_verification/requirements.txt +1 -0
  176. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  177. package/scripts/shared_tree_paths.py +32 -3
  178. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
  179. package/scripts/test_shared_tree_paths.py +33 -0
  180. package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
  181. package/scripts/tests/test-audit-hooks.mjs +94 -2
  182. package/scripts/tests/test_automatic_advisory.py +376 -0
  183. package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
  184. package/scripts/tests/test_automatic_advisory_polling.py +216 -0
  185. package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
  186. package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
  187. package/scripts/tests/test_automatic_advisory_settings.py +48 -0
  188. package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
  189. package/scripts/tests/test_closed_pr_label.py +157 -0
  190. package/scripts/tests/test_codex_compat_materializer.py +189 -6
  191. package/scripts/tests/test_github_labels.py +101 -0
  192. package/scripts/tests/test_github_transport.py +125 -0
  193. package/scripts/tests/test_local_report_publisher.py +396 -0
  194. package/scripts/tests/test_local_report_publisher_cli.py +85 -0
  195. package/scripts/tests/test_local_verification.py +348 -0
  196. package/scripts/tests/test_local_verification_cli.py +98 -0
  197. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  198. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  199. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  200. package/scripts/tests/test_policy_lint_rules_pairing.py +163 -0
  201. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  202. package/scripts/tests/test_policy_lint_selection.py +25 -2
  203. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  204. package/scripts/tests/test_pr_verification_github.py +392 -0
  205. package/scripts/tests/test_pr_verification_lock.py +168 -0
  206. package/scripts/tests/test_rules.py +3 -7
  207. package/scripts/tests/test_verification_notice.py +347 -0
  208. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  209. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  210. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  211. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  212. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  213. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  214. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  215. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  216. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  217. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  218. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  219. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  220. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  221. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  222. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  223. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  224. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  225. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  226. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  227. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  228. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  229. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  230. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  231. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  232. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  233. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  234. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  235. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  236. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  237. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  238. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  239. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  240. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  241. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  242. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  243. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  244. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  245. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  246. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  247. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  248. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  249. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  250. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  251. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  252. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  253. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  254. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  255. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  256. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  257. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  258. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  259. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  260. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  261. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  262. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  263. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  264. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  265. package/.agents/skills/autoconverge/SKILL.md +0 -431
  266. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  267. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  268. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  269. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  270. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  271. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  272. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  273. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  274. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  275. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  276. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  277. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  278. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  279. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  280. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  281. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  282. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  283. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  284. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  285. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  286. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  287. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  288. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  289. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  290. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  291. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  292. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  293. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  294. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  295. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  296. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  297. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  298. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  299. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  300. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  301. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  302. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  303. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  304. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  305. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  306. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  307. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  308. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  309. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  310. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  311. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  312. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  313. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  314. package/.agents/skills/hitl/SKILL.md +0 -45
  315. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  316. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  317. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  318. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  319. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  320. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  321. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  322. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  323. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  324. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  325. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  326. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  327. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  328. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  329. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  330. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  331. package/.agents/skills/prototype/SKILL.md +0 -85
  332. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  333. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  334. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  335. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  336. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  337. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  338. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  339. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  340. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  341. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  342. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  343. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  344. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  345. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  346. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  347. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  348. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  349. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  350. package/.agents/skills/rebase/AGENTS.md +0 -1
  351. package/.agents/skills/rebase/SKILL.md +0 -178
  352. package/.agents/skills/review-router/SKILL.md +0 -51
  353. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  354. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  355. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  356. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  357. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  358. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  359. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  360. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  361. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  362. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  363. package/.agents/skills/review-tier/SKILL.md +0 -56
  364. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  365. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  366. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  367. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  368. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  369. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  370. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  371. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  372. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  373. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  374. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  375. package/.agents/skills/session-log/AGENTS.md +0 -1
  376. package/.agents/skills/session-log/SKILL.md +0 -170
  377. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  378. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  379. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  380. package/.agents/skills/session-tidy/SKILL.md +0 -191
  381. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  382. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  383. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  384. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  385. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  386. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  387. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  388. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  389. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  390. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  391. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  392. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  393. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  394. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  395. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  396. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  397. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  398. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  399. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  400. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  401. package/.agents/skills/update/AGENTS.md +0 -1
  402. package/.agents/skills/update/SKILL.md +0 -190
  403. package/_shared/pr-loop/AGENTS.md +0 -1
  404. package/_shared/pr-loop/audit-contract.md +0 -183
  405. package/_shared/pr-loop/audit-reply-template.md +0 -151
  406. package/_shared/pr-loop/code-rules-gate.md +0 -65
  407. package/_shared/pr-loop/fix-protocol.md +0 -60
  408. package/_shared/pr-loop/gh-payloads.md +0 -75
  409. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  410. package/_shared/pr-loop/precatch-rubric.md +0 -66
  411. package/_shared/pr-loop/preflight-proposal.md +0 -56
  412. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  413. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  414. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  415. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  416. package/_shared/pr-loop/state-schema.md +0 -45
  417. package/_shared/pr-loop/worker-spawn.md +0 -189
  418. package/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
  419. package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
  420. package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
  421. package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
  422. package/hooks/blocking/destructive_command_blocker.py +0 -2073
  423. package/hooks/blocking/fable_spawn_gate.py +0 -187
  424. package/hooks/blocking/luna_fast_mode_gate.py +0 -160
  425. package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
  426. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
  427. package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
  428. package/hooks/blocking/pii_prevention_blocker.py +0 -365
  429. package/hooks/blocking/piped_pytest_blocker.py +0 -1223
  430. package/hooks/blocking/question_to_user_enforcer.py +0 -130
  431. package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
  432. package/hooks/blocking/sensitive_file_protector.py +0 -167
  433. package/hooks/blocking/session_edit_stage_gate.py +0 -684
  434. package/hooks/blocking/session_handoff_blocker.py +0 -182
  435. package/hooks/blocking/shell_substitution_blocker.py +0 -350
  436. package/hooks/blocking/test_ask_user_question_shape.py +0 -69
  437. package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
  438. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
  439. package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
  440. package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
  441. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
  442. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
  443. package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
  444. package/hooks/blocking/test_fable_spawn_gate.py +0 -381
  445. package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
  446. package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
  447. package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
  448. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
  449. package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
  450. package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
  451. package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
  452. package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
  453. package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
  454. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
  455. package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
  456. package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
  457. package/hooks/blocking/test_sensitive_file_protector.py +0 -365
  458. package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
  459. package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
  460. package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
  461. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
  462. package/hooks/blocking/test_session_handoff_blocker.py +0 -318
  463. package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
  464. package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
  465. package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
  466. package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
  467. package/hooks/blocking/unscoped_search_blocker.py +0 -391
  468. package/hooks/blocking/write_existing_file_blocker.py +0 -124
  469. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
  470. package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
  471. package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
  472. package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
  473. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
  474. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
  475. package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
  476. package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
  477. package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
  478. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
  479. /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
  480. /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
@@ -0,0 +1,347 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ import os
6
+ import subprocess
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ HOOKS_DIRECTORY = Path(__file__).resolve().parents[2] / "hooks" / "git-hooks"
11
+ NOTICE_SCRIPT = HOOKS_DIRECTORY / "verification_notice.py"
12
+ ALL_REMOTE_URLS = (
13
+ "https://github.com/JonEcho/python-automation.git",
14
+ "git@github.com:JonEcho/python-automation.git",
15
+ "ssh://git@github.com/JonEcho/python-automation.git",
16
+ )
17
+
18
+
19
+ def run_notice(
20
+ repository_path: Path,
21
+ event_name: str = "commit",
22
+ ) -> subprocess.CompletedProcess[str]:
23
+ return subprocess.run(
24
+ [
25
+ sys.executable,
26
+ str(NOTICE_SCRIPT),
27
+ "--event",
28
+ event_name,
29
+ "--repo",
30
+ str(repository_path),
31
+ ],
32
+ check=False,
33
+ capture_output=True,
34
+ text=True,
35
+ encoding="utf-8",
36
+ env={**os.environ, "PYTHONIOENCODING": "utf-8"},
37
+ )
38
+
39
+
40
+ def create_target_repository(
41
+ temporary_directory: Path,
42
+ remote_url: str,
43
+ ) -> tuple[Path, str]:
44
+ repository_path = temporary_directory / "Jon Echo project with spaces Ω"
45
+ repository_path.mkdir(parents=True)
46
+ run_git(repository_path, "init", "--quiet")
47
+ run_git(repository_path, "config", "user.email", "test@example.invalid")
48
+ run_git(repository_path, "config", "user.name", "Verification Test")
49
+ (repository_path / "README.md").write_text("check\n", encoding="utf-8")
50
+ run_git(repository_path, "add", "README.md")
51
+ run_git(repository_path, "commit", "--quiet", "-m", "initial")
52
+ run_git(repository_path, "remote", "add", "origin", remote_url)
53
+ current_head = run_git(repository_path, "rev-parse", "HEAD").stdout.strip()
54
+ return repository_path, current_head
55
+
56
+
57
+ def run_git(
58
+ repository_path: Path,
59
+ *arguments: str,
60
+ ) -> subprocess.CompletedProcess[str]:
61
+ return subprocess.run(
62
+ ["git", *arguments],
63
+ cwd=repository_path,
64
+ check=True,
65
+ capture_output=True,
66
+ text=True,
67
+ encoding="utf-8",
68
+ )
69
+
70
+
71
+ def write_report(
72
+ repository_path: Path,
73
+ report_fields: dict[str, object],
74
+ ) -> None:
75
+ manifest_path = repository_path / "config" / "local-verification.json"
76
+ manifest_path.parent.mkdir(exist_ok=True)
77
+ manifest_mapping = {
78
+ "version": 1,
79
+ "checks": [
80
+ {
81
+ "id": "smoke",
82
+ "argv": ["python", "-c", "pass"],
83
+ "cwd": ".",
84
+ "timeout_seconds": 1.0,
85
+ "minimum_tests": None,
86
+ }
87
+ ],
88
+ "exclusions": [],
89
+ }
90
+ manifest_path.write_text(json.dumps(manifest_mapping), encoding="utf-8")
91
+ report_path = repository_path / ".git" / "local-verification" / "report.json"
92
+ report_path.parent.mkdir(exist_ok=True)
93
+ all_report_fields = {
94
+ "selection": {"selected_manifest_path": "config/local-verification.json"},
95
+ "manifest_digest": hashlib.sha256(
96
+ json.dumps(manifest_mapping, sort_keys=True, separators=(",", ":")).encode()
97
+ ).hexdigest(),
98
+ **report_fields,
99
+ }
100
+ report_path.write_text(json.dumps(all_report_fields), encoding="utf-8")
101
+
102
+
103
+ def write_passing_report(repository_path: Path) -> str:
104
+ write_report(repository_path, {})
105
+ run_git(repository_path, "add", "config/local-verification.json")
106
+ run_git(repository_path, "commit", "--quiet", "-m", "manifest")
107
+ current_head = run_git(repository_path, "rev-parse", "HEAD").stdout.strip()
108
+ run_git(repository_path, "update-ref", "refs/remotes/origin/main", current_head)
109
+ write_report(
110
+ repository_path,
111
+ {
112
+ "head": current_head,
113
+ "base": current_head,
114
+ "worktree_clean": True,
115
+ "inputs_unchanged": True,
116
+ "publishable": True,
117
+ "status": "passed",
118
+ "aggregate": {
119
+ "status": "passed",
120
+ "total": 1,
121
+ "passed": 1,
122
+ "failed": 0,
123
+ "incomplete": 0,
124
+ "exit_code": 0,
125
+ },
126
+ },
127
+ )
128
+ return current_head
129
+
130
+
131
+ def write_worktree_passing_report(
132
+ repository_path: Path,
133
+ linked_git_directory: Path,
134
+ ) -> str:
135
+ current_head = run_git(repository_path, "rev-parse", "HEAD").stdout.strip()
136
+ source_manifest_path = repository_path / "config" / "local-verification.json"
137
+ source_report_path = repository_path / ".git" / "local-verification" / "report.json"
138
+ metadata_directory = linked_git_directory / "local-verification"
139
+ metadata_directory.mkdir(parents=True, exist_ok=True)
140
+ metadata_manifest_path = metadata_directory / "local-verification.json"
141
+ metadata_manifest_path.write_bytes(source_manifest_path.read_bytes())
142
+ all_report_fields = json.loads(source_report_path.read_text(encoding="utf-8"))
143
+ all_report_fields["selection"]["selected_manifest_path"] = str(
144
+ metadata_manifest_path
145
+ )
146
+ metadata_report_path = metadata_directory / "report.json"
147
+ metadata_report_path.write_text(json.dumps(all_report_fields), encoding="utf-8")
148
+ return current_head
149
+
150
+
151
+ def test_notice_matches_remote_formats_and_quotes_paths(tmp_path: Path) -> None:
152
+ for each_index, each_remote_url in enumerate(ALL_REMOTE_URLS):
153
+ repository_path, current_head = create_target_repository(
154
+ tmp_path / str(each_index), each_remote_url
155
+ )
156
+ completed_notice = run_notice(repository_path, "push")
157
+ assert completed_notice.returncode == 0
158
+ assert "LOCAL VERIFICATION ADVISORY" in completed_notice.stdout
159
+ assert f"Current SHA: {current_head}" in completed_notice.stdout
160
+ assert "State: pending" in completed_notice.stdout
161
+ assert "python '" in completed_notice.stdout
162
+ wrapper_suffix = str(Path(".github") / "ci" / "local_verify.py")
163
+ assert f"{wrapper_suffix}' --base origin/main" in completed_notice.stdout
164
+ assert "--executor '" in completed_notice.stdout
165
+ assert "--output '" in completed_notice.stdout
166
+ assert repository_path.name in completed_notice.stdout
167
+ assert "--base origin/main" in completed_notice.stdout
168
+ assert "does not block commit or push" in completed_notice.stdout
169
+
170
+
171
+ def test_notice_reports_pending_when_manifest_exists_without_report(
172
+ tmp_path: Path,
173
+ ) -> None:
174
+ repository_path, _ = create_target_repository(
175
+ tmp_path,
176
+ "https://github.com/JonEcho/python-automation.git",
177
+ )
178
+ write_report(repository_path, {})
179
+ (repository_path / ".git" / "local-verification" / "report.json").unlink()
180
+
181
+ completed_notice = run_notice(repository_path)
182
+
183
+ assert completed_notice.returncode == 0
184
+ assert "State: pending" in completed_notice.stdout
185
+ assert "manifest is missing or unreadable" not in completed_notice.stdout
186
+ assert "No complete current pass is recorded" in completed_notice.stdout
187
+
188
+
189
+ def test_notice_ignores_unrelated_remote(tmp_path: Path) -> None:
190
+ repository_path, _ = create_target_repository(
191
+ tmp_path,
192
+ "https://github.com/other-owner/other-repository.git",
193
+ )
194
+ completed_notice = run_notice(repository_path)
195
+ assert completed_notice.returncode == 0
196
+ assert completed_notice.stdout == ""
197
+
198
+
199
+ def test_notice_reports_failed_checks_without_pass_label(tmp_path: Path) -> None:
200
+ repository_path, current_head = create_target_repository(
201
+ tmp_path,
202
+ "https://github.com/JonEcho/python-automation.git",
203
+ )
204
+ write_report(repository_path, {"head": current_head, "status": "failed"})
205
+ completed_notice = run_notice(repository_path)
206
+ assert completed_notice.returncode == 0
207
+ assert f"Current SHA: {current_head}" in completed_notice.stdout
208
+ assert "State: failed" in completed_notice.stdout
209
+ assert "recorded local checks failed" in completed_notice.stdout
210
+ assert "local-checks:passed" not in completed_notice.stdout
211
+
212
+
213
+ def test_notice_reports_pass_only_for_complete_current_revision(tmp_path: Path) -> None:
214
+ repository_path, _ = create_target_repository(
215
+ tmp_path,
216
+ "https://github.com/JonEcho/python-automation.git",
217
+ )
218
+ current_head = write_passing_report(repository_path)
219
+ completed_notice = run_notice(repository_path)
220
+ assert completed_notice.returncode == 0
221
+ assert f"Verified SHA: {current_head}" in completed_notice.stdout
222
+ assert "State: passed" in completed_notice.stdout
223
+ assert (
224
+ "local-checks:passed is valid only for this exact current SHA"
225
+ in completed_notice.stdout
226
+ )
227
+
228
+
229
+ def test_notice_handles_malformed_report_and_missing_repository(tmp_path: Path) -> None:
230
+ repository_path, _ = create_target_repository(
231
+ tmp_path,
232
+ "https://github.com/JonEcho/python-automation.git",
233
+ )
234
+ manifest_path = repository_path / "config" / "local-verification.json"
235
+ manifest_path.parent.mkdir(exist_ok=True)
236
+ manifest_mapping = {
237
+ "version": 1,
238
+ "checks": [
239
+ {
240
+ "id": "smoke",
241
+ "argv": ["python", "-c", "pass"],
242
+ "cwd": ".",
243
+ "timeout_seconds": 1.0,
244
+ "minimum_tests": None,
245
+ }
246
+ ],
247
+ "exclusions": [],
248
+ }
249
+ manifest_path.write_text(json.dumps(manifest_mapping), encoding="utf-8")
250
+ report_path = repository_path / ".git" / "local-verification" / "report.json"
251
+ report_path.parent.mkdir(exist_ok=True)
252
+ report_path.write_bytes(b"not-json\xff")
253
+ malformed_notice = run_notice(repository_path)
254
+ missing_notice = run_notice(tmp_path / "missing repository")
255
+ assert malformed_notice.returncode == 0
256
+ assert "State: unverified" in malformed_notice.stdout
257
+ assert missing_notice.returncode == 0
258
+ assert missing_notice.stdout == ""
259
+
260
+
261
+ def test_notice_uses_worktree_specific_report_path(tmp_path: Path) -> None:
262
+ repository_path, _ = create_target_repository(
263
+ tmp_path / "main",
264
+ "https://github.com/JonEcho/python-automation.git",
265
+ )
266
+ linked_worktree_path = tmp_path / "linked worktree Ω"
267
+ run_git(repository_path, "worktree", "add", "--detach", str(linked_worktree_path))
268
+ linked_git_directory = Path(
269
+ run_git(linked_worktree_path, "rev-parse", "--absolute-git-dir").stdout.strip()
270
+ )
271
+
272
+ completed_notice = run_notice(linked_worktree_path)
273
+
274
+ expected_report_path = linked_git_directory / "local-verification" / "report.json"
275
+ shared_report_path = repository_path / ".git" / "local-verification" / "report.json"
276
+ assert completed_notice.returncode == 0
277
+ assert str(expected_report_path) in completed_notice.stdout
278
+ assert str(shared_report_path) not in completed_notice.stdout
279
+
280
+
281
+ def test_notice_accepts_complete_report_in_worktree_metadata(tmp_path: Path) -> None:
282
+ repository_path, _ = create_target_repository(
283
+ tmp_path / "main",
284
+ "https://github.com/JonEcho/python-automation.git",
285
+ )
286
+ current_head = write_passing_report(repository_path)
287
+ linked_worktree_path = tmp_path / "linked worktree Ω"
288
+ run_git(repository_path, "worktree", "add", "--detach", str(linked_worktree_path))
289
+ linked_git_directory = Path(
290
+ run_git(linked_worktree_path, "rev-parse", "--absolute-git-dir").stdout.strip()
291
+ )
292
+ write_worktree_passing_report(repository_path, linked_git_directory)
293
+
294
+ completed_notice = run_notice(linked_worktree_path)
295
+
296
+ future_path = linked_worktree_path / "future.txt"
297
+ future_path.write_text("future\n", encoding="utf-8")
298
+ run_git(linked_worktree_path, "add", "future.txt")
299
+ run_git(linked_worktree_path, "commit", "--quiet", "-m", "future")
300
+ future_head = run_git(linked_worktree_path, "rev-parse", "HEAD").stdout.strip()
301
+ stale_notice = run_notice(linked_worktree_path)
302
+ run_git(linked_worktree_path, "reset", "--quiet", "--hard", current_head)
303
+ run_git(linked_worktree_path, "update-ref", "refs/remotes/origin/main", future_head)
304
+ moved_base_notice = run_notice(linked_worktree_path)
305
+
306
+ assert "State: passed" in completed_notice.stdout
307
+ assert f"Verified SHA: {current_head}" in completed_notice.stdout
308
+ assert "State: stale" in stale_notice.stdout
309
+ assert "State: unverified" in moved_base_notice.stdout
310
+
311
+
312
+ def test_notice_invalidates_pass_after_worktree_edit(tmp_path: Path) -> None:
313
+ repository_path, _ = create_target_repository(
314
+ tmp_path,
315
+ "https://github.com/JonEcho/python-automation.git",
316
+ )
317
+ current_head = write_passing_report(repository_path)
318
+ passed_notice = run_notice(repository_path)
319
+ (repository_path / "untracked.txt").write_text("changed\n", encoding="utf-8")
320
+
321
+ changed_notice = run_notice(repository_path)
322
+
323
+ assert f"Verified SHA: {current_head}" in passed_notice.stdout
324
+ assert "State: passed" in passed_notice.stdout
325
+ assert "Verified SHA: none" in changed_notice.stdout
326
+ assert "State: unverified" in changed_notice.stdout
327
+
328
+
329
+ def test_notice_invalidates_pass_after_origin_base_moves(tmp_path: Path) -> None:
330
+ repository_path, _ = create_target_repository(
331
+ tmp_path,
332
+ "https://github.com/JonEcho/python-automation.git",
333
+ )
334
+ current_head = write_passing_report(repository_path)
335
+ passed_notice = run_notice(repository_path)
336
+ (repository_path / "future.txt").write_text("future\n", encoding="utf-8")
337
+ run_git(repository_path, "add", "future.txt")
338
+ run_git(repository_path, "commit", "--quiet", "-m", "future")
339
+ future_head = run_git(repository_path, "rev-parse", "HEAD").stdout.strip()
340
+ run_git(repository_path, "reset", "--quiet", "--hard", current_head)
341
+ run_git(repository_path, "update-ref", "refs/remotes/origin/main", future_head)
342
+
343
+ moved_base_notice = run_notice(repository_path)
344
+
345
+ assert "State: passed" in passed_notice.stdout
346
+ assert "Verified SHA: none" in moved_base_notice.stdout
347
+ assert "State: unverified" in moved_base_notice.stdout
@@ -1 +0,0 @@
1
- @../AGENTS.md
@@ -1,5 +0,0 @@
1
- # Audit contract
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/audit-contract.md
@@ -1,5 +0,0 @@
1
- # Audit reply template
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/audit-reply-template.md
@@ -1,5 +0,0 @@
1
- # Code rules gate
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/code-rules-gate.md
@@ -1,5 +0,0 @@
1
- # Fix protocol
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/fix-protocol.md
@@ -1,5 +0,0 @@
1
- # Gh payloads
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/gh-payloads.md
@@ -1,149 +0,0 @@
1
- # Portable converge driver
2
-
3
- **Rule: deterministic control is script-only.** Phase transitions, wait delays,
4
- clean stamps, ready decisions, task lists, and “what next” never live as prose
5
- for the agent to invent. The agent runs scripts, reads JSON, and only performs
6
- judgment steps the JSON names.
7
-
8
- ## Step 1 — task list (every autoconverge portable run)
9
-
10
- ```
11
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/build_converge_task_list.py" \
12
- [--bugbot-down 0|1] [--copilot-down 0|1] \
13
- [--codex-down 0|1] [--codex-required 0|1]
14
- ```
15
-
16
- Register every `tasks[]` entry on the session task list. **Final task id is
17
- always** `all_runnable_reviews_clean_same_head`. The run is complete only when
18
- that final task is completed: every runnable code review is CLEAN on one
19
- shared HEAD. Do not invent tasks in prose.
20
-
21
- `open-run` embeds the same list (`tasks`, `runnable_review_ids`,
22
- `final_task_id`, `done_when`).
23
-
24
- ## Pacer selection
25
-
26
- ```
27
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/select_converge_pacer.py" \
28
- --skill autoconverge \
29
- --has-workflow <0|1> \
30
- --has-schedule-wakeup <0|1>
31
- ```
32
-
33
- When `pacer` is not `portable`, use the skill’s native Workflow or
34
- ScheduleWakeup path. When `pacer=portable`, use the control script below.
35
-
36
- ## Isolation and worktree
37
-
38
- 1. When the tool list includes `EnterWorktree`, call it (same contract as the
39
- Claude-host skills).
40
- 2. When `EnterWorktree` is absent, isolate with git worktree machinery:
41
- - Prefer an existing worktree already on the PR head ref under
42
- `.claude/worktrees/` (or another dedicated worktree path).
43
- - Otherwise `git fetch origin <headRefName>` and
44
- `git worktree add <path> <headRefName>` (or `gh pr checkout <N>` into a
45
- dedicated directory), then `cd` into that checkout.
46
- 3. Confirm the working directory is the PR’s own repo on the PR head SHA:
47
- `python "$HOME/.claude/skills/_shared/pr-loop/scripts/preflight_worktree.py" --owner <O> --repo <R> --mode strict`.
48
- Non-zero exit → report the `ABORT` line and stop.
49
- 4. Cross-repo routing: every local review and edit runs with cwd set to the **PR worktree** (see autoconverge pre-flight and `preflight_worktree.py --mode strict`).
50
-
51
- `open-run` runs the same strict preflight before seeding state.
52
-
53
- ## Control script
54
-
55
- ```
56
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/portable_converge_driver.py" <command> ...
57
- ```
58
-
59
- Stdout JSON: `status`, `next`, `phase`, `state_file`, optional `commands`,
60
- `wait_seconds`, `blocker`, and on `open-run` the task-list fields. Exit `0` =
61
- ok; `1` = contract failure; `2` = usage error.
62
-
63
- | Command | Deterministic effect |
64
- |---|---|
65
- | `open-run` | Require `portable`; preflight; seed state + task list; when `--codex-down` is off, set `codex_required` from CLI force-on or the weekly usage probe (same rule as `check_convergence`); next=`run_code_review` |
66
- | `after-code-review` | From returncode / dirty_tree / served_command |
67
- | `after-bugteam` | From pushed / converged (bug-audit phase on portable pacer) |
68
- | `after-bugbot` | From classification / inline lag |
69
- | `after-codex` | From classification clean / dirty / down |
70
- | `after-copilot-wait` | From review surfaced / wait cap |
71
- | `after-ready-check` | From check_convergence exit |
72
- | `show-state` | Echo state; rehydrate `commands` / `wait_seconds` for pending next |
73
-
74
- ## Continuous tick loop
75
-
76
- After transport check, PR scope, isolation, permission grant, and the once-per-run
77
- Copilot quota pre-check:
78
-
79
- 1. Seed or restore state via `open-run` or `show-state` (and handoff
80
- `state-copy.json` when resuming).
81
- 2. Run the driver command for the current step; read JSON `next` / `commands` /
82
- `wait_seconds`.
83
- 3. On non-terminal `next`:
84
- - Write state and handoff when the after-* payload says so.
85
- - If `next` is `poll_wait`, sleep `wait_seconds` only, then re-poll and call
86
- the matching after-*.
87
- - If `next` is immediate work, continue in the same turn without sleeping.
88
- 4. On `mark_ready` / `stop_blocked` / named stop: run lifecycle Close, print the
89
- entry skill’s exit block, omit further pacing.
90
- 5. External reviewers remain skippable the same way as Claude-host runs when
91
- opted out or down. Push and head-change reset push-invalidated markers
92
- (`*_clean_at`, `merge_state_status`, `bugbot_down`, `codex_down`).
93
-
94
- ## Agent loop (judgment only)
95
-
96
- 1. Run the driver command for the current step.
97
- 2. If JSON `commands` is non-empty, run that argv (scripted helper).
98
- 3. Map JSON `next` to the single judgment action; report back via the matching
99
- `after-*` command.
100
- 4. Mark session tasks complete only when the scripted stamps say so; complete
101
- the final task only when every runnable review is clean on the same HEAD.
102
-
103
- | `next` | Agent does | Report with |
104
- |---|---|---|
105
- | `run_code_review` | Run `commands` | `after-code-review` |
106
- | `apply_fixes_and_push` | Fix protocol; commit; push | re-review then `after-code-review` |
107
- | `run_bugteam` | Bug-audit lens / worker spawn body | `after-bugteam` |
108
- | `run_bugbot_gate` | Bugbot helper scripts | `after-bugbot` |
109
- | `run_codex_review` | Run Codex review step | `after-codex` |
110
- | `request_copilot_review` | Request Copilot | `after-copilot-wait` |
111
- | `poll_wait` | Sleep `wait_seconds` only | re-poll then after-* |
112
- | `check_ready` | Run `commands` (check_convergence) | `after-ready-check` |
113
- | `mark_ready` | Run `commands` (`gh pr ready`) | teardown |
114
- | `stop_blocked` | Teardown; print blocker | stop |
115
-
116
- ## Autoconverge entry on portable pacer
117
-
118
- When `/autoconverge` selects `pacer=portable`:
119
-
120
- - Complete autoconverge pre-flight (scope, draft ownership, strict worktree,
121
- grant, Copilot quota).
122
- - Drive the continuous tick loop above (scripted phase machine) until ready
123
- or a documented blocker.
124
- - Skip `Workflow({ scriptPath: converge.mjs })` — that path requires the
125
- Workflow tool.
126
- - Teardown uses the lifecycle Close path; the Workflow-only closing HTML
127
- journal report is optional and skipped when no workflow run id exists.
128
- - Resume command on handoff: `/autoconverge <PR URL>`.
129
-
130
- When `/autoconverge` selects `pacer=workflow`, follow the skill’s Workflow
131
- sections unchanged.
132
-
133
- ## Helpers (scripted)
134
-
135
- | Concern | Script |
136
- |---|---|
137
- | Task list | `build_converge_task_list.py` |
138
- | Pacer | `select_converge_pacer.py` |
139
- | Worktree | `preflight_worktree.py` |
140
- | Code review | `$HOME/.claude/scripts/invoke_code_review.py` |
141
- | Workers | `$HOME/.claude/scripts/resolve_worker_spawn.py` |
142
- | Ready | `$HOME/.claude/_shared/pr-loop/scripts/check_convergence.py` |
143
- | Handoff | `write_handoff.py` |
144
-
145
- ## Fail closed
146
-
147
- Never abort solely because Workflow or ScheduleWakeup is missing once
148
- pacer=`portable`. Fail closed on contract failures only: auth, worktree,
149
- unresolvable gates, and wait caps.
@@ -1,5 +0,0 @@
1
- # Post-audit thread contract
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/post-audit-thread-contract.md
@@ -1,5 +0,0 @@
1
- # Precatch rubric
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/precatch-rubric.md
@@ -1,119 +0,0 @@
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
- })
@@ -1,5 +0,0 @@
1
- # Preflight proposal contract
2
-
3
- **Canonical home:**
4
-
5
- @~/.claude/_shared/pr-loop/preflight-proposal.md
@@ -1 +0,0 @@
1
- @../AGENTS.md