claude-dev-env 2.15.1 → 2.17.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 (841) hide show
  1. package/.agents/agents/.claude/CLAUDE.md +1 -0
  2. package/{agents → .agents/agents}/AGENTS.md +8 -2
  3. package/{agents → .agents/agents}/test_agent_frontmatter.py +1 -1
  4. package/.agents/skills/.claude/CLAUDE.md +1 -0
  5. package/.agents/skills/AGENTS.md +71 -0
  6. package/.agents/skills/_shared/.claude/CLAUDE.md +1 -0
  7. package/{skills → .agents/skills}/_shared/AGENTS.md +2 -2
  8. package/.agents/skills/_shared/advisor/.claude/CLAUDE.md +1 -0
  9. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +1 -0
  10. package/{skills → .agents/skills}/_shared/pr-loop/AGENTS.md +22 -15
  11. package/{skills → .agents/skills}/_shared/pr-loop/portable-driver.md +6 -7
  12. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +1 -0
  13. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
  14. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +1 -0
  15. package/{skills → .agents/skills}/_shared/pr-loop/scripts/AGENTS.md +1 -1
  16. package/{skills → .agents/skills}/_shared/pr-loop/scripts/portable_converge_driver.py +25 -16
  17. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +1 -0
  18. package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +6 -1
  19. package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +1 -5
  20. package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_audit_prompt.py +9 -3
  21. package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_audit_outcomes.py +1 -1
  22. package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_fix_outcomes.py +1 -1
  23. package/.agents/skills/autoconverge/.claude/CLAUDE.md +1 -0
  24. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +1 -0
  25. package/.agents/skills/autoconverge/reference/convergence-gates.md +31 -0
  26. package/{skills → .agents/skills}/autoconverge/reference/convergence.md +8 -10
  27. package/{skills → .agents/skills}/autoconverge/reference/gotchas.md +1 -1
  28. package/{skills → .agents/skills}/autoconverge/reference/stop-conditions.md +1 -1
  29. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +1 -0
  30. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +1 -0
  31. package/{skills → .agents/skills}/autoconverge/workflow/converge.codex-gate.test.mjs +1 -1
  32. package/{skills → .agents/skills}/autoconverge/workflow/converge.contract.test.mjs +1 -1
  33. package/{skills → .agents/skills}/autoconverge/workflow/converge.mjs +3 -3
  34. package/.agents/skills/cert-classification-rule/SKILL.md +224 -0
  35. package/.agents/skills/cert-classification-rule/scripts/resort_cert_folders.py +158 -0
  36. package/{skills → .agents/skills}/e-code-review/reference/effort-evaluation.md +1 -1
  37. package/.agents/skills/eli5/SKILL.md +128 -0
  38. package/.agents/skills/eli5/reference/task-seeds.md +11 -0
  39. package/.agents/skills/everything-search/.claude/CLAUDE.md +1 -0
  40. package/.agents/skills/fresh-branch/.claude/CLAUDE.md +1 -0
  41. package/{skills → .agents/skills}/fresh-branch/scripts/test_create_fresh_branch.py +2 -3
  42. package/.agents/skills/grok-spawn/.claude/CLAUDE.md +1 -0
  43. package/.agents/skills/name-by-capability-audit/SKILL.md +67 -0
  44. package/.agents/skills/name-by-capability-audit/reference/fetch-commands.md +29 -0
  45. package/.agents/skills/name-by-capability-audit/reference/offense-examples.md +32 -0
  46. package/.agents/skills/name-by-capability-audit/reference/report-template.md +29 -0
  47. package/.agents/skills/name-by-capability-audit/reference/rule-checklist.md +38 -0
  48. package/.agents/skills/name-by-capability-audit/reference/task-seeds.md +9 -0
  49. package/.agents/skills/pr-cleanup/SKILL.md +99 -0
  50. package/{skills → .agents/skills}/prototype/reference/honest-limitations.md +1 -1
  51. package/{skills → .agents/skills}/prototype/reference/promotion-tasks.md +1 -1
  52. package/{skills → .agents/skills}/prototype/scripts/test_build_sandbox_settings.py +2 -2
  53. package/{skills → .agents/skills}/prototype/scripts/test_probe_sandbox_safety.py +1 -1
  54. package/{skills → .agents/skills}/prototype/workflows/promotion.md +2 -2
  55. package/.agents/skills/rebase/.claude/CLAUDE.md +1 -0
  56. package/.agents/skills/review-router/SKILL.md +51 -0
  57. package/.agents/skills/review-router/reference/route-policy.json +7 -0
  58. package/.agents/skills/review-router/reference/task-seeds.md +1 -0
  59. package/.agents/skills/review-router/scripts/conftest.py +4 -0
  60. package/.agents/skills/review-router/scripts/review_router.py +50 -0
  61. package/.agents/skills/review-router/scripts/review_router_cli.py +211 -0
  62. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +1 -0
  63. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  64. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +13 -0
  65. package/.agents/skills/review-router/scripts/test_review_router.py +23 -0
  66. package/.agents/skills/review-router/scripts/test_review_router_cli.py +47 -0
  67. package/.agents/skills/review-tier/SKILL.md +56 -0
  68. package/.agents/skills/review-tier/reference/task-seeds.md +1 -0
  69. package/.agents/skills/review-tier/reference/tier-policy.json +9 -0
  70. package/.agents/skills/review-tier/scripts/conftest.py +4 -0
  71. package/.agents/skills/review-tier/scripts/review_tier.py +332 -0
  72. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +1 -0
  73. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  74. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +29 -0
  75. package/.agents/skills/review-tier/scripts/test_generation.py +171 -0
  76. package/.agents/skills/review-tier/scripts/test_review_tier.py +33 -0
  77. package/.agents/skills/run-claude-dev-env/SKILL.md +84 -0
  78. package/.agents/skills/run-claude-dev-env/driver.mjs +239 -0
  79. package/.agents/skills/session-log/.claude/CLAUDE.md +1 -0
  80. package/{skills → .agents/skills}/session-log/SKILL.md +1 -1
  81. package/.agents/skills/session-tidy/.claude/CLAUDE.md +1 -0
  82. package/.agents/skills/shared-extraction-audit/SKILL.md +160 -0
  83. package/.agents/skills/shared-extraction-audit/reference/examples.md +46 -0
  84. package/.agents/skills/shared-extraction-audit/reference/offense-taxonomy.md +100 -0
  85. package/.agents/skills/skill-builder/.claude/CLAUDE.md +1 -0
  86. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +1 -0
  87. package/{skills → .agents/skills}/skill-builder/references/deterministic-elements.md +1 -1
  88. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +1 -0
  89. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +1 -0
  90. package/.agents/skills/source-command-logifix/SKILL.md +29 -0
  91. package/.agents/skills/source-command-sr-loop/SKILL.md +58 -0
  92. package/.agents/skills/task-build/.claude/CLAUDE.md +1 -0
  93. package/.agents/skills/update/.claude/CLAUDE.md +1 -0
  94. package/.agents/skills-archived/AGENTS.md +45 -0
  95. package/.agents/skills-archived/anthropic-plan/.claude/CLAUDE.md +1 -0
  96. package/{skills → .agents/skills-archived}/anthropic-plan/AGENTS.md +1 -1
  97. package/.agents/skills-archived/anthropic-plan/scripts/.claude/CLAUDE.md +1 -0
  98. package/.agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants/.claude/CLAUDE.md +1 -0
  99. package/.agents/skills-archived/anthropic-plan/templates/.claude/CLAUDE.md +1 -0
  100. package/{skills → .agents/skills-archived}/anthropic-plan/test_skill_contract.py +4 -4
  101. package/.agents/skills-archived/anthropic-plan/workflow/.claude/CLAUDE.md +1 -0
  102. package/.agents/skills-archived/auditing-claude-config/.claude/CLAUDE.md +1 -0
  103. package/.agents/skills-archived/bugteam/.claude/CLAUDE.md +1 -0
  104. package/.agents/skills-archived/bugteam/reference/.claude/CLAUDE.md +1 -0
  105. package/.agents/skills-archived/bugteam/reference/obstacles/.claude/CLAUDE.md +1 -0
  106. package/.agents/skills-archived/bugteam/scripts/.claude/CLAUDE.md +1 -0
  107. package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_code_rules_gate.py +11 -1
  108. package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_fix_hookspath.py +11 -1
  109. package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_preflight.py +11 -1
  110. package/.agents/skills-archived/bugteam/scripts/bugteam_scripts_constants/.claude/CLAUDE.md +1 -0
  111. package/{skills → .agents/skills-archived}/bugteam/scripts/reflow_skill_md.py +3 -3
  112. package/.agents/skills-archived/codex-review/.claude/CLAUDE.md +1 -0
  113. package/.agents/skills-archived/codex-review/reference/.claude/CLAUDE.md +1 -0
  114. package/.agents/skills-archived/codex-review/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
  115. package/{skills → .agents/skills-archived}/codex-review/scripts/codex_usage_probe.py +11 -1
  116. package/{skills → .agents/skills-archived}/codex-review/scripts/run_codex_review.py +11 -1
  117. package/{skills → .agents/skills-archived}/codex-review/test_skill_scaffold.py +4 -4
  118. package/{skills → .agents/skills-archived}/copilot-finding-triage/SKILL.md +1 -1
  119. package/.agents/skills-archived/copilot-review/.claude/CLAUDE.md +1 -0
  120. package/.agents/skills-archived/pr-converge/.claude/CLAUDE.md +1 -0
  121. package/{skills → .agents/skills-archived}/pr-converge/SKILL.md +6 -6
  122. package/.agents/skills-archived/pr-converge/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
  123. package/{skills → .agents/skills-archived}/pr-converge/pr_converge_skill_constants/AGENTS.md +1 -1
  124. package/{skills → .agents/skills-archived}/pr-converge/pr_converge_skill_constants/constants.py +1 -1
  125. package/.agents/skills-archived/pr-converge/reference/.claude/CLAUDE.md +1 -0
  126. package/{skills → .agents/skills-archived}/pr-converge/reference/multi-pr-orchestration.md +1 -1
  127. package/.agents/skills-archived/pr-converge/reference/obstacles/.claude/CLAUDE.md +1 -0
  128. package/{skills → .agents/skills-archived}/pr-converge/reference/per-tick.md +3 -3
  129. package/.agents/skills-archived/pr-converge/scripts/.claude/CLAUDE.md +1 -0
  130. package/{skills → .agents/skills-archived}/pr-converge/scripts/_pr_converge_path_setup.py +17 -2
  131. package/.agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
  132. package/{skills → .agents/skills-archived}/pr-converge/scripts/reflow_skill_md.py +2 -2
  133. package/{skills → .agents/skills-archived}/pr-converge/scripts/test__pr_converge_path_setup.py +7 -4
  134. package/{skills → .agents/skills-archived}/pr-converge/test_portable_pacer_gate.py +6 -2
  135. package/.agents/skills-archived/pr-converge/workflows/.claude/CLAUDE.md +1 -0
  136. package/{skills → .agents/skills-archived}/pr-converge/workflows/schedule-wakeup-loop.md +1 -1
  137. package/.agents/skills-archived/recall/.claude/CLAUDE.md +1 -0
  138. package/.agents/skills-archived/remember/.claude/CLAUDE.md +1 -0
  139. package/{skills → .agents/skills-archived}/split-pr/reference/proposal-format.md +1 -1
  140. package/.claude/CLAUDE.md +1 -0
  141. package/AGENTS.md +34 -58
  142. package/_shared/AGENTS.md +2 -0
  143. package/_shared/advisor/reference/sol-rung.md +2 -2
  144. package/_shared/advisor/reference/third-party-bind.md +1 -1
  145. package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +1 -1
  146. package/_shared/pr-loop/audit-reply-template.md +4 -0
  147. package/_shared/pr-loop/code-rules-gate.md +1 -1
  148. package/_shared/pr-loop/fix-protocol.md +7 -6
  149. package/_shared/pr-loop/gh-payloads.md +8 -6
  150. package/_shared/pr-loop/precatch-rubric.md +6 -5
  151. package/_shared/pr-loop/scripts/AGENTS.md +15 -0
  152. package/_shared/pr-loop/scripts/_pr_converge_path_setup.py +38 -0
  153. package/_shared/pr-loop/scripts/check_bugbot_ci.py +279 -0
  154. package/_shared/pr-loop/scripts/check_convergence.py +923 -0
  155. package/_shared/pr-loop/scripts/check_convergence_availability.py +275 -0
  156. package/_shared/pr-loop/scripts/check_convergence_gates.py +279 -0
  157. package/_shared/pr-loop/scripts/check_convergence_thread_gates.py +219 -0
  158. package/_shared/pr-loop/scripts/check_pending_reviews.py +154 -0
  159. package/_shared/pr-loop/scripts/codex_down_classifier.py +98 -0
  160. package/_shared/pr-loop/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
  161. package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
  162. package/_shared/pr-loop/scripts/codex_review_scripts_constants/__init__.py +1 -0
  163. package/_shared/pr-loop/scripts/codex_review_scripts_constants/classifier_constants.py +35 -0
  164. package/_shared/pr-loop/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +82 -0
  165. package/_shared/pr-loop/scripts/codex_review_scripts_constants/findings_constants.py +18 -0
  166. package/_shared/pr-loop/scripts/codex_review_scripts_constants/run_constants.py +53 -0
  167. package/_shared/pr-loop/scripts/codex_usage_probe.py +570 -0
  168. package/_shared/pr-loop/scripts/conftest.py +43 -0
  169. package/_shared/pr-loop/scripts/fetch_copilot_reviews.py +134 -0
  170. package/_shared/pr-loop/scripts/fixtures/auth_failure_synthetic.txt +1 -0
  171. package/_shared/pr-loop/scripts/fixtures/config_load_failure_v0.125.0.txt +1 -0
  172. package/_shared/pr-loop/scripts/fixtures/freeform_findings_v0.144.3.txt +6 -0
  173. package/_shared/pr-loop/scripts/fixtures/model_rejection_v0.125.0.jsonl +5 -0
  174. package/_shared/pr-loop/scripts/fixtures/structured_findings.txt +13 -0
  175. package/_shared/pr-loop/scripts/fixtures/success_stream_v0.144.3.jsonl +6 -0
  176. package/_shared/pr-loop/scripts/fixtures/unknown_failure_synthetic.txt +1 -0
  177. package/_shared/pr-loop/scripts/fixtures/usage_limit_synthetic.txt +1 -0
  178. package/_shared/pr-loop/scripts/parse_codex_findings.py +207 -0
  179. package/_shared/pr-loop/scripts/post_fix_reply.py +168 -0
  180. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
  181. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
  182. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  183. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +70 -0
  184. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/pr_converge_constants.py +118 -0
  185. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +13 -0
  186. package/_shared/pr-loop/scripts/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
  187. package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +26 -0
  188. package/_shared/pr-loop/scripts/pr_converge_skill_constants/__init__.py +0 -0
  189. package/_shared/pr-loop/scripts/pr_converge_skill_constants/constants.py +69 -0
  190. package/_shared/pr-loop/scripts/run_codex_review.py +609 -0
  191. package/_shared/pr-loop/scripts/test__pr_converge_path_setup.py +30 -0
  192. package/_shared/pr-loop/scripts/test_check_bugbot_ci.py +312 -0
  193. package/_shared/pr-loop/scripts/test_check_convergence.py +438 -0
  194. package/_shared/pr-loop/scripts/test_check_convergence_availability.py +391 -0
  195. package/_shared/pr-loop/scripts/test_check_convergence_codex.py +517 -0
  196. package/_shared/pr-loop/scripts/test_check_convergence_contract.py +400 -0
  197. package/_shared/pr-loop/scripts/test_check_convergence_fixture.py +179 -0
  198. package/_shared/pr-loop/scripts/test_check_convergence_gates.py +84 -0
  199. package/_shared/pr-loop/scripts/test_check_convergence_thread_gates.py +99 -0
  200. package/_shared/pr-loop/scripts/test_codex_down_classifier.py +143 -0
  201. package/_shared/pr-loop/scripts/test_codex_usage_probe.py +683 -0
  202. package/_shared/pr-loop/scripts/test_parse_codex_findings.py +130 -0
  203. package/_shared/pr-loop/scripts/test_run_codex_review.py +969 -0
  204. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +1 -1
  205. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +1 -1
  206. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +1 -1
  207. package/_shared/pr-loop/state-schema.md +20 -28
  208. package/_shared/process-tree/AGENTS.md +3 -3
  209. package/bin/AGENTS.md +17 -12
  210. package/bin/ever-shipped-skills.mjs +34 -3
  211. package/bin/install-constants.mjs +46 -12
  212. package/bin/install-plan.mjs +6 -1
  213. package/bin/install.agents-home.test.mjs +199 -0
  214. package/bin/install.cursor-rules.test.mjs +3 -3
  215. package/bin/install.mjs +153 -23
  216. package/bin/install.plan.test.mjs +1 -0
  217. package/bin/install.profile-root.test.mjs +54 -1
  218. package/bin/install.prune.test.mjs +23 -204
  219. package/bin/install.test.mjs +17 -5
  220. package/bin/publish-directory-pointer.mjs +175 -0
  221. package/bin/publish-directory-pointer.test.mjs +129 -0
  222. package/bin/resolve-install-root.mjs +80 -4
  223. package/bin/resolve-package-managed-directory.mjs +29 -0
  224. package/bin/resolve-package-managed-directory.test.mjs +97 -0
  225. package/commands/AGENTS.md +2 -0
  226. package/commands/sr-loop.md +3 -0
  227. package/docs/references/prose-style-enforcement.md +3 -7
  228. package/hooks/AGENTS.md +0 -3
  229. package/hooks/blocking/AGENTS.md +0 -2
  230. package/hooks/blocking/ask_user_question_shape_blocker.py +83 -0
  231. package/hooks/blocking/hedging_language_blocker.py +1 -0
  232. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +10 -6
  233. package/hooks/blocking/pre_tool_use_dispatcher.py +2 -19
  234. package/hooks/blocking/state_description_blocker.py +1 -1
  235. package/hooks/blocking/test_ask_user_question_shape.py +69 -0
  236. package/hooks/blocking/test_code_rules_command_dispatch.py +1 -1
  237. package/hooks/blocking/test_code_rules_enforcer_magic_slice_bounds.py +1 -1
  238. package/hooks/blocking/test_code_rules_enforcer_split_annotations_length.py +1 -1
  239. package/hooks/blocking/test_code_rules_js_conventions.py +1 -1
  240. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +1 -1
  241. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +1 -1
  242. package/hooks/blocking/test_code_rules_js_sibling_return_object_key_drift.py +1 -1
  243. package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +1 -1
  244. package/hooks/blocking/test_fable_spawn_gate.py +1 -1
  245. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +1 -1
  246. package/hooks/blocking/test_pre_tool_use_dispatcher.py +17 -58
  247. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +9 -104
  248. package/hooks/blocking/test_state_description_blocker.py +1 -0
  249. package/hooks/blocking/test_stop_dispatcher.py +1 -26
  250. package/hooks/hooks.json +1 -1
  251. package/hooks/hooks_constants/AGENTS.md +0 -3
  252. package/hooks/hooks_constants/ask_user_question_shape.py +1 -1
  253. package/hooks/hooks_constants/ask_user_question_shape_constants.py +73 -0
  254. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +1 -2
  255. package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -1
  256. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +9 -0
  257. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -7
  258. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
  259. package/hooks/hooks_constants/test_ask_user_question_shape.py +1 -1
  260. package/hooks/hooks_constants/test_prose_metrics_parity.py +29 -107
  261. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
  262. package/hooks/hooks_constants/working_style_prompt_constants.py +9 -10
  263. package/hooks/session/AGENTS.md +4 -1
  264. package/hooks/session/test_working_style_prompt.py +8 -4
  265. package/hooks/session/working_style_prompt.py +4 -2
  266. package/installable-surfaces.manifest.json +2 -3
  267. package/package.json +4 -8
  268. package/rules/AGENTS.md +2 -5
  269. package/rules/asd-ste100-language.md +39 -0
  270. package/rules/ask-user-question-required.md +1 -1
  271. package/rules/long-horizon-autonomy.md +1 -1
  272. package/scripts/AGENTS.md +1 -0
  273. package/scripts/Show-Asset.ps1 +106 -0
  274. package/scripts/active_capability_references.py +38 -8
  275. package/scripts/claude_chain_usage.py +2 -0
  276. package/scripts/codex_compat_watcher.py +1 -1
  277. package/scripts/dev_env_scripts_constants/active_capability_constants.py +5 -2
  278. package/scripts/dev_env_scripts_constants/claude_chain_usage_constants.py +4 -1
  279. package/scripts/test_validate_instruction_pairs.py +30 -3
  280. package/scripts/test_verify_installable_package.py +2 -1
  281. package/scripts/tests/test_codex_compat_watcher.py +5 -5
  282. package/scripts/tests/test_engine.py +4 -4
  283. package/scripts/tests/test_rules.py +5 -5
  284. package/system-prompts/AGENTS.md +8 -0
  285. package/system-prompts/software-engineer.xml +8 -3
  286. package/CLAUDE.md +0 -1
  287. package/_shared/pr-loop/scripts/README.md +0 -21
  288. package/agents/CLAUDE.md +0 -1
  289. package/docs/imagegen.md +0 -22
  290. package/hooks/blocking/eli11_reply_enforcer.py +0 -436
  291. package/hooks/blocking/plain_language_blocker.py +0 -758
  292. package/hooks/blocking/test_eli11_reply_enforcer.py +0 -390
  293. package/hooks/blocking/test_plain_language_blocker.py +0 -683
  294. package/hooks/blocking/test_plain_language_blocker_allowlist.py +0 -228
  295. package/hooks/diagnostic/AGENTS.md +0 -75
  296. package/hooks/diagnostic/CLAUDE.md +0 -1
  297. package/hooks/diagnostic/hook_log_extractor.py +0 -875
  298. package/hooks/diagnostic/hook_log_init.py +0 -202
  299. package/hooks/diagnostic/hook_log_stop_wrapper.py +0 -26
  300. package/hooks/diagnostic/migrations/2026-04-25-drop-themes-hook-events.sql +0 -3
  301. package/hooks/diagnostic/migrations/AGENTS.md +0 -16
  302. package/hooks/diagnostic/migrations/CLAUDE.md +0 -1
  303. package/hooks/diagnostic/migrations/README.md +0 -76
  304. package/hooks/diagnostic/queries/AGENTS.md +0 -19
  305. package/hooks/diagnostic/queries/CLAUDE.md +0 -1
  306. package/hooks/diagnostic/queries/block_details_for_hook.sql +0 -26
  307. package/hooks/diagnostic/queries/blocks_by_category.sql +0 -10
  308. package/hooks/diagnostic/queries/blocks_by_tool.sql +0 -9
  309. package/hooks/diagnostic/queries/blocks_last_7_days.sql +0 -11
  310. package/hooks/diagnostic/queries/top_blockers_last_24_hours.sql +0 -12
  311. package/hooks/diagnostic/queries/top_blockers_overall.sql +0 -12
  312. package/hooks/diagnostic/requirements-hook-logs-dev.txt +0 -2
  313. package/hooks/diagnostic/requirements-hook-logs.txt +0 -1
  314. package/hooks/diagnostic/schema.sql +0 -51
  315. package/hooks/diagnostic/test_hook_log_extractor.py +0 -1518
  316. package/hooks/diagnostic/test_hook_log_init.py +0 -227
  317. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +0 -17
  318. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +0 -94
  319. package/hooks/hooks_constants/hook_log_extractor_constants.py +0 -233
  320. package/hooks/hooks_constants/plain_language_blocker_constants.py +0 -366
  321. package/hooks/hooks_constants/test_hook_log_extractor_constants.py +0 -123
  322. package/rules/doc-prose-cuts.md +0 -58
  323. package/rules/eli11-replies.md +0 -36
  324. package/rules/opus5-communication-contract.md +0 -45
  325. package/rules/plain-language.md +0 -9
  326. package/skills/AGENTS.md +0 -72
  327. package/skills/CLAUDE.md +0 -1
  328. package/skills/_shared/CLAUDE.md +0 -1
  329. package/skills/_shared/advisor/CLAUDE.md +0 -1
  330. package/skills/_shared/pr-loop/CLAUDE.md +0 -1
  331. package/skills/_shared/pr-loop/prompts/AGENTS.md +0 -9
  332. package/skills/_shared/pr-loop/prompts/CLAUDE.md +0 -1
  333. package/skills/_shared/pr-loop/scripts/CLAUDE.md +0 -1
  334. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +0 -1
  335. package/skills/anthropic-plan/CLAUDE.md +0 -1
  336. package/skills/anthropic-plan/scripts/CLAUDE.md +0 -1
  337. package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +0 -1
  338. package/skills/anthropic-plan/templates/CLAUDE.md +0 -1
  339. package/skills/anthropic-plan/workflow/CLAUDE.md +0 -1
  340. package/skills/auditing-claude-config/CLAUDE.md +0 -1
  341. package/skills/autoconverge/CLAUDE.md +0 -1
  342. package/skills/autoconverge/reference/CLAUDE.md +0 -1
  343. package/skills/autoconverge/workflow/CLAUDE.md +0 -1
  344. package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +0 -1
  345. package/skills/bugteam/CLAUDE.md +0 -1
  346. package/skills/bugteam/reference/CLAUDE.md +0 -1
  347. package/skills/bugteam/reference/obstacles/CLAUDE.md +0 -1
  348. package/skills/bugteam/scripts/CLAUDE.md +0 -1
  349. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
  350. package/skills/codex-review/CLAUDE.md +0 -1
  351. package/skills/codex-review/reference/CLAUDE.md +0 -1
  352. package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +0 -1
  353. package/skills/copilot-review/CLAUDE.md +0 -1
  354. package/skills/everything-search/CLAUDE.md +0 -1
  355. package/skills/fresh-branch/CLAUDE.md +0 -1
  356. package/skills/grok-spawn/CLAUDE.md +0 -1
  357. package/skills/grokify/evals/README.md +0 -72
  358. package/skills/grokify/evals/parse-payload.test.mjs +0 -171
  359. package/skills/grokify/evals/run-capability-evals.mjs +0 -545
  360. package/skills/pr-converge/CLAUDE.md +0 -1
  361. package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +0 -1
  362. package/skills/pr-converge/reference/CLAUDE.md +0 -1
  363. package/skills/pr-converge/reference/obstacles/CLAUDE.md +0 -1
  364. package/skills/pr-converge/scripts/CLAUDE.md +0 -1
  365. package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +0 -1
  366. package/skills/pr-converge/workflows/CLAUDE.md +0 -1
  367. package/skills/rebase/CLAUDE.md +0 -1
  368. package/skills/recall/CLAUDE.md +0 -1
  369. package/skills/remember/CLAUDE.md +0 -1
  370. package/skills/session-log/CLAUDE.md +0 -1
  371. package/skills/session-tidy/CLAUDE.md +0 -1
  372. package/skills/skill-builder/CLAUDE.md +0 -1
  373. package/skills/skill-builder/references/CLAUDE.md +0 -1
  374. package/skills/skill-builder/templates/CLAUDE.md +0 -1
  375. package/skills/skill-builder/workflows/CLAUDE.md +0 -1
  376. package/skills/task-build/CLAUDE.md +0 -1
  377. package/skills/update/CLAUDE.md +0 -1
  378. /package/{agents → .agents/agents}/clean-coder.md +0 -0
  379. /package/{agents → .agents/agents}/code-quality-agent.md +0 -0
  380. /package/{agents → .agents/agents}/git-commit-crafter.md +0 -0
  381. /package/{agents → .agents/agents}/issue-tracker.md +0 -0
  382. /package/{agents → .agents/agents}/plan-packet-validator.md +0 -0
  383. /package/{agents → .agents/agents}/pr-description-writer.md +0 -0
  384. /package/{agents → .agents/agents}/session-advisor.md +0 -0
  385. /package/{agents → .agents/agents}/skill-writer-agent.md +0 -0
  386. /package/{skills → .agents/skills}/_shared/advisor/AGENTS.md +0 -0
  387. /package/{skills → .agents/skills}/_shared/advisor/advisor-protocol.md +0 -0
  388. /package/{skills → .agents/skills}/_shared/advisor/scripts/README.md +0 -0
  389. /package/{skills → .agents/skills}/_shared/end-of-run-gotcha-recommendations.md +0 -0
  390. /package/{skills → .agents/skills}/_shared/pr-loop/audit-contract.md +0 -0
  391. /package/{skills → .agents/skills}/_shared/pr-loop/audit-reply-template.md +0 -0
  392. /package/{skills → .agents/skills}/_shared/pr-loop/code-rules-gate.md +0 -0
  393. /package/{skills → .agents/skills}/_shared/pr-loop/fix-protocol.md +0 -0
  394. /package/{skills → .agents/skills}/_shared/pr-loop/gh-payloads.md +0 -0
  395. /package/{skills → .agents/skills}/_shared/pr-loop/post-audit-thread-contract.md +0 -0
  396. /package/{skills → .agents/skills}/_shared/pr-loop/precatch-rubric.md +0 -0
  397. /package/{skills → .agents/skills}/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -0
  398. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -0
  399. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_cli_utils.py +0 -0
  400. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_path_resolver.py +0 -0
  401. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/_xml_utils.py +0 -0
  402. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/audit_category_schema.py +0 -0
  403. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_audit_prompt.py +0 -0
  404. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_converge_task_list.py +0 -0
  405. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/build_fix_prompt.py +0 -0
  406. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/init_loop_state.py +0 -0
  407. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/preflight_worktree.py +0 -0
  408. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/select_converge_pacer.py +0 -0
  409. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -0
  410. /package/{skills/pr-converge/pr_converge_skill_constants → .agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants}/__init__.py +0 -0
  411. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -0
  412. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -0
  413. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -0
  414. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -0
  415. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -0
  416. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/teardown_worktrees.py +0 -0
  417. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test__path_resolver.py +0 -0
  418. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -0
  419. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -0
  420. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -0
  421. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_init_loop_state.py +0 -0
  422. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -0
  423. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -0
  424. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -0
  425. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -0
  426. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/test_write_handoff.py +0 -0
  427. /package/{skills → .agents/skills}/_shared/pr-loop/scripts/write_handoff.py +0 -0
  428. /package/{skills → .agents/skills}/_shared/pr-loop/state-schema.md +0 -0
  429. /package/{skills → .agents/skills}/_shared/pr-loop/worker-spawn.md +0 -0
  430. /package/{skills → .agents/skills}/autoconverge/AGENTS.md +0 -0
  431. /package/{skills → .agents/skills}/autoconverge/SKILL.md +0 -0
  432. /package/{skills → .agents/skills}/autoconverge/reference/AGENTS.md +0 -0
  433. /package/{skills → .agents/skills}/autoconverge/reference/closing-report.md +0 -0
  434. /package/{skills → .agents/skills}/autoconverge/reference/copilot-findings.md +0 -0
  435. /package/{skills → .agents/skills}/autoconverge/reference/headless-safety.md +0 -0
  436. /package/{skills → .agents/skills}/autoconverge/reference/multi-pr.md +0 -0
  437. /package/{skills → .agents/skills}/autoconverge/reference/self-closing-loop.md +0 -0
  438. /package/{skills → .agents/skills}/autoconverge/test_portable_pacer_gate.py +0 -0
  439. /package/{skills → .agents/skills}/autoconverge/workflow/AGENTS.md +0 -0
  440. /package/{skills → .agents/skills}/autoconverge/workflow/aggregate_runs.py +0 -0
  441. /package/{skills → .agents/skills}/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -0
  442. /package/{skills/pr-converge/scripts/pr_converge_scripts_constants → .agents/skills/autoconverge/workflow/autoconverge_report_constants}/__init__.py +0 -0
  443. /package/{skills → .agents/skills}/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -0
  444. /package/{skills → .agents/skills}/autoconverge/workflow/converge.clean-audit.test.mjs +0 -0
  445. /package/{skills → .agents/skills}/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -0
  446. /package/{skills → .agents/skills}/autoconverge/workflow/converge.fix-progress.test.mjs +0 -0
  447. /package/{skills → .agents/skills}/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -0
  448. /package/{skills → .agents/skills}/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -0
  449. /package/{skills → .agents/skills}/autoconverge/workflow/converge.p2-advance.test.mjs +0 -0
  450. /package/{skills → .agents/skills}/autoconverge/workflow/converge.path-aware.test.mjs +0 -0
  451. /package/{skills → .agents/skills}/autoconverge/workflow/converge.precatch.test.mjs +0 -0
  452. /package/{skills → .agents/skills}/autoconverge/workflow/converge.run-input.test.mjs +0 -0
  453. /package/{skills → .agents/skills}/autoconverge/workflow/converge_multi.mjs +0 -0
  454. /package/{skills → .agents/skills}/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -0
  455. /package/{skills → .agents/skills}/autoconverge/workflow/convergence_summary.py +0 -0
  456. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -0
  457. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -0
  458. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -0
  459. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -0
  460. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -0
  461. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -0
  462. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -0
  463. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -0
  464. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -0
  465. /package/{skills → .agents/skills}/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -0
  466. /package/{skills → .agents/skills}/autoconverge/workflow/render_report.py +0 -0
  467. /package/{skills → .agents/skills}/autoconverge/workflow/test_aggregate_runs.py +0 -0
  468. /package/{skills → .agents/skills}/autoconverge/workflow/test_convergence_summary.py +0 -0
  469. /package/{skills → .agents/skills}/autoconverge/workflow/test_render_report.py +0 -0
  470. /package/{skills → .agents/skills}/e-code-review/SKILL.md +0 -0
  471. /package/{skills → .agents/skills}/e-code-review/reference/fix.md +0 -0
  472. /package/{skills → .agents/skills}/e-code-review/reference/loop.md +0 -0
  473. /package/{skills → .agents/skills}/e-code-review/reference/low.md +0 -0
  474. /package/{skills → .agents/skills}/e-code-review/reference/medium.md +0 -0
  475. /package/{skills → .agents/skills}/e-code-review/reference/runner-selection.md +0 -0
  476. /package/{skills → .agents/skills}/e-code-review/reference/xhigh.md +0 -0
  477. /package/{skills → .agents/skills}/e-code-review/scripts/config/e_code_review_effort_constants/__init__.py +0 -0
  478. /package/{skills → .agents/skills}/e-code-review/scripts/config/e_code_review_effort_constants/effort_constants.py +0 -0
  479. /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/__init__.py +0 -0
  480. /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/finding_pipeline_constants.py +0 -0
  481. /package/{skills → .agents/skills}/e-code-review/scripts/e_code_review_scripts_constants/grok_code_review_constants.py +0 -0
  482. /package/{skills → .agents/skills}/e-code-review/scripts/effort_defaults_evidence.json +0 -0
  483. /package/{skills → .agents/skills}/e-code-review/scripts/effort_evaluation.py +0 -0
  484. /package/{skills → .agents/skills}/e-code-review/scripts/finding_pipeline.py +0 -0
  485. /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/demanding.json +0 -0
  486. /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/easy.json +0 -0
  487. /package/{skills → .agents/skills}/e-code-review/scripts/fixtures/medium.json +0 -0
  488. /package/{skills → .agents/skills}/e-code-review/scripts/grok_code_review.py +0 -0
  489. /package/{skills → .agents/skills}/e-code-review/scripts/test_effort_evaluation.py +0 -0
  490. /package/{skills → .agents/skills}/e-code-review/scripts/test_finding_pipeline.py +0 -0
  491. /package/{skills → .agents/skills}/e-code-review/scripts/test_grok_code_review.py +0 -0
  492. /package/{skills → .agents/skills}/e-simplify/SKILL.md +0 -0
  493. /package/{skills → .agents/skills}/everything-search/AGENTS.md +0 -0
  494. /package/{skills → .agents/skills}/everything-search/SKILL.md +0 -0
  495. /package/{skills → .agents/skills}/fresh-branch/AGENTS.md +0 -0
  496. /package/{skills → .agents/skills}/fresh-branch/SKILL.md +0 -0
  497. /package/{skills → .agents/skills}/fresh-branch/scripts/create_fresh_branch.py +0 -0
  498. /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_git_commands.py +0 -0
  499. /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_scripts_constants/__init__.py +0 -0
  500. /package/{skills → .agents/skills}/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +0 -0
  501. /package/{skills → .agents/skills}/fresh-branch/scripts/pytest.ini +0 -0
  502. /package/{skills → .agents/skills}/fresh-branch/scripts/test_fresh_branch_git_commands.py +0 -0
  503. /package/{skills → .agents/skills}/grok-spawn/AGENTS.md +0 -0
  504. /package/{skills → .agents/skills}/grok-spawn/SKILL.md +0 -0
  505. /package/{skills → .agents/skills}/grok-spawn/reference/flag-profiles.md +0 -0
  506. /package/{skills → .agents/skills}/grok-spawn/reference/worker-briefs.md +0 -0
  507. /package/{skills → .agents/skills}/issue-tracker/SKILL.md +0 -0
  508. /package/{skills → .agents/skills}/issue-tracker/reference/epic-and-sub-issue-model.md +0 -0
  509. /package/{skills → .agents/skills}/issue-tracker/reference/handoff-schema.md +0 -0
  510. /package/{skills → .agents/skills}/issue-tracker/reference/operation-matrix.md +0 -0
  511. /package/{skills → .agents/skills}/orchestrator/SKILL.md +0 -0
  512. /package/{skills → .agents/skills}/orchestrator/scripts/status_gate.py +0 -0
  513. /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/__init__.py +0 -0
  514. /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/config/__init__.py +0 -0
  515. /package/{skills → .agents/skills}/orchestrator/scripts/status_gate_constants/config/constants.py +0 -0
  516. /package/{skills → .agents/skills}/orchestrator/scripts/test_status_gate.py +0 -0
  517. /package/{skills → .agents/skills}/orchestrator-refresh/SKILL.md +0 -0
  518. /package/{skills → .agents/skills}/privacy-hygiene/SKILL.md +0 -0
  519. /package/{skills → .agents/skills}/privacy-hygiene/reference/sweep-procedure.md +0 -0
  520. /package/{skills → .agents/skills}/prototype/SKILL.md +0 -0
  521. /package/{skills → .agents/skills}/prototype/scripts/build_sandbox_settings.py +0 -0
  522. /package/{skills → .agents/skills}/prototype/scripts/conftest.py +0 -0
  523. /package/{skills → .agents/skills}/prototype/scripts/launch_sandbox.py +0 -0
  524. /package/{skills → .agents/skills}/prototype/scripts/probe_sandbox_safety.py +0 -0
  525. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/__init__.py +0 -0
  526. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  527. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -0
  528. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -0
  529. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -0
  530. /package/{skills → .agents/skills}/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -0
  531. /package/{skills → .agents/skills}/prototype/scripts/test_launch_sandbox.py +0 -0
  532. /package/{skills → .agents/skills}/prototype/workflows/sandbox.md +0 -0
  533. /package/{skills → .agents/skills}/rebase/AGENTS.md +0 -0
  534. /package/{skills → .agents/skills}/rebase/SKILL.md +0 -0
  535. /package/{skills → .agents/skills}/session-log/AGENTS.md +0 -0
  536. /package/{skills → .agents/skills}/session-log/templates/frontmatter.md +0 -0
  537. /package/{skills → .agents/skills}/session-tidy/AGENTS.md +0 -0
  538. /package/{skills → .agents/skills}/session-tidy/SKILL.md +0 -0
  539. /package/{skills → .agents/skills}/skill-builder/AGENTS.md +0 -0
  540. /package/{skills → .agents/skills}/skill-builder/SKILL.md +0 -0
  541. /package/{skills → .agents/skills}/skill-builder/references/AGENTS.md +0 -0
  542. /package/{skills → .agents/skills}/skill-builder/references/delegation-map.md +0 -0
  543. /package/{skills → .agents/skills}/skill-builder/references/description-field.md +0 -0
  544. /package/{skills → .agents/skills}/skill-builder/references/progressive-disclosure.md +0 -0
  545. /package/{skills → .agents/skills}/skill-builder/references/self-audit-checklist.md +0 -0
  546. /package/{skills → .agents/skills}/skill-builder/references/skill-modularity.md +0 -0
  547. /package/{skills → .agents/skills}/skill-builder/references/skill-types.md +0 -0
  548. /package/{skills → .agents/skills}/skill-builder/references/thariq-x-post-skills.json +0 -0
  549. /package/{skills → .agents/skills}/skill-builder/templates/AGENTS.md +0 -0
  550. /package/{skills → .agents/skills}/skill-builder/templates/gap-analysis.md +0 -0
  551. /package/{skills → .agents/skills}/skill-builder/workflows/AGENTS.md +0 -0
  552. /package/{skills → .agents/skills}/skill-builder/workflows/improve-skill.md +0 -0
  553. /package/{skills → .agents/skills}/skill-builder/workflows/new-skill.md +0 -0
  554. /package/{skills → .agents/skills}/skill-builder/workflows/polish-skill.md +0 -0
  555. /package/{skills → .agents/skills}/small-cl/SKILL.md +0 -0
  556. /package/{skills → .agents/skills}/task-build/AGENTS.md +0 -0
  557. /package/{skills → .agents/skills}/task-build/SKILL.md +0 -0
  558. /package/{skills → .agents/skills}/task-build/reference/tool-routing.md +0 -0
  559. /package/{skills → .agents/skills}/team-advisor/SKILL.md +0 -0
  560. /package/{skills → .agents/skills}/team-advisor/reference/advisor-docs-review.md +0 -0
  561. /package/{skills → .agents/skills}/update/AGENTS.md +0 -0
  562. /package/{skills → .agents/skills}/update/SKILL.md +0 -0
  563. /package/{skills → .agents/skills}/usage-pause/SKILL.md +0 -0
  564. /package/{skills → .agents/skills}/usage-pause/scripts/resolve_usage_window.py +0 -0
  565. /package/{skills → .agents/skills}/usage-pause/scripts/test_resolve_usage_window.py +0 -0
  566. /package/{skills → .agents/skills}/usage-pause/scripts/usage_pause_constants/__init__.py +0 -0
  567. /package/{skills → .agents/skills}/usage-pause/scripts/usage_pause_constants/resolve_usage_window_constants.py +0 -0
  568. /package/{skills → .agents/skills-archived}/anthropic-plan/SKILL.md +0 -0
  569. /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/AGENTS.md +0 -0
  570. /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -0
  571. /package/{skills/_shared/pr-loop/scripts/skills_pr_loop_constants → .agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants}/__init__.py +0 -0
  572. /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/validate_packet_constants.py +0 -0
  573. /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/test_validate_packet.py +0 -0
  574. /package/{skills → .agents/skills-archived}/anthropic-plan/scripts/validate_packet.py +0 -0
  575. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/AGENTS.md +0 -0
  576. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/README.md +0 -0
  577. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/build-prompt.md +0 -0
  578. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/reuse-audit.md +0 -0
  579. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/source-map.md +0 -0
  580. /package/{skills → .agents/skills-archived}/anthropic-plan/templates/visual-plan.template.html +0 -0
  581. /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/AGENTS.md +0 -0
  582. /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/plan-packet.contract.test.mjs +0 -0
  583. /package/{skills → .agents/skills-archived}/anthropic-plan/workflow/plan-packet.mjs +0 -0
  584. /package/{skills → .agents/skills-archived}/auditing-claude-config/AGENTS.md +0 -0
  585. /package/{skills → .agents/skills-archived}/auditing-claude-config/SKILL.md +0 -0
  586. /package/{skills → .agents/skills-archived}/auditing-claude-config/reference/probe-hook.md +0 -0
  587. /package/{skills → .agents/skills-archived}/beat-sheet/SKILL.md +0 -0
  588. /package/{skills → .agents/skills-archived}/beat-sheet/reference/visual-beats.md +0 -0
  589. /package/{skills → .agents/skills-archived}/bugteam/AGENTS.md +0 -0
  590. /package/{skills → .agents/skills-archived}/bugteam/CONSTRAINTS.md +0 -0
  591. /package/{skills → .agents/skills-archived}/bugteam/EXAMPLES.md +0 -0
  592. /package/{skills → .agents/skills-archived}/bugteam/PROMPTS.md +0 -0
  593. /package/{skills → .agents/skills-archived}/bugteam/SKILL.md +0 -0
  594. /package/{skills → .agents/skills-archived}/bugteam/reference/AGENTS.md +0 -0
  595. /package/{skills → .agents/skills-archived}/bugteam/reference/README.md +0 -0
  596. /package/{skills → .agents/skills-archived}/bugteam/reference/audit-and-teammates.md +0 -0
  597. /package/{skills → .agents/skills-archived}/bugteam/reference/copilot-gap-analysis.md +0 -0
  598. /package/{skills → .agents/skills-archived}/bugteam/reference/design-rationale.md +0 -0
  599. /package/{skills → .agents/skills-archived}/bugteam/reference/github-pr-reviews.md +0 -0
  600. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/AGENTS.md +0 -0
  601. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-assign-ids.md +0 -0
  602. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-capture-excerpts.md +0 -0
  603. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-walk-categories.md +0 -0
  604. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/audit-write-xml.md +0 -0
  605. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-append-summary.md +0 -0
  606. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-apply-fixes.md +0 -0
  607. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-git-add-commit.md +0 -0
  608. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-git-push.md +0 -0
  609. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-post-reply.md +0 -0
  610. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-publish-summary.md +0 -0
  611. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-py-compile.md +0 -0
  612. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-read-files.md +0 -0
  613. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-resolve-thread.md +0 -0
  614. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-test-suite.md +0 -0
  615. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-violation-count.md +0 -0
  616. /package/{skills → .agents/skills-archived}/bugteam/reference/obstacles/fix-write-xml.md +0 -0
  617. /package/{skills → .agents/skills-archived}/bugteam/reference/team-setup.md +0 -0
  618. /package/{skills → .agents/skills-archived}/bugteam/scripts/AGENTS.md +0 -0
  619. /package/{skills → .agents/skills-archived}/bugteam/scripts/README.md +0 -0
  620. /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -0
  621. /package/{skills/anthropic-plan/scripts/anthropic_plan_scripts_constants → .agents/skills-archived/bugteam/scripts/bugteam_scripts_constants}/__init__.py +0 -0
  622. /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/probe_code_rules_enforcer_check_constants.py +0 -0
  623. /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/reflow_skill_md_constants.py +0 -0
  624. /package/{skills → .agents/skills-archived}/bugteam/scripts/bugteam_scripts_constants/windows_safe_rmtree_constants.py +0 -0
  625. /package/{skills → .agents/skills-archived}/bugteam/scripts/probe_code_rules_enforcer_check.py +0 -0
  626. /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_code_rules_gate.py +0 -0
  627. /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -0
  628. /package/{skills → .agents/skills-archived}/bugteam/scripts/test_bugteam_preflight.py +0 -0
  629. /package/{skills → .agents/skills-archived}/bugteam/scripts/test_probe_code_rules_enforcer_check.py +0 -0
  630. /package/{skills → .agents/skills-archived}/bugteam/scripts/test_windows_safe_rmtree.py +0 -0
  631. /package/{skills → .agents/skills-archived}/bugteam/scripts/windows_safe_rmtree.py +0 -0
  632. /package/{skills → .agents/skills-archived}/bugteam/sources.md +0 -0
  633. /package/{skills → .agents/skills-archived}/bugteam/test_skill_additions.py +0 -0
  634. /package/{skills → .agents/skills-archived}/closeout/SKILL.md +0 -0
  635. /package/{skills → .agents/skills-archived}/closeout/reference/handoff-prompt-template.md +0 -0
  636. /package/{skills → .agents/skills-archived}/closeout/reference/pii-redaction-checklist.md +0 -0
  637. /package/{skills → .agents/skills-archived}/codex-review/AGENTS.md +0 -0
  638. /package/{skills → .agents/skills-archived}/codex-review/SKILL.md +0 -0
  639. /package/{skills → .agents/skills-archived}/codex-review/reference/AGENTS.md +0 -0
  640. /package/{skills → .agents/skills-archived}/codex-review/reference/cli-contract.md +0 -0
  641. /package/{skills → .agents/skills-archived}/codex-review/reference/loop-integration.md +0 -0
  642. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_down_classifier.py +0 -0
  643. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -0
  644. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/__init__.py +0 -0
  645. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/classifier_constants.py +0 -0
  646. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +0 -0
  647. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/findings_constants.py +0 -0
  648. /package/{skills → .agents/skills-archived}/codex-review/scripts/codex_review_scripts_constants/run_constants.py +0 -0
  649. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/auth_failure_synthetic.txt +0 -0
  650. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/config_load_failure_v0.125.0.txt +0 -0
  651. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/freeform_findings_v0.144.3.txt +0 -0
  652. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/model_rejection_v0.125.0.jsonl +0 -0
  653. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/structured_findings.txt +0 -0
  654. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/success_stream_v0.144.3.jsonl +0 -0
  655. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/unknown_failure_synthetic.txt +0 -0
  656. /package/{skills → .agents/skills-archived}/codex-review/scripts/fixtures/usage_limit_synthetic.txt +0 -0
  657. /package/{skills → .agents/skills-archived}/codex-review/scripts/parse_codex_findings.py +0 -0
  658. /package/{skills → .agents/skills-archived}/codex-review/scripts/test_codex_down_classifier.py +0 -0
  659. /package/{skills → .agents/skills-archived}/codex-review/scripts/test_codex_usage_probe.py +0 -0
  660. /package/{skills → .agents/skills-archived}/codex-review/scripts/test_parse_codex_findings.py +0 -0
  661. /package/{skills → .agents/skills-archived}/codex-review/scripts/test_run_codex_review.py +0 -0
  662. /package/{skills → .agents/skills-archived}/comments/SKILL.md +0 -0
  663. /package/{skills → .agents/skills-archived}/condensing-instructions/SKILL.md +0 -0
  664. /package/{skills → .agents/skills-archived}/copilot-finding-triage/reference/tier-rubric.md +0 -0
  665. /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/conftest.py +0 -0
  666. /package/{skills/autoconverge/workflow/autoconverge_report_constants → .agents/skills-archived/copilot-finding-triage/scripts/copilot_finding_triage_constants}/__init__.py +0 -0
  667. /package/{skills/bugteam/scripts/bugteam_scripts_constants → .agents/skills-archived/copilot-finding-triage/scripts/copilot_finding_triage_constants/config}/__init__.py +0 -0
  668. /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +0 -0
  669. /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/notify_ntfy.py +0 -0
  670. /package/{skills → .agents/skills-archived}/copilot-finding-triage/scripts/test_notify_ntfy.py +0 -0
  671. /package/{skills → .agents/skills-archived}/copilot-finding-triage/templates/notification.md +0 -0
  672. /package/{skills → .agents/skills-archived}/copilot-review/AGENTS.md +0 -0
  673. /package/{skills → .agents/skills-archived}/copilot-review/SKILL.md +0 -0
  674. /package/{skills → .agents/skills-archived}/copilot-review/templates/subagent-prompt.md +0 -0
  675. /package/{skills → .agents/skills-archived}/descriptions/SKILL.md +0 -0
  676. /package/{skills → .agents/skills-archived}/emergencies/SKILL.md +0 -0
  677. /package/{skills → .agents/skills-archived}/grokify/SKILL.md +0 -0
  678. /package/{skills → .agents/skills-archived}/grokify/capability-claims.test.mjs +0 -0
  679. /package/{skills → .agents/skills-archived}/grokify/templates/handoff-template.md +0 -0
  680. /package/{skills → .agents/skills-archived}/plan-to-pr/SKILL.md +0 -0
  681. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/final-validation-tasks.md +0 -0
  682. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/model-routing.md +0 -0
  683. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/packet-contract.md +0 -0
  684. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/packet-schema.json +0 -0
  685. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/process-inventory.md +0 -0
  686. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/review-loop.md +0 -0
  687. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/run-record.schema.json +0 -0
  688. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/self-audit-tasks.md +0 -0
  689. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/task-seeds.md +0 -0
  690. /package/{skills → .agents/skills-archived}/plan-to-pr/reference/task-ticket.md +0 -0
  691. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/config/__init__.py +0 -0
  692. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/config/constants.py +0 -0
  693. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/create_packet.py +0 -0
  694. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/load_skill_constants.py +0 -0
  695. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_create_packet.py +0 -0
  696. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_packet.py +0 -0
  697. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_protocol.py +0 -0
  698. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/test_validate_run.py +0 -0
  699. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_packet.py +0 -0
  700. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_protocol.py +0 -0
  701. /package/{skills → .agents/skills-archived}/plan-to-pr/scripts/validate_run.py +0 -0
  702. /package/{skills → .agents/skills-archived}/plan-to-pr/test_skill_contract.py +0 -0
  703. /package/{skills → .agents/skills-archived}/plan-to-pr/test_task_ticket_contract.py +0 -0
  704. /package/{skills → .agents/skills-archived}/pr-converge/AGENTS.md +0 -0
  705. /package/{skills/copilot-finding-triage/scripts/copilot_finding_triage_constants → .agents/skills-archived/pr-converge/pr_converge_skill_constants}/__init__.py +0 -0
  706. /package/{skills → .agents/skills-archived}/pr-converge/reference/AGENTS.md +0 -0
  707. /package/{skills → .agents/skills-archived}/pr-converge/reference/convergence-gates.md +0 -0
  708. /package/{skills → .agents/skills-archived}/pr-converge/reference/examples.md +0 -0
  709. /package/{skills → .agents/skills-archived}/pr-converge/reference/fix-protocol.md +0 -0
  710. /package/{skills → .agents/skills-archived}/pr-converge/reference/ground-rules.md +0 -0
  711. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/AGENTS.md +0 -0
  712. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-post-replies.md +0 -0
  713. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-publish-summary.md +0 -0
  714. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-push.md +0 -0
  715. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-read-filelines.md +0 -0
  716. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-reset-state.md +0 -0
  717. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-resolve-threads.md +0 -0
  718. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +0 -0
  719. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-stage-commit.md +0 -0
  720. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-trigger-bugbot.md +0 -0
  721. /package/{skills → .agents/skills-archived}/pr-converge/reference/obstacles/fix-write-test.md +0 -0
  722. /package/{skills → .agents/skills-archived}/pr-converge/reference/progress-checklist.md +0 -0
  723. /package/{skills → .agents/skills-archived}/pr-converge/reference/state-schema.md +0 -0
  724. /package/{skills → .agents/skills-archived}/pr-converge/reference/stop-conditions.md +0 -0
  725. /package/{skills → .agents/skills-archived}/pr-converge/scripts/AGENTS.md +0 -0
  726. /package/{skills → .agents/skills-archived}/pr-converge/scripts/README.md +0 -0
  727. /package/{skills → .agents/skills-archived}/pr-converge/scripts/caller-window-pid.ps1 +0 -0
  728. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_bugbot_ci.py +0 -0
  729. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence.py +0 -0
  730. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_availability.py +0 -0
  731. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_gates.py +0 -0
  732. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_convergence_thread_gates.py +0 -0
  733. /package/{skills → .agents/skills-archived}/pr-converge/scripts/check_pending_reviews.py +0 -0
  734. /package/{skills → .agents/skills-archived}/pr-converge/scripts/conftest.py +0 -0
  735. /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue-caller.cmd +0 -0
  736. /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue-stop-others.ps1 +0 -0
  737. /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue.ahk +0 -0
  738. /package/{skills → .agents/skills-archived}/pr-converge/scripts/cursor-agents-continue.cmd +0 -0
  739. /package/{skills → .agents/skills-archived}/pr-converge/scripts/fetch_copilot_reviews.py +0 -0
  740. /package/{skills → .agents/skills-archived}/pr-converge/scripts/post_fix_reply.py +0 -0
  741. /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -0
  742. /package/{skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config → .agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants}/__init__.py +0 -0
  743. /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +0 -0
  744. /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/pr_converge_constants.py +0 -0
  745. /package/{skills → .agents/skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +0 -0
  746. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_bugbot_ci.py +0 -0
  747. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence.py +0 -0
  748. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_availability.py +0 -0
  749. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_codex.py +0 -0
  750. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_contract.py +0 -0
  751. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_fixture.py +0 -0
  752. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_gates.py +0 -0
  753. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_check_convergence_thread_gates.py +0 -0
  754. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_cursor_agents_continue.py +0 -0
  755. /package/{skills → .agents/skills-archived}/pr-converge/scripts/test_reflow_skill_md.py +0 -0
  756. /package/{skills → .agents/skills-archived}/pr-converge/test_step5_host_branch.py +0 -0
  757. /package/{skills → .agents/skills-archived}/pr-converge/workflows/AGENTS.md +0 -0
  758. /package/{skills → .agents/skills-archived}/pr-fix-protocol/SKILL.md +0 -0
  759. /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/SKILL.md +0 -0
  760. /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/reference/identity-and-hooks.md +0 -0
  761. /package/{skills → .agents/skills-archived}/pr-loop-cloud-transport/reference/substitution-matrix.md +0 -0
  762. /package/{skills → .agents/skills-archived}/pr-loop-lifecycle/SKILL.md +0 -0
  763. /package/{skills → .agents/skills-archived}/pr-loop-lifecycle/reference/teardown-publish-permissions.md +0 -0
  764. /package/{skills → .agents/skills-archived}/recall/AGENTS.md +0 -0
  765. /package/{skills → .agents/skills-archived}/recall/SKILL.md +0 -0
  766. /package/{skills → .agents/skills-archived}/release-notes-html/SKILL.md +0 -0
  767. /package/{skills → .agents/skills-archived}/remember/AGENTS.md +0 -0
  768. /package/{skills → .agents/skills-archived}/remember/SKILL.md +0 -0
  769. /package/{skills → .agents/skills-archived}/reviewer-gates/SKILL.md +0 -0
  770. /package/{skills → .agents/skills-archived}/reviews/SKILL.md +0 -0
  771. /package/{skills → .agents/skills-archived}/show/SKILL.md +0 -0
  772. /package/{skills → .agents/skills-archived}/show/references/accessibility.md +0 -0
  773. /package/{skills → .agents/skills-archived}/show/references/art.md +0 -0
  774. /package/{skills → .agents/skills-archived}/show/references/charts.md +0 -0
  775. /package/{skills → .agents/skills-archived}/show/references/core-design.md +0 -0
  776. /package/{skills → .agents/skills-archived}/show/references/erds.md +0 -0
  777. /package/{skills → .agents/skills-archived}/show/references/flowcharts.md +0 -0
  778. /package/{skills → .agents/skills-archived}/show/references/host-and-html.md +0 -0
  779. /package/{skills → .agents/skills-archived}/show/references/illustrative-diagrams.md +0 -0
  780. /package/{skills → .agents/skills-archived}/show/references/interaction.md +0 -0
  781. /package/{skills → .agents/skills-archived}/show/references/mockups.md +0 -0
  782. /package/{skills → .agents/skills-archived}/show/references/quality-gates.md +0 -0
  783. /package/{skills → .agents/skills-archived}/show/references/structural-diagrams.md +0 -0
  784. /package/{skills → .agents/skills-archived}/show/references/subject-inventory.md +0 -0
  785. /package/{skills → .agents/skills-archived}/show/references/svg-contract.md +0 -0
  786. /package/{skills → .agents/skills-archived}/show/routing.yaml +0 -0
  787. /package/{skills → .agents/skills-archived}/show/samples/pr1262-v2.svg +0 -0
  788. /package/{skills → .agents/skills-archived}/show/scripts/README.md +0 -0
  789. /package/{skills → .agents/skills-archived}/show/scripts/validate-artifact.py +0 -0
  790. /package/{skills → .agents/skills-archived}/show/scripts/validate-package.py +0 -0
  791. /package/{skills → .agents/skills-archived}/show/templates/html-widget.html +0 -0
  792. /package/{skills → .agents/skills-archived}/show/templates/svg-base.svg +0 -0
  793. /package/{skills → .agents/skills-archived}/show/tests/fixtures/css-var.svg +0 -0
  794. /package/{skills → .agents/skills-archived}/show/tests/fixtures/dead-ref.svg +0 -0
  795. /package/{skills → .agents/skills-archived}/show/tests/fixtures/filled-glyph.svg +0 -0
  796. /package/{skills → .agents/skills-archived}/show/tests/fixtures/inherited-fill.svg +0 -0
  797. /package/{skills → .agents/skills-archived}/show/tests/fixtures/invalid.svg +0 -0
  798. /package/{skills → .agents/skills-archived}/show/tests/fixtures/large-canvas.svg +0 -0
  799. /package/{skills → .agents/skills-archived}/show/tests/fixtures/unfilled-connector.svg +0 -0
  800. /package/{skills → .agents/skills-archived}/show/tests/fixtures/valid.html +0 -0
  801. /package/{skills → .agents/skills-archived}/show/tests/test_validate-artifact.py +0 -0
  802. /package/{skills → .agents/skills-archived}/show/tests/test_validators.py +0 -0
  803. /package/{skills → .agents/skills-archived}/show/workflows/create-visual.md +0 -0
  804. /package/{skills → .agents/skills-archived}/show/workflows/review-visual.md +0 -0
  805. /package/{skills → .agents/skills-archived}/split-pr/SKILL.md +0 -0
  806. /package/{skills → .agents/skills-archived}/split-pr/reference/path-layers.md +0 -0
  807. /package/{skills → .agents/skills-archived}/split-pr/reference/split-further-loop.md +0 -0
  808. /package/{skills → .agents/skills-archived}/split-pr/reference/splitting-principles.md +0 -0
  809. /package/{skills → .agents/skills-archived}/split-pr/scripts/analyze_pr.py +0 -0
  810. /package/{skills → .agents/skills-archived}/split-pr/scripts/categorize_files.py +0 -0
  811. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/__init__.py +0 -0
  812. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/dependency_constants.py +0 -0
  813. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/git_operations_constants.py +0 -0
  814. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/packing_constants.py +0 -0
  815. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/plan_constants.py +0 -0
  816. /package/{skills → .agents/skills-archived}/split-pr/scripts/config/split_pr_constants.py +0 -0
  817. /package/{skills → .agents/skills-archived}/split-pr/scripts/execute_split_slices.py +0 -0
  818. /package/{skills → .agents/skills-archived}/split-pr/scripts/pack_files_into_slices.py +0 -0
  819. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_dependency_graph.py +0 -0
  820. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_git_operations.py +0 -0
  821. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_layer_order.py +0 -0
  822. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_paginate.py +0 -0
  823. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_process_runner.py +0 -0
  824. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_script_types.py +0 -0
  825. /package/{skills → .agents/skills-archived}/split-pr/scripts/split_pr_title.py +0 -0
  826. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_analyze_pr.py +0 -0
  827. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_categorize_files.py +0 -0
  828. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_categorize_files_packing.py +0 -0
  829. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_execute_split_slices.py +0 -0
  830. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_dependency_graph.py +0 -0
  831. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_git_operations.py +0 -0
  832. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_layer_order.py +0 -0
  833. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_paginate.py +0 -0
  834. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_script_types.py +0 -0
  835. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_split_pr_title.py +0 -0
  836. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_dependency_graph.py +0 -0
  837. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan.py +0 -0
  838. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan_contract.py +0 -0
  839. /package/{skills → .agents/skills-archived}/split-pr/scripts/test_verify_plan_path_normalization.py +0 -0
  840. /package/{skills → .agents/skills-archived}/split-pr/scripts/verify_dependency_graph.py +0 -0
  841. /package/{skills → .agents/skills-archived}/split-pr/scripts/verify_plan.py +0 -0
@@ -0,0 +1,969 @@
1
+ """Behavioral tests for the headless codex review wrapper."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import subprocess
7
+ import sys
8
+ import time
9
+ from pathlib import Path
10
+ from typing import Callable
11
+
12
+ import pytest
13
+
14
+ SCRIPTS_DIRECTORY = Path(__file__).resolve().parent
15
+ if str(SCRIPTS_DIRECTORY) not in sys.path:
16
+ sys.path.insert(0, str(SCRIPTS_DIRECTORY))
17
+
18
+ import run_codex_review as wrapper # noqa: E402
19
+ from codex_review_scripts_constants.run_constants import ( # noqa: E402
20
+ ALL_SHAPE_PROBE_REQUIRED_FLAGS,
21
+ BASE_TARGET_FLAG,
22
+ CODEX_BINARY_NAME,
23
+ CODEX_HOME_ENV_VAR,
24
+ COMMIT_TARGET_FLAG,
25
+ CUSTOM_INSTRUCTIONS_PROMPT,
26
+ DEFAULT_TIMEOUT_SECONDS,
27
+ EXEC_SUBCOMMAND,
28
+ HELP_FLAG,
29
+ JSON_FLAG,
30
+ JSONL_CAPTURE_FILENAME,
31
+ MISSING_BINARY_EXIT_CODE,
32
+ MODEL_FLAG,
33
+ OUTCOME_CLASS_CODEX_DOWN,
34
+ OUTCOME_CLASS_COMPLETED,
35
+ REVIEW_SUBCOMMAND,
36
+ SUBPROCESS_DECODE_EXIT_CODE,
37
+ TIMEOUT_EXIT_CODE,
38
+ UNCOMMITTED_TARGET_FLAG,
39
+ UTF8_ENCODING,
40
+ VERSION_FLAG,
41
+ )
42
+
43
+ HELP_TEXT_WITH_TARGETS = (
44
+ "Usage: codex exec review [OPTIONS] [PROMPT]\n"
45
+ " --uncommitted\n"
46
+ " --base <BRANCH>\n"
47
+ " --commit <SHA>\n"
48
+ " --json\n"
49
+ )
50
+ VERSION_STDOUT = "codex-cli 0.144.3\n"
51
+ EXPECTED_BINARY_VERSION = "0.144.3"
52
+ AGENT_MESSAGE_BODY = "No issues found.\n\n```json\n[]\n```"
53
+ CARRIAGE_RETURN_LINE_ENDING = b"\r\n"
54
+ SUCCESS_JSONL = "\n".join(
55
+ [
56
+ json.dumps({"type": "thread.started", "thread_id": "thread-1"}),
57
+ json.dumps({"type": "turn.started"}),
58
+ json.dumps(
59
+ {
60
+ "type": "item.completed",
61
+ "item": {
62
+ "type": "agent_message",
63
+ "text": AGENT_MESSAGE_BODY,
64
+ },
65
+ }
66
+ ),
67
+ json.dumps(
68
+ {
69
+ "type": "turn.completed",
70
+ "usage": {
71
+ "input_tokens": 10,
72
+ "output_tokens": 5,
73
+ },
74
+ }
75
+ ),
76
+ ]
77
+ ) + "\n"
78
+
79
+
80
+ @pytest.fixture
81
+ def repository_directory(tmp_path: Path) -> Path:
82
+ existing_repository_directory = tmp_path / "repo"
83
+ existing_repository_directory.mkdir()
84
+ return existing_repository_directory
85
+
86
+
87
+ @pytest.fixture
88
+ def run_state_directory(tmp_path: Path) -> Path:
89
+ existing_run_state_directory = tmp_path / "run_state"
90
+ existing_run_state_directory.mkdir()
91
+ return existing_run_state_directory
92
+
93
+
94
+ class _SubprocessRecorder:
95
+ def __init__(
96
+ self,
97
+ behavior_for_invocation: Callable[
98
+ [list[str]], subprocess.CompletedProcess[str] | BaseException
99
+ ],
100
+ ) -> None:
101
+ self.behavior_for_invocation = behavior_for_invocation
102
+ self.all_invocations: list[list[str]] = []
103
+ self.all_keyword_arguments: list[dict[str, object]] = []
104
+
105
+ def __call__(
106
+ self,
107
+ invocation: list[str],
108
+ **keyword_arguments: object,
109
+ ) -> subprocess.CompletedProcess[str]:
110
+ self.all_invocations.append(list(invocation))
111
+ self.all_keyword_arguments.append(keyword_arguments)
112
+ behavior = self.behavior_for_invocation(list(invocation))
113
+ if isinstance(behavior, BaseException):
114
+ raise behavior
115
+ return behavior
116
+
117
+
118
+ def _completed(
119
+ all_arguments: list[str],
120
+ returncode: int,
121
+ stdout: str = "",
122
+ stderr: str = "",
123
+ ) -> subprocess.CompletedProcess[str]:
124
+ return subprocess.CompletedProcess(
125
+ args=all_arguments,
126
+ returncode=returncode,
127
+ stdout=stdout,
128
+ stderr=stderr,
129
+ )
130
+
131
+
132
+ def _is_version_probe(all_arguments: list[str]) -> bool:
133
+ return all_arguments == [CODEX_BINARY_NAME, VERSION_FLAG]
134
+
135
+
136
+ def _is_shape_probe(all_arguments: list[str]) -> bool:
137
+ return all_arguments == [
138
+ CODEX_BINARY_NAME,
139
+ EXEC_SUBCOMMAND,
140
+ REVIEW_SUBCOMMAND,
141
+ HELP_FLAG,
142
+ ]
143
+
144
+
145
+ def _is_review_run(all_arguments: list[str]) -> bool:
146
+ return (
147
+ len(all_arguments) >= 4
148
+ and all_arguments[0] == CODEX_BINARY_NAME
149
+ and all_arguments[1] == EXEC_SUBCOMMAND
150
+ and REVIEW_SUBCOMMAND in all_arguments
151
+ and JSON_FLAG in all_arguments
152
+ and HELP_FLAG not in all_arguments
153
+ and VERSION_FLAG not in all_arguments
154
+ )
155
+
156
+
157
+ def _install_recorder(
158
+ monkeypatch: pytest.MonkeyPatch,
159
+ behavior_for_invocation: Callable[
160
+ [list[str]], subprocess.CompletedProcess[str] | BaseException
161
+ ],
162
+ ) -> _SubprocessRecorder:
163
+ recorder = _SubprocessRecorder(behavior_for_invocation)
164
+ monkeypatch.setattr(wrapper, "codex_subprocess_runner", recorder)
165
+ monkeypatch.setattr(
166
+ wrapper, "_resolve_codex_command_prefix", lambda: [CODEX_BINARY_NAME]
167
+ )
168
+ return recorder
169
+
170
+
171
+ def _healthy_probe_then_review(
172
+ review_returncode: int = 0,
173
+ review_stdout: str = SUCCESS_JSONL,
174
+ review_stderr: str = "",
175
+ ) -> Callable[[list[str]], subprocess.CompletedProcess[str] | BaseException]:
176
+ def behavior(
177
+ all_arguments: list[str],
178
+ ) -> subprocess.CompletedProcess[str] | BaseException:
179
+ if _is_version_probe(all_arguments):
180
+ return _completed(all_arguments, 0, stdout=VERSION_STDOUT)
181
+ if _is_shape_probe(all_arguments):
182
+ return _completed(all_arguments, 0, stdout=HELP_TEXT_WITH_TARGETS)
183
+ if _is_review_run(all_arguments):
184
+ return _completed(
185
+ all_arguments,
186
+ review_returncode,
187
+ stdout=review_stdout,
188
+ stderr=review_stderr,
189
+ )
190
+ raise AssertionError(f"unexpected invocation: {all_arguments!r}")
191
+
192
+ return behavior
193
+
194
+
195
+ def _healthy_probe_then_failing_shape(
196
+ shape_stdout: str,
197
+ ) -> Callable[[list[str]], subprocess.CompletedProcess[str] | BaseException]:
198
+ def behavior(
199
+ all_arguments: list[str],
200
+ ) -> subprocess.CompletedProcess[str] | BaseException:
201
+ if _is_version_probe(all_arguments):
202
+ return _completed(all_arguments, 0, stdout=VERSION_STDOUT)
203
+ if _is_shape_probe(all_arguments):
204
+ return _completed(all_arguments, 0, stdout=shape_stdout)
205
+ raise AssertionError("review must not run after a failed shape probe")
206
+
207
+ return behavior
208
+
209
+
210
+ def _only_review_invocation(recorder: _SubprocessRecorder) -> list[str]:
211
+ return next(
212
+ each_invocation
213
+ for each_invocation in recorder.all_invocations
214
+ if _is_review_run(each_invocation)
215
+ )
216
+
217
+
218
+ def test_argv_assembly_for_uncommitted_target(
219
+ monkeypatch: pytest.MonkeyPatch,
220
+ repository_directory: Path,
221
+ run_state_directory: Path,
222
+ ) -> None:
223
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
224
+
225
+ review_outcome = wrapper.run_codex_review(
226
+ repository_directory=repository_directory,
227
+ run_state_directory=run_state_directory,
228
+ is_uncommitted=True,
229
+ )
230
+
231
+ review_invocation = _only_review_invocation(recorder)
232
+ assert review_invocation == [
233
+ CODEX_BINARY_NAME,
234
+ EXEC_SUBCOMMAND,
235
+ REVIEW_SUBCOMMAND,
236
+ JSON_FLAG,
237
+ UNCOMMITTED_TARGET_FLAG,
238
+ ]
239
+ assert CUSTOM_INSTRUCTIONS_PROMPT not in review_invocation
240
+ assert review_outcome.outcome_class == OUTCOME_CLASS_COMPLETED
241
+
242
+
243
+ def test_argv_assembly_for_base_branch_target(
244
+ monkeypatch: pytest.MonkeyPatch,
245
+ repository_directory: Path,
246
+ run_state_directory: Path,
247
+ ) -> None:
248
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
249
+ base_branch = "origin/main"
250
+
251
+ wrapper.run_codex_review(
252
+ repository_directory=repository_directory,
253
+ run_state_directory=run_state_directory,
254
+ base_branch=base_branch,
255
+ )
256
+
257
+ review_invocation = _only_review_invocation(recorder)
258
+ assert review_invocation == [
259
+ CODEX_BINARY_NAME,
260
+ EXEC_SUBCOMMAND,
261
+ REVIEW_SUBCOMMAND,
262
+ JSON_FLAG,
263
+ BASE_TARGET_FLAG,
264
+ base_branch,
265
+ ]
266
+ assert CUSTOM_INSTRUCTIONS_PROMPT not in review_invocation
267
+
268
+
269
+ def test_argv_assembly_for_commit_target(
270
+ monkeypatch: pytest.MonkeyPatch,
271
+ repository_directory: Path,
272
+ run_state_directory: Path,
273
+ ) -> None:
274
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
275
+ commit_sha = "abc123def456"
276
+
277
+ wrapper.run_codex_review(
278
+ repository_directory=repository_directory,
279
+ run_state_directory=run_state_directory,
280
+ commit_sha=commit_sha,
281
+ )
282
+
283
+ review_invocation = _only_review_invocation(recorder)
284
+ assert review_invocation == [
285
+ CODEX_BINARY_NAME,
286
+ EXEC_SUBCOMMAND,
287
+ REVIEW_SUBCOMMAND,
288
+ JSON_FLAG,
289
+ COMMIT_TARGET_FLAG,
290
+ commit_sha,
291
+ ]
292
+ assert CUSTOM_INSTRUCTIONS_PROMPT not in review_invocation
293
+
294
+
295
+ def test_argv_assembly_for_prompt_target(
296
+ monkeypatch: pytest.MonkeyPatch,
297
+ repository_directory: Path,
298
+ run_state_directory: Path,
299
+ ) -> None:
300
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
301
+
302
+ review_outcome = wrapper.run_codex_review(
303
+ repository_directory=repository_directory,
304
+ run_state_directory=run_state_directory,
305
+ is_prompt_target=True,
306
+ )
307
+
308
+ review_invocation = _only_review_invocation(recorder)
309
+ assert review_invocation == [
310
+ CODEX_BINARY_NAME,
311
+ EXEC_SUBCOMMAND,
312
+ REVIEW_SUBCOMMAND,
313
+ JSON_FLAG,
314
+ CUSTOM_INSTRUCTIONS_PROMPT,
315
+ ]
316
+ assert UNCOMMITTED_TARGET_FLAG not in review_invocation
317
+ assert BASE_TARGET_FLAG not in review_invocation
318
+ assert COMMIT_TARGET_FLAG not in review_invocation
319
+ assert review_outcome.outcome_class == OUTCOME_CLASS_COMPLETED
320
+
321
+
322
+ def test_shape_probe_missing_target_flags_returns_codex_down(
323
+ monkeypatch: pytest.MonkeyPatch,
324
+ repository_directory: Path,
325
+ run_state_directory: Path,
326
+ ) -> None:
327
+ recorder = _install_recorder(
328
+ monkeypatch,
329
+ _healthy_probe_then_failing_shape("Usage: codex exec review\n --legacy-only\n"),
330
+ )
331
+
332
+ review_outcome = wrapper.run_codex_review(
333
+ repository_directory=repository_directory,
334
+ run_state_directory=run_state_directory,
335
+ is_uncommitted=True,
336
+ )
337
+
338
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
339
+ assert review_outcome.binary_version == EXPECTED_BINARY_VERSION
340
+ assert review_outcome.agent_message == ""
341
+ assert review_outcome.jsonl_path is None
342
+ assert not any(
343
+ _is_review_run(each_invocation)
344
+ for each_invocation in recorder.all_invocations
345
+ )
346
+
347
+
348
+ def test_shape_probe_lookalike_flags_do_not_match_required_tokens(
349
+ monkeypatch: pytest.MonkeyPatch,
350
+ repository_directory: Path,
351
+ run_state_directory: Path,
352
+ ) -> None:
353
+ lookalike_help_text = (
354
+ "Usage: codex exec review [OPTIONS]\n"
355
+ " --baseline <BRANCH>\n"
356
+ " --commit-message <TEXT>\n"
357
+ " --uncommitted-only\n"
358
+ " --json-output\n"
359
+ )
360
+ recorder = _install_recorder(
361
+ monkeypatch, _healthy_probe_then_failing_shape(lookalike_help_text)
362
+ )
363
+
364
+ review_outcome = wrapper.run_codex_review(
365
+ repository_directory=repository_directory,
366
+ run_state_directory=run_state_directory,
367
+ is_uncommitted=True,
368
+ )
369
+
370
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
371
+ assert review_outcome.exit_code == 0
372
+ assert review_outcome.jsonl_path is None
373
+ assert not any(
374
+ _is_review_run(each_invocation)
375
+ for each_invocation in recorder.all_invocations
376
+ )
377
+ for each_required_flag in ALL_SHAPE_PROBE_REQUIRED_FLAGS:
378
+ assert each_required_flag in lookalike_help_text
379
+
380
+
381
+ def test_shape_probe_nonzero_help_returns_codex_down(
382
+ monkeypatch: pytest.MonkeyPatch,
383
+ repository_directory: Path,
384
+ run_state_directory: Path,
385
+ ) -> None:
386
+ def behavior(
387
+ all_arguments: list[str],
388
+ ) -> subprocess.CompletedProcess[str] | BaseException:
389
+ if _is_version_probe(all_arguments):
390
+ return _completed(all_arguments, 0, stdout=VERSION_STDOUT)
391
+ if _is_shape_probe(all_arguments):
392
+ return _completed(
393
+ all_arguments,
394
+ 2,
395
+ stderr="error: unrecognized subcommand 'review'\n",
396
+ )
397
+ raise AssertionError("review must not run after a failed shape probe")
398
+
399
+ _install_recorder(monkeypatch, behavior)
400
+
401
+ review_outcome = wrapper.run_codex_review(
402
+ repository_directory=repository_directory,
403
+ run_state_directory=run_state_directory,
404
+ is_uncommitted=True,
405
+ )
406
+
407
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
408
+ assert review_outcome.exit_code == 2
409
+
410
+
411
+ def test_missing_binary_returns_codex_down(
412
+ monkeypatch: pytest.MonkeyPatch,
413
+ repository_directory: Path,
414
+ run_state_directory: Path,
415
+ ) -> None:
416
+ def behavior(
417
+ all_arguments: list[str],
418
+ ) -> subprocess.CompletedProcess[str] | BaseException:
419
+ raise FileNotFoundError(all_arguments[0])
420
+
421
+ _install_recorder(monkeypatch, behavior)
422
+
423
+ review_outcome = wrapper.run_codex_review(
424
+ repository_directory=repository_directory,
425
+ run_state_directory=run_state_directory,
426
+ is_uncommitted=True,
427
+ )
428
+
429
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
430
+ assert review_outcome.exit_code == MISSING_BINARY_EXIT_CODE
431
+ assert review_outcome.jsonl_path is None
432
+
433
+
434
+ def test_jsonl_capture_and_agent_message_extraction(
435
+ monkeypatch: pytest.MonkeyPatch,
436
+ repository_directory: Path,
437
+ run_state_directory: Path,
438
+ ) -> None:
439
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
440
+
441
+ review_outcome = wrapper.run_codex_review(
442
+ repository_directory=repository_directory,
443
+ run_state_directory=run_state_directory,
444
+ is_uncommitted=True,
445
+ )
446
+
447
+ expected_jsonl_path = run_state_directory / JSONL_CAPTURE_FILENAME
448
+ assert review_outcome.outcome_class == OUTCOME_CLASS_COMPLETED
449
+ assert review_outcome.exit_code == 0
450
+ assert review_outcome.jsonl_path == expected_jsonl_path
451
+ assert expected_jsonl_path.read_text(encoding=UTF8_ENCODING) == SUCCESS_JSONL
452
+ assert review_outcome.agent_message == AGENT_MESSAGE_BODY
453
+ assert review_outcome.binary_version == EXPECTED_BINARY_VERSION
454
+ review_keyword_arguments = next(
455
+ each_keyword_arguments
456
+ for each_invocation, each_keyword_arguments in zip(
457
+ recorder.all_invocations,
458
+ recorder.all_keyword_arguments,
459
+ strict=True,
460
+ )
461
+ if _is_review_run(each_invocation)
462
+ )
463
+ assert review_keyword_arguments["cwd"] == str(repository_directory)
464
+ assert review_keyword_arguments["timeout"] == DEFAULT_TIMEOUT_SECONDS
465
+ assert review_keyword_arguments["capture_output"] is True
466
+ assert review_keyword_arguments["text"] is True
467
+ assert review_keyword_arguments["encoding"] == UTF8_ENCODING
468
+ assert review_keyword_arguments["check"] is False
469
+
470
+
471
+ def test_jsonl_capture_preserves_stream_line_endings(
472
+ monkeypatch: pytest.MonkeyPatch,
473
+ repository_directory: Path,
474
+ run_state_directory: Path,
475
+ ) -> None:
476
+ _install_recorder(monkeypatch, _healthy_probe_then_review())
477
+
478
+ review_outcome = wrapper.run_codex_review(
479
+ repository_directory=repository_directory,
480
+ run_state_directory=run_state_directory,
481
+ is_uncommitted=True,
482
+ )
483
+
484
+ assert review_outcome.jsonl_path is not None
485
+ captured_bytes = review_outcome.jsonl_path.read_bytes()
486
+ assert CARRIAGE_RETURN_LINE_ENDING not in captured_bytes
487
+ assert captured_bytes == SUCCESS_JSONL.encode(UTF8_ENCODING)
488
+
489
+
490
+ def test_unicode_decode_error_returns_codex_down(
491
+ monkeypatch: pytest.MonkeyPatch,
492
+ repository_directory: Path,
493
+ run_state_directory: Path,
494
+ ) -> None:
495
+ def behavior(
496
+ all_arguments: list[str],
497
+ ) -> subprocess.CompletedProcess[str] | BaseException:
498
+ raise UnicodeDecodeError("utf-8", b"\xff", 0, 1, "invalid start byte")
499
+
500
+ _install_recorder(monkeypatch, behavior)
501
+
502
+ review_outcome = wrapper.run_codex_review(
503
+ repository_directory=repository_directory,
504
+ run_state_directory=run_state_directory,
505
+ is_uncommitted=True,
506
+ )
507
+
508
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
509
+ assert review_outcome.exit_code == SUBPROCESS_DECODE_EXIT_CODE
510
+ assert review_outcome.jsonl_path is None
511
+
512
+
513
+ def test_timeout_returns_codex_down(
514
+ monkeypatch: pytest.MonkeyPatch,
515
+ repository_directory: Path,
516
+ run_state_directory: Path,
517
+ ) -> None:
518
+ def behavior(
519
+ all_arguments: list[str],
520
+ ) -> subprocess.CompletedProcess[str] | BaseException:
521
+ if _is_version_probe(all_arguments):
522
+ return _completed(all_arguments, 0, stdout=VERSION_STDOUT)
523
+ if _is_shape_probe(all_arguments):
524
+ return _completed(all_arguments, 0, stdout=HELP_TEXT_WITH_TARGETS)
525
+ if _is_review_run(all_arguments):
526
+ return subprocess.TimeoutExpired(cmd=all_arguments, timeout=1)
527
+ raise AssertionError(f"unexpected invocation: {all_arguments!r}")
528
+
529
+ _install_recorder(monkeypatch, behavior)
530
+
531
+ review_outcome = wrapper.run_codex_review(
532
+ repository_directory=repository_directory,
533
+ run_state_directory=run_state_directory,
534
+ is_uncommitted=True,
535
+ timeout_seconds=1,
536
+ )
537
+
538
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
539
+ assert review_outcome.exit_code == TIMEOUT_EXIT_CODE
540
+
541
+
542
+ def test_codex_home_env_is_passed_through_when_set(
543
+ monkeypatch: pytest.MonkeyPatch,
544
+ tmp_path: Path,
545
+ repository_directory: Path,
546
+ run_state_directory: Path,
547
+ ) -> None:
548
+ codex_home_directory = tmp_path / "codex_home"
549
+ codex_home_directory.mkdir()
550
+ monkeypatch.setenv(CODEX_HOME_ENV_VAR, str(codex_home_directory))
551
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
552
+
553
+ wrapper.run_codex_review(
554
+ repository_directory=repository_directory,
555
+ run_state_directory=run_state_directory,
556
+ is_uncommitted=True,
557
+ )
558
+
559
+ for each_keyword_arguments in recorder.all_keyword_arguments:
560
+ process_environment = each_keyword_arguments.get("env")
561
+ assert process_environment is not None
562
+ assert isinstance(process_environment, dict)
563
+ assert process_environment[CODEX_HOME_ENV_VAR] == str(codex_home_directory)
564
+
565
+
566
+ def test_rejects_multiple_targets(
567
+ monkeypatch: pytest.MonkeyPatch,
568
+ repository_directory: Path,
569
+ run_state_directory: Path,
570
+ ) -> None:
571
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
572
+
573
+ with pytest.raises(ValueError):
574
+ wrapper.run_codex_review(
575
+ repository_directory=repository_directory,
576
+ run_state_directory=run_state_directory,
577
+ is_uncommitted=True,
578
+ base_branch="main",
579
+ )
580
+
581
+ assert recorder.all_invocations == []
582
+
583
+
584
+ def test_rejects_missing_target(
585
+ monkeypatch: pytest.MonkeyPatch,
586
+ repository_directory: Path,
587
+ run_state_directory: Path,
588
+ ) -> None:
589
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
590
+
591
+ with pytest.raises(ValueError):
592
+ wrapper.run_codex_review(
593
+ repository_directory=repository_directory,
594
+ run_state_directory=run_state_directory,
595
+ )
596
+
597
+ assert recorder.all_invocations == []
598
+
599
+
600
+ def test_shape_probe_missing_json_flag_returns_codex_down(
601
+ monkeypatch: pytest.MonkeyPatch,
602
+ repository_directory: Path,
603
+ run_state_directory: Path,
604
+ ) -> None:
605
+ help_without_json = (
606
+ "Usage: codex exec review [OPTIONS]\n"
607
+ " --uncommitted\n"
608
+ " --base <BRANCH>\n"
609
+ " --commit <SHA>\n"
610
+ )
611
+ recorder = _install_recorder(
612
+ monkeypatch, _healthy_probe_then_failing_shape(help_without_json)
613
+ )
614
+
615
+ review_outcome = wrapper.run_codex_review(
616
+ repository_directory=repository_directory,
617
+ run_state_directory=run_state_directory,
618
+ is_uncommitted=True,
619
+ )
620
+
621
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
622
+ assert review_outcome.jsonl_path is None
623
+ assert not any(
624
+ _is_review_run(each_invocation)
625
+ for each_invocation in recorder.all_invocations
626
+ )
627
+ assert JSON_FLAG not in help_without_json
628
+ assert JSON_FLAG in ALL_SHAPE_PROBE_REQUIRED_FLAGS
629
+
630
+
631
+ def test_missing_repository_directory_raises_value_error(
632
+ monkeypatch: pytest.MonkeyPatch,
633
+ tmp_path: Path,
634
+ run_state_directory: Path,
635
+ ) -> None:
636
+ missing_repository_directory = tmp_path / "missing-repo"
637
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
638
+
639
+ with pytest.raises(ValueError, match="repository_directory"):
640
+ wrapper.run_codex_review(
641
+ repository_directory=missing_repository_directory,
642
+ run_state_directory=run_state_directory,
643
+ is_uncommitted=True,
644
+ )
645
+
646
+ assert recorder.all_invocations == []
647
+
648
+
649
+ def test_missing_run_state_directory_raises_before_any_codex_process(
650
+ monkeypatch: pytest.MonkeyPatch,
651
+ tmp_path: Path,
652
+ repository_directory: Path,
653
+ ) -> None:
654
+ missing_run_state_directory = tmp_path / "missing-run-state"
655
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
656
+
657
+ with pytest.raises(ValueError, match="run_state_directory"):
658
+ wrapper.run_codex_review(
659
+ repository_directory=repository_directory,
660
+ run_state_directory=missing_run_state_directory,
661
+ is_uncommitted=True,
662
+ )
663
+
664
+ assert recorder.all_invocations == []
665
+
666
+
667
+ def test_custom_instructions_prompt_demands_finding_bullet_format() -> None:
668
+ assert "- [P1]" in CUSTOM_INSTRUCTIONS_PROMPT
669
+ assert "Review comment:" in CUSTOM_INSTRUCTIONS_PROMPT
670
+ assert "fenced JSON" not in CUSTOM_INSTRUCTIONS_PROMPT
671
+ assert "JSON array" not in CUSTOM_INSTRUCTIONS_PROMPT
672
+
673
+
674
+ def test_model_pin_assembles_model_flag_before_review_subcommand(
675
+ monkeypatch: pytest.MonkeyPatch,
676
+ repository_directory: Path,
677
+ run_state_directory: Path,
678
+ ) -> None:
679
+ model_pin = "gpt-5-codex"
680
+ monkeypatch.setattr(wrapper, "CODEX_MODEL_PIN", model_pin)
681
+ recorder = _install_recorder(monkeypatch, _healthy_probe_then_review())
682
+
683
+ wrapper.run_codex_review(
684
+ repository_directory=repository_directory,
685
+ run_state_directory=run_state_directory,
686
+ is_uncommitted=True,
687
+ )
688
+
689
+ review_invocation = _only_review_invocation(recorder)
690
+ model_flag_index = review_invocation.index(MODEL_FLAG)
691
+ review_subcommand_index = review_invocation.index(REVIEW_SUBCOMMAND)
692
+ assert review_invocation[model_flag_index : model_flag_index + 2] == [
693
+ MODEL_FLAG,
694
+ model_pin,
695
+ ]
696
+ assert model_flag_index < review_subcommand_index
697
+
698
+
699
+ def test_review_exit_1_config_error_classifies_codex_down(
700
+ monkeypatch: pytest.MonkeyPatch,
701
+ repository_directory: Path,
702
+ run_state_directory: Path,
703
+ ) -> None:
704
+ config_error_stderr = (
705
+ "Error loading config.toml: unknown variant 'default', "
706
+ "expected 'fast' or 'flex' in 'service_tier'\n"
707
+ )
708
+ recorder = _install_recorder(
709
+ monkeypatch,
710
+ _healthy_probe_then_review(
711
+ review_returncode=1,
712
+ review_stdout="",
713
+ review_stderr=config_error_stderr,
714
+ ),
715
+ )
716
+
717
+ review_outcome = wrapper.run_codex_review(
718
+ repository_directory=repository_directory,
719
+ run_state_directory=run_state_directory,
720
+ is_uncommitted=True,
721
+ )
722
+
723
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
724
+ assert review_outcome.exit_code == 1
725
+ assert review_outcome.agent_message == config_error_stderr
726
+ assert review_outcome.jsonl_path is not None
727
+ assert review_outcome.jsonl_path.read_text(encoding=UTF8_ENCODING) == ""
728
+ assert any(
729
+ _is_review_run(each_invocation)
730
+ for each_invocation in recorder.all_invocations
731
+ )
732
+
733
+
734
+ def test_review_exit_2_argument_error_classifies_codex_down(
735
+ monkeypatch: pytest.MonkeyPatch,
736
+ repository_directory: Path,
737
+ run_state_directory: Path,
738
+ ) -> None:
739
+ argument_error_stderr = (
740
+ "error: the argument '--uncommitted' cannot be used with '[PROMPT]'\n"
741
+ "Usage: codex exec review --json --uncommitted [PROMPT]\n"
742
+ )
743
+ recorder = _install_recorder(
744
+ monkeypatch,
745
+ _healthy_probe_then_review(
746
+ review_returncode=2,
747
+ review_stdout="",
748
+ review_stderr=argument_error_stderr,
749
+ ),
750
+ )
751
+
752
+ review_outcome = wrapper.run_codex_review(
753
+ repository_directory=repository_directory,
754
+ run_state_directory=run_state_directory,
755
+ is_uncommitted=True,
756
+ )
757
+
758
+ assert review_outcome.outcome_class == OUTCOME_CLASS_CODEX_DOWN
759
+ assert review_outcome.exit_code == 2
760
+ assert review_outcome.agent_message == argument_error_stderr
761
+ assert review_outcome.jsonl_path is not None
762
+ assert review_outcome.jsonl_path.read_text(encoding=UTF8_ENCODING) == ""
763
+ assert any(
764
+ _is_review_run(each_invocation)
765
+ for each_invocation in recorder.all_invocations
766
+ )
767
+
768
+
769
+ def test_review_exit_0_stays_completed(
770
+ monkeypatch: pytest.MonkeyPatch,
771
+ repository_directory: Path,
772
+ run_state_directory: Path,
773
+ ) -> None:
774
+ _install_recorder(
775
+ monkeypatch,
776
+ _healthy_probe_then_review(review_returncode=0, review_stdout=SUCCESS_JSONL),
777
+ )
778
+
779
+ review_outcome = wrapper.run_codex_review(
780
+ repository_directory=repository_directory,
781
+ run_state_directory=run_state_directory,
782
+ is_uncommitted=True,
783
+ )
784
+
785
+ assert review_outcome.outcome_class == OUTCOME_CLASS_COMPLETED
786
+ assert review_outcome.exit_code == 0
787
+ assert review_outcome.agent_message == AGENT_MESSAGE_BODY
788
+
789
+
790
+ def test_resolve_prefix_wraps_windows_shim(monkeypatch: pytest.MonkeyPatch) -> None:
791
+ shim_path = r"C:\\Users\\dev\\AppData\\Roaming\\npm\\codex.CMD"
792
+ monkeypatch.setattr(wrapper.shutil, "which", lambda _name: shim_path)
793
+ monkeypatch.setattr(wrapper.os, "name", "nt")
794
+
795
+ assert wrapper._resolve_codex_command_prefix() == ["cmd", "/c", shim_path]
796
+
797
+
798
+ def test_resolve_prefix_uses_resolved_path_on_posix(
799
+ monkeypatch: pytest.MonkeyPatch,
800
+ ) -> None:
801
+ resolved_path = "/usr/local/bin/codex"
802
+ monkeypatch.setattr(wrapper.shutil, "which", lambda _name: resolved_path)
803
+ monkeypatch.setattr(wrapper.os, "name", "posix")
804
+
805
+ assert wrapper._resolve_codex_command_prefix() == [resolved_path]
806
+
807
+
808
+ def test_resolve_prefix_falls_back_to_bare_name_when_absent(
809
+ monkeypatch: pytest.MonkeyPatch,
810
+ ) -> None:
811
+ monkeypatch.setattr(wrapper.shutil, "which", lambda _name: None)
812
+
813
+ assert wrapper._resolve_codex_command_prefix() == [CODEX_BINARY_NAME]
814
+
815
+
816
+ def _is_process_running(process_identifier: int) -> bool:
817
+ if sys.platform == "win32":
818
+ process_listing = subprocess.run(
819
+ ["tasklist", "/FI", f"PID eq {process_identifier}"],
820
+ capture_output=True,
821
+ text=True,
822
+ check=False,
823
+ )
824
+ return str(process_identifier) in process_listing.stdout
825
+ liveness_probe = subprocess.run(
826
+ ["kill", "-0", str(process_identifier)],
827
+ capture_output=True,
828
+ check=False,
829
+ )
830
+ return liveness_probe.returncode == 0
831
+
832
+
833
+ def _wait_until_process_stops(
834
+ process_identifier: int, deadline_seconds: float
835
+ ) -> bool:
836
+ poll_interval_seconds = 0.5
837
+ deadline = time.monotonic() + deadline_seconds
838
+ while time.monotonic() < deadline:
839
+ if not _is_process_running(process_identifier):
840
+ return True
841
+ time.sleep(poll_interval_seconds)
842
+ return not _is_process_running(process_identifier)
843
+
844
+
845
+ def _grandchild_spawn_source(grandchild_pid_path: Path, lifetime_seconds: int) -> str:
846
+ """Python source that spawns a grandchild and records its PID before sleeping.
847
+
848
+ ::
849
+
850
+ Popen(grandchild) -> write grandchild.pid -> sleep grandchild holds pipe
851
+ """
852
+ return (
853
+ "import subprocess, sys, time, pathlib; "
854
+ "grandchild = subprocess.Popen([sys.executable, '-c', "
855
+ f"'import time; time.sleep({lifetime_seconds})']); "
856
+ f"pathlib.Path(r'{grandchild_pid_path}').write_text(str(grandchild.pid)); "
857
+ f"time.sleep({lifetime_seconds})"
858
+ )
859
+
860
+
861
+ def test_run_command_kills_grandchild_tree_on_timeout_without_hanging(
862
+ tmp_path: Path,
863
+ ) -> None:
864
+ """The timeout kills the grandchild that inherited the capture pipe.
865
+
866
+ ::
867
+
868
+ middle -> grandchild, timeout at 2s ok: grandchild PID stops running
869
+ kill only the middle child flag: grandchild lives on 30s
870
+
871
+ A direct-child-only kill leaves the grandchild alive on POSIX, so asserting
872
+ the recorded grandchild PID stops running guards the regression in CI.
873
+ """
874
+ grandchild_lifetime_seconds = 30
875
+ review_timeout_seconds = 2
876
+ wall_clock_ceiling_seconds = 20
877
+ grandchild_pid_path = tmp_path / "grandchild.pid"
878
+ grandchild_source = _grandchild_spawn_source(
879
+ grandchild_pid_path, grandchild_lifetime_seconds
880
+ )
881
+ start_time = time.monotonic()
882
+ with pytest.raises(subprocess.TimeoutExpired):
883
+ wrapper._run_command(
884
+ [sys.executable, "-c", grandchild_source],
885
+ working_directory=tmp_path,
886
+ timeout_seconds=review_timeout_seconds,
887
+ )
888
+ assert time.monotonic() - start_time < wall_clock_ceiling_seconds
889
+ grandchild_identifier = int(grandchild_pid_path.read_text())
890
+ assert _wait_until_process_stops(grandchild_identifier, wall_clock_ceiling_seconds)
891
+
892
+
893
+ def test_drain_joins_pipes_when_direct_kill_raises_process_lookup_error() -> None:
894
+ """Even when the process is already gone, drain still joins pipe readers."""
895
+ all_communicate_timeouts: list[float | None] = []
896
+
897
+ class _AlreadyDeadProcess:
898
+ def communicate(
899
+ self, timeout: float | None = None
900
+ ) -> tuple[str, str]:
901
+ all_communicate_timeouts.append(timeout)
902
+ if len(all_communicate_timeouts) == 1:
903
+ raise subprocess.TimeoutExpired(cmd="codex", timeout=timeout or 0)
904
+ return "", ""
905
+
906
+ def kill(self) -> None:
907
+ raise ProcessLookupError()
908
+
909
+ already_dead_process = _AlreadyDeadProcess()
910
+ wrapper._drain_process_after_tree_kill(
911
+ already_dead_process # type: ignore[arg-type] # duck-typed Popen stand-in
912
+ )
913
+ assert len(all_communicate_timeouts) == 2
914
+
915
+
916
+ def test_reap_process_with_grace_bounds_wait_when_child_survives() -> None:
917
+ """Cleanup kills a surviving child and waits with a grace timeout, not forever."""
918
+ all_wait_timeouts: list[float | None] = []
919
+ all_kill_calls: list[bool] = []
920
+
921
+ class _SurvivingProcess:
922
+ def poll(self) -> int | None:
923
+ return None
924
+
925
+ def kill(self) -> None:
926
+ all_kill_calls.append(True)
927
+
928
+ def wait(self, timeout: float | None = None) -> int:
929
+ all_wait_timeouts.append(timeout)
930
+ raise subprocess.TimeoutExpired(cmd="codex", timeout=timeout or 0)
931
+
932
+ surviving_process = _SurvivingProcess()
933
+ wrapper._reap_process_with_grace(
934
+ surviving_process # type: ignore[arg-type] # duck-typed Popen stand-in
935
+ )
936
+ assert all_kill_calls == [True]
937
+ assert all_wait_timeouts == [wrapper.PROCESS_TREE_KILL_TIMEOUT_SECONDS]
938
+
939
+
940
+ def test_run_command_surfaces_timeout_when_tree_kill_is_noop(
941
+ monkeypatch: pytest.MonkeyPatch,
942
+ tmp_path: Path,
943
+ ) -> None:
944
+ """An incomplete tree kill still raises TimeoutExpired inside a wall ceiling.
945
+
946
+ ::
947
+
948
+ terminate is a no-op, child sleeps 60s ok: TimeoutExpired < 25s wall
949
+ no post-kill drain / fallback kill flag: hang past ceiling on wait
950
+
951
+ The post-kill grace drain and direct-child kill fallback keep the caller
952
+ from blocking forever when taskkill/killpg leave the direct child alive.
953
+ """
954
+ review_timeout_seconds = 1
955
+ wall_clock_ceiling_seconds = 25
956
+ sleep_source = "import time; time.sleep(60)"
957
+
958
+ def leave_process_alive(_review_process: object) -> None:
959
+ return None
960
+
961
+ monkeypatch.setattr(wrapper, "terminate_process_tree", leave_process_alive)
962
+ start_time = time.monotonic()
963
+ with pytest.raises(subprocess.TimeoutExpired):
964
+ wrapper._run_command(
965
+ [sys.executable, "-c", sleep_source],
966
+ working_directory=tmp_path,
967
+ timeout_seconds=review_timeout_seconds,
968
+ )
969
+ assert time.monotonic() - start_time < wall_clock_ceiling_seconds