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,202 +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
-
10
- function functionBody(functionName) {
11
- const functionStart = convergeSource.indexOf(`function ${functionName}(`);
12
- assert.notEqual(functionStart, -1, `expected ${functionName} to exist`);
13
- const nextFunctionStart = convergeSource.indexOf('\nfunction ', functionStart + 1);
14
- const functionEnd = nextFunctionStart === -1 ? convergeSource.length : nextFunctionStart;
15
- return convergeSource.slice(functionStart, functionEnd);
16
- }
17
-
18
- const productionModule = new Function(
19
- `const SHA_COMPARISON_PREFIX_LENGTH = 7;\n` +
20
- `${functionBody('normalizeShaForComparison')}\n` +
21
- `${functionBody('isP2OnlyFindings')}\n` +
22
- `${functionBody('nextPhaseAfterP2OnlyFix')}\n` +
23
- `${functionBody('routeAfterP2OnlyFix')}\n` +
24
- 'return { isP2OnlyFindings, nextPhaseAfterP2OnlyFix, routeAfterP2OnlyFix };',
25
- )();
26
-
27
- const { isP2OnlyFindings, nextPhaseAfterP2OnlyFix, routeAfterP2OnlyFix } = productionModule;
28
-
29
- function finding(overrides) {
30
- return {
31
- file: 'a.py',
32
- line: 1,
33
- severity: 'P2',
34
- category: 'bug',
35
- title: 't',
36
- detail: 'd',
37
- replyToCommentId: null,
38
- ...overrides,
39
- };
40
- }
41
-
42
- function phaseBranch(phaseMarker) {
43
- const phaseStart = convergeSource.indexOf(phaseMarker);
44
- assert.notEqual(phaseStart, -1, `expected ${phaseMarker} to exist`);
45
- const nextPhaseStart = convergeSource.indexOf('\n if (phase === ', phaseStart + 1);
46
- const phaseEnd = nextPhaseStart === -1 ? convergeSource.length : nextPhaseStart;
47
- return convergeSource.slice(phaseStart, phaseEnd);
48
- }
49
-
50
- test('isP2OnlyFindings is false for an empty findings list', () => {
51
- assert.equal(isP2OnlyFindings([]), false);
52
- });
53
-
54
- test('isP2OnlyFindings is true when every finding is severity P2', () => {
55
- assert.equal(isP2OnlyFindings([finding(), finding({ file: 'b.py', line: 2 })]), true);
56
- });
57
-
58
- test('isP2OnlyFindings is false when a P1 is mixed in with P2 findings', () => {
59
- assert.equal(isP2OnlyFindings([finding(), finding({ severity: 'P1' })]), false);
60
- });
61
-
62
- test('isP2OnlyFindings is false when every finding is severity P1', () => {
63
- assert.equal(isP2OnlyFindings([finding({ severity: 'P1' })]), false);
64
- });
65
-
66
- test('isP2OnlyFindings is false when a finding is missing severity', () => {
67
- assert.equal(isP2OnlyFindings([{ file: 'a.py', line: 1, category: 'bug' }]), false);
68
- });
69
-
70
- test('nextPhaseAfterP2OnlyFix advances CONVERGE to BUGBOT', () => {
71
- assert.equal(nextPhaseAfterP2OnlyFix('CONVERGE'), 'BUGBOT');
72
- });
73
-
74
- test('nextPhaseAfterP2OnlyFix advances BUGBOT to COPILOT', () => {
75
- assert.equal(nextPhaseAfterP2OnlyFix('BUGBOT'), 'COPILOT');
76
- });
77
-
78
- test('nextPhaseAfterP2OnlyFix advances COPILOT to CODEX', () => {
79
- assert.equal(nextPhaseAfterP2OnlyFix('COPILOT'), 'CODEX');
80
- });
81
-
82
- test('nextPhaseAfterP2OnlyFix advances CODEX to FINALIZE', () => {
83
- assert.equal(nextPhaseAfterP2OnlyFix('CODEX'), 'FINALIZE');
84
- });
85
-
86
- test('routeAfterP2OnlyFix re-converges when the fix moved HEAD', () => {
87
- const route = routeAfterP2OnlyFix('aaa111', { newSha: 'bbb222' }, 'COPILOT');
88
- assert.equal(route.didMoveHead, true);
89
- assert.equal(route.fixedHead, 'bbb222');
90
- assert.equal(route.nextPhase, 'CONVERGE');
91
- });
92
-
93
- test('routeAfterP2OnlyFix advances when HEAD is unchanged', () => {
94
- const route = routeAfterP2OnlyFix('aaa111', { newSha: 'aaa111' }, 'COPILOT');
95
- assert.equal(route.didMoveHead, false);
96
- assert.equal(route.fixedHead, 'aaa111');
97
- assert.equal(route.nextPhase, 'COPILOT');
98
- });
99
-
100
- test('nextPhaseAfterP2OnlyFix uses an in-function lookup map', () => {
101
- const body = functionBody('nextPhaseAfterP2OnlyFix');
102
- assert.match(body, /nextPhaseByCurrent/);
103
- assert.match(body, /CONVERGE:\s*'BUGBOT'/);
104
- assert.match(body, /BUGBOT:\s*'COPILOT'/);
105
- assert.match(body, /COPILOT:\s*'CODEX'/);
106
- });
107
-
108
- test('applyP2OnlyFix runs applyFixes then detectFixProgress in order', () => {
109
- const body = functionBody('applyP2OnlyFix');
110
- const applyIndex = body.indexOf('applyFixes(head, findings, sourceLabel)');
111
- const detectIndex = body.indexOf('detectFixProgress(fixResult, head, hadThreadBearingFinding)');
112
- assert.notEqual(applyIndex, -1, 'expected applyFixes in applyP2OnlyFix');
113
- assert.notEqual(detectIndex, -1, 'expected detectFixProgress in applyP2OnlyFix');
114
- assert.ok(applyIndex < detectIndex, 'applyFixes must precede detectFixProgress');
115
- assert.match(body, /collectFindingThreadIds/);
116
- });
117
-
118
- test('CONVERGE places the P2-only branch between standards-only and generic fix', () => {
119
- const convergeBranch = phaseBranch("if (phase === 'CONVERGE')");
120
- const standardsIndex = convergeBranch.indexOf('isStandardsOnlyRound(findings)');
121
- const p2OnlyIndex = convergeBranch.indexOf('isP2OnlyFindings(findings)');
122
- const genericFixIndex = convergeBranch.indexOf("finding(s) — applying fixes");
123
- assert.notEqual(standardsIndex, -1, 'expected the standards-only branch');
124
- assert.notEqual(p2OnlyIndex, -1, 'expected the P2-only branch');
125
- assert.notEqual(genericFixIndex, -1, 'expected the generic fix branch');
126
- assert.ok(standardsIndex < p2OnlyIndex, 'standards-only must precede P2-only');
127
- assert.ok(p2OnlyIndex < genericFixIndex, 'P2-only must precede generic fix');
128
- });
129
-
130
- test('CONVERGE P2-only branch fixes once and routes via routeAfterP2OnlyFix', () => {
131
- const convergeBranch = phaseBranch("if (phase === 'CONVERGE')");
132
- const p2Start = convergeBranch.indexOf('isP2OnlyFindings(findings)');
133
- const genericFixStart = convergeBranch.indexOf("finding(s) — applying fixes");
134
- const p2Branch = convergeBranch.slice(p2Start, genericFixStart);
135
- assert.match(p2Branch, /P2-only/);
136
- assert.match(p2Branch, /applyP2OnlyFix\(head, findings, 'converge-round'/);
137
- assert.match(p2Branch, /routeAfterP2OnlyFix\(head, p2Fix, advancePhase\)/);
138
- assert.match(p2Branch, /nextPhaseAfterP2OnlyFix\('CONVERGE'\)/);
139
- assert.match(p2Branch, /head = p2Route\.fixedHead/);
140
- assert.match(p2Branch, /phase = p2Route\.nextPhase/);
141
- assert.doesNotMatch(p2Branch, /head = null/);
142
- });
143
-
144
- test('BUGBOT P2-only branch routes through routeAfterP2OnlyFix', () => {
145
- const bugbotBranch = phaseBranch("if (phase === 'BUGBOT')");
146
- const standardsIndex = bugbotBranch.indexOf('isStandardsOnlyRound(bugbotOutcome.findings)');
147
- const p2OnlyIndex = bugbotBranch.indexOf('isP2OnlyFindings(bugbotOutcome.findings)');
148
- const genericFixIndex = bugbotBranch.indexOf('fixing and re-converging');
149
- assert.ok(standardsIndex < p2OnlyIndex, 'standards-only must precede P2-only on BUGBOT');
150
- assert.ok(p2OnlyIndex < genericFixIndex, 'P2-only must precede generic re-converge on BUGBOT');
151
- const p2Branch = bugbotBranch.slice(p2OnlyIndex, genericFixIndex);
152
- assert.match(p2Branch, /P2-only/);
153
- assert.match(p2Branch, /nextPhaseAfterP2OnlyFix\('BUGBOT'\)/);
154
- assert.match(p2Branch, /applyP2OnlyFix\(head, bugbotOutcome\.findings, 'bugbot'/);
155
- assert.match(p2Branch, /routeAfterP2OnlyFix\(head, p2Fix, advancePhase\)/);
156
- assert.match(p2Branch, /phase = p2Route\.nextPhase/);
157
- });
158
-
159
- test('COPILOT P2-only branch routes through routeAfterP2OnlyFix', () => {
160
- const copilotBranch = phaseBranch("if (phase === 'COPILOT')");
161
- const standardsIndex = copilotBranch.indexOf('isStandardsOnlyRound(roundFindings)');
162
- const p2OnlyIndex = copilotBranch.indexOf('isP2OnlyFindings(roundFindings)');
163
- const genericFixIndex = copilotBranch.indexOf('fixing and re-converging');
164
- assert.ok(standardsIndex < p2OnlyIndex, 'standards-only must precede P2-only on COPILOT');
165
- assert.ok(p2OnlyIndex < genericFixIndex, 'P2-only must precede generic re-converge on COPILOT');
166
- const p2Branch = copilotBranch.slice(p2OnlyIndex, genericFixIndex);
167
- assert.match(p2Branch, /P2-only/);
168
- assert.match(p2Branch, /nextPhaseAfterP2OnlyFix\('COPILOT'\)/);
169
- assert.match(p2Branch, /applyP2OnlyFix\(head, roundFindings, 'copilot'/);
170
- assert.match(p2Branch, /routeAfterP2OnlyFix\(head, p2Fix, advancePhase\)/);
171
- assert.match(p2Branch, /phase = p2Route\.nextPhase/);
172
- });
173
-
174
- test('CODEX P2-only branch routes through routeAfterP2OnlyFix and stamps codexCleanAt only when HEAD is stable', () => {
175
- const codexBranch = phaseBranch("if (phase === 'CODEX')");
176
- const standardsIndex = codexBranch.indexOf('isStandardsOnlyRound(codexOutcome.findings)');
177
- const p2OnlyIndex = codexBranch.indexOf('isP2OnlyFindings(codexOutcome.findings)');
178
- const genericFixIndex = codexBranch.indexOf('fixing and re-converging');
179
- assert.ok(standardsIndex < p2OnlyIndex, 'standards-only must precede P2-only on CODEX');
180
- assert.ok(p2OnlyIndex < genericFixIndex, 'P2-only must precede generic re-converge on CODEX');
181
- const p2Branch = codexBranch.slice(p2OnlyIndex, genericFixIndex);
182
- assert.match(p2Branch, /P2-only/);
183
- assert.match(p2Branch, /nextPhaseAfterP2OnlyFix\('CODEX'\)/);
184
- assert.match(p2Branch, /applyP2OnlyFix\(head, codexOutcome\.findings, 'codex'/);
185
- assert.match(p2Branch, /routeAfterP2OnlyFix\(head, p2Fix, advancePhase\)/);
186
- assert.match(p2Branch, /codexCleanAt = head/);
187
- assert.match(p2Branch, /didMoveHead/);
188
- });
189
-
190
- test('generic fix branches still re-converge for mixed or P0/P1 findings', () => {
191
- const bugbotBranch = phaseBranch("if (phase === 'BUGBOT')");
192
- const genericStart = bugbotBranch.indexOf('fixing and re-converging');
193
- const genericBranch = bugbotBranch.slice(genericStart);
194
- assert.match(genericBranch, /phase = 'CONVERGE'/);
195
- assert.match(genericBranch, /head = null/);
196
-
197
- const copilotBranch = phaseBranch("if (phase === 'COPILOT')");
198
- const copilotGenericStart = copilotBranch.indexOf('fixing and re-converging');
199
- const copilotGeneric = copilotBranch.slice(copilotGenericStart);
200
- assert.match(copilotGeneric, /phase = 'CONVERGE'/);
201
- assert.match(copilotGeneric, /head = null/);
202
- });
@@ -1,47 +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
-
10
- function sliceBetween(startNeedle, endNeedle) {
11
- const sliceStart = convergeSource.indexOf(startNeedle);
12
- assert.notEqual(sliceStart, -1, `expected ${startNeedle} to exist`);
13
- const sliceEnd = convergeSource.indexOf(endNeedle, sliceStart + startNeedle.length);
14
- assert.notEqual(sliceEnd, -1, `expected ${endNeedle} to exist after ${startNeedle}`);
15
- return convergeSource.slice(sliceStart, sliceEnd);
16
- }
17
-
18
- const productionModule = new Function(
19
- `${sliceBetween('const worktreeDirective =', '\nconst convergeAgent =')}\n` +
20
- 'return { worktreeDirective };',
21
- )();
22
- const { worktreeDirective } = productionModule;
23
-
24
- test('a single-PR run (no repoPath) produces an empty worktree directive', () => {
25
- assert.equal(worktreeDirective(null), '');
26
- });
27
-
28
- test('a path-scoped run pins every agent to the PR worktree by absolute path', () => {
29
- const directive = worktreeDirective('/worktrees/pr-398');
30
- assert.match(directive, /\/worktrees\/pr-398/);
31
- assert.match(directive, /cd /);
32
- assert.match(directive, /git, gh, diff, edit, commit, push, and test/);
33
- });
34
-
35
- test('a path-scoped run defers to a step that names a different repository directory', () => {
36
- assert.match(worktreeDirective('/worktrees/pr-398'), /different repository directory/i);
37
- });
38
-
39
- test('convergeAgent prepends the worktree directive for the active repo path', () => {
40
- const agentDefinition = sliceBetween('const convergeAgent =', '\nconst PRE_COMMIT_GATE_STEP');
41
- assert.match(agentDefinition, /worktreeDirective\(activeRepoPath\)/);
42
- assert.match(agentDefinition, /HEADLESS_EDIT_PREAMBLE/);
43
- });
44
-
45
- test('the run binds activeRepoPath from input.repoPath after the input is parsed', () => {
46
- assert.match(convergeSource, /activeRepoPath = typeof input\.repoPath === 'string'/);
47
- });
@@ -1,152 +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
-
10
- function functionSource(functionName) {
11
- const functionStart = convergeSource.indexOf(`function ${functionName}(`);
12
- assert.notEqual(functionStart, -1, `expected ${functionName} to exist`);
13
- const nextMatch = /\n(?:async )?function /.exec(convergeSource.slice(functionStart + 1));
14
- const functionEnd =
15
- nextMatch === null ? convergeSource.length : functionStart + 1 + nextMatch.index;
16
- return convergeSource.slice(functionStart, functionEnd);
17
- }
18
-
19
- function sliceBetween(startNeedle, endNeedle) {
20
- const sliceStart = convergeSource.indexOf(startNeedle);
21
- assert.notEqual(sliceStart, -1, `expected ${startNeedle} to exist`);
22
- const sliceEnd = convergeSource.indexOf(endNeedle, sliceStart + startNeedle.length);
23
- assert.notEqual(sliceEnd, -1, `expected ${endNeedle} to exist after ${startNeedle}`);
24
- return convergeSource.slice(sliceStart, sliceEnd);
25
- }
26
-
27
- test('runStaticSweep exists and runs after the preflight-git no-SHA guard and before the parallel lenses', () => {
28
- assert.match(convergeSource, /function runStaticSweep\(/, 'expected the static-sweep lens builder to exist');
29
- const sweepCallIndex = convergeSource.indexOf('await runStaticSweep(');
30
- assert.notEqual(sweepCallIndex, -1, 'expected the CONVERGE round to invoke runStaticSweep');
31
- const noShaGuardIndex = convergeSource.indexOf('preflight-git agent returned no SHA');
32
- const parallelIndex = convergeSource.indexOf('const lenses = await parallel(');
33
- assert.ok(
34
- noShaGuardIndex !== -1 && noShaGuardIndex < sweepCallIndex,
35
- 'expected the static sweep to run after the no-SHA guard',
36
- );
37
- assert.ok(
38
- sweepCallIndex < parallelIndex,
39
- 'expected the static sweep to run before the opus reading lenses so they review sweep-clean code',
40
- );
41
- });
42
-
43
- test('the static-sweep prompt names the deterministic gates and never invokes the gh CLI', () => {
44
- const body = functionSource('runStaticSweep');
45
- assert.match(body, /code_rules_gate\.py/, 'expected the CODE_RULES gate to be named');
46
- assert.match(body, /--base/, 'expected the gate to run against the origin/main base');
47
- assert.match(body, /\bruff\b/, 'expected ruff to be named');
48
- assert.match(body, /\bmypy\b/, 'expected mypy to be named');
49
- assert.match(body, /\bpytest\b/, 'expected stem-matched pytest to be named');
50
- assert.doesNotMatch(body, /\bgh\b/, 'expected the sweep to use only local commands so it runs in a cloud session');
51
- });
52
-
53
- test('the static-sweep runs on the sonnetMedium tier via convergeReadOnlyAgent with the Explore agent type', () => {
54
- const body = functionSource('runStaticSweep');
55
- assert.match(body, /convergeReadOnlyAgent\(/, 'expected the sweep to spawn through the read-only preamble');
56
- assert.match(body, /renderLensDiffContext\(preflightResult\)/, 'expected the sweep to inject the preflight changed-file context');
57
- assert.match(body, /label: 'lens:static-sweep'/);
58
- assert.match(body, /agentType: 'Explore'/);
59
- assert.match(body, /\.\.\.TIERS\.sonnetMedium/, 'expected the deterministic sweep to run on the cheaper sonnet tier');
60
- });
61
-
62
- test('a static-sweep finding routes through applyFixes with the static-sweep label and nulls head before continue', () => {
63
- const sweepBranch = sliceBetween('await runStaticSweep(', "const lenses = await parallel(");
64
- assert.match(sweepBranch, /applyFixes\(head, sweep\.findings, 'static-sweep'\)/, 'expected sweep findings to route through applyFixes');
65
- assert.match(sweepBranch, /detectFixProgress\(sweepFix, head, false\)/, 'expected the sweep fix to check fix progress with no thread-bearing finding');
66
- const headNullIndex = sweepBranch.indexOf('head = null');
67
- const continueIndex = sweepBranch.indexOf('continue');
68
- assert.notEqual(headNullIndex, -1, 'expected the sweep-findings branch to null head so the next round reviews the fixed code');
69
- assert.ok(headNullIndex < continueIndex, 'expected head to be invalidated before the sweep branch continues');
70
- });
71
-
72
- test('runAuditLens carries the adversarial second pass and points at the pre-catch rubric', () => {
73
- const body = functionSource('runAuditLens');
74
- assert.match(body, /missed at least 3 P1/, 'expected the mandatory adversarial second pass');
75
- assert.match(body, /CONFIG\.precatchRubric/, 'expected the audit lens to point at the pre-catch rubric for the doc-parity/test/PR-description lanes');
76
- assert.doesNotMatch(body, /nothing new is an acceptable/i, 'expected a bare "nothing new" to be rejected');
77
- });
78
-
79
- test('runSelfReviewLens exists on opusMedium via convergeReadOnlyAgent and covers the three semantic lanes', () => {
80
- const body = functionSource('runSelfReviewLens');
81
- assert.match(body, /convergeReadOnlyAgent\(/, 'expected the self-review lens to spawn through the read-only preamble');
82
- assert.match(body, /renderLensDiffContext\(preflightResult\)/, 'expected the self-review lens to inject the preflight changed-file context');
83
- assert.match(body, /CONFIG\.precatchRubric/, 'expected the self-review lens to read the pre-catch rubric');
84
- assert.match(body, /pr-consistency-audit/, 'expected the self-review lens to reuse the pr-consistency-audit method');
85
- assert.match(body, /category-o-docstring-vs-impl-drift/, 'expected the self-review lens to cite the category-o drift rubric');
86
- assert.match(body, /parity/i, 'expected the doc-vs-code parity lane');
87
- assert.match(body, /Test-assertion completeness/i, 'expected the test-assertion completeness lane');
88
- assert.match(body, /PR-description-vs-diff/i, 'expected the PR-description parity lane');
89
- assert.match(body, /label: 'lens:self-review'/);
90
- assert.match(body, /\.\.\.TIERS\.opusMedium/, 'expected the semantic lens to stay on opus');
91
- });
92
-
93
- test('the round parallel array holds exactly the three internal lenses and no Bugbot slot', () => {
94
- const parallelArray = sliceBetween('const lenses = await parallel([', '])');
95
- assert.match(parallelArray, /runCodeReviewLens\(head, reviewerAvailability\)/);
96
- assert.match(parallelArray, /runAuditLens\(head, reviewerAvailability\)/);
97
- assert.match(parallelArray, /runSelfReviewLens\(head, reviewerAvailability\)/);
98
- assert.doesNotMatch(parallelArray, /runBugbotLens/, 'expected Bugbot to leave the per-round parallel and become a terminal gate');
99
- assert.doesNotMatch(parallelArray, /isBugbotDownPreSpawn/, 'expected the pre-spawn Bugbot-down decision to be gone from the round');
100
- assert.doesNotMatch(convergeSource, /const isBugbotDownPreSpawn/, 'expected no pre-spawn Bugbot-down decision anywhere in the round');
101
- });
102
-
103
- test('both the CONVERGE clean branch and the standards-only branch route to the terminal BUGBOT phase', () => {
104
- const convergeBranch = sliceBetween("if (phase === 'CONVERGE') {", "if (phase === 'BUGBOT') {");
105
- const toBugbot = convergeBranch.match(/phase = 'BUGBOT'/g) || [];
106
- assert.equal(toBugbot.length, 2, 'expected the standards-only and all-clean branches to both set phase = BUGBOT');
107
- assert.doesNotMatch(convergeBranch, /phase = 'COPILOT'/, 'expected the CONVERGE block to route to BUGBOT, not straight to COPILOT');
108
- });
109
-
110
- test('the terminal BUGBOT phase skips runBugbotLens when the reviewer-availability gate reports Bugbot down', () => {
111
- const bugbotPhase = sliceBetween("if (phase === 'BUGBOT') {", "if (phase === 'COPILOT') {");
112
- const availabilityGateIndex = bugbotPhase.indexOf('resolveReviewerDown(reviewerAvailability?.bugbot, input.bugbotDisabled || false)');
113
- const gateCallIndex = bugbotPhase.indexOf('await runBugbotLens(head, reviewerAvailability)');
114
- assert.notEqual(availabilityGateIndex, -1, 'expected the terminal gate to consult resolveReviewerDown before spawning the Bugbot lens');
115
- assert.notEqual(gateCallIndex, -1, 'expected the terminal gate to call runBugbotLens when Bugbot is enabled');
116
- assert.ok(availabilityGateIndex < gateCallIndex, 'expected the availability gate to short-circuit before any Bugbot agent spawns');
117
- const beforeGate = bugbotPhase.slice(availabilityGateIndex, gateCallIndex);
118
- assert.match(beforeGate, /bugbotDown = true/, 'expected the availability-down path to mark bugbotDown');
119
- assert.match(beforeGate, /phase = 'COPILOT'/, 'expected the availability-down path to advance to the Copilot gate with no agent');
120
- });
121
-
122
- test('the terminal BUGBOT phase classifies via the shared reviewer-gate classifier and routes each outcome', () => {
123
- const bugbotPhase = sliceBetween("if (phase === 'BUGBOT') {", "if (phase === 'COPILOT') {");
124
- assert.match(bugbotPhase, /classifyReviewerGateOutcome\(bugbot\)/, 'expected the terminal gate to reuse the shared reviewer-gate classifier');
125
- assert.match(bugbotPhase, /applyFixes\(head, bugbotOutcome\.findings, 'bugbot'\)/, 'expected a Bugbot fix outcome to route through applyFixes');
126
- assert.match(bugbotPhase, /head = null\n\s*phase = 'CONVERGE'/, 'expected a Bugbot fix to invalidate head and re-enter CONVERGE');
127
- assert.match(bugbotPhase, /phase = 'COPILOT'/, 'expected a clean or down Bugbot verdict to advance to the Copilot gate');
128
- });
129
-
130
- test('convergeReadOnlyAgent exists and the read-only preamble omits the rm-shape paragraph the edit preamble keeps', () => {
131
- assert.match(convergeSource, /const convergeReadOnlyAgent = \(prompt, options\) =>/, 'expected the read-only agent spawner to exist');
132
- const preambleRegion = convergeSource.slice(
133
- convergeSource.indexOf('const HEADLESS_EDIT_PREAMBLE ='),
134
- convergeSource.indexOf('\nlet activeRepoPath'),
135
- );
136
- const preambleModule = new Function(
137
- `${preambleRegion}\nreturn { HEADLESS_EDIT_PREAMBLE, HEADLESS_READONLY_PREAMBLE };`,
138
- )();
139
- assert.match(preambleModule.HEADLESS_EDIT_PREAMBLE, /rm shape rules/, 'expected the edit preamble to retain the rm-shape rules');
140
- assert.doesNotMatch(preambleModule.HEADLESS_READONLY_PREAMBLE, /rm shape rules/, 'expected the read-only preamble to drop the rm-shape paragraph');
141
- assert.ok(
142
- preambleModule.HEADLESS_READONLY_PREAMBLE.length < preambleModule.HEADLESS_EDIT_PREAMBLE.length,
143
- 'expected the read-only preamble to be shorter than the edit preamble',
144
- );
145
- });
146
-
147
- test('COMMIT_RECOVERY_MAX_ATTEMPTS is one and bounds the commitWithRecovery loop', () => {
148
- assert.match(convergeSource, /const COMMIT_RECOVERY_MAX_ATTEMPTS = 1/, 'expected a dedicated commit-recovery cap of one');
149
- assert.match(convergeSource, /const FIX_RECOVERY_MAX_ATTEMPTS = 2/, 'expected the wider verify-recovery cap to stay at two');
150
- const commitBody = functionSource('commitWithRecovery');
151
- assert.match(commitBody, /attempt <= COMMIT_RECOVERY_MAX_ATTEMPTS/, 'expected commitWithRecovery to bound its loop by the dedicated cap');
152
- });
@@ -1,116 +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
-
10
- function sourceSliceBetween(startNeedle, endNeedle) {
11
- const sliceStart = convergeSource.indexOf(startNeedle);
12
- assert.notEqual(sliceStart, -1, `expected ${startNeedle} to exist`);
13
- const sliceEnd = convergeSource.indexOf(endNeedle, sliceStart + startNeedle.length);
14
- assert.notEqual(sliceEnd, -1, `expected ${endNeedle} to exist after ${startNeedle}`);
15
- return convergeSource.slice(sliceStart, sliceEnd);
16
- }
17
-
18
- const productionModule = new Function(
19
- `${sourceSliceBetween('function normalizeRunInput(', '\nconst runInput =')}\n` +
20
- 'return { normalizeRunInput, classifyRunInput, githubTransportDirective };',
21
- )();
22
-
23
- const { normalizeRunInput, classifyRunInput, githubTransportDirective } = productionModule;
24
-
25
- const VALID_COORDINATES = { owner: 'jl-cmd', repo: 'claude-dev-env', prNumber: 543 };
26
-
27
- test('an object payload passes through unchanged', () => {
28
- assert.deepEqual(normalizeRunInput(VALID_COORDINATES), VALID_COORDINATES);
29
- });
30
-
31
- test('a JSON-encoded string payload is parsed into coordinates', () => {
32
- assert.deepEqual(normalizeRunInput(JSON.stringify(VALID_COORDINATES)), VALID_COORDINATES);
33
- });
34
-
35
- test('a non-JSON string returns null rather than throwing', () => {
36
- assert.equal(normalizeRunInput('not json at all'), null);
37
- });
38
-
39
- test('an empty string returns null rather than throwing', () => {
40
- assert.equal(normalizeRunInput(''), null);
41
- });
42
-
43
- test('classifyRunInput accepts coordinates carrying owner, repo, and prNumber', () => {
44
- const classified = classifyRunInput(VALID_COORDINATES);
45
- assert.deepEqual(classified.input, VALID_COORDINATES);
46
- assert.equal(classified.blocker, null);
47
- });
48
-
49
- test('classifyRunInput accepts the cloud transport without changing the input shape', () => {
50
- const cloudInput = { ...VALID_COORDINATES, transport: 'cloud' };
51
- const classified = classifyRunInput(cloudInput);
52
- assert.deepEqual(classified.input, cloudInput);
53
- assert.equal(classified.blocker, null);
54
- });
55
-
56
- test('classifyRunInput blocks an unknown transport before any GitHub work starts', () => {
57
- const classified = classifyRunInput({ ...VALID_COORDINATES, transport: 'proxy' });
58
- assert.equal(classified.input, null);
59
- assert.match(classified.blocker, /transport/i);
60
- });
61
-
62
- test('classifyRunInput blocks a failed parse with a structured blocker and no input', () => {
63
- const classified = classifyRunInput('not json at all');
64
- assert.equal(classified.input, null);
65
- assert.match(classified.blocker, /coordinates/i);
66
- });
67
-
68
- test('classifyRunInput blocks a null payload with a structured blocker', () => {
69
- const classified = classifyRunInput(null);
70
- assert.equal(classified.input, null);
71
- assert.match(classified.blocker, /coordinates/i);
72
- });
73
-
74
- test('classifyRunInput blocks a payload missing owner', () => {
75
- const classified = classifyRunInput({ repo: 'claude-dev-env', prNumber: 543 });
76
- assert.equal(classified.input, null);
77
- assert.match(classified.blocker, /coordinates/i);
78
- });
79
-
80
- test('classifyRunInput blocks a payload missing prNumber', () => {
81
- const classified = classifyRunInput({ owner: 'jl-cmd', repo: 'claude-dev-env' });
82
- assert.equal(classified.input, null);
83
- assert.match(classified.blocker, /coordinates/i);
84
- });
85
-
86
- test('the top-level run guards an unusable input into a structured blocker before reading input.owner', () => {
87
- const guardBlock = convergeSource.slice(
88
- convergeSource.indexOf('const runInput = classifyRunInput('),
89
- convergeSource.indexOf('const prCoordinates ='),
90
- );
91
- assert.match(guardBlock, /runInput\.blocker/);
92
- assert.match(guardBlock, /converged: false/);
93
- assert.match(guardBlock, /return/);
94
- });
95
-
96
- test('classifyRunInput passes copilotDisabled through alongside the coordinates', () => {
97
- const classified = classifyRunInput({ ...VALID_COORDINATES, copilotDisabled: true });
98
- assert.equal(classified.blocker, null);
99
- assert.equal(classified.input.copilotDisabled, true);
100
- });
101
-
102
- test('classifyRunInput leaves copilotDisabled undefined when the input omits it', () => {
103
- const classified = classifyRunInput(VALID_COORDINATES);
104
- assert.equal(classified.input.copilotDisabled, undefined);
105
- });
106
-
107
- test('the cloud transport directive selects MCP and contains no local CLI auth command', () => {
108
- const cloudDirective = githubTransportDirective('cloud');
109
- assert.match(cloudDirective, /mcp__github__/);
110
- assert.match(cloudDirective, /credentialed push path/);
111
- assert.doesNotMatch(cloudDirective, /gh auth/);
112
- });
113
-
114
- test('the local transport directive keeps the local CLI path', () => {
115
- assert.match(githubTransportDirective('local'), /authenticated local GitHub CLI/);
116
- });