@adia-ai/adia-ui-forge 0.1.3 → 0.8.1

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 (259) hide show
  1. package/.claude-plugin/plugin.json +4 -7
  2. package/CHANGELOG.md +35 -34
  3. package/README.md +35 -40
  4. package/agents/a2ui-engineer.md +22 -53
  5. package/agents/component-author.md +29 -0
  6. package/agents/framework-verifier.md +26 -0
  7. package/agents/release-engineer.md +21 -81
  8. package/agents/routing-corpus.json +293 -64
  9. package/bin/demo-postwrite-pattern-gate +94 -0
  10. package/bin/forge-lint +17 -2
  11. package/bin/sidecar-prewrite-guard +104 -0
  12. package/commands/deploy.md +9 -0
  13. package/commands/dogfood.md +10 -0
  14. package/commands/gen-review.md +9 -0
  15. package/commands/release.md +10 -0
  16. package/hooks/hooks.json +15 -0
  17. package/package.json +3 -6
  18. package/references/contracts/a2ui-mcp-surface.md +35 -0
  19. package/references/contracts/migration-guide-format.md +34 -0
  20. package/references/shared/content-trust.md +19 -74
  21. package/skills/adia-a2ui/SKILL.md +99 -0
  22. package/skills/{adia-ui-a2ui → adia-a2ui}/evals/routing-corpus.json +10 -10
  23. package/skills/adia-a2ui/references/anti-patterns.md +27 -0
  24. package/skills/adia-a2ui/references/chunk-authoring.md +71 -0
  25. package/skills/adia-a2ui/references/corpus-discipline.md +68 -0
  26. package/skills/adia-a2ui/references/eval-diagnostics.md +86 -0
  27. package/skills/adia-a2ui/references/format-extension-decisions.md +66 -0
  28. package/skills/adia-a2ui/references/leverage-rules.md +52 -0
  29. package/skills/adia-a2ui/references/mcp-pipeline-ops.md +83 -0
  30. package/skills/adia-a2ui/references/mcp-tool-reference.md +59 -0
  31. package/skills/adia-a2ui/references/pipeline-overview.md +115 -0
  32. package/skills/adia-a2ui/references/semantic-fail-lifting.md +74 -0
  33. package/skills/adia-a2ui/references/strategy-engines.md +109 -0
  34. package/skills/adia-a2ui/references/zettel-calibration.md +104 -0
  35. package/skills/adia-author/SKILL.md +112 -0
  36. package/skills/adia-author/evals/routing-corpus.json +222 -0
  37. package/skills/{adia-ui-authoring → adia-author}/references/anti-patterns.md +33 -4
  38. package/skills/{adia-ui-authoring → adia-author}/references/authoring-cycle.md +9 -11
  39. package/skills/adia-author/references/canonical-pattern-index.md +243 -0
  40. package/skills/{adia-ui-authoring → adia-author}/references/code-style.md +19 -21
  41. package/skills/adia-author/references/common-gotchas.md +129 -0
  42. package/skills/adia-author/references/composite-demo-protocol.md +271 -0
  43. package/skills/{adia-ui-authoring → adia-author}/references/css-patterns.md +19 -6
  44. package/skills/{adia-ui-authoring → adia-author}/references/lifecycle-patterns.md +1 -0
  45. package/skills/{adia-ui-authoring → adia-author}/references/llm-bridge.md +3 -5
  46. package/skills/{adia-ui-authoring → adia-author}/references/module-promotion.md +20 -38
  47. package/skills/{adia-ui-authoring → adia-author}/references/primitive-audit.md +2 -4
  48. package/skills/{adia-ui-authoring → adia-author}/references/shell-patterns.md +12 -18
  49. package/skills/{adia-ui-authoring → adia-author}/references/token-contract.md +5 -7
  50. package/skills/{adia-ui-authoring → adia-author}/references/worked-example.md +3 -3
  51. package/skills/{adia-ui-authoring → adia-author}/references/yaml-contract.md +3 -3
  52. package/skills/{adia-ui-authoring → adia-author}/scripts/build-canonical-pattern-index.mjs +3 -3
  53. package/skills/adia-deploy/SKILL.md +128 -0
  54. package/skills/{adia-ui-ops → adia-deploy}/references/deploy-playbooks.md +47 -30
  55. package/skills/adia-dogfood/SKILL.md +124 -0
  56. package/skills/adia-dogfood/references/admin-shell-anatomy.md +77 -0
  57. package/skills/adia-dogfood/references/app-shell-pitfalls.md +66 -0
  58. package/skills/adia-dogfood/references/card-anatomy-sweep.md +66 -0
  59. package/skills/adia-dogfood/references/html-attr-sweep.md +63 -0
  60. package/skills/adia-dogfood/references/native-leak-annotations.md +73 -0
  61. package/skills/adia-dogfood/references/visual-probe-triage.md +80 -0
  62. package/skills/{adia-ui-dogfood → adia-dogfood}/scripts/analyze.mjs +30 -14
  63. package/skills/adia-gen-review/SKILL.md +127 -0
  64. package/skills/adia-gen-review/references/corpus-html-patterns.md +279 -0
  65. package/skills/adia-gen-review/references/loop-protocol.md +216 -0
  66. package/skills/adia-gen-review/references/rubric-cosmetic.md +100 -0
  67. package/skills/adia-gen-review/references/rubric-decompose.md +101 -0
  68. package/skills/adia-gen-review/references/rubric-score.md +214 -0
  69. package/skills/{adia-ui-gen-review → adia-gen-review}/references/scores.schema.json +2 -2
  70. package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-coverage-audit.mjs +4 -4
  71. package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-decompose.mjs +10 -6
  72. package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/gen-review-status.mjs +5 -5
  73. package/skills/{adia-ui-gen-review → adia-gen-review}/scripts/validate-cycle-scores.mjs +5 -5
  74. package/skills/adia-llm-internals/SKILL.md +77 -0
  75. package/skills/{adia-ui-llm → adia-llm-internals}/references/adapter-contract.md +4 -2
  76. package/skills/{adia-ui-llm → adia-llm-internals}/references/add-a-provider.md +4 -5
  77. package/skills/{adia-ui-llm → adia-llm-internals}/references/bridge-facade.md +10 -3
  78. package/skills/{adia-ui-llm → adia-llm-internals}/references/browser-proxy-boundary.md +1 -1
  79. package/skills/{adia-ui-llm → adia-llm-internals}/references/model-registry.md +5 -3
  80. package/skills/{adia-ui-llm → adia-llm-internals}/references/streaming-sse.md +2 -2
  81. package/skills/adia-release/SKILL.md +72 -0
  82. package/skills/adia-release/references/changelog-discipline.md +119 -0
  83. package/skills/adia-release/references/cut-procedure.md +247 -0
  84. package/skills/adia-release/references/gates-catalog.md +222 -0
  85. package/skills/adia-release/references/independent-package-release.md +52 -0
  86. package/skills/adia-release/references/migration-guide-authoring.md +86 -0
  87. package/skills/adia-release/references/notes-authoring.md +90 -0
  88. package/skills/adia-release/references/recovery-paths.md +106 -0
  89. package/skills/{adia-ui-release → adia-release}/scripts/bump.mjs +28 -3
  90. package/skills/{adia-ui-release → adia-release}/scripts/dispatch-publish.mjs +10 -7
  91. package/skills/{adia-ui-release → adia-release}/scripts/insert-stub.mjs +1 -1
  92. package/skills/{adia-ui-release → adia-release}/scripts/package-paths.mjs +6 -0
  93. package/skills/{adia-ui-release → adia-release}/scripts/promote-unreleased.mjs +1 -1
  94. package/skills/{adia-ui-release → adia-release}/scripts/release-pack.mjs +38 -31
  95. package/skills/{adia-ui-release → adia-release}/scripts/tag-lockstep.mjs +7 -3
  96. package/skills/adia-site-docs/SKILL.md +68 -0
  97. package/skills/adia-site-docs/evals/audit-report.md +30 -0
  98. package/skills/adia-site-docs/evals/routing-corpus.json +176 -0
  99. package/skills/adia-site-docs/intent.md +72 -0
  100. package/agents/README.md +0 -209
  101. package/agents/author.md +0 -56
  102. package/agents/repo-steward.md +0 -56
  103. package/agents/spec-architect.md +0 -53
  104. package/agents/tech-lead.md +0 -57
  105. package/agents/verifier.md +0 -55
  106. package/bin/lib/audit-axes.mjs +0 -555
  107. package/bin/lib/dry-run-irreversible.mjs +0 -236
  108. package/bin/lib/run-skill-evals.mjs +0 -487
  109. package/bin/lib/teach-router.mjs +0 -250
  110. package/commands/adia-forge-a2ui.md +0 -10
  111. package/commands/adia-forge-author.md +0 -10
  112. package/commands/adia-forge-dogfood.md +0 -8
  113. package/commands/adia-forge-llm.md +0 -8
  114. package/commands/adia-forge-orient.md +0 -10
  115. package/commands/adia-forge-release.md +0 -8
  116. package/commands/adia-forge-review.md +0 -10
  117. package/references/shared/pev-rationale.md +0 -64
  118. package/references/shared/skill-conventions.md +0 -133
  119. package/skills/adia-ui-a2ui/CHANGELOG.md +0 -32
  120. package/skills/adia-ui-a2ui/SKILL.md +0 -243
  121. package/skills/adia-ui-a2ui/evals/adversarial-corpus.json +0 -75
  122. package/skills/adia-ui-a2ui/evals/teach-routing-cases.json +0 -100
  123. package/skills/adia-ui-a2ui/references/anti-patterns.md +0 -24
  124. package/skills/adia-ui-a2ui/references/chunk-authoring.md +0 -88
  125. package/skills/adia-ui-a2ui/references/corpus-discipline.md +0 -56
  126. package/skills/adia-ui-a2ui/references/eval-diagnostics.md +0 -127
  127. package/skills/adia-ui-a2ui/references/fragment-graph.md +0 -91
  128. package/skills/adia-ui-a2ui/references/mcp-pipeline-ops.md +0 -106
  129. package/skills/adia-ui-a2ui/references/mcp-tool-reference.md +0 -398
  130. package/skills/adia-ui-a2ui/references/pipeline-overview.md +0 -175
  131. package/skills/adia-ui-a2ui/references/semantic-fail-lifting.md +0 -120
  132. package/skills/adia-ui-a2ui/references/strategy-engines.md +0 -111
  133. package/skills/adia-ui-a2ui/references/teach-protocol.md +0 -220
  134. package/skills/adia-ui-a2ui/references/zettel-calibration.md +0 -93
  135. package/skills/adia-ui-a2ui/scripts/audit-a2ui-roster.mjs +0 -96
  136. package/skills/adia-ui-a2ui/scripts/teach-route.mjs +0 -157
  137. package/skills/adia-ui-a2ui/skill.json +0 -38
  138. package/skills/adia-ui-authoring/CHANGELOG.md +0 -32
  139. package/skills/adia-ui-authoring/SKILL.md +0 -256
  140. package/skills/adia-ui-authoring/assets/case-studies/admin-shell-decomposition.md +0 -101
  141. package/skills/adia-ui-authoring/assets/case-studies/maxtokens-32768-discovery.md +0 -109
  142. package/skills/adia-ui-authoring/assets/case-studies/theme-panel-promotion.md +0 -113
  143. package/skills/adia-ui-authoring/evals/adversarial-design-plan-gates.json +0 -138
  144. package/skills/adia-ui-authoring/evals/routing-corpus.json +0 -245
  145. package/skills/adia-ui-authoring/references/canonical-pattern-index.md +0 -179
  146. package/skills/adia-ui-authoring/references/common-gotchas.md +0 -93
  147. package/skills/adia-ui-authoring/references/composite-demo-protocol.md +0 -1084
  148. package/skills/adia-ui-authoring/references/teach-protocol.md +0 -428
  149. package/skills/adia-ui-authoring/scripts/audit-authoring-roster.mjs +0 -148
  150. package/skills/adia-ui-authoring/skill.json +0 -45
  151. package/skills/adia-ui-dogfood/CHANGELOG.md +0 -17
  152. package/skills/adia-ui-dogfood/README.md +0 -62
  153. package/skills/adia-ui-dogfood/SKILL.md +0 -866
  154. package/skills/adia-ui-dogfood/skill.json +0 -40
  155. package/skills/adia-ui-forge/SKILL.md +0 -88
  156. package/skills/adia-ui-forge/evals/routing-corpus.json +0 -30
  157. package/skills/adia-ui-gen-review/CHANGELOG.md +0 -108
  158. package/skills/adia-ui-gen-review/SKILL.md +0 -266
  159. package/skills/adia-ui-gen-review/references/loop-protocol.md +0 -712
  160. package/skills/adia-ui-gen-review/references/rubric-cosmetic.md +0 -144
  161. package/skills/adia-ui-gen-review/references/rubric-decompose.md +0 -117
  162. package/skills/adia-ui-gen-review/references/rubric-score.md +0 -249
  163. package/skills/adia-ui-gen-review/references/teach-protocol.md +0 -214
  164. package/skills/adia-ui-gen-review/skill.json +0 -23
  165. package/skills/adia-ui-llm/CHANGELOG.md +0 -25
  166. package/skills/adia-ui-llm/SKILL.md +0 -165
  167. package/skills/adia-ui-llm/evals/adversarial-corpus.json +0 -75
  168. package/skills/adia-ui-llm/evals/routing-corpus.json +0 -30
  169. package/skills/adia-ui-llm/evals/teach-routing-cases.json +0 -73
  170. package/skills/adia-ui-llm/references/teach-protocol.md +0 -78
  171. package/skills/adia-ui-llm/scripts/audit-llm-roster.mjs +0 -93
  172. package/skills/adia-ui-llm/scripts/teach-route.mjs +0 -119
  173. package/skills/adia-ui-llm/skill.json +0 -33
  174. package/skills/adia-ui-ops/CHANGELOG.md +0 -291
  175. package/skills/adia-ui-ops/SKILL.md +0 -401
  176. package/skills/adia-ui-ops/references/INDEX.md +0 -158
  177. package/skills/adia-ui-ops/references/audit-cadence.md +0 -263
  178. package/skills/adia-ui-ops/references/audit-patterns/archive-link-sweep.md +0 -96
  179. package/skills/adia-ui-ops/references/audit-patterns/audit-history-ledger.md +0 -162
  180. package/skills/adia-ui-ops/references/audit-patterns/browser-bundle-node-imports.md +0 -154
  181. package/skills/adia-ui-ops/references/audit-patterns/changelog-unreleased-bloat.md +0 -75
  182. package/skills/adia-ui-ops/references/audit-patterns/coverage-gaps.md +0 -187
  183. package/skills/adia-ui-ops/references/audit-patterns/entry-file-coverage.md +0 -122
  184. package/skills/adia-ui-ops/references/audit-patterns/format-hygiene.md +0 -217
  185. package/skills/adia-ui-ops/references/audit-patterns/lockstep-versioning.md +0 -113
  186. package/skills/adia-ui-ops/references/audit-patterns/memory-fragmentation.md +0 -180
  187. package/skills/adia-ui-ops/references/audit-patterns/orphan-detection.md +0 -202
  188. package/skills/adia-ui-ops/references/audit-patterns/pointer-validation.md +0 -180
  189. package/skills/adia-ui-ops/references/audit-patterns/redundancy-detection.md +0 -210
  190. package/skills/adia-ui-ops/references/audit-patterns/spec-dating-sweep.md +0 -91
  191. package/skills/adia-ui-ops/references/audit-patterns/stale-content.md +0 -182
  192. package/skills/adia-ui-ops/references/audit-patterns/staleness-tooling.md +0 -156
  193. package/skills/adia-ui-ops/references/audit-patterns/token-waste-detection.md +0 -196
  194. package/skills/adia-ui-ops/references/doc-types/adr-pattern.md +0 -210
  195. package/skills/adia-ui-ops/references/doc-types/architecture-md.md +0 -190
  196. package/skills/adia-ui-ops/references/doc-types/changelog.md +0 -183
  197. package/skills/adia-ui-ops/references/doc-types/decisions-log.md +0 -146
  198. package/skills/adia-ui-ops/references/doc-types/plan-roadmap.md +0 -182
  199. package/skills/adia-ui-ops/references/doc-types/postmortem-pattern.md +0 -206
  200. package/skills/adia-ui-ops/references/genres/prose-and-writing.md +0 -149
  201. package/skills/adia-ui-ops/references/guidance/context-budget.md +0 -137
  202. package/skills/adia-ui-ops/references/guidance/llm-doc-writing.md +0 -116
  203. package/skills/adia-ui-ops/references/guidance/reliability-dial.md +0 -186
  204. package/skills/adia-ui-ops/references/recipes/adr-introduction.md +0 -211
  205. package/skills/adia-ui-ops/references/recipes/audit-existing-repo.md +0 -234
  206. package/skills/adia-ui-ops/references/recipes/cold-start-harvest.md +0 -263
  207. package/skills/adia-ui-ops/references/recipes/concurrent-learnings-merge.md +0 -158
  208. package/skills/adia-ui-ops/references/recipes/continuous-learning-loop.md +0 -169
  209. package/skills/adia-ui-ops/references/recipes/external-reference-verification.md +0 -158
  210. package/skills/adia-ui-ops/references/recipes/findings-index-readout.md +0 -126
  211. package/skills/adia-ui-ops/references/recipes/greenfield-setup.md +0 -252
  212. package/skills/adia-ui-ops/references/recipes/harvest-repo-brain.md +0 -169
  213. package/skills/adia-ui-ops/references/recipes/import-repo-brain-harvest.md +0 -153
  214. package/skills/adia-ui-ops/references/recipes/memory-organization.md +0 -182
  215. package/skills/adia-ui-ops/references/recipes/recommend-then-validate.md +0 -199
  216. package/skills/adia-ui-ops/references/recipes/self-healing-hooks.md +0 -366
  217. package/skills/adia-ui-ops/references/recipes/skill-stewardship-loop.md +0 -113
  218. package/skills/adia-ui-ops/references/standards/agents-md-spec.md +0 -138
  219. package/skills/adia-ui-ops/references/standards/claude-md-convention.md +0 -123
  220. package/skills/adia-ui-ops/references/standards/cross-tool-matrix.md +0 -85
  221. package/skills/adia-ui-ops/references/standards/readme-conventions.md +0 -232
  222. package/skills/adia-ui-ops/references/teach-protocol.md +0 -215
  223. package/skills/adia-ui-ops/scripts/audit-ops-roster.mjs +0 -104
  224. package/skills/adia-ui-ops/skill.json +0 -65
  225. package/skills/adia-ui-release/CHANGELOG.md +0 -66
  226. package/skills/adia-ui-release/SKILL.md +0 -323
  227. package/skills/adia-ui-release/assets/case-studies/2026-05-20-batch-push-v0.6.14-v0.6.15.md +0 -144
  228. package/skills/adia-ui-release/assets/case-studies/2026-05-20-corpus-drift-remediation-v0.6.15.md +0 -155
  229. package/skills/adia-ui-release/assets/case-studies/2026-05-20-version-skip-correction-v0.6.12.md +0 -114
  230. package/skills/adia-ui-release/assets/case-studies/2026-05-21-author-from-scratch-v0.6.18.md +0 -139
  231. package/skills/adia-ui-release/assets/case-studies/2026-05-21-feedback37-retraction-v0.6.21.md +0 -124
  232. package/skills/adia-ui-release/assets/case-studies/2026-05-21-fn1-enrichment-pass-v0.6.19.md +0 -125
  233. package/skills/adia-ui-release/assets/case-studies/2026-05-21-stale-test-detection-v0.6.20.md +0 -142
  234. package/skills/adia-ui-release/assets/case-studies/2026-05-23-freshness-gate-recovery-v0.6.32.md +0 -97
  235. package/skills/adia-ui-release/assets/case-studies/2026-05-26-catalog-drift-recurring-v0.6.40.md +0 -147
  236. package/skills/adia-ui-release/assets/templates/stub-changelog.template.md +0 -22
  237. package/skills/adia-ui-release/evals/evals.json +0 -164
  238. package/skills/adia-ui-release/references/changelog-discipline.md +0 -250
  239. package/skills/adia-ui-release/references/cycle-happy-path.md +0 -520
  240. package/skills/adia-ui-release/references/exe-deploy.md +0 -149
  241. package/skills/adia-ui-release/references/gates-catalog.md +0 -778
  242. package/skills/adia-ui-release/references/independent-package-release.md +0 -129
  243. package/skills/adia-ui-release/references/ledger-discipline.md +0 -232
  244. package/skills/adia-ui-release/references/migration-guide-authoring.md +0 -174
  245. package/skills/adia-ui-release/references/multi-agent-baseline.md +0 -207
  246. package/skills/adia-ui-release/references/notes-authoring.md +0 -212
  247. package/skills/adia-ui-release/references/recovery-paths.md +0 -262
  248. package/skills/adia-ui-release/references/rollup-notes.md +0 -208
  249. package/skills/adia-ui-release/references/teach-protocol.md +0 -468
  250. package/skills/adia-ui-release/scripts/audit-gate-roster.mjs +0 -196
  251. package/skills/adia-ui-release/scripts/make-ledger.mjs +0 -200
  252. package/skills/adia-ui-release/skill.json +0 -77
  253. package/skills/dogfood-sweep/CHANGELOG.md +0 -37
  254. package/skills/dogfood-sweep/README.md +0 -105
  255. package/skills/dogfood-sweep/SKILL.md +0 -1000
  256. package/skills/dogfood-sweep/analyze.mjs +0 -600
  257. package/skills/dogfood-sweep/skill.json +0 -31
  258. /package/skills/{adia-ui-authoring → adia-author}/references/api-contract.md +0 -0
  259. /package/skills/{adia-ui-release → adia-release}/scripts/assert-monorepo-root.mjs +0 -0
@@ -1,600 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Dogfooding analyzer — walks every `/site/components/*` demo page in a
4
- * headless browser and runs visual-correctness probes that type-checks
5
- * and tests don't catch.
6
- *
7
- * Probes:
8
- * 1. Zero-area — `*-ui` elements that render at 0×0 (e.g. parent
9
- * `display:none`, children moved into an overflow
10
- * popover, contents collapsed).
11
- * 2. Transparent — swatches/badges/indicators with known
12
- * "should-be-colored" semantics whose computed
13
- * background is `rgba(0,0,0,0)` (chart-legend bug
14
- * class — a fallback token that doesn't resolve).
15
- * 3. Empty-control — form controls (`input-ui`, `search-ui`, etc.)
16
- * whose `connected()` should have stamped an
17
- * `<input>` or `[contenteditable]` but didn't.
18
- * 4. Synonym-attr — known synonym-attribute / synonym-slot drift
19
- * classes documented in
20
- * `docs/conventions/attribute-api-migration.md`.
21
- * 5. Console — errors + deprecation warnings during page
22
- * load + 800ms settling.
23
- *
24
- * Output:
25
- * docs/reports/dogfooding-YYYY-MM-DD.md (or path from --out)
26
- * Severity levels: critical (page broken), warning (likely-broken),
27
- * info (drift, deprecation, non-blocking).
28
- *
29
- * Usage:
30
- * node .agents/skills/dogfood-sweep/analyze.mjs # full sweep
31
- * node .agents/skills/dogfood-sweep/analyze.mjs --filter chart-legend # one page
32
- * node .agents/skills/dogfood-sweep/analyze.mjs --port 5173 # custom port
33
- * node .agents/skills/dogfood-sweep/analyze.mjs --out /tmp/report.md # custom path
34
- * node .agents/skills/dogfood-sweep/analyze.mjs --quiet # report only
35
- *
36
- * Assumes the dev server is already running. Spin one up first:
37
- * npm run dev # in a separate terminal
38
- */
39
-
40
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
41
- import { join, dirname } from 'node:path';
42
- import { fileURLToPath } from 'node:url';
43
- import { chromium } from 'playwright';
44
-
45
- const __dirname = dirname(fileURLToPath(import.meta.url));
46
- // SoT lives at packages/plugins/adia-ui-forge/skills/dogfood-sweep/ → repo root
47
- // is five levels up (ADR-0040 Phase 4 carve; the .agents/skills/dogfood-sweep
48
- // path is a symlink, and Node resolves import.meta.url to the real file location).
49
- const REPO_ROOT = join(__dirname, '..', '..', '..', '..', '..');
50
-
51
- // ── Args ──────────────────────────────────────────────────────────────────
52
-
53
- const args = process.argv.slice(2);
54
- const argVal = (flag) => {
55
- const i = args.indexOf(flag);
56
- return i >= 0 && args[i + 1] && !args[i + 1].startsWith('--') ? args[i + 1] : null;
57
- };
58
- const FILTER = argVal('--filter');
59
- const PORT = parseInt(argVal('--port') || '5173', 10);
60
- const QUIET = args.includes('--quiet');
61
- const today = new Date().toISOString().slice(0, 10);
62
- const OUT = argVal('--out') || join(REPO_ROOT, 'docs/reports', `dogfooding-${today}.md`);
63
-
64
- const log = (...m) => { if (!QUIET) console.error(...m); };
65
-
66
- // ── Component contracts (what each component MUST stamp at render) ────────
67
- //
68
- // Narrow on purpose: most AdiaUI components are *the* interactive surface
69
- // (role="button" + tabindex + own listeners), not host-of-native-control.
70
- // Listing them here as "must have a <button> child" produces 300+ false
71
- // positives. The genuinely-stamping components are input-ui (creates an
72
- // `<input>` or `<span contenteditable>`) and search-ui (wraps input-ui).
73
-
74
- const STAMP_CONTRACTS = {
75
- 'input-ui': {
76
- reason: 'connected() should stamp <input slot="text"> or <span slot="text" contenteditable>',
77
- },
78
- 'search-ui': {
79
- reason: 'connected() should stamp <input-ui type="search"> internally',
80
- },
81
- };
82
-
83
- // ── Selectors that should resolve to a non-transparent background ─────────
84
- //
85
- // `[data-swatch]`, semantic-variant pills/buttons, and chart indicators.
86
- // rgba(0,0,0,0) on these = bug (the chart-legend class).
87
-
88
- const COLORED_SELECTORS = [
89
- // chart-legend / chart-tooltip swatches
90
- '[data-swatch]',
91
- '[data-indicator]',
92
- // semantic variants on tag-ui / button-ui / alert-ui
93
- 'tag-ui[variant=primary]',
94
- 'tag-ui[variant=success]',
95
- 'tag-ui[variant=warning]',
96
- 'tag-ui[variant=danger]',
97
- 'tag-ui[variant=info]',
98
- 'button-ui[variant=primary]:not([disabled])',
99
- 'button-ui[color=danger]:not([disabled])',
100
- ];
101
-
102
- // ── Synonym-attribute / synonym-slot drift markers ────────────────────────
103
- //
104
- // Mirrors `docs/conventions/attribute-api-migration.md`. These run via
105
- // querySelectorAll; matching elements are flagged as info-level.
106
-
107
- const DRIFT_MARKERS = [
108
- { selector: 'avatar-ui[name]', message: '<avatar-ui name=…> is deprecated; use text=…' },
109
- { selector: 'grid-ui[cols]', message: '<grid-ui cols=…> is the synonym; canonical is columns=…' },
110
- { selector: 'stepper-ui[current]', message: '<stepper-ui current=…> is the synonym; canonical is step=…' },
111
- { selector: 'stepper-item-ui[state]', message: '<stepper-item-ui state=…> is the synonym; parent <stepper-ui step> drives it' },
112
- { selector: 'card-ui [slot="meta"]', message: 'card-ui has no slot="meta" rule — tag falls into bare grid cell and stretches' },
113
- ];
114
-
115
- // ── Probes (all run in-page via page.evaluate) ────────────────────────────
116
-
117
- async function runProbes(page) {
118
- return await page.evaluate(({ COLORED_SELECTORS, DRIFT_MARKERS }) => {
119
- const findings = [];
120
- const push = (severity, kind, detail) => findings.push({ severity, kind, ...detail });
121
-
122
- // 1. Zero-area
123
- // Walk artifact items; skip elements that are intentionally hidden
124
- // (any display:none / visibility:hidden / [hidden] ancestor — e.g.
125
- // avatar-group's overflow children, popover panels, drawer contents)
126
- // or that are "rendered-on-demand" components which only paint when
127
- // opened (drawers, modals, popovers, tooltips, toasts).
128
- const ON_DEMAND_TAGS = new Set([
129
- 'drawer-ui', 'modal-ui', 'popover-ui', 'tooltip-ui', 'toast-ui',
130
- 'context-menu-ui', 'sheet-ui', 'dialog-ui',
131
- ]);
132
- const isIntentionallyHidden = (el) => {
133
- let p = el;
134
- while (p && p.nodeType === 1) {
135
- if (p.hasAttribute?.('hidden')) return true;
136
- if (p.hasAttribute?.('popover')) return true; // popover API closed
137
- if (p.tagName === 'DIALOG' && !p.open) return true;
138
- if (ON_DEMAND_TAGS.has(p.tagName?.toLowerCase())) return true;
139
- const cs = getComputedStyle(p);
140
- if (cs.display === 'none' || cs.visibility === 'hidden') return true;
141
- // Stop walking at the artifact-item boundary.
142
- if (p.matches?.('[data-artifact-item]')) return false;
143
- p = p.parentElement;
144
- }
145
- return false;
146
- };
147
- document.querySelectorAll('[data-artifact-item] *').forEach((el) => {
148
- if (!el.tagName.endsWith('-UI')) return;
149
- if (ON_DEMAND_TAGS.has(el.tagName.toLowerCase())) return;
150
- if (isIntentionallyHidden(el)) return;
151
- const r = el.getBoundingClientRect();
152
- // Only flag elements that should have rendered something — skip those
153
- // with no children, no text, and no [icon]/[text] attrs.
154
- const hasIntent =
155
- el.children.length > 0 ||
156
- (el.textContent || '').trim().length > 0 ||
157
- el.hasAttribute('icon') ||
158
- el.hasAttribute('text') ||
159
- el.hasAttribute('label');
160
- if (hasIntent && (r.width === 0 || r.height === 0)) {
161
- push('critical', 'zero-area', {
162
- tag: el.tagName.toLowerCase(),
163
- label: el.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
164
- rect: { w: Math.round(r.width), h: Math.round(r.height) },
165
- hint: el.parentElement?.tagName === 'TOOLBAR-UI'
166
- ? 'parent toolbar-ui — likely overflow="menu" spilled it into the popover'
167
- : null,
168
- });
169
- }
170
- });
171
-
172
- // 2. Transparent-where-colored
173
- for (const selector of COLORED_SELECTORS) {
174
- document.querySelectorAll(selector).forEach((el) => {
175
- const r = el.getBoundingClientRect();
176
- if (r.width === 0 || r.height === 0) return; // already flagged or hidden
177
- const cs = getComputedStyle(el);
178
- const bg = cs.backgroundColor;
179
- const borderTop = cs.borderTopColor;
180
- const isTransparent = bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent';
181
- const borderTransparent = !borderTop || borderTop === 'rgba(0, 0, 0, 0)';
182
- // [data-swatch] for shape="dashed" intentionally has transparent bg
183
- // and paints via border-top instead. Test that directly: any
184
- // colored top border with non-zero width is "by design".
185
- const paintsViaBorder =
186
- el.matches('[data-swatch]') &&
187
- parseFloat(cs.borderTopWidth) > 0 &&
188
- !borderTransparent;
189
- if (paintsViaBorder) return;
190
- if (isTransparent) {
191
- push('critical', 'transparent-fill', {
192
- selector,
193
- tag: el.tagName.toLowerCase(),
194
- label: el.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
195
- inlineSwatchVar: el.style.getPropertyValue('--swatch-color') || null,
196
- });
197
- }
198
- });
199
- }
200
-
201
- // 3. Synonym-attr / synonym-slot drift
202
- for (const { selector, message } of DRIFT_MARKERS) {
203
- document.querySelectorAll(selector).forEach((el) => {
204
- push('info', 'drift', {
205
- selector,
206
- message,
207
- tag: el.tagName.toLowerCase(),
208
- label: el.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
209
- });
210
- });
211
- }
212
-
213
- // 4. Multi-child rich content inside alert-ui (no col-ui wrap)
214
- document.querySelectorAll('alert-ui').forEach((alert) => {
215
- const direct = Array.from(alert.children).filter(
216
- (c) => !c.hasAttribute('slot'),
217
- );
218
- if (direct.length >= 2 && direct.every((c) => c.tagName === 'TEXT-UI')) {
219
- push('warning', 'alert-flex-row', {
220
- tag: 'alert-ui',
221
- label: alert.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
222
- message: 'multiple bare <text-ui> inside alert-ui lay out as flex-row — wrap in <col-ui slot="content">',
223
- });
224
- }
225
- });
226
-
227
- // 5. Missing component CSS — for each unique *-ui tag rendered on
228
- // the page, verify a stylesheet matching `/components/{prefix}/{prefix}.css`
229
- // is loaded. Catches the "swap to <select-ui> but forget to <link>
230
- // select.css" class — markup looks right, JS registers the element,
231
- // every other probe passes, but the listbox renders unstyled.
232
- //
233
- // Demo pages under /site/components/<X>/ usually embed all sibling
234
- // components transitively (their docs router shell loads tokens.css
235
- // + a barrel, so most components resolve). When this probe fires
236
- // on a demo page, it's signaling a real authoring miss — either
237
- // a link tag was dropped or a new component on the page wasn't
238
- // added to the shell loader.
239
- // Components / infra elements that legitimately ship without a sibling
240
- // {prefix}/{prefix}.css under packages/web-components/components/. Two
241
- // groups:
242
- //
243
- // 1. CSS-only components (yaml + a2ui.json only, styled by parent slot
244
- // rules — per `feedback_css_only_components`). Source of truth:
245
- // `for d in components/*/; do n="${d%/}"; [ ! -f "$d$n.css" ] &&
246
- // echo "$n"; done` enumerates them.
247
- //
248
- // 2. Infrastructure elements registered outside components/ (e.g.
249
- // `router-ui` from core/provider.js). They have inline / shell
250
- // stylesheets that don't match the path pattern.
251
- //
252
- // When this list grows: re-run the source-of-truth grep above + audit
253
- // `customElements.define(...)` calls under packages/web-components/core/.
254
- const COMPONENTS_WITHOUT_OWN_CSS = new Set([
255
- // CSS-only components (no .css sibling) — styled by parent slot rules
256
- 'aside-ui', 'footer-ui', 'header-ui', 'section-ui', 'stat-ui',
257
- // Co-located siblings (CSS lives in the parent component's directory)
258
- 'tab-ui', // css + js in components/tabs/, not components/tab/
259
- // Module-tier composites with no own CSS (styled by shell/parent)
260
- 'chat-thread-ui',
261
- // Infrastructure elements (registered outside components/)
262
- 'router-ui',
263
- ]);
264
- const allCustomTags = new Set();
265
- document.querySelectorAll('*').forEach((el) => {
266
- if (el.tagName.endsWith('-UI') && !ON_DEMAND_TAGS.has(el.tagName.toLowerCase())) {
267
- allCustomTags.add(el.tagName.toLowerCase());
268
- }
269
- });
270
- const loadedHrefs = Array.from(document.styleSheets)
271
- .map((s) => { try { return s.href || ''; } catch { return ''; } })
272
- .filter(Boolean);
273
- for (const tag of allCustomTags) {
274
- if (COMPONENTS_WITHOUT_OWN_CSS.has(tag)) continue;
275
- const prefix = tag.replace(/-ui$/, '');
276
- const expected = `/components/${prefix}/${prefix}.css`;
277
- const linked = loadedHrefs.some((h) => h.includes(expected));
278
- if (linked) continue;
279
- // Heuristic fallback: if at least one conventional component-prefixed
280
- // CSS custom property resolves on a rendered instance, the stylesheet
281
- // probably loaded under a different URL pattern (bundled / aliased).
282
- const inst = document.querySelector(tag);
283
- let resolved = false;
284
- if (inst) {
285
- const cs = getComputedStyle(inst);
286
- // Primary probe: standard token naming convention
287
- const probeNames = [
288
- `--${prefix}-bg`, `--${prefix}-fg`, `--${prefix}-pad`,
289
- `--${prefix}-radius`, `--${prefix}-size`, `--${prefix}-gap`,
290
- `--${prefix}-border`,
291
- ];
292
- resolved = probeNames.some((n) => cs.getPropertyValue(n).trim().length > 0);
293
- // Broader fallback: scan all custom properties for any --{prefix}-* token.
294
- // Catches components that use sub-namespaced tokens (e.g. --menu-popover-bg,
295
- // --toggle-option-gap) rather than the flat --{prefix}-bg convention.
296
- if (!resolved) {
297
- const propPrefix = `--${prefix}-`;
298
- for (const prop of cs) {
299
- if (prop.startsWith(propPrefix) && cs.getPropertyValue(prop).trim().length > 0) {
300
- resolved = true;
301
- break;
302
- }
303
- }
304
- }
305
- }
306
- if (!resolved) {
307
- push('critical', 'missing-component-css', {
308
- tag,
309
- label: inst?.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
310
- message: `<${tag}> rendered but no stylesheet matching ${expected} loaded — controls render unstyled (popover bg transparent, listbox = raw text). Add the <link rel="stylesheet"> in the page or shell.`,
311
- expectedHref: expected,
312
- });
313
- }
314
- }
315
-
316
- // 6. Unstyled popover — runtime check for [popover]:popover-open
317
- // whose computed background is transparent + zero padding. This
318
- // is the visual symptom of missing-component-css for a popover-
319
- // bearing primitive (select-ui listbox, tooltip-ui, etc.). Catches
320
- // the case from a different angle in case the URL heuristic above
321
- // didn't match a particular bundling scheme.
322
- // Popovers whose host element is intentionally transparent — visual
323
- // background comes from child elements, not the host itself.
324
- const TRANSPARENT_HOST_POPOVERS = new Set([
325
- 'feed-ui', // toast feed: host is transparent; feed-item-ui children carry bg
326
- ]);
327
- document.querySelectorAll('[popover]').forEach((el) => {
328
- if (!el.matches?.(':popover-open')) return;
329
- if (TRANSPARENT_HOST_POPOVERS.has(el.tagName.toLowerCase())) return;
330
- const cs = getComputedStyle(el);
331
- const transparent = cs.backgroundColor === 'rgba(0, 0, 0, 0)' || cs.backgroundColor === 'transparent';
332
- const noPad = parseFloat(cs.paddingTop) === 0 && parseFloat(cs.paddingLeft) === 0;
333
- if (transparent && noPad) {
334
- push('critical', 'unstyled-popover', {
335
- tag: el.tagName.toLowerCase(),
336
- host: el.parentElement?.tagName?.toLowerCase() || null,
337
- label: el.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
338
- message: 'open popover has transparent bg + zero padding — host component CSS likely missing',
339
- });
340
- }
341
- });
342
-
343
- return findings;
344
- }, { COLORED_SELECTORS, DRIFT_MARKERS });
345
- }
346
-
347
- async function runStampContractProbe(page) {
348
- // Functions don't survive page.evaluate serialization — pass tag+reason
349
- // pairs only and re-implement the predicate in-page below.
350
- const reasons = Object.fromEntries(
351
- Object.entries(STAMP_CONTRACTS).map(([k, v]) => [k, v.reason]),
352
- );
353
- return await page.evaluate((contracts) => {
354
- const findings = [];
355
- for (const [tag, reason] of Object.entries(contracts)) {
356
- document.querySelectorAll(`${tag}`).forEach((el) => {
357
- // Skip elements clearly outside artifact frames (icons in nav, etc.).
358
- if (!el.closest('[data-artifact-item]')) return;
359
- const r = el.getBoundingClientRect();
360
- if (r.width === 0 || r.height === 0) return;
361
- // Re-implement contracts in-page (functions don't survive serialization).
362
- let ok = true;
363
- if (tag === 'input-ui') ok = !!el.querySelector('[slot="text"]');
364
- else if (tag === 'search-ui') ok = !!el.querySelector('input-ui');
365
- if (!ok) {
366
- findings.push({
367
- severity: 'critical',
368
- kind: 'empty-control',
369
- tag,
370
- label: el.closest('[data-artifact-label]')?.dataset.artifactLabel || null,
371
- reason,
372
- });
373
- }
374
- });
375
- }
376
- return findings;
377
- }, reasons);
378
- }
379
-
380
- // ── Sweep ─────────────────────────────────────────────────────────────────
381
-
382
- async function loadComponentRoutes() {
383
- const sitemap = JSON.parse(await readFile(join(REPO_ROOT, 'site/sitemap.json'), 'utf8'));
384
- const routes = [];
385
- // Sitemap shape varies by section; recurse over every key generically
386
- // and pick up nodes that have a `/site/components/*` path + content.
387
- const walk = (node, depth = 0) => {
388
- if (!node || depth > 12) return;
389
- if (Array.isArray(node)) return node.forEach((n) => walk(n, depth));
390
- if (typeof node !== 'object') return;
391
- if (node.path?.startsWith('/site/components/') && node.content) {
392
- routes.push({ path: node.path, content: node.content, name: node.path.split('/').pop() });
393
- }
394
- for (const v of Object.values(node)) walk(v, depth + 1);
395
- };
396
- walk(sitemap);
397
- return FILTER ? routes.filter((r) => r.name.includes(FILTER)) : routes;
398
- }
399
-
400
- async function probePage(browser, base, route) {
401
- const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
402
- const page = await ctx.newPage();
403
- const consoleEntries = [];
404
- page.on('console', (msg) => {
405
- const type = msg.type();
406
- if (type === 'error' || type === 'warning') {
407
- consoleEntries.push({ type, text: msg.text().slice(0, 240) });
408
- }
409
- });
410
- page.on('pageerror', (err) => consoleEntries.push({ type: 'error', text: err.message.slice(0, 240) }));
411
-
412
- // Hit the route path (not the raw `content` HTML) — the docs shell is
413
- // what loads the component bundle. Visiting the raw HTML directly leaves
414
- // every `*-ui` element inert and makes every probe report 0×0.
415
- const url = `${base}${route.path}`;
416
- try {
417
- await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 });
418
- } catch (err) {
419
- await ctx.close();
420
- return {
421
- route: route.path,
422
- error: `navigation failed: ${err.message}`,
423
- findings: [],
424
- consoleEntries: [],
425
- };
426
- }
427
- // Settle: components often stamp on connected() + microtasks.
428
- await page.waitForTimeout(800);
429
-
430
- const probeFindings = await runProbes(page);
431
- const stampFindings = await runStampContractProbe(page);
432
- const findings = [...probeFindings, ...stampFindings];
433
-
434
- await ctx.close();
435
- return { route: route.path, findings, consoleEntries };
436
- }
437
-
438
- // ── Report ────────────────────────────────────────────────────────────────
439
-
440
- function severityOrder(s) {
441
- return { critical: 0, warning: 1, info: 2 }[s] ?? 3;
442
- }
443
-
444
- function renderReport(results, base) {
445
- const all = results.flatMap((r) =>
446
- r.findings.map((f) => ({ ...f, route: r.route })),
447
- );
448
- const errors = results.filter((r) => r.error);
449
- const consoleErrors = results.flatMap((r) =>
450
- r.consoleEntries
451
- .filter((e) => e.type === 'error')
452
- .map((e) => ({ ...e, route: r.route })),
453
- );
454
- const consoleWarnings = results.flatMap((r) =>
455
- r.consoleEntries
456
- .filter((e) => e.type === 'warning')
457
- .map((e) => ({ ...e, route: r.route })),
458
- );
459
-
460
- const bySeverity = (sev) =>
461
- all.filter((f) => f.severity === sev).sort((a, b) => a.route.localeCompare(b.route));
462
- const critical = bySeverity('critical');
463
- const warning = bySeverity('warning');
464
- const info = bySeverity('info');
465
-
466
- const renderFinding = (f) => {
467
- const head = `- **${f.kind}** on \`${f.route}\``;
468
- const labelBit = f.label ? ` (${f.label})` : '';
469
- const detailBits = [];
470
- if (f.tag) detailBits.push(`tag=\`${f.tag}\``);
471
- if (f.selector) detailBits.push(`selector=\`${f.selector}\``);
472
- if (f.rect) detailBits.push(`rect=${f.rect.w}×${f.rect.h}`);
473
- if (f.inlineSwatchVar) detailBits.push(`swatch=\`${f.inlineSwatchVar}\``);
474
- if (f.hint) detailBits.push(f.hint);
475
- if (f.reason) detailBits.push(f.reason);
476
- if (f.message) detailBits.push(f.message);
477
- return `${head}${labelBit} — ${detailBits.join(' · ')}`;
478
- };
479
-
480
- const lines = [];
481
- lines.push(`# Dogfooding report — ${today}`);
482
- lines.push('');
483
- lines.push(`Sweep of every \`/site/components/*\` demo page against ${base}.`);
484
- lines.push('Generated by `node .agents/skills/dogfood-sweep/analyze.mjs`.');
485
- lines.push('');
486
- lines.push('## Summary');
487
- lines.push('');
488
- lines.push(`| Severity | Count |`);
489
- lines.push(`|----------|------:|`);
490
- lines.push(`| critical | ${critical.length} |`);
491
- lines.push(`| warning | ${warning.length} |`);
492
- lines.push(`| info | ${info.length} |`);
493
- lines.push(`| console errors | ${consoleErrors.length} |`);
494
- lines.push(`| console warnings | ${consoleWarnings.length} |`);
495
- lines.push(`| pages scanned | ${results.length} |`);
496
- lines.push(`| navigation errors | ${errors.length} |`);
497
- lines.push('');
498
-
499
- if (critical.length) {
500
- lines.push(`## Critical (${critical.length})`);
501
- lines.push('');
502
- lines.push('Page is visibly broken — element collapsed, swatch transparent, control un-stamped.');
503
- lines.push('');
504
- critical.forEach((f) => lines.push(renderFinding(f)));
505
- lines.push('');
506
- }
507
-
508
- if (warning.length) {
509
- lines.push(`## Warning (${warning.length})`);
510
- lines.push('');
511
- lines.push('Likely-broken composition the layout will silently mis-render.');
512
- lines.push('');
513
- warning.forEach((f) => lines.push(renderFinding(f)));
514
- lines.push('');
515
- }
516
-
517
- if (info.length) {
518
- lines.push(`## Info (${info.length})`);
519
- lines.push('');
520
- lines.push('Synonym-attribute / deprecation drift. Not breaking; sweep when convenient.');
521
- lines.push('');
522
- info.forEach((f) => lines.push(renderFinding(f)));
523
- lines.push('');
524
- }
525
-
526
- if (consoleErrors.length) {
527
- lines.push(`## Console errors (${consoleErrors.length})`);
528
- lines.push('');
529
- consoleErrors.slice(0, 50).forEach((e) =>
530
- lines.push(`- \`${e.route}\` — ${e.text}`),
531
- );
532
- if (consoleErrors.length > 50) {
533
- lines.push(`- … ${consoleErrors.length - 50} more truncated`);
534
- }
535
- lines.push('');
536
- }
537
-
538
- if (errors.length) {
539
- lines.push(`## Navigation errors (${errors.length})`);
540
- lines.push('');
541
- errors.forEach((r) => lines.push(`- \`${r.route}\` — ${r.error}`));
542
- lines.push('');
543
- }
544
-
545
- lines.push('---');
546
- lines.push('');
547
- lines.push('## Probe coverage');
548
- lines.push('');
549
- lines.push('1. **Zero-area** — `*-ui` element with intent (children, text, icon attr) but `getBoundingClientRect()` width or height = 0.');
550
- lines.push('2. **Transparent fill** — `[data-swatch]`, semantic-variant pills/buttons, chart indicators with `background-color: rgba(0,0,0,0)`. Bug class: chart-legend `--chart-N` fallback that doesn\'t resolve standalone.');
551
- lines.push('3. **Empty control** — `input-ui`, `search-ui`, `button-ui`, `select-ui`, `tag-ui` whose `connected()` should have stamped internals but didn\'t.');
552
- lines.push('4. **Synonym-attr / synonym-slot drift** — markers documented in `docs/conventions/attribute-api-migration.md`.');
553
- lines.push('5. **Alert flex-row** — `alert-ui` with multiple bare `<text-ui>` children (need `<col-ui slot="content">` wrap).');
554
- lines.push('6. **Console** — every `console.error` and `console.warn` during page load + 800ms settling.');
555
- lines.push('');
556
-
557
- return lines.join('\n');
558
- }
559
-
560
- // ── Main ──────────────────────────────────────────────────────────────────
561
-
562
- async function main() {
563
- const base = `http://localhost:${PORT}`;
564
- const routes = await loadComponentRoutes();
565
- log(`▶ Dogfooding sweep — ${routes.length} component pages against ${base}`);
566
-
567
- const browser = await chromium.launch({ headless: true });
568
- const results = [];
569
- let i = 0;
570
- for (const route of routes) {
571
- i += 1;
572
- log(` [${i}/${routes.length}] ${route.path}`);
573
- try {
574
- const r = await probePage(browser, base, route);
575
- results.push(r);
576
- } catch (err) {
577
- results.push({ route: route.path, error: err.message, findings: [], consoleEntries: [] });
578
- }
579
- }
580
- await browser.close();
581
-
582
- const report = renderReport(results, base);
583
- await mkdir(dirname(OUT), { recursive: true });
584
- await writeFile(OUT, report, 'utf8');
585
-
586
- const total = results.reduce((acc, r) => acc + r.findings.length, 0);
587
- const critical = results.reduce(
588
- (acc, r) => acc + r.findings.filter((f) => f.severity === 'critical').length,
589
- 0,
590
- );
591
- log(`✔ ${total} findings (${critical} critical) → ${OUT}`);
592
-
593
- // Exit code: 1 if any critical, 0 otherwise. CI-friendly.
594
- process.exit(critical > 0 ? 1 : 0);
595
- }
596
-
597
- main().catch((err) => {
598
- console.error('dogfood analyzer crashed:', err);
599
- process.exit(2);
600
- });
@@ -1,31 +0,0 @@
1
- {
2
- "name": "dogfood-sweep",
3
- "version": "0.1.0",
4
- "description": "Six-mode static + visual sweep across /site/components/*, apps/, playgrounds/, catalog/. Use whenever the user wants to FIND VISUAL BUGS / AUDIT NATIVE PRIMITIVE LEAKS / SCAN ADMIN-SHELL COMPOSITION / SWEEP HTML TYPOS / AUDIT COMPONENT ANATOMY / RUN APP-SHELL QA. Triggers on \"run dogfood sweep\", \"scan component pages\", \"find broken demos\", \"visual-QA all components\", \"audit native primitive leaks\", \"find raw <button> usage\", \"audit admin-shell composition\", \"shell composition audit\", \"sweep html typos\", \"audit card header anatomy\", or scheduled dogfood-* CRON routines. Does NOT trigger for: composing UI screens (use adia-ui-kit), authoring primitives (use adia-ui-authoring), cutting releases (use adia-ui-release).",
5
- "status": "stable",
6
- "authors": ["kim.granlund"],
7
- "tags": [
8
- "dogfood",
9
- "audit",
10
- "visual-qa",
11
- "static-analysis",
12
- "headless-chromium",
13
- "native-primitive-leak",
14
- "admin-shell",
15
- "html-typo",
16
- "anatomy-sweep"
17
- ],
18
- "peer_skills": [
19
- "adia-ui-kit",
20
- "adia-ui-authoring",
21
- "adia-ui-release"
22
- ],
23
- "absorbs": [],
24
- "files": [
25
- "SKILL.md",
26
- "skill.json",
27
- "CHANGELOG.md",
28
- "README.md",
29
- "analyze.mjs"
30
- ]
31
- }