@litfamily/litclaude 1.0.10 → 1.0.13

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 (718) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +436 -45
  3. package/README_ko-KR.md +403 -17
  4. package/bin/install-ownership.mjs +155 -18
  5. package/bin/litclaude-ai.js +91 -9
  6. package/docs/ab/S11-baseline-desktop.webp +0 -0
  7. package/docs/ab/S11-baseline-phone.webp +0 -0
  8. package/docs/ab/S11-litclaude-desktop.webp +0 -0
  9. package/docs/ab/S11-litclaude-phone.webp +0 -0
  10. package/docs/ab/S3-baseline-desktop.webp +0 -0
  11. package/docs/ab/S3-baseline-phone.webp +0 -0
  12. package/docs/ab/S3-litclaude-desktop.webp +0 -0
  13. package/docs/ab/S3-litclaude-phone.webp +0 -0
  14. package/docs/ab/S4-baseline-desktop.webp +0 -0
  15. package/docs/ab/S4-baseline-phone.webp +0 -0
  16. package/docs/ab/S4-litclaude-desktop.webp +0 -0
  17. package/docs/ab/S4-litclaude-phone.webp +0 -0
  18. package/docs/ab/S5-baseline-pages.webp +0 -0
  19. package/docs/ab/S5-baseline-slides.webp +0 -0
  20. package/docs/ab/S5-litclaude-pages.webp +0 -0
  21. package/docs/ab/S5-litclaude-slides.webp +0 -0
  22. package/docs/ab/S7-litclaude-diagram.webp +0 -0
  23. package/docs/ab/S8-baseline-slides.webp +0 -0
  24. package/docs/ab/S8-litclaude-slides.webp +0 -0
  25. package/docs/ab/S9-litclaude-pages.webp +0 -0
  26. package/docs/agents.md +10 -7
  27. package/docs/assets/cover-motion-still.webp +0 -0
  28. package/docs/assets/cover-motion.webp +0 -0
  29. package/docs/assets/readme/badge-version.svg +1 -1
  30. package/docs/assets/skills/autoconference.webp +0 -0
  31. package/docs/assets/skills/automatic-checks.webp +0 -0
  32. package/docs/assets/skills/autoresearch.webp +0 -0
  33. package/docs/assets/skills/browser-drive.webp +0 -0
  34. package/docs/assets/skills/debugging.webp +0 -0
  35. package/docs/assets/skills/deep-interview.webp +0 -0
  36. package/docs/assets/skills/frontend-ui-ux.webp +0 -0
  37. package/docs/assets/skills/lit-burnoff-file.webp +0 -0
  38. package/docs/assets/skills/lit-burnoff.webp +0 -0
  39. package/docs/assets/skills/lit-code.webp +0 -0
  40. package/docs/assets/skills/lit-commit.webp +0 -0
  41. package/docs/assets/skills/lit-comprehend.webp +0 -0
  42. package/docs/assets/skills/lit-crucible.webp +0 -0
  43. package/docs/assets/skills/lit-diagram-drawer.webp +0 -0
  44. package/docs/assets/skills/lit-docx.webp +0 -0
  45. package/docs/assets/skills/lit-handoff.webp +0 -0
  46. package/docs/assets/skills/lit-humanizer.webp +0 -0
  47. package/docs/assets/skills/lit-init.webp +0 -0
  48. package/docs/assets/skills/lit-loop.webp +0 -0
  49. package/docs/assets/skills/lit-plan.webp +0 -0
  50. package/docs/assets/skills/lit-pptx.webp +0 -0
  51. package/docs/assets/skills/lit-recap.webp +0 -0
  52. package/docs/assets/skills/lit-scientific-visualization.webp +0 -0
  53. package/docs/assets/skills/lit-team.webp +0 -0
  54. package/docs/assets/skills/lit-typographic-motion.webp +0 -0
  55. package/docs/assets/skills/litgoal.webp +0 -0
  56. package/docs/assets/skills/litresearch.webp +0 -0
  57. package/docs/assets/skills/litwork.webp +0 -0
  58. package/docs/assets/skills/lsp-setup.webp +0 -0
  59. package/docs/assets/skills/readme-studio.webp +0 -0
  60. package/docs/assets/skills/refactor.webp +0 -0
  61. package/docs/assets/skills/review-work.webp +0 -0
  62. package/docs/assets/skills/start-work.webp +0 -0
  63. package/docs/assets/skills/structural-search.webp +0 -0
  64. package/docs/assets/skills/visual-qa.webp +0 -0
  65. package/docs/assets/skills/wikify.webp +0 -0
  66. package/docs/hooks.md +185 -41
  67. package/docs/migration.md +6 -3
  68. package/docs/privacy.md +6 -1
  69. package/package.json +4 -2
  70. package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
  71. package/plugins/litclaude/agents/korean-prose-editor.md +1 -0
  72. package/plugins/litclaude/agents/korean-style-analyzer.md +1 -0
  73. package/plugins/litclaude/agents/meaning-preservation-auditor.md +1 -0
  74. package/plugins/litclaude/agents/native-flow-reviewer.md +1 -0
  75. package/plugins/litclaude/agents/polish-orchestrator.md +1 -0
  76. package/plugins/litclaude/bin/litclaude-hook.js +347 -35
  77. package/plugins/litclaude/bin/litclaude-hud.js +29 -1
  78. package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
  79. package/plugins/litclaude/bundled-rules/lit-humanizer.md +14 -0
  80. package/plugins/litclaude/commands/korean-ai-slop-remover.md +2 -2
  81. package/plugins/litclaude/commands/lit-comprehend.md +11 -11
  82. package/plugins/litclaude/commands/lit-humanizer.md +75 -0
  83. package/plugins/litclaude/commands/lit-korean.md +4 -130
  84. package/plugins/litclaude/commands/litresearch.md +12 -10
  85. package/plugins/litclaude/hooks/hooks.json +1 -1
  86. package/plugins/litclaude/lib/canonical-runtime-commitments.mjs +2 -2
  87. package/plugins/litclaude/lib/canonical-skill-catalog.mjs +5 -1
  88. package/plugins/litclaude/lib/canonical-skill-resources.mjs +618 -13
  89. package/plugins/litclaude/lib/deliverable-hedge-guard.mjs +256 -350
  90. package/plugins/litclaude/lib/hud-accent-palette.mjs +33 -0
  91. package/plugins/litclaude/lib/interface-mode.mjs +33 -0
  92. package/plugins/litclaude/lib/interface-probe-gate.mjs +125 -0
  93. package/plugins/litclaude/lib/jev-skill-hint.mjs +445 -0
  94. package/plugins/litclaude/lib/motion-render-gate.mjs +164 -0
  95. package/plugins/litclaude/lib/mutated-file-paths.mjs +32 -1
  96. package/plugins/litclaude/lib/office-runtime-lock/package-lock.json +745 -0
  97. package/plugins/litclaude/lib/office-runtime-lock/package.json +12 -0
  98. package/plugins/litclaude/lib/office-runtime-lock/requirements.lock +15 -0
  99. package/plugins/litclaude/lib/office-runtime.mjs +255 -0
  100. package/plugins/litclaude/lib/office_data.py +493 -0
  101. package/plugins/litclaude/lib/office_runtime_bootstrap.py +61 -0
  102. package/plugins/litclaude/lib/ooxml_integrity.py +199 -0
  103. package/plugins/litclaude/lib/rename-aliases.mjs +3 -1
  104. package/plugins/litclaude/lib/render_pages.py +105 -0
  105. package/plugins/litclaude/skills/autoconference/SKILL.md +2 -0
  106. package/plugins/litclaude/skills/browser-drive/SKILL.md +19 -6
  107. package/plugins/litclaude/skills/browser-drive/scripts/capability-probe.mjs +44 -8
  108. package/plugins/litclaude/skills/frontend-ui-ux/ATTRIBUTION.md +26 -0
  109. package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +50 -16
  110. package/plugins/litclaude/skills/frontend-ui-ux/examples/phase-3-readme-ab/README.md +9 -0
  111. package/plugins/litclaude/skills/frontend-ui-ux/references/complete-contract.md +32 -6
  112. package/plugins/litclaude/skills/frontend-ui-ux/references/craft-floor.md +257 -0
  113. package/plugins/litclaude/skills/frontend-ui-ux/references/default-editorial-pixel.json +6 -0
  114. package/plugins/litclaude/skills/frontend-ui-ux/references/interaction-motion.md +34 -88
  115. package/plugins/litclaude/skills/frontend-ui-ux/references/motion-guide.md +130 -0
  116. package/plugins/litclaude/skills/frontend-ui-ux/references/slop-register.md +150 -0
  117. package/plugins/litclaude/skills/frontend-ui-ux/references/visual-reconstruction.md +39 -85
  118. package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +1534 -0
  119. package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +141 -0
  120. package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-server.mjs +57 -0
  121. package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +129 -0
  122. package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe.mjs +316 -0
  123. package/plugins/litclaude/skills/lit-comprehend/SKILL.md +34 -43
  124. package/plugins/litclaude/skills/lit-comprehend/references/artifact-template.md +5 -44
  125. package/plugins/litclaude/skills/lit-comprehend/scripts/verify-explainer.mjs +6 -16
  126. package/plugins/litclaude/skills/lit-diagram-drawer/NOTICE +33 -0
  127. package/plugins/litclaude/skills/lit-diagram-drawer/SKILL.md +123 -0
  128. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-dark.html +1 -0
  129. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-full.html +1 -0
  130. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-light.html +1 -0
  131. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-dark.html +1 -0
  132. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-full.html +1 -0
  133. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-light.html +1 -0
  134. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-dark.html +1 -0
  135. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-full.html +1 -0
  136. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-light.html +1 -0
  137. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-dark.html +1 -0
  138. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-full.html +1 -0
  139. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-light.html +1 -0
  140. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-dark.html +1 -0
  141. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-full.html +1 -0
  142. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-light.html +1 -0
  143. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-dark.html +1 -0
  144. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-full.html +1 -0
  145. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-light.html +1 -0
  146. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-dark.html +1 -0
  147. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-full.html +1 -0
  148. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-light.html +1 -0
  149. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-dark.html +1 -0
  150. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-full.html +1 -0
  151. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-light.html +1 -0
  152. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-dark.html +1 -0
  153. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-full.html +1 -0
  154. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-light.html +1 -0
  155. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-dark.html +1 -0
  156. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-full.html +1 -0
  157. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-light.html +1 -0
  158. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-dark.html +1 -0
  159. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-full.html +1 -0
  160. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-light.html +1 -0
  161. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-dark.html +1 -0
  162. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-full.html +1 -0
  163. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-light.html +1 -0
  164. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-dark.html +1 -0
  165. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-full.html +1 -0
  166. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-light.html +1 -0
  167. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-dark.html +1 -0
  168. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-full.html +1 -0
  169. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-light.html +1 -0
  170. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-dark.html +1 -0
  171. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-full.html +1 -0
  172. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-light.html +1 -0
  173. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-dark.html +1 -0
  174. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-full.html +1 -0
  175. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-light.html +1 -0
  176. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-dark.html +1 -0
  177. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-full.html +1 -0
  178. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-light.html +1 -0
  179. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-dark.html +1 -0
  180. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-full.html +1 -0
  181. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-light.html +1 -0
  182. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-dark.html +1 -0
  183. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-full.html +1 -0
  184. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-light.html +1 -0
  185. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-dark.html +1 -0
  186. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-full.html +1 -0
  187. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-light.html +1 -0
  188. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-dark.html +1 -0
  189. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-full.html +1 -0
  190. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-light.html +1 -0
  191. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-dark.html +1 -0
  192. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-full.html +1 -0
  193. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-light.html +1 -0
  194. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-dark.html +1 -0
  195. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-full.html +1 -0
  196. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-light.html +1 -0
  197. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-dark.html +1 -0
  198. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-full.html +1 -0
  199. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-light.html +1 -0
  200. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-dark.html +1 -0
  201. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-full.html +1 -0
  202. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-light.html +1 -0
  203. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-dark.html +1 -0
  204. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-full.html +1 -0
  205. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-light.html +1 -0
  206. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-dark.html +1 -0
  207. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-full.html +1 -0
  208. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-light.html +1 -0
  209. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-dark.html +1 -0
  210. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-full.html +1 -0
  211. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-light.html +1 -0
  212. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-dark.html +1 -0
  213. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-full.html +1 -0
  214. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-light.html +1 -0
  215. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-dark.html +1 -0
  216. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-full.html +1 -0
  217. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-light.html +1 -0
  218. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-dark.html +1 -0
  219. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-full.html +1 -0
  220. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-light.html +1 -0
  221. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-dark.html +1 -0
  222. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-full.html +1 -0
  223. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-light.html +1 -0
  224. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-dark.html +1 -0
  225. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-full.html +1 -0
  226. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-light.html +1 -0
  227. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-dark.html +1 -0
  228. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-full.html +1 -0
  229. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-light.html +1 -0
  230. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-dark.html +1 -0
  231. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-full.html +1 -0
  232. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-light.html +1 -0
  233. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-dark.html +1 -0
  234. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-full.html +1 -0
  235. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-light.html +1 -0
  236. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-dark.html +1 -0
  237. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-full.html +1 -0
  238. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-light.html +1 -0
  239. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-dark.html +1 -0
  240. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-full.html +1 -0
  241. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-light.html +1 -0
  242. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-dark.html +1 -0
  243. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-full.html +1 -0
  244. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-light.html +1 -0
  245. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-dark.html +1 -0
  246. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-full.html +1 -0
  247. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-light.html +1 -0
  248. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-dark.html +1 -0
  249. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-full.html +1 -0
  250. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-light.html +1 -0
  251. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-dark.html +1 -0
  252. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-full.html +1 -0
  253. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-light.html +1 -0
  254. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-dark.html +1 -0
  255. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-full.html +1 -0
  256. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-light.html +1 -0
  257. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-dark.html +1 -0
  258. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-full.html +1 -0
  259. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-light.html +1 -0
  260. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-dark.html +1 -0
  261. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-full.html +1 -0
  262. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-light.html +1 -0
  263. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-dark.html +1 -0
  264. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-full.html +1 -0
  265. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-light.html +1 -0
  266. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-dark.html +1 -0
  267. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-full.html +1 -0
  268. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-light.html +1 -0
  269. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-dark.html +1 -0
  270. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-full.html +1 -0
  271. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-light.html +1 -0
  272. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-dark.html +1 -0
  273. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-full.html +1 -0
  274. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-dark.html +1 -0
  275. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-full.html +1 -0
  276. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-light.html +1 -0
  277. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-light.html +1 -0
  278. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-dark.html +1 -0
  279. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-full.html +1 -0
  280. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-light.html +1 -0
  281. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-dark.html +1 -0
  282. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-full.html +1 -0
  283. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-light.html +1 -0
  284. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-dark.html +1 -0
  285. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-full.html +1 -0
  286. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-light.html +1 -0
  287. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-dark.html +1 -0
  288. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-full.html +1 -0
  289. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-light.html +1 -0
  290. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-dark.html +1 -0
  291. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-full.html +1 -0
  292. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-light.html +1 -0
  293. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-dark.html +1 -0
  294. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-full.html +1 -0
  295. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-light.html +1 -0
  296. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-dark.html +1 -0
  297. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-full.html +1 -0
  298. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-light.html +1 -0
  299. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-dark.html +1 -0
  300. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-full.html +1 -0
  301. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-light.html +1 -0
  302. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-dark.html +1 -0
  303. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-full.html +1 -0
  304. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-light.html +1 -0
  305. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-dark.html +1 -0
  306. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-full.html +1 -0
  307. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-light.html +1 -0
  308. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-dark.html +1 -0
  309. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-full.html +1 -0
  310. package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-light.html +1 -0
  311. package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/OFL.txt +94 -0
  312. package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/PretendardVariable.woff2 +0 -0
  313. package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/provenance.json +22 -0
  314. package/plugins/litclaude/skills/lit-diagram-drawer/assets/icons.html +231 -0
  315. package/plugins/litclaude/skills/lit-diagram-drawer/assets/index.html +1 -0
  316. package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/devicon-MIT.txt +20 -0
  317. package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/diagram-design-MIT.txt +21 -0
  318. package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/log-z-MIT.txt +21 -0
  319. package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/simple-icons-CC0.md +30 -0
  320. package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/tabler-MIT.txt +21 -0
  321. package/plugins/litclaude/skills/lit-diagram-drawer/examples/01-service-architecture/after.html +1 -0
  322. package/plugins/litclaude/skills/lit-diagram-drawer/examples/01-service-architecture/brief.md +33 -0
  323. package/plugins/litclaude/skills/lit-diagram-drawer/examples/02-release-decision/after.html +1 -0
  324. package/plugins/litclaude/skills/lit-diagram-drawer/examples/02-release-decision/brief.md +18 -0
  325. package/plugins/litclaude/skills/lit-diagram-drawer/examples/03-data-retention/after.html +1 -0
  326. package/plugins/litclaude/skills/lit-diagram-drawer/examples/03-data-retention/brief.md +19 -0
  327. package/plugins/litclaude/skills/lit-diagram-drawer/examples/04-oauth-sequence/after.html +1 -0
  328. package/plugins/litclaude/skills/lit-diagram-drawer/examples/04-oauth-sequence/brief.md +17 -0
  329. package/plugins/litclaude/skills/lit-diagram-drawer/examples/05-review-lanes/after.html +1 -0
  330. package/plugins/litclaude/skills/lit-diagram-drawer/examples/05-review-lanes/brief.md +17 -0
  331. package/plugins/litclaude/skills/lit-diagram-drawer/examples/06-rollout-gates/after.html +1 -0
  332. package/plugins/litclaude/skills/lit-diagram-drawer/examples/06-rollout-gates/brief.md +17 -0
  333. package/plugins/litclaude/skills/lit-diagram-drawer/examples/07-deployment-boundary/after.html +1 -0
  334. package/plugins/litclaude/skills/lit-diagram-drawer/examples/07-deployment-boundary/brief.md +19 -0
  335. package/plugins/litclaude/skills/lit-diagram-drawer/examples/08-policy-traces/after.html +1 -0
  336. package/plugins/litclaude/skills/lit-diagram-drawer/examples/08-policy-traces/brief.md +20 -0
  337. package/plugins/litclaude/skills/lit-diagram-drawer/references/accessibility.md +37 -0
  338. package/plugins/litclaude/skills/lit-diagram-drawer/references/export.md +29 -0
  339. package/plugins/litclaude/skills/lit-diagram-drawer/references/import-drawio.md +21 -0
  340. package/plugins/litclaude/skills/lit-diagram-drawer/references/import-excalidraw.md +14 -0
  341. package/plugins/litclaude/skills/lit-diagram-drawer/references/import-mermaid.md +18 -0
  342. package/plugins/litclaude/skills/lit-diagram-drawer/references/import-schema.md +28 -0
  343. package/plugins/litclaude/skills/lit-diagram-drawer/references/korean-typography.md +34 -0
  344. package/plugins/litclaude/skills/lit-diagram-drawer/references/motion.md +29 -0
  345. package/plugins/litclaude/skills/lit-diagram-drawer/references/office-pptx-docx.md +42 -0
  346. package/plugins/litclaude/skills/lit-diagram-drawer/references/output-spec.md +48 -0
  347. package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-annotation.md +12 -0
  348. package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-icons.md +21 -0
  349. package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-sketchy.md +11 -0
  350. package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-terminal.md +11 -0
  351. package/plugins/litclaude/skills/lit-diagram-drawer/references/profiles.md +24 -0
  352. package/plugins/litclaude/skills/lit-diagram-drawer/references/semantic-patterns.md +27 -0
  353. package/plugins/litclaude/skills/lit-diagram-drawer/references/style-guide.md +67 -0
  354. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-architecture.md +51 -0
  355. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bar.md +51 -0
  356. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-beeswarm.md +49 -0
  357. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bubble.md +49 -0
  358. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bump.md +49 -0
  359. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-catalog.json +1433 -0
  360. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-data-flow.md +51 -0
  361. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-datalake.md +49 -0
  362. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-db-schema.md +49 -0
  363. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dependency.md +49 -0
  364. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-deployment.md +49 -0
  365. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dp-integration.md +49 -0
  366. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dp-security-matrix.md +49 -0
  367. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-er.md +49 -0
  368. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-fishbone.md +49 -0
  369. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-flowchart.md +49 -0
  370. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-gantt.md +49 -0
  371. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-heatmap.md +53 -0
  372. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-high-level-vertical.md +53 -0
  373. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-high-level.md +53 -0
  374. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-drawio.md +53 -0
  375. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-excalidraw.md +53 -0
  376. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-mermaid.md +53 -0
  377. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-it-state.md +54 -0
  378. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-journey.md +54 -0
  379. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-kanban.md +54 -0
  380. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-layers.md +54 -0
  381. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-line.md +54 -0
  382. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-loop-terminal.md +53 -0
  383. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-loop.md +54 -0
  384. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-marimekko.md +54 -0
  385. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-medallion.md +54 -0
  386. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-nested.md +59 -0
  387. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-org-chart.md +58 -0
  388. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-paved-road-animated.md +72 -0
  389. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-polar.md +67 -0
  390. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-policy-trace-animated.md +69 -0
  391. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-process.md +58 -0
  392. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-pyramid.md +59 -0
  393. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-quadrant-consultant.md +60 -0
  394. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-quadrant.md +57 -0
  395. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-queue-animated.md +63 -0
  396. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-radar.md +57 -0
  397. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-ridgeline.md +63 -0
  398. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sankey.md +68 -0
  399. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-scatter.md +60 -0
  400. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sequence-oauth.md +66 -0
  401. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sequence.md +63 -0
  402. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-slopegraph.md +65 -0
  403. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-state-lifecycle.md +53 -0
  404. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-state.md +59 -0
  405. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-story-map.md +52 -0
  406. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-streamgraph.md +53 -0
  407. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-swimlane.md +52 -0
  408. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-timeline.md +52 -0
  409. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-tree-block-decomposition.md +57 -0
  410. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-tree.md +54 -0
  411. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-treemap.md +54 -0
  412. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-uml-class.md +52 -0
  413. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-venn.md +51 -0
  414. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-wardley.md +52 -0
  415. package/plugins/litclaude/skills/lit-diagram-drawer/references/type-waterfall.md +54 -0
  416. package/plugins/litclaude/skills/lit-diagram-drawer/references/verifier-guide.md +66 -0
  417. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/block-registry.mjs +43 -0
  418. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/brief-contract.mjs +94 -0
  419. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/check-visible-text.mjs +15 -0
  420. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/diagram-metrics.mjs +223 -0
  421. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/doctor.mjs +35 -0
  422. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/drawio-extract.mjs +635 -0
  423. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/excalidraw-extract.mjs +319 -0
  424. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/export.mjs +116 -0
  425. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/mermaid-extract.mjs +438 -0
  426. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/office-safety.mjs +54 -0
  427. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/renderer.mjs +33 -0
  428. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-all.mjs +58 -0
  429. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-brief.mjs +22 -0
  430. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-coverage.mjs +56 -0
  431. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-diagram.mjs +27 -0
  432. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-motion.mjs +12 -0
  433. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-type.mjs +48 -0
  434. package/plugins/litclaude/skills/lit-diagram-drawer/scripts/visual-quality.mjs +376 -0
  435. package/plugins/litclaude/skills/lit-docx/NOTICE +33 -0
  436. package/plugins/litclaude/skills/lit-docx/SKILL.md +170 -0
  437. package/plugins/litclaude/skills/lit-docx/references/frontmatter_schema.md +42 -0
  438. package/plugins/litclaude/skills/lit-docx/references/journal_style_spec.md +17 -0
  439. package/plugins/litclaude/skills/lit-docx/references/markdown_quality_checklist.md +37 -0
  440. package/plugins/litclaude/skills/lit-docx/references/slop_phrase_list.yaml +58 -0
  441. package/plugins/litclaude/skills/lit-docx/references/slop_rules.md +35 -0
  442. package/plugins/litclaude/skills/lit-docx/scripts/clean_markdown.py +95 -0
  443. package/plugins/litclaude/skills/lit-docx/scripts/convert_md_to_docx.py +1194 -0
  444. package/plugins/litclaude/skills/lit-docx/scripts/convert_md_to_pdf.py +290 -0
  445. package/plugins/litclaude/skills/lit-docx/scripts/convert_pdf.py +139 -0
  446. package/plugins/litclaude/skills/lit-docx/scripts/edit_docx.py +306 -0
  447. package/plugins/litclaude/skills/lit-docx/scripts/embed_images.py +78 -0
  448. package/plugins/litclaude/skills/lit-docx/scripts/generate_docx_templates.py +500 -0
  449. package/plugins/litclaude/skills/lit-docx/scripts/qa_docx.py +177 -0
  450. package/plugins/litclaude/skills/lit-docx/scripts/slop_lint.py +561 -0
  451. package/plugins/litclaude/skills/lit-docx/scripts/visual_audit.py +48 -0
  452. package/plugins/litclaude/skills/lit-docx/templates/docx/acs.docx +0 -0
  453. package/plugins/litclaude/skills/lit-docx/templates/docx/elsevier.docx +0 -0
  454. package/plugins/litclaude/skills/lit-docx/templates/docx/ieee.docx +0 -0
  455. package/plugins/litclaude/skills/lit-docx/templates/docx/korean-generic.docx +0 -0
  456. package/plugins/litclaude/skills/lit-docx/templates/docx/nature.docx +0 -0
  457. package/plugins/litclaude/skills/lit-docx/templates/latex/acs/README.md +5 -0
  458. package/plugins/litclaude/skills/lit-docx/templates/latex/acs/template.tex +37 -0
  459. package/plugins/litclaude/skills/lit-docx/templates/latex/elsevier/README.md +5 -0
  460. package/plugins/litclaude/skills/lit-docx/templates/latex/elsevier/template.tex +38 -0
  461. package/plugins/litclaude/skills/lit-docx/templates/latex/ieee/README.md +5 -0
  462. package/plugins/litclaude/skills/lit-docx/templates/latex/ieee/template.tex +37 -0
  463. package/plugins/litclaude/skills/lit-docx/templates/latex/korean-generic/README.md +5 -0
  464. package/plugins/litclaude/skills/lit-docx/templates/latex/korean-generic/template.tex +37 -0
  465. package/plugins/litclaude/skills/lit-docx/templates/latex/nature/README.md +5 -0
  466. package/plugins/litclaude/skills/lit-docx/templates/latex/nature/template.tex +37 -0
  467. package/plugins/litclaude/skills/lit-docx/templates/registry.yaml +1366 -0
  468. package/plugins/litclaude/skills/lit-humanizer/NOTICE +160 -0
  469. package/plugins/litclaude/skills/lit-humanizer/SKILL.md +164 -0
  470. package/plugins/litclaude/skills/lit-humanizer/assets/always-on-rule.md +9 -0
  471. package/plugins/litclaude/skills/lit-humanizer/assets/report-skeleton.md +25 -0
  472. package/plugins/litclaude/skills/lit-humanizer/assets/slide-text-skeleton.md +28 -0
  473. package/plugins/litclaude/skills/lit-humanizer/bench/prompts.md +73 -0
  474. package/plugins/litclaude/skills/lit-humanizer/examples/accessibility-note/after.md +7 -0
  475. package/plugins/litclaude/skills/lit-humanizer/examples/accessibility-note/before.md +7 -0
  476. package/plugins/litclaude/skills/lit-humanizer/examples/api-reference/after.md +9 -0
  477. package/plugins/litclaude/skills/lit-humanizer/examples/api-reference/before.md +15 -0
  478. package/plugins/litclaude/skills/lit-humanizer/examples/changelog/after.md +5 -0
  479. package/plugins/litclaude/skills/lit-humanizer/examples/changelog/before.md +12 -0
  480. package/plugins/litclaude/skills/lit-humanizer/examples/code-comments/after.md +10 -0
  481. package/plugins/litclaude/skills/lit-humanizer/examples/code-comments/before.md +19 -0
  482. package/plugins/litclaude/skills/lit-humanizer/examples/commit/after.md +5 -0
  483. package/plugins/litclaude/skills/lit-humanizer/examples/commit/before.md +7 -0
  484. package/plugins/litclaude/skills/lit-humanizer/examples/data-release/after.md +7 -0
  485. package/plugins/litclaude/skills/lit-humanizer/examples/data-release/before.md +9 -0
  486. package/plugins/litclaude/skills/lit-humanizer/examples/english-essay/after.md +5 -0
  487. package/plugins/litclaude/skills/lit-humanizer/examples/english-essay/before.md +5 -0
  488. package/plugins/litclaude/skills/lit-humanizer/examples/incident-update/after.md +7 -0
  489. package/plugins/litclaude/skills/lit-humanizer/examples/incident-update/before.md +7 -0
  490. package/plugins/litclaude/skills/lit-humanizer/examples/ko-essay/after.md +7 -0
  491. package/plugins/litclaude/skills/lit-humanizer/examples/ko-essay/before.md +9 -0
  492. package/plugins/litclaude/skills/lit-humanizer/examples/ko-report/after.md +9 -0
  493. package/plugins/litclaude/skills/lit-humanizer/examples/ko-report/before.md +13 -0
  494. package/plugins/litclaude/skills/lit-humanizer/examples/ko-slide/after.md +19 -0
  495. package/plugins/litclaude/skills/lit-humanizer/examples/ko-slide/before.md +21 -0
  496. package/plugins/litclaude/skills/lit-humanizer/examples/meeting-brief/after.md +9 -0
  497. package/plugins/litclaude/skills/lit-humanizer/examples/meeting-brief/before.md +11 -0
  498. package/plugins/litclaude/skills/lit-humanizer/examples/policy-faq/after.md +9 -0
  499. package/plugins/litclaude/skills/lit-humanizer/examples/policy-faq/before.md +9 -0
  500. package/plugins/litclaude/skills/lit-humanizer/examples/pr/after.md +15 -0
  501. package/plugins/litclaude/skills/lit-humanizer/examples/pr/before.md +17 -0
  502. package/plugins/litclaude/skills/lit-humanizer/examples/project-update/after.md +7 -0
  503. package/plugins/litclaude/skills/lit-humanizer/examples/project-update/before.md +9 -0
  504. package/plugins/litclaude/skills/lit-humanizer/examples/readme/after.md +12 -0
  505. package/plugins/litclaude/skills/lit-humanizer/examples/readme/before.md +14 -0
  506. package/plugins/litclaude/skills/lit-humanizer/examples/report/after.md +13 -0
  507. package/plugins/litclaude/skills/lit-humanizer/examples/report/before.md +11 -0
  508. package/plugins/litclaude/skills/lit-humanizer/examples/research-abstract/after.md +5 -0
  509. package/plugins/litclaude/skills/lit-humanizer/examples/research-abstract/before.md +5 -0
  510. package/plugins/litclaude/skills/lit-humanizer/examples/slides/after.md +19 -0
  511. package/plugins/litclaude/skills/lit-humanizer/examples/slides/before.md +19 -0
  512. package/plugins/litclaude/skills/lit-humanizer/examples/troubleshooting/after.md +11 -0
  513. package/plugins/litclaude/skills/lit-humanizer/examples/troubleshooting/before.md +11 -0
  514. package/plugins/litclaude/skills/lit-humanizer/motion-guide.md +123 -0
  515. package/plugins/litclaude/skills/lit-humanizer/references/code-patterns.md +468 -0
  516. package/plugins/litclaude/skills/lit-humanizer/references/deliverable-channels.md +111 -0
  517. package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-checklist.md +43 -0
  518. package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-content.md +243 -0
  519. package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-structure.md +375 -0
  520. package/plugins/litclaude/skills/lit-humanizer/references/en-patterns.md +57 -0
  521. package/plugins/litclaude/skills/lit-humanizer/references/ko-metrics.md +33 -0
  522. package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns-a-d.md +659 -0
  523. package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns-e-j.md +387 -0
  524. package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns.md +31 -0
  525. package/plugins/litclaude/skills/lit-humanizer/references/rewrite-playbook.md +54 -0
  526. package/plugins/litclaude/skills/lit-humanizer/references/taxonomy.md +153 -0
  527. package/plugins/litclaude/skills/lit-humanizer/rules.json +884 -0
  528. package/plugins/litclaude/skills/lit-humanizer/scripts/artifact-text.mjs +38 -0
  529. package/plugins/litclaude/skills/lit-humanizer/scripts/core.mjs +207 -0
  530. package/plugins/litclaude/skills/lit-humanizer/scripts/detect.mjs +64 -0
  531. package/plugins/litclaude/skills/lit-humanizer/scripts/extract_office_text.py +112 -0
  532. package/plugins/litclaude/skills/lit-humanizer/scripts/ko-metrics.mjs +124 -0
  533. package/plugins/litclaude/skills/lit-humanizer/scripts/scan-input.mjs +29 -0
  534. package/plugins/litclaude/skills/lit-loop/SKILL.md +30 -1
  535. package/plugins/litclaude/skills/lit-plan/SKILL.md +4 -1
  536. package/plugins/litclaude/skills/lit-pptx/NOTICE +38 -0
  537. package/plugins/litclaude/skills/lit-pptx/SKILL.md +207 -0
  538. package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-lg.png +0 -0
  539. package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-md.png +0 -0
  540. package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-sm.png +0 -0
  541. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Black.otf +0 -0
  542. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Bold.otf +0 -0
  543. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Light.otf +0 -0
  544. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Medium.otf +0 -0
  545. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Regular.otf +0 -0
  546. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/OFL.txt +94 -0
  547. package/plugins/litclaude/skills/lit-pptx/fonts/a2z/SOURCE.md +29 -0
  548. package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/OFL.txt +94 -0
  549. package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/Pretendard-Bold.otf +0 -0
  550. package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/Pretendard-Regular.otf +0 -0
  551. package/plugins/litclaude/skills/lit-pptx/fonts/provenance.json +78 -0
  552. package/plugins/litclaude/skills/lit-pptx/references/agents/analyst.md +49 -0
  553. package/plugins/litclaude/skills/lit-pptx/references/agents/antithesis.md +59 -0
  554. package/plugins/litclaude/skills/lit-pptx/references/agents/architect.md +44 -0
  555. package/plugins/litclaude/skills/lit-pptx/references/agents/critic.md +42 -0
  556. package/plugins/litclaude/skills/lit-pptx/references/agents/synthesizer.md +47 -0
  557. package/plugins/litclaude/skills/lit-pptx/references/agents/thesis.md +33 -0
  558. package/plugins/litclaude/skills/lit-pptx/references/anti-slop-checklist.md +81 -0
  559. package/plugins/litclaude/skills/lit-pptx/references/authoring-guide.md +173 -0
  560. package/plugins/litclaude/skills/lit-pptx/references/consensus-protocol.md +125 -0
  561. package/plugins/litclaude/skills/lit-pptx/references/data-display-cookbook.md +45 -0
  562. package/plugins/litclaude/skills/lit-pptx/references/design-system-azure.md +58 -0
  563. package/plugins/litclaude/skills/lit-pptx/references/interview-protocol.md +113 -0
  564. package/plugins/litclaude/skills/lit-pptx/references/stages/autopilot.md +48 -0
  565. package/plugins/litclaude/skills/lit-pptx/references/stages/interview.md +52 -0
  566. package/plugins/litclaude/skills/lit-pptx/references/stages/plan.md +42 -0
  567. package/plugins/litclaude/skills/lit-pptx/scripts/compile-deck.js +414 -0
  568. package/plugins/litclaude/skills/lit-pptx/scripts/craft_extras.py +373 -0
  569. package/plugins/litclaude/skills/lit-pptx/scripts/deck_craft.py +321 -0
  570. package/plugins/litclaude/skills/lit-pptx/scripts/embed_fonts.py +215 -0
  571. package/plugins/litclaude/skills/lit-pptx/scripts/forbidden-terms.json +55 -0
  572. package/plugins/litclaude/skills/lit-pptx/scripts/layout_inventory.py +418 -0
  573. package/plugins/litclaude/skills/lit-pptx/scripts/learn_template.py +446 -0
  574. package/plugins/litclaude/skills/lit-pptx/scripts/lib/derive-palette.js +176 -0
  575. package/plugins/litclaude/skills/lit-pptx/scripts/lib/directive-parser.js +244 -0
  576. package/plugins/litclaude/skills/lit-pptx/scripts/lib/font-map.js +79 -0
  577. package/plugins/litclaude/skills/lit-pptx/scripts/lib/gen-bg.js +86 -0
  578. package/plugins/litclaude/skills/lit-pptx/scripts/lib/gen-gradient-assets.js +37 -0
  579. package/plugins/litclaude/skills/lit-pptx/scripts/lib/layout-resolver.js +768 -0
  580. package/plugins/litclaude/skills/lit-pptx/scripts/lib/markdown-loader.js +136 -0
  581. package/plugins/litclaude/skills/lit-pptx/scripts/lib/render-adapter-html.js +356 -0
  582. package/plugins/litclaude/skills/lit-pptx/scripts/lib/render-adapter-pptx.js +2094 -0
  583. package/plugins/litclaude/skills/lit-pptx/scripts/lib/runtime-require.js +28 -0
  584. package/plugins/litclaude/skills/lit-pptx/scripts/lib/slide-ast.js +561 -0
  585. package/plugins/litclaude/skills/lit-pptx/scripts/lib/spec-validator.js +94 -0
  586. package/plugins/litclaude/skills/lit-pptx/scripts/lib/template-registry.js +394 -0
  587. package/plugins/litclaude/skills/lit-pptx/scripts/package.json +4 -0
  588. package/plugins/litclaude/skills/lit-pptx/scripts/qa_deck.py +766 -0
  589. package/plugins/litclaude/skills/lit-pptx/scripts/validate_pptx.py +215 -0
  590. package/plugins/litclaude/skills/lit-pptx/specs/markdown-slide-spec-v1.md +251 -0
  591. package/plugins/litclaude/skills/lit-pptx/specs/markdown-slide-spec-v2.md +214 -0
  592. package/plugins/litclaude/skills/lit-pptx/specs/slide-ast-v1.schema.json +229 -0
  593. package/plugins/litclaude/skills/lit-pptx/specs/slide-ast-v2.schema.json +144 -0
  594. package/plugins/litclaude/skills/lit-pptx/specs/template-enrollment-contract.md +382 -0
  595. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/capabilities.yaml +146 -0
  596. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/layout-mapping.yaml +454 -0
  597. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/template.yaml +37 -0
  598. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/capabilities.yaml +154 -0
  599. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/layout-mapping.yaml +475 -0
  600. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/template.yaml +37 -0
  601. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/capabilities.yaml +179 -0
  602. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/layout-mapping.yaml +299 -0
  603. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/template.yaml +45 -0
  604. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/capabilities.yaml +181 -0
  605. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/layout-mapping.yaml +299 -0
  606. package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/template.yaml +44 -0
  607. package/plugins/litclaude/skills/lit-scientific-visualization/SKILL.md +1 -0
  608. package/plugins/litclaude/skills/lit-typographic-motion/SKILL.md +131 -0
  609. package/plugins/litclaude/skills/lit-typographic-motion/engine/NOTICE +23 -0
  610. package/plugins/litclaude/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +56 -0
  611. package/plugins/litclaude/skills/lit-typographic-motion/engine/audio/beat_grid.py +56 -0
  612. package/plugins/litclaude/skills/lit-typographic-motion/engine/audio/requirements.lock +1084 -0
  613. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/constants.mjs +211 -0
  614. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/contrast.mjs +90 -0
  615. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/events.mjs +46 -0
  616. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/flash.mjs +211 -0
  617. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/gate-rules.mjs +550 -0
  618. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/presets.mjs +123 -0
  619. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/text.mjs +100 -0
  620. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/timeline.mjs +142 -0
  621. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/util.mjs +167 -0
  622. package/plugins/litclaude/skills/lit-typographic-motion/engine/core/voices.mjs +19 -0
  623. package/plugins/litclaude/skills/lit-typographic-motion/engine/models/word-timing.json +198 -0
  624. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/analysis.mjs +108 -0
  625. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/brief.mjs +158 -0
  626. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/chrome.mjs +330 -0
  627. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/coverage.mjs +83 -0
  628. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/done.mjs +104 -0
  629. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/encode.mjs +104 -0
  630. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/frame-worker.mjs +36 -0
  631. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/look.mjs +128 -0
  632. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/pipeline.mjs +592 -0
  633. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/png.mjs +112 -0
  634. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/report.mjs +66 -0
  635. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/runtime.mjs +330 -0
  636. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/session.mjs +145 -0
  637. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/sound-cli.mjs +60 -0
  638. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/sound.mjs +641 -0
  639. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-capture.mjs +178 -0
  640. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-gate.mjs +122 -0
  641. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-qa.mjs +295 -0
  642. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-serve.mjs +278 -0
  643. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage.mjs +503 -0
  644. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stills.mjs +100 -0
  645. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/treatment.mjs +343 -0
  646. package/plugins/litclaude/skills/lit-typographic-motion/engine/node/ws-server.mjs +132 -0
  647. package/plugins/litclaude/skills/lit-typographic-motion/engine/package-lock.json +25 -0
  648. package/plugins/litclaude/skills/lit-typographic-motion/engine/package.json +10 -0
  649. package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/init.js +288 -0
  650. package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/qa.js +157 -0
  651. package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/stage-kit.js +701 -0
  652. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/boot.mjs +123 -0
  653. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/engine.mjs +281 -0
  654. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/gl.mjs +319 -0
  655. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/glsl-common.mjs +78 -0
  656. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/index.html +6 -0
  657. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/lines.mjs +112 -0
  658. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/crt.mjs +98 -0
  659. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/dither.mjs +49 -0
  660. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/glitch.mjs +77 -0
  661. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/swiss-grid.mjs +61 -0
  662. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/terminal-ui.mjs +88 -0
  663. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/tidal-gradient.mjs +86 -0
  664. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/post.mjs +165 -0
  665. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scale.mjs +15 -0
  666. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scene.mjs +82 -0
  667. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/end-card.mjs +30 -0
  668. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/index.mjs +16 -0
  669. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/karaoke-line.mjs +47 -0
  670. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/kinetic-list.mjs +45 -0
  671. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/number-counter.mjs +29 -0
  672. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/signature.mjs +73 -0
  673. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/title-slam.mjs +73 -0
  674. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/stroke.mjs +236 -0
  675. package/plugins/litclaude/skills/lit-typographic-motion/engine/web/type.mjs +180 -0
  676. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-400.ttf +0 -0
  677. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-700.ttf +0 -0
  678. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-900.ttf +0 -0
  679. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-400.ttf +0 -0
  680. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-700.ttf +0 -0
  681. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-900.ttf +0 -0
  682. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-400.ttf +0 -0
  683. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-700.ttf +0 -0
  684. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-900.ttf +0 -0
  685. package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/OFL.txt +93 -0
  686. package/plugins/litclaude/skills/lit-typographic-motion/fonts/manifest.json +437 -0
  687. package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/OFL.txt +93 -0
  688. package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/Silkscreen-Bold.ttf +0 -0
  689. package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/Silkscreen-Regular.ttf +0 -0
  690. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/CREDITS +42 -0
  691. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSAllure.svg +216 -0
  692. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSFelix.svg +216 -0
  693. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSOsmotron.svg +216 -0
  694. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSReadability.svg +216 -0
  695. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSTech.svg +217 -0
  696. package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/OFL.txt +91 -0
  697. package/plugins/litclaude/skills/lit-typographic-motion/fonts/vt323/OFL.txt +93 -0
  698. package/plugins/litclaude/skills/lit-typographic-motion/fonts/vt323/VT323-Regular.ttf +0 -0
  699. package/plugins/litclaude/skills/lit-typographic-motion/references/brief-schema.md +91 -0
  700. package/plugins/litclaude/skills/lit-typographic-motion/references/craft-loop.md +69 -0
  701. package/plugins/litclaude/skills/lit-typographic-motion/references/engine-contract.md +104 -0
  702. package/plugins/litclaude/skills/lit-typographic-motion/references/look.md +106 -0
  703. package/plugins/litclaude/skills/lit-typographic-motion/references/runtime.md +65 -0
  704. package/plugins/litclaude/skills/lit-typographic-motion/references/sound.md +83 -0
  705. package/plugins/litclaude/skills/lit-typographic-motion/references/stage.md +192 -0
  706. package/plugins/litclaude/skills/lit-typographic-motion/references/style-bibles.md +117 -0
  707. package/plugins/litclaude/skills/lit-typographic-motion/references/treatment.md +114 -0
  708. package/plugins/litclaude/skills/lit-typographic-motion/references/type-craft.md +79 -0
  709. package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion-doctor.mjs +78 -0
  710. package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion-runtime.mjs +67 -0
  711. package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion.mjs +132 -0
  712. package/plugins/litclaude/skills/litresearch/SKILL.md +54 -18
  713. package/scripts/doctor.mjs +5 -0
  714. package/scripts/postinstall.mjs +1 -0
  715. package/plugins/litclaude/skills/lit-korean/SKILL.md +0 -327
  716. /package/plugins/litclaude/skills/{lit-korean/references/fidelity-checklist.md → lit-humanizer/references/litclaude-fidelity-checklist.md} +0 -0
  717. /package/plugins/litclaude/skills/{lit-korean/references/rewrite-rules.md → lit-humanizer/references/litclaude-rewrite-rules.md} +0 -0
  718. /package/plugins/litclaude/skills/{lit-korean/references/style-patterns.md → lit-humanizer/references/litclaude-style-patterns.md} +0 -0
@@ -0,0 +1,766 @@
1
+ #!/usr/bin/env python3
2
+ """Honest, renderer-agnostic QA gate for generated PPTX decks.
3
+
4
+ Brand-neutral: works for any enrolled template. Combines three checks and
5
+ exits non-zero if ANY real defect is found:
6
+
7
+ 1. Layout issues — layout_inventory.py (frame overflow / slide overflow / off-slide)
8
+ 2. Anti-slop — validate_pptx.py (forbidden/placeholder terms, default fonts)
9
+ 3. WCAG contrast — text colour vs its fill (body < 4.5:1, large < 3:1)
10
+ 4. Integrity — plugins/litclaude/lib/ooxml_integrity.py (package opens,
11
+ relationships resolve, no NaN attribute values)
12
+ 5. Deck craft — deck_craft.py (sparse slides, table-only decks, shapes off
13
+ the canvas, stray empty boxes, [placeholder] blanks, long
14
+ foreign-language source lines on a Korean deck)
15
+
16
+ No LibreOffice / rendering engine required: everything is read from the OOXML
17
+ via python-pptx. (A renderer is only ever needed for the *visual* pass, which
18
+ lives in plugins/litclaude/lib/render_pages.py and needs soffice.)
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import os as _os
24
+ import sys as _sys
25
+
26
+ _sys.dont_write_bytecode = True # the installed skill directory stays read-only
27
+ _sys.path.insert(0, _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), "..", "..", "..", "lib"))
28
+ from office_runtime_bootstrap import ensure_runtime # noqa: E402
29
+
30
+ ensure_runtime(["pptx"])
31
+
32
+ import argparse
33
+ import json
34
+ import re
35
+ import subprocess
36
+ import sys
37
+ import tempfile
38
+ from pathlib import Path
39
+ from typing import Any
40
+
41
+ from pptx import Presentation
42
+ from pptx.dml.color import RGBColor
43
+ from pptx.enum.shapes import MSO_SHAPE_TYPE
44
+ from pptx.opc.constants import RELATIONSHIP_TYPE as RT
45
+
46
+ ROOT = Path(__file__).resolve().parents[1]
47
+ VALIDATE = ROOT / "scripts" / "validate_pptx.py"
48
+ INVENTORY = ROOT / "scripts" / "layout_inventory.py"
49
+
50
+ # WCAG 2.x contrast floors.
51
+ BODY_MIN = 4.5
52
+ LARGE_MIN = 3.0
53
+
54
+
55
+ # ── WCAG contrast ──────────────────────────────────────────────────────────
56
+ def _rel_luminance(rgb: tuple[int, int, int]) -> float:
57
+ def chan(c: int) -> float:
58
+ s = c / 255.0
59
+ return s / 12.92 if s <= 0.03928 else ((s + 0.055) / 1.055) ** 2.4
60
+
61
+ r, g, b = (chan(x) for x in rgb)
62
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b
63
+
64
+
65
+ def _ratio(fg: tuple[int, int, int], bg: tuple[int, int, int]) -> float:
66
+ l1, l2 = _rel_luminance(fg), _rel_luminance(bg)
67
+ hi, lo = max(l1, l2), min(l1, l2)
68
+ return (hi + 0.05) / (lo + 0.05)
69
+
70
+
71
+ def _hex_to_rgb(value: Any) -> tuple[int, int, int] | None:
72
+ if isinstance(value, RGBColor):
73
+ value = str(value)
74
+ if not isinstance(value, str):
75
+ return None
76
+ v = value.lstrip("#")
77
+ if len(v) != 6:
78
+ return None
79
+ try:
80
+ return (int(v[0:2], 16), int(v[2:4], 16), int(v[4:6], 16))
81
+ except ValueError:
82
+ return None
83
+
84
+
85
+ def _shape_fill_rgb(shape) -> tuple[int, int, int] | None:
86
+ fill = getattr(shape, "fill", None)
87
+ if fill is None or getattr(fill, "type", None) is None:
88
+ return None
89
+ try:
90
+ rgb = fill.fore_color.rgb
91
+ except (TypeError, AttributeError):
92
+ return None
93
+ return _hex_to_rgb(rgb)
94
+
95
+
96
+ def _is_large(size_pt: float | None, bold: bool) -> bool:
97
+ if size_pt is None:
98
+ return False
99
+ return size_pt >= 18 or (bold and size_pt >= 14)
100
+
101
+
102
+ def _bbox(shape):
103
+ try:
104
+ l, t, w, h = int(shape.left), int(shape.top), int(shape.width), int(shape.height)
105
+ return (l, t, l + w, t + h)
106
+ except (TypeError, ValueError):
107
+ return None
108
+
109
+
110
+ def _resolve_bg(shape, idx, filled):
111
+ """Effective background for a text shape: its own fill, else the topmost
112
+ filled shape drawn *behind* it (lower z-order) that contains its centre,
113
+ else white. Prevents false positives like white text over a charcoal band."""
114
+ own = _shape_fill_rgb(shape)
115
+ if own is not None:
116
+ return own
117
+ box = _bbox(shape)
118
+ if box is not None:
119
+ cx, cy = (box[0] + box[2]) / 2, (box[1] + box[3]) / 2
120
+ best = None
121
+ for f_idx, f_rgb, f_box in filled:
122
+ if f_idx >= idx or f_box is None:
123
+ continue
124
+ if f_box[0] <= cx <= f_box[2] and f_box[1] <= cy <= f_box[3]:
125
+ best = f_rgb # later (higher idx) wins -> topmost behind text
126
+ if best is not None:
127
+ return best
128
+ return (255, 255, 255)
129
+
130
+
131
+ def check_contrast(path: Path) -> dict[str, Any]:
132
+ """Flag explicit-colour text that falls under the WCAG floor on its fill."""
133
+ prs = Presentation(str(path))
134
+ violations: list[dict[str, Any]] = []
135
+ checked = 0
136
+ for s_idx, slide in enumerate(prs.slides, start=1):
137
+ shapes = list(slide.shapes)
138
+ filled = [(i, rgb, _bbox(sh)) for i, sh in enumerate(shapes) if (rgb := _shape_fill_rgb(sh)) is not None]
139
+ for idx, shape in enumerate(shapes):
140
+ if not getattr(shape, "has_text_frame", False):
141
+ continue
142
+ bg = _resolve_bg(shape, idx, filled)
143
+ for para in shape.text_frame.paragraphs:
144
+ for run in para.runs:
145
+ if not run.text.strip():
146
+ continue
147
+ try:
148
+ fg = _hex_to_rgb(run.font.color.rgb)
149
+ except (TypeError, AttributeError):
150
+ fg = None
151
+ if fg is None:
152
+ continue # theme/inherited colour — cannot judge, skip
153
+ checked += 1
154
+ size = float(run.font.size.pt) if run.font.size is not None else None
155
+ bold = bool(run.font.bold)
156
+ ratio = _ratio(fg, bg)
157
+ floor = LARGE_MIN if _is_large(size, bold) else BODY_MIN
158
+ if ratio < floor:
159
+ violations.append({
160
+ "slide": s_idx,
161
+ "text": run.text.strip()[:60],
162
+ "fg": "#%02X%02X%02X" % fg,
163
+ "bg": "#%02X%02X%02X" % bg,
164
+ "ratio": round(ratio, 2),
165
+ "floor": floor,
166
+ })
167
+ return {"pass": not violations, "checked_runs": checked, "violations": violations[:30]}
168
+
169
+
170
+ # ── picture / table overlap ─────────────────────────────────────────────────
171
+ # The layout inventory's overlap list is plain box geometry with no z-order, so it
172
+ # cannot tell a chart drawn over a data table from text sitting on its card. This check covers
173
+ # PICTURE and TABLE (graphicFrame) shapes against every other content-bearing
174
+ # shape and fails on any real overlap.
175
+ OVERLAP_TOL_IN = 0.06 # inches; ignore hairline touches / rounding
176
+ MIN_TEXT_PT = 6.0
177
+
178
+
179
+ def _shape_kind(shape) -> str | None:
180
+ """Classify a shape for overlap purposes: 'picture', 'table', 'text', or
181
+ None for decorative/empty shapes (backgrounds, rules, blank frames)."""
182
+ if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
183
+ return "picture"
184
+ if getattr(shape, "has_table", False):
185
+ return "table"
186
+ if getattr(shape, "has_text_frame", False) and shape.text_frame.text.strip():
187
+ return "text"
188
+ return None
189
+
190
+
191
+ def _bbox_in(shape) -> tuple[float, float, float, float] | None:
192
+ try:
193
+ l = shape.left / 914400.0
194
+ t = shape.top / 914400.0
195
+ w = shape.width / 914400.0
196
+ h = shape.height / 914400.0
197
+ except (TypeError, ValueError):
198
+ return None
199
+ return (l, t, l + w, t + h)
200
+
201
+
202
+ def _is_full_bleed(box, page_area: float) -> bool:
203
+ """A shape covering essentially the whole canvas is a ground, not an occluder."""
204
+ return ((box[2] - box[0]) * (box[3] - box[1])) >= 0.92 * page_area
205
+
206
+
207
+ def _overlap_extent(box_a, box_b) -> tuple[float, float]:
208
+ return (min(box_a[2], box_b[2]) - max(box_a[0], box_b[0]),
209
+ min(box_a[3], box_b[3]) - max(box_a[1], box_b[1]))
210
+
211
+
212
+ def check_semantic_overlaps(path: Path) -> dict[str, Any]:
213
+ """Text running over other text — the one occlusion nothing else catches.
214
+
215
+ Free positioning lets an author drop a box anywhere, so two text frames can
216
+ now land on top of each other and produce a slide where neither is readable.
217
+ The layout inventory lists box overlaps but cannot tell a card's own text
218
+ from two frames colliding, so its count stays informational.
219
+
220
+ Every other pairing already has a more careful owner, and duplicating them
221
+ here would only reintroduce their false positives:
222
+
223
+ picture or table drawn over content -> check_overlaps (z-order aware)
224
+ declared figure or table occluded -> check_figure_table_occlusion
225
+ text on a card, panel or backdrop -> check_contrast, on its real fill
226
+
227
+ That last one is why an undeclared picture is not treated as content. A
228
+ gradient circle behind a cover title is a ground exactly as a navy panel is;
229
+ a picture only carries content once its description declares it as evidence,
230
+ and check_figure_table_occlusion is what reads that declaration.
231
+ """
232
+ prs = Presentation(str(path))
233
+ page_area = (prs.slide_width / 914400.0) * (prs.slide_height / 914400.0)
234
+ violations: list[dict[str, Any]] = []
235
+
236
+ for s_idx, slide in enumerate(prs.slides, start=1):
237
+ texts = [
238
+ (_bbox_in(sh), sh) for sh in slide.shapes
239
+ if _shape_kind(sh) == "text" and _bbox_in(sh) is not None
240
+ ]
241
+ for i in range(len(texts)):
242
+ for j in range(i + 1, len(texts)):
243
+ box_a, sh_a = texts[i]
244
+ box_b, sh_b = texts[j]
245
+ if _is_full_bleed(box_a, page_area) or _is_full_bleed(box_b, page_area):
246
+ continue
247
+ ow, oh = _overlap_extent(box_a, box_b)
248
+ if ow <= OVERLAP_TOL_IN or oh <= OVERLAP_TOL_IN:
249
+ continue
250
+ violations.append({
251
+ "slide": s_idx,
252
+ "a": "text",
253
+ "b": "text",
254
+ "area": round(ow * oh, 2),
255
+ "a_text": _shape_text(sh_a)[:40],
256
+ "b_text": _shape_text(sh_b)[:40],
257
+ })
258
+
259
+ return {"pass": not violations, "violations": violations[:30]}
260
+
261
+
262
+ def check_overlaps(path: Path) -> dict[str, Any]:
263
+ """A PICTURE or TABLE must never be drawn on top of (higher z-order than)
264
+ another content-bearing shape. Decorations are drawn first (behind), so they
265
+ are never the 'top' shape and never false-flag."""
266
+ prs = Presentation(str(path))
267
+ page_area = (prs.slide_width / 914400.0) * (prs.slide_height / 914400.0)
268
+ violations: list[dict[str, Any]] = []
269
+ for s_idx, slide in enumerate(prs.slides, start=1):
270
+ shapes = []
271
+ for z, sh in enumerate(slide.shapes):
272
+ box = _bbox_in(sh)
273
+ if box is None:
274
+ continue
275
+ shapes.append((z, sh, _shape_kind(sh), box))
276
+
277
+ def is_full_bleed(b):
278
+ return _is_full_bleed(b, page_area)
279
+ for z, sh, kind, box in shapes:
280
+ if kind not in ("picture", "table"):
281
+ continue
282
+ for z2, sh2, kind2, box2 in shapes:
283
+ if z2 >= z or kind2 is None:
284
+ continue # only shapes drawn *behind* this picture/table
285
+ # A full-bleed background image (mesh/gradient wash) is never an
286
+ # occlusion victim — anything may sit on top of it by design.
287
+ if kind2 == "picture" and is_full_bleed(box2):
288
+ continue
289
+ # Picture-over-picture is intentional decorative layering.
290
+ if kind == "picture" and kind2 == "picture":
291
+ continue
292
+ ow = min(box[2], box2[2]) - max(box[0], box2[0])
293
+ oh = min(box[3], box2[3]) - max(box[1], box2[1])
294
+ if ow > OVERLAP_TOL_IN and oh > OVERLAP_TOL_IN:
295
+ violations.append({
296
+ "slide": s_idx,
297
+ "top": kind,
298
+ "under": kind2,
299
+ "area": round(ow * oh, 2),
300
+ })
301
+ return {"pass": not violations, "violations": violations[:30]}
302
+
303
+
304
+ # ── objective executive/research checks ────────────────────────────────────
305
+ def _intersection(box_a, box_b) -> tuple[float, float]:
306
+ return (
307
+ min(box_a[2], box_b[2]) - max(box_a[0], box_b[0]),
308
+ min(box_a[3], box_b[3]) - max(box_a[1], box_b[1]),
309
+ )
310
+
311
+
312
+ def _iter_shape_runs(shape):
313
+ if getattr(shape, "has_text_frame", False):
314
+ for paragraph in shape.text_frame.paragraphs:
315
+ yield from paragraph.runs
316
+ if getattr(shape, "has_table", False):
317
+ for row in shape.table.rows:
318
+ for cell in row.cells:
319
+ for paragraph in cell.text_frame.paragraphs:
320
+ yield from paragraph.runs
321
+
322
+
323
+ def _shape_text(shape) -> str:
324
+ return "\n".join(run.text for run in _iter_shape_runs(shape) if run.text).strip()
325
+
326
+
327
+ def _semantic_label(shape) -> str:
328
+ values = [getattr(shape, "name", "") or ""]
329
+ try:
330
+ c_nv_pr = shape._element.xpath(".//p:cNvPr")[0]
331
+ values.extend([c_nv_pr.get("name", ""), c_nv_pr.get("descr", ""), c_nv_pr.get("title", "")])
332
+ except (AttributeError, IndexError):
333
+ pass
334
+ return " ".join(value for value in values if value).strip()
335
+
336
+
337
+ def check_side_stripes(path: Path) -> dict[str, Any]:
338
+ """Detect a narrow filled bar attached to the vertical edge of a larger card."""
339
+ prs = Presentation(str(path))
340
+ violations: list[dict[str, Any]] = []
341
+ for slide_idx, slide in enumerate(prs.slides, start=1):
342
+ filled = [
343
+ (idx, shape, _bbox_in(shape), _shape_fill_rgb(shape))
344
+ for idx, shape in enumerate(slide.shapes)
345
+ if _bbox_in(shape) is not None and _shape_fill_rgb(shape) is not None
346
+ ]
347
+ for stripe_idx, stripe, stripe_box, stripe_rgb in filled:
348
+ sw = stripe_box[2] - stripe_box[0]
349
+ sh = stripe_box[3] - stripe_box[1]
350
+ if sw > 0.15 or sh < 0.5 or sh / max(sw, 0.001) < 5:
351
+ continue
352
+ for card_idx, card, card_box, card_rgb in filled:
353
+ if card_idx == stripe_idx or card_rgb == stripe_rgb:
354
+ continue
355
+ cw = card_box[2] - card_box[0]
356
+ ch = card_box[3] - card_box[1]
357
+ if cw < 1.0 or ch < 0.5 or sh < ch * 0.7:
358
+ continue
359
+ same_vertical_band = abs(stripe_box[1] - card_box[1]) <= 0.08 and abs(stripe_box[3] - card_box[3]) <= 0.08
360
+ on_edge = abs(stripe_box[0] - card_box[0]) <= 0.08 or abs(stripe_box[2] - card_box[2]) <= 0.08
361
+ if same_vertical_band and on_edge:
362
+ violations.append({
363
+ "slide": slide_idx,
364
+ "stripe_shape": stripe_idx + 1,
365
+ "card_shape": card_idx + 1,
366
+ "stripe_width_in": round(sw, 3),
367
+ })
368
+ break
369
+ return {"pass": not violations, "violations": violations[:30]}
370
+
371
+
372
+ def check_text_size_floor(path: Path) -> dict[str, Any]:
373
+ """Fail only on explicit text below the absolute 6pt export floor."""
374
+ prs = Presentation(str(path))
375
+ violations: list[dict[str, Any]] = []
376
+ checked = 0
377
+ for slide_idx, slide in enumerate(prs.slides, start=1):
378
+ for shape_idx, shape in enumerate(slide.shapes, start=1):
379
+ for run in _iter_shape_runs(shape):
380
+ if not run.text.strip() or run.font.size is None:
381
+ continue
382
+ checked += 1
383
+ size = float(run.font.size.pt)
384
+ if size < MIN_TEXT_PT:
385
+ violations.append({
386
+ "slide": slide_idx,
387
+ "shape": shape_idx,
388
+ "text": run.text.strip()[:60],
389
+ "size_pt": round(size, 2),
390
+ "floor_pt": MIN_TEXT_PT,
391
+ })
392
+ return {"pass": not violations, "checked_runs": checked, "violations": violations[:30]}
393
+
394
+
395
+ def check_figure_table_occlusion(path: Path) -> dict[str, Any]:
396
+ """Flag content shapes drawn over a non-background figure or table."""
397
+ prs = Presentation(str(path))
398
+ violations: list[dict[str, Any]] = []
399
+ for slide_idx, slide in enumerate(prs.slides, start=1):
400
+ page_area = (prs.slide_width / 914400.0) * (prs.slide_height / 914400.0)
401
+ shapes = [
402
+ (idx, shape, _shape_kind(shape), _bbox_in(shape))
403
+ for idx, shape in enumerate(slide.shapes)
404
+ if _bbox_in(shape) is not None
405
+ ]
406
+ for victim_idx, victim, victim_kind, victim_box in shapes:
407
+ if victim_kind not in ("picture", "table"):
408
+ continue
409
+ # A generic picture may intentionally be a background or decorated
410
+ # asset. Only pictures explicitly declared as evidence/figures have
411
+ # objective occlusion semantics; tables are always data objects.
412
+ if victim_kind == "picture" and not _EVIDENCE_MARKER.search(_semantic_label(victim)):
413
+ continue
414
+ victim_area = (victim_box[2] - victim_box[0]) * (victim_box[3] - victim_box[1])
415
+ if victim_kind == "picture" and victim_area >= 0.92 * page_area:
416
+ continue
417
+ for top_idx, top, top_kind, top_box in shapes:
418
+ if top_idx <= victim_idx or top_kind is None:
419
+ continue
420
+ if victim_kind == "picture" and top_kind == "picture":
421
+ continue
422
+ ow, oh = _intersection(victim_box, top_box)
423
+ if ow <= OVERLAP_TOL_IN or oh <= OVERLAP_TOL_IN:
424
+ continue
425
+ overlap_area = ow * oh
426
+ if overlap_area < max(0.08, victim_area * 0.03):
427
+ continue
428
+ violations.append({
429
+ "slide": slide_idx,
430
+ "victim": victim_kind,
431
+ "victim_shape": victim_idx + 1,
432
+ "occluding": top_kind,
433
+ "occluding_shape": top_idx + 1,
434
+ "area": round(overlap_area, 2),
435
+ })
436
+ return {"pass": not violations, "violations": violations[:30]}
437
+
438
+
439
+ _EVIDENCE_MARKER = re.compile(
440
+ r"(?:^|\b)(?:figure|evidence|source[ -]?capture|그림|도표|근거|출처\s*캡처)\s*(?::|\d|\b)",
441
+ re.IGNORECASE,
442
+ )
443
+ _CAPTION_MARKER = re.compile(r"(?:그림|도|figure|fig\.)\s*\d+", re.IGNORECASE)
444
+ _SOURCE_MARKER = re.compile(r"(?:출처|source)\s*:", re.IGNORECASE)
445
+
446
+
447
+ def check_evidence_binding(path: Path) -> dict[str, Any]:
448
+ """Require visible, adjacent caption and source text for declared evidence figures."""
449
+ prs = Presentation(str(path))
450
+ violations: list[dict[str, Any]] = []
451
+ checked = 0
452
+ for slide_idx, slide in enumerate(prs.slides, start=1):
453
+ shapes = list(slide.shapes)
454
+ for shape_idx, shape in enumerate(shapes, start=1):
455
+ if shape.shape_type != MSO_SHAPE_TYPE.PICTURE or not _EVIDENCE_MARKER.search(_semantic_label(shape)):
456
+ continue
457
+ checked += 1
458
+ figure_box = _bbox_in(shape)
459
+ nearby: list[str] = []
460
+ if figure_box is not None:
461
+ figure_width = figure_box[2] - figure_box[0]
462
+ for other in shapes:
463
+ text = _shape_text(other)
464
+ other_box = _bbox_in(other)
465
+ if not text or other_box is None:
466
+ continue
467
+ horizontal = min(figure_box[2], other_box[2]) - max(figure_box[0], other_box[0])
468
+ vertical_gap = other_box[1] - figure_box[3]
469
+ if horizontal >= figure_width * 0.2 and -0.04 <= vertical_gap <= 1.1:
470
+ nearby.append(text)
471
+ bound_text = "\n".join(nearby)
472
+ missing = []
473
+ if not _CAPTION_MARKER.search(bound_text):
474
+ missing.append("caption")
475
+ if not _SOURCE_MARKER.search(bound_text):
476
+ missing.append("source")
477
+ if missing:
478
+ violations.append({
479
+ "slide": slide_idx,
480
+ "shape": shape_idx,
481
+ "label": _semantic_label(shape)[:100],
482
+ "missing": missing,
483
+ })
484
+ return {"pass": not violations, "checked_figures": checked, "violations": violations[:30]}
485
+
486
+
487
+ _APPENDIX_MARKER = re.compile(r"\bappendix\b|부록", re.IGNORECASE)
488
+ _RAW_URL = re.compile(r"https?://[^\s<>\]\[)}]+", re.IGNORECASE)
489
+ _DOI_VALUE = re.compile(r"(?<!doi\.org/)\b10\.\d{4,9}/[^\s<>\]\[)}]+", re.IGNORECASE)
490
+ _LINK_FIELD = re.compile(
491
+ r"\bdoi\b|canonical\s+link|source\s+link|정식\s*링크|원문(?:\s*링크)?",
492
+ re.IGNORECASE,
493
+ )
494
+ _SOURCE_LOCATOR = re.compile(r"\bsource\b|출처", re.IGNORECASE)
495
+
496
+
497
+ def _appendix_link_units(shape):
498
+ """Yield visible text and run-level hyperlink targets per paragraph/cell."""
499
+ if getattr(shape, "has_table", False):
500
+ headers = [cell.text.strip() for cell in shape.table.rows[0].cells]
501
+ for row_idx, row in enumerate(shape.table.rows):
502
+ if row_idx == 0:
503
+ continue
504
+ for column_idx, cell in enumerate(row.cells):
505
+ for paragraph in cell.text_frame.paragraphs:
506
+ runs = [(run.text, run.hyperlink.address) for run in paragraph.runs if run.text]
507
+ text = "".join(run_text for run_text, _ in runs).strip()
508
+ if text:
509
+ yield (
510
+ text,
511
+ [address for _, address in runs if address],
512
+ bool(
513
+ _LINK_FIELD.search(headers[column_idx])
514
+ or (
515
+ _SOURCE_LOCATOR.search(headers[column_idx])
516
+ and any(address for _, address in runs)
517
+ )
518
+ ),
519
+ )
520
+ return
521
+ if getattr(shape, "has_text_frame", False):
522
+ for paragraph in shape.text_frame.paragraphs:
523
+ runs = [(run.text, run.hyperlink.address) for run in paragraph.runs if run.text]
524
+ text = "".join(run_text for run_text, _ in runs).strip()
525
+ if text:
526
+ run_links = [address for _, address in runs if address]
527
+ yield text, run_links, bool(
528
+ _LINK_FIELD.search(text)
529
+ or (_SOURCE_LOCATOR.search(text) and run_links)
530
+ )
531
+
532
+
533
+ def _slide_hyperlink_targets(slide) -> list[str]:
534
+ targets = []
535
+ for relationship in slide.part.rels.values():
536
+ if relationship.reltype == RT.HYPERLINK and relationship.is_external:
537
+ targets.append(relationship.target_ref)
538
+ return targets
539
+
540
+
541
+ def check_appendix_links(path: Path) -> dict[str, Any]:
542
+ """Appendix DOI, canonical-link, and raw-URL fields must be clickable."""
543
+ prs = Presentation(str(path))
544
+ violations: list[dict[str, Any]] = []
545
+ declared = 0
546
+ relationship_targets: list[str] = []
547
+ for slide_idx, slide in enumerate(prs.slides, start=1):
548
+ slide_text = "\n".join(_shape_text(shape) for shape in slide.shapes)
549
+ if not _APPENDIX_MARKER.search(slide_text):
550
+ continue
551
+ slide_targets = _slide_hyperlink_targets(slide)
552
+ relationship_targets.extend(slide_targets)
553
+ for shape_idx, shape in enumerate(slide.shapes, start=1):
554
+ for text, run_links, is_link_field in _appendix_link_units(shape):
555
+ raw_urls = [url.rstrip(".,;:") for url in _RAW_URL.findall(text)]
556
+ doi_values = [] if raw_urls else [doi.rstrip(".,;:") for doi in _DOI_VALUE.findall(text)]
557
+ candidates = raw_urls or doi_values
558
+ if not candidates and is_link_field:
559
+ candidates = [run_links[0]] if run_links else [None]
560
+ for candidate in candidates:
561
+ declared += 1
562
+ if candidate is None:
563
+ linked = False
564
+ elif candidate.startswith(("http://", "https://")):
565
+ linked = candidate in run_links and candidate in slide_targets
566
+ else:
567
+ linked = any(
568
+ candidate.lower() in target.lower() and target in run_links
569
+ for target in slide_targets
570
+ )
571
+ if not linked:
572
+ violations.append({
573
+ "slide": slide_idx,
574
+ "shape": shape_idx,
575
+ "text": text[:100],
576
+ "locator": candidate,
577
+ "missing": "OOXML hyperlink relationship",
578
+ })
579
+ return {
580
+ "pass": not violations,
581
+ "declared_links": declared,
582
+ "hyperlink_relationships": len(relationship_targets),
583
+ "relationship_targets": relationship_targets[:20],
584
+ "violations": violations[:30],
585
+ }
586
+
587
+
588
+ def check_objective_quality(path: Path) -> dict[str, Any]:
589
+ checks = {
590
+ "side_stripes": check_side_stripes(path),
591
+ "text_size_floor": check_text_size_floor(path),
592
+ "figure_table_occlusion": check_figure_table_occlusion(path),
593
+ "evidence_binding": check_evidence_binding(path),
594
+ "appendix_links": check_appendix_links(path),
595
+ }
596
+ return {"pass": all(check["pass"] for check in checks.values()), **checks}
597
+
598
+
599
+ # ── inventory issues ───────────────────────────────────────────────────────
600
+ def load_inventory_issues(pptx: Path) -> dict[str, Any]:
601
+ with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as tmp:
602
+ tmp_path = Path(tmp.name)
603
+ try:
604
+ subprocess.run(
605
+ [sys.executable, str(INVENTORY), str(pptx), str(tmp_path), "--issues-only"],
606
+ capture_output=True, text=True, cwd=ROOT, timeout=120,
607
+ )
608
+ return json.loads(tmp_path.read_text(encoding="utf-8")) if tmp_path.exists() and tmp_path.stat().st_size else {}
609
+ finally:
610
+ tmp_path.unlink(missing_ok=True)
611
+
612
+
613
+ def summarize_inventory(issues: dict[str, Any]) -> dict[str, Any]:
614
+ if not issues:
615
+ # No inventory is not a clean inventory: report it so the gate fails.
616
+ return {"available": False, "issue_shapes": 0, "overflow_shapes": 0, "slide_overflow_shapes": 0,
617
+ "frame_overflow_shapes": 0, "off_slide_shapes": 0, "overlap_shapes": 0, "details": []}
618
+ shape_count = overflow = slide_overflow = frame_overflow = off_slide = overlap = 0
619
+ details: list[dict[str, Any]] = []
620
+ for slide in issues.get("slides", []):
621
+ for shape in slide.get("shapes", []):
622
+ found = shape.get("issues") or {}
623
+ if not found:
624
+ continue
625
+ shape_count += 1
626
+ defect = False
627
+ if "frame_overflow" in found:
628
+ frame_overflow += 1
629
+ defect = True
630
+ if "slide_overflow" in found:
631
+ slide_overflow += 1
632
+ defect = True
633
+ if "off_slide" in found:
634
+ off_slide += 1
635
+ defect = True
636
+ if defect:
637
+ overflow += 1
638
+ details.append({"slide": slide.get("slide"), "shape": shape.get("name"),
639
+ **{k: v for k, v in found.items() if k != "overlaps"}})
640
+ # Reported only — see qa(): raw box overlap has no notion of z-order.
641
+ if found.get("overlaps"):
642
+ overlap += 1
643
+ return {
644
+ "available": True,
645
+ "issue_shapes": shape_count,
646
+ "overflow_shapes": overflow,
647
+ "slide_overflow_shapes": slide_overflow,
648
+ "frame_overflow_shapes": frame_overflow,
649
+ "off_slide_shapes": off_slide,
650
+ "overlap_shapes": overlap,
651
+ "details": details[:30],
652
+ }
653
+
654
+
655
+ def run_validate(pptx: Path) -> dict[str, Any]:
656
+ result = subprocess.run(
657
+ [sys.executable, str(VALIDATE), str(pptx)],
658
+ capture_output=True, text=True, cwd=ROOT, timeout=120,
659
+ )
660
+ try:
661
+ return json.loads(result.stdout)
662
+ except json.JSONDecodeError:
663
+ return {"pass": False, "error": "validate_pptx produced no JSON", "stderr": result.stderr[:400]}
664
+
665
+
666
+ # ── gate ───────────────────────────────────────────────────────────────────
667
+ def qa(pptx: Path) -> dict[str, Any]:
668
+ from ooxml_integrity import check_package
669
+ from deck_craft import analyse as analyse_craft
670
+ from craft_extras import analyse as analyse_extras
671
+
672
+ integrity = check_package(pptx)
673
+ craft = analyse_craft(pptx)
674
+ extras = analyse_extras(pptx)
675
+ validate_report = run_validate(pptx)
676
+ inv_summary = summarize_inventory(load_inventory_issues(pptx))
677
+ contrast = check_contrast(pptx)
678
+ overlaps = check_overlaps(pptx)
679
+ semantic = check_semantic_overlaps(pptx)
680
+ objective = check_objective_quality(pptx)
681
+
682
+ reasons: list[str] = []
683
+ if not integrity["pass"]:
684
+ reasons.append("integrity: " + "; ".join(integrity["problems"][:5]))
685
+ by_check: dict[str, list] = {}
686
+ for finding in craft["findings"]:
687
+ by_check.setdefault(finding["check"], []).append(finding)
688
+ for check, found in by_check.items():
689
+ slides = sorted({f["slide"] for f in found if f["slide"] is not None})
690
+ where = f" on slide(s) {', '.join(map(str, slides))}" if slides else ""
691
+ reasons.append(f"craft {check}{where} — {found[0]['hint']}")
692
+ extras_high: dict[str, list] = {}
693
+ for finding in extras["findings"]:
694
+ if finding["severity"] == "HIGH":
695
+ extras_high.setdefault(finding["check"], []).append(finding)
696
+ for check, found in extras_high.items():
697
+ slides = sorted({f["slide"] for f in found if f["slide"] is not None})
698
+ reasons.append(f"craft {check} on slide(s) {', '.join(map(str, slides))} — {found[0]['hint']}")
699
+ if not validate_report.get("pass", False):
700
+ reasons.append("anti-slop: " + ", ".join(
701
+ k for k, v in validate_report.get("checks", {}).items() if isinstance(v, dict) and not v.get("pass", True)
702
+ ) or "anti-slop: validate_pptx failed")
703
+ # Fail only on real layout defects: text spilling out of its frame, text or a
704
+ # grown table running past the canvas, a text box placed off the canvas.
705
+ #
706
+ # inv_summary["overlap_shapes"] is deliberately NOT part of this sum. It is
707
+ # raw pairwise geometry with no notion of z-order or shape kind, so every
708
+ # tinted card counts its own text as an overlap. check_semantic_overlaps owns
709
+ # the overlap verdict; this number is carried in the report for transparency.
710
+ layout_defects = inv_summary["overflow_shapes"]
711
+ if not inv_summary["available"]:
712
+ reasons.append("layout: the layout inventory produced no report")
713
+ if layout_defects:
714
+ reasons.append(
715
+ f"layout defects: {layout_defects} shapes "
716
+ f"({inv_summary['slide_overflow_shapes']} slide-overflow, "
717
+ f"{inv_summary['frame_overflow_shapes']} frame-overflow, "
718
+ f"{inv_summary['off_slide_shapes']} off-slide)"
719
+ )
720
+ if not contrast["pass"]:
721
+ reasons.append(f"contrast: {len(contrast['violations'])} run(s) below WCAG floor")
722
+ if not overlaps["pass"]:
723
+ reasons.append(
724
+ f"overlap: {len(overlaps['violations'])} picture/table shape(s) drawn over other content"
725
+ )
726
+ if not semantic["pass"]:
727
+ reasons.append(
728
+ f"semantic overlap: {len(semantic['violations'])} content pair(s) occluding each other"
729
+ )
730
+ if not objective["pass"]:
731
+ failed = [name for name, check in objective.items() if isinstance(check, dict) and not check.get("pass", True)]
732
+ reasons.append("objective quality: " + ", ".join(failed))
733
+
734
+ return {
735
+ "file": str(pptx),
736
+ "pass": not reasons,
737
+ "integrity": {"pass": integrity["pass"], "problems": integrity["problems"][:20]},
738
+ "craft": {"pass": craft["pass"], "slides": craft["slides"], "findings": craft["findings"][:40]},
739
+ "craft_floor": {"pass": not extras_high,
740
+ "findings": [f for f in extras["findings"] if f["severity"] == "HIGH"][:40],
741
+ "advisories": [f for f in extras["findings"] if f["severity"] != "HIGH"][:40]},
742
+ "failure_reasons": reasons,
743
+ "anti_slop": {
744
+ "pass": validate_report.get("pass"),
745
+ "slop_score": validate_report.get("slop_score"),
746
+ "review_warnings": validate_report.get("checks", {}).get("forbidden_terms", {}).get("soft_warnings", []),
747
+ },
748
+ "layout": {**inv_summary, "picture_table_overlaps": len(overlaps["violations"])},
749
+ "contrast": contrast,
750
+ "overlaps": overlaps,
751
+ "semantic_overlaps": semantic,
752
+ "objective": objective,
753
+ }
754
+
755
+
756
+ def main(argv: list[str] | None = None) -> int:
757
+ parser = argparse.ArgumentParser(description="Honest renderer-agnostic QA gate for PPTX decks.")
758
+ parser.add_argument("pptx", type=Path)
759
+ args = parser.parse_args(argv)
760
+ report = qa(args.pptx.resolve())
761
+ print(json.dumps(report, ensure_ascii=False, indent=2))
762
+ return 0 if report["pass"] else 1
763
+
764
+
765
+ if __name__ == "__main__":
766
+ raise SystemExit(main())