@litfamily/litopencode 1.0.7 → 1.0.10

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