claude-dev-env 2.16.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (535) 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/pr-cleanup/SKILL.md +99 -0
  28. package/.agents/skills/prototype/reference/honest-limitations.md +1 -1
  29. package/.agents/skills/prototype/reference/promotion-tasks.md +1 -1
  30. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +2 -2
  31. package/.agents/skills/prototype/workflows/promotion.md +2 -2
  32. package/.agents/skills/review-router/SKILL.md +51 -0
  33. package/.agents/skills/review-router/reference/route-policy.json +7 -0
  34. package/.agents/skills/review-router/reference/task-seeds.md +1 -0
  35. package/.agents/skills/review-router/scripts/conftest.py +4 -0
  36. package/.agents/skills/review-router/scripts/review_router.py +50 -0
  37. package/.agents/skills/review-router/scripts/review_router_cli.py +211 -0
  38. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +1 -0
  39. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  40. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +13 -0
  41. package/.agents/skills/review-router/scripts/test_review_router.py +23 -0
  42. package/.agents/skills/review-router/scripts/test_review_router_cli.py +47 -0
  43. package/.agents/skills/review-tier/SKILL.md +56 -0
  44. package/.agents/skills/review-tier/reference/task-seeds.md +1 -0
  45. package/.agents/skills/review-tier/reference/tier-policy.json +9 -0
  46. package/.agents/skills/review-tier/scripts/conftest.py +4 -0
  47. package/.agents/skills/review-tier/scripts/review_tier.py +332 -0
  48. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +1 -0
  49. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  50. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +29 -0
  51. package/.agents/skills/review-tier/scripts/test_generation.py +171 -0
  52. package/.agents/skills/review-tier/scripts/test_review_tier.py +33 -0
  53. package/.agents/skills/session-log/SKILL.md +1 -1
  54. package/.agents/skills/shared-extraction-audit/SKILL.md +160 -0
  55. package/.agents/skills/shared-extraction-audit/reference/examples.md +46 -0
  56. package/.agents/skills/shared-extraction-audit/reference/offense-taxonomy.md +100 -0
  57. package/.agents/skills/source-command-logifix/SKILL.md +29 -0
  58. package/.agents/skills/source-command-sr-loop/SKILL.md +58 -0
  59. package/.agents/skills-archived/AGENTS.md +45 -0
  60. package/.agents/{skills → skills-archived}/anthropic-plan/AGENTS.md +1 -1
  61. package/.agents/{skills → skills-archived}/bugteam/scripts/reflow_skill_md.py +3 -3
  62. package/.agents/{skills → skills-archived}/codex-review/test_skill_scaffold.py +1 -1
  63. package/.agents/{skills → skills-archived}/copilot-finding-triage/SKILL.md +1 -1
  64. package/.agents/{skills → skills-archived}/pr-converge/SKILL.md +6 -6
  65. package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/AGENTS.md +1 -1
  66. package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/constants.py +1 -1
  67. package/.agents/{skills → skills-archived}/pr-converge/reference/multi-pr-orchestration.md +1 -1
  68. package/.agents/{skills → skills-archived}/pr-converge/reference/per-tick.md +3 -3
  69. package/.agents/{skills → skills-archived}/pr-converge/scripts/reflow_skill_md.py +2 -2
  70. package/.agents/{skills → skills-archived}/pr-converge/test_portable_pacer_gate.py +6 -2
  71. package/.agents/{skills → skills-archived}/pr-converge/workflows/schedule-wakeup-loop.md +1 -1
  72. package/.agents/{skills → skills-archived}/split-pr/reference/proposal-format.md +1 -1
  73. package/AGENTS.md +34 -58
  74. package/_shared/AGENTS.md +2 -0
  75. package/_shared/advisor/reference/sol-rung.md +2 -2
  76. package/_shared/advisor/reference/third-party-bind.md +1 -1
  77. package/_shared/pr-loop/audit-reply-template.md +4 -0
  78. package/_shared/pr-loop/fix-protocol.md +7 -6
  79. package/_shared/pr-loop/gh-payloads.md +8 -6
  80. package/_shared/pr-loop/precatch-rubric.md +6 -5
  81. package/_shared/pr-loop/scripts/AGENTS.md +15 -0
  82. package/_shared/pr-loop/scripts/_pr_converge_path_setup.py +38 -0
  83. package/_shared/pr-loop/scripts/check_bugbot_ci.py +279 -0
  84. package/_shared/pr-loop/scripts/check_convergence.py +923 -0
  85. package/_shared/pr-loop/scripts/check_convergence_availability.py +275 -0
  86. package/_shared/pr-loop/scripts/check_convergence_gates.py +279 -0
  87. package/_shared/pr-loop/scripts/check_convergence_thread_gates.py +219 -0
  88. package/_shared/pr-loop/scripts/check_pending_reviews.py +154 -0
  89. package/_shared/pr-loop/scripts/codex_down_classifier.py +98 -0
  90. package/_shared/pr-loop/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +1 -0
  91. package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
  92. package/_shared/pr-loop/scripts/codex_review_scripts_constants/__init__.py +1 -0
  93. package/_shared/pr-loop/scripts/codex_review_scripts_constants/classifier_constants.py +35 -0
  94. package/_shared/pr-loop/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +82 -0
  95. package/_shared/pr-loop/scripts/codex_review_scripts_constants/findings_constants.py +18 -0
  96. package/_shared/pr-loop/scripts/codex_review_scripts_constants/run_constants.py +53 -0
  97. package/_shared/pr-loop/scripts/codex_usage_probe.py +570 -0
  98. package/_shared/pr-loop/scripts/conftest.py +43 -0
  99. package/_shared/pr-loop/scripts/fetch_copilot_reviews.py +134 -0
  100. package/_shared/pr-loop/scripts/fixtures/auth_failure_synthetic.txt +1 -0
  101. package/_shared/pr-loop/scripts/fixtures/config_load_failure_v0.125.0.txt +1 -0
  102. package/_shared/pr-loop/scripts/fixtures/freeform_findings_v0.144.3.txt +6 -0
  103. package/_shared/pr-loop/scripts/fixtures/model_rejection_v0.125.0.jsonl +5 -0
  104. package/_shared/pr-loop/scripts/fixtures/structured_findings.txt +13 -0
  105. package/_shared/pr-loop/scripts/fixtures/success_stream_v0.144.3.jsonl +6 -0
  106. package/_shared/pr-loop/scripts/fixtures/unknown_failure_synthetic.txt +1 -0
  107. package/_shared/pr-loop/scripts/fixtures/usage_limit_synthetic.txt +1 -0
  108. package/_shared/pr-loop/scripts/parse_codex_findings.py +207 -0
  109. package/_shared/pr-loop/scripts/post_fix_reply.py +168 -0
  110. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +1 -0
  111. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
  112. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  113. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +70 -0
  114. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/pr_converge_constants.py +118 -0
  115. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +13 -0
  116. package/_shared/pr-loop/scripts/pr_converge_skill_constants/.claude/CLAUDE.md +1 -0
  117. package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +26 -0
  118. package/_shared/pr-loop/scripts/pr_converge_skill_constants/__init__.py +0 -0
  119. package/_shared/pr-loop/scripts/pr_converge_skill_constants/constants.py +69 -0
  120. package/_shared/pr-loop/scripts/run_codex_review.py +609 -0
  121. package/_shared/pr-loop/scripts/test__pr_converge_path_setup.py +30 -0
  122. package/_shared/pr-loop/scripts/test_check_bugbot_ci.py +312 -0
  123. package/_shared/pr-loop/scripts/test_check_convergence.py +438 -0
  124. package/_shared/pr-loop/scripts/test_check_convergence_availability.py +391 -0
  125. package/_shared/pr-loop/scripts/test_check_convergence_codex.py +517 -0
  126. package/_shared/pr-loop/scripts/test_check_convergence_contract.py +400 -0
  127. package/_shared/pr-loop/scripts/test_check_convergence_fixture.py +179 -0
  128. package/_shared/pr-loop/scripts/test_check_convergence_gates.py +84 -0
  129. package/_shared/pr-loop/scripts/test_check_convergence_thread_gates.py +99 -0
  130. package/_shared/pr-loop/scripts/test_codex_down_classifier.py +143 -0
  131. package/_shared/pr-loop/scripts/test_codex_usage_probe.py +683 -0
  132. package/_shared/pr-loop/scripts/test_parse_codex_findings.py +130 -0
  133. package/_shared/pr-loop/scripts/test_run_codex_review.py +969 -0
  134. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +1 -1
  135. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +1 -1
  136. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +1 -1
  137. package/_shared/pr-loop/state-schema.md +20 -28
  138. package/_shared/process-tree/AGENTS.md +3 -3
  139. package/bin/ever-shipped-skills.mjs +29 -1
  140. package/bin/install-constants.mjs +15 -6
  141. package/bin/install.agents-home.test.mjs +13 -0
  142. package/bin/install.cursor-rules.test.mjs +3 -3
  143. package/bin/install.mjs +80 -20
  144. package/bin/install.profile-root.test.mjs +1 -1
  145. package/bin/install.prune.test.mjs +23 -204
  146. package/bin/install.test.mjs +8 -5
  147. package/bin/resolve-install-root.mjs +21 -0
  148. package/bin/resolve-package-managed-directory.mjs +4 -4
  149. package/commands/AGENTS.md +2 -0
  150. package/commands/sr-loop.md +3 -0
  151. package/docs/references/prose-style-enforcement.md +3 -7
  152. package/hooks/AGENTS.md +0 -3
  153. package/hooks/blocking/AGENTS.md +0 -2
  154. package/hooks/blocking/ask_user_question_shape_blocker.py +83 -0
  155. package/hooks/blocking/pre_tool_use_dispatcher.py +2 -19
  156. package/hooks/blocking/state_description_blocker.py +1 -1
  157. package/hooks/blocking/test_ask_user_question_shape.py +69 -0
  158. package/hooks/blocking/test_pre_tool_use_dispatcher.py +17 -58
  159. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +9 -104
  160. package/hooks/blocking/test_state_description_blocker.py +1 -0
  161. package/hooks/blocking/test_stop_dispatcher.py +1 -26
  162. package/hooks/hooks.json +1 -1
  163. package/hooks/hooks_constants/AGENTS.md +0 -3
  164. package/hooks/hooks_constants/ask_user_question_shape.py +1 -1
  165. package/hooks/hooks_constants/ask_user_question_shape_constants.py +73 -0
  166. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +1 -2
  167. package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -1
  168. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -7
  169. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
  170. package/hooks/hooks_constants/test_ask_user_question_shape.py +1 -1
  171. package/hooks/hooks_constants/test_prose_metrics_parity.py +29 -107
  172. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
  173. package/hooks/hooks_constants/working_style_prompt_constants.py +9 -10
  174. package/hooks/session/AGENTS.md +4 -1
  175. package/hooks/session/test_working_style_prompt.py +8 -4
  176. package/hooks/session/working_style_prompt.py +4 -2
  177. package/package.json +1 -4
  178. package/rules/AGENTS.md +2 -5
  179. package/rules/asd-ste100-language.md +39 -0
  180. package/rules/ask-user-question-required.md +1 -1
  181. package/rules/long-horizon-autonomy.md +1 -1
  182. package/scripts/AGENTS.md +1 -0
  183. package/scripts/Show-Asset.ps1 +106 -0
  184. package/scripts/test_validate_instruction_pairs.py +30 -3
  185. package/scripts/tests/test_engine.py +4 -4
  186. package/scripts/tests/test_rules.py +5 -5
  187. package/system-prompts/AGENTS.md +8 -0
  188. package/system-prompts/software-engineer.xml +8 -3
  189. package/.agents/skills/grokify/evals/README.md +0 -72
  190. package/.agents/skills/grokify/evals/parse-payload.test.mjs +0 -171
  191. package/.agents/skills/grokify/evals/run-capability-evals.mjs +0 -545
  192. package/_shared/pr-loop/scripts/README.md +0 -21
  193. package/docs/imagegen.md +0 -22
  194. package/hooks/blocking/eli11_reply_enforcer.py +0 -436
  195. package/hooks/blocking/plain_language_blocker.py +0 -758
  196. package/hooks/blocking/test_eli11_reply_enforcer.py +0 -390
  197. package/hooks/blocking/test_plain_language_blocker.py +0 -683
  198. package/hooks/blocking/test_plain_language_blocker_allowlist.py +0 -228
  199. package/hooks/diagnostic/AGENTS.md +0 -75
  200. package/hooks/diagnostic/CLAUDE.md +0 -1
  201. package/hooks/diagnostic/hook_log_extractor.py +0 -875
  202. package/hooks/diagnostic/hook_log_init.py +0 -202
  203. package/hooks/diagnostic/hook_log_stop_wrapper.py +0 -26
  204. package/hooks/diagnostic/migrations/2026-04-25-drop-themes-hook-events.sql +0 -3
  205. package/hooks/diagnostic/migrations/AGENTS.md +0 -16
  206. package/hooks/diagnostic/migrations/CLAUDE.md +0 -1
  207. package/hooks/diagnostic/migrations/README.md +0 -76
  208. package/hooks/diagnostic/queries/AGENTS.md +0 -19
  209. package/hooks/diagnostic/queries/CLAUDE.md +0 -1
  210. package/hooks/diagnostic/queries/block_details_for_hook.sql +0 -26
  211. package/hooks/diagnostic/queries/blocks_by_category.sql +0 -10
  212. package/hooks/diagnostic/queries/blocks_by_tool.sql +0 -9
  213. package/hooks/diagnostic/queries/blocks_last_7_days.sql +0 -11
  214. package/hooks/diagnostic/queries/top_blockers_last_24_hours.sql +0 -12
  215. package/hooks/diagnostic/queries/top_blockers_overall.sql +0 -12
  216. package/hooks/diagnostic/requirements-hook-logs-dev.txt +0 -2
  217. package/hooks/diagnostic/requirements-hook-logs.txt +0 -1
  218. package/hooks/diagnostic/schema.sql +0 -51
  219. package/hooks/diagnostic/test_hook_log_extractor.py +0 -1518
  220. package/hooks/diagnostic/test_hook_log_init.py +0 -227
  221. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +0 -17
  222. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +0 -94
  223. package/hooks/hooks_constants/hook_log_extractor_constants.py +0 -233
  224. package/hooks/hooks_constants/plain_language_blocker_constants.py +0 -366
  225. package/hooks/hooks_constants/test_hook_log_extractor_constants.py +0 -123
  226. package/rules/doc-prose-cuts.md +0 -58
  227. package/rules/eli11-replies.md +0 -36
  228. package/rules/opus5-communication-contract.md +0 -45
  229. package/rules/plain-language.md +0 -9
  230. /package/.agents/{skills → skills-archived}/anthropic-plan/.claude/CLAUDE.md +0 -0
  231. /package/.agents/{skills → skills-archived}/anthropic-plan/SKILL.md +0 -0
  232. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/.claude/CLAUDE.md +0 -0
  233. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/AGENTS.md +0 -0
  234. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/.claude/CLAUDE.md +0 -0
  235. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -0
  236. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/__init__.py +0 -0
  237. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/anthropic_plan_scripts_constants/validate_packet_constants.py +0 -0
  238. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/test_validate_packet.py +0 -0
  239. /package/.agents/{skills → skills-archived}/anthropic-plan/scripts/validate_packet.py +0 -0
  240. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/.claude/CLAUDE.md +0 -0
  241. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/AGENTS.md +0 -0
  242. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/README.md +0 -0
  243. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/build-prompt.md +0 -0
  244. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/reuse-audit.md +0 -0
  245. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/source-map.md +0 -0
  246. /package/.agents/{skills → skills-archived}/anthropic-plan/templates/visual-plan.template.html +0 -0
  247. /package/.agents/{skills → skills-archived}/anthropic-plan/test_skill_contract.py +0 -0
  248. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/.claude/CLAUDE.md +0 -0
  249. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/AGENTS.md +0 -0
  250. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/plan-packet.contract.test.mjs +0 -0
  251. /package/.agents/{skills → skills-archived}/anthropic-plan/workflow/plan-packet.mjs +0 -0
  252. /package/.agents/{skills → skills-archived}/auditing-claude-config/.claude/CLAUDE.md +0 -0
  253. /package/.agents/{skills → skills-archived}/auditing-claude-config/AGENTS.md +0 -0
  254. /package/.agents/{skills → skills-archived}/auditing-claude-config/SKILL.md +0 -0
  255. /package/.agents/{skills → skills-archived}/auditing-claude-config/reference/probe-hook.md +0 -0
  256. /package/.agents/{skills → skills-archived}/beat-sheet/SKILL.md +0 -0
  257. /package/.agents/{skills → skills-archived}/beat-sheet/reference/visual-beats.md +0 -0
  258. /package/.agents/{skills → skills-archived}/bugteam/.claude/CLAUDE.md +0 -0
  259. /package/.agents/{skills → skills-archived}/bugteam/AGENTS.md +0 -0
  260. /package/.agents/{skills → skills-archived}/bugteam/CONSTRAINTS.md +0 -0
  261. /package/.agents/{skills → skills-archived}/bugteam/EXAMPLES.md +0 -0
  262. /package/.agents/{skills → skills-archived}/bugteam/PROMPTS.md +0 -0
  263. /package/.agents/{skills → skills-archived}/bugteam/SKILL.md +0 -0
  264. /package/.agents/{skills → skills-archived}/bugteam/reference/.claude/CLAUDE.md +0 -0
  265. /package/.agents/{skills → skills-archived}/bugteam/reference/AGENTS.md +0 -0
  266. /package/.agents/{skills → skills-archived}/bugteam/reference/README.md +0 -0
  267. /package/.agents/{skills → skills-archived}/bugteam/reference/audit-and-teammates.md +0 -0
  268. /package/.agents/{skills → skills-archived}/bugteam/reference/copilot-gap-analysis.md +0 -0
  269. /package/.agents/{skills → skills-archived}/bugteam/reference/design-rationale.md +0 -0
  270. /package/.agents/{skills → skills-archived}/bugteam/reference/github-pr-reviews.md +0 -0
  271. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/.claude/CLAUDE.md +0 -0
  272. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/AGENTS.md +0 -0
  273. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-assign-ids.md +0 -0
  274. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-capture-excerpts.md +0 -0
  275. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-walk-categories.md +0 -0
  276. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/audit-write-xml.md +0 -0
  277. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-append-summary.md +0 -0
  278. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-apply-fixes.md +0 -0
  279. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-git-add-commit.md +0 -0
  280. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-git-push.md +0 -0
  281. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-post-reply.md +0 -0
  282. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-publish-summary.md +0 -0
  283. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-py-compile.md +0 -0
  284. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-read-files.md +0 -0
  285. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-resolve-thread.md +0 -0
  286. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-test-suite.md +0 -0
  287. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-violation-count.md +0 -0
  288. /package/.agents/{skills → skills-archived}/bugteam/reference/obstacles/fix-write-xml.md +0 -0
  289. /package/.agents/{skills → skills-archived}/bugteam/reference/team-setup.md +0 -0
  290. /package/.agents/{skills → skills-archived}/bugteam/scripts/.claude/CLAUDE.md +0 -0
  291. /package/.agents/{skills → skills-archived}/bugteam/scripts/AGENTS.md +0 -0
  292. /package/.agents/{skills → skills-archived}/bugteam/scripts/README.md +0 -0
  293. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_code_rules_gate.py +0 -0
  294. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_fix_hookspath.py +0 -0
  295. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_preflight.py +0 -0
  296. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/.claude/CLAUDE.md +0 -0
  297. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -0
  298. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/__init__.py +0 -0
  299. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/probe_code_rules_enforcer_check_constants.py +0 -0
  300. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/reflow_skill_md_constants.py +0 -0
  301. /package/.agents/{skills → skills-archived}/bugteam/scripts/bugteam_scripts_constants/windows_safe_rmtree_constants.py +0 -0
  302. /package/.agents/{skills → skills-archived}/bugteam/scripts/probe_code_rules_enforcer_check.py +0 -0
  303. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_code_rules_gate.py +0 -0
  304. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -0
  305. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_bugteam_preflight.py +0 -0
  306. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_probe_code_rules_enforcer_check.py +0 -0
  307. /package/.agents/{skills → skills-archived}/bugteam/scripts/test_windows_safe_rmtree.py +0 -0
  308. /package/.agents/{skills → skills-archived}/bugteam/scripts/windows_safe_rmtree.py +0 -0
  309. /package/.agents/{skills → skills-archived}/bugteam/sources.md +0 -0
  310. /package/.agents/{skills → skills-archived}/bugteam/test_skill_additions.py +0 -0
  311. /package/.agents/{skills → skills-archived}/closeout/SKILL.md +0 -0
  312. /package/.agents/{skills → skills-archived}/closeout/reference/handoff-prompt-template.md +0 -0
  313. /package/.agents/{skills → skills-archived}/closeout/reference/pii-redaction-checklist.md +0 -0
  314. /package/.agents/{skills → skills-archived}/codex-review/.claude/CLAUDE.md +0 -0
  315. /package/.agents/{skills → skills-archived}/codex-review/AGENTS.md +0 -0
  316. /package/.agents/{skills → skills-archived}/codex-review/SKILL.md +0 -0
  317. /package/.agents/{skills → skills-archived}/codex-review/reference/.claude/CLAUDE.md +0 -0
  318. /package/.agents/{skills → skills-archived}/codex-review/reference/AGENTS.md +0 -0
  319. /package/.agents/{skills → skills-archived}/codex-review/reference/cli-contract.md +0 -0
  320. /package/.agents/{skills → skills-archived}/codex-review/reference/loop-integration.md +0 -0
  321. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_down_classifier.py +0 -0
  322. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/.claude/CLAUDE.md +0 -0
  323. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -0
  324. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/__init__.py +0 -0
  325. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/classifier_constants.py +0 -0
  326. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/codex_usage_probe_constants.py +0 -0
  327. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/findings_constants.py +0 -0
  328. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_review_scripts_constants/run_constants.py +0 -0
  329. /package/.agents/{skills → skills-archived}/codex-review/scripts/codex_usage_probe.py +0 -0
  330. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/auth_failure_synthetic.txt +0 -0
  331. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/config_load_failure_v0.125.0.txt +0 -0
  332. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/freeform_findings_v0.144.3.txt +0 -0
  333. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/model_rejection_v0.125.0.jsonl +0 -0
  334. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/structured_findings.txt +0 -0
  335. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/success_stream_v0.144.3.jsonl +0 -0
  336. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/unknown_failure_synthetic.txt +0 -0
  337. /package/.agents/{skills → skills-archived}/codex-review/scripts/fixtures/usage_limit_synthetic.txt +0 -0
  338. /package/.agents/{skills → skills-archived}/codex-review/scripts/parse_codex_findings.py +0 -0
  339. /package/.agents/{skills → skills-archived}/codex-review/scripts/run_codex_review.py +0 -0
  340. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_codex_down_classifier.py +0 -0
  341. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_codex_usage_probe.py +0 -0
  342. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_parse_codex_findings.py +0 -0
  343. /package/.agents/{skills → skills-archived}/codex-review/scripts/test_run_codex_review.py +0 -0
  344. /package/.agents/{skills → skills-archived}/comments/SKILL.md +0 -0
  345. /package/.agents/{skills → skills-archived}/condensing-instructions/SKILL.md +0 -0
  346. /package/.agents/{skills → skills-archived}/copilot-finding-triage/reference/tier-rubric.md +0 -0
  347. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/conftest.py +0 -0
  348. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/__init__.py +0 -0
  349. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/__init__.py +0 -0
  350. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +0 -0
  351. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/notify_ntfy.py +0 -0
  352. /package/.agents/{skills → skills-archived}/copilot-finding-triage/scripts/test_notify_ntfy.py +0 -0
  353. /package/.agents/{skills → skills-archived}/copilot-finding-triage/templates/notification.md +0 -0
  354. /package/.agents/{skills → skills-archived}/copilot-review/.claude/CLAUDE.md +0 -0
  355. /package/.agents/{skills → skills-archived}/copilot-review/AGENTS.md +0 -0
  356. /package/.agents/{skills → skills-archived}/copilot-review/SKILL.md +0 -0
  357. /package/.agents/{skills → skills-archived}/copilot-review/templates/subagent-prompt.md +0 -0
  358. /package/.agents/{skills → skills-archived}/descriptions/SKILL.md +0 -0
  359. /package/.agents/{skills → skills-archived}/emergencies/SKILL.md +0 -0
  360. /package/.agents/{skills → skills-archived}/grokify/SKILL.md +0 -0
  361. /package/.agents/{skills → skills-archived}/grokify/capability-claims.test.mjs +0 -0
  362. /package/.agents/{skills → skills-archived}/grokify/templates/handoff-template.md +0 -0
  363. /package/.agents/{skills → skills-archived}/plan-to-pr/SKILL.md +0 -0
  364. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/final-validation-tasks.md +0 -0
  365. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/model-routing.md +0 -0
  366. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/packet-contract.md +0 -0
  367. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/packet-schema.json +0 -0
  368. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/process-inventory.md +0 -0
  369. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/review-loop.md +0 -0
  370. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/run-record.schema.json +0 -0
  371. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/self-audit-tasks.md +0 -0
  372. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/task-seeds.md +0 -0
  373. /package/.agents/{skills → skills-archived}/plan-to-pr/reference/task-ticket.md +0 -0
  374. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/config/__init__.py +0 -0
  375. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/config/constants.py +0 -0
  376. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/create_packet.py +0 -0
  377. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/load_skill_constants.py +0 -0
  378. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_create_packet.py +0 -0
  379. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_packet.py +0 -0
  380. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_protocol.py +0 -0
  381. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/test_validate_run.py +0 -0
  382. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_packet.py +0 -0
  383. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_protocol.py +0 -0
  384. /package/.agents/{skills → skills-archived}/plan-to-pr/scripts/validate_run.py +0 -0
  385. /package/.agents/{skills → skills-archived}/plan-to-pr/test_skill_contract.py +0 -0
  386. /package/.agents/{skills → skills-archived}/plan-to-pr/test_task_ticket_contract.py +0 -0
  387. /package/.agents/{skills → skills-archived}/pr-converge/.claude/CLAUDE.md +0 -0
  388. /package/.agents/{skills → skills-archived}/pr-converge/AGENTS.md +0 -0
  389. /package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/.claude/CLAUDE.md +0 -0
  390. /package/.agents/{skills → skills-archived}/pr-converge/pr_converge_skill_constants/__init__.py +0 -0
  391. /package/.agents/{skills → skills-archived}/pr-converge/reference/.claude/CLAUDE.md +0 -0
  392. /package/.agents/{skills → skills-archived}/pr-converge/reference/AGENTS.md +0 -0
  393. /package/.agents/{skills → skills-archived}/pr-converge/reference/convergence-gates.md +0 -0
  394. /package/.agents/{skills → skills-archived}/pr-converge/reference/examples.md +0 -0
  395. /package/.agents/{skills → skills-archived}/pr-converge/reference/fix-protocol.md +0 -0
  396. /package/.agents/{skills → skills-archived}/pr-converge/reference/ground-rules.md +0 -0
  397. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/.claude/CLAUDE.md +0 -0
  398. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/AGENTS.md +0 -0
  399. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-post-replies.md +0 -0
  400. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-publish-summary.md +0 -0
  401. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-push.md +0 -0
  402. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-read-filelines.md +0 -0
  403. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-reset-state.md +0 -0
  404. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-resolve-threads.md +0 -0
  405. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +0 -0
  406. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-stage-commit.md +0 -0
  407. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-trigger-bugbot.md +0 -0
  408. /package/.agents/{skills → skills-archived}/pr-converge/reference/obstacles/fix-write-test.md +0 -0
  409. /package/.agents/{skills → skills-archived}/pr-converge/reference/progress-checklist.md +0 -0
  410. /package/.agents/{skills → skills-archived}/pr-converge/reference/state-schema.md +0 -0
  411. /package/.agents/{skills → skills-archived}/pr-converge/reference/stop-conditions.md +0 -0
  412. /package/.agents/{skills → skills-archived}/pr-converge/scripts/.claude/CLAUDE.md +0 -0
  413. /package/.agents/{skills → skills-archived}/pr-converge/scripts/AGENTS.md +0 -0
  414. /package/.agents/{skills → skills-archived}/pr-converge/scripts/README.md +0 -0
  415. /package/.agents/{skills → skills-archived}/pr-converge/scripts/_pr_converge_path_setup.py +0 -0
  416. /package/.agents/{skills → skills-archived}/pr-converge/scripts/caller-window-pid.ps1 +0 -0
  417. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_bugbot_ci.py +0 -0
  418. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence.py +0 -0
  419. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_availability.py +0 -0
  420. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_gates.py +0 -0
  421. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_convergence_thread_gates.py +0 -0
  422. /package/.agents/{skills → skills-archived}/pr-converge/scripts/check_pending_reviews.py +0 -0
  423. /package/.agents/{skills → skills-archived}/pr-converge/scripts/conftest.py +0 -0
  424. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue-caller.cmd +0 -0
  425. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue-stop-others.ps1 +0 -0
  426. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue.ahk +0 -0
  427. /package/.agents/{skills → skills-archived}/pr-converge/scripts/cursor-agents-continue.cmd +0 -0
  428. /package/.agents/{skills → skills-archived}/pr-converge/scripts/fetch_copilot_reviews.py +0 -0
  429. /package/.agents/{skills → skills-archived}/pr-converge/scripts/post_fix_reply.py +0 -0
  430. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/.claude/CLAUDE.md +0 -0
  431. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -0
  432. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  433. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +0 -0
  434. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/pr_converge_constants.py +0 -0
  435. /package/.agents/{skills → skills-archived}/pr-converge/scripts/pr_converge_scripts_constants/reflow_skill_md_constants.py +0 -0
  436. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test__pr_converge_path_setup.py +0 -0
  437. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_bugbot_ci.py +0 -0
  438. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence.py +0 -0
  439. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_availability.py +0 -0
  440. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_codex.py +0 -0
  441. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_contract.py +0 -0
  442. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_fixture.py +0 -0
  443. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_gates.py +0 -0
  444. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_check_convergence_thread_gates.py +0 -0
  445. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_cursor_agents_continue.py +0 -0
  446. /package/.agents/{skills → skills-archived}/pr-converge/scripts/test_reflow_skill_md.py +0 -0
  447. /package/.agents/{skills → skills-archived}/pr-converge/test_step5_host_branch.py +0 -0
  448. /package/.agents/{skills → skills-archived}/pr-converge/workflows/.claude/CLAUDE.md +0 -0
  449. /package/.agents/{skills → skills-archived}/pr-converge/workflows/AGENTS.md +0 -0
  450. /package/.agents/{skills → skills-archived}/pr-fix-protocol/SKILL.md +0 -0
  451. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/SKILL.md +0 -0
  452. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/reference/identity-and-hooks.md +0 -0
  453. /package/.agents/{skills → skills-archived}/pr-loop-cloud-transport/reference/substitution-matrix.md +0 -0
  454. /package/.agents/{skills → skills-archived}/pr-loop-lifecycle/SKILL.md +0 -0
  455. /package/.agents/{skills → skills-archived}/pr-loop-lifecycle/reference/teardown-publish-permissions.md +0 -0
  456. /package/.agents/{skills → skills-archived}/recall/.claude/CLAUDE.md +0 -0
  457. /package/.agents/{skills → skills-archived}/recall/AGENTS.md +0 -0
  458. /package/.agents/{skills → skills-archived}/recall/SKILL.md +0 -0
  459. /package/.agents/{skills → skills-archived}/release-notes-html/SKILL.md +0 -0
  460. /package/.agents/{skills → skills-archived}/remember/.claude/CLAUDE.md +0 -0
  461. /package/.agents/{skills → skills-archived}/remember/AGENTS.md +0 -0
  462. /package/.agents/{skills → skills-archived}/remember/SKILL.md +0 -0
  463. /package/.agents/{skills → skills-archived}/reviewer-gates/SKILL.md +0 -0
  464. /package/.agents/{skills → skills-archived}/reviews/SKILL.md +0 -0
  465. /package/.agents/{skills → skills-archived}/show/SKILL.md +0 -0
  466. /package/.agents/{skills → skills-archived}/show/references/accessibility.md +0 -0
  467. /package/.agents/{skills → skills-archived}/show/references/art.md +0 -0
  468. /package/.agents/{skills → skills-archived}/show/references/charts.md +0 -0
  469. /package/.agents/{skills → skills-archived}/show/references/core-design.md +0 -0
  470. /package/.agents/{skills → skills-archived}/show/references/erds.md +0 -0
  471. /package/.agents/{skills → skills-archived}/show/references/flowcharts.md +0 -0
  472. /package/.agents/{skills → skills-archived}/show/references/host-and-html.md +0 -0
  473. /package/.agents/{skills → skills-archived}/show/references/illustrative-diagrams.md +0 -0
  474. /package/.agents/{skills → skills-archived}/show/references/interaction.md +0 -0
  475. /package/.agents/{skills → skills-archived}/show/references/mockups.md +0 -0
  476. /package/.agents/{skills → skills-archived}/show/references/quality-gates.md +0 -0
  477. /package/.agents/{skills → skills-archived}/show/references/structural-diagrams.md +0 -0
  478. /package/.agents/{skills → skills-archived}/show/references/subject-inventory.md +0 -0
  479. /package/.agents/{skills → skills-archived}/show/references/svg-contract.md +0 -0
  480. /package/.agents/{skills → skills-archived}/show/routing.yaml +0 -0
  481. /package/.agents/{skills → skills-archived}/show/samples/pr1262-v2.svg +0 -0
  482. /package/.agents/{skills → skills-archived}/show/scripts/README.md +0 -0
  483. /package/.agents/{skills → skills-archived}/show/scripts/validate-artifact.py +0 -0
  484. /package/.agents/{skills → skills-archived}/show/scripts/validate-package.py +0 -0
  485. /package/.agents/{skills → skills-archived}/show/templates/html-widget.html +0 -0
  486. /package/.agents/{skills → skills-archived}/show/templates/svg-base.svg +0 -0
  487. /package/.agents/{skills → skills-archived}/show/tests/fixtures/css-var.svg +0 -0
  488. /package/.agents/{skills → skills-archived}/show/tests/fixtures/dead-ref.svg +0 -0
  489. /package/.agents/{skills → skills-archived}/show/tests/fixtures/filled-glyph.svg +0 -0
  490. /package/.agents/{skills → skills-archived}/show/tests/fixtures/inherited-fill.svg +0 -0
  491. /package/.agents/{skills → skills-archived}/show/tests/fixtures/invalid.svg +0 -0
  492. /package/.agents/{skills → skills-archived}/show/tests/fixtures/large-canvas.svg +0 -0
  493. /package/.agents/{skills → skills-archived}/show/tests/fixtures/unfilled-connector.svg +0 -0
  494. /package/.agents/{skills → skills-archived}/show/tests/fixtures/valid.html +0 -0
  495. /package/.agents/{skills → skills-archived}/show/tests/test_validate-artifact.py +0 -0
  496. /package/.agents/{skills → skills-archived}/show/tests/test_validators.py +0 -0
  497. /package/.agents/{skills → skills-archived}/show/workflows/create-visual.md +0 -0
  498. /package/.agents/{skills → skills-archived}/show/workflows/review-visual.md +0 -0
  499. /package/.agents/{skills → skills-archived}/split-pr/SKILL.md +0 -0
  500. /package/.agents/{skills → skills-archived}/split-pr/reference/path-layers.md +0 -0
  501. /package/.agents/{skills → skills-archived}/split-pr/reference/split-further-loop.md +0 -0
  502. /package/.agents/{skills → skills-archived}/split-pr/reference/splitting-principles.md +0 -0
  503. /package/.agents/{skills → skills-archived}/split-pr/scripts/analyze_pr.py +0 -0
  504. /package/.agents/{skills → skills-archived}/split-pr/scripts/categorize_files.py +0 -0
  505. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/__init__.py +0 -0
  506. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/dependency_constants.py +0 -0
  507. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/git_operations_constants.py +0 -0
  508. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/packing_constants.py +0 -0
  509. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/plan_constants.py +0 -0
  510. /package/.agents/{skills → skills-archived}/split-pr/scripts/config/split_pr_constants.py +0 -0
  511. /package/.agents/{skills → skills-archived}/split-pr/scripts/execute_split_slices.py +0 -0
  512. /package/.agents/{skills → skills-archived}/split-pr/scripts/pack_files_into_slices.py +0 -0
  513. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_dependency_graph.py +0 -0
  514. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_git_operations.py +0 -0
  515. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_layer_order.py +0 -0
  516. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_paginate.py +0 -0
  517. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_process_runner.py +0 -0
  518. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_script_types.py +0 -0
  519. /package/.agents/{skills → skills-archived}/split-pr/scripts/split_pr_title.py +0 -0
  520. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_analyze_pr.py +0 -0
  521. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_categorize_files.py +0 -0
  522. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_categorize_files_packing.py +0 -0
  523. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_execute_split_slices.py +0 -0
  524. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_dependency_graph.py +0 -0
  525. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_git_operations.py +0 -0
  526. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_layer_order.py +0 -0
  527. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_paginate.py +0 -0
  528. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_script_types.py +0 -0
  529. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_split_pr_title.py +0 -0
  530. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_dependency_graph.py +0 -0
  531. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan.py +0 -0
  532. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan_contract.py +0 -0
  533. /package/.agents/{skills → skills-archived}/split-pr/scripts/test_verify_plan_path_normalization.py +0 -0
  534. /package/.agents/{skills → skills-archived}/split-pr/scripts/verify_dependency_graph.py +0 -0
  535. /package/.agents/{skills → skills-archived}/split-pr/scripts/verify_plan.py +0 -0
@@ -0,0 +1,47 @@
1
+ """CLI production-path acceptance tests."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import subprocess
7
+ import sys
8
+ from pathlib import Path
9
+ import pytest
10
+
11
+ from review_router_cli import arm, close, resolve
12
+ from review_router_constants.config.constants import UNSUPPORTED_ROUTE
13
+
14
+ CLI = Path(__file__).with_name("review_router_cli.py")
15
+
16
+
17
+ def test_public_arm_and_close_reject_missing_signed_state(tmp_path: Path) -> None:
18
+ with pytest.raises(OSError):
19
+ arm(str(tmp_path), "missing", "slot")
20
+ with pytest.raises(OSError):
21
+ close(str(tmp_path), "missing")
22
+
23
+
24
+ def test_resolve_returns_unsupported_for_unknown_route(tmp_path: Path) -> None:
25
+ resolve_response = resolve(str(tmp_path), "unknown-route", "", None)
26
+ assert resolve_response["status"] == UNSUPPORTED_ROUTE
27
+
28
+
29
+ def test_cli_rejects_requested_dispatch(tmp_path: Path) -> None:
30
+ command_result = subprocess.run(
31
+ [sys.executable, str(CLI), "next", "--cwd", str(tmp_path)],
32
+ capture_output=True,
33
+ text=True,
34
+ )
35
+ assert command_result.returncode != 0
36
+ assert "invalid choice" in command_result.stderr
37
+
38
+
39
+ @pytest.mark.parametrize("arguments", ["--tier 4", "--tier", "--tier x", "--tier 1 --tier 2"])
40
+ def test_malformed_tier_override_writes_no_artifacts(tmp_path: Path, arguments: str) -> None:
41
+ repository = tmp_path / "repository"
42
+ repository.mkdir()
43
+ subprocess.run(["git", "init", "-q"], cwd=repository, check=True)
44
+ environment = {**os.environ, "CLAUDE_PLUGIN_DATA": str(tmp_path / "data")}
45
+ command_result = subprocess.run([sys.executable, str(CLI), "resolve", "--cwd", str(repository), "--arguments", arguments], capture_output=True, text=True, env=environment)
46
+ assert command_result.returncode != 0
47
+ assert not (tmp_path / "data").exists()
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: review-tier
3
+ description: >-
4
+ Classify `review_tier_constants` from change axes, hard triggers, and user overrides. Triggers: /review-tier, tier override, and review classification.
5
+ ---
6
+
7
+ # Review Tier
8
+
9
+ Classify one current change surface into T1, T2, or T3 using `reference/tier-policy.json` and `scripts/review_tier.py`.
10
+
11
+ ## Composition
12
+
13
+ | Skill | When | Produces |
14
+ |---|---|---|
15
+ | `/review-router` | After classification | Current decision route and guarded execution |
16
+ | `/task-build` | At workflow start | Registered classification tasks |
17
+
18
+ If `/review-router` is unavailable, return the current classification.
19
+
20
+ ## When this applies
21
+
22
+ Use for `/review-tier` and automatic review classification. Refuse execution requests with: `This is a route execution request — use /review-router.` Refuse malformed policy with: `The review-tier policy is invalid; repair the policy before classification.`
23
+
24
+ ## Process
25
+
26
+ 1. Register `reference/task-seeds.md` with the host task tool.
27
+ 2. Run `scripts/review_tier.py` and record the current decision fields.
28
+ 3. Hand the current decision to `/review-router` when route execution is requested.
29
+
30
+ ## Examples
31
+
32
+ Input `{"files": 0, "lines": 0}` produces `T1`. Input `{"hard_triggers": ["migration"]}` produces `T3`. Input `{"files": 0}` with override `T2` produces calculated `T1` and effective `T2`.
33
+
34
+ ## Dependencies
35
+
36
+ Requires Python 3.11+ and the standard library only. Treat a non-zero script exit as a failed classification.
37
+
38
+ ## File index
39
+
40
+ | File | Purpose |
41
+ |---|---|
42
+ | `SKILL.md` | Classification workflow and boundaries |
43
+ | `reference/tier-policy.json` | Versioned axes, thresholds, and hard triggers |
44
+ | `reference/task-seeds.md` | Ordered classification tasks |
45
+ | `scripts/review_tier.py` | Deterministic classifier |
46
+ | `scripts/test_review_tier.py` | Classifier behavior tests |
47
+ | `scripts/test_generation.py` | Inventory generation tests |
48
+ | `scripts/conftest.py` | Test import setup |
49
+ | `scripts/review_tier_constants/__init__.py` | Constants package |
50
+ | `scripts/review_tier_constants/config/__init__.py` | Runtime configuration package |
51
+ | `scripts/review_tier_constants/config/constants.py` | Portable tier constants |
52
+
53
+ ## Folder map
54
+
55
+ - `reference/` — policy and task data.
56
+ - `scripts/` — executable classifier and paired tests.
@@ -0,0 +1 @@
1
+ Register classification inputs, policy validation, tier selection, and override resolution as host tasks. Complete each with command output or the current decision.
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 1,
3
+ "tiers": ["T1", "T2", "T3"],
4
+ "thresholds": {"T1": 0, "T2": 2, "T3": 5},
5
+ "hard_triggers": ["security", "migration", "public-api", "release"],
6
+ "axes": ["files", "lines", "packages", "risk", "public_api", "dependencies"],
7
+ "axis_weights": {"files": 1, "lines": 1, "packages": 2, "risk": 2, "public_api": 2, "dependencies": 1},
8
+ "approved_downgrades": ["T1", "T2"]
9
+ }
@@ -0,0 +1,4 @@
1
+ from pathlib import Path
2
+ import sys
3
+
4
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
@@ -0,0 +1,332 @@
1
+ """Build canonical pull-request evidence and select a review tier."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import os
8
+ import subprocess
9
+ from pathlib import Path
10
+ from typing import Mapping, Sequence
11
+
12
+ from review_tier_constants.config.constants import ALL_DEPENDENCY_MARKERS, ALL_HARD_TRIGGER_MARKERS, ALL_PACKAGE_ROOT_NAMES, ALL_PUBLIC_API_MARKERS, ALL_SOURCE_SUFFIXES, ALL_STATUS_ARGUMENTS, ALL_STATUS_DOMAINS, ALL_TIER_ORDER, ALL_UNTRACKED_ARGUMENTS, AMBIGUOUS_BASE_REF, DEFAULT_BRANCH_FALLBACK, GIT_COMMAND_FAILED, GIT_HEAD_REF, INVALID_BASE_REF, JSON_INDENT, MALFORMED_TIER_POLICY, MAX_AXIS_VALUE, MIN_NONEMPTY_RISK, PATH_SEPARATOR, PLUGIN_DATA_ENVIRONMENT, REMOTE_HEAD_REF, ROOT_PACKAGE, ROUTING_STATE_ROOT_TRACKED, STATUS_CODE_LENGTH, STATUS_PREFIX_LENGTH, UNAPPROVED_TIER_DOWNGRADE, UNKNOWN_TIER
13
+
14
+
15
+ def router_state_root(repo_root: str | Path, all_environment: Mapping[str, str] | None = None) -> Path:
16
+ """Return the canonical router state root for a repository."""
17
+ selected_environment = all_environment or os.environ
18
+ plugin_root = Path(selected_environment.get(PLUGIN_DATA_ENVIRONMENT, Path(repo_root).resolve() / ".claude-plugin-data"))
19
+ return (plugin_root / "review-routing" / "v1").resolve()
20
+
21
+
22
+ def router_state_directory(repo_root: str | Path, all_environment: Mapping[str, str] | None = None) -> Path:
23
+ """Return the repository-specific directory under the router state root."""
24
+ resolved_root = Path(repo_root).resolve()
25
+ worktree_key = hashlib.sha256(str(resolved_root).encode()).hexdigest()
26
+ return router_state_root(resolved_root, all_environment=all_environment) / worktree_key
27
+
28
+
29
+ def router_state_root_id(state_root: str | Path) -> str:
30
+ """Return the stable identity digest for a canonical router state root."""
31
+ return hashlib.sha256(str(Path(state_root).resolve()).casefold().encode()).hexdigest()
32
+
33
+
34
+ def _is_inside_state_root(repo_root: Path, relative_path: str, state_root: Path) -> bool:
35
+ return (repo_root / relative_path).resolve().is_relative_to(state_root)
36
+
37
+ def _git(root: Path, all_arguments: Sequence[str], is_required: bool) -> bytes:
38
+ command = ["git", *all_arguments]
39
+ completed_process = subprocess.run(command, cwd=root, check=is_required, capture_output=True)
40
+ if completed_process.returncode and is_required:
41
+ raise ValueError(GIT_COMMAND_FAILED)
42
+ return completed_process.stdout
43
+
44
+
45
+ def _resolve_base(root: Path, requested_base: str | None) -> tuple[str, str]:
46
+ if requested_base:
47
+ candidate = _git(root, ["rev-parse", "--verify", requested_base], is_required=False).decode().strip()
48
+ if not candidate:
49
+ raise ValueError(INVALID_BASE_REF)
50
+ return requested_base, candidate
51
+ remote_head = _git(root, ["symbolic-ref", "--quiet", REMOTE_HEAD_REF], is_required=False).decode().strip()
52
+ if remote_head:
53
+ candidate = _git(root, ["rev-parse", "--verify", remote_head], is_required=False).decode().strip()
54
+ if candidate:
55
+ return remote_head, candidate
56
+ fallback = _git(root, ["rev-parse", "--verify", DEFAULT_BRANCH_FALLBACK], is_required=False).decode().strip()
57
+ if fallback:
58
+ return DEFAULT_BRANCH_FALLBACK, fallback
59
+ raise ValueError(AMBIGUOUS_BASE_REF)
60
+
61
+
62
+ def _status_domains(root: Path, state_root: Path | None = None) -> dict[str, set[str]]:
63
+ all_status_lines = _git(root, list(ALL_STATUS_ARGUMENTS), is_required=True).decode(errors="surrogateescape").split("\0")
64
+ domains = {domain: set() for domain in ALL_STATUS_DOMAINS}
65
+ for each_status_line in all_status_lines:
66
+ if len(each_status_line) < STATUS_PREFIX_LENGTH:
67
+ continue
68
+ path = each_status_line[STATUS_PREFIX_LENGTH:]
69
+ if state_root is not None and _is_inside_state_root(root, path, state_root):
70
+ continue
71
+ if each_status_line[:STATUS_CODE_LENGTH] == "??":
72
+ domains["untracked"].add(path)
73
+ else:
74
+ if each_status_line[0] != " ":
75
+ domains["staged"].add(path)
76
+ if each_status_line[1] != " ":
77
+ domains["unstaged"].add(path)
78
+ return domains
79
+
80
+
81
+ def _untracked_paths(root: Path, state_root: Path | None = None) -> list[str]:
82
+ untracked_listing = _git(root, ALL_UNTRACKED_ARGUMENTS, is_required=True)
83
+ all_paths = [each_path.decode(errors="surrogateescape") for each_path in untracked_listing.split(b"\0") if each_path]
84
+ return [each_path for each_path in all_paths if state_root is None or not _is_inside_state_root(root, each_path, state_root)]
85
+
86
+
87
+ def _record_content(root: Path, merge_base: str, relative_path: str) -> tuple[bytes, str]:
88
+ file_path = root / relative_path
89
+ if file_path.is_symlink():
90
+ content = b""
91
+ identity = hashlib.sha256(os.readlink(file_path).encode()).hexdigest()
92
+ elif file_path.is_file():
93
+ content = file_path.read_bytes()
94
+ identity = hashlib.sha256(content).hexdigest()
95
+ else:
96
+ content = _git(root, ["show", f"{merge_base}:{relative_path}"], is_required=True)
97
+ identity = hashlib.sha256(content).hexdigest()
98
+ return content, identity
99
+
100
+
101
+ def _annotate_record(root: Path, merge_base: str, relative_path: str, all_record: dict[str, object], all_domains: dict[str, set[str]]) -> None:
102
+ content, identity = _record_content(root, merge_base, relative_path)
103
+ lower_path = relative_path.lower()
104
+ all_record.update({"domains": sorted([each_domain for each_domain, all_paths in all_domains.items() if relative_path in all_paths] + (["committed"] if all_record["status"] != "?" else [])), "operation_by_domain": {}, "content_sha256": identity, "binary": b"\0" in content, "added": 0, "deleted": 0, "package": _package_key(relative_path), "public_api": int(any(marker.lower() in lower_path for marker in ALL_PUBLIC_API_MARKERS)), "dependency": int(any(marker.lower() in lower_path for marker in ALL_DEPENDENCY_MARKERS)), "call_path": int(lower_path.endswith(ALL_SOURCE_SUFFIXES))})
105
+ all_record["operation_by_domain"] = {each_domain: ("A" if all_record["status"] == "?" else all_record["status"]) for each_domain in all_record["domains"]}
106
+
107
+
108
+ def _effective_records(root: Path, merge_base: str, all_domains: dict[str, set[str]], state_root: Path | None = None) -> list[dict[str, object]]:
109
+ status_bytes = _git(root, ["diff", "--name-status", "-z", merge_base, "--"], is_required=True)
110
+ status_tokens = status_bytes.split(b"\0")
111
+ records_by_path: dict[str, dict[str, object]] = {}
112
+ all_untracked_paths = _untracked_paths(root, state_root)
113
+ index = 0
114
+ while index < len(status_tokens) - 1:
115
+ status = status_tokens[index].decode(errors="surrogateescape")
116
+ index += 1
117
+ if not status:
118
+ continue
119
+ prior_path = None
120
+ if status[0] in {"R", "C"}:
121
+ prior_path = status_tokens[index].decode(errors="surrogateescape")
122
+ index += 1
123
+ current_path = status_tokens[index].decode(errors="surrogateescape")
124
+ index += 1
125
+ records_by_path[current_path] = {"path": current_path, "prior_path": prior_path, "status": status[0]}
126
+ for each_path in all_untracked_paths:
127
+ records_by_path.setdefault(each_path, {"path": each_path, "prior_path": None, "status": "?"})
128
+ if state_root is not None:
129
+ tracked_state_paths = [each_path for each_path in records_by_path if _is_inside_state_root(root, each_path, state_root) and records_by_path[each_path]["status"] != "?"]
130
+ if tracked_state_paths:
131
+ raise ValueError(ROUTING_STATE_ROOT_TRACKED)
132
+ records_by_path = {each_path: record for each_path, record in records_by_path.items() if not _is_inside_state_root(root, each_path, state_root)}
133
+ for each_path, each_record in records_by_path.items():
134
+ _annotate_record(root, merge_base, each_path, each_record, all_domains)
135
+ numstat = _git(root, ["diff", "--numstat", "-z", merge_base, "--"], is_required=True).split(b"\0")
136
+ index = 0
137
+ while index + 1 < len(numstat):
138
+ fields = numstat[index].split(b"\t")
139
+ index += 1
140
+ if len(fields) < STATUS_CODE_LENGTH:
141
+ continue
142
+ if len(fields) == STATUS_CODE_LENGTH:
143
+ if index >= len(numstat):
144
+ continue
145
+ path = numstat[index].decode(errors="surrogateescape")
146
+ index += 1
147
+ else:
148
+ path = fields[2].decode(errors="surrogateescape")
149
+ record = records_by_path.get(path)
150
+ if record is None:
151
+ continue
152
+ record["added"] = int(fields[0]) if fields[0].isdigit() else 0
153
+ record["deleted"] = int(fields[1]) if fields[1].isdigit() else 0
154
+ record["binary"] = fields[0] == b"-" or fields[1] == b"-"
155
+ for each_path in all_untracked_paths:
156
+ record = records_by_path[each_path]
157
+ content = (root / each_path).read_bytes() if (root / each_path).is_file() else b""
158
+ if b"\0" not in content:
159
+ record["added"] = content.count(b"\n")
160
+ return [records_by_path[each_path] for each_path in sorted(records_by_path)]
161
+
162
+
163
+ def _committed_paths(root: Path, merge_base: str) -> set[str]:
164
+ committed_paths = _git(root, ["diff", "--name-only", "-z", f"{merge_base}..{GIT_HEAD_REF}"], is_required=True).decode(errors="surrogateescape")
165
+ return {path for path in committed_paths.split("\0") if path}
166
+
167
+
168
+ def _hard_triggers(all_paths: set[str]) -> list[str]:
169
+ lower_paths = {path.lower() for path in all_paths}
170
+ return [name for name, markers in ALL_HARD_TRIGGER_MARKERS.items() if any(marker in path for path in lower_paths for marker in markers)]
171
+
172
+
173
+ def inventory_generation(repo_root: str | Path, base_ref: str | None = None, state_root: str | Path | None = None) -> dict[str, object]:
174
+ """Return one hashed inventory covering committed and working-tree changes.
175
+
176
+ Args:
177
+ repo_root: Repository to inspect.
178
+ base_ref: Optional validated base reference.
179
+ Returns:
180
+ Canonical evidence and domain metadata.
181
+ """
182
+ root = Path(repo_root).resolve()
183
+ state_root = Path(state_root).resolve() if state_root is not None else None
184
+ head = _git(root, ["rev-parse", "--verify", GIT_HEAD_REF], is_required=True).decode().strip()
185
+ requested_base, base = _resolve_base(root, base_ref)
186
+ merge_base = _git(root, ["merge-base", base, head], is_required=True)
187
+ merge_base = merge_base.decode().strip()
188
+ domains = _status_domains(root, state_root=state_root)
189
+ committed = _committed_paths(root, merge_base)
190
+ all_paths = committed | set().union(*domains.values())
191
+ records = _effective_records(root, merge_base, domains, state_root=state_root)
192
+ packages = {str(record["package"]) for record in records}
193
+ public_api = int(any(record["public_api"] for record in records))
194
+ dependencies = int(any(record["dependency"] for record in records))
195
+ triggers = _hard_triggers(all_paths)
196
+ patch_bytes = _git(root, ["diff", "--binary", "--full-index", "--no-ext-diff", merge_base, "--"], is_required=True)
197
+ untracked_identities = [{"path": each_path, "sha256": record["content_sha256"]} for each_path, record in ((record["path"], record) for record in records) if "untracked" in record["domains"]]
198
+ base_source = "explicit" if base_ref else ("remote_default" if requested_base == REMOTE_HEAD_REF else "configured_fallback")
199
+ canonical = json.dumps({"base_ref": requested_base, "base_source": base_source, "base_sha": base, "merge_base_sha": merge_base, "head_sha": head, "domains": {each_domain: sorted(all_paths) for each_domain, all_paths in domains.items()}, "files": records, "untracked_identities": sorted(untracked_identities, key=lambda record: record["path"])}, sort_keys=True, separators=(",", ":")).encode() + patch_bytes
200
+ lines = sum(int(record["added"]) + int(record["deleted"]) for record in records)
201
+ digest = hashlib.sha256(canonical).hexdigest()
202
+ return {"paths": [record["path"] for record in records], "files_by_domain": records, "committed": sorted(committed), "staged": sorted(domains["staged"]), "unstaged": sorted(domains["unstaged"]), "untracked": sorted(domains["untracked"]), "base_ref": requested_base, "base_source": base_source, "base_sha": base, "merge_base_sha": merge_base, "head_sha": head, "merge_base": merge_base, "HEAD": head, "inventory_hash": digest, "diff_hash": digest, "files": len(records), "lines": lines, "packages": len(packages), "risk": MIN_NONEMPTY_RISK if records else 0, "public_api": public_api, "dependencies": dependencies, "hard_triggers": triggers}
203
+
204
+
205
+ def _package_key(path: str) -> str:
206
+ parts = path.split("/")
207
+ if len(parts) > 1 and parts[0] in ALL_PACKAGE_ROOT_NAMES:
208
+ return PATH_SEPARATOR.join(parts[:2])
209
+ return parts[0] if len(parts) > 1 else ROOT_PACKAGE
210
+
211
+
212
+ def build_generation(repo_root: str | Path, requested_override: str | None = None, card_path: str | Path | None = None, base_ref: str | None = None, all_policy: Mapping[str, object] | None = None, state_root: str | Path | None = None) -> dict[str, object]:
213
+ """Build and optionally persist one immutable tier card.
214
+
215
+ Args:
216
+ repo_root: Repository to inspect.
217
+ requested_override: Optional requested tier.
218
+ card_path: Optional destination for the card.
219
+ base_ref: Optional base reference.
220
+ all_policy: Optional tier policy.
221
+ Returns:
222
+ The generated decision card.
223
+ """
224
+ inventory = inventory_generation(repo_root, base_ref=base_ref, state_root=state_root)
225
+ card = build_decision(inventory, str(inventory["base_ref"]), str(inventory["HEAD"]), str(Path(repo_root).resolve()), str(inventory["inventory_hash"]), requested_override=requested_override, all_policy=all_policy)
226
+ card["inventory_hash"] = inventory["inventory_hash"]
227
+ if card_path is not None:
228
+ destination = Path(card_path)
229
+ destination.parent.mkdir(parents=True, exist_ok=True)
230
+ with destination.open("x", encoding="utf-8") as card_file:
231
+ json.dump(card, card_file, sort_keys=True, indent=JSON_INDENT)
232
+ card_file.write("\n")
233
+ return card
234
+
235
+
236
+ def load_policy() -> dict[str, object]:
237
+ """Load and validate versioned tier policy data.
238
+
239
+ Args:
240
+ Returns:
241
+ Parsed policy mapping.
242
+ Raises:
243
+ ValueError: If the policy schema is invalid.
244
+ """
245
+ policy_path = Path(__file__).parent.parent / "reference" / "tier-policy.json"
246
+ policy = json.loads(policy_path.read_text(encoding="utf-8"))
247
+ if policy.get("version") != 1 or tuple(policy.get("tiers", ())) != ALL_TIER_ORDER or set(policy.get("thresholds", {})) != set(ALL_TIER_ORDER):
248
+ raise ValueError(MALFORMED_TIER_POLICY)
249
+ return policy
250
+
251
+
252
+ def policy_hash(all_policy: Mapping[str, object]) -> str:
253
+ """Return the stable policy digest used by decision records.
254
+
255
+ Args:
256
+ all_policy: Parsed tier policy.
257
+ Returns:
258
+ Stable SHA-256 digest.
259
+ """
260
+ return canonical_json_hash(all_policy)
261
+
262
+
263
+ def canonical_json_hash(all_record: Mapping[str, object]) -> str:
264
+ """Return the stable SHA-256 digest for a JSON-compatible mapping.
265
+
266
+ Args:
267
+ all_record: Mapping to encode.
268
+ Returns:
269
+ Stable SHA-256 digest.
270
+ """
271
+ encoded_record = json.dumps(all_record, sort_keys=True, separators=(",", ":")).encode()
272
+ return hashlib.sha256(encoded_record).hexdigest()
273
+
274
+
275
+ def calculate_tier(all_evidence: Mapping[str, object], all_policy: Mapping[str, object] | None = None) -> str:
276
+ """Calculate a tier from six bounded axes and hard triggers.
277
+
278
+ Args:
279
+ all_evidence: Bounded change evidence.
280
+ all_policy: Optional tier policy.
281
+ Returns:
282
+ Automatic tier identifier.
283
+ """
284
+ selected_policy = all_policy or load_policy()
285
+ if set(all_evidence.get("hard_triggers", ())).intersection(selected_policy["hard_triggers"]):
286
+ return "T3"
287
+ score = sum(min(MAX_AXIS_VALUE, int(all_evidence.get(axis, 0))) * int(weight) for axis, weight in selected_policy["axis_weights"].items())
288
+ if score >= selected_policy["thresholds"]["T3"]:
289
+ return "T3"
290
+ if score >= selected_policy["thresholds"]["T2"]:
291
+ return "T2"
292
+ return "T1"
293
+
294
+
295
+ def effective_tier(calculated_tier: str, requested_override: str | None, all_policy: Mapping[str, object] | None = None) -> str:
296
+ """Apply an approved explicit tier override.
297
+
298
+ Args:
299
+ calculated_tier: Automatic tier.
300
+ requested_override: Optional requested tier.
301
+ all_policy: Optional tier policy.
302
+ Returns:
303
+ Effective tier identifier.
304
+ Raises:
305
+ ValueError: If either tier is invalid or the downgrade is unapproved.
306
+ """
307
+ selected_policy = all_policy or load_policy()
308
+ if calculated_tier not in ALL_TIER_ORDER or requested_override not in (*ALL_TIER_ORDER, None):
309
+ raise ValueError(UNKNOWN_TIER)
310
+ if requested_override is None or requested_override == calculated_tier or requested_override > calculated_tier:
311
+ return requested_override or calculated_tier
312
+ if requested_override in selected_policy["approved_downgrades"]:
313
+ return requested_override
314
+ raise ValueError(UNAPPROVED_TIER_DOWNGRADE)
315
+
316
+
317
+ def build_decision(all_change: Mapping[str, object], base: str, commit: str, worktree: str, diff_hash: str, requested_override: str | None = None, all_policy: Mapping[str, object] | None = None) -> dict[str, object]:
318
+ """Build a serializable tier card with evidence and policy identity.
319
+
320
+ Args:
321
+ all_change: Canonical inventory evidence.
322
+ base: Resolved base reference.
323
+ commit: Current HEAD.
324
+ worktree: Repository path.
325
+ diff_hash: Canonical evidence digest.
326
+ requested_override: Optional requested tier.
327
+ Returns:
328
+ Serializable decision card.
329
+ """
330
+ selected_policy = all_policy or load_policy()
331
+ calculated = calculate_tier(all_change, all_policy=selected_policy)
332
+ return {"calculated_tier": calculated, "requested_override": requested_override, "effective_tier": effective_tier(calculated, requested_override, all_policy=selected_policy), "evidence": dict(all_change), "policy_hash": policy_hash(selected_policy), "base_ref": base, "base_source": all_change.get("base_source"), "merge_base": all_change.get("merge_base"), "HEAD": commit, "worktree": str(Path(worktree).resolve()), "diff_hash": diff_hash}
@@ -0,0 +1 @@
1
+ """Review-tier constants package."""
@@ -0,0 +1,29 @@
1
+ """Constants for review_tier_constants."""
2
+
3
+ DEFAULT_BRANCH_FALLBACK = "main"
4
+ GIT_HEAD_REF = "HEAD"
5
+ REMOTE_HEAD_REF = "refs/remotes/origin/HEAD"
6
+ MAX_AXIS_VALUE = 2
7
+ MIN_NONEMPTY_RISK = 1
8
+ GIT_COMMAND_FAILED = "GIT_COMMAND_FAILED"
9
+ INVALID_BASE_REF = "INVALID_BASE_REF"
10
+ AMBIGUOUS_BASE_REF = "AMBIGUOUS_BASE_REF"
11
+ MALFORMED_TIER_POLICY = "MALFORMED_TIER_POLICY"
12
+ UNKNOWN_TIER = "UNKNOWN_TIER"
13
+ UNAPPROVED_TIER_DOWNGRADE = "UNAPPROVED_TIER_DOWNGRADE"
14
+ ALL_TIER_ORDER = ("T1", "T2", "T3")
15
+ ALL_PUBLIC_API_MARKERS = ("__init__.py", "api.py", "cli.py", "SKILL.md")
16
+ ALL_DEPENDENCY_MARKERS = ("package.json", "requirements", "pyproject.toml", "poetry.lock")
17
+ ALL_HARD_TRIGGER_MARKERS = {"security": ("security", "auth", "permission"), "migration": ("migration", "migrations"), "public-api": ("api.py", "__init__.py"), "release": ("release", "version")}
18
+ ALL_STATUS_DOMAINS = ("staged", "unstaged", "untracked")
19
+ JSON_INDENT = 2
20
+ ALL_STATUS_ARGUMENTS = ("status", "--porcelain=v1", "-z", "--untracked-files=all")
21
+ ROOT_PACKAGE = "."
22
+ STATUS_PREFIX_LENGTH = 3
23
+ STATUS_CODE_LENGTH = 2
24
+ ALL_PACKAGE_ROOT_NAMES = ("packages", "apps", "libs", "services")
25
+ PATH_SEPARATOR = "/"
26
+ ALL_SOURCE_SUFFIXES = (".py", ".js", ".ts")
27
+ ALL_UNTRACKED_ARGUMENTS = ("ls-files", "--others", "--exclude-standard", "-z")
28
+ ROUTING_STATE_ROOT_TRACKED = "ROUTING_STATE_ROOT_TRACKED"
29
+ PLUGIN_DATA_ENVIRONMENT = "CLAUDE_PLUGIN_DATA"