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,683 @@
1
+ """Tests for the Codex weekly-usage probe CLI.
2
+
3
+ Fixtures note the binary version they were captured against:
4
+ codex-cli 0.144.3 (account/rateLimits/read via ``codex app-server``).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import importlib.util
10
+ import json
11
+ import subprocess
12
+ import sys
13
+ import threading
14
+ import time
15
+ from pathlib import Path
16
+ from types import ModuleType
17
+
18
+ import pytest
19
+
20
+ SCRIPTS_DIRECTORY = Path(__file__).resolve().parent
21
+ if str(SCRIPTS_DIRECTORY) not in sys.path:
22
+ sys.path.insert(0, str(SCRIPTS_DIRECTORY))
23
+
24
+ from codex_review_scripts_constants.codex_usage_probe_constants import (
25
+ EXIT_CODE_CRASH,
26
+ EXIT_CODE_SUCCESS,
27
+ PERCENT_FULL,
28
+ READER_THREAD_JOIN_TIMEOUT_SECONDS,
29
+ SOURCE_APP_SERVER_RATE_LIMITS,
30
+ SOURCE_NO_USAGE_SURFACE,
31
+ SOURCE_TEXT_STATUS,
32
+ USAGE_REPORT_KEY_PERCENT_LEFT,
33
+ USAGE_REPORT_KEY_SOURCE,
34
+ USAGE_REPORT_KEY_WINDOW_RESET,
35
+ WEEKLY_USAGE_GATE_THRESHOLD_PERCENT,
36
+ WEEKLY_WINDOW_DURATION_MINUTES,
37
+ )
38
+
39
+ PROBE_PATH = SCRIPTS_DIRECTORY / "codex_usage_probe.py"
40
+
41
+ REAL_APP_SERVER_RATE_LIMITS_REPLY_CODEX_0_144_3 = json.dumps(
42
+ {
43
+ "id": 2,
44
+ "result": {
45
+ "rateLimits": {
46
+ "limitId": "codex",
47
+ "limitName": None,
48
+ "primary": {
49
+ "usedPercent": 95,
50
+ "windowDurationMins": WEEKLY_WINDOW_DURATION_MINUTES,
51
+ "resetsAt": 1784504948,
52
+ },
53
+ "secondary": None,
54
+ "credits": {
55
+ "hasCredits": False,
56
+ "unlimited": False,
57
+ "balance": None,
58
+ },
59
+ "individualLimit": None,
60
+ "planType": "team",
61
+ "rateLimitReachedType": None,
62
+ }
63
+ },
64
+ }
65
+ )
66
+
67
+ SESSION_WINDOW_DURATION_MINUTES = 300
68
+
69
+ DUAL_WINDOW_APP_SERVER_RATE_LIMITS_REPLY = json.dumps(
70
+ {
71
+ "id": 2,
72
+ "result": {
73
+ "rateLimits": {
74
+ "limitId": "codex",
75
+ "primary": {
76
+ "usedPercent": 40,
77
+ "windowDurationMins": SESSION_WINDOW_DURATION_MINUTES,
78
+ "resetsAt": 1783958400,
79
+ },
80
+ "secondary": {
81
+ "usedPercent": 20,
82
+ "windowDurationMins": WEEKLY_WINDOW_DURATION_MINUTES,
83
+ "resetsAt": 1784504948,
84
+ },
85
+ }
86
+ },
87
+ }
88
+ )
89
+
90
+ PRIMARY_ONLY_SESSION_WINDOW_REPLY = json.dumps(
91
+ {
92
+ "id": 2,
93
+ "result": {
94
+ "rateLimits": {
95
+ "limitId": "codex",
96
+ "primary": {
97
+ "usedPercent": 10,
98
+ "windowDurationMins": SESSION_WINDOW_DURATION_MINUTES,
99
+ "resetsAt": 1783958400,
100
+ },
101
+ "secondary": None,
102
+ }
103
+ },
104
+ }
105
+ )
106
+
107
+ EXPECTED_TEXT_STATUS_WINDOW_RESET = "2026-07-19T23:49:08+00:00"
108
+ EXPECTED_FIVE_HOUR_WINDOW_RESET = "2026-07-01T00:00:00+00:00"
109
+
110
+ NO_USAGE_SURFACE_LOGIN_STATUS_OUTPUT = "Logged in using ChatGPT\n"
111
+
112
+ TEXT_STATUS_WITH_FIVE_HOUR_AND_WEEKLY_RESETS = (
113
+ "Status\n"
114
+ f"5-hour limit: 60% left (resets {EXPECTED_FIVE_HOUR_WINDOW_RESET})\n"
115
+ f"Weekly limit: 42% left (resets {EXPECTED_TEXT_STATUS_WINDOW_RESET})\n"
116
+ )
117
+
118
+ PROCESS_TREE_WAIT_SECONDS = 5
119
+ READER_JOIN_TEARDOWN_WAIT_SECONDS = 0.2
120
+
121
+ NO_RATE_LIMITS_APP_SERVER_REPLY = json.dumps(
122
+ {
123
+ "id": 2,
124
+ "result": {"rateLimits": {}},
125
+ }
126
+ )
127
+
128
+ JSON_RPC_ERROR_APP_SERVER_REPLY = json.dumps(
129
+ {
130
+ "id": 2,
131
+ "error": {
132
+ "code": -32601,
133
+ "message": "Method not found",
134
+ },
135
+ }
136
+ )
137
+
138
+ TEXT_STATUS_WITH_WEEKLY_LEFT = (
139
+ "Status\n"
140
+ "5-hour limit: 60% left\n"
141
+ "Weekly limit: 42% left (resets 2026-07-19T23:49:08+00:00)\n"
142
+ )
143
+
144
+ TEXT_STATUS_WITH_RESETS_AT_PHRASING = (
145
+ "Status\n"
146
+ "Weekly limit: 42% left, resets at 2026-07-19T23:49:08+00:00\n"
147
+ )
148
+
149
+ TIMEOUT_SECONDS = 30
150
+ TIMEOUT_COMMAND = "codex"
151
+
152
+
153
+
154
+ def load_probe_module() -> ModuleType:
155
+ spec = importlib.util.spec_from_file_location("codex_usage_probe", PROBE_PATH)
156
+ assert spec is not None
157
+ assert spec.loader is not None
158
+ probe_module = importlib.util.module_from_spec(spec)
159
+ sys.modules[spec.name] = probe_module
160
+ spec.loader.exec_module(probe_module)
161
+ return probe_module
162
+
163
+
164
+ def _app_server_lines_from_rate_limits_payload(payload_line: str) -> list[str]:
165
+ return [
166
+ json.dumps(
167
+ {
168
+ "id": 1,
169
+ "result": {
170
+ "userAgent": "codex-usage-probe/0.144.3",
171
+ "platformOs": "windows",
172
+ },
173
+ }
174
+ ),
175
+ payload_line,
176
+ ]
177
+
178
+
179
+ def _assert_main_yields_null_skip_report(
180
+ probe: ModuleType,
181
+ capsys: pytest.CaptureFixture[str],
182
+ ) -> None:
183
+ exit_code = probe.main()
184
+ assert exit_code == EXIT_CODE_SUCCESS
185
+ captured = capsys.readouterr()
186
+ payload = json.loads(captured.out)
187
+ assert payload[USAGE_REPORT_KEY_PERCENT_LEFT] is None
188
+ assert payload[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
189
+ assert USAGE_REPORT_KEY_WINDOW_RESET in payload
190
+
191
+
192
+ def _assert_main_yields_cli_failure_not_usage_skip(
193
+ probe: ModuleType,
194
+ capsys: pytest.CaptureFixture[str],
195
+ ) -> None:
196
+ exit_code = probe.main()
197
+ assert exit_code == EXIT_CODE_CRASH
198
+ captured = capsys.readouterr()
199
+ payload = json.loads(captured.out)
200
+ assert payload[USAGE_REPORT_KEY_PERCENT_LEFT] is None
201
+ assert payload[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
202
+ assert USAGE_REPORT_KEY_WINDOW_RESET in payload
203
+
204
+
205
+ class TestParseRateLimitsMessage:
206
+ def should_compute_percent_left_from_weekly_primary_window(
207
+ self,
208
+ ) -> None:
209
+ probe = load_probe_module()
210
+ usage_report = probe.parse_rate_limits_message(
211
+ REAL_APP_SERVER_RATE_LIMITS_REPLY_CODEX_0_144_3
212
+ )
213
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 5
214
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] is not None
215
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_APP_SERVER_RATE_LIMITS
216
+
217
+ def should_prefer_secondary_weekly_window_over_primary_session(
218
+ self,
219
+ ) -> None:
220
+ probe = load_probe_module()
221
+ usage_report = probe.parse_rate_limits_message(
222
+ DUAL_WINDOW_APP_SERVER_RATE_LIMITS_REPLY
223
+ )
224
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 80
225
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] is not None
226
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_APP_SERVER_RATE_LIMITS
227
+
228
+ def should_return_null_when_only_non_weekly_session_window(self) -> None:
229
+ probe = load_probe_module()
230
+ usage_report = probe.parse_rate_limits_message(
231
+ PRIMARY_ONLY_SESSION_WINDOW_REPLY
232
+ )
233
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
234
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] is None
235
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
236
+
237
+ def should_return_null_percent_when_rate_limits_empty(self) -> None:
238
+ probe = load_probe_module()
239
+ usage_report = probe.parse_rate_limits_message(
240
+ NO_RATE_LIMITS_APP_SERVER_REPLY
241
+ )
242
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
243
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] is None
244
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
245
+
246
+ def should_return_null_percent_when_json_rpc_error_payload(self) -> None:
247
+ probe = load_probe_module()
248
+ usage_report = probe.parse_rate_limits_message(JSON_RPC_ERROR_APP_SERVER_REPLY)
249
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
250
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] is None
251
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
252
+
253
+
254
+ class TestParseTextStatus:
255
+ def should_parse_weekly_percent_left_from_status_text(self) -> None:
256
+ probe = load_probe_module()
257
+ usage_report = probe.parse_text_usage_status(TEXT_STATUS_WITH_WEEKLY_LEFT)
258
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 42.0
259
+ assert (
260
+ usage_report[USAGE_REPORT_KEY_WINDOW_RESET]
261
+ == EXPECTED_TEXT_STATUS_WINDOW_RESET
262
+ )
263
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_TEXT_STATUS
264
+
265
+ def should_parse_window_reset_from_resets_at_phrasing(self) -> None:
266
+ probe = load_probe_module()
267
+ usage_report = probe.parse_text_usage_status(
268
+ TEXT_STATUS_WITH_RESETS_AT_PHRASING
269
+ )
270
+ assert (
271
+ usage_report[USAGE_REPORT_KEY_WINDOW_RESET]
272
+ == EXPECTED_TEXT_STATUS_WINDOW_RESET
273
+ )
274
+
275
+ def should_prefer_weekly_reset_when_five_hour_reset_appears_first(self) -> None:
276
+ probe = load_probe_module()
277
+ usage_report = probe.parse_text_usage_status(
278
+ TEXT_STATUS_WITH_FIVE_HOUR_AND_WEEKLY_RESETS
279
+ )
280
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 42.0
281
+ assert (
282
+ usage_report[USAGE_REPORT_KEY_WINDOW_RESET]
283
+ == EXPECTED_TEXT_STATUS_WINDOW_RESET
284
+ )
285
+ assert usage_report[USAGE_REPORT_KEY_WINDOW_RESET] != (
286
+ EXPECTED_FIVE_HOUR_WINDOW_RESET
287
+ )
288
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_TEXT_STATUS
289
+
290
+ def should_yield_null_for_login_status_without_usage(self) -> None:
291
+ probe = load_probe_module()
292
+ usage_report = probe.parse_text_usage_status(
293
+ NO_USAGE_SURFACE_LOGIN_STATUS_OUTPUT
294
+ )
295
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
296
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
297
+
298
+
299
+ class TestProcessTreeTeardown:
300
+ def should_end_a_running_app_server_and_reap_it(self) -> None:
301
+ """A real sleeping child is gone once teardown returns, on any platform."""
302
+ probe = load_probe_module()
303
+ sleeping_process = subprocess.Popen(
304
+ [sys.executable, "-c", "import time; time.sleep(30)"],
305
+ stdout=subprocess.DEVNULL,
306
+ stderr=subprocess.DEVNULL,
307
+ start_new_session=probe.should_start_new_session(),
308
+ )
309
+ try:
310
+ probe._terminate_process_tree(sleeping_process)
311
+ assert sleeping_process.poll() is not None
312
+ finally:
313
+ if sleeping_process.poll() is None:
314
+ sleeping_process.kill()
315
+ sleeping_process.wait(timeout=PROCESS_TREE_WAIT_SECONDS)
316
+
317
+ def should_hand_the_whole_tree_to_the_shared_kill(
318
+ self,
319
+ monkeypatch: pytest.MonkeyPatch,
320
+ ) -> None:
321
+ """Teardown routes the server process through the shared tree kill.
322
+
323
+ ::
324
+
325
+ shared tree kill ok: the cmd.exe shim's app-server child dies too
326
+ Popen.kill() flag: the app-server grandchild holds stdout open
327
+ """
328
+ probe = load_probe_module()
329
+ all_killed_processes: list[object] = []
330
+ finished_process = subprocess.Popen(
331
+ [sys.executable, "-c", ""],
332
+ stdout=subprocess.DEVNULL,
333
+ stderr=subprocess.DEVNULL,
334
+ )
335
+ finished_process.wait(timeout=PROCESS_TREE_WAIT_SECONDS)
336
+ monkeypatch.setattr(
337
+ probe,
338
+ "terminate_process_tree",
339
+ lambda target_process: all_killed_processes.append(target_process),
340
+ )
341
+
342
+ probe._terminate_process_tree(finished_process)
343
+
344
+ assert all_killed_processes == [finished_process]
345
+
346
+ def should_return_when_a_killed_child_never_reaps(
347
+ self,
348
+ monkeypatch: pytest.MonkeyPatch,
349
+ ) -> None:
350
+ """A child that outlives its grace window ends teardown, never hangs it."""
351
+ probe = load_probe_module()
352
+
353
+ class _UnreapableProcess:
354
+ def wait(self, timeout: float | None = None) -> int:
355
+ raise subprocess.TimeoutExpired(cmd="codex", timeout=timeout or 0)
356
+
357
+ monkeypatch.setattr(probe, "terminate_process_tree", lambda _process: None)
358
+
359
+ probe._terminate_process_tree(_UnreapableProcess())
360
+
361
+
362
+ class TestReaderThreadLifecycle:
363
+ def should_join_stdout_reader_after_process_tree_teardown(self) -> None:
364
+ probe = load_probe_module()
365
+ is_exchange_over = threading.Event()
366
+ all_server_lines: list[str] = []
367
+
368
+ def collect_until_event(
369
+ _server_stdout: object,
370
+ collected_lines: list[str],
371
+ exchange_over: threading.Event,
372
+ ) -> None:
373
+ collected_lines.append("reader-started")
374
+ time.sleep(READER_JOIN_TEARDOWN_WAIT_SECONDS)
375
+ collected_lines.append("reader-finished")
376
+ exchange_over.set()
377
+
378
+ reader_thread = threading.Thread(
379
+ target=collect_until_event,
380
+ args=(None, all_server_lines, is_exchange_over),
381
+ daemon=True,
382
+ )
383
+ reader_thread.start()
384
+ finished_process = subprocess.Popen(
385
+ [sys.executable, "-c", "pass"],
386
+ stdout=subprocess.DEVNULL,
387
+ stderr=subprocess.DEVNULL,
388
+ )
389
+ finished_process.wait(timeout=PROCESS_TREE_WAIT_SECONDS)
390
+ probe._teardown_app_server_exchange(
391
+ server_process=finished_process,
392
+ reader_thread=reader_thread,
393
+ )
394
+ assert reader_thread.is_alive() is False
395
+ assert all_server_lines == ["reader-started", "reader-finished"]
396
+ assert READER_THREAD_JOIN_TIMEOUT_SECONDS >= 1
397
+
398
+
399
+ class TestDefaultExchangeWiring:
400
+ def should_wire_subprocess_exchange_from_main(
401
+ self,
402
+ monkeypatch: pytest.MonkeyPatch,
403
+ capsys: pytest.CaptureFixture[str],
404
+ ) -> None:
405
+ probe = load_probe_module()
406
+ all_server_lines = _app_server_lines_from_rate_limits_payload(
407
+ REAL_APP_SERVER_RATE_LIMITS_REPLY_CODEX_0_144_3
408
+ )
409
+ all_call_counts = {"exchange": 0}
410
+
411
+ def fake_exchange(all_request_messages: list[dict[str, object]]) -> list[str]:
412
+ all_call_counts["exchange"] += 1
413
+ assert len(all_request_messages) >= 2
414
+ return all_server_lines
415
+
416
+ monkeypatch.setattr(
417
+ probe,
418
+ "_exchange_app_server_messages_via_subprocess",
419
+ fake_exchange,
420
+ )
421
+ exit_code = probe.main()
422
+ captured = capsys.readouterr()
423
+ usage_report = json.loads(captured.out)
424
+ assert exit_code == EXIT_CODE_SUCCESS
425
+ assert all_call_counts["exchange"] == 1
426
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 5
427
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_APP_SERVER_RATE_LIMITS
428
+
429
+
430
+ class TestProbeWeeklyUsage:
431
+ def should_probe_through_swappable_app_server_exchange(self) -> None:
432
+ probe = load_probe_module()
433
+ all_server_lines = _app_server_lines_from_rate_limits_payload(
434
+ REAL_APP_SERVER_RATE_LIMITS_REPLY_CODEX_0_144_3
435
+ )
436
+
437
+ def fake_exchange(all_request_messages: list[dict[str, object]]) -> list[str]:
438
+ assert len(all_request_messages) >= 2
439
+ return all_server_lines
440
+
441
+ usage_report = probe.probe_weekly_usage(
442
+ exchange_app_server_messages=fake_exchange
443
+ )
444
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 5
445
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_APP_SERVER_RATE_LIMITS
446
+
447
+ def should_yield_null_when_exchange_returns_no_usage_payload(self) -> None:
448
+ probe = load_probe_module()
449
+
450
+ def empty_exchange(
451
+ all_request_messages: list[dict[str, object]],
452
+ ) -> list[str]:
453
+ del all_request_messages
454
+ return [
455
+ json.dumps({"id": 1, "result": {}}),
456
+ NO_RATE_LIMITS_APP_SERVER_REPLY,
457
+ ]
458
+
459
+ usage_report = probe.probe_weekly_usage(
460
+ exchange_app_server_messages=empty_exchange
461
+ )
462
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
463
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
464
+
465
+ def should_yield_null_when_exchange_returns_json_rpc_error(self) -> None:
466
+ probe = load_probe_module()
467
+
468
+ def error_exchange(
469
+ all_request_messages: list[dict[str, object]],
470
+ ) -> list[str]:
471
+ del all_request_messages
472
+ return _app_server_lines_from_rate_limits_payload(
473
+ JSON_RPC_ERROR_APP_SERVER_REPLY
474
+ )
475
+
476
+ usage_report = probe.probe_weekly_usage(
477
+ exchange_app_server_messages=error_exchange
478
+ )
479
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] is None
480
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_NO_USAGE_SURFACE
481
+
482
+
483
+ class TestProbeWeeklyUsageViaSubprocess:
484
+ def should_report_usage_from_the_real_subprocess_exchange(
485
+ self,
486
+ monkeypatch: pytest.MonkeyPatch,
487
+ ) -> None:
488
+ probe = load_probe_module()
489
+ all_server_lines = _app_server_lines_from_rate_limits_payload(
490
+ REAL_APP_SERVER_RATE_LIMITS_REPLY_CODEX_0_144_3
491
+ )
492
+
493
+ def fake_subprocess_exchange(
494
+ all_request_messages: list[dict[str, object]],
495
+ ) -> list[str]:
496
+ assert len(all_request_messages) >= 2
497
+ return all_server_lines
498
+
499
+ monkeypatch.setattr(
500
+ probe,
501
+ "_exchange_app_server_messages_via_subprocess",
502
+ fake_subprocess_exchange,
503
+ )
504
+
505
+ usage_report = probe.probe_weekly_usage_via_subprocess()
506
+
507
+ assert usage_report[USAGE_REPORT_KEY_PERCENT_LEFT] == 5
508
+ assert usage_report[USAGE_REPORT_KEY_SOURCE] == SOURCE_APP_SERVER_RATE_LIMITS
509
+
510
+
511
+ class TestGateThresholdHelper:
512
+ def should_export_threshold_constant_of_ten(self) -> None:
513
+ assert WEEKLY_USAGE_GATE_THRESHOLD_PERCENT == 10
514
+
515
+ def should_skip_review_when_percent_is_null(self) -> None:
516
+ probe = load_probe_module()
517
+ assert probe.is_codex_review_required(None) is False
518
+
519
+ def should_skip_review_when_percent_at_or_below_threshold(self) -> None:
520
+ probe = load_probe_module()
521
+ assert (
522
+ probe.is_codex_review_required(float(WEEKLY_USAGE_GATE_THRESHOLD_PERCENT))
523
+ is False
524
+ )
525
+ assert probe.is_codex_review_required(5.0) is False
526
+
527
+ def should_require_review_when_percent_above_threshold(self) -> None:
528
+ probe = load_probe_module()
529
+ assert probe.is_codex_review_required(10.1) is True
530
+ assert probe.is_codex_review_required(float(PERCENT_FULL)) is True
531
+
532
+
533
+ class TestMainExitCodes:
534
+ def should_exit_zero_with_json_even_when_usage_is_null(
535
+ self,
536
+ capsys: pytest.CaptureFixture[str],
537
+ monkeypatch: pytest.MonkeyPatch,
538
+ ) -> None:
539
+ probe = load_probe_module()
540
+
541
+ def empty_exchange(
542
+ all_request_messages: list[dict[str, object]],
543
+ ) -> list[str]:
544
+ del all_request_messages
545
+ return [NO_RATE_LIMITS_APP_SERVER_REPLY]
546
+
547
+ monkeypatch.setattr(
548
+ probe,
549
+ "_exchange_app_server_messages_via_subprocess",
550
+ empty_exchange,
551
+ )
552
+ _assert_main_yields_null_skip_report(probe, capsys)
553
+
554
+ def should_exit_nonzero_when_binary_missing(
555
+ self,
556
+ capsys: pytest.CaptureFixture[str],
557
+ monkeypatch: pytest.MonkeyPatch,
558
+ ) -> None:
559
+ probe = load_probe_module()
560
+
561
+ def missing_binary_exchange(
562
+ all_request_messages: list[dict[str, object]],
563
+ ) -> list[str]:
564
+ del all_request_messages
565
+ raise FileNotFoundError("codex binary not found on PATH")
566
+
567
+ monkeypatch.setattr(
568
+ probe,
569
+ "_exchange_app_server_messages_via_subprocess",
570
+ missing_binary_exchange,
571
+ )
572
+ _assert_main_yields_cli_failure_not_usage_skip(probe, capsys)
573
+
574
+ def should_exit_nonzero_when_subprocess_times_out(
575
+ self,
576
+ capsys: pytest.CaptureFixture[str],
577
+ monkeypatch: pytest.MonkeyPatch,
578
+ ) -> None:
579
+ probe = load_probe_module()
580
+
581
+ def timeout_exchange(
582
+ all_request_messages: list[dict[str, object]],
583
+ ) -> list[str]:
584
+ del all_request_messages
585
+ raise subprocess.TimeoutExpired(
586
+ cmd=TIMEOUT_COMMAND,
587
+ timeout=TIMEOUT_SECONDS,
588
+ )
589
+
590
+ monkeypatch.setattr(
591
+ probe,
592
+ "_exchange_app_server_messages_via_subprocess",
593
+ timeout_exchange,
594
+ )
595
+ _assert_main_yields_cli_failure_not_usage_skip(probe, capsys)
596
+
597
+ def should_exit_nonzero_when_os_error(
598
+ self,
599
+ capsys: pytest.CaptureFixture[str],
600
+ monkeypatch: pytest.MonkeyPatch,
601
+ ) -> None:
602
+ probe = load_probe_module()
603
+
604
+ def os_error_exchange(
605
+ all_request_messages: list[dict[str, object]],
606
+ ) -> list[str]:
607
+ del all_request_messages
608
+ raise OSError("permission denied launching codex")
609
+
610
+ monkeypatch.setattr(
611
+ probe,
612
+ "_exchange_app_server_messages_via_subprocess",
613
+ os_error_exchange,
614
+ )
615
+ _assert_main_yields_cli_failure_not_usage_skip(probe, capsys)
616
+
617
+ def should_exit_nonzero_when_subprocess_error(
618
+ self,
619
+ capsys: pytest.CaptureFixture[str],
620
+ monkeypatch: pytest.MonkeyPatch,
621
+ ) -> None:
622
+ probe = load_probe_module()
623
+
624
+ def subprocess_error_exchange(
625
+ all_request_messages: list[dict[str, object]],
626
+ ) -> list[str]:
627
+ del all_request_messages
628
+ raise subprocess.SubprocessError("codex app-server failed")
629
+
630
+ monkeypatch.setattr(
631
+ probe,
632
+ "_exchange_app_server_messages_via_subprocess",
633
+ subprocess_error_exchange,
634
+ )
635
+ _assert_main_yields_cli_failure_not_usage_skip(probe, capsys)
636
+
637
+ def should_exit_zero_with_null_report_when_json_rpc_error_payload(
638
+ self,
639
+ capsys: pytest.CaptureFixture[str],
640
+ monkeypatch: pytest.MonkeyPatch,
641
+ ) -> None:
642
+ probe = load_probe_module()
643
+
644
+ def error_payload_exchange(
645
+ all_request_messages: list[dict[str, object]],
646
+ ) -> list[str]:
647
+ del all_request_messages
648
+ return _app_server_lines_from_rate_limits_payload(
649
+ JSON_RPC_ERROR_APP_SERVER_REPLY
650
+ )
651
+
652
+ monkeypatch.setattr(
653
+ probe,
654
+ "_exchange_app_server_messages_via_subprocess",
655
+ error_payload_exchange,
656
+ )
657
+ _assert_main_yields_null_skip_report(probe, capsys)
658
+
659
+ def should_exit_nonzero_when_unicode_decode_error(
660
+ self,
661
+ capsys: pytest.CaptureFixture[str],
662
+ monkeypatch: pytest.MonkeyPatch,
663
+ ) -> None:
664
+ probe = load_probe_module()
665
+
666
+ def unicode_decode_error_exchange(
667
+ all_request_messages: list[dict[str, object]],
668
+ ) -> list[str]:
669
+ del all_request_messages
670
+ raise UnicodeDecodeError(
671
+ "utf-8",
672
+ b"\xff",
673
+ 0,
674
+ 1,
675
+ "invalid start byte",
676
+ )
677
+
678
+ monkeypatch.setattr(
679
+ probe,
680
+ "_exchange_app_server_messages_via_subprocess",
681
+ unicode_decode_error_exchange,
682
+ )
683
+ _assert_main_yields_cli_failure_not_usage_skip(probe, capsys)