drawspec 0.1.0__tar.gz

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 (686) hide show
  1. drawspec-0.1.0/.claude/settings.json +40 -0
  2. drawspec-0.1.0/.claude/skills/continue/.arsenal-vendored +0 -0
  3. drawspec-0.1.0/.claude/skills/continue/SKILL.md +129 -0
  4. drawspec-0.1.0/.claude/skills/continue/evals/loading_verification.json +11 -0
  5. drawspec-0.1.0/.claude/skills/coverage-gaps/.arsenal-vendored +0 -0
  6. drawspec-0.1.0/.claude/skills/coverage-gaps/SKILL.md +74 -0
  7. drawspec-0.1.0/.claude/skills/coverage-gaps/evals/loading_verification.json +18 -0
  8. drawspec-0.1.0/.claude/skills/coverage-gaps/scripts/analyze_coverage.py +103 -0
  9. drawspec-0.1.0/.claude/skills/dep-upgrade/.arsenal-vendored +0 -0
  10. drawspec-0.1.0/.claude/skills/dep-upgrade/SKILL.md +89 -0
  11. drawspec-0.1.0/.claude/skills/dep-upgrade/evals/loading_verification.json +18 -0
  12. drawspec-0.1.0/.claude/skills/dep-upgrade/scripts/compare_lockfile.py +132 -0
  13. drawspec-0.1.0/.claude/skills/design/.arsenal-vendored +0 -0
  14. drawspec-0.1.0/.claude/skills/design/SKILL.md +113 -0
  15. drawspec-0.1.0/.claude/skills/design/evals/loading_verification.json +20 -0
  16. drawspec-0.1.0/.claude/skills/design/references/template-plan.md +80 -0
  17. drawspec-0.1.0/.claude/skills/design/references/template-specification-tail.md +42 -0
  18. drawspec-0.1.0/.claude/skills/design/scripts/validate_plan.py +116 -0
  19. drawspec-0.1.0/.claude/skills/execution/.arsenal-vendored +0 -0
  20. drawspec-0.1.0/.claude/skills/execution/SKILL.md +127 -0
  21. drawspec-0.1.0/.claude/skills/execution/evals/loading_verification.json +20 -0
  22. drawspec-0.1.0/.claude/skills/execution/references/template.md +46 -0
  23. drawspec-0.1.0/.claude/skills/gate-check/.arsenal-vendored +0 -0
  24. drawspec-0.1.0/.claude/skills/gate-check/SKILL.md +109 -0
  25. drawspec-0.1.0/.claude/skills/gate-check/evals/loading_verification.json +19 -0
  26. drawspec-0.1.0/.claude/skills/gate-check/references/gate-grammar.md +116 -0
  27. drawspec-0.1.0/.claude/skills/gate-check/scripts/run_gate.py +345 -0
  28. drawspec-0.1.0/.claude/skills/github/.arsenal-vendored +0 -0
  29. drawspec-0.1.0/.claude/skills/github/SKILL.md +109 -0
  30. drawspec-0.1.0/.claude/skills/github/evals/loading_verification.json +18 -0
  31. drawspec-0.1.0/.claude/skills/github/references/pr-review-loop.md +95 -0
  32. drawspec-0.1.0/.claude/skills/github/references/projects-detection.md +65 -0
  33. drawspec-0.1.0/.claude/skills/github/scripts/query_pr_state.py +455 -0
  34. drawspec-0.1.0/.claude/skills/github/scripts/query_project_type.py +116 -0
  35. drawspec-0.1.0/.claude/skills/init/.arsenal-vendored +0 -0
  36. drawspec-0.1.0/.claude/skills/init/SKILL.md +75 -0
  37. drawspec-0.1.0/.claude/skills/init/assets/.bundle-version +1 -0
  38. drawspec-0.1.0/.claude/skills/init/assets/AGENTS.md +203 -0
  39. drawspec-0.1.0/.claude/skills/init/assets/agents/worker.md +174 -0
  40. drawspec-0.1.0/.claude/skills/init/assets/bin/budget_check.sh +107 -0
  41. drawspec-0.1.0/.claude/skills/init/assets/bin/check_skill_workshop_loaded.sh +65 -0
  42. drawspec-0.1.0/.claude/skills/init/assets/bin/check_update.sh +305 -0
  43. drawspec-0.1.0/.claude/skills/init/assets/bin/claim_task.sh +103 -0
  44. drawspec-0.1.0/.claude/skills/init/assets/bin/detect_surface.sh +49 -0
  45. drawspec-0.1.0/.claude/skills/init/assets/bin/gate_run.sh +369 -0
  46. drawspec-0.1.0/.claude/skills/init/assets/bin/gate_target.py +168 -0
  47. drawspec-0.1.0/.claude/skills/init/assets/bin/github_channel.sh +158 -0
  48. drawspec-0.1.0/.claude/skills/init/assets/bin/mark_skill_workshop_loaded.sh +35 -0
  49. drawspec-0.1.0/.claude/skills/init/assets/bin/mark_skill_workshop_loaded_from_prompt.sh +37 -0
  50. drawspec-0.1.0/.claude/skills/init/assets/bin/open_task_pr.sh +601 -0
  51. drawspec-0.1.0/.claude/skills/init/assets/bin/outline.sh +120 -0
  52. drawspec-0.1.0/.claude/skills/init/assets/bin/rebase_stack.sh +227 -0
  53. drawspec-0.1.0/.claude/skills/init/assets/bin/rescue_snapshot.sh +83 -0
  54. drawspec-0.1.0/.claude/skills/init/assets/bin/statusline_capture.sh +81 -0
  55. drawspec-0.1.0/.claude/skills/init/assets/bin/worker_postcheck.sh +185 -0
  56. drawspec-0.1.0/.claude/skills/init/assets/bin/workspace_list.sh +13 -0
  57. drawspec-0.1.0/.claude/skills/init/assets/bin/worktree_probe.sh +65 -0
  58. drawspec-0.1.0/.claude/skills/init/assets/references/claiming-internals.md +41 -0
  59. drawspec-0.1.0/.claude/skills/init/assets/references/evidence-gates.md +134 -0
  60. drawspec-0.1.0/.claude/skills/init/assets/references/github-automation.md +121 -0
  61. drawspec-0.1.0/.claude/skills/init/assets/references/queue-seeding.md +146 -0
  62. drawspec-0.1.0/.claude/skills/init/assets/references/quota-governance.md +29 -0
  63. drawspec-0.1.0/.claude/skills/init/assets/references/state-layout.md +82 -0
  64. drawspec-0.1.0/.claude/skills/init/assets/references/worker-loop.md +301 -0
  65. drawspec-0.1.0/.claude/skills/init/assets/scripts/arsenal_config.py +249 -0
  66. drawspec-0.1.0/.claude/skills/init/assets/scripts/arsenal_migrate.py +310 -0
  67. drawspec-0.1.0/.claude/skills/init/assets/scripts/create_reader.py +916 -0
  68. drawspec-0.1.0/.claude/skills/init/assets/scripts/gate_evidence.py +208 -0
  69. drawspec-0.1.0/.claude/skills/init/assets/scripts/handle_sync.py +201 -0
  70. drawspec-0.1.0/.claude/skills/init/assets/scripts/issue_for_task.py +118 -0
  71. drawspec-0.1.0/.claude/skills/init/assets/scripts/issue_import.py +204 -0
  72. drawspec-0.1.0/.claude/skills/init/assets/scripts/query_status.py +206 -0
  73. drawspec-0.1.0/.claude/skills/init/assets/scripts/queue_hooks.py +573 -0
  74. drawspec-0.1.0/.claude/skills/init/assets/scripts/task_select.py +576 -0
  75. drawspec-0.1.0/.claude/skills/init/assets/session/handover.md +32 -0
  76. drawspec-0.1.0/.claude/skills/init/assets/workflows/arsenal-queue.yml +136 -0
  77. drawspec-0.1.0/.claude/skills/init/evals/loading_verification.json +11 -0
  78. drawspec-0.1.0/.claude/skills/init/scripts/init.py +993 -0
  79. drawspec-0.1.0/.claude/skills/mutmut-report/.arsenal-vendored +0 -0
  80. drawspec-0.1.0/.claude/skills/mutmut-report/SKILL.md +32 -0
  81. drawspec-0.1.0/.claude/skills/mutmut-report/evals/loading_verification.json +18 -0
  82. drawspec-0.1.0/.claude/skills/mutmut-report/scripts/analyze_mutmut.py +268 -0
  83. drawspec-0.1.0/.claude/skills/pypi-release/.arsenal-vendored +0 -0
  84. drawspec-0.1.0/.claude/skills/pypi-release/SKILL.md +103 -0
  85. drawspec-0.1.0/.claude/skills/pypi-release/evals/loading_verification.json +18 -0
  86. drawspec-0.1.0/.claude/skills/pypi-release/scripts/validate_release.py +142 -0
  87. drawspec-0.1.0/.claude/skills/python-bootstrap/.arsenal-vendored +0 -0
  88. drawspec-0.1.0/.claude/skills/python-bootstrap/SKILL.md +84 -0
  89. drawspec-0.1.0/.claude/skills/python-bootstrap/evals/loading_verification.json +18 -0
  90. drawspec-0.1.0/.claude/skills/python-bootstrap/references/canonical-config.md +102 -0
  91. drawspec-0.1.0/.claude/skills/python-bootstrap/scripts/analyze_project.py +157 -0
  92. drawspec-0.1.0/.claude/skills/queue-add/.arsenal-vendored +0 -0
  93. drawspec-0.1.0/.claude/skills/queue-add/SKILL.md +86 -0
  94. drawspec-0.1.0/.claude/skills/queue-add/evals/loading_verification.json +11 -0
  95. drawspec-0.1.0/.claude/skills/queue-add/references/payload-template.md +42 -0
  96. drawspec-0.1.0/.claude/skills/queue-add/scripts/new_task.py +224 -0
  97. drawspec-0.1.0/.claude/skills/queue-status/.arsenal-vendored +0 -0
  98. drawspec-0.1.0/.claude/skills/queue-status/SKILL.md +86 -0
  99. drawspec-0.1.0/.claude/skills/queue-status/evals/loading_verification.json +11 -0
  100. drawspec-0.1.0/.claude/skills/review/.arsenal-vendored +0 -0
  101. drawspec-0.1.0/.claude/skills/review/SKILL.md +67 -0
  102. drawspec-0.1.0/.claude/skills/review/evals/loading_verification.json +20 -0
  103. drawspec-0.1.0/.claude/skills/review/references/template.md +74 -0
  104. drawspec-0.1.0/.claude/skills/session-end/.arsenal-vendored +0 -0
  105. drawspec-0.1.0/.claude/skills/session-end/SKILL.md +133 -0
  106. drawspec-0.1.0/.claude/skills/session-end/evals/loading_verification.json +18 -0
  107. drawspec-0.1.0/.claude/skills/session-end/references/auto-fire-setup.md +129 -0
  108. drawspec-0.1.0/.claude/skills/session-end/references/handoff-mode.md +76 -0
  109. drawspec-0.1.0/.claude/skills/session-end/references/retrospective-rubric.md +120 -0
  110. drawspec-0.1.0/.claude/skills/session-end/scripts/create_handoff.py +82 -0
  111. drawspec-0.1.0/.claude/skills/session-end/scripts/query_session_history.py +278 -0
  112. drawspec-0.1.0/.claude/skills/ship/.arsenal-vendored +0 -0
  113. drawspec-0.1.0/.claude/skills/ship/SKILL.md +114 -0
  114. drawspec-0.1.0/.claude/skills/ship/evals/loading_verification.json +20 -0
  115. drawspec-0.1.0/.claude/skills/ship/references/template.md +149 -0
  116. drawspec-0.1.0/.claude/skills/specify/.arsenal-vendored +0 -0
  117. drawspec-0.1.0/.claude/skills/specify/SKILL.md +134 -0
  118. drawspec-0.1.0/.claude/skills/specify/evals/loading_verification.json +20 -0
  119. drawspec-0.1.0/.claude/skills/specify/references/template.md +83 -0
  120. drawspec-0.1.0/.claude/skills/specify/scripts/validate_spec.py +138 -0
  121. drawspec-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
  122. drawspec-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  123. drawspec-0.1.0/.github/ISSUE_TEMPLATE/kind_or_field_request.yml +40 -0
  124. drawspec-0.1.0/.github/dependabot.yml +20 -0
  125. drawspec-0.1.0/.github/pull_request_template.md +16 -0
  126. drawspec-0.1.0/.github/workflows/arsenal-queue.yml +136 -0
  127. drawspec-0.1.0/.github/workflows/ci.yml +85 -0
  128. drawspec-0.1.0/.github/workflows/release.yml +198 -0
  129. drawspec-0.1.0/.gitignore +249 -0
  130. drawspec-0.1.0/AGENTS.md +200 -0
  131. drawspec-0.1.0/CHANGELOG.md +437 -0
  132. drawspec-0.1.0/CLAUDE.md +23 -0
  133. drawspec-0.1.0/CONTRIBUTING.md +150 -0
  134. drawspec-0.1.0/LICENSE +21 -0
  135. drawspec-0.1.0/Makefile +51 -0
  136. drawspec-0.1.0/PKG-INFO +368 -0
  137. drawspec-0.1.0/README.md +328 -0
  138. drawspec-0.1.0/_config.yml +32 -0
  139. drawspec-0.1.0/arsenal/config.toml +44 -0
  140. drawspec-0.1.0/arsenal/session/handover.md +191 -0
  141. drawspec-0.1.0/arsenal/tasks/_history/lo-0727.md +59 -0
  142. drawspec-0.1.0/arsenal/tasks/_history/lo-0e20.md +37 -0
  143. drawspec-0.1.0/arsenal/tasks/_history/lo-0e91.md +71 -0
  144. drawspec-0.1.0/arsenal/tasks/_history/lo-1270.md +41 -0
  145. drawspec-0.1.0/arsenal/tasks/_history/lo-1291.md +32 -0
  146. drawspec-0.1.0/arsenal/tasks/_history/lo-1b55.md +41 -0
  147. drawspec-0.1.0/arsenal/tasks/_history/lo-1c11.md +70 -0
  148. drawspec-0.1.0/arsenal/tasks/_history/lo-1c47.md +36 -0
  149. drawspec-0.1.0/arsenal/tasks/_history/lo-1d28.md +60 -0
  150. drawspec-0.1.0/arsenal/tasks/_history/lo-21c8.md +90 -0
  151. drawspec-0.1.0/arsenal/tasks/_history/lo-2382.md +63 -0
  152. drawspec-0.1.0/arsenal/tasks/_history/lo-2f7f.md +36 -0
  153. drawspec-0.1.0/arsenal/tasks/_history/lo-2f92.md +79 -0
  154. drawspec-0.1.0/arsenal/tasks/_history/lo-30b0.md +35 -0
  155. drawspec-0.1.0/arsenal/tasks/_history/lo-38d8.md +38 -0
  156. drawspec-0.1.0/arsenal/tasks/_history/lo-3b60.md +128 -0
  157. drawspec-0.1.0/arsenal/tasks/_history/lo-3ecf.md +27 -0
  158. drawspec-0.1.0/arsenal/tasks/_history/lo-4c51.md +32 -0
  159. drawspec-0.1.0/arsenal/tasks/_history/lo-4e89.md +58 -0
  160. drawspec-0.1.0/arsenal/tasks/_history/lo-4f9b.md +37 -0
  161. drawspec-0.1.0/arsenal/tasks/_history/lo-533d.md +36 -0
  162. drawspec-0.1.0/arsenal/tasks/_history/lo-6e34.md +47 -0
  163. drawspec-0.1.0/arsenal/tasks/_history/lo-7bfe.md +37 -0
  164. drawspec-0.1.0/arsenal/tasks/_history/lo-825e.md +89 -0
  165. drawspec-0.1.0/arsenal/tasks/_history/lo-88b7.md +58 -0
  166. drawspec-0.1.0/arsenal/tasks/_history/lo-9dd6.md +36 -0
  167. drawspec-0.1.0/arsenal/tasks/_history/lo-a204.md +69 -0
  168. drawspec-0.1.0/arsenal/tasks/_history/lo-a63e.md +70 -0
  169. drawspec-0.1.0/arsenal/tasks/_history/lo-b569.md +36 -0
  170. drawspec-0.1.0/arsenal/tasks/_history/lo-b67b.md +41 -0
  171. drawspec-0.1.0/arsenal/tasks/_history/lo-b7a8.md +39 -0
  172. drawspec-0.1.0/arsenal/tasks/_history/lo-b94c.md +36 -0
  173. drawspec-0.1.0/arsenal/tasks/_history/lo-c107.md +35 -0
  174. drawspec-0.1.0/arsenal/tasks/_history/lo-dcd5.md +38 -0
  175. drawspec-0.1.0/arsenal/tasks/_history/lo-e854.md +22 -0
  176. drawspec-0.1.0/arsenal/tasks/_history/lo-e93c.md +37 -0
  177. drawspec-0.1.0/arsenal/tasks/_history/lo-ee92.md +41 -0
  178. drawspec-0.1.0/arsenal/tasks/_history/lo-f75a.md +37 -0
  179. drawspec-0.1.0/arsenal/tasks/_history/lo-fbbb.md +122 -0
  180. drawspec-0.1.0/arsenal/tasks/_migrated-history.md +42 -0
  181. drawspec-0.1.0/arsenal/tasks/lo-2158.md +88 -0
  182. drawspec-0.1.0/arsenal/tasks/lo-52fa.md +63 -0
  183. drawspec-0.1.0/arsenal/tasks/lo-666f.md +113 -0
  184. drawspec-0.1.0/arsenal/tasks/lo-70ef.md +87 -0
  185. drawspec-0.1.0/arsenal/tasks/lo-f0f8.md +107 -0
  186. drawspec-0.1.0/arsenal/tasks/t-5e82a719.md +17 -0
  187. drawspec-0.1.0/arsenal/tasks/t-ae407597.md +37 -0
  188. drawspec-0.1.0/arsenal/tasks/t-e783b178.md +27 -0
  189. drawspec-0.1.0/claude-arsenal/.bundle-version +1 -0
  190. drawspec-0.1.0/claude-arsenal/AGENTS.md +203 -0
  191. drawspec-0.1.0/claude-arsenal/agents/worker.md +174 -0
  192. drawspec-0.1.0/claude-arsenal/bin/budget_check.sh +107 -0
  193. drawspec-0.1.0/claude-arsenal/bin/check_skill_workshop_loaded.sh +65 -0
  194. drawspec-0.1.0/claude-arsenal/bin/check_update.sh +305 -0
  195. drawspec-0.1.0/claude-arsenal/bin/claim_task.sh +103 -0
  196. drawspec-0.1.0/claude-arsenal/bin/detect_surface.sh +49 -0
  197. drawspec-0.1.0/claude-arsenal/bin/gate_run.sh +369 -0
  198. drawspec-0.1.0/claude-arsenal/bin/gate_target.py +168 -0
  199. drawspec-0.1.0/claude-arsenal/bin/github_channel.sh +158 -0
  200. drawspec-0.1.0/claude-arsenal/bin/mark_skill_workshop_loaded.sh +35 -0
  201. drawspec-0.1.0/claude-arsenal/bin/mark_skill_workshop_loaded_from_prompt.sh +37 -0
  202. drawspec-0.1.0/claude-arsenal/bin/open_task_pr.sh +601 -0
  203. drawspec-0.1.0/claude-arsenal/bin/outline.sh +120 -0
  204. drawspec-0.1.0/claude-arsenal/bin/rebase_stack.sh +227 -0
  205. drawspec-0.1.0/claude-arsenal/bin/rescue_snapshot.sh +83 -0
  206. drawspec-0.1.0/claude-arsenal/bin/statusline_capture.sh +81 -0
  207. drawspec-0.1.0/claude-arsenal/bin/worker_postcheck.sh +185 -0
  208. drawspec-0.1.0/claude-arsenal/bin/workspace_list.sh +13 -0
  209. drawspec-0.1.0/claude-arsenal/bin/worktree_probe.sh +65 -0
  210. drawspec-0.1.0/claude-arsenal/references/claiming-internals.md +41 -0
  211. drawspec-0.1.0/claude-arsenal/references/evidence-gates.md +134 -0
  212. drawspec-0.1.0/claude-arsenal/references/github-automation.md +121 -0
  213. drawspec-0.1.0/claude-arsenal/references/queue-seeding.md +146 -0
  214. drawspec-0.1.0/claude-arsenal/references/quota-governance.md +29 -0
  215. drawspec-0.1.0/claude-arsenal/references/state-layout.md +82 -0
  216. drawspec-0.1.0/claude-arsenal/references/worker-loop.md +301 -0
  217. drawspec-0.1.0/claude-arsenal/scripts/arsenal_config.py +249 -0
  218. drawspec-0.1.0/claude-arsenal/scripts/arsenal_migrate.py +310 -0
  219. drawspec-0.1.0/claude-arsenal/scripts/create_reader.py +916 -0
  220. drawspec-0.1.0/claude-arsenal/scripts/gate_evidence.py +208 -0
  221. drawspec-0.1.0/claude-arsenal/scripts/handle_sync.py +201 -0
  222. drawspec-0.1.0/claude-arsenal/scripts/issue_for_task.py +118 -0
  223. drawspec-0.1.0/claude-arsenal/scripts/issue_import.py +204 -0
  224. drawspec-0.1.0/claude-arsenal/scripts/query_status.py +206 -0
  225. drawspec-0.1.0/claude-arsenal/scripts/queue_hooks.py +573 -0
  226. drawspec-0.1.0/claude-arsenal/scripts/task_select.py +576 -0
  227. drawspec-0.1.0/claude-arsenal/session/handover.md +32 -0
  228. drawspec-0.1.0/claude-arsenal/workflows/arsenal-queue.yml +136 -0
  229. drawspec-0.1.0/corpus/README.md +57 -0
  230. drawspec-0.1.0/corpus/fixtures/fixture-001.svg +23 -0
  231. drawspec-0.1.0/corpus/fixtures/fixture-002.svg +35 -0
  232. drawspec-0.1.0/corpus/fixtures/fixture-003.svg +29 -0
  233. drawspec-0.1.0/corpus/fixtures/fixture-004.svg +19 -0
  234. drawspec-0.1.0/corpus/fixtures/fixture-005.svg +39 -0
  235. drawspec-0.1.0/corpus/fixtures/fixture-006.svg +17 -0
  236. drawspec-0.1.0/corpus/fixtures/fixture-007.svg +17 -0
  237. drawspec-0.1.0/corpus/fixtures/fixture-008.svg +34 -0
  238. drawspec-0.1.0/corpus/fixtures/fixture-009.svg +34 -0
  239. drawspec-0.1.0/corpus/fixtures/fixture-010.svg +29 -0
  240. drawspec-0.1.0/corpus/fixtures/fixture-011.svg +28 -0
  241. drawspec-0.1.0/corpus/fixtures/fixture-012.svg +27 -0
  242. drawspec-0.1.0/corpus/fixtures/fixture-013.svg +32 -0
  243. drawspec-0.1.0/corpus/fixtures/fixture-014.svg +34 -0
  244. drawspec-0.1.0/corpus/fixtures/fixture-015.svg +17 -0
  245. drawspec-0.1.0/corpus/fixtures/fixture-016.svg +31 -0
  246. drawspec-0.1.0/corpus/fixtures/fixture-017.svg +41 -0
  247. drawspec-0.1.0/corpus/fixtures/fixture-018.svg +16 -0
  248. drawspec-0.1.0/corpus/fixtures/fixture-019.svg +22 -0
  249. drawspec-0.1.0/corpus/fixtures/fixture-020.svg +38 -0
  250. drawspec-0.1.0/corpus/fixtures/fixture-021.svg +43 -0
  251. drawspec-0.1.0/corpus/fixtures/fixture-022.svg +26 -0
  252. drawspec-0.1.0/corpus/fixtures/fixture-023.svg +25 -0
  253. drawspec-0.1.0/corpus/fixtures/fixture-024.svg +16 -0
  254. drawspec-0.1.0/corpus/fixtures/fixture-025.svg +37 -0
  255. drawspec-0.1.0/corpus/fixtures/fixture-026.svg +34 -0
  256. drawspec-0.1.0/corpus/fixtures/fixture-027.svg +39 -0
  257. drawspec-0.1.0/corpus/fixtures/fixture-028.svg +36 -0
  258. drawspec-0.1.0/corpus/fixtures/fixture-029.svg +28 -0
  259. drawspec-0.1.0/corpus/fixtures/fixture-030.svg +36 -0
  260. drawspec-0.1.0/corpus/fixtures/fixture-031.svg +20 -0
  261. drawspec-0.1.0/corpus/fixtures/fixture-032.svg +22 -0
  262. drawspec-0.1.0/corpus/fixtures/fixture-033.svg +34 -0
  263. drawspec-0.1.0/corpus/fixtures/fixture-034.svg +36 -0
  264. drawspec-0.1.0/corpus/fixtures/fixture-035.svg +39 -0
  265. drawspec-0.1.0/corpus/fixtures/fixture-036.svg +41 -0
  266. drawspec-0.1.0/corpus/fixtures/fixture-037.svg +19 -0
  267. drawspec-0.1.0/corpus/fixtures/fixture-038.svg +19 -0
  268. drawspec-0.1.0/corpus/fixtures/fixture-039.svg +40 -0
  269. drawspec-0.1.0/corpus/fixtures/fixture-040.svg +35 -0
  270. drawspec-0.1.0/corpus/fixtures/fixture-041.svg +28 -0
  271. drawspec-0.1.0/corpus/fixtures/fixture-042.svg +17 -0
  272. drawspec-0.1.0/corpus/fixtures/fixture-043.svg +31 -0
  273. drawspec-0.1.0/corpus/fixtures/fixture-044.svg +30 -0
  274. drawspec-0.1.0/corpus/fixtures/fixture-045.svg +19 -0
  275. drawspec-0.1.0/corpus/fixtures/fixture-046.svg +27 -0
  276. drawspec-0.1.0/corpus/fixtures/fixture-047.svg +30 -0
  277. drawspec-0.1.0/corpus/fixtures/fixture-048.svg +27 -0
  278. drawspec-0.1.0/corpus/fixtures/fixture-049.svg +50 -0
  279. drawspec-0.1.0/corpus/fixtures/fixture-050.svg +26 -0
  280. drawspec-0.1.0/corpus/fixtures/fixture-051.svg +14 -0
  281. drawspec-0.1.0/corpus/fixtures/fixture-052.svg +22 -0
  282. drawspec-0.1.0/corpus/fixtures/fixture-053.svg +16 -0
  283. drawspec-0.1.0/corpus/fixtures/fixture-054.svg +19 -0
  284. drawspec-0.1.0/corpus/fixtures/fixture-055.svg +28 -0
  285. drawspec-0.1.0/corpus/fixtures/fixture-056.svg +37 -0
  286. drawspec-0.1.0/corpus/fixtures/fixture-057.svg +25 -0
  287. drawspec-0.1.0/corpus/fixtures/fixture-058.svg +32 -0
  288. drawspec-0.1.0/corpus/fixtures/fixture-059.svg +24 -0
  289. drawspec-0.1.0/corpus/fixtures/fixture-060.svg +34 -0
  290. drawspec-0.1.0/corpus/fixtures/fixture-061.svg +22 -0
  291. drawspec-0.1.0/corpus/fixtures/fixture-062.svg +29 -0
  292. drawspec-0.1.0/corpus/fixtures/fixture-063.svg +30 -0
  293. drawspec-0.1.0/corpus/fixtures/fixture-064.svg +28 -0
  294. drawspec-0.1.0/corpus/fixtures/fixture-065.svg +30 -0
  295. drawspec-0.1.0/corpus/fixtures/fixture-066.svg +32 -0
  296. drawspec-0.1.0/corpus/fixtures/fixture-067.svg +34 -0
  297. drawspec-0.1.0/corpus/fixtures/fixture-068.svg +30 -0
  298. drawspec-0.1.0/corpus/fixtures/fixture-069.svg +27 -0
  299. drawspec-0.1.0/corpus/fixtures/fixture-070.svg +53 -0
  300. drawspec-0.1.0/corpus/fixtures/fixture-071.svg +35 -0
  301. drawspec-0.1.0/corpus/fixtures/fixture-072.svg +10 -0
  302. drawspec-0.1.0/corpus/fixtures/fixture-073.svg +24 -0
  303. drawspec-0.1.0/corpus/fixtures/fixture-074.svg +41 -0
  304. drawspec-0.1.0/corpus/fixtures/fixture-075.svg +23 -0
  305. drawspec-0.1.0/corpus/fixtures/fixture-076.svg +37 -0
  306. drawspec-0.1.0/corpus/fixtures/fixture-077.svg +33 -0
  307. drawspec-0.1.0/corpus/fixtures/fixture-078.svg +30 -0
  308. drawspec-0.1.0/corpus/fixtures/fixture-079.svg +23 -0
  309. drawspec-0.1.0/corpus/fixtures/fixture-080.svg +51 -0
  310. drawspec-0.1.0/corpus/fixtures/fixture-081.svg +38 -0
  311. drawspec-0.1.0/corpus/fixtures/fixture-082.svg +12 -0
  312. drawspec-0.1.0/corpus/fixtures/fixture-083.svg +27 -0
  313. drawspec-0.1.0/corpus/fixtures/fixture-084.svg +27 -0
  314. drawspec-0.1.0/corpus/fixtures/fixture-085.svg +33 -0
  315. drawspec-0.1.0/corpus/fixtures/fixture-086.svg +22 -0
  316. drawspec-0.1.0/corpus/fixtures/fixture-087.svg +28 -0
  317. drawspec-0.1.0/corpus/metrics.json +2716 -0
  318. drawspec-0.1.0/docs/brief.md +178 -0
  319. drawspec-0.1.0/docs/cli.md +162 -0
  320. drawspec-0.1.0/docs/format.md +789 -0
  321. drawspec-0.1.0/docs/gallery/board-migration.svg +1 -0
  322. drawspec-0.1.0/docs/gallery/board-onboarding.svg +1 -0
  323. drawspec-0.1.0/docs/gallery/board-retrospective.svg +1 -0
  324. drawspec-0.1.0/docs/gallery/board-story-map.svg +1 -0
  325. drawspec-0.1.0/docs/gallery/chart-accent.svg +1 -0
  326. drawspec-0.1.0/docs/gallery/chart-area.svg +1 -0
  327. drawspec-0.1.0/docs/gallery/chart-bars.svg +1 -0
  328. drawspec-0.1.0/docs/gallery/chart-brand-readings.svg +1 -0
  329. drawspec-0.1.0/docs/gallery/chart-complaints.svg +1 -0
  330. drawspec-0.1.0/docs/gallery/chart-responsibility.svg +1 -0
  331. drawspec-0.1.0/docs/gallery/chart-stacked.svg +1 -0
  332. drawspec-0.1.0/docs/gallery/columns-before-after.svg +1 -0
  333. drawspec-0.1.0/docs/gallery/columns-rise.svg +1 -0
  334. drawspec-0.1.0/docs/gallery/curve-burndown.svg +1 -0
  335. drawspec-0.1.0/docs/gallery/curve-hype.svg +1 -0
  336. drawspec-0.1.0/docs/gallery/curve-variance.svg +1 -0
  337. drawspec-0.1.0/docs/gallery/cycle-hub-flywheel.svg +1 -0
  338. drawspec-0.1.0/docs/gallery/cycle-hub-oncall.svg +1 -0
  339. drawspec-0.1.0/docs/gallery/cycle-hub-quality.svg +1 -0
  340. drawspec-0.1.0/docs/gallery/cycle-review.svg +1 -0
  341. drawspec-0.1.0/docs/gallery/cycle-wheel.svg +1 -0
  342. drawspec-0.1.0/docs/gallery/entities-enrolment.svg +1 -0
  343. drawspec-0.1.0/docs/gallery/entities-library.svg +1 -0
  344. drawspec-0.1.0/docs/gallery/entities-orders.svg +1 -0
  345. drawspec-0.1.0/docs/gallery/entities-shapes.svg +1 -0
  346. drawspec-0.1.0/docs/gallery/files-project.svg +1 -0
  347. drawspec-0.1.0/docs/gallery/files-text.svg +1 -0
  348. drawspec-0.1.0/docs/gallery/fishbone-backup.svg +1 -0
  349. drawspec-0.1.0/docs/gallery/fishbone-flaky-ci.svg +1 -0
  350. drawspec-0.1.0/docs/gallery/fishbone-late-orders.svg +1 -0
  351. drawspec-0.1.0/docs/gallery/fishbone-signups.svg +1 -0
  352. drawspec-0.1.0/docs/gallery/flow-accent.svg +1 -0
  353. drawspec-0.1.0/docs/gallery/flow-actor-handover.svg +1 -0
  354. drawspec-0.1.0/docs/gallery/flow-actors.svg +1 -0
  355. drawspec-0.1.0/docs/gallery/flow-bands.svg +1 -0
  356. drawspec-0.1.0/docs/gallery/flow-brand-release.svg +1 -0
  357. drawspec-0.1.0/docs/gallery/flow-critical-path.svg +1 -0
  358. drawspec-0.1.0/docs/gallery/flow-edge-roles.svg +1 -0
  359. drawspec-0.1.0/docs/gallery/flow-groups.svg +1 -0
  360. drawspec-0.1.0/docs/gallery/flow-hub.svg +1 -0
  361. drawspec-0.1.0/docs/gallery/flow-inventory.svg +1 -0
  362. drawspec-0.1.0/docs/gallery/flow-mesh.svg +1 -0
  363. drawspec-0.1.0/docs/gallery/flow-node-roles.svg +1 -0
  364. drawspec-0.1.0/docs/gallery/flow-retry.svg +1 -0
  365. drawspec-0.1.0/docs/gallery/flow-status-failover.svg +1 -0
  366. drawspec-0.1.0/docs/gallery/flow-status-search.svg +1 -0
  367. drawspec-0.1.0/docs/gallery/flow-triage.svg +1 -0
  368. drawspec-0.1.0/docs/gallery/flow-validation.svg +1 -0
  369. drawspec-0.1.0/docs/gallery/funnel-innovation.svg +1 -0
  370. drawspec-0.1.0/docs/gallery/gantt-critical-path.svg +1 -0
  371. drawspec-0.1.0/docs/gallery/gantt-migration.svg +1 -0
  372. drawspec-0.1.0/docs/gallery/gantt-semester.svg +1 -0
  373. drawspec-0.1.0/docs/gallery/gantt-upgrade.svg +1 -0
  374. drawspec-0.1.0/docs/gallery/index.html +315 -0
  375. drawspec-0.1.0/docs/gallery/journey-bug-report.svg +1 -0
  376. drawspec-0.1.0/docs/gallery/journey-first-week.svg +1 -0
  377. drawspec-0.1.0/docs/gallery/journey-outpatient.svg +1 -0
  378. drawspec-0.1.0/docs/gallery/journey-parking-permit.svg +1 -0
  379. drawspec-0.1.0/docs/gallery/lanes-disclosure.svg +1 -0
  380. drawspec-0.1.0/docs/gallery/lanes-expense.svg +1 -0
  381. drawspec-0.1.0/docs/gallery/lanes-onboarding.svg +1 -0
  382. drawspec-0.1.0/docs/gallery/lanes-tender.svg +1 -0
  383. drawspec-0.1.0/docs/gallery/matrix-process.svg +1 -0
  384. drawspec-0.1.0/docs/gallery/matrix-raid.svg +1 -0
  385. drawspec-0.1.0/docs/gallery/matrix-scale-ci.svg +1 -0
  386. drawspec-0.1.0/docs/gallery/matrix-scale-risk.svg +1 -0
  387. drawspec-0.1.0/docs/gallery/matrix-scale-skills.svg +1 -0
  388. drawspec-0.1.0/docs/gallery/pyramid-evidence.svg +1 -0
  389. drawspec-0.1.0/docs/gallery/pyramid-top-heavy.svg +1 -0
  390. drawspec-0.1.0/docs/gallery/quadrant-conflict.svg +1 -0
  391. drawspec-0.1.0/docs/gallery/rings-scope.svg +1 -0
  392. drawspec-0.1.0/docs/gallery/sankey-budget.svg +1 -0
  393. drawspec-0.1.0/docs/gallery/sankey-cores.svg +1 -0
  394. drawspec-0.1.0/docs/gallery/sankey-energy.svg +1 -0
  395. drawspec-0.1.0/docs/gallery/sankey-tickets.svg +1 -0
  396. drawspec-0.1.0/docs/gallery/scatter-pareto.svg +1 -0
  397. drawspec-0.1.0/docs/gallery/sequence-checkout.svg +1 -0
  398. drawspec-0.1.0/docs/gallery/sequence-dns.svg +1 -0
  399. drawspec-0.1.0/docs/gallery/sequence-drain.svg +1 -0
  400. drawspec-0.1.0/docs/gallery/sequence-upload.svg +1 -0
  401. drawspec-0.1.0/docs/gallery/stack-decisions.svg +1 -0
  402. drawspec-0.1.0/docs/gallery/states-brand-station.svg +1 -0
  403. drawspec-0.1.0/docs/gallery/states-breaker.svg +1 -0
  404. drawspec-0.1.0/docs/gallery/states-invoice.svg +1 -0
  405. drawspec-0.1.0/docs/gallery/states-process.svg +1 -0
  406. drawspec-0.1.0/docs/gallery/states-ticket.svg +1 -0
  407. drawspec-0.1.0/docs/gallery/timeline-disaster.svg +1 -0
  408. drawspec-0.1.0/docs/gallery/timeline-rise.svg +1 -0
  409. drawspec-0.1.0/docs/gallery/timeline-work.svg +1 -0
  410. drawspec-0.1.0/docs/gallery/tree-compartments.svg +1 -0
  411. drawspec-0.1.0/docs/gallery/tree-decisions.svg +1 -0
  412. drawspec-0.1.0/docs/gallery/tree-status-reorg.svg +1 -0
  413. drawspec-0.1.0/docs/gallery/treemap-bundle.svg +1 -0
  414. drawspec-0.1.0/docs/gallery/treemap-disk.svg +1 -0
  415. drawspec-0.1.0/docs/gallery/treemap-latency.svg +1 -0
  416. drawspec-0.1.0/docs/gallery/treemap-oncall.svg +1 -0
  417. drawspec-0.1.0/docs/gallery/venn-data-roles.svg +1 -0
  418. drawspec-0.1.0/docs/gallery/venn-frameworks.svg +1 -0
  419. drawspec-0.1.0/docs/gallery/venn-parity.svg +1 -0
  420. drawspec-0.1.0/docs/gallery/venn-telemetry.svg +1 -0
  421. drawspec-0.1.0/docs/guide.md +1404 -0
  422. drawspec-0.1.0/docs/hero.png +0 -0
  423. drawspec-0.1.0/docs/hero.svg +1 -0
  424. drawspec-0.1.0/docs/kinds-wanted.md +450 -0
  425. drawspec-0.1.0/docs/plan-round-five.md +349 -0
  426. drawspec-0.1.0/docs/plan-round-three.md +418 -0
  427. drawspec-0.1.0/docs/plan-round-two.md +214 -0
  428. drawspec-0.1.0/docs/proposals/README.md +96 -0
  429. drawspec-0.1.0/docs/proposals/board.md +191 -0
  430. drawspec-0.1.0/docs/proposals/coverage-vs-diagram-design.md +102 -0
  431. drawspec-0.1.0/docs/proposals/cycle-hub.md +151 -0
  432. drawspec-0.1.0/docs/proposals/entities.md +249 -0
  433. drawspec-0.1.0/docs/proposals/exports.md +77 -0
  434. drawspec-0.1.0/docs/proposals/filetree.md +32 -0
  435. drawspec-0.1.0/docs/proposals/fishbone.md +171 -0
  436. drawspec-0.1.0/docs/proposals/flow-status.md +141 -0
  437. drawspec-0.1.0/docs/proposals/gantt.md +215 -0
  438. drawspec-0.1.0/docs/proposals/journey.md +184 -0
  439. drawspec-0.1.0/docs/proposals/lanes.md +199 -0
  440. drawspec-0.1.0/docs/proposals/matrix-scale.md +168 -0
  441. drawspec-0.1.0/docs/proposals/sankey.md +218 -0
  442. drawspec-0.1.0/docs/proposals/sequence.md +245 -0
  443. drawspec-0.1.0/docs/proposals/states.md +236 -0
  444. drawspec-0.1.0/docs/proposals/theme-from.md +114 -0
  445. drawspec-0.1.0/docs/proposals/treemap.md +179 -0
  446. drawspec-0.1.0/docs/proposals/venn.md +153 -0
  447. drawspec-0.1.0/docs/reference/board-migration.json +21 -0
  448. drawspec-0.1.0/docs/reference/board-onboarding.json +32 -0
  449. drawspec-0.1.0/docs/reference/board-retrospective.json +18 -0
  450. drawspec-0.1.0/docs/reference/board-story-map.json +27 -0
  451. drawspec-0.1.0/docs/reference/brand/tidemark.css +40 -0
  452. drawspec-0.1.0/docs/reference/brand/tidemark.tokens.json +31 -0
  453. drawspec-0.1.0/docs/reference/brand/tidemark.toml +79 -0
  454. drawspec-0.1.0/docs/reference/chart-accent.json +16 -0
  455. drawspec-0.1.0/docs/reference/chart-area.json +24 -0
  456. drawspec-0.1.0/docs/reference/chart-bars.json +15 -0
  457. drawspec-0.1.0/docs/reference/chart-brand-readings.json +16 -0
  458. drawspec-0.1.0/docs/reference/chart-complaints.json +15 -0
  459. drawspec-0.1.0/docs/reference/chart-responsibility.json +63 -0
  460. drawspec-0.1.0/docs/reference/chart-stacked.json +15 -0
  461. drawspec-0.1.0/docs/reference/columns-before-after.json +11 -0
  462. drawspec-0.1.0/docs/reference/columns-rise.json +16 -0
  463. drawspec-0.1.0/docs/reference/curve-burndown.json +61 -0
  464. drawspec-0.1.0/docs/reference/curve-hype.json +57 -0
  465. drawspec-0.1.0/docs/reference/curve-variance.json +43 -0
  466. drawspec-0.1.0/docs/reference/cycle-hub-flywheel.json +22 -0
  467. drawspec-0.1.0/docs/reference/cycle-hub-oncall.json +22 -0
  468. drawspec-0.1.0/docs/reference/cycle-hub-quality.json +20 -0
  469. drawspec-0.1.0/docs/reference/cycle-review.json +22 -0
  470. drawspec-0.1.0/docs/reference/cycle-wheel.json +19 -0
  471. drawspec-0.1.0/docs/reference/entities-enrolment.json +22 -0
  472. drawspec-0.1.0/docs/reference/entities-library.json +18 -0
  473. drawspec-0.1.0/docs/reference/entities-orders.json +29 -0
  474. drawspec-0.1.0/docs/reference/entities-shapes.json +19 -0
  475. drawspec-0.1.0/docs/reference/files-project.json +20 -0
  476. drawspec-0.1.0/docs/reference/files-text.json +18 -0
  477. drawspec-0.1.0/docs/reference/fishbone-backup.json +23 -0
  478. drawspec-0.1.0/docs/reference/fishbone-flaky-ci.json +11 -0
  479. drawspec-0.1.0/docs/reference/fishbone-late-orders.json +15 -0
  480. drawspec-0.1.0/docs/reference/fishbone-signups.json +29 -0
  481. drawspec-0.1.0/docs/reference/flow-accent.json +23 -0
  482. drawspec-0.1.0/docs/reference/flow-actor-handover.json +19 -0
  483. drawspec-0.1.0/docs/reference/flow-actors.json +21 -0
  484. drawspec-0.1.0/docs/reference/flow-bands.json +31 -0
  485. drawspec-0.1.0/docs/reference/flow-brand-release.json +25 -0
  486. drawspec-0.1.0/docs/reference/flow-critical-path.json +20 -0
  487. drawspec-0.1.0/docs/reference/flow-edge-roles.json +102 -0
  488. drawspec-0.1.0/docs/reference/flow-groups.json +32 -0
  489. drawspec-0.1.0/docs/reference/flow-hub.json +19 -0
  490. drawspec-0.1.0/docs/reference/flow-inventory.json +31 -0
  491. drawspec-0.1.0/docs/reference/flow-mesh.json +30 -0
  492. drawspec-0.1.0/docs/reference/flow-node-roles.json +16 -0
  493. drawspec-0.1.0/docs/reference/flow-retry.json +22 -0
  494. drawspec-0.1.0/docs/reference/flow-status-failover.json +22 -0
  495. drawspec-0.1.0/docs/reference/flow-status-search.json +23 -0
  496. drawspec-0.1.0/docs/reference/flow-triage.json +18 -0
  497. drawspec-0.1.0/docs/reference/flow-validation.json +26 -0
  498. drawspec-0.1.0/docs/reference/funnel-innovation.json +12 -0
  499. drawspec-0.1.0/docs/reference/gantt-critical-path.json +22 -0
  500. drawspec-0.1.0/docs/reference/gantt-migration.json +27 -0
  501. drawspec-0.1.0/docs/reference/gantt-semester.json +26 -0
  502. drawspec-0.1.0/docs/reference/gantt-upgrade.json +22 -0
  503. drawspec-0.1.0/docs/reference/journey-bug-report.json +14 -0
  504. drawspec-0.1.0/docs/reference/journey-first-week.json +28 -0
  505. drawspec-0.1.0/docs/reference/journey-outpatient.json +43 -0
  506. drawspec-0.1.0/docs/reference/journey-parking-permit.json +35 -0
  507. drawspec-0.1.0/docs/reference/lanes-disclosure.json +26 -0
  508. drawspec-0.1.0/docs/reference/lanes-expense.json +22 -0
  509. drawspec-0.1.0/docs/reference/lanes-onboarding.json +25 -0
  510. drawspec-0.1.0/docs/reference/lanes-tender.json +25 -0
  511. drawspec-0.1.0/docs/reference/matrix-process.json +28 -0
  512. drawspec-0.1.0/docs/reference/matrix-raid.json +130 -0
  513. drawspec-0.1.0/docs/reference/matrix-scale-ci.json +33 -0
  514. drawspec-0.1.0/docs/reference/matrix-scale-risk.json +26 -0
  515. drawspec-0.1.0/docs/reference/matrix-scale-skills.json +28 -0
  516. drawspec-0.1.0/docs/reference/pyramid-evidence.json +12 -0
  517. drawspec-0.1.0/docs/reference/pyramid-top-heavy.json +12 -0
  518. drawspec-0.1.0/docs/reference/quadrant-conflict.json +17 -0
  519. drawspec-0.1.0/docs/reference/rendered/cycle-review-grandalf-down.svg +1 -0
  520. drawspec-0.1.0/docs/reference/rendered/cycle-review-grandalf-right.svg +1 -0
  521. drawspec-0.1.0/docs/reference/rendered/cycle-review-layered-down.svg +1 -0
  522. drawspec-0.1.0/docs/reference/rendered/cycle-review-layered-right.svg +1 -0
  523. drawspec-0.1.0/docs/reference/rendered/flow-validation-grandalf-down.svg +1 -0
  524. drawspec-0.1.0/docs/reference/rendered/flow-validation-grandalf-right.svg +1 -0
  525. drawspec-0.1.0/docs/reference/rendered/flow-validation-layered-down.svg +1 -0
  526. drawspec-0.1.0/docs/reference/rendered/flow-validation-layered-right.svg +1 -0
  527. drawspec-0.1.0/docs/reference/rendered/tree-decisions-grandalf-down.svg +1 -0
  528. drawspec-0.1.0/docs/reference/rendered/tree-decisions-grandalf-right.svg +1 -0
  529. drawspec-0.1.0/docs/reference/rendered/tree-decisions-layered-down.svg +1 -0
  530. drawspec-0.1.0/docs/reference/rendered/tree-decisions-layered-right.svg +1 -0
  531. drawspec-0.1.0/docs/reference/rings-scope.json +19 -0
  532. drawspec-0.1.0/docs/reference/sankey-budget.json +26 -0
  533. drawspec-0.1.0/docs/reference/sankey-cores.json +20 -0
  534. drawspec-0.1.0/docs/reference/sankey-energy.json +30 -0
  535. drawspec-0.1.0/docs/reference/sankey-tickets.json +28 -0
  536. drawspec-0.1.0/docs/reference/scatter-pareto.json +22 -0
  537. drawspec-0.1.0/docs/reference/sequence-checkout.json +33 -0
  538. drawspec-0.1.0/docs/reference/sequence-dns.json +24 -0
  539. drawspec-0.1.0/docs/reference/sequence-drain.json +24 -0
  540. drawspec-0.1.0/docs/reference/sequence-upload.json +29 -0
  541. drawspec-0.1.0/docs/reference/stack-decisions.json +12 -0
  542. drawspec-0.1.0/docs/reference/states-brand-station.json +26 -0
  543. drawspec-0.1.0/docs/reference/states-breaker.json +19 -0
  544. drawspec-0.1.0/docs/reference/states-invoice.json +26 -0
  545. drawspec-0.1.0/docs/reference/states-process.json +22 -0
  546. drawspec-0.1.0/docs/reference/states-ticket.json +28 -0
  547. drawspec-0.1.0/docs/reference/timeline-disaster.json +54 -0
  548. drawspec-0.1.0/docs/reference/timeline-rise.json +14 -0
  549. drawspec-0.1.0/docs/reference/timeline-work.json +14 -0
  550. drawspec-0.1.0/docs/reference/tree-compartments.json +37 -0
  551. drawspec-0.1.0/docs/reference/tree-decisions.json +32 -0
  552. drawspec-0.1.0/docs/reference/tree-status-reorg.json +26 -0
  553. drawspec-0.1.0/docs/reference/treemap-bundle.json +15 -0
  554. drawspec-0.1.0/docs/reference/treemap-disk.json +18 -0
  555. drawspec-0.1.0/docs/reference/treemap-latency.json +23 -0
  556. drawspec-0.1.0/docs/reference/treemap-oncall.json +14 -0
  557. drawspec-0.1.0/docs/reference/venn-data-roles.json +16 -0
  558. drawspec-0.1.0/docs/reference/venn-frameworks.json +14 -0
  559. drawspec-0.1.0/docs/reference/venn-parity.json +17 -0
  560. drawspec-0.1.0/docs/reference/venn-telemetry.json +19 -0
  561. drawspec-0.1.0/docs/review-2026-10.md +56 -0
  562. drawspec-0.1.0/docs/theme-requirements.md +161 -0
  563. drawspec-0.1.0/docs/theme.md +286 -0
  564. drawspec-0.1.0/llms.txt +34 -0
  565. drawspec-0.1.0/pyproject.toml +157 -0
  566. drawspec-0.1.0/schema/drawspec-v1.schema.json +3489 -0
  567. drawspec-0.1.0/skills/drawspec/SKILL.md +32 -0
  568. drawspec-0.1.0/src/drawspec/__init__.py +57 -0
  569. drawspec-0.1.0/src/drawspec/brand.py +1184 -0
  570. drawspec-0.1.0/src/drawspec/charts.py +1790 -0
  571. drawspec-0.1.0/src/drawspec/clearance.py +330 -0
  572. drawspec-0.1.0/src/drawspec/cli.py +466 -0
  573. drawspec-0.1.0/src/drawspec/emit.py +666 -0
  574. drawspec-0.1.0/src/drawspec/errors.py +97 -0
  575. drawspec-0.1.0/src/drawspec/examples.py +339 -0
  576. drawspec-0.1.0/src/drawspec/export.py +177 -0
  577. drawspec-0.1.0/src/drawspec/filetree.py +294 -0
  578. drawspec-0.1.0/src/drawspec/fonts/LICENSE +57 -0
  579. drawspec-0.1.0/src/drawspec/fonts/mono-bold.ttf +0 -0
  580. drawspec-0.1.0/src/drawspec/fonts/mono.ttf +0 -0
  581. drawspec-0.1.0/src/drawspec/fonts/sans-bold.ttf +0 -0
  582. drawspec-0.1.0/src/drawspec/fonts/sans.ttf +0 -0
  583. drawspec-0.1.0/src/drawspec/fonts/serif-bold.ttf +0 -0
  584. drawspec-0.1.0/src/drawspec/fonts/serif.ttf +0 -0
  585. drawspec-0.1.0/src/drawspec/geometry.py +657 -0
  586. drawspec-0.1.0/src/drawspec/kinds/__init__.py +143 -0
  587. drawspec-0.1.0/src/drawspec/kinds/board.py +351 -0
  588. drawspec-0.1.0/src/drawspec/kinds/common.py +441 -0
  589. drawspec-0.1.0/src/drawspec/kinds/containers.py +551 -0
  590. drawspec-0.1.0/src/drawspec/kinds/cycle.py +760 -0
  591. drawspec-0.1.0/src/drawspec/kinds/entities.py +990 -0
  592. drawspec-0.1.0/src/drawspec/kinds/files.py +492 -0
  593. drawspec-0.1.0/src/drawspec/kinds/fishbone.py +524 -0
  594. drawspec-0.1.0/src/drawspec/kinds/gantt.py +635 -0
  595. drawspec-0.1.0/src/drawspec/kinds/graph.py +1244 -0
  596. drawspec-0.1.0/src/drawspec/kinds/grid.py +830 -0
  597. drawspec-0.1.0/src/drawspec/kinds/journey.py +352 -0
  598. drawspec-0.1.0/src/drawspec/kinds/lanes.py +614 -0
  599. drawspec-0.1.0/src/drawspec/kinds/sankey.py +664 -0
  600. drawspec-0.1.0/src/drawspec/kinds/sequence.py +772 -0
  601. drawspec-0.1.0/src/drawspec/kinds/shape.py +771 -0
  602. drawspec-0.1.0/src/drawspec/kinds/treemap.py +714 -0
  603. drawspec-0.1.0/src/drawspec/kinds/venn.py +467 -0
  604. drawspec-0.1.0/src/drawspec/layout/__init__.py +44 -0
  605. drawspec-0.1.0/src/drawspec/layout/base.py +542 -0
  606. drawspec-0.1.0/src/drawspec/layout/grandalf_engine.py +271 -0
  607. drawspec-0.1.0/src/drawspec/layout/layered.py +363 -0
  608. drawspec-0.1.0/src/drawspec/legend.py +226 -0
  609. drawspec-0.1.0/src/drawspec/mcp.py +344 -0
  610. drawspec-0.1.0/src/drawspec/py.typed +0 -0
  611. drawspec-0.1.0/src/drawspec/render.py +289 -0
  612. drawspec-0.1.0/src/drawspec/routing.py +2782 -0
  613. drawspec-0.1.0/src/drawspec/scene.py +390 -0
  614. drawspec-0.1.0/src/drawspec/schema.py +6991 -0
  615. drawspec-0.1.0/src/drawspec/text/__init__.py +25 -0
  616. drawspec-0.1.0/src/drawspec/text/fontlib.py +494 -0
  617. drawspec-0.1.0/src/drawspec/text/measure.py +210 -0
  618. drawspec-0.1.0/src/drawspec/text/wrap.py +383 -0
  619. drawspec-0.1.0/src/drawspec/theme.py +1796 -0
  620. drawspec-0.1.0/src/drawspec/themes/accent.toml +95 -0
  621. drawspec-0.1.0/src/drawspec/themes/compartment.toml +26 -0
  622. drawspec-0.1.0/src/drawspec/themes/default.toml +356 -0
  623. drawspec-0.1.0/src/drawspec/themes/wheel.toml +23 -0
  624. drawspec-0.1.0/status/plan.md +349 -0
  625. drawspec-0.1.0/status/spec-annotated.md +688 -0
  626. drawspec-0.1.0/status/spec-reader.html +1336 -0
  627. drawspec-0.1.0/status/specification.md +623 -0
  628. drawspec-0.1.0/tests/test_acceptance.py +475 -0
  629. drawspec-0.1.0/tests/test_actor.py +262 -0
  630. drawspec-0.1.0/tests/test_box.py +557 -0
  631. drawspec-0.1.0/tests/test_brand.py +405 -0
  632. drawspec-0.1.0/tests/test_caption.py +202 -0
  633. drawspec-0.1.0/tests/test_clearance.py +159 -0
  634. drawspec-0.1.0/tests/test_cli.py +338 -0
  635. drawspec-0.1.0/tests/test_clipping.py +171 -0
  636. drawspec-0.1.0/tests/test_docs.py +242 -0
  637. drawspec-0.1.0/tests/test_embedding.py +289 -0
  638. drawspec-0.1.0/tests/test_emit.py +543 -0
  639. drawspec-0.1.0/tests/test_export.py +290 -0
  640. drawspec-0.1.0/tests/test_failure_families.py +506 -0
  641. drawspec-0.1.0/tests/test_gallery.py +127 -0
  642. drawspec-0.1.0/tests/test_kinds_board.py +416 -0
  643. drawspec-0.1.0/tests/test_kinds_chart.py +1480 -0
  644. drawspec-0.1.0/tests/test_kinds_containers.py +580 -0
  645. drawspec-0.1.0/tests/test_kinds_cycle.py +719 -0
  646. drawspec-0.1.0/tests/test_kinds_entities.py +579 -0
  647. drawspec-0.1.0/tests/test_kinds_files.py +270 -0
  648. drawspec-0.1.0/tests/test_kinds_fishbone.py +306 -0
  649. drawspec-0.1.0/tests/test_kinds_gantt.py +492 -0
  650. drawspec-0.1.0/tests/test_kinds_graph.py +482 -0
  651. drawspec-0.1.0/tests/test_kinds_grid.py +1116 -0
  652. drawspec-0.1.0/tests/test_kinds_journey.py +334 -0
  653. drawspec-0.1.0/tests/test_kinds_lanes.py +418 -0
  654. drawspec-0.1.0/tests/test_kinds_sankey.py +468 -0
  655. drawspec-0.1.0/tests/test_kinds_sequence.py +499 -0
  656. drawspec-0.1.0/tests/test_kinds_shape.py +753 -0
  657. drawspec-0.1.0/tests/test_kinds_states.py +543 -0
  658. drawspec-0.1.0/tests/test_kinds_treemap.py +442 -0
  659. drawspec-0.1.0/tests/test_kinds_venn.py +262 -0
  660. drawspec-0.1.0/tests/test_labels.py +263 -0
  661. drawspec-0.1.0/tests/test_layout.py +577 -0
  662. drawspec-0.1.0/tests/test_layout_spike.py +183 -0
  663. drawspec-0.1.0/tests/test_lead_rule.py +132 -0
  664. drawspec-0.1.0/tests/test_legend.py +300 -0
  665. drawspec-0.1.0/tests/test_margins.py +144 -0
  666. drawspec-0.1.0/tests/test_mcp.py +259 -0
  667. drawspec-0.1.0/tests/test_measure.py +337 -0
  668. drawspec-0.1.0/tests/test_packaging.py +149 -0
  669. drawspec-0.1.0/tests/test_readability.py +160 -0
  670. drawspec-0.1.0/tests/test_routing.py +809 -0
  671. drawspec-0.1.0/tests/test_routing_crossings.py +335 -0
  672. drawspec-0.1.0/tests/test_schema.py +733 -0
  673. drawspec-0.1.0/tests/test_self_loops.py +158 -0
  674. drawspec-0.1.0/tests/test_skill.py +55 -0
  675. drawspec-0.1.0/tests/test_status.py +273 -0
  676. drawspec-0.1.0/tests/test_theme.py +708 -0
  677. drawspec-0.1.0/tests/test_wrap.py +367 -0
  678. drawspec-0.1.0/tools/clipping.py +299 -0
  679. drawspec-0.1.0/tools/collisions.py +356 -0
  680. drawspec-0.1.0/tools/compare.py +690 -0
  681. drawspec-0.1.0/tools/docs.py +793 -0
  682. drawspec-0.1.0/tools/gallery.py +164 -0
  683. drawspec-0.1.0/tools/hero.py +640 -0
  684. drawspec-0.1.0/tools/spike_layout.py +301 -0
  685. drawspec-0.1.0/tools/subset_fonts.py +113 -0
  686. drawspec-0.1.0/uv.lock +1107 -0
@@ -0,0 +1,40 @@
1
+ {
2
+ "statusLine": {
3
+ "type": "command",
4
+ "command": "bash claude-arsenal/bin/statusline_capture.sh"
5
+ },
6
+ "hooks": {
7
+ "PreToolUse": [
8
+ {
9
+ "hooks": [
10
+ {
11
+ "type": "command",
12
+ "command": "bash claude-arsenal/bin/check_skill_workshop_loaded.sh"
13
+ }
14
+ ],
15
+ "matcher": "Edit|Write|MultiEdit|Bash"
16
+ }
17
+ ],
18
+ "PostToolUse": [
19
+ {
20
+ "hooks": [
21
+ {
22
+ "type": "command",
23
+ "command": "bash claude-arsenal/bin/mark_skill_workshop_loaded.sh"
24
+ }
25
+ ],
26
+ "matcher": "Skill"
27
+ }
28
+ ],
29
+ "UserPromptSubmit": [
30
+ {
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "bash claude-arsenal/bin/mark_skill_workshop_loaded_from_prompt.sh"
35
+ }
36
+ ]
37
+ }
38
+ ]
39
+ }
40
+ }
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: continue
3
+ description: When the user wants to resume work or run the worker loop — picks the next unblocked task, optionally scoped by tag(s) and/or a workspace, or matched by title text. Use /continue [TAG … | WORKSPACE | search-text]. Do NOT use before running init.
4
+ user-invocable: true
5
+ argument-hint: "[TAG … | WORKSPACE | search-text]"
6
+ metadata:
7
+ type: workflow
8
+ ---
9
+
10
+ # continue
11
+
12
+ Resumes session work: reads the task graph from the repository, picks the next unblocked
13
+ task, claims it so no other agent can take it, and runs the worker loop. Optionally scoped
14
+ by tag(s) and/or a workspace, or matched against a fuzzy task title.
15
+
16
+ CANARY: continue-loaded-2026-06-13-fb78d23e-b2c3d4e5f6a7b8c9
17
+
18
+ ## When to load
19
+
20
+ Load this skill when:
21
+
22
+ - The user types `/continue`, "continue", "resume", "run the workers", or "WORKSPACE: Continue".
23
+ - The session needs to pick up where a previous session left off.
24
+ - The user provides a workspace name or task search string after the command.
25
+
26
+ ## The loop
27
+
28
+ **1. Fetch the task issues.** List issues labelled `arsenal:task`, open **and** closed, using whatever GitHub access
29
+ this surface offers — the built-in GitHub tools, `gh`, or REST — and save the JSON. Closed ones matter: a closed-as-completed issue is what marks a
30
+ dependency satisfied.
31
+
32
+ Request `number`, `title`, `state`, `labels`, `assignees` — **not `body`**. The resolver reads the
33
+ `arsenal-task:` line when a body is present and falls back to matching the title against the task
34
+ files, so bodies change no answer here while dominating the cost: on a 40-issue board they are the
35
+ difference between ~9k and ~1.2k tokens, spent before the first task is even chosen.
36
+
37
+ Run `github_channel.sh --detect` (in `claude-arsenal/bin/`); it prints `gh`, `rest`, or `none`.
38
+
39
+ `none` means no scriptable channel exists here; make the call with the built-in GitHub
40
+ tools instead. It is not a reason to skip the step — a skipped step here means the session
41
+ picks up work another agent is already doing.
42
+
43
+ **2. Ask for the next task.** One call, one line of output:
44
+
45
+ Run `task_select.py` (in `claude-arsenal/scripts/`) with the saved issues:
46
+
47
+ ```
48
+ task_select.py --tasks-dir arsenal/tasks --issues /tmp/issues.json \
49
+ --capability surface:cli --workspace FRONTEND --tag CLI
50
+ ```
51
+
52
+ Ordering is a computation, not a judgement — deps, priority, capabilities and scope are
53
+ all applied by the script, so the decision costs one line of context rather than a
54
+ protocol re-read each session.
55
+
56
+ **3. Check nobody else holds it.** Before claiming, read the task's issue and skip it if
57
+ it is closed, has an assignee, or carries `arsenal:claimed`. This is not a race — a human
58
+ who assigned themselves did so long ago — so a plain check settles it.
59
+
60
+ **4. Claim it.**
61
+
62
+ Run `claim_task.sh <task-id>` (in `claude-arsenal/bin/`).
63
+
64
+ Obey the result verbatim:
65
+
66
+ - `won <ref>` → the task is claimed. Nobody else can hold it: creating the ref is a
67
+ compare-and-swap that GitHub itself arbitrates.
68
+ - `lost` → another agent got there first. Drop it, take the next task. This is normal, not
69
+ an error.
70
+ - `manual POST <path> <body>` → no scriptable channel; make that exact call with the
71
+ built-in GitHub tools. **201 means won, 422 means lost.**
72
+ - `error:` → misconfiguration. Stop and surface it to the user.
73
+
74
+ Never work around a `lost` by claiming a different ref or re-running with another attempt
75
+ number. The whole point of the ref is that exactly one agent proceeds; routing around it
76
+ recreates the double-claims it exists to prevent.
77
+
78
+ Then mark the issue so a human can see which agent holds it: self-assign, add
79
+ `arsenal:claimed`, and comment with the session id from `CLAUDE_CODE_REMOTE_SESSION_ID`
80
+ — a `cse_…` value that doubles as a session URL, so the claim is clickable.
81
+
82
+ **5. Work the task, then open its PR with `open_task_pr.sh`.** It resolves the task's
83
+ issue number, writes `Closes #<issue>` into the PR body *and* the commit message, and
84
+ moves the task file into `arsenal/tasks/_history/` inside the same diff. Merging therefore
85
+ closes the issue, archives the task, and unblocks its dependents in one act — there is no
86
+ "update the queue" step to forget, and nothing left to verify afterwards.
87
+
88
+ Both keyword sites matter: the body form fires on a merge into the default branch, the
89
+ commit form survives a squash and covers a stacked PR based on another branch.
90
+
91
+ **6. Loop back to step 2.**
92
+
93
+ ## Scoping
94
+
95
+ ```bash
96
+ # Bare-word tokens are order-independent and resolved by membership:
97
+ # known workspace -> workspace filter (at most one)
98
+ # known tag -> tag filter (multiple tags are ANDed)
99
+ # anything else -> fuzzy title search
100
+ /continue CLI FRONTEND # tag CLI AND workspace FRONTEND
101
+ /continue CLI WEB # tag CLI AND tag WEB
102
+ /continue FRONTEND # workspace only
103
+ ```
104
+
105
+ `/continue CLI FRONTEND` and `/continue FRONTEND CLI` resolve to the same scope. A task
106
+ qualifies only if it carries **every** requested tag and matches the workspace when one is
107
+ given.
108
+
109
+ ## Gotchas
110
+
111
+ - **`WORKSPACE: Continue`** as natural language (e.g. "FRONTEND: Continue") is equivalent
112
+ to `/continue FRONTEND`.
113
+ - **Task files are read from the default branch.** That is what makes every agent compute
114
+ the same graph regardless of the branch it is working on. A task file on an unmerged
115
+ branch is not yet in the queue.
116
+ - **A task with no issue handle is invisible.** Where `.github/workflows/arsenal-queue.yml`
117
+ is installed, GitHub opens the handle as soon as the task file lands, so this should
118
+ never be outstanding. Where it is not, run `handle_sync.py` (in `claude-arsenal/scripts/`)
119
+ to list task files that need one, and create them. Missing handles delay work; they never
120
+ corrupt it — and `open_task_pr.sh` refuses to open a PR for a task it cannot link, rather
121
+ than merging one that closes nothing.
122
+ - **`gate: false` in the selector output means the task has no runnable gate.** A prose-only
123
+ gate executes nothing and therefore passes everything. Fix the task file before working
124
+ it, rather than completing something that nothing checked.
125
+ - **Blocked workspace**: if a scoped selection is empty but the global queue has tasks,
126
+ report what is blocking and offer to fall back to the global queue.
127
+ - **Retries claim a new ref.** A crashed session blocks nothing: attempt 2 claims
128
+ `<id>.a2`. Past `max-attempts` the task stops being offered and needs a human — read the
129
+ `## Failure notes` in the task file before re-dispatching.
@@ -0,0 +1,11 @@
1
+ {
2
+ "skill": "continue",
3
+ "canary": "continue-loaded-2026-06-13-fb78d23e-b2c3d4e5f6a7b8c9",
4
+ "negative_control": "this-fact-is-false-and-must-not-appear-in-the-skill-body",
5
+ "load_prompts": [
6
+ "Use the continue skill to resume work on the queue"
7
+ ],
8
+ "no_load_prompts": [
9
+ "Generic prompt that should NOT activate continue"
10
+ ]
11
+ }
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: coverage-gaps
3
+ description: Use whenever the user wants to turn coverage.py's coverage.json into a ranked list of the highest-value missing tests — surfaces contiguous missing-line runs marking whole untested functions or branches. A cheap line-coverage pass below mutmut-report. Triggers — "what tests am I missing", "where are the coverage gaps". Do NOT use to run the suite or generate the report (run coverage / pytest --cov first), or for non-Python coverage.
4
+ argument-hint: "--input coverage.json --limit N"
5
+ user-invocable: true
6
+ ---
7
+
8
+ # coverage-gaps
9
+
10
+ Turn an existing coverage.py report into a ranked, actionable list of the tests
11
+ worth writing next.
12
+
13
+ CANARY: coverage-gaps-loaded-2026-06-04-ea39c2b5-b32fe2b1b5ae5e96
14
+
15
+ ## When to load
16
+
17
+ Load when a `coverage.json` already exists and the question is *which* gaps to
18
+ fill first. This is the cheap, line-level first pass; once line coverage is
19
+ healthy and the question shifts to whether the existing tests actually *assert*
20
+ behavior, escalate to the `mutmut-report` skill (mutation testing).
21
+
22
+ ## Step 1 — Ensure a JSON report exists
23
+
24
+ The script reads coverage.py's JSON export, not the `.coverage` SQLite file or
25
+ the terminal table. If only a run has happened, produce the JSON first:
26
+
27
+ ```bash
28
+ coverage json # after `coverage run -m pytest`
29
+ # or in one shot:
30
+ pytest --cov=PKG --cov-report=json # writes coverage.json
31
+ ```
32
+
33
+ ## Step 2 — Rank the gaps
34
+
35
+ ```bash
36
+ python3 "${CLAUDE_SKILL_DIR}/scripts/analyze_coverage.py" --input coverage.json --limit 20
37
+ ```
38
+
39
+ Output is JSON: `total_percent_covered`, `files_with_gaps`, and a ranked `gaps`
40
+ list. Each entry carries `missing_count`, `percent_covered`, `missing_branches`,
41
+ `largest_run`, and `missing_runs` (inclusive `[start, end]` line ranges).
42
+
43
+ ## Step 3 — Propose tests
44
+
45
+ Read the source at each `missing_runs` range and report concisely:
46
+
47
+ 1. The top files by uncovered lines, and for each, what the largest run is —
48
+ open the source at those lines to name the untested function or branch.
49
+ 2. For each high-value gap: the specific test to add (which function, which
50
+ input, which branch).
51
+ 3. Note which gaps are low-value (scattered single lines — often defensive
52
+ `raise` / logging paths) and can be deferred or marked `# pragma: no cover`.
53
+
54
+ Lead with the 2-3 tests worth writing now. Do not re-explain what coverage is.
55
+
56
+ ## Gotchas
57
+
58
+ - **No JSON report yet.** The script needs `coverage.json`; a bare `coverage
59
+ run` leaves only the `.coverage` SQLite db and a terminal summary. Run
60
+ `coverage json` (or `--cov-report=json`) first, or the script exits 2.
61
+ - **100% line coverage is not 100% tested.** A line counts as covered the
62
+ moment it executes, even if nothing asserts its result. Treat this skill as
63
+ the floor; for assertion quality, escalate to the `mutmut-report` skill.
64
+ - **Big contiguous run ≠ always the priority.** A long `missing_run` can be a
65
+ generated block, a `__repr__`, or a `if TYPE_CHECKING:` import island. Open
66
+ the source before recommending — rank by what the code *does*, not just line
67
+ count.
68
+ - **Branch gaps hide inside covered files.** A file at high line coverage can
69
+ still have untaken branches; check `missing_branches`, which only populates
70
+ when the report was generated with branch coverage (`--cov-branch` or
71
+ `[tool.coverage.run] branch = true`).
72
+ - **Stale report after a refactor.** Line numbers in an old `coverage.json`
73
+ drift from current source. Regenerate the report against the current tree
74
+ before trusting the ranges.
@@ -0,0 +1,18 @@
1
+ {
2
+ "skill": "coverage-gaps",
3
+ "canary": "coverage-gaps-loaded-2026-06-04-ea39c2b5-b32fe2b1b5ae5e96",
4
+ "negative_control": "the coverage-gaps skill runs the pytest suite and generates the coverage.json report itself before analyzing it",
5
+ "load_prompts": [
6
+ "Which tests am I missing the most?",
7
+ "Analyze my coverage and tell me where the gaps are",
8
+ "Where is the most valuable untested code in this project?",
9
+ "Triage my coverage.json for the highest-value tests to add",
10
+ "/coverage-gaps --input coverage.json --limit 15"
11
+ ],
12
+ "no_load_prompts": [
13
+ "Run the test suite with coverage",
14
+ "Which surviving mutants are real test gaps?",
15
+ "Publish this package to PyPI",
16
+ "Set up pyproject and ruff for this repo"
17
+ ]
18
+ }
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env python3
2
+ """analyze_coverage.py — rank a coverage.py report's gaps by test value.
3
+
4
+ Reads a coverage.py JSON report (produced by `coverage json`) and emits a
5
+ ranked JSON list of the files with the most to gain from new tests. For each
6
+ file it reports the uncovered line count, the percent covered, and the
7
+ *contiguous* missing-line runs — a run of consecutive uncovered lines usually
8
+ marks a whole untested function or branch, which is higher-value than the
9
+ scattered single lines that tend to be defensive error handlers.
10
+
11
+ JSON-only on stdout; errors on stderr. Exit 0 when the report builds; exit 2 on
12
+ a usage error (e.g. the input file is missing — run `coverage json` first).
13
+ """
14
+
15
+ import argparse
16
+ import json
17
+ import sys
18
+ from pathlib import Path
19
+
20
+
21
+ def contiguous_runs(lines: list[int]) -> list[list[int]]:
22
+ """Collapse a sorted line list into [start, end] inclusive runs."""
23
+ runs: list[list[int]] = []
24
+ for line in sorted(lines):
25
+ if runs and line == runs[-1][1] + 1:
26
+ runs[-1][1] = line
27
+ else:
28
+ runs.append([line, line])
29
+ return runs
30
+
31
+
32
+ def build_report(data: dict, limit: int) -> dict:
33
+ files_data = data.get("files")
34
+ files = []
35
+ for path, info in (files_data if isinstance(files_data, dict) else {}).items():
36
+ if not isinstance(info, dict):
37
+ continue
38
+ missing = info.get("missing_lines", [])
39
+ missing_branches = info.get("missing_branches", [])
40
+ # Include files with missing lines OR with missing branch coverage (a file
41
+ # at 100% line coverage can still have untaken branches — see Gotchas).
42
+ if not missing and not missing_branches:
43
+ continue
44
+ summary = info.get("summary") or {}
45
+ runs = contiguous_runs(missing)
46
+ files.append(
47
+ {
48
+ "file": path,
49
+ "percent_covered": round(summary.get("percent_covered", 0.0), 1),
50
+ "missing_count": len(missing),
51
+ "missing_branches": len(missing_branches),
52
+ "largest_run": max((r[1] - r[0] + 1 for r in runs), default=0),
53
+ "missing_runs": runs,
54
+ }
55
+ )
56
+
57
+ # Most uncovered lines first; break ties toward the least-covered file.
58
+ files.sort(key=lambda f: (-f["missing_count"], f["percent_covered"]))
59
+ totals = data.get("totals", {})
60
+ return {
61
+ "total_percent_covered": round(totals.get("percent_covered", 0.0), 1),
62
+ "files_with_gaps": len(files),
63
+ "gaps": files[:limit],
64
+ }
65
+
66
+
67
+ def main() -> int:
68
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
69
+ parser.add_argument(
70
+ "--input",
71
+ default="coverage.json",
72
+ help="coverage.py JSON report (default: coverage.json). Generate with `coverage json`.",
73
+ )
74
+ parser.add_argument("--limit", type=int, default=20, help="Max files to report (default: 20)")
75
+ args = parser.parse_args()
76
+
77
+ path = Path(args.input)
78
+ if not path.exists():
79
+ print(
80
+ f"✗ {path} not found — run `coverage json` (or `pytest --cov ... "
81
+ "--cov-report json`) first",
82
+ file=sys.stderr,
83
+ )
84
+ return 2
85
+ try:
86
+ data = json.loads(path.read_text(encoding="utf-8"))
87
+ except json.JSONDecodeError as exc:
88
+ print(f"✗ {path} is not valid JSON: {exc}", file=sys.stderr)
89
+ return 2
90
+ except OSError as exc:
91
+ print(f"✗ failed to read {path}: {exc}", file=sys.stderr)
92
+ return 2
93
+
94
+ if not isinstance(data, dict):
95
+ print(f"✗ {path} is not a coverage.py report (expected a JSON object)", file=sys.stderr)
96
+ return 2
97
+
98
+ print(json.dumps(build_report(data, args.limit), indent=2))
99
+ return 0
100
+
101
+
102
+ if __name__ == "__main__":
103
+ sys.exit(main())
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: dep-upgrade
3
+ description: Use whenever a uv-managed Python project's dependencies need upgrading safely — the uv lock --upgrade, pip-audit, test-gate, classify-breakage runbook, splitting lockfile churn into direct vs transitive. Triggers — "upgrade the dependencies", "check for vulnerable dependencies". Do NOT use to add one dependency (just uv add), scaffold tooling (see python-bootstrap), or publish (see pypi-release).
4
+ argument-hint: "uv.lock.bak uv.lock"
5
+ user-invocable: true
6
+ ---
7
+
8
+ # dep-upgrade
9
+
10
+ Upgrade a uv-managed project's dependencies under a safety net: snapshot, lock,
11
+ audit for CVEs, gate on the test suite, then classify whatever broke.
12
+
13
+ CANARY: dep-upgrade-loaded-2026-06-04-ea39c2b5-719c61e6e84e1453
14
+
15
+ ## When to load
16
+
17
+ Load when the task is a deliberate dependency *upgrade* of a uv project —
18
+ refreshing the lockfile, chasing CVEs, or pulling in newer versions. For adding
19
+ one new package, plain `uv add` is enough; for scaffolding tooling defer to the
20
+ `python-bootstrap` skill.
21
+
22
+ ## Step 1 — Snapshot, then upgrade
23
+
24
+ Keep the pre-upgrade lockfile so the change is reviewable and revertible:
25
+
26
+ ```bash
27
+ cp uv.lock uv.lock.bak
28
+ uv lock --upgrade # refresh every pin to the latest compatible release
29
+ uv sync # install the new resolution into the environment
30
+ ```
31
+
32
+ To upgrade a single package instead of everything: `uv lock --upgrade-package NAME`.
33
+
34
+ ## Step 2 — See what actually changed
35
+
36
+ ```bash
37
+ python3 "${CLAUDE_SKILL_DIR}/scripts/compare_lockfile.py" uv.lock.bak uv.lock
38
+ ```
39
+
40
+ The JSON splits `changed` into `direct` (declared in `pyproject.toml`) and
41
+ transitive, with `direct_changes` / `transitive_changes` counts, plus `added`
42
+ and `removed`. Transitive bumps are where "passes locally, breaks on a clean
43
+ install" hides — read them, do not skim.
44
+
45
+ ## Step 3 — Audit for CVEs
46
+
47
+ ```bash
48
+ uvx pip-audit # scans the resolved environment for known CVEs
49
+ ```
50
+
51
+ Treat a finding as a reason to upgrade *further* (to the patched version), not
52
+ to pin backwards onto the vulnerable release. Note any advisory with no fixed
53
+ version as a risk to surface.
54
+
55
+ ## Step 4 — Test gate + classify
56
+
57
+ Run the project's full suite against the new resolution:
58
+
59
+ ```bash
60
+ make test # or: uv run pytest
61
+ ```
62
+
63
+ If green, report the upgrade with the direct/transitive breakdown and any CVE
64
+ findings. If red, classify each failure: a behavior change in a direct dep
65
+ (read its changelog), a transitive bump that surfaced a latent bug, or a real
66
+ incompatibility that needs a constraint. Pin the minimum necessary in
67
+ `pyproject.toml`, re-lock, and re-run — never weaken the test to pass.
68
+
69
+ ## Gotchas
70
+
71
+ - **Transitive churn breaks clean installs only.** A transitive bump can pass
72
+ every local test yet fail `uv sync` on a fresh machine or minimal CI image,
73
+ because the local cache still holds the old wheel. Always check
74
+ `transitive_changes` and re-resolve in a clean environment before trusting
75
+ green.
76
+ - **`uv lock --upgrade` moves everything at once.** A repo-wide upgrade folds
77
+ dozens of changes into one diff, making the culprit of a new failure hard to
78
+ isolate. Prefer `--upgrade-package NAME` for a targeted bump when chasing a
79
+ specific CVE or feature.
80
+ - **Pinning backwards to dodge a CVE.** Constraining a package to an old,
81
+ vulnerable version to "make pip-audit quiet" reintroduces the vulnerability.
82
+ Move forward to the fixed release; only pin backwards with an explicit,
83
+ documented reason.
84
+ - **Lockfile churn buries the signal.** `git diff uv.lock` after an upgrade is
85
+ enormous and mostly hash noise. Use the script's direct/transitive summary to
86
+ find the handful of changes that matter rather than reading the raw diff.
87
+ - **Skipping `uv sync` after `uv lock`.** `uv lock --upgrade` rewrites the
88
+ lockfile but does not touch the environment; tests run against the *old*
89
+ installed versions and falsely pass. Always `uv sync` before the test gate.
@@ -0,0 +1,18 @@
1
+ {
2
+ "skill": "dep-upgrade",
3
+ "canary": "dep-upgrade-loaded-2026-06-04-ea39c2b5-719c61e6e84e1453",
4
+ "negative_control": "the dep-upgrade skill pins dependencies backwards to their previous versions to silence pip-audit findings",
5
+ "load_prompts": [
6
+ "Upgrade all the dependencies in this project",
7
+ "Run uv lock --upgrade and make sure nothing broke",
8
+ "Check for vulnerable dependencies and patch them",
9
+ "Bump our packages and tell me what changed",
10
+ "Is anything out of date or insecure in this repo?"
11
+ ],
12
+ "no_load_prompts": [
13
+ "Add the requests package to this project",
14
+ "Set up pyproject and ruff for this repo",
15
+ "Publish this package to PyPI",
16
+ "Which tests am I missing the most?"
17
+ ]
18
+ }
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python3
2
+ """compare_lockfile.py — diff two uv.lock files and classify what changed.
3
+
4
+ Takes the lockfile from before an upgrade and the lockfile after, and emits a
5
+ JSON summary on stdout: which packages were added, removed, or version-bumped,
6
+ and for each change whether the package is a *direct* dependency (declared in
7
+ pyproject.toml) or *transitive* (pulled in by something else). Transitive churn
8
+ is the usual source of "passes locally, breaks on a clean install" surprises,
9
+ so separating it from the deps actually requested is the point.
10
+
11
+ JSON-only on stdout; errors on stderr. Exit 0 when the diff builds; exit 2 on a
12
+ usage error (missing file, malformed TOML).
13
+ """
14
+
15
+ import argparse
16
+ import json
17
+ import re
18
+ import sys
19
+ import tomllib
20
+ from pathlib import Path
21
+
22
+ NAME_RE = re.compile(r"^([A-Za-z0-9._-]+)")
23
+
24
+
25
+ def load_lock(path: Path) -> dict[str, str]:
26
+ with path.open("rb") as fh:
27
+ data = tomllib.load(fh)
28
+ packages = data.get("package", [])
29
+ if not isinstance(packages, list):
30
+ return {}
31
+ return {
32
+ pkg["name"]: pkg.get("version", "")
33
+ for pkg in packages
34
+ if isinstance(pkg, dict) and "name" in pkg
35
+ }
36
+
37
+
38
+ def direct_dep_names(pyproject: Path) -> set[str]:
39
+ """Canonical names of every dependency declared in pyproject.toml."""
40
+ if not pyproject.exists():
41
+ return set()
42
+ with pyproject.open("rb") as fh:
43
+ data = tomllib.load(fh)
44
+
45
+ specs: list[str] = []
46
+ project = data.get("project", {})
47
+ if isinstance(project, dict):
48
+ deps = project.get("dependencies", [])
49
+ if isinstance(deps, list):
50
+ specs += deps
51
+ opt_deps = project.get("optional-dependencies", {})
52
+ if isinstance(opt_deps, dict):
53
+ for group in opt_deps.values():
54
+ if isinstance(group, list):
55
+ specs += group
56
+ dep_groups = data.get("dependency-groups", {})
57
+ if isinstance(dep_groups, dict):
58
+ for group in dep_groups.values():
59
+ if isinstance(group, list):
60
+ specs += group
61
+ tool = data.get("tool", {})
62
+ uv = tool.get("uv", {}) if isinstance(tool, dict) else {}
63
+ if isinstance(uv, dict):
64
+ dev_deps = uv.get("dev-dependencies", [])
65
+ if isinstance(dev_deps, list):
66
+ specs += dev_deps
67
+
68
+ names = set()
69
+ for spec in specs:
70
+ if not isinstance(spec, str):
71
+ continue
72
+ match = NAME_RE.match(spec.strip())
73
+ if match:
74
+ names.add(match.group(1).lower().replace("_", "-"))
75
+ return names
76
+
77
+
78
+ def build_report(before: dict[str, str], after: dict[str, str], direct: set[str]) -> dict:
79
+ def is_direct(name: str) -> bool:
80
+ return name.lower().replace("_", "-") in direct
81
+
82
+ changed = [
83
+ {"name": n, "from": before[n], "to": after[n], "direct": is_direct(n)}
84
+ for n in sorted(before.keys() & after.keys())
85
+ if before[n] != after[n]
86
+ ]
87
+ added = [
88
+ {"name": n, "version": after[n], "direct": is_direct(n)}
89
+ for n in sorted(after.keys() - before.keys())
90
+ ]
91
+ removed = [{"name": n, "version": before[n]} for n in sorted(before.keys() - after.keys())]
92
+ return {
93
+ "changed": changed,
94
+ "added": added,
95
+ "removed": removed,
96
+ "direct_changes": sum(1 for c in changed if c["direct"]),
97
+ "transitive_changes": sum(1 for c in changed if not c["direct"]),
98
+ }
99
+
100
+
101
+ def main() -> int:
102
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
103
+ parser.add_argument("before", help="uv.lock from before the upgrade (e.g. uv.lock.bak)")
104
+ parser.add_argument("after", help="uv.lock after the upgrade")
105
+ parser.add_argument(
106
+ "--input",
107
+ default="pyproject.toml",
108
+ help="pyproject.toml used to classify direct vs transitive (default: pyproject.toml)",
109
+ )
110
+ args = parser.parse_args()
111
+
112
+ try:
113
+ before = load_lock(Path(args.before))
114
+ after = load_lock(Path(args.after))
115
+ direct = direct_dep_names(Path(args.input))
116
+ except FileNotFoundError as exc:
117
+ print(f"✗ {exc}", file=sys.stderr)
118
+ return 2
119
+ except tomllib.TOMLDecodeError as exc:
120
+ print(f"✗ malformed TOML: {exc}", file=sys.stderr)
121
+ return 2
122
+ except OSError as exc:
123
+ print(f"✗ failed to read file: {exc}", file=sys.stderr)
124
+ return 2
125
+
126
+ report = build_report(before, after, direct)
127
+ print(json.dumps(report, indent=2))
128
+ return 0
129
+
130
+
131
+ if __name__ == "__main__":
132
+ sys.exit(main())
File without changes