@oriro/orirocli 0.1.8 → 0.1.9

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 (350) hide show
  1. package/ATTRIBUTION.md +8 -0
  2. package/LICENSE +21 -0
  3. package/package.json +1 -1
  4. package/skills/21stdev/SKILL.md +64 -0
  5. package/skills/graphify/SKILL.md +619 -0
  6. package/skills/graphify/__init__.py +28 -0
  7. package/skills/graphify/__main__.py +4582 -0
  8. package/skills/graphify/affected.py +154 -0
  9. package/skills/graphify/always_on/agents-md.md +12 -0
  10. package/skills/graphify/always_on/antigravity-rules.md +14 -0
  11. package/skills/graphify/always_on/claude-md.md +9 -0
  12. package/skills/graphify/always_on/gemini-md.md +9 -0
  13. package/skills/graphify/always_on/kiro-steering.md +5 -0
  14. package/skills/graphify/always_on/vscode-instructions.md +17 -0
  15. package/skills/graphify/analyze.py +724 -0
  16. package/skills/graphify/benchmark.py +155 -0
  17. package/skills/graphify/build.py +487 -0
  18. package/skills/graphify/cache.py +417 -0
  19. package/skills/graphify/callflow_html.py +2020 -0
  20. package/skills/graphify/cluster.py +272 -0
  21. package/skills/graphify/command-kilo.md +15 -0
  22. package/skills/graphify/dedup.py +429 -0
  23. package/skills/graphify/detect.py +1379 -0
  24. package/skills/graphify/diagnostics.py +390 -0
  25. package/skills/graphify/export.py +1408 -0
  26. package/skills/graphify/extract.py +11570 -0
  27. package/skills/graphify/global_graph.py +159 -0
  28. package/skills/graphify/google_workspace.py +223 -0
  29. package/skills/graphify/hooks.py +457 -0
  30. package/skills/graphify/ingest.py +331 -0
  31. package/skills/graphify/llm.py +1896 -0
  32. package/skills/graphify/manifest.py +4 -0
  33. package/skills/graphify/mcp_ingest.py +392 -0
  34. package/skills/graphify/multigraph_compat.py +212 -0
  35. package/skills/graphify/pg_introspect.py +142 -0
  36. package/skills/graphify/prs.py +748 -0
  37. package/skills/graphify/querylog.py +70 -0
  38. package/skills/graphify/report.py +218 -0
  39. package/skills/graphify/scip_ingest.py +363 -0
  40. package/skills/graphify/security.py +336 -0
  41. package/skills/graphify/semantic_cleanup.py +319 -0
  42. package/skills/graphify/serve.py +1309 -0
  43. package/skills/graphify/skill-aider.md +1246 -0
  44. package/skills/graphify/skill-amp.md +613 -0
  45. package/skills/graphify/skill-claw.md +616 -0
  46. package/skills/graphify/skill-codex.md +613 -0
  47. package/skills/graphify/skill-copilot.md +616 -0
  48. package/skills/graphify/skill-devin.md +1372 -0
  49. package/skills/graphify/skill-droid.md +613 -0
  50. package/skills/graphify/skill-kilo.md +625 -0
  51. package/skills/graphify/skill-kiro.md +615 -0
  52. package/skills/graphify/skill-opencode.md +608 -0
  53. package/skills/graphify/skill-pi.md +615 -0
  54. package/skills/graphify/skill-trae.md +614 -0
  55. package/skills/graphify/skill-vscode.md +612 -0
  56. package/skills/graphify/skill-windows.md +651 -0
  57. package/skills/graphify/skills/amp/references/add-watch.md +56 -0
  58. package/skills/graphify/skills/amp/references/exports.md +71 -0
  59. package/skills/graphify/skills/amp/references/extraction-spec.md +68 -0
  60. package/skills/graphify/skills/amp/references/github-and-merge.md +46 -0
  61. package/skills/graphify/skills/amp/references/hooks.md +33 -0
  62. package/skills/graphify/skills/amp/references/query.md +249 -0
  63. package/skills/graphify/skills/amp/references/transcribe.md +48 -0
  64. package/skills/graphify/skills/amp/references/update.md +179 -0
  65. package/skills/graphify/skills/claude/references/add-watch.md +56 -0
  66. package/skills/graphify/skills/claude/references/exports.md +71 -0
  67. package/skills/graphify/skills/claude/references/extraction-spec.md +68 -0
  68. package/skills/graphify/skills/claude/references/github-and-merge.md +46 -0
  69. package/skills/graphify/skills/claude/references/hooks.md +33 -0
  70. package/skills/graphify/skills/claude/references/query.md +103 -0
  71. package/skills/graphify/skills/claude/references/transcribe.md +48 -0
  72. package/skills/graphify/skills/claude/references/update.md +179 -0
  73. package/skills/graphify/skills/claw/references/add-watch.md +56 -0
  74. package/skills/graphify/skills/claw/references/exports.md +71 -0
  75. package/skills/graphify/skills/claw/references/extraction-spec.md +29 -0
  76. package/skills/graphify/skills/claw/references/github-and-merge.md +46 -0
  77. package/skills/graphify/skills/claw/references/hooks.md +33 -0
  78. package/skills/graphify/skills/claw/references/query.md +249 -0
  79. package/skills/graphify/skills/claw/references/transcribe.md +48 -0
  80. package/skills/graphify/skills/claw/references/update.md +179 -0
  81. package/skills/graphify/skills/codex/references/add-watch.md +56 -0
  82. package/skills/graphify/skills/codex/references/exports.md +71 -0
  83. package/skills/graphify/skills/codex/references/extraction-spec.md +29 -0
  84. package/skills/graphify/skills/codex/references/github-and-merge.md +46 -0
  85. package/skills/graphify/skills/codex/references/hooks.md +33 -0
  86. package/skills/graphify/skills/codex/references/query.md +249 -0
  87. package/skills/graphify/skills/codex/references/transcribe.md +48 -0
  88. package/skills/graphify/skills/codex/references/update.md +179 -0
  89. package/skills/graphify/skills/copilot/references/add-watch.md +56 -0
  90. package/skills/graphify/skills/copilot/references/exports.md +71 -0
  91. package/skills/graphify/skills/copilot/references/extraction-spec.md +68 -0
  92. package/skills/graphify/skills/copilot/references/github-and-merge.md +46 -0
  93. package/skills/graphify/skills/copilot/references/hooks.md +33 -0
  94. package/skills/graphify/skills/copilot/references/query.md +249 -0
  95. package/skills/graphify/skills/copilot/references/transcribe.md +48 -0
  96. package/skills/graphify/skills/copilot/references/update.md +179 -0
  97. package/skills/graphify/skills/droid/references/add-watch.md +56 -0
  98. package/skills/graphify/skills/droid/references/exports.md +71 -0
  99. package/skills/graphify/skills/droid/references/extraction-spec.md +68 -0
  100. package/skills/graphify/skills/droid/references/github-and-merge.md +46 -0
  101. package/skills/graphify/skills/droid/references/hooks.md +33 -0
  102. package/skills/graphify/skills/droid/references/query.md +249 -0
  103. package/skills/graphify/skills/droid/references/transcribe.md +48 -0
  104. package/skills/graphify/skills/droid/references/update.md +179 -0
  105. package/skills/graphify/skills/kilo/references/add-watch.md +56 -0
  106. package/skills/graphify/skills/kilo/references/exports.md +71 -0
  107. package/skills/graphify/skills/kilo/references/extraction-spec.md +68 -0
  108. package/skills/graphify/skills/kilo/references/github-and-merge.md +46 -0
  109. package/skills/graphify/skills/kilo/references/hooks.md +33 -0
  110. package/skills/graphify/skills/kilo/references/query.md +249 -0
  111. package/skills/graphify/skills/kilo/references/transcribe.md +48 -0
  112. package/skills/graphify/skills/kilo/references/update.md +179 -0
  113. package/skills/graphify/skills/kiro/references/add-watch.md +56 -0
  114. package/skills/graphify/skills/kiro/references/exports.md +71 -0
  115. package/skills/graphify/skills/kiro/references/extraction-spec.md +29 -0
  116. package/skills/graphify/skills/kiro/references/github-and-merge.md +46 -0
  117. package/skills/graphify/skills/kiro/references/hooks.md +33 -0
  118. package/skills/graphify/skills/kiro/references/query.md +249 -0
  119. package/skills/graphify/skills/kiro/references/transcribe.md +48 -0
  120. package/skills/graphify/skills/kiro/references/update.md +179 -0
  121. package/skills/graphify/skills/opencode/references/add-watch.md +56 -0
  122. package/skills/graphify/skills/opencode/references/exports.md +71 -0
  123. package/skills/graphify/skills/opencode/references/extraction-spec.md +68 -0
  124. package/skills/graphify/skills/opencode/references/github-and-merge.md +46 -0
  125. package/skills/graphify/skills/opencode/references/hooks.md +33 -0
  126. package/skills/graphify/skills/opencode/references/query.md +249 -0
  127. package/skills/graphify/skills/opencode/references/transcribe.md +48 -0
  128. package/skills/graphify/skills/opencode/references/update.md +179 -0
  129. package/skills/graphify/skills/pi/references/add-watch.md +56 -0
  130. package/skills/graphify/skills/pi/references/exports.md +71 -0
  131. package/skills/graphify/skills/pi/references/extraction-spec.md +29 -0
  132. package/skills/graphify/skills/pi/references/github-and-merge.md +46 -0
  133. package/skills/graphify/skills/pi/references/hooks.md +33 -0
  134. package/skills/graphify/skills/pi/references/query.md +249 -0
  135. package/skills/graphify/skills/pi/references/transcribe.md +48 -0
  136. package/skills/graphify/skills/pi/references/update.md +179 -0
  137. package/skills/graphify/skills/trae/references/add-watch.md +56 -0
  138. package/skills/graphify/skills/trae/references/exports.md +71 -0
  139. package/skills/graphify/skills/trae/references/extraction-spec.md +68 -0
  140. package/skills/graphify/skills/trae/references/github-and-merge.md +46 -0
  141. package/skills/graphify/skills/trae/references/hooks.md +35 -0
  142. package/skills/graphify/skills/trae/references/query.md +249 -0
  143. package/skills/graphify/skills/trae/references/transcribe.md +48 -0
  144. package/skills/graphify/skills/trae/references/update.md +179 -0
  145. package/skills/graphify/skills/vscode/references/add-watch.md +56 -0
  146. package/skills/graphify/skills/vscode/references/exports.md +71 -0
  147. package/skills/graphify/skills/vscode/references/extraction-spec.md +68 -0
  148. package/skills/graphify/skills/vscode/references/github-and-merge.md +46 -0
  149. package/skills/graphify/skills/vscode/references/hooks.md +33 -0
  150. package/skills/graphify/skills/vscode/references/query.md +249 -0
  151. package/skills/graphify/skills/vscode/references/transcribe.md +48 -0
  152. package/skills/graphify/skills/vscode/references/update.md +179 -0
  153. package/skills/graphify/skills/windows/references/add-watch.md +56 -0
  154. package/skills/graphify/skills/windows/references/exports.md +71 -0
  155. package/skills/graphify/skills/windows/references/extraction-spec.md +68 -0
  156. package/skills/graphify/skills/windows/references/github-and-merge.md +46 -0
  157. package/skills/graphify/skills/windows/references/hooks.md +33 -0
  158. package/skills/graphify/skills/windows/references/query.md +249 -0
  159. package/skills/graphify/skills/windows/references/transcribe.md +48 -0
  160. package/skills/graphify/skills/windows/references/update.md +179 -0
  161. package/skills/graphify/symbol_resolution.py +538 -0
  162. package/skills/graphify/transcribe.py +184 -0
  163. package/skills/graphify/tree_html.py +582 -0
  164. package/skills/graphify/validate.py +72 -0
  165. package/skills/graphify/watch.py +898 -0
  166. package/skills/graphify/wiki.py +282 -0
  167. package/skills/impeccable/SKILL.md +186 -0
  168. package/skills/impeccable/agents/impeccable_asset_producer.toml +92 -0
  169. package/skills/impeccable/agents/impeccable_manual_edit_applier.toml +95 -0
  170. package/skills/impeccable/agents/openai.yaml +4 -0
  171. package/skills/impeccable/reference/adapt.md +311 -0
  172. package/skills/impeccable/reference/animate.md +201 -0
  173. package/skills/impeccable/reference/audit.md +133 -0
  174. package/skills/impeccable/reference/bolder.md +113 -0
  175. package/skills/impeccable/reference/brand.md +108 -0
  176. package/skills/impeccable/reference/clarify.md +288 -0
  177. package/skills/impeccable/reference/codex.md +105 -0
  178. package/skills/impeccable/reference/colorize.md +257 -0
  179. package/skills/impeccable/reference/craft.md +123 -0
  180. package/skills/impeccable/reference/critique.md +790 -0
  181. package/skills/impeccable/reference/delight.md +302 -0
  182. package/skills/impeccable/reference/distill.md +111 -0
  183. package/skills/impeccable/reference/document.md +429 -0
  184. package/skills/impeccable/reference/extract.md +69 -0
  185. package/skills/impeccable/reference/harden.md +347 -0
  186. package/skills/impeccable/reference/init.md +172 -0
  187. package/skills/impeccable/reference/interaction-design.md +189 -0
  188. package/skills/impeccable/reference/layout.md +161 -0
  189. package/skills/impeccable/reference/live.md +720 -0
  190. package/skills/impeccable/reference/onboard.md +234 -0
  191. package/skills/impeccable/reference/optimize.md +258 -0
  192. package/skills/impeccable/reference/overdrive.md +130 -0
  193. package/skills/impeccable/reference/polish.md +241 -0
  194. package/skills/impeccable/reference/product.md +60 -0
  195. package/skills/impeccable/reference/quieter.md +99 -0
  196. package/skills/impeccable/reference/shape.md +165 -0
  197. package/skills/impeccable/reference/typeset.md +279 -0
  198. package/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  199. package/skills/impeccable/scripts/command-metadata.json +94 -0
  200. package/skills/impeccable/scripts/context-signals.mjs +225 -0
  201. package/skills/impeccable/scripts/context.mjs +266 -0
  202. package/skills/impeccable/scripts/critique-storage.mjs +242 -0
  203. package/skills/impeccable/scripts/design-parser.mjs +835 -0
  204. package/skills/impeccable/scripts/detect-csp.mjs +198 -0
  205. package/skills/impeccable/scripts/detect.mjs +21 -0
  206. package/skills/impeccable/scripts/detector/browser/injected/index.mjs +1733 -0
  207. package/skills/impeccable/scripts/detector/cli/main.mjs +244 -0
  208. package/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +4618 -0
  209. package/skills/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
  210. package/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
  211. package/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
  212. package/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
  213. package/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
  214. package/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
  215. package/skills/impeccable/scripts/detector/findings.mjs +12 -0
  216. package/skills/impeccable/scripts/detector/node/file-system.mjs +198 -0
  217. package/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
  218. package/skills/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
  219. package/skills/impeccable/scripts/detector/rules/checks.mjs +2384 -0
  220. package/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
  221. package/skills/impeccable/scripts/detector/shared/constants.mjs +101 -0
  222. package/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
  223. package/skills/impeccable/scripts/impeccable-paths.mjs +126 -0
  224. package/skills/impeccable/scripts/is-generated.mjs +69 -0
  225. package/skills/impeccable/scripts/live-accept.mjs +812 -0
  226. package/skills/impeccable/scripts/live-browser-session.js +123 -0
  227. package/skills/impeccable/scripts/live-browser.js +10295 -0
  228. package/skills/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
  229. package/skills/impeccable/scripts/live-complete.mjs +75 -0
  230. package/skills/impeccable/scripts/live-completion.mjs +19 -0
  231. package/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
  232. package/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
  233. package/skills/impeccable/scripts/live-event-validation.mjs +137 -0
  234. package/skills/impeccable/scripts/live-inject.mjs +557 -0
  235. package/skills/impeccable/scripts/live-insert-ui.mjs +458 -0
  236. package/skills/impeccable/scripts/live-insert.mjs +272 -0
  237. package/skills/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
  238. package/skills/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
  239. package/skills/impeccable/scripts/live-poll.mjs +379 -0
  240. package/skills/impeccable/scripts/live-resume.mjs +94 -0
  241. package/skills/impeccable/scripts/live-server.mjs +2326 -0
  242. package/skills/impeccable/scripts/live-session-store.mjs +289 -0
  243. package/skills/impeccable/scripts/live-status.mjs +61 -0
  244. package/skills/impeccable/scripts/live-svelte-component.mjs +826 -0
  245. package/skills/impeccable/scripts/live-sveltekit-adapter.mjs +274 -0
  246. package/skills/impeccable/scripts/live-ui-core.mjs +179 -0
  247. package/skills/impeccable/scripts/live-vocabulary.mjs +36 -0
  248. package/skills/impeccable/scripts/live-wrap.mjs +894 -0
  249. package/skills/impeccable/scripts/live.mjs +246 -0
  250. package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  251. package/skills/impeccable/scripts/palette.mjs +633 -0
  252. package/skills/impeccable/scripts/pin.mjs +214 -0
  253. package/skills/uipm-ui-styling/LICENSE.txt +202 -0
  254. package/skills/uipm-ui-styling/SKILL.md +328 -0
  255. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  256. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  257. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  258. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  259. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  260. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  261. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  262. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  263. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  264. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  265. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  266. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  267. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  268. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  269. package/skills/uipm-ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  270. package/skills/uipm-ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  271. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  272. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  273. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  274. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  275. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  276. package/skills/uipm-ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  277. package/skills/uipm-ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  278. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  279. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  280. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  281. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  282. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  283. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  284. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  285. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  286. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  287. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  288. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  289. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  290. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  291. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  292. package/skills/uipm-ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  293. package/skills/uipm-ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  294. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  295. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  296. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  297. package/skills/uipm-ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  298. package/skills/uipm-ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  299. package/skills/uipm-ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  300. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  301. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  302. package/skills/uipm-ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  303. package/skills/uipm-ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  304. package/skills/uipm-ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  305. package/skills/uipm-ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  306. package/skills/uipm-ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  307. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  308. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  309. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  310. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  311. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  312. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  313. package/skills/uipm-ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  314. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  315. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  316. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  317. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  318. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  319. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  320. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  321. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  322. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  323. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  324. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  325. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  326. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  327. package/skills/uipm-ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  328. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  329. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  330. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  331. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  332. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  333. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  334. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  335. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  336. package/skills/uipm-ui-styling/references/canvas-design-system.md +320 -0
  337. package/skills/uipm-ui-styling/references/shadcn-accessibility.md +471 -0
  338. package/skills/uipm-ui-styling/references/shadcn-components.md +424 -0
  339. package/skills/uipm-ui-styling/references/shadcn-theming.md +373 -0
  340. package/skills/uipm-ui-styling/references/tailwind-customization.md +483 -0
  341. package/skills/uipm-ui-styling/references/tailwind-responsive.md +382 -0
  342. package/skills/uipm-ui-styling/references/tailwind-utilities.md +455 -0
  343. package/skills/uipm-ui-styling/scripts/.coverage +0 -0
  344. package/skills/uipm-ui-styling/scripts/requirements.txt +17 -0
  345. package/skills/uipm-ui-styling/scripts/shadcn_add.py +292 -0
  346. package/skills/uipm-ui-styling/scripts/tailwind_config_gen.py +456 -0
  347. package/skills/uipm-ui-styling/scripts/tests/coverage-ui.json +1 -0
  348. package/skills/uipm-ui-styling/scripts/tests/requirements.txt +3 -0
  349. package/skills/uipm-ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  350. package/skills/uipm-ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
@@ -0,0 +1,417 @@
1
+ # per-file extraction cache - skip unchanged files on re-run
2
+ from __future__ import annotations
3
+
4
+ import atexit
5
+ import hashlib
6
+ import json
7
+ import os
8
+ import tempfile
9
+ from pathlib import Path
10
+
11
+ # Output directory name — override with GRAPHIFY_OUT env var for worktrees or
12
+ # shared-output setups. Accepts a relative name ("graphify-out-feature") or an
13
+ # absolute path ("/shared/graphify-out").
14
+ _GRAPHIFY_OUT = os.environ.get("GRAPHIFY_OUT", "graphify-out")
15
+
16
+
17
+ def _body_content(content: bytes) -> bytes:
18
+ """Strip YAML frontmatter from Markdown content, returning only the body."""
19
+ text = content.decode(errors="replace")
20
+ if text.startswith("---"):
21
+ end = text.find("\n---", 3)
22
+ if end != -1:
23
+ return text[end + 4:].encode()
24
+ return content
25
+
26
+
27
+ # Stat-based index: maps absolute path → {size, mtime_ns, hash}.
28
+ # Loaded once per process, flushed via atexit. Skips full file reads when
29
+ # size+mtime_ns are unchanged — same trade-off as make(1).
30
+ # Correctness risks: `touch` causes a harmless extra re-hash; same-size edits
31
+ # within NFS second-resolution mtime have a 1-second window (same as make).
32
+ # Use `graphify extract --force` to bypass when needed.
33
+ _stat_index: dict[str, dict] = {}
34
+ _stat_index_root: Path | None = None
35
+ _stat_index_dirty: bool = False
36
+
37
+
38
+ def _stat_index_file(root: Path) -> Path:
39
+ _out = Path(_GRAPHIFY_OUT)
40
+ base = _out if _out.is_absolute() else Path(root).resolve() / _out
41
+ return base / "cache" / "stat-index.json"
42
+
43
+
44
+ def _ensure_stat_index(root: Path) -> None:
45
+ global _stat_index, _stat_index_root, _stat_index_dirty
46
+ if _stat_index_root is not None:
47
+ return
48
+ _stat_index_root = Path(root).resolve()
49
+ p = _stat_index_file(_stat_index_root)
50
+ if p.exists():
51
+ try:
52
+ _stat_index = json.loads(p.read_text(encoding="utf-8"))
53
+ except (json.JSONDecodeError, OSError):
54
+ _stat_index = {}
55
+ else:
56
+ _stat_index = {}
57
+ atexit.register(_flush_stat_index)
58
+
59
+
60
+ def _flush_stat_index() -> None:
61
+ global _stat_index_dirty, _stat_index_root
62
+ if not _stat_index_dirty or _stat_index_root is None:
63
+ return
64
+ p = _stat_index_file(_stat_index_root)
65
+ try:
66
+ p.parent.mkdir(parents=True, exist_ok=True)
67
+ fd, tmp = tempfile.mkstemp(dir=p.parent, prefix="stat-index.", suffix=".tmp")
68
+ try:
69
+ os.write(fd, json.dumps(_stat_index, separators=(",", ":")).encode())
70
+ os.close(fd)
71
+ os.replace(tmp, p)
72
+ except Exception:
73
+ try:
74
+ os.close(fd)
75
+ except OSError:
76
+ pass
77
+ try:
78
+ os.unlink(tmp)
79
+ except OSError:
80
+ pass
81
+ except OSError:
82
+ pass
83
+ _stat_index_dirty = False
84
+
85
+
86
+ def _normalize_path(path: Path) -> Path:
87
+ """Normalize path for consistent cache keys across Windows path spellings."""
88
+ import sys
89
+ if sys.platform != "win32":
90
+ return path
91
+ s = str(path)
92
+ if s.startswith("\\\\?\\"):
93
+ s = s[4:] # strip extended-length prefix \\?\
94
+ return Path(os.path.normcase(s))
95
+
96
+
97
+ def file_hash(path: Path, root: Path = Path(".")) -> str:
98
+ """SHA256 of file contents + path relative to root.
99
+
100
+ Uses a stat-based fastpath (size + mtime_ns) to skip full reads when the
101
+ file hasn't changed. Falls through to full SHA256 on first encounter or
102
+ when stat changes. Index is flushed atomically at process exit.
103
+
104
+ Using a relative path (not absolute) makes cache entries portable across
105
+ machines and checkout directories, so shared caches and CI work correctly.
106
+ Falls back to the resolved absolute path if the file is outside root.
107
+
108
+ For Markdown files (.md), only the body below the YAML frontmatter is hashed,
109
+ so metadata-only changes (e.g. reviewed, status, tags) do not invalidate the cache.
110
+ """
111
+ global _stat_index_dirty
112
+ p = _normalize_path(Path(path))
113
+ root = _normalize_path(Path(root))
114
+ if not p.is_file():
115
+ raise IsADirectoryError(f"file_hash requires a file, got: {p}")
116
+
117
+ _ensure_stat_index(root)
118
+ abs_key = str(p.resolve())
119
+ st: "os.stat_result | None" = None
120
+ try:
121
+ st = p.stat()
122
+ entry = _stat_index.get(abs_key)
123
+ if (entry
124
+ and entry.get("size") == st.st_size
125
+ and entry.get("mtime_ns") == st.st_mtime_ns):
126
+ return entry["hash"]
127
+ except OSError:
128
+ pass
129
+
130
+ raw = p.read_bytes()
131
+ content = _body_content(raw) if p.suffix.lower() == ".md" else raw
132
+ h = hashlib.sha256()
133
+ h.update(content)
134
+ h.update(b"\x00")
135
+ try:
136
+ rel = p.resolve().relative_to(Path(root).resolve())
137
+ h.update(rel.as_posix().lower().encode())
138
+ except ValueError:
139
+ h.update(p.resolve().as_posix().lower().encode())
140
+ digest = h.hexdigest()
141
+
142
+ if st is not None:
143
+ _stat_index[abs_key] = {"size": st.st_size, "mtime_ns": st.st_mtime_ns, "hash": digest}
144
+ _stat_index_dirty = True
145
+
146
+ return digest
147
+
148
+
149
+ def _relativize_source_files_in(payload: dict, root: Path) -> None:
150
+ """Mutate ``payload`` to rewrite absolute ``source_file`` fields as
151
+ forward-slash relative paths from ``root``.
152
+
153
+ Mirror of :func:`graphify.watch._relativize_source_files` so cached
154
+ extraction fragments persist in portable form (#777). Already-relative
155
+ fields and out-of-root paths pass through unchanged.
156
+
157
+ Only ``root`` is resolved — ``source_file`` itself is relativized
158
+ symbolically so in-root symlinks keep their original name rather than
159
+ pointing at the resolved target. Same reasoning as
160
+ :func:`graphify.detect._to_relative_for_storage`.
161
+ """
162
+ try:
163
+ root_resolved = Path(root).resolve()
164
+ except OSError:
165
+ return
166
+ for bucket in ("nodes", "edges", "hyperedges"):
167
+ for item in payload.get(bucket, []):
168
+ if not isinstance(item, dict):
169
+ continue
170
+ source = item.get("source_file")
171
+ if not source:
172
+ continue
173
+ sp = Path(source)
174
+ if not sp.is_absolute():
175
+ continue
176
+ try:
177
+ rel = os.path.relpath(sp, root_resolved)
178
+ except (ValueError, OSError):
179
+ continue # out-of-root (e.g. Windows cross-drive)
180
+ if rel == ".." or rel.startswith(".." + os.sep) or rel.startswith("../"):
181
+ continue # escaped root — keep absolute
182
+ item["source_file"] = rel.replace(os.sep, "/")
183
+
184
+
185
+ def _absolutize_source_files_in(payload: dict, root: Path) -> None:
186
+ """Inverse of :func:`_relativize_source_files_in`.
187
+
188
+ Re-anchor relative ``source_file`` fields against ``root`` so callers
189
+ that load a cached fragment see the same absolute-path shape that a
190
+ fresh in-process extraction would produce. Legacy cache entries with
191
+ absolute ``source_file`` values pass through unchanged.
192
+ """
193
+ try:
194
+ root_resolved = Path(root).resolve()
195
+ except OSError:
196
+ return
197
+ for bucket in ("nodes", "edges", "hyperedges"):
198
+ for item in payload.get(bucket, []):
199
+ if not isinstance(item, dict):
200
+ continue
201
+ source = item.get("source_file")
202
+ if not source:
203
+ continue
204
+ sp = Path(source)
205
+ if sp.is_absolute():
206
+ continue
207
+ try:
208
+ item["source_file"] = str(root_resolved / sp)
209
+ except (TypeError, OSError):
210
+ continue
211
+
212
+
213
+ def cache_dir(root: Path = Path("."), kind: str = "ast") -> Path:
214
+ """Returns graphify-out/cache/{kind}/ - creates it if needed.
215
+
216
+ kind is "ast" or "semantic". Separate subdirectories prevent semantic cache
217
+ entries from overwriting AST cache entries for the same source_file (#582).
218
+ """
219
+ _out = Path(_GRAPHIFY_OUT)
220
+ base = _out if _out.is_absolute() else Path(root).resolve() / _out
221
+ d = base / "cache" / kind
222
+ d.mkdir(parents=True, exist_ok=True)
223
+ return d
224
+
225
+
226
+ def load_cached(path: Path, root: Path = Path("."), kind: str = "ast") -> dict | None:
227
+ """Return cached extraction for this file if hash matches, else None.
228
+
229
+ Cache key: SHA256 of file contents.
230
+ Cache value: stored as graphify-out/cache/{kind}/{hash}.json
231
+
232
+ For kind="ast", also checks the legacy flat cache/ directory so users
233
+ upgrading from pre-0.5.3 don't lose their existing AST cache entries.
234
+ Returns None if no cache entry or file has changed.
235
+ """
236
+ try:
237
+ h = file_hash(path, root)
238
+ except OSError:
239
+ return None
240
+ entry = cache_dir(root, kind) / f"{h}.json"
241
+ if entry.exists():
242
+ try:
243
+ result = json.loads(entry.read_text(encoding="utf-8"))
244
+ except (json.JSONDecodeError, OSError):
245
+ return None
246
+ # Re-anchor relative source_file fields so callers see the same
247
+ # absolute-path shape that a fresh in-process extraction produces
248
+ # (#777). Legacy entries with absolute source_file pass through.
249
+ if isinstance(result, dict):
250
+ _absolutize_source_files_in(result, root)
251
+ return result
252
+ # Migration fallback: check legacy flat cache/ dir for AST entries
253
+ if kind == "ast":
254
+ legacy = Path(root).resolve() / _GRAPHIFY_OUT / "cache" / f"{h}.json"
255
+ if legacy.exists():
256
+ try:
257
+ result = json.loads(legacy.read_text(encoding="utf-8"))
258
+ except (json.JSONDecodeError, OSError):
259
+ return None
260
+ if isinstance(result, dict):
261
+ _absolutize_source_files_in(result, root)
262
+ return result
263
+ return None
264
+
265
+
266
+ def save_cached(path: Path, result: dict, root: Path = Path("."), kind: str = "ast") -> None:
267
+ """Save extraction result for this file.
268
+
269
+ Stores as graphify-out/cache/{kind}/{hash}.json where hash = SHA256 of current file contents.
270
+ result should be a dict with 'nodes' and 'edges' lists.
271
+
272
+ No-ops if `path` is not a regular file. Subagent-produced semantic fragments
273
+ occasionally carry a directory path in `source_file`; skipping them prevents
274
+ IsADirectoryError from aborting the whole batch.
275
+ """
276
+ p = Path(path)
277
+ if not p.is_file():
278
+ return
279
+ # Relativize source_file fields against ``root`` before write so the
280
+ # cache file on disk is portable across machines and checkout
281
+ # directories (#777). The cache key is content-hashed so lookup is
282
+ # already path-independent; this fixes the embedded path leak.
283
+ #
284
+ # Serialize a relativized copy rather than mutating the caller's dict —
285
+ # downstream pipeline steps (notably extract.py's AST prefix remap, which
286
+ # looks up Path(source_file).resolve() in a prefix table) depend on the
287
+ # source_file field's original absolute form. Mutating the input here would
288
+ # silently break those remaps on the first extraction pass.
289
+ on_disk = result
290
+ if isinstance(result, dict) and any(result.get(k) for k in ("nodes", "edges", "hyperedges")):
291
+ import copy as _copy
292
+ on_disk = _copy.deepcopy(result)
293
+ _relativize_source_files_in(on_disk, root)
294
+ h = file_hash(p, root)
295
+ target_dir = cache_dir(root, kind)
296
+ entry = target_dir / f"{h}.json"
297
+ fd, tmp_path = tempfile.mkstemp(dir=target_dir, prefix=f"{h}.", suffix=".tmp")
298
+ try:
299
+ os.write(fd, json.dumps(on_disk).encode())
300
+ os.close(fd)
301
+ try:
302
+ os.replace(tmp_path, entry)
303
+ except PermissionError:
304
+ # Windows: os.replace can fail with WinError 5 if the target is
305
+ # briefly locked. Fall back to copy-then-delete.
306
+ import shutil
307
+ shutil.copy2(tmp_path, entry)
308
+ os.unlink(tmp_path)
309
+ except Exception:
310
+ try:
311
+ os.close(fd)
312
+ except OSError:
313
+ pass
314
+ try:
315
+ os.unlink(tmp_path)
316
+ except OSError:
317
+ pass
318
+ raise
319
+
320
+
321
+ def cached_files(root: Path = Path(".")) -> set[str]:
322
+ """Return set of file hashes that have a valid cache entry (any kind)."""
323
+ base = Path(root).resolve() / _GRAPHIFY_OUT / "cache"
324
+ hashes: set[str] = set()
325
+ # Legacy flat entries
326
+ if base.is_dir():
327
+ hashes.update(p.stem for p in base.glob("*.json"))
328
+ # Namespaced entries
329
+ for kind in ("ast", "semantic"):
330
+ d = base / kind
331
+ if d.is_dir():
332
+ hashes.update(p.stem for p in d.glob("*.json"))
333
+ return hashes
334
+
335
+
336
+ def clear_cache(root: Path = Path(".")) -> None:
337
+ """Delete all cache entries (ast/, semantic/, and legacy flat entries)."""
338
+ base = Path(root).resolve() / _GRAPHIFY_OUT / "cache"
339
+ # Legacy flat entries
340
+ if base.is_dir():
341
+ for f in base.glob("*.json"):
342
+ f.unlink()
343
+ # Namespaced entries
344
+ for kind in ("ast", "semantic"):
345
+ d = base / kind
346
+ if d.is_dir():
347
+ for f in d.glob("*.json"):
348
+ f.unlink()
349
+
350
+
351
+ def check_semantic_cache(
352
+ files: list[str],
353
+ root: Path = Path("."),
354
+ ) -> tuple[list[dict], list[dict], list[dict], list[str]]:
355
+ """Check semantic extraction cache for a list of absolute file paths.
356
+
357
+ Returns (cached_nodes, cached_edges, cached_hyperedges, uncached_files).
358
+ Uncached files need Claude extraction; cached files are merged directly.
359
+ """
360
+ cached_nodes: list[dict] = []
361
+ cached_edges: list[dict] = []
362
+ cached_hyperedges: list[dict] = []
363
+ uncached: list[str] = []
364
+
365
+ for fpath in files:
366
+ p = Path(fpath)
367
+ if not p.is_absolute():
368
+ p = Path(root) / p
369
+ result = load_cached(p, root, kind="semantic")
370
+ if result is not None:
371
+ cached_nodes.extend(result.get("nodes", []))
372
+ cached_edges.extend(result.get("edges", []))
373
+ cached_hyperedges.extend(result.get("hyperedges", []))
374
+ else:
375
+ uncached.append(fpath)
376
+
377
+ return cached_nodes, cached_edges, cached_hyperedges, uncached
378
+
379
+
380
+ def save_semantic_cache(
381
+ nodes: list[dict],
382
+ edges: list[dict],
383
+ hyperedges: list[dict] | None = None,
384
+ root: Path = Path("."),
385
+ ) -> int:
386
+ """Save semantic extraction results to cache, keyed by source_file.
387
+
388
+ Groups nodes and edges by source_file, then saves one cache entry per file
389
+ under cache/semantic/ (separate from AST entries in cache/ast/) to prevent
390
+ hash-key collisions (#582).
391
+ Returns the number of files cached.
392
+ """
393
+ from collections import defaultdict
394
+
395
+ by_file: dict[str, dict] = defaultdict(lambda: {"nodes": [], "edges": [], "hyperedges": []})
396
+ for n in nodes:
397
+ src = n.get("source_file", "")
398
+ if src:
399
+ by_file[src]["nodes"].append(n)
400
+ for e in edges:
401
+ src = e.get("source_file", "")
402
+ if src:
403
+ by_file[src]["edges"].append(e)
404
+ for h in (hyperedges or []):
405
+ src = h.get("source_file", "")
406
+ if src:
407
+ by_file[src]["hyperedges"].append(h)
408
+
409
+ saved = 0
410
+ for fpath, result in by_file.items():
411
+ p = Path(fpath)
412
+ if not p.is_absolute():
413
+ p = Path(root) / p
414
+ if p.is_file():
415
+ save_cached(p, result, root, kind="semantic")
416
+ saved += 1
417
+ return saved