lazycodex-ai 5.1.44 β†’ 5.1.46

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 (412) hide show
  1. package/README.de.md +0 -5
  2. package/README.es.md +0 -5
  3. package/README.fr.md +0 -5
  4. package/README.it.md +0 -5
  5. package/README.ja.md +0 -5
  6. package/README.ko.md +0 -5
  7. package/README.md +4 -5
  8. package/README.pt-br.md +0 -5
  9. package/README.ru.md +0 -6
  10. package/README.zh-cn.md +0 -5
  11. package/dist/cli/index.js +865 -413
  12. package/dist/cli/service-auth/keystore.d.ts +4 -2
  13. package/dist/cli-node/index.js +865 -413
  14. package/docs/reference/web-terminal-visual-qa.md +8 -0
  15. package/package.json +1 -1
  16. package/packages/lsp-daemon/dist/cli.js +7 -7
  17. package/packages/lsp-daemon/dist/client.js +7 -7
  18. package/packages/lsp-daemon/dist/index.js +7 -7
  19. package/packages/lsp-daemon/package.json +3 -3
  20. package/packages/lsp-tools-mcp/dist/cli.js +7 -7
  21. package/packages/lsp-tools-mcp/dist/mcp.js +7 -7
  22. package/packages/lsp-tools-mcp/dist/tools.js +4 -4
  23. package/packages/lsp-tools-mcp/package.json +3 -3
  24. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  25. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +77 -26
  26. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -1
  29. package/packages/omo-codex/plugin/components/comment-checker/biome.json +1 -21
  30. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  31. package/packages/omo-codex/plugin/components/comment-checker/package.json +4 -4
  32. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  33. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  34. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +1 -21
  35. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  36. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +4 -4
  37. package/packages/omo-codex/plugin/components/lsp/biome.json +1 -21
  38. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  39. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +4 -4
  40. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  41. package/packages/omo-codex/plugin/components/lsp/package.json +4 -4
  42. package/packages/omo-codex/plugin/components/lsp/scripts/build-runtime.mjs +0 -1
  43. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-not-installed.test.ts +1 -1
  44. package/packages/omo-codex/plugin/components/rules/biome.json +1 -21
  45. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  46. package/packages/omo-codex/plugin/components/rules/package.json +4 -4
  47. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  48. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  49. package/packages/omo-codex/plugin/components/telemetry/biome.json +1 -21
  50. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +90 -1
  51. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +91 -1
  52. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/telemetry/package.json +4 -4
  54. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +2 -2
  55. package/packages/omo-codex/plugin/components/ultrawork/biome.json +1 -21
  56. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/package.json +4 -4
  58. package/packages/omo-codex/plugin/components/ulw-execute-continuation/biome.json +1 -21
  59. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
  60. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  61. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +4 -4
  62. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +1 -21
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +1 -1
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +7 -7
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +5 -5
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +1 -1
  67. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  68. package/packages/omo-codex/plugin/components/ulw-loop/package.json +4 -4
  69. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +1 -1
  70. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +5 -5
  71. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +1 -1
  72. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-mutations.mjs +2 -0
  73. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  78. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  79. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  80. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  81. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  82. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  83. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  84. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  85. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  86. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  87. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  94. package/packages/omo-codex/plugin/package-lock.json +12 -12
  95. package/packages/omo-codex/plugin/package.json +1 -1
  96. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +14 -9
  97. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +1 -1
  98. package/packages/omo-codex/plugin/skills/browser/SKILL.md +21 -22
  99. package/packages/omo-codex/plugin/skills/browser/references/commands.md +2 -9
  100. package/packages/omo-codex/plugin/skills/browser/references/install.md +1 -2
  101. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  102. package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +2 -2
  103. package/packages/omo-codex/plugin/skills/browser/scripts/browser-engine-guard.mjs +63 -487
  104. package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +1 -1
  105. package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +1 -10
  106. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +2 -2
  107. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +79 -118
  108. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +75 -224
  109. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +32 -27
  110. package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +2 -2
  111. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/check-accent-stripes.ts +8 -24
  112. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/check-draft-guard.ts +40 -0
  113. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/collect-files.ts +53 -0
  114. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/findings.ts +16 -0
  115. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/lint.ts +38 -0
  116. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/rules.ts +69 -0
  117. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/text-nodes.ts +121 -0
  118. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/attr-lookalikes.tsx +10 -0
  119. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/bound-values.tsx +12 -0
  120. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/const-generics.tsx +3 -0
  121. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/generics.tsx +7 -0
  122. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/measured-stats.html +6 -0
  123. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/plain-copy.html +9 -0
  124. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/state-copy.html +11 -0
  125. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/attribute-edges.html +7 -0
  126. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/components.tsx +16 -0
  127. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/decorative-badge.vue +7 -0
  128. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/emoji-icons.tsx +9 -0
  129. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/jsx-edges.tsx +1 -0
  130. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.html +6 -0
  131. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.tsx +8 -0
  132. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/vanity-stats.html +5 -0
  133. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
  134. package/packages/omo-codex/plugin/skills/programming/SKILL.md +10 -7
  135. package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +10 -7
  136. package/packages/omo-codex/plugin/skills/programming/references/typescript/bootstrap.md +9 -23
  137. package/packages/omo-codex/plugin/skills/programming/references/typescript/oxc-lint.md +130 -0
  138. package/packages/omo-codex/plugin/skills/programming/references/typescript/tsconfig-strict.md +6 -62
  139. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +12 -12
  140. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/new-project.ts +20 -81
  141. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/.oxfmtrc.json +9 -0
  142. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/.oxlintrc.json +46 -0
  143. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/LICENSE +21 -0
  144. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/index.js +10 -0
  145. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/no-em-dash-copy.js +28 -0
  146. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/require-suppression-reason.js +62 -0
  147. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/tsconfig.json +29 -0
  148. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +14 -14
  149. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
  150. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +2 -2
  151. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  152. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +2 -2
  153. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +1 -1
  154. package/packages/omo-codex/plugin/skills/ulw-research/AGENTS.md +21 -3
  155. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +37 -12
  156. package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +77 -16
  157. package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +134 -0
  158. package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger.md +95 -0
  159. package/packages/omo-codex/plugin/skills/ulw-research/references/fidelity-claim-kinds.md +19 -0
  160. package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +68 -3
  161. package/packages/omo-codex/plugin/skills/ulw-research/references/report-visualization.md +2 -0
  162. package/packages/omo-codex/plugin/skills/ulw-research/references/unit-rules.md +157 -0
  163. package/packages/omo-codex/plugin/skills/ulw-research/scripts/claim-kinds.mjs +116 -0
  164. package/packages/omo-codex/plugin/skills/ulw-research/scripts/claims-index.mjs +125 -0
  165. package/packages/omo-codex/plugin/skills/ulw-research/scripts/cli-support.mjs +19 -5
  166. package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +89 -3
  167. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +191 -0
  168. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +164 -0
  169. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +239 -0
  170. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-derive.mjs +66 -0
  171. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-expr.mjs +108 -0
  172. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-fill.mjs +194 -0
  173. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +250 -0
  174. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-schema.mjs +221 -0
  175. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger.mjs +123 -0
  176. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-locate.mjs +231 -0
  177. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-pairs.mjs +187 -0
  178. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-recompute.mjs +89 -0
  179. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-binding.mjs +130 -0
  180. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-brief.mjs +150 -0
  181. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-claims.mjs +89 -0
  182. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-lexicon.mjs +145 -0
  183. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-records.mjs +163 -0
  184. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-state.mjs +64 -0
  185. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-trace.mjs +85 -0
  186. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +229 -0
  187. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-fidelity.mjs +113 -0
  188. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +29 -9
  189. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-structure.mjs +1 -1
  190. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-text.mjs +1 -27
  191. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-lite.mjs +2 -2
  192. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-markup.mjs +182 -0
  193. package/packages/omo-codex/plugin/skills/ulw-research/scripts/lexicon.mjs +47 -0
  194. package/packages/omo-codex/plugin/skills/ulw-research/scripts/md-lite.mjs +193 -0
  195. package/packages/omo-codex/plugin/skills/ulw-research/scripts/meaning-check.mjs +196 -0
  196. package/packages/omo-codex/plugin/skills/ulw-research/scripts/numerals.mjs +226 -0
  197. package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome.mjs +8 -8
  198. package/packages/omo-codex/plugin/skills/ulw-research/scripts/particles-ko.mjs +108 -0
  199. package/packages/omo-codex/plugin/skills/ulw-research/scripts/placeholder.mjs +184 -0
  200. package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-apply.mjs +115 -0
  201. package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-diff.mjs +31 -0
  202. package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-project.mjs +125 -0
  203. package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-rules.mjs +170 -0
  204. package/packages/omo-codex/plugin/skills/ulw-research/scripts/rational.mjs +139 -0
  205. package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools-commands.mjs +21 -10
  206. package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools.mjs +15 -0
  207. package/packages/omo-codex/plugin/skills/ulw-research/scripts/sentence-split.mjs +77 -0
  208. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +140 -0
  209. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-snapshot.mjs +176 -0
  210. package/packages/omo-codex/plugin/skills/ulw-research/scripts/text-normalize.mjs +82 -0
  211. package/packages/omo-codex/plugin/skills/ulw-research/scripts/text-similarity.mjs +28 -0
  212. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-algebra.mjs +101 -0
  213. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-errors.mjs +23 -0
  214. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-metadata.mjs +31 -0
  215. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-pairs.mjs +72 -0
  216. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-precision.mjs +44 -0
  217. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-rules-shapes.mjs +64 -0
  218. package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-rules.mjs +173 -0
  219. package/packages/omo-codex/plugin/skills/ulw-research/scripts/units.mjs +105 -0
  220. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +71 -64
  221. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +4 -1
  222. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +19 -0
  223. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -8
  224. package/packages/omo-codex/scripts/install-dist/install-local.mjs +169 -30
  225. package/packages/shared-skills/skills/ast-grep/AGENTS.md +1 -1
  226. package/packages/shared-skills/skills/browser/SKILL.md +21 -22
  227. package/packages/shared-skills/skills/browser/references/commands.md +2 -9
  228. package/packages/shared-skills/skills/browser/references/install.md +1 -2
  229. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  230. package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +2 -2
  231. package/packages/shared-skills/skills/browser/scripts/browser-engine-guard.mjs +63 -487
  232. package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +1 -1
  233. package/packages/shared-skills/skills/browser/scripts/omowright.mjs +1 -10
  234. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +2 -2
  235. package/packages/shared-skills/skills/frontend/SKILL.md +79 -118
  236. package/packages/shared-skills/skills/frontend/references/design/README.md +75 -224
  237. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +32 -27
  238. package/packages/shared-skills/skills/frontend/references/perfection/README.md +2 -2
  239. package/packages/shared-skills/skills/frontend/scripts/perfection/check-accent-stripes.ts +8 -24
  240. package/packages/shared-skills/skills/frontend/scripts/perfection/check-draft-guard.test.ts +101 -0
  241. package/packages/shared-skills/skills/frontend/scripts/perfection/check-draft-guard.ts +40 -0
  242. package/packages/shared-skills/skills/frontend/scripts/perfection/collect-files.test.ts +50 -0
  243. package/packages/shared-skills/skills/frontend/scripts/perfection/collect-files.ts +53 -0
  244. package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/findings.ts +16 -0
  245. package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/lint.ts +38 -0
  246. package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/rules.ts +69 -0
  247. package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/text-nodes.ts +121 -0
  248. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/attr-lookalikes.tsx +10 -0
  249. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/bound-values.tsx +12 -0
  250. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/const-generics.tsx +3 -0
  251. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/generics.tsx +7 -0
  252. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/measured-stats.html +6 -0
  253. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/plain-copy.html +9 -0
  254. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/state-copy.html +11 -0
  255. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/attribute-edges.html +7 -0
  256. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/components.tsx +16 -0
  257. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/decorative-badge.vue +7 -0
  258. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/emoji-icons.tsx +9 -0
  259. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/jsx-edges.tsx +1 -0
  260. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.html +6 -0
  261. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.tsx +8 -0
  262. package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/vanity-stats.html +5 -0
  263. package/packages/shared-skills/skills/programming/SKILL.md +10 -7
  264. package/packages/shared-skills/skills/programming/references/typescript/README.md +10 -7
  265. package/packages/shared-skills/skills/programming/references/typescript/bootstrap.md +9 -23
  266. package/packages/shared-skills/skills/programming/references/typescript/oxc-lint.md +130 -0
  267. package/packages/shared-skills/skills/programming/references/typescript/tsconfig-strict.md +6 -62
  268. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +12 -12
  269. package/packages/shared-skills/skills/programming/scripts/typescript/new-project.test.ts +162 -0
  270. package/packages/shared-skills/skills/programming/scripts/typescript/new-project.ts +20 -81
  271. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/.oxfmtrc.json +9 -0
  272. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/.oxlintrc.json +46 -0
  273. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/LICENSE +21 -0
  274. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/index.js +10 -0
  275. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/no-em-dash-copy.js +28 -0
  276. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/require-suppression-reason.js +62 -0
  277. package/packages/shared-skills/skills/programming/scripts/typescript/oxc/tsconfig.json +29 -0
  278. package/packages/shared-skills/skills/refactor/SKILL.md +13 -13
  279. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  280. package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
  281. package/packages/shared-skills/skills/ulw-research/AGENTS.md +21 -3
  282. package/packages/shared-skills/skills/ulw-research/SKILL.md +37 -12
  283. package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +77 -16
  284. package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +134 -0
  285. package/packages/shared-skills/skills/ulw-research/references/fact-ledger.md +95 -0
  286. package/packages/shared-skills/skills/ulw-research/references/fidelity-claim-kinds.md +19 -0
  287. package/packages/shared-skills/skills/ulw-research/references/report-gates.md +68 -3
  288. package/packages/shared-skills/skills/ulw-research/references/report-visualization.md +2 -0
  289. package/packages/shared-skills/skills/ulw-research/references/unit-rules.md +157 -0
  290. package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.mjs +116 -0
  291. package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.test.ts +193 -0
  292. package/packages/shared-skills/skills/ulw-research/scripts/claims-index.mjs +125 -0
  293. package/packages/shared-skills/skills/ulw-research/scripts/claims-index.test.ts +149 -0
  294. package/packages/shared-skills/skills/ulw-research/scripts/cli-support.mjs +19 -5
  295. package/packages/shared-skills/skills/ulw-research/scripts/cli-support.test.ts +13 -2
  296. package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +89 -3
  297. package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +100 -12
  298. package/packages/shared-skills/skills/ulw-research/scripts/copy-returns.test.ts +183 -0
  299. package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier.test.ts +245 -0
  300. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +191 -0
  301. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +164 -0
  302. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +239 -0
  303. package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.mjs +66 -0
  304. package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.test.ts +375 -0
  305. package/packages/shared-skills/skills/ulw-research/scripts/fact-expr.mjs +108 -0
  306. package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.mjs +194 -0
  307. package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.test.ts +221 -0
  308. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-grammar.test.ts +197 -0
  309. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +250 -0
  310. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +156 -0
  311. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +160 -0
  312. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-schema.mjs +221 -0
  313. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-schema.test.ts +43 -0
  314. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger.mjs +123 -0
  315. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger.test.ts +254 -0
  316. package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.mjs +231 -0
  317. package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.test.ts +118 -0
  318. package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.mjs +187 -0
  319. package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.test.ts +167 -0
  320. package/packages/shared-skills/skills/ulw-research/scripts/fact-recompute.mjs +89 -0
  321. package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +409 -0
  322. package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-rules.test.ts +388 -0
  323. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-binding.mjs +130 -0
  324. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-binding.test.ts +81 -0
  325. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.mjs +150 -0
  326. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.test.ts +179 -0
  327. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-claims.mjs +89 -0
  328. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.mjs +145 -0
  329. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.test.ts +117 -0
  330. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-records.mjs +163 -0
  331. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.mjs +64 -0
  332. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.test.ts +46 -0
  333. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.mjs +85 -0
  334. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.test.ts +58 -0
  335. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +229 -0
  336. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +270 -0
  337. package/packages/shared-skills/skills/ulw-research/scripts/gates-context.test.ts +64 -0
  338. package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.mjs +113 -0
  339. package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.test.ts +73 -0
  340. package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +29 -9
  341. package/packages/shared-skills/skills/ulw-research/scripts/gates-structure.mjs +1 -1
  342. package/packages/shared-skills/skills/ulw-research/scripts/gates-text.mjs +1 -27
  343. package/packages/shared-skills/skills/ulw-research/scripts/html-lite.mjs +2 -2
  344. package/packages/shared-skills/skills/ulw-research/scripts/html-markup.mjs +182 -0
  345. package/packages/shared-skills/skills/ulw-research/scripts/lexicon.mjs +47 -0
  346. package/packages/shared-skills/skills/ulw-research/scripts/lexicon.test.ts +57 -0
  347. package/packages/shared-skills/skills/ulw-research/scripts/md-lite.mjs +193 -0
  348. package/packages/shared-skills/skills/ulw-research/scripts/md-lite.test.ts +271 -0
  349. package/packages/shared-skills/skills/ulw-research/scripts/meaning-check.mjs +196 -0
  350. package/packages/shared-skills/skills/ulw-research/scripts/meaning-check.test.ts +228 -0
  351. package/packages/shared-skills/skills/ulw-research/scripts/numerals.mjs +226 -0
  352. package/packages/shared-skills/skills/ulw-research/scripts/numerals.test.ts +120 -0
  353. package/packages/shared-skills/skills/ulw-research/scripts/outcome.mjs +8 -8
  354. package/packages/shared-skills/skills/ulw-research/scripts/outcome.test.ts +29 -0
  355. package/packages/shared-skills/skills/ulw-research/scripts/particles-ko.mjs +108 -0
  356. package/packages/shared-skills/skills/ulw-research/scripts/particles-ko.test.ts +86 -0
  357. package/packages/shared-skills/skills/ulw-research/scripts/placeholder.mjs +184 -0
  358. package/packages/shared-skills/skills/ulw-research/scripts/placeholder.test.ts +77 -0
  359. package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.mjs +115 -0
  360. package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.test.ts +363 -0
  361. package/packages/shared-skills/skills/ulw-research/scripts/polish-diff.mjs +31 -0
  362. package/packages/shared-skills/skills/ulw-research/scripts/polish-diff.test.ts +168 -0
  363. package/packages/shared-skills/skills/ulw-research/scripts/polish-markup.test.ts +187 -0
  364. package/packages/shared-skills/skills/ulw-research/scripts/polish-project.mjs +125 -0
  365. package/packages/shared-skills/skills/ulw-research/scripts/polish-rules.mjs +170 -0
  366. package/packages/shared-skills/skills/ulw-research/scripts/rational.mjs +139 -0
  367. package/packages/shared-skills/skills/ulw-research/scripts/rational.test.ts +46 -0
  368. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-commands.mjs +21 -10
  369. package/packages/shared-skills/skills/ulw-research/scripts/report-tools.mjs +15 -0
  370. package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +458 -2
  371. package/packages/shared-skills/skills/ulw-research/scripts/sentence-split.mjs +77 -0
  372. package/packages/shared-skills/skills/ulw-research/scripts/sentence-split.test.ts +109 -0
  373. package/packages/shared-skills/skills/ulw-research/scripts/source-commands.mjs +140 -0
  374. package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.mjs +176 -0
  375. package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.test.ts +113 -0
  376. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/assets/share.csv +3 -0
  377. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/claim-graph.md +13 -0
  378. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/gen-legacy-dev.mjs +89 -0
  379. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-basic.json +223 -0
  380. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-legacy-dev.json +859 -0
  381. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-verify.json +420 -0
  382. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/report-bad.html +19 -0
  383. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/report-good.html +39 -0
  384. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/acronyms.json +3 -0
  385. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/meta.json +9 -0
  386. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/sentences.jsonl +7 -0
  387. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/text.txt +7 -0
  388. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4.html +19 -0
  389. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/acronyms.json +1 -0
  390. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/meta.json +9 -0
  391. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/sentences.jsonl +1 -0
  392. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/text.txt +1 -0
  393. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S9.txt +1 -0
  394. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity-brief-locked.md +17 -0
  395. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity-brief-pending.md +17 -0
  396. package/packages/shared-skills/skills/ulw-research/scripts/text-normalize.mjs +82 -0
  397. package/packages/shared-skills/skills/ulw-research/scripts/text-normalize.test.ts +73 -0
  398. package/packages/shared-skills/skills/ulw-research/scripts/text-similarity.mjs +28 -0
  399. package/packages/shared-skills/skills/ulw-research/scripts/text-similarity.test.ts +38 -0
  400. package/packages/shared-skills/skills/ulw-research/scripts/unit-algebra.mjs +101 -0
  401. package/packages/shared-skills/skills/ulw-research/scripts/unit-errors.mjs +23 -0
  402. package/packages/shared-skills/skills/ulw-research/scripts/unit-metadata.mjs +31 -0
  403. package/packages/shared-skills/skills/ulw-research/scripts/unit-pairs.mjs +72 -0
  404. package/packages/shared-skills/skills/ulw-research/scripts/unit-precision.mjs +44 -0
  405. package/packages/shared-skills/skills/ulw-research/scripts/unit-rules-shapes.mjs +64 -0
  406. package/packages/shared-skills/skills/ulw-research/scripts/unit-rules.mjs +173 -0
  407. package/packages/shared-skills/skills/ulw-research/scripts/units.mjs +105 -0
  408. package/packages/shared-skills/skills/ulw-research/scripts/units.test.ts +83 -0
  409. package/packages/shared-skills/skills/visual-qa/SKILL.md +70 -63
  410. package/packages/shared-skills/skills/visual-qa/scripts/skill-doc-fields.test.ts +34 -0
  411. package/script/qa/web-terminal-visual-qa.mjs +6 -2
  412. package/script/qa/xterm-live-terminal.mjs +26 -3
@@ -0,0 +1,101 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import { spawnSync } from "node:child_process"
3
+ import { readdirSync, readFileSync } from "node:fs"
4
+ import { join } from "node:path"
5
+ import type { DraftRuleId } from "./draft-guard/findings"
6
+ import { lintDraft } from "./draft-guard/lint"
7
+
8
+ const FIXTURES = join(import.meta.dir, "fixtures", "draft-guard")
9
+ const ACCENT_FIXTURES = join(import.meta.dir, "fixtures", "accent-stripes")
10
+ const SCRIPT = join(import.meta.dir, "check-draft-guard.ts")
11
+
12
+ const EXPECTED: Readonly<Record<string, ReadonlyArray<[number, DraftRuleId]>>> = {
13
+ "promo-copy.html": [[2, "promo-copy"], [3, "promo-copy"], [5, "promo-copy"]],
14
+ "promo-copy.tsx": [[4, "promo-copy"], [5, "promo-copy"]],
15
+ "emoji-icons.tsx": [[4, "emoji-icon"], [6, "emoji-icon"]],
16
+ "vanity-stats.html": [[2, "vanity-stat"], [3, "vanity-stat"], [4, "vanity-stat"]],
17
+ "decorative-badge.vue": [[3, "decorative-badge"], [4, "decorative-badge"]],
18
+ "components.tsx": [
19
+ [5, "decorative-badge"],
20
+ [6, "decorative-badge"],
21
+ [7, "emoji-icon"],
22
+ [7, "decorative-badge"],
23
+ [8, "emoji-icon"],
24
+ [9, "emoji-icon"],
25
+ [10, "vanity-stat"],
26
+ [11, "vanity-stat"],
27
+ [12, "vanity-stat"],
28
+ [13, "promo-copy"],
29
+ ],
30
+ "attribute-edges.html": [[2, "promo-copy"], [3, "promo-copy"], [4, "vanity-stat"], [5, "decorative-badge"], [6, "promo-copy"]],
31
+ "jsx-edges.tsx": [[1, "promo-copy"]],
32
+ }
33
+
34
+ function lintFixture(dir: string, name: string) {
35
+ const path = join(FIXTURES, dir, name)
36
+ return lintDraft([{ path, text: readFileSync(path, "utf8") }])
37
+ }
38
+
39
+ describe("#given a positive fixture with a generated-look tell in its markup", () => {
40
+ test("#then every positive fixture has an expectation", () => {
41
+ expect(readdirSync(join(FIXTURES, "positive")).sort()).toEqual(Object.keys(EXPECTED).sort())
42
+ })
43
+
44
+ for (const [name, expected] of Object.entries(EXPECTED)) {
45
+ test(`#when ${name} is linted #then it reports exactly ${expected.length} finding(s) at the expected lines`, () => {
46
+ const findings = lintFixture("positive", name).map((f): [number, DraftRuleId] => [f.line, f.rule])
47
+ expect(findings).toEqual([...expected])
48
+ })
49
+ }
50
+ })
51
+
52
+ describe("#given a negative fixture (plain copy, code, scripts, styles, comments, bound values, status badges)", () => {
53
+ for (const name of readdirSync(join(FIXTURES, "negative"))) {
54
+ test(`#when ${name} is linted #then it reports nothing`, () => {
55
+ expect(lintFixture("negative", name)).toEqual([])
56
+ })
57
+ }
58
+ })
59
+
60
+ describe("#given a generated page written on one line", () => {
61
+ test("#when it holds two promo phrases #then both are reported, each at its own column", () => {
62
+ const text = "<p>Seamless sync and effortless setup</p>\n"
63
+ const findings = lintDraft([{ path: "page.html", text }])
64
+ expect(findings.map((f) => [f.line, f.column, f.rule])).toEqual([
65
+ [1, text.indexOf("Seamless") + 1, "promo-copy"],
66
+ [1, text.indexOf("effortless") + 1, "promo-copy"],
67
+ ])
68
+ })
69
+ })
70
+
71
+ describe("#given a stylesheet", () => {
72
+ test("#when it is linted #then text rules are not applied to CSS", () => {
73
+ expect(lintDraft([{ path: "a.css", text: '.hero::before { content: "Unlock πŸš€"; }\n' }])).toEqual([])
74
+ })
75
+ })
76
+
77
+ describe("#given the CLI", () => {
78
+ const run = (...args: string[]) => spawnSync(process.execPath, [SCRIPT, ...args], { encoding: "utf8", timeout: 30_000 })
79
+
80
+ test("#when it scans the draft-guard positives #then it exits 1 and prints file:line findings", () => {
81
+ const result = run(join(FIXTURES, "positive"))
82
+ expect(result.status).toBe(1)
83
+ expect(result.stdout).toMatch(/vanity-stats\.html:2:\d+ {2}vanity-stat/)
84
+ })
85
+
86
+ test("#when it scans an accent-stripe positive #then the accent-stripe rules still report through it", () => {
87
+ const result = run("--json", join(ACCENT_FIXTURES, "positive", "border-top-card.css"))
88
+ expect(JSON.parse(result.stdout)).toEqual([expect.objectContaining({ line: 4, rule: "edge-stripe" })])
89
+ expect(result.status).toBe(1)
90
+ })
91
+
92
+ test("#when it scans both negative fixture sets #then it exits 0", () => {
93
+ expect(run(join(FIXTURES, "negative"), join(ACCENT_FIXTURES, "negative")).status).toBe(0)
94
+ })
95
+
96
+ test("#when no path is given #then it exits 2 with usage", () => {
97
+ const result = run()
98
+ expect(result.status).toBe(2)
99
+ expect(result.stderr).toContain("usage:")
100
+ })
101
+ })
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bun
2
+ // The draft guard in one command: accent stripes plus generated-look copy and markup (promo copy, emoji icons, hype badges, vanity stats).
3
+ // Usage: bun check-draft-guard.ts [--json] <file-or-dir>... Exit 0 clean, 1 findings, 2 usage or unreadable target.
4
+ import { readFileSync } from "node:fs"
5
+ import { RULE_MESSAGES } from "./accent-stripes/findings"
6
+ import { lintFiles, type SourceFile } from "./accent-stripes/lint"
7
+ import { collectFiles } from "./collect-files"
8
+ import { DRAFT_RULE_MESSAGES } from "./draft-guard/findings"
9
+ import { lintDraft } from "./draft-guard/lint"
10
+
11
+ const MESSAGES: Readonly<Record<string, string>> = { ...RULE_MESSAGES, ...DRAFT_RULE_MESSAGES }
12
+
13
+ function main(argv: readonly string[]): number {
14
+ const json = argv.includes("--json")
15
+ const targets = argv.filter((a) => a !== "--json")
16
+ if (targets.length === 0) {
17
+ process.stderr.write("usage: check-draft-guard.ts [--json] <file-or-dir>...\n")
18
+ return 2
19
+ }
20
+ const { paths, missing } = collectFiles(targets)
21
+ if (missing.length > 0) {
22
+ process.stderr.write(`check-draft-guard: cannot read ${missing.join(", ")}\n`)
23
+ return 2
24
+ }
25
+ const files: SourceFile[] = paths.map((path) => ({ path, text: readFileSync(path, "utf8") }))
26
+ const findings = [...lintFiles(files), ...lintDraft(files)].sort(
27
+ (a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.column - b.column,
28
+ )
29
+ if (json) process.stdout.write(`${JSON.stringify(findings, null, 2)}\n`)
30
+ else {
31
+ for (const f of findings) {
32
+ process.stdout.write(`${f.file}:${f.line}:${f.column} ${f.rule} ${MESSAGES[f.rule]}\n > ${f.excerpt}\n`)
33
+ }
34
+ const summary = findings.length === 0 ? "clean" : `${findings.length} finding(s); fix each before visual QA`
35
+ process.stdout.write(`check-draft-guard: ${paths.length} file(s), ${summary}\n`)
36
+ }
37
+ return findings.length === 0 ? 0 : 1
38
+ }
39
+
40
+ process.exitCode = main(process.argv.slice(2))
@@ -0,0 +1,50 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import { chmodSync, mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs"
3
+ import { tmpdir } from "node:os"
4
+ import { join } from "node:path"
5
+ import { collectFiles } from "./collect-files"
6
+
7
+ // Owner test for the file-walk contract both perfection CLIs share (check-accent-stripes.ts, check-draft-guard.ts).
8
+ function withDir(run: (dir: string) => void): void {
9
+ const dir = mkdtempSync(join(tmpdir(), "collect-files-"))
10
+ try {
11
+ run(dir)
12
+ } finally {
13
+ chmodSync(dir, 0o700)
14
+ rmSync(dir, { recursive: true, force: true })
15
+ }
16
+ }
17
+
18
+ // Permission bits do not stop root, and Windows ignores chmod, so the unreadable-directory case cannot be built there.
19
+ const cannotBuildUnreadableDir = process.platform === "win32" || process.getuid?.() === 0
20
+
21
+ describe("#given a scanned directory", () => {
22
+ test("#when it holds a dangling symlink #then the link is skipped and the rest is collected", () => {
23
+ withDir((dir) => {
24
+ symlinkSync(join(dir, "missing-target"), join(dir, "broken-link.tsx"))
25
+ writeFileSync(join(dir, "page.html"), "<p>ok</p>\n")
26
+ expect(collectFiles([dir])).toEqual({ paths: [join(dir, "page.html")], missing: [] })
27
+ })
28
+ })
29
+
30
+ test.skipIf(cannotBuildUnreadableDir)("#when a nested directory cannot be listed #then it is skipped and the rest is collected", () => {
31
+ withDir((dir) => {
32
+ const locked = join(dir, "locked")
33
+ mkdirSync(locked)
34
+ writeFileSync(join(locked, "hidden.css"), ".a {}\n")
35
+ writeFileSync(join(dir, "page.html"), "<p>ok</p>\n")
36
+ chmodSync(locked, 0o000)
37
+ try {
38
+ expect(collectFiles([dir])).toEqual({ paths: [join(dir, "page.html")], missing: [] })
39
+ } finally {
40
+ chmodSync(locked, 0o700)
41
+ }
42
+ })
43
+ })
44
+
45
+ test("#when an explicit target does not exist #then it is reported as missing", () => {
46
+ withDir((dir) => {
47
+ expect(collectFiles([join(dir, "nope")])).toEqual({ paths: [], missing: [join(dir, "nope")] })
48
+ })
49
+ })
50
+ })
@@ -0,0 +1,53 @@
1
+ import { readdirSync, statSync, type Stats } from "node:fs"
2
+ import { join } from "node:path"
3
+
4
+ const SCANNED = /\.(?:css|scss|less|pcss|postcss|html?|[cm]?[jt]sx?|vue|svelte|astro)$/i
5
+ const SKIPPED_DIRS = new Set([
6
+ "node_modules", ".git", "dist", "build", "out", ".next", ".nuxt", ".svelte-kit", ".astro",
7
+ ".turbo", ".cache", "coverage", "vendor", ".vercel", ".output",
8
+ ])
9
+ const MAX_BYTES = 1_000_000
10
+
11
+ function statOrNull(path: string): Stats | null {
12
+ try {
13
+ return statSync(path)
14
+ } catch {
15
+ return null
16
+ }
17
+ }
18
+
19
+ function entriesOrNull(path: string): string[] | null {
20
+ try {
21
+ return readdirSync(path)
22
+ } catch {
23
+ return null
24
+ }
25
+ }
26
+
27
+ /** Lintable source files under the targets; dangling links and unreadable entries are skipped, an unreadable explicit target is reported. */
28
+ export function collectFiles(targets: readonly string[]): { readonly paths: string[]; readonly missing: string[] } {
29
+ const paths: string[] = []
30
+ const missing: string[] = []
31
+ const walk = (path: string, explicit: boolean): void => {
32
+ const stat = statOrNull(path)
33
+ if (!stat) {
34
+ if (explicit) missing.push(path)
35
+ return
36
+ }
37
+ if (stat.isDirectory()) {
38
+ const entries = entriesOrNull(path)
39
+ if (entries === null) {
40
+ if (explicit) missing.push(path)
41
+ return
42
+ }
43
+ for (const entry of entries) {
44
+ if (!SKIPPED_DIRS.has(entry)) walk(join(path, entry), false)
45
+ }
46
+ return
47
+ }
48
+ const minified = /\.min\.[a-z]+$/i.test(path) || path.endsWith(".d.ts")
49
+ if (SCANNED.test(path) && !minified && stat.size <= MAX_BYTES) paths.push(path)
50
+ }
51
+ for (const target of targets) walk(target, true)
52
+ return { paths, missing }
53
+ }
@@ -0,0 +1,16 @@
1
+ export type DraftRuleId = "promo-copy" | "emoji-icon" | "decorative-badge" | "vanity-stat"
2
+
3
+ export type DraftFinding = {
4
+ readonly file: string
5
+ readonly line: number
6
+ readonly column: number
7
+ readonly rule: DraftRuleId
8
+ readonly excerpt: string
9
+ }
10
+
11
+ export const DRAFT_RULE_MESSAGES: Readonly<Record<DraftRuleId, string>> = {
12
+ "promo-copy": "promotional filler in visible copy; say what the screen does or shows instead",
13
+ "emoji-icon": "emoji used as an icon or bullet; use an SVG icon from the project's icon set, or nothing",
14
+ "decorative-badge": "badge or chip carrying a hype label instead of a state; remove it or show a real status",
15
+ "vanity-stat": "stat tile with a marketing-form number (10x, 500+, 24/7); show the measured figure with its unit and period, or remove the tile",
16
+ }
@@ -0,0 +1,38 @@
1
+ import { lineLocator } from "../accent-stripes/findings"
2
+ import type { SourceFile } from "../accent-stripes/lint"
3
+ import type { DraftFinding } from "./findings"
4
+ import { checkNode } from "./rules"
5
+ import { type MarkupKind, textNodes } from "./text-nodes"
6
+
7
+ function markupKind(path: string): MarkupKind | null {
8
+ if (/\.html?$/i.test(path)) return "html"
9
+ if (/\.[cm]?[jt]sx$/i.test(path)) return "jsx"
10
+ if (/\.(?:vue|svelte|astro)$/i.test(path)) return "sfc"
11
+ return null
12
+ }
13
+
14
+ function excerptAt(text: string, offset: number): string {
15
+ const lineStart = text.lastIndexOf("\n", offset - 1) + 1
16
+ const lineEnd = text.indexOf("\n", offset)
17
+ return text.slice(lineStart, lineEnd < 0 ? undefined : lineEnd).trim().slice(0, 140)
18
+ }
19
+
20
+ export function lintDraft(files: readonly SourceFile[]): DraftFinding[] {
21
+ const findings: DraftFinding[] = []
22
+ for (const file of files) {
23
+ const kind = markupKind(file.path)
24
+ if (kind === null) continue
25
+ const locate = lineLocator(file.text)
26
+ const seen = new Set<string>()
27
+ for (const node of textNodes(file.text, kind)) {
28
+ for (const hit of checkNode(node)) {
29
+ const at = locate(hit.offset)
30
+ const key = `${hit.offset}:${hit.rule}`
31
+ if (seen.has(key)) continue
32
+ seen.add(key)
33
+ findings.push({ file: file.path, ...at, rule: hit.rule, excerpt: excerptAt(file.text, hit.offset) })
34
+ }
35
+ }
36
+ }
37
+ return findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.column - b.column)
38
+ }
@@ -0,0 +1,69 @@
1
+ import type { DraftRuleId } from "./findings"
2
+ import { type Element, isStatElement, type TextNode } from "./text-nodes"
3
+
4
+ export type RuleHit = { readonly rule: DraftRuleId; readonly offset: number }
5
+
6
+ const PROMO_PHRASES = new RegExp(
7
+ [
8
+ String.raw`\bseamless(?:ly)?\b`,
9
+ String.raw`\beffortless(?:ly)?\b`,
10
+ String.raw`\bsupercharge[sd]?\b`,
11
+ String.raw`\bunlock (?:the (?:full )?power|the full potential|your (?:full )?potential)\b`,
12
+ String.raw`\bat a glance\b`,
13
+ String.raw`\bcutting[- ]edge\b`,
14
+ String.raw`\bgame[- ]chang(?:er|ing)\b`,
15
+ String.raw`\brevolutioni[sz]e\b`,
16
+ String.raw`\bnext[- ]level\b`,
17
+ String.raw`\bworld[- ]class\b`,
18
+ String.raw`\belevate your\b`,
19
+ "ν•œλˆˆμ—",
20
+ "μ†μ‰½κ²Œ",
21
+ "μŠ€λ§ˆνŠΈν•œ",
22
+ "ν˜μ‹ μ μΈ",
23
+ ].join("|"),
24
+ "giu",
25
+ )
26
+
27
+ const EMOJI = /\p{Emoji_Presentation}|\p{Extended_Pictographic}\uFE0F/u
28
+ const EMOJI_ALL = /\p{Emoji_Presentation}|\p{Extended_Pictographic}\uFE0F?/gu
29
+ const NUMERIC_ENTITY = /&#(?:x([0-9a-f]+)|(\d+));/gi
30
+ const BADGE_CLASS = /^(?:badge|chip|pill|tag)(?:$|[-_])/
31
+ const BADGE_COMPONENT = /^(?:Badge|Chip|Pill|Tag)$/
32
+ const HYPE_LABEL = /^(?:new!?|hot|trending|popular|featured|ai|ai[- ]powered|premium|recommended|best|μ‹ κ·œ|인기|μΆ”μ²œ|베슀트)$/i
33
+ const AMOUNT = String.raw`(?:\d{1,3}(?:[.,]\d{3})+|\d+)(?:[.,]\d+)?`
34
+ const MARKETING_NUMBER = new RegExp(String.raw`^(?:[$€£Β₯β‚©]?${AMOUNT}\s*(?:[kmb]|%)?\s*\+|${AMOUNT}\s*[xΓ—]|24\/7)$`, "i")
35
+
36
+ const isBadge = (element: Element | undefined): boolean =>
37
+ element !== undefined && !element.stateful && (BADGE_COMPONENT.test(element.name) || element.classes.some((c) => BADGE_CLASS.test(c)))
38
+
39
+ function leadingOffset(node: TextNode): number {
40
+ return node.offset + (node.text.length - node.text.trimStart().length)
41
+ }
42
+
43
+ function emojiOffset(text: string): number | null {
44
+ const direct = EMOJI.exec(text)
45
+ if (direct) return direct.index
46
+ for (const m of text.matchAll(NUMERIC_ENTITY)) {
47
+ const code = m[1] === undefined ? Number(m[2]) : Number.parseInt(m[1], 16)
48
+ if (Number.isInteger(code) && code <= 0x10ffff && EMOJI.test(String.fromCodePoint(code))) return m.index ?? 0
49
+ }
50
+ return null
51
+ }
52
+
53
+ /** A stat is a vanity number only in marketing form (10x, 500+, $2M+, 24/7); a measured figure such as 42% or 1.2k passes. */
54
+ export function checkNode(node: TextNode): RuleHit[] {
55
+ const hits: RuleHit[] = []
56
+ const label = node.text.trim()
57
+ if (node.kind !== "value") {
58
+ for (const m of node.text.matchAll(PROMO_PHRASES)) hits.push({ rule: "promo-copy", offset: node.offset + (m.index ?? 0) })
59
+ const emoji = emojiOffset(node.text)
60
+ if (emoji !== null) hits.push({ rule: "emoji-icon", offset: node.offset + emoji })
61
+ }
62
+ if (node.kind === "text" && isBadge(node.stack.at(-1)) && HYPE_LABEL.test(label.replace(EMOJI_ALL, "").trim())) {
63
+ hits.push({ rule: "decorative-badge", offset: leadingOffset(node) })
64
+ }
65
+ if (node.kind !== "label" && node.stack.some(isStatElement) && MARKETING_NUMBER.test(label)) {
66
+ hits.push({ rule: "vanity-stat", offset: leadingOffset(node) })
67
+ }
68
+ return hits
69
+ }
@@ -0,0 +1,121 @@
1
+ export type Element = {
2
+ readonly tag: string
3
+ readonly name: string
4
+ readonly classes: readonly string[]
5
+ readonly stateful: boolean
6
+ }
7
+
8
+ /** `text` is visible copy, `label` an announced attribute (aria-label, title, alt, placeholder), `value` a stat component's value prop. */
9
+ export type NodeKind = "text" | "label" | "value"
10
+ export type TextNode = { readonly kind: NodeKind; readonly text: string; readonly offset: number; readonly stack: readonly Element[] }
11
+
12
+ export type MarkupKind = "html" | "jsx" | "sfc"
13
+
14
+ const NEVER_RENDERED = /<(script|style|pre|code|textarea|noscript)\b[^>]*>[\s\S]*?<\/\1\s*>|<!--[\s\S]*?-->|\{\/\*[\s\S]*?\*\/\}/gi
15
+ const HTML_TEMPLATE = /<template\b(?![^>]*\s(?:x-[\w-]+|v-[\w-]+|[:@#][\w.-]+))[^>]*>[\s\S]*?<\/template\s*>/gi
16
+ const TAG = /<(\/?)([A-Za-z][\w.:-]*)((?:[^>"'{}]|"[^"]*"|'[^']*'|\{(?:[^{}]|\{[^{}]*\})*\})*)>/g
17
+ const CLASS_ATTR = /\b(?:class|className)\s*=\s*(?:"([^"]*)"|'([^']*)'|\{((?:[^{}]|\{[^{}]*\})*)\})/
18
+ const STRING_LITERAL = /["'`]([^"'`]*)["'`]/g
19
+ const ANNOUNCED_NAME = /(?:^|\s)(?:aria-label|title|alt|placeholder)\s*=/g
20
+ const VALUE_NAME = /(?:^|\s)value\s*=/
21
+ const LITERAL_VALUE = /^\s*(?:"([^"]*)"|'([^']*)'|\{\s*["'`]([^"'`]*)["'`]\s*\})/
22
+ const HIDDEN_ATTR = /(?:^|\s)hidden(?=\s|=|\/|$)/
23
+ const STATE_ATTR = /(?:^|\s)(?:data-status|data-state|aria-(?:current|selected|pressed|checked|expanded|busy|invalid|disabled|valuenow))\s*=/
24
+ const ATTR_VALUES = /"[^"]*"|'[^']*'|\{(?:[^{}]|\{[^{}]*\})*\}/g
25
+ const STAT_COMPONENT = /^(?:Stats?|Metrics?|Kpis?|KPIs?)(?:[A-Z]\w*)?$/
26
+ const STAT_CLASS = /^(?:stat|stats|metric|metrics|kpi)(?:$|[-_])/
27
+ const VOID_TAGS = new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "source", "track", "wbr"])
28
+ const JSX_LEAD = new Set(["(", "[", "{", "}", ",", ":", "?", "=", ">", "&", "|", ";"])
29
+
30
+ function blank(text: string, pattern: RegExp): string {
31
+ return text.replace(pattern, (m) => m.replace(/[^\n]/g, " "))
32
+ }
33
+
34
+ function classesOf(attrs: string): string[] {
35
+ const m = CLASS_ATTR.exec(attrs)
36
+ if (!m) return []
37
+ const literal = m[1] ?? m[2]
38
+ const raw = literal ?? [...(m[3] ?? "").matchAll(STRING_LITERAL)].map((s) => s[1] ?? "").join(" ")
39
+ return raw.split(/\s+/).filter(Boolean)
40
+ }
41
+
42
+ export function isStatElement(element: Element): boolean {
43
+ return STAT_COMPONENT.test(element.name) || element.classes.some((c) => STAT_CLASS.test(c))
44
+ }
45
+
46
+ function closeTo(stack: Element[], tag: string): void {
47
+ const at = stack.map((e) => e.tag).lastIndexOf(tag)
48
+ if (at >= 0) stack.length = at
49
+ }
50
+
51
+ /** In a script, `<` opens JSX only where an expression can start; `Array<string>`, `pick<T>(` and `a<b` stay code. */
52
+ function opensJsx(text: string, start: number, name: string, attrs: string): boolean {
53
+ if (/^\s*,|^\s+extends\b/.test(attrs)) return false
54
+ if (/^(?:const|in|out)$/.test(name) && /^\s+[A-Za-z_$]/.test(attrs)) return false
55
+ const before = text.slice(0, start).trimEnd()
56
+ if (before === "" || /\b(?:return|yield|default)$/.test(before)) return true
57
+ return JSX_LEAD.has(before.at(-1) ?? "")
58
+ }
59
+
60
+ function literalAfter(attrs: string, from: number): { readonly value: string; readonly at: number } | null {
61
+ const m = LITERAL_VALUE.exec(attrs.slice(from))
62
+ if (!m) return null
63
+ const value = m[1] ?? m[2] ?? m[3] ?? ""
64
+ return { value, at: from + m[0].lastIndexOf(value) }
65
+ }
66
+
67
+ function keepLiterals(segment: string): string {
68
+ return segment.replace(/\{[^{}]*\}/g, (m) => {
69
+ const lit = /^\{\s*(["'`])([^"'`]*)\1\s*\}$/.exec(m)
70
+ if (!lit) return " ".repeat(m.length)
71
+ const inner = lit[2] ?? ""
72
+ const at = m.indexOf(lit[1] ?? "") + 1
73
+ return " ".repeat(at) + inner + " ".repeat(m.length - at - inner.length)
74
+ })
75
+ }
76
+
77
+ /** Copy a reader sees or hears, each piece with the elements open around it. Code, hidden elements and never-rendered blocks are skipped. */
78
+ export function textNodes(source: string, kind: MarkupKind): TextNode[] {
79
+ const text = kind === "html" ? blank(blank(source, NEVER_RENDERED), HTML_TEMPLATE) : blank(source, NEVER_RENDERED)
80
+ const nodes: TextNode[] = []
81
+ const stack: Element[] = []
82
+ let hiddenDepth = 0
83
+ let cursor = 0
84
+ const flush = (end: number) => {
85
+ if (stack.length === 0 || hiddenDepth > 0) return
86
+ const segment = keepLiterals(text.slice(cursor, end))
87
+ if (segment.trim()) nodes.push({ kind: "text", text: segment, offset: cursor, stack: [...stack] })
88
+ }
89
+ for (const m of text.matchAll(TAG)) {
90
+ const start = m.index ?? 0
91
+ const [whole, closing, rawName = "", attrs = ""] = m
92
+ const end = start + whole.length
93
+ if (kind === "jsx" && !closing && stack.length === 0 && !opensJsx(text, start, rawName, attrs)) continue
94
+ flush(start)
95
+ cursor = end
96
+ const tag = rawName.toLowerCase()
97
+ if (closing) {
98
+ const at = stack.map((e) => e.tag).lastIndexOf(tag)
99
+ if (at >= 0 && hiddenDepth > at) hiddenDepth = 0
100
+ closeTo(stack, tag)
101
+ continue
102
+ }
103
+ const names = attrs.replace(ATTR_VALUES, (v) => " ".repeat(v.length))
104
+ const element: Element = { tag, name: rawName, classes: classesOf(attrs), stateful: STATE_ATTR.test(names) }
105
+ const attrsAt = start + 1 + rawName.length
106
+ const hidden = hiddenDepth > 0 || HIDDEN_ATTR.test(names)
107
+ if (!hidden) {
108
+ for (const a of names.matchAll(ANNOUNCED_NAME)) {
109
+ const lit = literalAfter(attrs, (a.index ?? 0) + a[0].length)
110
+ if (lit?.value.trim()) nodes.push({ kind: "label", text: lit.value, offset: attrsAt + lit.at, stack: [...stack, element] })
111
+ }
112
+ const v = isStatElement(element) ? VALUE_NAME.exec(names) : null
113
+ const lit = v ? literalAfter(attrs, v.index + v[0].length) : null
114
+ if (lit?.value.trim()) nodes.push({ kind: "value", text: lit.value, offset: attrsAt + lit.at, stack: [...stack, element] })
115
+ }
116
+ if (VOID_TAGS.has(tag) || attrs.trimEnd().endsWith("/")) continue
117
+ stack.push(element)
118
+ if (hiddenDepth === 0 && HIDDEN_ATTR.test(names)) hiddenDepth = stack.length
119
+ }
120
+ return nodes
121
+ }
@@ -0,0 +1,10 @@
1
+ export function Bar() {
2
+ return (
3
+ <div data-title="Supercharge your team">
4
+ <StatusBar><span>24/7</span></StatusBar>
5
+ <span className="badge" aria-current="page">New</span>
6
+ <div data-x="a title='Supercharge your team'" />
7
+ <Stat data-value="10x" />
8
+ </div>
9
+ )
10
+ }
@@ -0,0 +1,12 @@
1
+ export function Summary({ count, status, uptime }: { count: number; status: string; uptime: string }) {
2
+ return (
3
+ <section>
4
+ <div className="stat"><span className="stat-value">{count}</span><span>open tickets</span></div>
5
+ <div className="metric">{uptime}</div>
6
+ <span className="badge" data-status={status}>{status}</span>
7
+ <span className="badge">3</span>
8
+ <span className="chip">Failed</span>
9
+ <p>Seams in the fabric are reinforced.</p>
10
+ </section>
11
+ )
12
+ }
@@ -0,0 +1,3 @@
1
+ export const keep = <const T,>(x: T) => x
2
+ export const label = "Seamless sync"
3
+ export const Saved = () => <p>saved</p>
@@ -0,0 +1,7 @@
1
+ export const labels: Array<string> = ["Unlock the power", "πŸš€ launch"]
2
+ export const pick = <T,>(xs: T[]): T | undefined => xs[0]
3
+ export const first = <T extends object>(xs: T[]) => xs[0]
4
+ export const flag = (a: number, b: number) => (a<b && b>a ? "seamless sync" : "x")
5
+ export function Saved() {
6
+ return <p>Saved 3 files</p>
7
+ }
@@ -0,0 +1,6 @@
1
+ <section class="stats">
2
+ <div class="stat"><span class="stat-value">42%</span><span>refund rate, Q3</span></div>
3
+ <div class="metric">99.9%</div>
4
+ <div class="kpi"><strong>1.2k</strong> open tickets</div>
5
+ <div class="stat">$2M</div>
6
+ </section>
@@ -0,0 +1,9 @@
1
+ <main>
2
+ <h1>Monthly revenue</h1>
3
+ <p>Revenue rose 4% after the refund fix shipped on 3 June.</p>
4
+ <pre><code>const seamless = "Supercharge"</code></pre>
5
+ <footer>Β© 2026 Example Inc. Next page β†’</footer>
6
+ <script>const label = "Unlock the power of your data πŸš€"</script>
7
+ <style>.stat::after { content: "10x"; }</style>
8
+ <!-- ν•œλˆˆμ— λ³΄λŠ” λ©”λͺ¨ -->
9
+ </main>
@@ -0,0 +1,11 @@
1
+ <main>
2
+ <p>Unlock your account to continue.</p>
3
+ <p>졜적의 경둜λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.</p>
4
+ <p>Docs β†—</p>
5
+ <p>β–Ά Play</p>
6
+ <li>Inbox <span class="badge" data-status="unread">New</span></li>
7
+ <span class="pill">Pro</span>
8
+ <div hidden>Seamless onboarding</div>
9
+ <noscript>Supercharge your browser</noscript>
10
+ <template><p>Unlock the power of templates</p></template>
11
+ </main>
@@ -0,0 +1,7 @@
1
+ <main>
2
+ <div class="block hidden md:flex"><p>Seamless sync</p></div>
3
+ <button title="Show hidden files"><span>Supercharge your team</span></button>
4
+ <div class="stat"><span>1,000,000+</span></div>
5
+ <span class="badge" aria-hidden="true">New</span>
6
+ <template x-if="open"><p>Effortless setup</p></template>
7
+ </main>
@@ -0,0 +1,16 @@
1
+ const cn = (...names: string[]) => names.join(" ")
2
+ export function Page() {
3
+ return (
4
+ <main>
5
+ <Badge>New</Badge>
6
+ <span className={cn("badge", "badge--hot")}>Hot</span>
7
+ <span className="badge">✨ New</span>
8
+ <p>Launch &#x1F680; today</p>
9
+ <button type="button" aria-label="πŸš€ Launch">Go</button>
10
+ <Stat value="10x" />
11
+ <StatCard><p>10x</p></StatCard>
12
+ <div className="metric">{"500+"}</div>
13
+ <input placeholder="Supercharge your search" />
14
+ </main>
15
+ )
16
+ }
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <div>
3
+ <span class="badge">New</span>
4
+ <span class="chip chip--accent">AI-powered</span>
5
+ <h3>Monthly revenue</h3>
6
+ </div>
7
+ </template>
@@ -0,0 +1,9 @@
1
+ export function Actions() {
2
+ return (
3
+ <ul>
4
+ <li>βœ… Fast setup</li>
5
+ <li>Plain item</li>
6
+ <button type="button">πŸš€ Launch</button>
7
+ </ul>
8
+ )
9
+ }
@@ -0,0 +1 @@
1
+ export const Beta = () => <p>(beta) Seamless sync</p>
@@ -0,0 +1,6 @@
1
+ <section class="hero">
2
+ <h1>Seamlessly manage every report</h1>
3
+ <p>ν•œλˆˆμ— λ³΄λŠ” 맀좜 ν˜„ν™©</p>
4
+ <p>Track revenue and refunds.</p>
5
+ <p>Unlock the power of your data</p>
6
+ </section>
@@ -0,0 +1,8 @@
1
+ export function Hero() {
2
+ return (
3
+ <header>
4
+ <h2>Supercharge your workflow</h2>
5
+ <p>μ†μ‰½κ²Œ μ‹œμž‘ν•˜μ„Έμš”</p>
6
+ </header>
7
+ )
8
+ }
@@ -0,0 +1,5 @@
1
+ <div class="stats">
2
+ <div class="stat"><span class="stat-value">10x</span><span>faster</span></div>
3
+ <div class="metric">$2M+</div>
4
+ <div class="kpi-card"><strong>24/7</strong></div>
5
+ </div>