claude-dev-env 2.16.0 → 2.18.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 (557) hide show
  1. package/.agents/agents/AGENTS.md +6 -0
  2. package/.agents/skills/AGENTS.md +34 -35
  3. package/.agents/skills/_shared/pr-loop/AGENTS.md +22 -15
  4. package/.agents/skills/_shared/pr-loop/portable-driver.md +6 -7
  5. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +2 -2
  6. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +1 -1
  7. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +25 -16
  8. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +1 -5
  9. package/.agents/skills/autoconverge/reference/convergence-gates.md +31 -0
  10. package/.agents/skills/autoconverge/reference/convergence.md +8 -10
  11. package/.agents/skills/autoconverge/reference/gotchas.md +1 -1
  12. package/.agents/skills/autoconverge/reference/stop-conditions.md +1 -1
  13. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +1 -1
  14. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +1 -1
  15. package/.agents/skills/autoconverge/workflow/converge.mjs +3 -3
  16. package/.agents/skills/cert-classification-rule/SKILL.md +224 -0
  17. package/.agents/skills/cert-classification-rule/scripts/resort_cert_folders.py +158 -0
  18. package/.agents/skills/eli5/SKILL.md +128 -0
  19. package/.agents/skills/eli5/reference/task-seeds.md +11 -0
  20. package/.agents/skills/fresh-branch/scripts/test_create_fresh_branch.py +2 -3
  21. package/.agents/skills/name-by-capability-audit/SKILL.md +67 -0
  22. package/.agents/skills/name-by-capability-audit/reference/fetch-commands.md +29 -0
  23. package/.agents/skills/name-by-capability-audit/reference/offense-examples.md +32 -0
  24. package/.agents/skills/name-by-capability-audit/reference/report-template.md +29 -0
  25. package/.agents/skills/name-by-capability-audit/reference/rule-checklist.md +38 -0
  26. package/.agents/skills/name-by-capability-audit/reference/task-seeds.md +9 -0
  27. package/.agents/skills/orchestrator/SKILL.md +6 -4
  28. package/.agents/skills/orchestrator-refresh/SKILL.md +9 -5
  29. package/.agents/skills/pr-cleanup/SKILL.md +99 -0
  30. package/.agents/skills/prototype/reference/honest-limitations.md +1 -1
  31. package/.agents/skills/prototype/reference/promotion-tasks.md +1 -1
  32. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +2 -2
  33. package/.agents/skills/prototype/workflows/promotion.md +2 -2
  34. package/.agents/skills/review-router/SKILL.md +51 -0
  35. package/.agents/skills/review-router/reference/route-policy.json +7 -0
  36. package/.agents/skills/review-router/reference/task-seeds.md +1 -0
  37. package/.agents/skills/review-router/scripts/conftest.py +4 -0
  38. package/.agents/skills/review-router/scripts/review_router.py +50 -0
  39. package/.agents/skills/review-router/scripts/review_router_cli.py +211 -0
  40. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +1 -0
  41. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  42. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +13 -0
  43. package/.agents/skills/review-router/scripts/test_review_router.py +23 -0
  44. package/.agents/skills/review-router/scripts/test_review_router_cli.py +47 -0
  45. package/.agents/skills/review-tier/SKILL.md +56 -0
  46. package/.agents/skills/review-tier/reference/task-seeds.md +1 -0
  47. package/.agents/skills/review-tier/reference/tier-policy.json +9 -0
  48. package/.agents/skills/review-tier/scripts/conftest.py +4 -0
  49. package/.agents/skills/review-tier/scripts/review_tier.py +332 -0
  50. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +1 -0
  51. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  52. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +29 -0
  53. package/.agents/skills/review-tier/scripts/test_generation.py +171 -0
  54. package/.agents/skills/review-tier/scripts/test_review_tier.py +33 -0
  55. package/.agents/skills/session-log/SKILL.md +1 -1
  56. package/.agents/skills/shared-extraction-audit/SKILL.md +160 -0
  57. package/.agents/skills/shared-extraction-audit/reference/examples.md +46 -0
  58. package/.agents/skills/shared-extraction-audit/reference/offense-taxonomy.md +100 -0
  59. package/.agents/skills/source-command-logifix/SKILL.md +29 -0
  60. package/.agents/skills/source-command-sr-loop/SKILL.md +58 -0
  61. package/.agents/skills/team-advisor/SKILL.md +5 -5
  62. package/.agents/skills-archived/AGENTS.md +45 -0
  63. package/.agents/{skills → skills-archived}/anthropic-plan/AGENTS.md +1 -1
  64. package/.agents/{skills → skills-archived}/bugteam/scripts/reflow_skill_md.py +3 -3
  65. package/.agents/{skills → skills-archived}/codex-review/test_skill_scaffold.py +1 -1
  66. package/.agents/{skills → skills-archived}/copilot-finding-triage/SKILL.md +1 -1
  67. package/.agents/{skills → skills-archived}/pr-converge/SKILL.md +6 -6
  68. package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/AGENTS.md +1 -1
  69. package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/constants.py +1 -1
  70. package/.agents/{skills → skills-archived}/pr-converge/reference/multi-pr-orchestration.md +1 -1
  71. package/.agents/{skills → skills-archived}/pr-converge/reference/per-tick.md +3 -3
  72. package/.agents/{skills → skills-archived}/pr-converge/scripts/reflow_skill_md.py +2 -2
  73. package/.agents/{skills → skills-archived}/pr-converge/test_portable_pacer_gate.py +6 -2
  74. package/.agents/{skills → skills-archived}/pr-converge/workflows/schedule-wakeup-loop.md +1 -1
  75. package/.agents/{skills → skills-archived}/split-pr/reference/proposal-format.md +1 -1
  76. package/AGENTS.md +34 -58
  77. package/_shared/AGENTS.md +2 -0
  78. package/_shared/advisor/AGENTS.md +5 -5
  79. package/_shared/advisor/advisor-protocol.md +54 -31
  80. package/_shared/advisor/reference/advisor-block.md +5 -1
  81. package/_shared/advisor/reference/consult-format.md +1 -1
  82. package/_shared/advisor/reference/identity.md +28 -0
  83. package/_shared/advisor/reference/lifecycle.md +8 -1
  84. package/_shared/advisor/reference/sol-rung.md +14 -9
  85. package/_shared/advisor/reference/spawn-walk-log.md +6 -5
  86. package/_shared/advisor/reference/third-party-bind.md +6 -7
  87. package/_shared/advisor/reference/warm-up.md +9 -2
  88. package/_shared/advisor/scripts/codex_sol_advisor.py +66 -11
  89. package/_shared/advisor/scripts/config/advisor_scripts_constants/advisor_route_constants.py +9 -0
  90. package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +16 -4
  91. package/_shared/advisor/scripts/config/advisor_scripts_constants/sol_advisor_constants.py +11 -10
  92. package/_shared/advisor/scripts/model_tier_run_validator.py +50 -23
  93. package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +108 -3
  94. package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +171 -82
  95. package/_shared/advisor/scripts/tests/test_tier_model_ids.py +43 -0
  96. package/_shared/advisor/scripts/tier_model_ids.py +75 -7
  97. package/_shared/pr-loop/audit-reply-template.md +4 -0
  98. package/_shared/pr-loop/fix-protocol.md +7 -6
  99. package/_shared/pr-loop/gh-payloads.md +8 -6
  100. package/_shared/pr-loop/precatch-rubric.md +6 -5
  101. package/_shared/pr-loop/scripts/AGENTS.md +15 -0
  102. package/_shared/pr-loop/scripts/_pr_converge_path_setup.py +38 -0
  103. package/_shared/pr-loop/scripts/check_bugbot_ci.py +279 -0
  104. package/_shared/pr-loop/scripts/check_convergence.py +923 -0
  105. package/_shared/pr-loop/scripts/check_convergence_availability.py +275 -0
  106. package/_shared/pr-loop/scripts/check_convergence_gates.py +279 -0
  107. package/_shared/pr-loop/scripts/check_convergence_thread_gates.py +219 -0
  108. package/_shared/pr-loop/scripts/check_pending_reviews.py +154 -0
  109. package/_shared/pr-loop/scripts/codex_down_classifier.py +98 -0
  110. package/_shared/pr-loop/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
  111. package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
  112. package/_shared/pr-loop/scripts/codex_review_scripts_constants/__init__.py +1 -0
  113. package/_shared/pr-loop/scripts/codex_review_scripts_constants/classifier_constants.py +35 -0
  114. package/_shared/pr-loop/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +82 -0
  115. package/_shared/pr-loop/scripts/codex_review_scripts_constants/findings_constants.py +18 -0
  116. package/_shared/pr-loop/scripts/codex_review_scripts_constants/run_constants.py +53 -0
  117. package/_shared/pr-loop/scripts/codex_usage_probe.py +570 -0
  118. package/_shared/pr-loop/scripts/conftest.py +43 -0
  119. package/_shared/pr-loop/scripts/fetch_copilot_reviews.py +134 -0
  120. package/_shared/pr-loop/scripts/fixtures/auth_failure_synthetic.txt +1 -0
  121. package/_shared/pr-loop/scripts/fixtures/config_load_failure_v0.125.0.txt +1 -0
  122. package/_shared/pr-loop/scripts/fixtures/freeform_findings_v0.144.3.txt +6 -0
  123. package/_shared/pr-loop/scripts/fixtures/model_rejection_v0.125.0.jsonl +5 -0
  124. package/_shared/pr-loop/scripts/fixtures/structured_findings.txt +13 -0
  125. package/_shared/pr-loop/scripts/fixtures/success_stream_v0.144.3.jsonl +6 -0
  126. package/_shared/pr-loop/scripts/fixtures/unknown_failure_synthetic.txt +1 -0
  127. package/_shared/pr-loop/scripts/fixtures/usage_limit_synthetic.txt +1 -0
  128. package/_shared/pr-loop/scripts/parse_codex_findings.py +207 -0
  129. package/_shared/pr-loop/scripts/post_fix_reply.py +168 -0
  130. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
  131. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
  132. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  133. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +70 -0
  134. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/pr_converge_constants.py +118 -0
  135. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +13 -0
  136. package/_shared/pr-loop/scripts/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
  137. package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +26 -0
  138. package/_shared/pr-loop/scripts/pr_converge_skill_constants/__init__.py +0 -0
  139. package/_shared/pr-loop/scripts/pr_converge_skill_constants/constants.py +69 -0
  140. package/_shared/pr-loop/scripts/run_codex_review.py +609 -0
  141. package/_shared/pr-loop/scripts/test__pr_converge_path_setup.py +30 -0
  142. package/_shared/pr-loop/scripts/test_check_bugbot_ci.py +312 -0
  143. package/_shared/pr-loop/scripts/test_check_convergence.py +438 -0
  144. package/_shared/pr-loop/scripts/test_check_convergence_availability.py +391 -0
  145. package/_shared/pr-loop/scripts/test_check_convergence_codex.py +517 -0
  146. package/_shared/pr-loop/scripts/test_check_convergence_contract.py +400 -0
  147. package/_shared/pr-loop/scripts/test_check_convergence_fixture.py +179 -0
  148. package/_shared/pr-loop/scripts/test_check_convergence_gates.py +84 -0
  149. package/_shared/pr-loop/scripts/test_check_convergence_thread_gates.py +99 -0
  150. package/_shared/pr-loop/scripts/test_codex_down_classifier.py +143 -0
  151. package/_shared/pr-loop/scripts/test_codex_usage_probe.py +683 -0
  152. package/_shared/pr-loop/scripts/test_parse_codex_findings.py +130 -0
  153. package/_shared/pr-loop/scripts/test_run_codex_review.py +969 -0
  154. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +1 -1
  155. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +1 -1
  156. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +1 -1
  157. package/_shared/pr-loop/state-schema.md +20 -28
  158. package/_shared/pr-loop/worker-spawn.md +4 -3
  159. package/_shared/process-tree/AGENTS.md +3 -3
  160. package/bin/ever-shipped-skills.mjs +29 -1
  161. package/bin/install-constants.mjs +15 -6
  162. package/bin/install.agents-home.test.mjs +13 -0
  163. package/bin/install.cursor-rules.test.mjs +3 -3
  164. package/bin/install.mjs +80 -20
  165. package/bin/install.profile-root.test.mjs +1 -1
  166. package/bin/install.prune.test.mjs +23 -204
  167. package/bin/install.test.mjs +8 -5
  168. package/bin/resolve-install-root.mjs +21 -0
  169. package/bin/resolve-package-managed-directory.mjs +4 -4
  170. package/commands/AGENTS.md +2 -0
  171. package/commands/sr-loop.md +3 -0
  172. package/docs/references/prose-style-enforcement.md +3 -7
  173. package/docs/references/team-advisor-skill.md +2 -2
  174. package/hooks/AGENTS.md +0 -3
  175. package/hooks/blocking/AGENTS.md +0 -2
  176. package/hooks/blocking/ask_user_question_shape_blocker.py +83 -0
  177. package/hooks/blocking/pre_tool_use_dispatcher.py +2 -19
  178. package/hooks/blocking/state_description_blocker.py +1 -1
  179. package/hooks/blocking/test_ask_user_question_shape.py +69 -0
  180. package/hooks/blocking/test_pre_tool_use_dispatcher.py +17 -58
  181. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +9 -104
  182. package/hooks/blocking/test_state_description_blocker.py +1 -0
  183. package/hooks/blocking/test_stop_dispatcher.py +1 -26
  184. package/hooks/hooks.json +1 -1
  185. package/hooks/hooks_constants/AGENTS.md +0 -3
  186. package/hooks/hooks_constants/ask_user_question_shape.py +1 -1
  187. package/hooks/hooks_constants/ask_user_question_shape_constants.py +73 -0
  188. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +1 -2
  189. package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -1
  190. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -7
  191. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
  192. package/hooks/hooks_constants/test_ask_user_question_shape.py +1 -1
  193. package/hooks/hooks_constants/test_prose_metrics_parity.py +29 -107
  194. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
  195. package/hooks/hooks_constants/working_style_prompt_constants.py +9 -10
  196. package/hooks/session/AGENTS.md +4 -1
  197. package/hooks/session/test_working_style_prompt.py +8 -4
  198. package/hooks/session/working_style_prompt.py +4 -2
  199. package/package.json +1 -4
  200. package/rules/AGENTS.md +2 -5
  201. package/rules/asd-ste100-language.md +39 -0
  202. package/rules/ask-user-question-required.md +1 -1
  203. package/rules/long-horizon-autonomy.md +1 -1
  204. package/scripts/AGENTS.md +1 -0
  205. package/scripts/Show-Asset.ps1 +106 -0
  206. package/scripts/test_validate_instruction_pairs.py +30 -3
  207. package/scripts/tests/test_engine.py +4 -4
  208. package/scripts/tests/test_rules.py +5 -5
  209. package/system-prompts/AGENTS.md +8 -0
  210. package/system-prompts/software-engineer.xml +8 -3
  211. package/.agents/skills/grokify/evals/README.md +0 -72
  212. package/.agents/skills/grokify/evals/parse-payload.test.mjs +0 -171
  213. package/.agents/skills/grokify/evals/run-capability-evals.mjs +0 -545
  214. package/_shared/pr-loop/scripts/README.md +0 -21
  215. package/docs/imagegen.md +0 -22
  216. package/hooks/blocking/eli11_reply_enforcer.py +0 -436
  217. package/hooks/blocking/plain_language_blocker.py +0 -758
  218. package/hooks/blocking/test_eli11_reply_enforcer.py +0 -390
  219. package/hooks/blocking/test_plain_language_blocker.py +0 -683
  220. package/hooks/blocking/test_plain_language_blocker_allowlist.py +0 -228
  221. package/hooks/diagnostic/AGENTS.md +0 -75
  222. package/hooks/diagnostic/CLAUDE.md +0 -1
  223. package/hooks/diagnostic/hook_log_extractor.py +0 -875
  224. package/hooks/diagnostic/hook_log_init.py +0 -202
  225. package/hooks/diagnostic/hook_log_stop_wrapper.py +0 -26
  226. package/hooks/diagnostic/migrations/2026-04-25-drop-themes-hook-events.sql +0 -3
  227. package/hooks/diagnostic/migrations/AGENTS.md +0 -16
  228. package/hooks/diagnostic/migrations/CLAUDE.md +0 -1
  229. package/hooks/diagnostic/migrations/README.md +0 -76
  230. package/hooks/diagnostic/queries/AGENTS.md +0 -19
  231. package/hooks/diagnostic/queries/CLAUDE.md +0 -1
  232. package/hooks/diagnostic/queries/block_details_for_hook.sql +0 -26
  233. package/hooks/diagnostic/queries/blocks_by_category.sql +0 -10
  234. package/hooks/diagnostic/queries/blocks_by_tool.sql +0 -9
  235. package/hooks/diagnostic/queries/blocks_last_7_days.sql +0 -11
  236. package/hooks/diagnostic/queries/top_blockers_last_24_hours.sql +0 -12
  237. package/hooks/diagnostic/queries/top_blockers_overall.sql +0 -12
  238. package/hooks/diagnostic/requirements-hook-logs-dev.txt +0 -2
  239. package/hooks/diagnostic/requirements-hook-logs.txt +0 -1
  240. package/hooks/diagnostic/schema.sql +0 -51
  241. package/hooks/diagnostic/test_hook_log_extractor.py +0 -1518
  242. package/hooks/diagnostic/test_hook_log_init.py +0 -227
  243. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +0 -17
  244. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +0 -94
  245. package/hooks/hooks_constants/hook_log_extractor_constants.py +0 -233
  246. package/hooks/hooks_constants/plain_language_blocker_constants.py +0 -366
  247. package/hooks/hooks_constants/test_hook_log_extractor_constants.py +0 -123
  248. package/rules/doc-prose-cuts.md +0 -58
  249. package/rules/eli11-replies.md +0 -36
  250. package/rules/opus5-communication-contract.md +0 -45
  251. package/rules/plain-language.md +0 -9
  252. /package/.agents/{skills → skills-archived}/anthropic-plan/.claude/CLAUDE.md +0 -0
  253. /package/.agents/{skills → skills-archived}/anthropic-plan/SKILL.md +0 -0
  254. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/.claude/CLAUDE.md +0 -0
  255. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/AGENTS.md +0 -0
  256. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/.claude/CLAUDE.md +0 -0
  257. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -0
  258. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/__init__.py +0 -0
  259. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/validate_packet_constants.py +0 -0
  260. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/test_validate_packet.py +0 -0
  261. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/validate_packet.py +0 -0
  262. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/.claude/CLAUDE.md +0 -0
  263. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/AGENTS.md +0 -0
  264. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/README.md +0 -0
  265. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/build-prompt.md +0 -0
  266. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/reuse-audit.md +0 -0
  267. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/source-map.md +0 -0
  268. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/visual-plan.template.html +0 -0
  269. /package/.agents/{skills → skills-archived}/anthropic-plan/test_skill_contract.py +0 -0
  270. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/.claude/CLAUDE.md +0 -0
  271. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/AGENTS.md +0 -0
  272. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/plan-packet.contract.test.mjs +0 -0
  273. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/plan-packet.mjs +0 -0
  274. /package/.agents/{skills → skills-archived}/auditing-claude-config/.claude/CLAUDE.md +0 -0
  275. /package/.agents/{skills → skills-archived}/auditing-claude-config/AGENTS.md +0 -0
  276. /package/.agents/{skills → skills-archived}/auditing-claude-config/SKILL.md +0 -0
  277. /package/.agents/{skills → skills-archived}/auditing-claude-config/reference/probe-hook.md +0 -0
  278. /package/.agents/{skills → skills-archived}/beat-sheet/SKILL.md +0 -0
  279. /package/.agents/{skills → skills-archived}/beat-sheet/reference/visual-beats.md +0 -0
  280. /package/.agents/{skills → skills-archived}/bugteam/.claude/CLAUDE.md +0 -0
  281. /package/.agents/{skills → skills-archived}/bugteam/AGENTS.md +0 -0
  282. /package/.agents/{skills → skills-archived}/bugteam/CONSTRAINTS.md +0 -0
  283. /package/.agents/{skills → skills-archived}/bugteam/EXAMPLES.md +0 -0
  284. /package/.agents/{skills → skills-archived}/bugteam/PROMPTS.md +0 -0
  285. /package/.agents/{skills → skills-archived}/bugteam/SKILL.md +0 -0
  286. /package/.agents/{skills → skills-archived}/bugteam/reference/.claude/CLAUDE.md +0 -0
  287. /package/.agents/{skills → skills-archived}/bugteam/reference/AGENTS.md +0 -0
  288. /package/.agents/{skills → skills-archived}/bugteam/reference/README.md +0 -0
  289. /package/.agents/{skills → skills-archived}/bugteam/reference/audit-and-teammates.md +0 -0
  290. /package/.agents/{skills → skills-archived}/bugteam/reference/copilot-gap-analysis.md +0 -0
  291. /package/.agents/{skills → skills-archived}/bugteam/reference/design-rationale.md +0 -0
  292. /package/.agents/{skills → skills-archived}/bugteam/reference/github-pr-reviews.md +0 -0
  293. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/.claude/CLAUDE.md +0 -0
  294. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/AGENTS.md +0 -0
  295. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-assign-ids.md +0 -0
  296. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-capture-excerpts.md +0 -0
  297. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-walk-categories.md +0 -0
  298. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-write-xml.md +0 -0
  299. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-append-summary.md +0 -0
  300. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-apply-fixes.md +0 -0
  301. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-git-add-commit.md +0 -0
  302. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-git-push.md +0 -0
  303. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-post-reply.md +0 -0
  304. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-publish-summary.md +0 -0
  305. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-py-compile.md +0 -0
  306. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-read-files.md +0 -0
  307. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-resolve-thread.md +0 -0
  308. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-test-suite.md +0 -0
  309. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-violation-count.md +0 -0
  310. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-write-xml.md +0 -0
  311. /package/.agents/{skills → skills-archived}/bugteam/reference/team-setup.md +0 -0
  312. /package/.agents/{skills → skills-archived}/bugteam/scripts/.claude/CLAUDE.md +0 -0
  313. /package/.agents/{skills → skills-archived}/bugteam/scripts/AGENTS.md +0 -0
  314. /package/.agents/{skills → skills-archived}/bugteam/scripts/README.md +0 -0
  315. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_code_rules_gate.py +0 -0
  316. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_fix_hookspath.py +0 -0
  317. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_preflight.py +0 -0
  318. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/.claude/CLAUDE.md +0 -0
  319. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -0
  320. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/__init__.py +0 -0
  321. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/probe_code_rules_enforcer_check_constants.py +0 -0
  322. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/reflow_skill_md_constants.py +0 -0
  323. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/windows_safe_rmtree_constants.py +0 -0
  324. /package/.agents/{skills → skills-archived}/bugteam/scripts/probe_code_rules_enforcer_check.py +0 -0
  325. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_code_rules_gate.py +0 -0
  326. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -0
  327. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_preflight.py +0 -0
  328. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_probe_code_rules_enforcer_check.py +0 -0
  329. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_windows_safe_rmtree.py +0 -0
  330. /package/.agents/{skills → skills-archived}/bugteam/scripts/windows_safe_rmtree.py +0 -0
  331. /package/.agents/{skills → skills-archived}/bugteam/sources.md +0 -0
  332. /package/.agents/{skills → skills-archived}/bugteam/test_skill_additions.py +0 -0
  333. /package/.agents/{skills → skills-archived}/closeout/SKILL.md +0 -0
  334. /package/.agents/{skills → skills-archived}/closeout/reference/handoff-prompt-template.md +0 -0
  335. /package/.agents/{skills → skills-archived}/closeout/reference/pii-redaction-checklist.md +0 -0
  336. /package/.agents/{skills → skills-archived}/codex-review/.claude/CLAUDE.md +0 -0
  337. /package/.agents/{skills → skills-archived}/codex-review/AGENTS.md +0 -0
  338. /package/.agents/{skills → skills-archived}/codex-review/SKILL.md +0 -0
  339. /package/.agents/{skills → skills-archived}/codex-review/reference/.claude/CLAUDE.md +0 -0
  340. /package/.agents/{skills → skills-archived}/codex-review/reference/AGENTS.md +0 -0
  341. /package/.agents/{skills → skills-archived}/codex-review/reference/cli-contract.md +0 -0
  342. /package/.agents/{skills → skills-archived}/codex-review/reference/loop-integration.md +0 -0
  343. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_down_classifier.py +0 -0
  344. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +0 -0
  345. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -0
  346. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/__init__.py +0 -0
  347. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/classifier_constants.py +0 -0
  348. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +0 -0
  349. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/findings_constants.py +0 -0
  350. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/run_constants.py +0 -0
  351. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_usage_probe.py +0 -0
  352. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/auth_failure_synthetic.txt +0 -0
  353. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/config_load_failure_v0.125.0.txt +0 -0
  354. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/freeform_findings_v0.144.3.txt +0 -0
  355. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/model_rejection_v0.125.0.jsonl +0 -0
  356. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/structured_findings.txt +0 -0
  357. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/success_stream_v0.144.3.jsonl +0 -0
  358. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/unknown_failure_synthetic.txt +0 -0
  359. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/usage_limit_synthetic.txt +0 -0
  360. /package/.agents/{skills → skills-archived}/codex-review/scripts/parse_codex_findings.py +0 -0
  361. /package/.agents/{skills → skills-archived}/codex-review/scripts/run_codex_review.py +0 -0
  362. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_codex_down_classifier.py +0 -0
  363. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_codex_usage_probe.py +0 -0
  364. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_parse_codex_findings.py +0 -0
  365. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_run_codex_review.py +0 -0
  366. /package/.agents/{skills → skills-archived}/comments/SKILL.md +0 -0
  367. /package/.agents/{skills → skills-archived}/condensing-instructions/SKILL.md +0 -0
  368. /package/.agents/{skills → skills-archived}/copilot-finding-triage/reference/tier-rubric.md +0 -0
  369. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/conftest.py +0 -0
  370. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/__init__.py +0 -0
  371. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/__init__.py +0 -0
  372. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +0 -0
  373. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/notify_ntfy.py +0 -0
  374. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/test_notify_ntfy.py +0 -0
  375. /package/.agents/{skills → skills-archived}/copilot-finding-triage/templates/notification.md +0 -0
  376. /package/.agents/{skills → skills-archived}/copilot-review/.claude/CLAUDE.md +0 -0
  377. /package/.agents/{skills → skills-archived}/copilot-review/AGENTS.md +0 -0
  378. /package/.agents/{skills → skills-archived}/copilot-review/SKILL.md +0 -0
  379. /package/.agents/{skills → skills-archived}/copilot-review/templates/subagent-prompt.md +0 -0
  380. /package/.agents/{skills → skills-archived}/descriptions/SKILL.md +0 -0
  381. /package/.agents/{skills → skills-archived}/emergencies/SKILL.md +0 -0
  382. /package/.agents/{skills → skills-archived}/grokify/SKILL.md +0 -0
  383. /package/.agents/{skills → skills-archived}/grokify/capability-claims.test.mjs +0 -0
  384. /package/.agents/{skills → skills-archived}/grokify/templates/handoff-template.md +0 -0
  385. /package/.agents/{skills → skills-archived}/plan-to-pr/SKILL.md +0 -0
  386. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/final-validation-tasks.md +0 -0
  387. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/model-routing.md +0 -0
  388. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/packet-contract.md +0 -0
  389. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/packet-schema.json +0 -0
  390. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/process-inventory.md +0 -0
  391. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/review-loop.md +0 -0
  392. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/run-record.schema.json +0 -0
  393. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/self-audit-tasks.md +0 -0
  394. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/task-seeds.md +0 -0
  395. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/task-ticket.md +0 -0
  396. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/config/__init__.py +0 -0
  397. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/config/constants.py +0 -0
  398. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/create_packet.py +0 -0
  399. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/load_skill_constants.py +0 -0
  400. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_create_packet.py +0 -0
  401. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_packet.py +0 -0
  402. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_protocol.py +0 -0
  403. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_run.py +0 -0
  404. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_packet.py +0 -0
  405. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_protocol.py +0 -0
  406. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_run.py +0 -0
  407. /package/.agents/{skills → skills-archived}/plan-to-pr/test_skill_contract.py +0 -0
  408. /package/.agents/{skills → skills-archived}/plan-to-pr/test_task_ticket_contract.py +0 -0
  409. /package/.agents/{skills → skills-archived}/pr-converge/.claude/CLAUDE.md +0 -0
  410. /package/.agents/{skills → skills-archived}/pr-converge/AGENTS.md +0 -0
  411. /package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/.claude/CLAUDE.md +0 -0
  412. /package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/__init__.py +0 -0
  413. /package/.agents/{skills → skills-archived}/pr-converge/reference/.claude/CLAUDE.md +0 -0
  414. /package/.agents/{skills → skills-archived}/pr-converge/reference/AGENTS.md +0 -0
  415. /package/.agents/{skills → skills-archived}/pr-converge/reference/convergence-gates.md +0 -0
  416. /package/.agents/{skills → skills-archived}/pr-converge/reference/examples.md +0 -0
  417. /package/.agents/{skills → skills-archived}/pr-converge/reference/fix-protocol.md +0 -0
  418. /package/.agents/{skills → skills-archived}/pr-converge/reference/ground-rules.md +0 -0
  419. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/.claude/CLAUDE.md +0 -0
  420. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/AGENTS.md +0 -0
  421. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-post-replies.md +0 -0
  422. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-publish-summary.md +0 -0
  423. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-push.md +0 -0
  424. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-read-filelines.md +0 -0
  425. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-reset-state.md +0 -0
  426. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-resolve-threads.md +0 -0
  427. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +0 -0
  428. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-stage-commit.md +0 -0
  429. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-trigger-bugbot.md +0 -0
  430. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-write-test.md +0 -0
  431. /package/.agents/{skills → skills-archived}/pr-converge/reference/progress-checklist.md +0 -0
  432. /package/.agents/{skills → skills-archived}/pr-converge/reference/state-schema.md +0 -0
  433. /package/.agents/{skills → skills-archived}/pr-converge/reference/stop-conditions.md +0 -0
  434. /package/.agents/{skills → skills-archived}/pr-converge/scripts/.claude/CLAUDE.md +0 -0
  435. /package/.agents/{skills → skills-archived}/pr-converge/scripts/AGENTS.md +0 -0
  436. /package/.agents/{skills → skills-archived}/pr-converge/scripts/README.md +0 -0
  437. /package/.agents/{skills → skills-archived}/pr-converge/scripts/_pr_converge_path_setup.py +0 -0
  438. /package/.agents/{skills → skills-archived}/pr-converge/scripts/caller-window-pid.ps1 +0 -0
  439. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_bugbot_ci.py +0 -0
  440. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence.py +0 -0
  441. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_availability.py +0 -0
  442. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_gates.py +0 -0
  443. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_thread_gates.py +0 -0
  444. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_pending_reviews.py +0 -0
  445. /package/.agents/{skills → skills-archived}/pr-converge/scripts/conftest.py +0 -0
  446. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue-caller.cmd +0 -0
  447. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue-stop-others.ps1 +0 -0
  448. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue.ahk +0 -0
  449. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue.cmd +0 -0
  450. /package/.agents/{skills → skills-archived}/pr-converge/scripts/fetch_copilot_reviews.py +0 -0
  451. /package/.agents/{skills → skills-archived}/pr-converge/scripts/post_fix_reply.py +0 -0
  452. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +0 -0
  453. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -0
  454. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  455. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +0 -0
  456. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/pr_converge_constants.py +0 -0
  457. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +0 -0
  458. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test__pr_converge_path_setup.py +0 -0
  459. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_bugbot_ci.py +0 -0
  460. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence.py +0 -0
  461. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_availability.py +0 -0
  462. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_codex.py +0 -0
  463. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_contract.py +0 -0
  464. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_fixture.py +0 -0
  465. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_gates.py +0 -0
  466. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_thread_gates.py +0 -0
  467. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_cursor_agents_continue.py +0 -0
  468. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_reflow_skill_md.py +0 -0
  469. /package/.agents/{skills → skills-archived}/pr-converge/test_step5_host_branch.py +0 -0
  470. /package/.agents/{skills → skills-archived}/pr-converge/workflows/.claude/CLAUDE.md +0 -0
  471. /package/.agents/{skills → skills-archived}/pr-converge/workflows/AGENTS.md +0 -0
  472. /package/.agents/{skills → skills-archived}/pr-fix-protocol/SKILL.md +0 -0
  473. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/SKILL.md +0 -0
  474. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/reference/identity-and-hooks.md +0 -0
  475. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/reference/substitution-matrix.md +0 -0
  476. /package/.agents/{skills → skills-archived}/pr-loop-lifecycle/SKILL.md +0 -0
  477. /package/.agents/{skills → skills-archived}/pr-loop-lifecycle/reference/teardown-publish-permissions.md +0 -0
  478. /package/.agents/{skills → skills-archived}/recall/.claude/CLAUDE.md +0 -0
  479. /package/.agents/{skills → skills-archived}/recall/AGENTS.md +0 -0
  480. /package/.agents/{skills → skills-archived}/recall/SKILL.md +0 -0
  481. /package/.agents/{skills → skills-archived}/release-notes-html/SKILL.md +0 -0
  482. /package/.agents/{skills → skills-archived}/remember/.claude/CLAUDE.md +0 -0
  483. /package/.agents/{skills → skills-archived}/remember/AGENTS.md +0 -0
  484. /package/.agents/{skills → skills-archived}/remember/SKILL.md +0 -0
  485. /package/.agents/{skills → skills-archived}/reviewer-gates/SKILL.md +0 -0
  486. /package/.agents/{skills → skills-archived}/reviews/SKILL.md +0 -0
  487. /package/.agents/{skills → skills-archived}/show/SKILL.md +0 -0
  488. /package/.agents/{skills → skills-archived}/show/references/accessibility.md +0 -0
  489. /package/.agents/{skills → skills-archived}/show/references/art.md +0 -0
  490. /package/.agents/{skills → skills-archived}/show/references/charts.md +0 -0
  491. /package/.agents/{skills → skills-archived}/show/references/core-design.md +0 -0
  492. /package/.agents/{skills → skills-archived}/show/references/erds.md +0 -0
  493. /package/.agents/{skills → skills-archived}/show/references/flowcharts.md +0 -0
  494. /package/.agents/{skills → skills-archived}/show/references/host-and-html.md +0 -0
  495. /package/.agents/{skills → skills-archived}/show/references/illustrative-diagrams.md +0 -0
  496. /package/.agents/{skills → skills-archived}/show/references/interaction.md +0 -0
  497. /package/.agents/{skills → skills-archived}/show/references/mockups.md +0 -0
  498. /package/.agents/{skills → skills-archived}/show/references/quality-gates.md +0 -0
  499. /package/.agents/{skills → skills-archived}/show/references/structural-diagrams.md +0 -0
  500. /package/.agents/{skills → skills-archived}/show/references/subject-inventory.md +0 -0
  501. /package/.agents/{skills → skills-archived}/show/references/svg-contract.md +0 -0
  502. /package/.agents/{skills → skills-archived}/show/routing.yaml +0 -0
  503. /package/.agents/{skills → skills-archived}/show/samples/pr1262-v2.svg +0 -0
  504. /package/.agents/{skills → skills-archived}/show/scripts/README.md +0 -0
  505. /package/.agents/{skills → skills-archived}/show/scripts/validate-artifact.py +0 -0
  506. /package/.agents/{skills → skills-archived}/show/scripts/validate-package.py +0 -0
  507. /package/.agents/{skills → skills-archived}/show/templates/html-widget.html +0 -0
  508. /package/.agents/{skills → skills-archived}/show/templates/svg-base.svg +0 -0
  509. /package/.agents/{skills → skills-archived}/show/tests/fixtures/css-var.svg +0 -0
  510. /package/.agents/{skills → skills-archived}/show/tests/fixtures/dead-ref.svg +0 -0
  511. /package/.agents/{skills → skills-archived}/show/tests/fixtures/filled-glyph.svg +0 -0
  512. /package/.agents/{skills → skills-archived}/show/tests/fixtures/inherited-fill.svg +0 -0
  513. /package/.agents/{skills → skills-archived}/show/tests/fixtures/invalid.svg +0 -0
  514. /package/.agents/{skills → skills-archived}/show/tests/fixtures/large-canvas.svg +0 -0
  515. /package/.agents/{skills → skills-archived}/show/tests/fixtures/unfilled-connector.svg +0 -0
  516. /package/.agents/{skills → skills-archived}/show/tests/fixtures/valid.html +0 -0
  517. /package/.agents/{skills → skills-archived}/show/tests/test_validate-artifact.py +0 -0
  518. /package/.agents/{skills → skills-archived}/show/tests/test_validators.py +0 -0
  519. /package/.agents/{skills → skills-archived}/show/workflows/create-visual.md +0 -0
  520. /package/.agents/{skills → skills-archived}/show/workflows/review-visual.md +0 -0
  521. /package/.agents/{skills → skills-archived}/split-pr/SKILL.md +0 -0
  522. /package/.agents/{skills → skills-archived}/split-pr/reference/path-layers.md +0 -0
  523. /package/.agents/{skills → skills-archived}/split-pr/reference/split-further-loop.md +0 -0
  524. /package/.agents/{skills → skills-archived}/split-pr/reference/splitting-principles.md +0 -0
  525. /package/.agents/{skills → skills-archived}/split-pr/scripts/analyze_pr.py +0 -0
  526. /package/.agents/{skills → skills-archived}/split-pr/scripts/categorize_files.py +0 -0
  527. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/__init__.py +0 -0
  528. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/dependency_constants.py +0 -0
  529. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/git_operations_constants.py +0 -0
  530. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/packing_constants.py +0 -0
  531. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/plan_constants.py +0 -0
  532. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/split_pr_constants.py +0 -0
  533. /package/.agents/{skills → skills-archived}/split-pr/scripts/execute_split_slices.py +0 -0
  534. /package/.agents/{skills → skills-archived}/split-pr/scripts/pack_files_into_slices.py +0 -0
  535. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_dependency_graph.py +0 -0
  536. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_git_operations.py +0 -0
  537. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_layer_order.py +0 -0
  538. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_paginate.py +0 -0
  539. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_process_runner.py +0 -0
  540. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_script_types.py +0 -0
  541. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_title.py +0 -0
  542. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_analyze_pr.py +0 -0
  543. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_categorize_files.py +0 -0
  544. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_categorize_files_packing.py +0 -0
  545. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_execute_split_slices.py +0 -0
  546. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_dependency_graph.py +0 -0
  547. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_git_operations.py +0 -0
  548. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_layer_order.py +0 -0
  549. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_paginate.py +0 -0
  550. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_script_types.py +0 -0
  551. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_title.py +0 -0
  552. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_dependency_graph.py +0 -0
  553. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan.py +0 -0
  554. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan_contract.py +0 -0
  555. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan_path_normalization.py +0 -0
  556. /package/.agents/{skills → skills-archived}/split-pr/scripts/verify_dependency_graph.py +0 -0
  557. /package/.agents/{skills → skills-archived}/split-pr/scripts/verify_plan.py +0 -0
@@ -0,0 +1,570 @@
1
+ #!/usr/bin/env python3
2
+ """Report remaining weekly Codex usage as machine-readable JSON.
3
+
4
+ Discovery (codex-cli 0.144.3): no dedicated ``codex usage`` subcommand.
5
+ ``codex login status`` prints auth only. Weekly meters come from the
6
+ app-server JSON-RPC method ``account/rateLimits/read`` via
7
+ ``codex app-server --listen stdio://``. The weekly window is the rate-limit
8
+ window whose ``windowDurationMins`` is 10080 (seven days), preferring
9
+ ``secondary`` when both primary and secondary carry that duration.
10
+
11
+ stdout is one JSON object ``{percent_left, window_reset, source}``.
12
+ ``percent_left`` is 0-100, or null when the binary offers no usage data.
13
+ Exit 0 when the probe completed against a reachable CLI (including null
14
+ data). Exit non-zero when the Codex CLI is missing or broken, or when the
15
+ probe itself crashes — consumers must not treat that as a usage-threshold
16
+ skip.
17
+
18
+ Gate rule for consumers: null or unknown ``percent_left`` on exit 0 counts
19
+ as at-or-below ``WEEKLY_USAGE_GATE_THRESHOLD_PERCENT`` — the gate may skip
20
+ and never blocks on missing meters. A non-zero probe exit is CLI failure
21
+ (classify ``codex_down`` or fail closed), not a threshold skip. Require
22
+ review only when exit 0 and ``is_codex_review_required(percent_left)``.
23
+
24
+ ::
25
+
26
+ python codex_usage_probe.py
27
+ {"percent_left": 5, "window_reset": "2026-07-19T23:49:08+00:00",
28
+ "source": "codex app-server account/rateLimits/read"}
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import json
34
+ import math
35
+ import os
36
+ import re
37
+ import shutil
38
+ import subprocess
39
+ import sys
40
+ import threading
41
+ from collections.abc import Mapping, Sequence
42
+ from datetime import datetime, timezone
43
+ from pathlib import Path
44
+ from typing import IO, Protocol
45
+
46
+ _here = Path(__file__).resolve()
47
+ _skills_home_directory = _here.parents[3]
48
+ _package_or_user_home = (
49
+ _skills_home_directory.parent
50
+ if _skills_home_directory.name == ".agents"
51
+ else _skills_home_directory
52
+ )
53
+ _shared_under_package = _package_or_user_home / "_shared" / "process-tree" / "scripts"
54
+ _shared_process_tree_scripts_directory = (
55
+ _shared_under_package
56
+ if _shared_under_package.is_dir()
57
+ else _package_or_user_home / ".claude" / "_shared" / "process-tree" / "scripts"
58
+ )
59
+ if str(_shared_process_tree_scripts_directory) not in sys.path:
60
+ sys.path.insert(0, str(_shared_process_tree_scripts_directory))
61
+
62
+ from process_tree_kill import ( # noqa: E402
63
+ should_start_new_session,
64
+ terminate_process_tree,
65
+ )
66
+
67
+ from codex_review_scripts_constants.codex_usage_probe_constants import ( # noqa: E402
68
+ ALL_APP_SERVER_COMMAND_PARTS,
69
+ ALL_WINDOWS_SCRIPT_SUFFIXES,
70
+ APP_SERVER_TIMEOUT_SECONDS,
71
+ CAPABILITIES_KEY,
72
+ CLIENT_INFO_KEY,
73
+ CLIENT_INFO_NAME,
74
+ CLIENT_INFO_NAME_KEY,
75
+ CLIENT_INFO_VERSION,
76
+ CLIENT_INFO_VERSION_KEY,
77
+ CODEX_BINARY_NAME,
78
+ EXIT_CODE_CRASH,
79
+ EXIT_CODE_SUCCESS,
80
+ EXPERIMENTAL_API_KEY,
81
+ INITIALIZE_REQUEST_ID,
82
+ JSONRPC_KEY_ERROR,
83
+ JSONRPC_KEY_ID,
84
+ JSONRPC_KEY_METHOD,
85
+ JSONRPC_KEY_PARAMS,
86
+ JSONRPC_KEY_REPLY_BODY,
87
+ JSONRPC_KEY_VERSION,
88
+ JSONRPC_VERSION,
89
+ METHOD_INITIALIZE,
90
+ METHOD_INITIALIZED,
91
+ METHOD_RATE_LIMITS_READ,
92
+ NEWLINE,
93
+ PERCENT_EMPTY,
94
+ PERCENT_FULL,
95
+ PRIMARY_WINDOW_KEY,
96
+ PROCESS_TREE_WAIT_TIMEOUT_SECONDS,
97
+ RATE_LIMITS_KEY,
98
+ RATE_LIMITS_REQUEST_ID,
99
+ READER_THREAD_JOIN_TIMEOUT_SECONDS,
100
+ RESETS_AT_KEY,
101
+ SECONDARY_WINDOW_KEY,
102
+ SOURCE_APP_SERVER_RATE_LIMITS,
103
+ SOURCE_NO_USAGE_SURFACE,
104
+ SOURCE_TEXT_STATUS,
105
+ TEXT_WEEKLY_PERCENT_LEFT_PATTERN,
106
+ TEXT_WEEKLY_USED_PERCENT_PATTERN,
107
+ TEXT_WINDOW_RESET_PATTERN,
108
+ USAGE_REPORT_KEY_PERCENT_LEFT,
109
+ USAGE_REPORT_KEY_SOURCE,
110
+ USAGE_REPORT_KEY_WINDOW_RESET,
111
+ USED_PERCENT_KEY,
112
+ UTF8_ENCODING,
113
+ WEEKLY_USAGE_GATE_THRESHOLD_PERCENT,
114
+ WEEKLY_WINDOW_DURATION_MINUTES,
115
+ WINDOW_DURATION_MINS_KEY,
116
+ WINDOWS_COMMAND_SHELL,
117
+ WINDOWS_COMMAND_SHELL_RUN_FLAG,
118
+ WINDOWS_OS_NAME,
119
+ )
120
+
121
+
122
+ class AppServerExchange(Protocol):
123
+ """Callable that sends JSON-RPC request objects and returns stdout lines."""
124
+
125
+ def __call__(
126
+ self, all_request_messages: list[dict[str, object]]
127
+ ) -> list[str]:
128
+ """Exchange request messages for server stdout lines.
129
+
130
+ Args:
131
+ all_request_messages: JSON-RPC request/notification objects to send.
132
+
133
+ Returns:
134
+ Raw stdout lines from the app-server process.
135
+ """
136
+
137
+
138
+ UsageReport = dict[str, float | str | None]
139
+
140
+
141
+ def is_codex_review_required(percent_left: float | None) -> bool:
142
+ """Return whether the weekly gate should require a Codex review pass.
143
+
144
+ ::
145
+
146
+ None -> False # missing data never blocks
147
+ 10.0 -> False # at threshold: skip
148
+ 10.1 -> True # above threshold: require
149
+
150
+ Args:
151
+ percent_left: Weekly percent remaining, or None when unknown.
152
+
153
+ Returns:
154
+ True only when percent_left is known and strictly greater than
155
+ WEEKLY_USAGE_GATE_THRESHOLD_PERCENT.
156
+ """
157
+ if percent_left is None:
158
+ return False
159
+ return percent_left > WEEKLY_USAGE_GATE_THRESHOLD_PERCENT
160
+
161
+
162
+ def _null_usage_report() -> UsageReport:
163
+ return {
164
+ USAGE_REPORT_KEY_PERCENT_LEFT: None,
165
+ USAGE_REPORT_KEY_WINDOW_RESET: None,
166
+ USAGE_REPORT_KEY_SOURCE: SOURCE_NO_USAGE_SURFACE,
167
+ }
168
+
169
+
170
+ def _clamp_percent(raw_percent: float) -> float:
171
+ return max(float(PERCENT_EMPTY), min(float(PERCENT_FULL), raw_percent))
172
+
173
+
174
+ def _format_resets_at(raw_resets_at: object) -> str | None:
175
+ if isinstance(raw_resets_at, bool):
176
+ return None
177
+ if isinstance(raw_resets_at, (int, float)):
178
+ if not math.isfinite(raw_resets_at):
179
+ return None
180
+ try:
181
+ return datetime.fromtimestamp(
182
+ float(raw_resets_at), tz=timezone.utc
183
+ ).isoformat()
184
+ except (OverflowError, OSError, ValueError):
185
+ return None
186
+ if isinstance(raw_resets_at, str):
187
+ stripped = raw_resets_at.strip()
188
+ return stripped or None
189
+ return None
190
+
191
+
192
+ def _window_used_percent(all_window_fields: Mapping[str, object]) -> float | None:
193
+ raw_used_percent = all_window_fields.get(USED_PERCENT_KEY)
194
+ if isinstance(raw_used_percent, bool):
195
+ return None
196
+ if isinstance(raw_used_percent, (int, float)):
197
+ if not math.isfinite(raw_used_percent):
198
+ return None
199
+ return float(raw_used_percent)
200
+ return None
201
+
202
+
203
+ def _window_duration_minutes(
204
+ all_window_fields: Mapping[str, object],
205
+ ) -> int | None:
206
+ raw_duration = all_window_fields.get(WINDOW_DURATION_MINS_KEY)
207
+ if isinstance(raw_duration, bool):
208
+ return None
209
+ if isinstance(raw_duration, (int, float)):
210
+ if not math.isfinite(raw_duration):
211
+ return None
212
+ return int(raw_duration)
213
+ return None
214
+
215
+
216
+ def _select_weekly_window(
217
+ all_rate_limit_fields: Mapping[str, object],
218
+ ) -> Mapping[str, object] | None:
219
+ primary_payload = all_rate_limit_fields.get(PRIMARY_WINDOW_KEY)
220
+ secondary_payload = all_rate_limit_fields.get(SECONDARY_WINDOW_KEY)
221
+ all_candidate_windows: list[Mapping[str, object]] = []
222
+ if isinstance(secondary_payload, Mapping):
223
+ all_candidate_windows.append(secondary_payload)
224
+ if isinstance(primary_payload, Mapping):
225
+ all_candidate_windows.append(primary_payload)
226
+ if not all_candidate_windows:
227
+ return None
228
+ for each_window in all_candidate_windows:
229
+ if _window_duration_minutes(each_window) == WEEKLY_WINDOW_DURATION_MINUTES:
230
+ return each_window
231
+ return None
232
+
233
+
234
+ def _usage_report_from_window(
235
+ all_weekly_window_fields: Mapping[str, object],
236
+ source: str,
237
+ ) -> UsageReport:
238
+ used_percent = _window_used_percent(all_weekly_window_fields)
239
+ if used_percent is None:
240
+ return _null_usage_report()
241
+ percent_left = _clamp_percent(float(PERCENT_FULL) - used_percent)
242
+ return {
243
+ USAGE_REPORT_KEY_PERCENT_LEFT: percent_left,
244
+ USAGE_REPORT_KEY_WINDOW_RESET: _format_resets_at(
245
+ all_weekly_window_fields.get(RESETS_AT_KEY)
246
+ ),
247
+ USAGE_REPORT_KEY_SOURCE: source,
248
+ }
249
+
250
+
251
+ def _parse_rate_limits_snapshot(
252
+ all_rate_limit_fields: Mapping[str, object],
253
+ ) -> UsageReport:
254
+ weekly_window = _select_weekly_window(all_rate_limit_fields)
255
+ if weekly_window is None:
256
+ return _null_usage_report()
257
+ return _usage_report_from_window(weekly_window, SOURCE_APP_SERVER_RATE_LIMITS)
258
+
259
+
260
+ def parse_rate_limits_message(message_text: str) -> UsageReport:
261
+ """Parse one JSON-RPC reply line that may carry rateLimits.
262
+
263
+ Args:
264
+ message_text: A single stdout line from ``codex app-server``.
265
+
266
+ Returns:
267
+ The usage report, or a null report when the line has no usable meters.
268
+ """
269
+ try:
270
+ message_payload = json.loads(message_text)
271
+ except json.JSONDecodeError:
272
+ return _null_usage_report()
273
+ if not isinstance(message_payload, dict):
274
+ return _null_usage_report()
275
+ if message_payload.get(JSONRPC_KEY_ERROR) is not None:
276
+ return _null_usage_report()
277
+ reply_body = message_payload.get(JSONRPC_KEY_REPLY_BODY)
278
+ if not isinstance(reply_body, dict):
279
+ return _null_usage_report()
280
+ all_rate_limit_fields = reply_body.get(RATE_LIMITS_KEY)
281
+ if not isinstance(all_rate_limit_fields, dict):
282
+ return _null_usage_report()
283
+ return _parse_rate_limits_snapshot(all_rate_limit_fields)
284
+
285
+
286
+ def _text_status_report(
287
+ percent_left: float,
288
+ status_text: str,
289
+ search_from_index: int,
290
+ ) -> UsageReport:
291
+ weekly_scoped_text = status_text[search_from_index:]
292
+ reset_match = re.search(TEXT_WINDOW_RESET_PATTERN, weekly_scoped_text)
293
+ window_reset = (
294
+ reset_match.group("reset").strip() if reset_match is not None else None
295
+ )
296
+ return {
297
+ USAGE_REPORT_KEY_PERCENT_LEFT: percent_left,
298
+ USAGE_REPORT_KEY_WINDOW_RESET: window_reset,
299
+ USAGE_REPORT_KEY_SOURCE: SOURCE_TEXT_STATUS,
300
+ }
301
+
302
+
303
+ def parse_text_usage_status(status_text: str) -> UsageReport:
304
+ """Parse human status text for a weekly percent remaining.
305
+
306
+ Args:
307
+ status_text: Captured CLI or TUI status text.
308
+
309
+ Returns:
310
+ The usage report when a weekly percent pattern matches, else null.
311
+ """
312
+ left_match = re.search(TEXT_WEEKLY_PERCENT_LEFT_PATTERN, status_text)
313
+ if left_match is not None:
314
+ percent_left = _clamp_percent(float(left_match.group("percent")))
315
+ return _text_status_report(
316
+ percent_left,
317
+ status_text,
318
+ search_from_index=left_match.start(),
319
+ )
320
+ used_match = re.search(TEXT_WEEKLY_USED_PERCENT_PATTERN, status_text)
321
+ if used_match is not None:
322
+ percent_left = _clamp_percent(
323
+ float(PERCENT_FULL) - float(used_match.group("percent"))
324
+ )
325
+ return _text_status_report(
326
+ percent_left,
327
+ status_text,
328
+ search_from_index=used_match.start(),
329
+ )
330
+ return _null_usage_report()
331
+
332
+
333
+ def _build_app_server_request_messages() -> list[dict[str, object]]:
334
+ initialize_request: dict[str, object] = {
335
+ JSONRPC_KEY_VERSION: JSONRPC_VERSION,
336
+ JSONRPC_KEY_ID: INITIALIZE_REQUEST_ID,
337
+ JSONRPC_KEY_METHOD: METHOD_INITIALIZE,
338
+ JSONRPC_KEY_PARAMS: {
339
+ CLIENT_INFO_KEY: {
340
+ CLIENT_INFO_NAME_KEY: CLIENT_INFO_NAME,
341
+ CLIENT_INFO_VERSION_KEY: CLIENT_INFO_VERSION,
342
+ },
343
+ CAPABILITIES_KEY: {EXPERIMENTAL_API_KEY: True},
344
+ },
345
+ }
346
+ initialized_notification: dict[str, object] = {
347
+ JSONRPC_KEY_VERSION: JSONRPC_VERSION,
348
+ JSONRPC_KEY_METHOD: METHOD_INITIALIZED,
349
+ JSONRPC_KEY_PARAMS: {},
350
+ }
351
+ rate_limits_request: dict[str, object] = {
352
+ JSONRPC_KEY_VERSION: JSONRPC_VERSION,
353
+ JSONRPC_KEY_ID: RATE_LIMITS_REQUEST_ID,
354
+ JSONRPC_KEY_METHOD: METHOD_RATE_LIMITS_READ,
355
+ JSONRPC_KEY_PARAMS: {},
356
+ }
357
+ return [initialize_request, initialized_notification, rate_limits_request]
358
+
359
+
360
+ def _resolve_codex_command() -> list[str]:
361
+ codex_path = shutil.which(CODEX_BINARY_NAME)
362
+ if codex_path is None:
363
+ raise FileNotFoundError(f"{CODEX_BINARY_NAME} binary not found on PATH")
364
+ lower_path = codex_path.lower()
365
+ if os.name == WINDOWS_OS_NAME and lower_path.endswith(
366
+ ALL_WINDOWS_SCRIPT_SUFFIXES
367
+ ):
368
+ return [
369
+ WINDOWS_COMMAND_SHELL,
370
+ WINDOWS_COMMAND_SHELL_RUN_FLAG,
371
+ codex_path,
372
+ *ALL_APP_SERVER_COMMAND_PARTS,
373
+ ]
374
+ return [codex_path, *ALL_APP_SERVER_COMMAND_PARTS]
375
+
376
+
377
+ def _is_rate_limits_reply(message_text: str) -> bool:
378
+ """Return whether a stdout line is the reply to our rate-limits request."""
379
+ try:
380
+ message_payload = json.loads(message_text)
381
+ except json.JSONDecodeError:
382
+ return False
383
+ if not isinstance(message_payload, dict):
384
+ return False
385
+ return message_payload.get(JSONRPC_KEY_ID) == RATE_LIMITS_REQUEST_ID
386
+
387
+
388
+ def _collect_server_lines(
389
+ server_stdout: IO[str],
390
+ all_server_lines: list[str],
391
+ is_exchange_over: threading.Event,
392
+ ) -> None:
393
+ """Append server stdout lines until the rate-limits reply lands or stdout ends."""
394
+ try:
395
+ for each_line in server_stdout:
396
+ stripped_line = each_line.strip()
397
+ if not stripped_line:
398
+ continue
399
+ all_server_lines.append(stripped_line)
400
+ if _is_rate_limits_reply(stripped_line):
401
+ break
402
+ except (OSError, ValueError):
403
+ pass
404
+ is_exchange_over.set()
405
+
406
+
407
+ def _terminate_process_tree(server_process: subprocess.Popen[str]) -> None:
408
+ """Stop the app-server process and any children it launched, then reap it.
409
+
410
+ On Windows the probe may wrap a ``.cmd``/``.bat`` shim as ``cmd /c``, so
411
+ ``Popen.pid`` is ``cmd.exe``. Killing only that process leaves the real
412
+ Codex app-server grandchild alive and holding stdout. The shared tree kill
413
+ ends the whole tree on either platform; the timed wait that follows reaps
414
+ the direct child so the enclosing ``with`` block exits without a long wait.
415
+ """
416
+ terminate_process_tree(server_process)
417
+ try:
418
+ server_process.wait(timeout=PROCESS_TREE_WAIT_TIMEOUT_SECONDS)
419
+ except subprocess.TimeoutExpired:
420
+ return
421
+
422
+
423
+ def _teardown_app_server_exchange(
424
+ server_process: subprocess.Popen[str],
425
+ reader_thread: threading.Thread,
426
+ ) -> None:
427
+ """Terminate the process tree, then join the stdout reader before return."""
428
+ _terminate_process_tree(server_process)
429
+ reader_thread.join(timeout=READER_THREAD_JOIN_TIMEOUT_SECONDS)
430
+
431
+
432
+ def _exchange_app_server_messages_via_subprocess(
433
+ all_request_messages: list[dict[str, object]],
434
+ ) -> list[str]:
435
+ """Run ``codex app-server`` and collect its replies to the probe's requests.
436
+
437
+ ::
438
+
439
+ write requests -> stdin stays OPEN -> server answers -> read reply -> close
440
+
441
+ The server treats end-of-input on stdin as a shutdown signal, so it exits
442
+ without answering when stdin closes right after the requests are written.
443
+ Stdin is held open until the rate-limits reply arrives or the timeout runs
444
+ out, then the process tree is torn down and the stdout reader is joined.
445
+
446
+ Args:
447
+ all_request_messages: JSON-RPC request/notification objects to send.
448
+
449
+ Returns:
450
+ The non-empty stdout lines the server emitted before the exchange ended.
451
+ """
452
+ all_command_parts = _resolve_codex_command()
453
+ stdin_text = NEWLINE.join(
454
+ json.dumps(each_message) for each_message in all_request_messages
455
+ ) + NEWLINE
456
+ all_server_lines: list[str] = []
457
+ is_exchange_over = threading.Event()
458
+ with subprocess.Popen(
459
+ all_command_parts,
460
+ stdin=subprocess.PIPE,
461
+ stdout=subprocess.PIPE,
462
+ stderr=subprocess.DEVNULL,
463
+ text=True,
464
+ encoding=UTF8_ENCODING,
465
+ shell=False,
466
+ start_new_session=should_start_new_session(),
467
+ ) as server_process:
468
+ server_stdin = server_process.stdin
469
+ server_stdout = server_process.stdout
470
+ if server_stdin is None or server_stdout is None:
471
+ _terminate_process_tree(server_process)
472
+ raise OSError("codex app-server offered no stdio pipes")
473
+ reader_thread = threading.Thread(
474
+ target=_collect_server_lines,
475
+ args=(server_stdout, all_server_lines, is_exchange_over),
476
+ daemon=True,
477
+ )
478
+ reader_thread.start()
479
+ try:
480
+ server_stdin.write(stdin_text)
481
+ server_stdin.flush()
482
+ is_exchange_over.wait(timeout=APP_SERVER_TIMEOUT_SECONDS)
483
+ finally:
484
+ _teardown_app_server_exchange(
485
+ server_process=server_process,
486
+ reader_thread=reader_thread,
487
+ )
488
+ return list(all_server_lines)
489
+
490
+
491
+ def _usage_report_from_server_lines(all_server_lines: Sequence[str]) -> UsageReport:
492
+ for each_line in all_server_lines:
493
+ usage_report = parse_rate_limits_message(each_line)
494
+ if usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is not None:
495
+ return usage_report
496
+ return _null_usage_report()
497
+
498
+
499
+ def probe_weekly_usage(
500
+ exchange_app_server_messages: AppServerExchange,
501
+ ) -> UsageReport:
502
+ """Probe weekly Codex usage through the app-server rate-limits surface.
503
+
504
+ Args:
505
+ exchange_app_server_messages: JSON-RPC exchange seam. Production passes
506
+ the real subprocess exchange; tests inject a fake.
507
+
508
+ Returns:
509
+ The usage report with percent_left, window_reset, and source.
510
+ """
511
+ all_request_messages = _build_app_server_request_messages()
512
+ all_server_lines = exchange_app_server_messages(all_request_messages)
513
+ return _usage_report_from_server_lines(all_server_lines)
514
+
515
+
516
+ def probe_weekly_usage_via_subprocess() -> UsageReport:
517
+ """Probe weekly usage against the real ``codex app-server`` subprocess.
518
+
519
+ ::
520
+
521
+ probe_weekly_usage_via_subprocess()
522
+ # ok: {"percent_left": 62.0, "window_reset": ..., "source": ...}
523
+
524
+ The production entry point for every caller that has no exchange seam of
525
+ its own to inject.
526
+
527
+ Returns:
528
+ The usage report with percent_left, window_reset, and source.
529
+ """
530
+ return probe_weekly_usage(
531
+ exchange_app_server_messages=_exchange_app_server_messages_via_subprocess
532
+ )
533
+
534
+
535
+ def main() -> int:
536
+ """Run the probe and print one JSON object on stdout.
537
+
538
+ ::
539
+
540
+ reachable CLI, meters present -> exit 0, percent_left number
541
+ reachable CLI, no meters -> exit 0, percent_left null (usage skip ok)
542
+ missing or broken CLI -> exit non-zero (not a usage skip)
543
+
544
+ Returns:
545
+ EXIT_CODE_SUCCESS on a completed probe against a reachable CLI
546
+ (including null data), or EXIT_CODE_CRASH when the Codex CLI is
547
+ missing or broken or the probe itself fails.
548
+ """
549
+ try:
550
+ usage_report = probe_weekly_usage(
551
+ exchange_app_server_messages=_exchange_app_server_messages_via_subprocess
552
+ )
553
+ except (
554
+ FileNotFoundError,
555
+ OSError,
556
+ subprocess.TimeoutExpired,
557
+ subprocess.SubprocessError,
558
+ UnicodeDecodeError,
559
+ ):
560
+ print(json.dumps(_null_usage_report()))
561
+ return EXIT_CODE_CRASH
562
+ except (json.JSONDecodeError, ValueError, TypeError, KeyError):
563
+ print(json.dumps(_null_usage_report()))
564
+ return EXIT_CODE_CRASH
565
+ print(json.dumps(usage_report))
566
+ return EXIT_CODE_SUCCESS
567
+
568
+
569
+ if __name__ == "__main__":
570
+ sys.exit(main())
@@ -0,0 +1,43 @@
1
+ """Put the shared PR-loop scripts directory on sys.path for the test suite."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+
8
+ _scripts_directory = Path(__file__).resolve().parent
9
+ if str(_scripts_directory) not in sys.path:
10
+ sys.path.insert(0, str(_scripts_directory))
11
+
12
+ import check_convergence_availability # noqa: E402
13
+ from pr_loop_shared_constants.reviews_disabled_constants import ( # noqa: E402
14
+ CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN,
15
+ CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN,
16
+ CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR,
17
+ CLAUDE_REVIEWS_ENABLED_ENV_VAR_NAME,
18
+ )
19
+
20
+ _MISSING_SETTINGS_PATH = Path("settings-absent-in-tests.json")
21
+
22
+
23
+ @pytest.fixture(autouse=True)
24
+ def opt_gated_reviewers_in(monkeypatch: pytest.MonkeyPatch) -> None:
25
+ """Point settings at an absent file and opt bugteam and codex in.
26
+
27
+ Bugteam and codex are off by default, and the resolver reads the real
28
+ ``~/.claude/settings.json`` first. Both together would decide these cases
29
+ from whatever the host machine has on disk. Aiming the resolver at an
30
+ absent path restores the env fallback, and the opt-in lets each case reach
31
+ the gate it was written for. A case that tests the lists themselves
32
+ overrides this from its own body.
33
+ """
34
+ check_convergence_availability._resolve_reviews_settings.cache_clear()
35
+ monkeypatch.setattr(
36
+ check_convergence_availability,
37
+ "get_claude_user_settings_path",
38
+ lambda: _MISSING_SETTINGS_PATH,
39
+ )
40
+ all_opted_in_tokens = CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR.join(
41
+ (CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN, CLAUDE_REVIEWS_DISABLED_CODEX_TOKEN)
42
+ )
43
+ monkeypatch.setenv(CLAUDE_REVIEWS_ENABLED_ENV_VAR_NAME, all_opted_in_tokens)