claude-dev-env 4.3.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/.agents/agents/pr-description-writer.md +2 -2
  2. package/.agents/agents/test_agent_frontmatter.py +2 -2
  3. package/.agents/agents/test_pr_description_writer_style.py +1 -3
  4. package/.agents/skills/e-code-review/SKILL.md +12 -12
  5. package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
  6. package/.agents/skills/e-code-review/reference/fix.md +15 -17
  7. package/.agents/skills/e-code-review/reference/loop.md +35 -39
  8. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
  9. package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
  10. package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
  11. package/.agents/skills/issue-tracker/SKILL.md +5 -4
  12. package/.agents/skills/pull-request/SKILL.md +11 -13
  13. package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
  14. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
  15. package/.agents/skills/pull-request/scripts/pull_request.py +35 -44
  16. package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
  17. package/.agents/skills/pull-request/scripts/test_pull_request.py +35 -3
  18. package/.agents/skills/session-continuity/README.md +189 -0
  19. package/.agents/skills/session-continuity/SKILL.md +114 -0
  20. package/.agents/skills/session-continuity/continuity.mjs +375 -0
  21. package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
  22. package/.agents/skills/skill-builder/SKILL.md +3 -196
  23. package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
  24. package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
  25. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  26. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  27. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  28. package/bin/cde.mjs +36 -8
  29. package/bin/cde.test.mjs +48 -0
  30. package/bin/ever-shipped-skills.mjs +2 -20
  31. package/bin/ever-shipped-skills.test.mjs +8 -0
  32. package/bin/expand_home_directory_tokens.mjs +4 -5
  33. package/bin/expand_home_directory_tokens.test.mjs +128 -0
  34. package/bin/git_hooks_installer.mjs +22 -3
  35. package/bin/git_hooks_installer.test.mjs +159 -5
  36. package/bin/install-session-continuity.mjs +78 -0
  37. package/bin/install-session-continuity.test.mjs +42 -0
  38. package/bin/install.agents-home.test.mjs +15 -13
  39. package/bin/install.codex-rules.test.mjs +5 -2
  40. package/bin/install.cursor-rules.test.mjs +5 -2
  41. package/bin/install.mjs +506 -63
  42. package/bin/install.policy-lint.test.mjs +130 -0
  43. package/bin/install.profiles.test.mjs +10 -0
  44. package/bin/install.prune.test.mjs +286 -37
  45. package/bin/install.pstack-plugin.test.mjs +114 -0
  46. package/bin/install.test.mjs +537 -120
  47. package/bin/install.transaction.test.mjs +3 -3
  48. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  49. package/docs/CODE_RULES.md +1 -1
  50. package/hooks/advisory/pr_done_reminder.py +342 -0
  51. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  52. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  53. package/hooks/blocking/code_rules_banned_identifiers.py +3 -0
  54. package/hooks/blocking/code_rules_paired_test.py +22 -15
  55. package/hooks/blocking/precommit_code_rules_gate.py +5 -8
  56. package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
  57. package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
  58. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
  59. package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
  60. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  61. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  62. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  63. package/hooks/blocking/test_pre_tool_use_dispatcher.py +43 -342
  64. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  65. package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
  66. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  67. package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
  68. package/hooks/git-hooks/post_commit.py +33 -0
  69. package/hooks/git-hooks/pre_commit.py +18 -49
  70. package/hooks/git-hooks/pre_push.py +45 -541
  71. package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
  72. package/hooks/git-hooks/test_native_hook_support.py +129 -0
  73. package/hooks/git-hooks/test_native_policy_commit.py +120 -0
  74. package/hooks/git-hooks/test_post_commit.py +43 -0
  75. package/hooks/git-hooks/test_pre_commit.py +38 -148
  76. package/hooks/git-hooks/test_pre_push.py +48 -1631
  77. package/hooks/git-hooks/test_verification_notice.py +60 -0
  78. package/hooks/git-hooks/test_verification_start.py +173 -0
  79. package/hooks/git-hooks/verification_notice.py +192 -0
  80. package/hooks/git-hooks/verification_notice_context.py +253 -0
  81. package/hooks/git-hooks/verification_notice_state.py +237 -0
  82. package/hooks/git-hooks/verification_start.py +100 -0
  83. package/hooks/hooks.json +1 -120
  84. package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
  85. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
  86. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
  87. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
  88. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  89. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
  90. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
  91. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
  92. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
  93. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  94. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
  95. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
  96. package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
  97. package/hooks/validators/run_all_validators.py +5 -1
  98. package/hooks/validators/security_checks.py +57 -2
  99. package/hooks/validators/test_hook_timing_harness.py +2 -5
  100. package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
  101. package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
  102. package/hooks/validators/test_security_checks.py +57 -0
  103. package/package.json +2 -2
  104. package/rules/confirm-implementation-forks.md +2 -0
  105. package/rules/durable-post-artifacts.md +2 -1
  106. package/rules/git-workflow.md +18 -6
  107. package/rules/pstack-host-mapping.md +48 -0
  108. package/rules/vault-context.md +3 -5
  109. package/rules/verify-runtime-state.md +7 -0
  110. package/scripts/audit-hooks-cli.mjs +5 -0
  111. package/scripts/audit-hooks.mjs +72 -16
  112. package/scripts/automatic_advisory/__init__.py +1 -0
  113. package/scripts/automatic_advisory/checkout.py +51 -0
  114. package/scripts/automatic_advisory/cli.py +334 -0
  115. package/scripts/automatic_advisory/config/__init__.py +1 -0
  116. package/scripts/automatic_advisory/config/constants.py +93 -0
  117. package/scripts/automatic_advisory/config/timing.py +4 -0
  118. package/scripts/automatic_advisory/configuration.py +197 -0
  119. package/scripts/automatic_advisory/execution.py +350 -0
  120. package/scripts/automatic_advisory/git.py +69 -0
  121. package/scripts/automatic_advisory/model.py +107 -0
  122. package/scripts/automatic_advisory/process_host.py +32 -0
  123. package/scripts/automatic_advisory/publisher.py +84 -0
  124. package/scripts/automatic_advisory/runner.py +399 -0
  125. package/scripts/automatic_advisory/state.py +116 -0
  126. package/scripts/automatic_advisory/window_flags.py +41 -0
  127. package/scripts/automatic_advisory/windows_job.py +122 -0
  128. package/scripts/check.ps1 +0 -1
  129. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  130. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  131. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  132. package/scripts/codex_compat_materializer.py +99 -13
  133. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  134. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
  135. package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
  136. package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
  137. package/scripts/local_report_cli.py +184 -0
  138. package/scripts/local_report_core.py +247 -0
  139. package/scripts/local_report_publisher.py +12 -0
  140. package/scripts/local_report_validation.py +357 -0
  141. package/scripts/local_verification/__init__.py +23 -0
  142. package/scripts/local_verification/check_runner.py +364 -0
  143. package/scripts/local_verification/check_support.py +99 -0
  144. package/scripts/local_verification/cli.py +158 -0
  145. package/scripts/local_verification/command_runner.py +84 -0
  146. package/scripts/local_verification/config/__init__.py +1 -0
  147. package/scripts/local_verification/config/constants.py +89 -0
  148. package/scripts/local_verification/config/timing.py +1 -0
  149. package/scripts/local_verification/git_state.py +146 -0
  150. package/scripts/local_verification/manifest.py +224 -0
  151. package/scripts/local_verification/model.py +174 -0
  152. package/scripts/local_verification/runner.py +234 -0
  153. package/scripts/policy_lint/adapter_detectors.py +13 -6
  154. package/scripts/policy_lint/adapter_pairing.py +58 -3
  155. package/scripts/policy_lint/adapters.py +7 -4
  156. package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
  157. package/scripts/policy_lint/config/constants.py +5 -0
  158. package/scripts/policy_lint/engine.py +48 -4
  159. package/scripts/policy_lint/model.py +1 -0
  160. package/scripts/policy_lint/registry.py +1 -1
  161. package/scripts/policy_lint/selection.py +2 -1
  162. package/scripts/policy_lint/selection_git.py +2 -0
  163. package/scripts/pr_verification/__init__.py +1 -0
  164. package/scripts/pr_verification/branch_refs.py +114 -0
  165. package/scripts/pr_verification/config/__init__.py +1 -0
  166. package/scripts/pr_verification/config/constants.py +84 -0
  167. package/scripts/pr_verification/config/timing.py +5 -0
  168. package/scripts/pr_verification/github.py +137 -0
  169. package/scripts/pr_verification/github_api.py +376 -0
  170. package/scripts/pr_verification/github_labels.py +88 -0
  171. package/scripts/pr_verification/github_parsing.py +182 -0
  172. package/scripts/pr_verification/github_transport.py +91 -0
  173. package/scripts/pr_verification/lock.py +122 -0
  174. package/scripts/pr_verification/model.py +43 -0
  175. package/scripts/pr_verification/requirements.txt +1 -0
  176. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  177. package/scripts/shared_tree_paths.py +32 -3
  178. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
  179. package/scripts/test_shared_tree_paths.py +33 -0
  180. package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
  181. package/scripts/tests/test-audit-hooks.mjs +94 -2
  182. package/scripts/tests/test_automatic_advisory.py +376 -0
  183. package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
  184. package/scripts/tests/test_automatic_advisory_polling.py +216 -0
  185. package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
  186. package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
  187. package/scripts/tests/test_automatic_advisory_settings.py +48 -0
  188. package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
  189. package/scripts/tests/test_closed_pr_label.py +157 -0
  190. package/scripts/tests/test_codex_compat_materializer.py +189 -6
  191. package/scripts/tests/test_github_labels.py +101 -0
  192. package/scripts/tests/test_github_transport.py +125 -0
  193. package/scripts/tests/test_local_report_publisher.py +396 -0
  194. package/scripts/tests/test_local_report_publisher_cli.py +85 -0
  195. package/scripts/tests/test_local_verification.py +348 -0
  196. package/scripts/tests/test_local_verification_cli.py +98 -0
  197. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  198. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  199. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  200. package/scripts/tests/test_policy_lint_rules_pairing.py +163 -0
  201. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  202. package/scripts/tests/test_policy_lint_selection.py +25 -2
  203. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  204. package/scripts/tests/test_pr_verification_github.py +392 -0
  205. package/scripts/tests/test_pr_verification_lock.py +168 -0
  206. package/scripts/tests/test_rules.py +3 -7
  207. package/scripts/tests/test_verification_notice.py +347 -0
  208. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  209. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  210. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  211. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  212. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  213. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  214. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  215. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  216. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  217. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  218. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  219. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  220. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  221. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  222. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  223. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  224. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  225. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  226. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  227. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  228. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  229. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  230. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  231. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  232. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  233. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  234. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  235. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  236. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  237. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  238. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  239. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  240. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  241. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  242. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  243. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  244. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  245. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  246. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  247. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  248. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  249. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  250. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  251. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  252. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  253. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  254. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  255. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  256. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  257. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  258. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  259. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  260. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  261. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  262. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  263. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  264. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  265. package/.agents/skills/autoconverge/SKILL.md +0 -431
  266. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  267. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  268. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  269. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  270. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  271. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  272. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  273. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  274. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  275. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  276. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  277. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  278. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  279. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  280. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  281. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  282. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  283. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  284. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  285. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  286. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  287. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  288. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  289. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  290. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  291. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  292. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  293. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  294. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  295. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  296. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  297. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  298. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  299. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  300. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  301. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  302. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  303. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  304. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  305. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  306. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  307. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  308. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  309. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  310. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  311. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  312. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  313. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  314. package/.agents/skills/hitl/SKILL.md +0 -45
  315. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  316. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  317. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  318. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  319. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  320. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  321. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  322. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  323. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  324. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  325. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  326. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  327. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  328. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  329. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  330. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  331. package/.agents/skills/prototype/SKILL.md +0 -85
  332. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  333. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  334. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  335. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  336. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  337. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  338. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  339. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  340. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  341. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  342. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  343. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  344. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  345. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  346. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  347. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  348. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  349. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  350. package/.agents/skills/rebase/AGENTS.md +0 -1
  351. package/.agents/skills/rebase/SKILL.md +0 -178
  352. package/.agents/skills/review-router/SKILL.md +0 -51
  353. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  354. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  355. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  356. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  357. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  358. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  359. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  360. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  361. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  362. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  363. package/.agents/skills/review-tier/SKILL.md +0 -56
  364. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  365. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  366. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  367. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  368. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  369. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  370. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  371. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  372. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  373. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  374. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  375. package/.agents/skills/session-log/AGENTS.md +0 -1
  376. package/.agents/skills/session-log/SKILL.md +0 -170
  377. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  378. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  379. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  380. package/.agents/skills/session-tidy/SKILL.md +0 -191
  381. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  382. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  383. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  384. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  385. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  386. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  387. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  388. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  389. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  390. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  391. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  392. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  393. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  394. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  395. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  396. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  397. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  398. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  399. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  400. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  401. package/.agents/skills/update/AGENTS.md +0 -1
  402. package/.agents/skills/update/SKILL.md +0 -190
  403. package/_shared/pr-loop/AGENTS.md +0 -1
  404. package/_shared/pr-loop/audit-contract.md +0 -183
  405. package/_shared/pr-loop/audit-reply-template.md +0 -151
  406. package/_shared/pr-loop/code-rules-gate.md +0 -65
  407. package/_shared/pr-loop/fix-protocol.md +0 -60
  408. package/_shared/pr-loop/gh-payloads.md +0 -75
  409. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  410. package/_shared/pr-loop/precatch-rubric.md +0 -66
  411. package/_shared/pr-loop/preflight-proposal.md +0 -56
  412. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  413. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  414. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  415. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  416. package/_shared/pr-loop/state-schema.md +0 -45
  417. package/_shared/pr-loop/worker-spawn.md +0 -189
  418. package/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
  419. package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
  420. package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
  421. package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
  422. package/hooks/blocking/destructive_command_blocker.py +0 -2073
  423. package/hooks/blocking/fable_spawn_gate.py +0 -187
  424. package/hooks/blocking/luna_fast_mode_gate.py +0 -160
  425. package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
  426. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
  427. package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
  428. package/hooks/blocking/pii_prevention_blocker.py +0 -365
  429. package/hooks/blocking/piped_pytest_blocker.py +0 -1223
  430. package/hooks/blocking/question_to_user_enforcer.py +0 -130
  431. package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
  432. package/hooks/blocking/sensitive_file_protector.py +0 -167
  433. package/hooks/blocking/session_edit_stage_gate.py +0 -684
  434. package/hooks/blocking/session_handoff_blocker.py +0 -182
  435. package/hooks/blocking/shell_substitution_blocker.py +0 -350
  436. package/hooks/blocking/test_ask_user_question_shape.py +0 -69
  437. package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
  438. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
  439. package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
  440. package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
  441. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
  442. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
  443. package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
  444. package/hooks/blocking/test_fable_spawn_gate.py +0 -381
  445. package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
  446. package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
  447. package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
  448. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
  449. package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
  450. package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
  451. package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
  452. package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
  453. package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
  454. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
  455. package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
  456. package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
  457. package/hooks/blocking/test_sensitive_file_protector.py +0 -365
  458. package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
  459. package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
  460. package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
  461. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
  462. package/hooks/blocking/test_session_handoff_blocker.py +0 -318
  463. package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
  464. package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
  465. package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
  466. package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
  467. package/hooks/blocking/unscoped_search_blocker.py +0 -391
  468. package/hooks/blocking/write_existing_file_blocker.py +0 -124
  469. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
  470. package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
  471. package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
  472. package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
  473. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
  474. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
  475. package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
  476. package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
  477. package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
  478. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
  479. /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
  480. /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
@@ -1,472 +0,0 @@
1
- import { test } from 'node:test';
2
- import { strict as assert } from 'node:assert';
3
- import { readFileSync } from 'node:fs';
4
- import { fileURLToPath } from 'node:url';
5
- import { dirname, join } from 'node:path';
6
-
7
- const workflowDirectory = dirname(fileURLToPath(import.meta.url));
8
- const convergeSource = readFileSync(join(workflowDirectory, 'converge.mjs'), 'utf8');
9
- const skillSource = readFileSync(join(workflowDirectory, '..', 'SKILL.md'), 'utf8');
10
- const stopConditionsSource = readFileSync(
11
- join(workflowDirectory, '..', 'reference', 'stop-conditions.md'),
12
- 'utf8',
13
- );
14
-
15
- function functionBody(functionName) {
16
- const functionStart = convergeSource.indexOf(`function ${functionName}(`);
17
- assert.notEqual(functionStart, -1, `expected ${functionName} to exist`);
18
- const nextFunctionStart = convergeSource.indexOf('\nfunction ', functionStart + 1);
19
- const functionEnd = nextFunctionStart === -1 ? convergeSource.length : nextFunctionStart;
20
- return convergeSource.slice(functionStart, functionEnd);
21
- }
22
-
23
- const productionModule = new Function(
24
- `${functionBody('classifyCodexGateOutcome')}\n` +
25
- 'return { classifyCodexGateOutcome };',
26
- )();
27
- const { classifyCodexGateOutcome } = productionModule;
28
-
29
- function codexResult(overrides) {
30
- return {
31
- sha: 'abcdef0',
32
- clean: false,
33
- down: false,
34
- skipped: false,
35
- skipReason: '',
36
- findings: [],
37
- ...overrides,
38
- };
39
- }
40
-
41
- function codexFinding(overrides) {
42
- return {
43
- file: 'a.py',
44
- line: 1,
45
- severity: 'P1',
46
- category: 'bug',
47
- title: 't',
48
- detail: 'd',
49
- replyToCommentId: null,
50
- ...overrides,
51
- };
52
- }
53
-
54
- test('a required clean Codex result routes to clean so the run stamps codex-clean HEAD', () => {
55
- const outcome = classifyCodexGateOutcome(codexResult({ clean: true }));
56
- assert.equal(outcome.kind, 'clean');
57
- });
58
-
59
- test('an opt-out token skip routes to skip-token', () => {
60
- const outcome = classifyCodexGateOutcome(
61
- codexResult({ clean: true, down: true, skipped: true, skipReason: 'token' }),
62
- );
63
- assert.equal(outcome.kind, 'skip-token');
64
- });
65
-
66
- test('a usage-threshold skip routes to skip-usage', () => {
67
- const outcome = classifyCodexGateOutcome(
68
- codexResult({ clean: true, down: false, skipped: true, skipReason: 'usage' }),
69
- );
70
- assert.equal(outcome.kind, 'skip-usage');
71
- });
72
-
73
- test('a codex_down result routes to down', () => {
74
- const outcome = classifyCodexGateOutcome(codexResult({ clean: false, down: true }));
75
- assert.equal(outcome.kind, 'down');
76
- });
77
-
78
- test('Codex findings route to a fix when the review completed with findings', () => {
79
- const outcome = classifyCodexGateOutcome(
80
- codexResult({
81
- findings: [codexFinding()],
82
- }),
83
- );
84
- assert.equal(outcome.kind, 'fix');
85
- assert.equal(outcome.findings.length, 1);
86
- });
87
-
88
- test('a dead Codex gate agent retries rather than passing', () => {
89
- assert.equal(classifyCodexGateOutcome(null).kind, 'retry');
90
- });
91
-
92
- test('a reachable Codex gate with no findings and no clean verdict retries', () => {
93
- const outcome = classifyCodexGateOutcome(codexResult({ clean: false, down: false }));
94
- assert.equal(outcome.kind, 'retry');
95
- });
96
-
97
- test('skipped with an unknown skipReason retries rather than silently advancing', () => {
98
- const outcome = classifyCodexGateOutcome(
99
- codexResult({ skipped: true, skipReason: 'mystery' }),
100
- );
101
- assert.equal(outcome.kind, 'retry');
102
- });
103
-
104
- test('CODEX_SCHEMA requires skipped and skipReason drawn from the skip-reason constant', () => {
105
- const schemaStart = convergeSource.indexOf('const CODEX_SCHEMA =');
106
- const schemaEnd = convergeSource.indexOf('const COPILOT_VERIFY_VERDICTS =');
107
- assert.notEqual(schemaStart, -1, 'expected CODEX_SCHEMA to exist');
108
- const schemaSource = convergeSource.slice(schemaStart, schemaEnd);
109
- assert.match(schemaSource, /skipped:\s*\{\s*type:\s*'boolean'/);
110
- assert.match(schemaSource, /enum:\s*CODEX_SKIP_REASONS/);
111
- assert.match(schemaSource, /required:\s*\[[^\]]*'skipped'[^\]]*\]/);
112
- assert.match(schemaSource, /required:\s*\[[^\]]*'skipReason'[^\]]*\]/);
113
- });
114
-
115
- test('the Codex gate prompt honors reviews_disabled.py with only --reviewer codex', () => {
116
- const codexPrompt = functionBody('runCodexGate');
117
- const reviewsDisabledIndex = codexPrompt.indexOf('reviews_disabled.py');
118
- assert.notEqual(reviewsDisabledIndex, -1, 'expected reviews_disabled.py invocation');
119
- const invocationLineEnd = codexPrompt.indexOf('\\n', reviewsDisabledIndex);
120
- const invocationLine = codexPrompt.slice(reviewsDisabledIndex, invocationLineEnd);
121
- assert.match(invocationLine, /--reviewer codex/);
122
- assert.doesNotMatch(invocationLine, /--owner|--repo/);
123
- });
124
-
125
- test('the Codex gate prompt decides required vs skip only through is_codex_review_required', () => {
126
- const codexPrompt = functionBody('runCodexGate');
127
- assert.match(codexPrompt, /codex_usage_probe\.py/, 'expected the usage probe CLI');
128
- assert.match(
129
- codexPrompt,
130
- /is_codex_review_required/,
131
- 'expected the shared probe helper rather than an inline percent threshold',
132
- );
133
- assert.doesNotMatch(
134
- codexPrompt,
135
- /WEEKLY_USAGE_GATE_THRESHOLD_PERCENT|\b10\s*%|\bpercent_left\s*[><=]/,
136
- 'expected no duplicate threshold literal or inline comparison in the gate prompt',
137
- );
138
- });
139
-
140
- test('the Codex gate prompt treats a non-zero usage-probe exit as codex_down not usage skip', () => {
141
- const codexPrompt = functionBody('runCodexGate');
142
- assert.match(
143
- codexPrompt,
144
- /Non-zero exit means the Codex CLI or probe is broken/,
145
- 'expected an explicit non-zero probe exit branch',
146
- );
147
- assert.match(
148
- codexPrompt,
149
- /Never map a failed probe to skipReason:'usage'/,
150
- 'expected failed probe to be barred from the usage-skip path',
151
- );
152
- assert.match(
153
- codexPrompt,
154
- /clean:false, down:true, skipped:false, skipReason:''/,
155
- 'expected failed probe to return the codex_down schema shape',
156
- );
157
- });
158
-
159
- test('the Codex gate prompt sys.path insert uses CONFIG.codexScripts not a literal $HOME token', () => {
160
- const codexPrompt = functionBody('runCodexGate');
161
- assert.match(
162
- codexPrompt,
163
- /sys\.path\.insert\(0, r'\$\{CONFIG\.codexScripts\}'\)/,
164
- 'expected sys.path.insert to interpolate CONFIG.codexScripts (home-expanded at CONFIG build)',
165
- );
166
- assert.doesNotMatch(
167
- codexPrompt,
168
- /sys\.path\.insert\(0, r'\$HOME/,
169
- 'expected no unexpanded $HOME inside the Python raw-string path',
170
- );
171
- });
172
-
173
- test('the Codex gate prompt runs the review wrapper against the PR base branch', () => {
174
- const codexPrompt = functionBody('runCodexGate');
175
- assert.match(codexPrompt, /run_codex_review/, 'expected the codex-review wrapper');
176
- assert.match(codexPrompt, /base_branch/, 'expected the wrapper to receive the PR base');
177
- assert.match(codexPrompt, /\.base\.ref/, 'expected the agent to resolve the PR base ref');
178
- assert.match(codexPrompt, /parse_codex_findings/, 'expected findings to come from the shared parser');
179
- });
180
-
181
- test('the Codex gate prompt passes an explicit generous timeout so a slow-but-healthy review is not cut short', () => {
182
- const codexPrompt = functionBody('runCodexGate');
183
- assert.match(
184
- codexPrompt,
185
- /timeout_seconds=\$\{CONFIG\.codexReviewTimeoutSeconds\}/,
186
- 'expected the driver to pass CONFIG.codexReviewTimeoutSeconds, overriding the too-small wrapper default',
187
- );
188
- });
189
-
190
- test('CONFIG.codexReviewTimeoutSeconds exceeds the observed real Codex runtime', () => {
191
- const match = convergeSource.match(/codexReviewTimeoutSeconds:\s*(\d+)/);
192
- assert.notEqual(match, null, 'expected CONFIG.codexReviewTimeoutSeconds to be defined');
193
- const budgetSeconds = Number(match[1]);
194
- assert.ok(
195
- budgetSeconds >= 900,
196
- `expected a budget comfortably above the ~683s measured Codex runtime, got ${budgetSeconds}`,
197
- );
198
- });
199
-
200
- test('the Codex gate prompt runs the review in the background rather than the default foreground timeout', () => {
201
- const codexPrompt = functionBody('runCodexGate');
202
- assert.match(
203
- codexPrompt,
204
- /run_in_background/i,
205
- 'expected the review driver to run in the background — the foreground tool timeout caps below the review runtime and would kill a healthy review',
206
- );
207
- assert.match(
208
- codexPrompt,
209
- /result file/i,
210
- 'expected the driver to persist its outcome to a result file the agent reads once the background run finishes',
211
- );
212
- });
213
-
214
- test('the Codex gate prompt waits for the background review inside the same turn with a bounded Monitor loop', () => {
215
- const codexPrompt = functionBody('runCodexGate');
216
- assert.match(codexPrompt, /Monitor tool/, 'expected a same-turn Monitor wait for the background review');
217
- assert.match(codexPrompt, /until-loop/, 'expected a bounded until-loop that re-checks the result file');
218
- assert.match(codexPrompt, /codexReviewPollIntervalSeconds/, 'expected a named poll interval in the wait protocol');
219
- assert.match(codexPrompt, /codexReviewMaxPolls/, 'expected a named attempt budget in the wait protocol');
220
- assert.match(
221
- codexPrompt,
222
- /Do NOT end this turn/i,
223
- 'expected an explicit instruction against ending the schema-bearing turn to await the background run',
224
- );
225
- });
226
-
227
- test('the Codex background-review poll budget covers the review timeout', () => {
228
- const intervalMatch = convergeSource.match(/codexReviewPollIntervalSeconds:\s*(\d+)/);
229
- const pollsMatch = convergeSource.match(/codexReviewMaxPolls:\s*(\d+)/);
230
- const timeoutMatch = convergeSource.match(/codexReviewTimeoutSeconds:\s*(\d+)/);
231
- assert.notEqual(intervalMatch, null, 'expected codexReviewPollIntervalSeconds in CONFIG');
232
- assert.notEqual(pollsMatch, null, 'expected codexReviewMaxPolls in CONFIG');
233
- assert.notEqual(timeoutMatch, null, 'expected codexReviewTimeoutSeconds in CONFIG');
234
- const intervalSeconds = Number(intervalMatch[1]);
235
- const maxPolls = Number(pollsMatch[1]);
236
- const timeoutSeconds = Number(timeoutMatch[1]);
237
- assert.ok(
238
- intervalSeconds * maxPolls >= timeoutSeconds,
239
- `expected the poll budget ${intervalSeconds * maxPolls}s to cover the ${timeoutSeconds}s review timeout`,
240
- );
241
- });
242
-
243
- test('the Codex gate prompt returns codex_down when the background poll budget is spent', () => {
244
- const codexPrompt = functionBody('runCodexGate');
245
- assert.match(
246
- codexPrompt,
247
- /full poll budget is spent with no result file[\s\S]*?down:true/,
248
- 'expected a spent-budget branch that returns the codex_down schema shape',
249
- );
250
- });
251
-
252
- test('meta Codex gate phase describes codex_down as a non-blocking skip that logs a note', () => {
253
- const phaseStart = convergeSource.indexOf("title: 'Codex gate'");
254
- const phaseEnd = convergeSource.indexOf("title: 'Finalize'");
255
- assert.notEqual(phaseStart, -1, 'expected a Codex gate phase in meta');
256
- const codexPhaseDetail = convergeSource.slice(phaseStart, phaseEnd);
257
- assert.match(codexPhaseDetail, /codex_down/, 'expected the phase detail to name codex_down');
258
- assert.match(
259
- codexPhaseDetail,
260
- /codex_down, the gate skips without blocking/,
261
- 'expected codex_down to be described as a non-blocking skip',
262
- );
263
- assert.match(
264
- codexPhaseDetail,
265
- /logged as a note/,
266
- 'expected the codex_down skip to be logged as a note so the bypass stays visible',
267
- );
268
- assert.doesNotMatch(
269
- codexPhaseDetail,
270
- /holds the PR as a draft with a codex-down blocker/,
271
- 'codex_down must not be described as holding the PR draft with a blocker',
272
- );
273
- });
274
-
275
- test('CODEX_SCHEMA down.description describes codex_down as a skipped, bypassed gate recorded as a note', () => {
276
- const schemaStart = convergeSource.indexOf('const CODEX_SCHEMA =');
277
- const schemaEnd = convergeSource.indexOf('const COPILOT_VERIFY_VERDICTS =');
278
- assert.notEqual(schemaStart, -1, 'expected CODEX_SCHEMA to exist');
279
- const schemaSource = convergeSource.slice(schemaStart, schemaEnd);
280
- const downLineStart = schemaSource.indexOf('down: {');
281
- const downLine = schemaSource.slice(downLineStart, schemaSource.indexOf('\n', downLineStart));
282
- assert.match(downLine, /codex_down/, 'expected the down description to name codex_down');
283
- assert.match(downLine, /skipped and bypassed/, 'expected codex_down to be described as a skipped, bypassed gate');
284
- assert.match(downLine, /recorded as a note/, 'expected codex_down to be recorded as a note');
285
- assert.doesNotMatch(
286
- downLine,
287
- /holds the PR as a draft with a codex-down blocker/,
288
- 'the down description must not claim codex_down holds the PR draft as a blocker',
289
- );
290
- });
291
-
292
- test('the CODEX phase stamps codexCleanAt on clean and clears it on an opt-out, usage, or down skip', () => {
293
- const codexPhaseStart = convergeSource.indexOf("if (phase === 'CODEX') {");
294
- const finalizePhaseStart = convergeSource.indexOf("if (phase === 'FINALIZE') {", codexPhaseStart);
295
- assert.notEqual(codexPhaseStart, -1, 'expected a CODEX phase block');
296
- assert.notEqual(finalizePhaseStart, -1, 'expected FINALIZE after CODEX');
297
- const codexPhase = convergeSource.slice(codexPhaseStart, finalizePhaseStart);
298
- assert.match(codexPhase, /await runCodexGate\(head\)/);
299
- assert.match(codexPhase, /classifyCodexGateOutcome\(codex\)/);
300
- assert.match(codexPhase, /codexCleanAt = head/, 'expected a clean pass to stamp the HEAD');
301
- assert.match(codexPhase, /skip-token[\s\S]*codexDown = true[\s\S]*codexCleanAt = null/);
302
- assert.match(codexPhase, /skip-usage[\s\S]*codexDown = false[\s\S]*codexCleanAt = null/);
303
- assert.match(codexPhase, /kind === 'down'[\s\S]*codexDown = true[\s\S]*codexCleanAt = null/);
304
- });
305
-
306
- test('the CODEX phase skips a genuine codex_down gracefully, recording a note and advancing to mark-ready', () => {
307
- const codexPhaseStart = convergeSource.indexOf("if (phase === 'CODEX') {");
308
- const finalizePhaseStart = convergeSource.indexOf("if (phase === 'FINALIZE') {", codexPhaseStart);
309
- const codexPhase = convergeSource.slice(codexPhaseStart, finalizePhaseStart);
310
- const downBranchStart = codexPhase.indexOf("codexOutcome.kind === 'down'");
311
- const downBranchEnd = codexPhase.indexOf("codexOutcome.kind === 'fix'", downBranchStart);
312
- assert.notEqual(downBranchStart, -1, 'expected a codex_down branch in the CODEX phase');
313
- assert.notEqual(downBranchEnd, -1, 'expected a fix branch after the down branch');
314
- const downBranch = codexPhase.slice(downBranchStart, downBranchEnd);
315
- assert.match(downBranch, /codexNote =/, 'a genuine codex_down records a transparent note');
316
- assert.match(downBranch, /codexDown = true/, 'the down branch sets the bypass flag so mark-ready skips the required Codex gate');
317
- assert.match(downBranch, /codexCleanAt = null/, 'the down branch clears any codex-clean stamp');
318
- assert.match(
319
- downBranch,
320
- /phase = 'FINALIZE'/,
321
- 'a genuine codex_down advances to mark-ready with the gate bypassed rather than blocking the run',
322
- );
323
- assert.doesNotMatch(downBranch, /blocker =/, 'a genuine codex_down must not record a blocker');
324
- assert.doesNotMatch(downBranch, /\bbreak\b/, 'the down branch continues rather than breaking the loop');
325
- });
326
-
327
- test('the workflow return object includes codexNote so the final report surfaces the Codex skip', () => {
328
- const assembleStart = convergeSource.indexOf('const assembleResult =');
329
- assert.notEqual(assembleStart, -1, 'expected assembleResult to exist');
330
- const assembleEnd = convergeSource.indexOf('})', assembleStart);
331
- assert.notEqual(assembleEnd, -1, 'expected the assembleResult object to close');
332
- const assembleSource = convergeSource.slice(assembleStart, assembleEnd);
333
- assert.match(assembleSource, /codexNote,/, 'expected codexNote among the returned notes');
334
- });
335
-
336
- test('the CODEX phase routes findings through applyFixes and re-enters CONVERGE', () => {
337
- const codexPhaseStart = convergeSource.indexOf("if (phase === 'CODEX') {");
338
- const finalizePhaseStart = convergeSource.indexOf("if (phase === 'FINALIZE') {", codexPhaseStart);
339
- const codexPhase = convergeSource.slice(codexPhaseStart, finalizePhaseStart);
340
- assert.match(codexPhase, /applyFixes\(head, codexOutcome\.findings, 'codex'\)/);
341
- assert.match(codexPhase, /phase = 'CONVERGE'/);
342
- assert.match(codexPhase, /head = null/);
343
- });
344
-
345
- test('the COPILOT phase advances to CODEX rather than FINALIZE on a clean or bypass path', () => {
346
- const copilotPhaseStart = convergeSource.indexOf("if (phase === 'COPILOT') {");
347
- const codexPhaseStart = convergeSource.indexOf("if (phase === 'CODEX') {", copilotPhaseStart);
348
- assert.notEqual(copilotPhaseStart, -1, 'expected a COPILOT phase block');
349
- assert.notEqual(codexPhaseStart, -1, 'expected a CODEX phase after COPILOT');
350
- const copilotPhase = convergeSource.slice(copilotPhaseStart, codexPhaseStart);
351
- assert.match(copilotPhase, /phase = 'CODEX'/);
352
- assert.doesNotMatch(copilotPhase, /phase = 'FINALIZE'/);
353
- });
354
-
355
- test('the merged FINALIZE check receives codexDown and codexCleanAt and passes matching flags', () => {
356
- const finalizeStart = convergeSource.indexOf("if (phase === 'FINALIZE') {");
357
- assert.notEqual(finalizeStart, -1, 'expected a FINALIZE phase block');
358
- const checkCall = convergeSource.indexOf('runConvergenceCheck(', finalizeStart);
359
- assert.notEqual(checkCall, -1, 'expected the FINALIZE phase to call runConvergenceCheck');
360
- const checkLine = convergeSource.slice(checkCall, convergeSource.indexOf('\n', checkCall));
361
- assert.match(checkLine, /codexDown/);
362
- assert.match(checkLine, /codexCleanAt/);
363
- const checkBody = functionBody('runConvergenceCheck');
364
- assert.match(checkBody, /context\.codexDown \? ' --codex-down' : ''/);
365
- assert.match(checkBody, /context\.codexCleanAt \? ` --codex-clean-at \$\{context\.codexCleanAt\}` : ''/);
366
- assert.match(checkBody, /if \(context\.codexDown\) reviewerOptOutTokens\.push\('codex'\)/);
367
- });
368
-
369
- test('runConvergenceCheck tells the finalize agent to persist codex_clean_at for the flagless mark-ready re-check', () => {
370
- const checkBody = functionBody('runConvergenceCheck');
371
- assert.match(
372
- checkBody,
373
- /codexCleanAtNote/,
374
- 'expected a dedicated note when the Codex gate stamped clean on HEAD',
375
- );
376
- assert.match(
377
- checkBody,
378
- /pr-converge-state\.json/,
379
- 'expected the note to name the job-dir state file the mark-ready blocker re-reads',
380
- );
381
- assert.match(
382
- checkBody,
383
- /codex_clean_at/,
384
- 'expected the note to write the codex_clean_at key the flagless re-check resolves',
385
- );
386
- assert.match(
387
- checkBody,
388
- /CLAUDE_JOB_DIR/,
389
- 'expected the note to locate the state file under CLAUDE_JOB_DIR',
390
- );
391
- assert.match(
392
- checkBody,
393
- /needsCodexCleanExportFallback/,
394
- 'expected a single-export fallback path when CLAUDE_JOB_DIR is unset',
395
- );
396
- assert.match(
397
- checkBody,
398
- /Emit exactly one export/,
399
- 'expected the opt-out instruction to forbid a second overwriting export',
400
- );
401
- assert.doesNotMatch(
402
- checkBody,
403
- /export CLAUDE_REVIEWS_DISABLED="codex"/,
404
- 'expected no second solo codex export that would overwrite other tokens',
405
- );
406
- });
407
-
408
- test('CONFIG expands home for the codex-review scripts directory', () => {
409
- assert.match(
410
- convergeSource,
411
- /const homeDirectory = \([\s\S]*?homeDirectoryPayload\.homeDirectory/,
412
- 'expected home to be sourced from the workflow args payload (the sandbox exposes no process)',
413
- );
414
- assert.match(
415
- convergeSource,
416
- /codexScripts:\s*`\$\{homeDirectory\}\/\.claude\/_shared\/pr-loop\/scripts`/,
417
- 'expected codexScripts to expand homeDirectory rather than embed $HOME',
418
- );
419
- assert.doesNotMatch(
420
- convergeSource,
421
- /codexScripts:\s*'\$HOME\//,
422
- 'expected no literal $HOME token in codexScripts (Python raw strings do not expand it)',
423
- );
424
- });
425
-
426
- test('no process global is read unguarded (the workflow sandbox exposes no process)', () => {
427
- const unguardedProcessLines = convergeSource
428
- .split('\n')
429
- .filter((sourceLine) => sourceLine.includes('process.') && !sourceLine.includes('typeof process'));
430
- assert.deepEqual(
431
- unguardedProcessLines,
432
- [],
433
- 'every process.* read must sit on a line guarded by typeof process; the Bun workflow sandbox has no process global',
434
- );
435
- });
436
-
437
- test('the home directory is sourced from the workflow args payload', () => {
438
- assert.match(
439
- convergeSource,
440
- /const homeDirectoryPayload = normalizeRunInput\(args\)/,
441
- 'expected homeDirectory to read args (the only channel into the process-less sandbox), parsed via normalizeRunInput',
442
- );
443
- });
444
-
445
- test('meta lists the Codex gate phase between Copilot and Finalize', () => {
446
- const copilotPhaseIndex = convergeSource.indexOf("title: 'Copilot gate'");
447
- const codexPhaseIndex = convergeSource.indexOf("title: 'Codex gate'");
448
- const finalizePhaseIndex = convergeSource.indexOf("title: 'Finalize'");
449
- assert.notEqual(codexPhaseIndex, -1, 'expected a Codex gate phase in meta');
450
- assert.ok(copilotPhaseIndex < codexPhaseIndex && codexPhaseIndex < finalizePhaseIndex);
451
- });
452
-
453
- test('SKILL.md names Codex among the terminal confirmation gates', () => {
454
- assert.match(skillSource, /Codex/i);
455
- });
456
-
457
- test('SKILL.md documents codexNote in the workflow return shape', () => {
458
- const returnShapeMatch = skillSource.match(/`\{ converged, rounds, finalSha, blocker,[^`]*\}`/);
459
- assert.ok(returnShapeMatch, 'expected the documented return shape literal in SKILL.md');
460
- assert.match(returnShapeMatch[0], /codexNote/);
461
- });
462
-
463
- test('SKILL.md final-report template surfaces the codexNote so a bypassed Codex gate stays visible', () => {
464
- const reportBlockMatch = skillSource.match(/\/autoconverge exit:[\s\S]*?```/);
465
- assert.ok(reportBlockMatch, 'expected the final-report template block in SKILL.md');
466
- assert.match(reportBlockMatch[0], /Codex: <codexNote>/);
467
- });
468
-
469
- test('stop-conditions.md documents the Codex gate skip paths as non-blockers', () => {
470
- assert.match(stopConditionsSource, /Codex/i);
471
- assert.match(stopConditionsSource, /codex/i);
472
- });
@@ -1,64 +0,0 @@
1
- import assert from 'node:assert/strict'
2
- import { readFileSync } from 'node:fs'
3
- import test from 'node:test'
4
- import vm from 'node:vm'
5
-
6
- const sourcePath = new URL('./converge.mjs', import.meta.url)
7
- const workflowSource = readFileSync(sourcePath, 'utf8')
8
-
9
- function loadReviewResultParser() {
10
- const passMarker = workflowSource.match(/const REVIEW_RESULT_PASS_MARKER = .+/)[0]
11
- const findingsMarker = workflowSource.match(/const REVIEW_RESULT_FINDINGS_MARKER = .+/)[0]
12
- const parserStart = workflowSource.indexOf('function parseReviewResult')
13
- const parserEnd = workflowSource.indexOf('\n}\n', parserStart) + 2
14
- const parserSource = `${passMarker}\n${findingsMarker}\n${workflowSource.slice(parserStart, parserEnd)}`
15
- const parserContext = {}
16
- vm.runInNewContext(`${parserSource}\nglobalThis.parseReviewResult = parseReviewResult`, parserContext)
17
- return parserContext.parseReviewResult
18
- }
19
-
20
- test('review tasks apply the canonical review guide and return a review result', () => {
21
- assert.match(workflowSource, /function runReviewTask\(task, context\)/)
22
- assert.match(workflowSource, /_shared\/pr-loop\/precatch-rubric\.md/)
23
- assert.match(workflowSource, /REVIEW_RESULT: PASS/)
24
- assert.match(workflowSource, /REVIEW_RESULT: FINDINGS/)
25
- })
26
-
27
- test('review tasks use code-quality-agent and keep the working tree read-only', () => {
28
- const reviewTaskStart = workflowSource.indexOf('function runReviewTask')
29
- const reviewTaskEnd = workflowSource.indexOf('function serializeOneLineJson', reviewTaskStart)
30
- const reviewTaskSource = workflowSource.slice(reviewTaskStart, reviewTaskEnd)
31
- assert.match(reviewTaskSource, /agentType: 'code-quality-agent'/)
32
- assert.match(reviewTaskSource, /Make no edit to the tree under verification/)
33
- })
34
-
35
- test('workflow agents receive the selected GitHub transport before role instructions', () => {
36
- assert.match(
37
- workflowSource,
38
- /HEADLESS_EDIT_PREAMBLE\}\$\{githubTransportDirective\(activeGithubTransport\)\}\$\{worktreeDirective/,
39
- )
40
- assert.match(
41
- workflowSource,
42
- /HEADLESS_READONLY_PREAMBLE\}\$\{githubTransportDirective\(activeGithubTransport\)\}\$\{worktreeDirective/,
43
- )
44
- })
45
-
46
- test('review result parser accepts one standalone terminal disposition only', () => {
47
- const parseReviewResult = loadReviewResultParser()
48
-
49
- assert.equal(parseReviewResult('review complete\nREVIEW_RESULT: PASS'), 'PASS')
50
- assert.equal(parseReviewResult('finding: missing test\nREVIEW_RESULT: FINDINGS'), 'FINDINGS')
51
- assert.equal(parseReviewResult('REVIEW_RESULT: PASSING'), null)
52
- assert.equal(parseReviewResult('REVIEW_RESULT: PASS\nREVIEW_RESULT: FINDINGS'), null)
53
- assert.equal(parseReviewResult('REVIEW_RESULT: PASS\n> REVIEW_RESULT: FINDINGS'), null)
54
- assert.equal(parseReviewResult('review complete'), null)
55
- })
56
-
57
- test('the fix flow keeps edit, review, and commit as distinct operational steps', () => {
58
- const fixerStart = workflowSource.indexOf('async function fixerWithRecovery')
59
- const fixerEnd = workflowSource.indexOf('function runCodeEditorTask', fixerStart)
60
- const fixerSource = workflowSource.slice(fixerStart, fixerEnd)
61
- assert.match(fixerSource, /runReviewTask\('fix-verify'/)
62
- assert.match(fixerSource, /runFixerTask\('commit'/)
63
- assert.match(fixerSource, /reviewPassed\(verifyTranscript\)/)
64
- })