@event4u/agent-config 16.4.0 → 17.0.0

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 (1052) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +2 -2
  4. package/.claude-plugin/skills/install-agent-config/SKILL.md +4 -4
  5. package/CHANGELOG.md +483 -669
  6. package/CONTRIBUTING.md +47 -0
  7. package/README.md +25 -25
  8. package/dist/agent-src/commands/{design.md → agent-design.md} +11 -7
  9. package/dist/agent-src/commands/agents/init.md +66 -3
  10. package/dist/agent-src/commands/agents/user/init.md +3 -0
  11. package/dist/agent-src/commands/{optimize/deep.md → analyze/and-optimize.md} +72 -33
  12. package/dist/agent-src/commands/analyze/inbox.md +168 -37
  13. package/dist/agent-src/commands/analyze/pr.md +144 -0
  14. package/dist/agent-src/commands/analyze/{repo.md → reference.md} +85 -14
  15. package/dist/agent-src/commands/analyze/roadmap-repos.md +19 -10
  16. package/dist/agent-src/commands/analyze.md +28 -12
  17. package/dist/agent-src/commands/audit.md +115 -0
  18. package/dist/agent-src/commands/brand/review.md +13 -2
  19. package/dist/agent-src/commands/brand/tokens.md +3 -3
  20. package/dist/agent-src/commands/brand/voice.md +8 -5
  21. package/dist/agent-src/commands/brand.md +2 -2
  22. package/dist/agent-src/commands/challenge-me/closure.md +25 -0
  23. package/dist/agent-src/commands/design-system/import.md +8 -3
  24. package/dist/agent-src/commands/design-system/sync.md +98 -0
  25. package/dist/agent-src/commands/design-system.md +6 -1
  26. package/dist/agent-src/commands/evals/analyze.json +44 -0
  27. package/dist/agent-src/commands/evals/audit.json +12 -0
  28. package/dist/agent-src/commands/evals/retro.json +12 -0
  29. package/dist/agent-src/commands/fix/ci.md +10 -8
  30. package/dist/agent-src/commands/ghostwriter/write.md +22 -0
  31. package/dist/agent-src/commands/memory/learn-low-impact.md +70 -83
  32. package/dist/agent-src/commands/memory/propose.md +12 -0
  33. package/dist/agent-src/commands/memory.md +1 -1
  34. package/dist/agent-src/commands/optimize.md +4 -3
  35. package/dist/agent-src/commands/post-as/me.md +18 -0
  36. package/dist/agent-src/commands/pr/create.md +17 -342
  37. package/dist/agent-src/commands/pr/merge.md +129 -368
  38. package/dist/agent-src/commands/retro.md +121 -0
  39. package/dist/agent-src/commands/review/routing.md +1 -1
  40. package/dist/agent-src/commands/roadmap/next.md +4 -1
  41. package/dist/agent-src/commands/roadmap/process-full.md +46 -333
  42. package/dist/agent-src/commands/roadmap/triage-parked.md +6 -2
  43. package/dist/agent-src/commands/team-knowledge/consolidate.md +2 -2
  44. package/dist/agent-src/commands/team-knowledge.md +1 -1
  45. package/dist/agent-src/commands/threat-model.md +1 -1
  46. package/dist/agent-src/commands/upstream-contribute.md +91 -101
  47. package/dist/agent-src/commands/worktree/cleanup.md +18 -11
  48. package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +54 -0
  49. package/dist/agent-src/contexts/execution/analysis-loop.md +137 -0
  50. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +3 -3
  51. package/dist/agent-src/contexts/execution/decision-closure-execution.md +1 -1
  52. package/dist/agent-src/contexts/execution/host-capability-manifest.md +6 -0
  53. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +11 -4
  54. package/dist/agent-src/contexts/execution/pr-create-branches-content.md +250 -0
  55. package/dist/agent-src/contexts/execution/pr-create-branches-freshness.md +150 -0
  56. package/dist/agent-src/contexts/execution/pr-merge-queue.md +287 -0
  57. package/dist/agent-src/contexts/execution/pr-merge-sync.md +276 -0
  58. package/dist/agent-src/contexts/execution/pr-merge-trust-boundary.md +69 -0
  59. package/dist/agent-src/contexts/execution/process-full-all.md +233 -0
  60. package/dist/agent-src/contexts/execution/process-full-delivery.md +231 -0
  61. package/dist/agent-src/contexts/execution/roadmap-execution-contract-branches.md +42 -0
  62. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -35
  63. package/dist/agent-src/contexts/execution/roadmap-process-loop-close.md +235 -0
  64. package/dist/agent-src/contexts/execution/roadmap-process-loop-prescan.md +216 -0
  65. package/dist/agent-src/contexts/execution/roadmap-process-loop-run.md +253 -0
  66. package/dist/agent-src/contexts/execution/roadmap-process-loop-set.md +212 -0
  67. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +25 -864
  68. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +14 -2
  69. package/dist/agent-src/contexts/execution/subagent-steering.md +65 -8
  70. package/dist/agent-src/contexts/model-recommendations.md +5 -5
  71. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  72. package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +4 -3
  73. package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +11 -5
  74. package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
  75. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
  76. package/dist/agent-src/guidelines/design-antipatterns.md +6 -1
  77. package/dist/agent-src/guidelines/design-asset-discipline.md +17 -0
  78. package/dist/agent-src/guidelines/design-fidelity-routing.md +1 -0
  79. package/dist/agent-src/guidelines/php/api-design.md +10 -1
  80. package/dist/agent-src/rules/brand-source-of-truth.md +7 -6
  81. package/dist/agent-src/rules/code-provenance.md +1 -1
  82. package/dist/agent-src/rules/context-hygiene.md +0 -1
  83. package/dist/agent-src/rules/design-fidelity.md +12 -13
  84. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  85. package/dist/agent-src/rules/fix-what-you-see.md +1 -1
  86. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +14 -15
  87. package/dist/agent-src/rules/missing-skill-recovery.md +12 -11
  88. package/dist/agent-src/rules/neighbour-precedence.md +1 -1
  89. package/dist/agent-src/rules/recurring-criticism.md +1 -1
  90. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -2
  91. package/dist/agent-src/rules/self-repair-loop.md +2 -2
  92. package/dist/agent-src/rules/token-budget-discipline.md +2 -2
  93. package/dist/agent-src/scripts/dashboard_mode.ts +4 -1
  94. package/dist/agent-src/scripts/roadmap_age.ts +175 -0
  95. package/dist/agent-src/scripts/update_roadmap_progress.ts +10 -2
  96. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +3 -3
  97. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
  98. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  99. package/dist/agent-src/skills/agent-security-review/SKILL.md +2 -2
  100. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +12 -4
  101. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +7 -0
  102. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +11 -1
  103. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +7 -0
  104. package/dist/agent-src/skills/ai-council/references/execution-modes.md +7 -0
  105. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +19 -0
  106. package/dist/agent-src/skills/ai-council/references/procedure.md +7 -0
  107. package/dist/agent-src/skills/api-design/SKILL.md +2 -2
  108. package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
  109. package/dist/agent-src/skills/authz-review/SKILL.md +5 -3
  110. package/dist/agent-src/skills/blade-ui/SKILL.md +2 -2
  111. package/dist/agent-src/skills/brand/SKILL.md +7 -3
  112. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +13 -6
  113. package/dist/agent-src/skills/brand-audit/SKILL.md +2 -1
  114. package/dist/agent-src/skills/brand-identity/SKILL.md +5 -4
  115. package/dist/agent-src/skills/brand-strategy/SKILL.md +5 -4
  116. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +18 -39
  117. package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +2 -2
  118. package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +2 -2
  119. package/dist/agent-src/skills/canvas-design/SKILL.md +16 -4
  120. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  121. package/dist/agent-src/skills/composer-packages/SKILL.md +18 -0
  122. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  123. package/dist/agent-src/skills/content-funnel-design/SKILL.md +8 -1
  124. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  125. package/dist/agent-src/skills/context-document/SKILL.md +2 -2
  126. package/dist/agent-src/skills/corpus-grounding/SKILL.md +6 -6
  127. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +13 -11
  128. package/dist/agent-src/skills/corpus-grounding/scripts/ground.mjs +1706 -0
  129. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +7 -1
  130. package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
  131. package/dist/agent-src/skills/data-flow-mapper/SKILL.md +5 -2
  132. package/dist/agent-src/skills/database/SKILL.md +5 -4
  133. package/dist/agent-src/skills/decision-record/references/weighted-matrix.md +12 -0
  134. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -1
  135. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +61 -11
  136. package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
  137. package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
  138. package/dist/agent-src/skills/design-intelligence/data/landing.csv +1 -1
  139. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +10 -2
  140. package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
  141. package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -3
  142. package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +25 -22
  143. package/dist/agent-src/skills/{wireframe → design-review}/references/story-beat-ledger.schema.json +1 -1
  144. package/dist/agent-src/skills/design-review/references/verification-automation.md +11 -3
  145. package/dist/agent-src/skills/design-system-capture/SKILL.md +15 -10
  146. package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -5
  147. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +2 -2
  148. package/dist/agent-src/skills/design-tokens/SKILL.md +23 -23
  149. package/dist/agent-src/skills/design-tokens/scripts/tokens.mjs +1037 -0
  150. package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +336 -13
  151. package/dist/agent-src/skills/design-tokens/templates/design-tokens-starter.json +52 -53
  152. package/dist/agent-src/skills/docker/SKILL.md +1 -1
  153. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  154. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -276
  155. package/dist/agent-src/skills/existing-ui-audit/procedure.yaml +44 -0
  156. package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +1 -1
  157. package/dist/agent-src/skills/existing-ui-audit/references/steps/00-inspect-stack-and-input.md +4 -0
  158. package/dist/agent-src/skills/existing-ui-audit/references/steps/01-enumerate-components.md +26 -0
  159. package/dist/agent-src/skills/existing-ui-audit/references/steps/01b-detect-component-taxonomy.md +7 -0
  160. package/dist/agent-src/skills/existing-ui-audit/references/steps/02-identify-design-system.md +12 -0
  161. package/dist/agent-src/skills/existing-ui-audit/references/steps/03-detect-design-tokens.md +35 -0
  162. package/dist/agent-src/skills/existing-ui-audit/references/steps/04-detect-shadcn-inventory.md +13 -0
  163. package/dist/agent-src/skills/existing-ui-audit/references/steps/04b-live-storybook-read.md +26 -0
  164. package/dist/agent-src/skills/existing-ui-audit/references/steps/05-list-reusable-patterns.md +14 -0
  165. package/dist/agent-src/skills/existing-ui-audit/references/steps/06-match-candidates.md +52 -0
  166. package/dist/agent-src/skills/existing-ui-audit/references/steps/07-greenfield-branch.md +29 -0
  167. package/dist/agent-src/skills/existing-ui-audit/references/steps/08-a11y-baseline.md +40 -0
  168. package/dist/agent-src/skills/existing-ui-audit/references/steps/09-validate-and-write.md +5 -0
  169. package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
  170. package/dist/agent-src/skills/fe-design/references/design-patterns.md +65 -4
  171. package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +1 -1
  172. package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
  173. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +6 -6
  174. package/dist/agent-src/skills/flux/SKILL.md +1 -1
  175. package/dist/agent-src/skills/form-handler/SKILL.md +15 -2
  176. package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
  177. package/dist/agent-src/skills/git-workflow/SKILL.md +2 -2
  178. package/dist/agent-src/skills/git-workflow/references/branch-update.md +7 -0
  179. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +12 -0
  180. package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +10 -0
  181. package/dist/agent-src/skills/gtm-launch/SKILL.md +8 -1
  182. package/dist/agent-src/skills/html-deck/SKILL.md +7 -2
  183. package/dist/agent-src/skills/humanizer/SKILL.md +16 -3
  184. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +13 -1
  185. package/dist/agent-src/skills/humanizer/references/fixtures.md +8 -0
  186. package/dist/agent-src/skills/iconography/SKILL.md +4 -2
  187. package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
  188. package/dist/agent-src/skills/js-library-packaging/SKILL.md +5 -4
  189. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.mjs +197 -0
  190. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
  191. package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -2
  192. package/dist/agent-src/skills/launch-readiness/SKILL.md +18 -22
  193. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +5 -5
  194. package/dist/agent-src/skills/livewire/SKILL.md +1 -1
  195. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +18 -0
  196. package/dist/agent-src/skills/logo-generation/SKILL.md +21 -11
  197. package/dist/agent-src/skills/market-entry-analysis/SKILL.md +6 -1
  198. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  199. package/dist/agent-src/skills/memory-consolidation/SKILL.md +2 -2
  200. package/dist/agent-src/skills/messaging-architecture/SKILL.md +8 -1
  201. package/dist/agent-src/skills/motion-choreographer/SKILL.md +2 -2
  202. package/dist/agent-src/skills/playwright-testing/SKILL.md +2 -0
  203. package/dist/agent-src/skills/positioning-strategy/SKILL.md +10 -2
  204. package/dist/agent-src/skills/prediction-pool-optimizer/references/ev-fixtures.md +13 -0
  205. package/dist/agent-src/skills/prediction-pool-optimizer/references/odds-and-bonus.md +7 -0
  206. package/dist/agent-src/skills/project-analysis-core/SKILL.md +1 -1
  207. package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +1 -1
  208. package/dist/agent-src/skills/project-analyzer/SKILL.md +14 -75
  209. package/dist/agent-src/skills/project-analyzer/procedure.yaml +39 -0
  210. package/dist/agent-src/skills/project-analyzer/references/steps/01-project-overview.md +9 -0
  211. package/dist/agent-src/skills/project-analyzer/references/steps/02-architecture.md +7 -0
  212. package/dist/agent-src/skills/project-analyzer/references/steps/03-data-layer.md +6 -0
  213. package/dist/agent-src/skills/project-analyzer/references/steps/04-business-domains.md +7 -0
  214. package/dist/agent-src/skills/project-analyzer/references/steps/05-api-surface.md +6 -0
  215. package/dist/agent-src/skills/project-analyzer/references/steps/06-service-map.md +6 -0
  216. package/dist/agent-src/skills/project-analyzer/references/steps/07-module-inventory.md +6 -0
  217. package/dist/agent-src/skills/project-analyzer/references/steps/08-infrastructure-and-testing.md +5 -0
  218. package/dist/agent-src/skills/project-analyzer/references/steps/09-agent-docs-audit.md +6 -0
  219. package/dist/agent-src/skills/project-analyzer/references/steps/10-gap-analysis.md +6 -0
  220. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +10 -0
  221. package/dist/agent-src/skills/quality-tools/references/php-tools.md +13 -0
  222. package/dist/agent-src/skills/quality-tools/references/python-tools.md +11 -0
  223. package/dist/agent-src/skills/react-native-setup/SKILL.md +7 -2
  224. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +5 -1
  225. package/dist/agent-src/skills/react-shadcn-ui/references/registry.md +13 -0
  226. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.mjs +315 -0
  227. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +6 -6
  228. package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
  229. package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
  230. package/dist/agent-src/skills/release-comms/SKILL.md +2 -1
  231. package/dist/agent-src/skills/repomix-packer/SKILL.md +2 -2
  232. package/dist/agent-src/skills/requesting-code-review/SKILL.md +3 -3
  233. package/dist/agent-src/skills/roadmap-management/references/archival.md +3 -3
  234. package/dist/agent-src/skills/roadmap-management/references/authoring.md +9 -2
  235. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +3 -3
  236. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +3 -3
  237. package/dist/agent-src/skills/roadmap-writing/SKILL.md +4 -4
  238. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
  239. package/dist/agent-src/skills/rule-writing/SKILL.md +1 -2
  240. package/dist/agent-src/skills/security/SKILL.md +41 -5
  241. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
  242. package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
  243. package/dist/agent-src/skills/skill-writing/SKILL.md +23 -8
  244. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +19 -1
  245. package/dist/agent-src/skills/source-discovery/SKILL.md +3 -3
  246. package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
  247. package/dist/agent-src/skills/standards-from-config/SKILL.md +2 -2
  248. package/dist/agent-src/skills/storybook-workshop/SKILL.md +5 -0
  249. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.mjs +99 -0
  250. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +13 -13
  251. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +4 -3
  252. package/dist/agent-src/skills/svg-authoring/SKILL.md +324 -0
  253. package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
  254. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +8 -3
  255. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.mjs +482 -0
  256. package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
  257. package/dist/agent-src/skills/threat-modeling/SKILL.md +8 -1
  258. package/dist/agent-src/skills/threat-modeling/data/manifest.json +5 -2
  259. package/dist/agent-src/skills/threat-modeling/data/reasoning.csv +10 -10
  260. package/dist/agent-src/skills/threat-modeling/data/surfaces.csv +11 -10
  261. package/dist/agent-src/skills/threat-modeling/data/threats.csv +34 -20
  262. package/dist/agent-src/skills/type-design/SKILL.md +196 -0
  263. package/dist/agent-src/skills/type-design/references/font-spec.md +90 -0
  264. package/dist/agent-src/skills/type-design/references/gates.md +113 -0
  265. package/dist/agent-src/skills/type-design/references/toolchain.md +66 -0
  266. package/dist/agent-src/skills/typography-system/SKILL.md +21 -11
  267. package/dist/agent-src/skills/typography-system/references/worked-scales.md +85 -0
  268. package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
  269. package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
  270. package/dist/agent-src/skills/upstream-contribute/SKILL.md +120 -125
  271. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -0
  272. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +1 -1
  273. package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +71 -2
  274. package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
  275. package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +16 -14
  276. package/dist/agent-src/templates/AGENTS.md +1 -1
  277. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  278. package/dist/agent-src/templates/agents/proposal.example.md +1 -1
  279. package/dist/agent-src/templates/github-workflows/advisories-daily.yml +85 -0
  280. package/dist/agent-src/templates/roadmaps.md +39 -1
  281. package/dist/agent-src/templates/scripts/check_memory.ts +2 -2
  282. package/dist/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
  283. package/dist/agent-src/templates/scripts/work_engine/cli.ts +17 -0
  284. package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
  285. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
  286. package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
  287. package/dist/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
  288. package/dist/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
  289. package/dist/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
  290. package/dist/agent-src/templates/scripts/work_engine/state.ts +3 -0
  291. package/dist/cli/commands/uiRender.js +265 -13
  292. package/dist/cli/commands/uiRenderAsset.js +1316 -0
  293. package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
  294. package/dist/cli/commands/uiRenderAssetFonts.js +158 -0
  295. package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
  296. package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
  297. package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
  298. package/dist/cli/commands/uiRenderAssetTypes.js +133 -0
  299. package/dist/cli/initRouting.js +1 -1
  300. package/dist/cli/main.js +47 -1
  301. package/dist/cli/mcp/dispatch.js +31 -9
  302. package/dist/cli/python/knowledge_ingest.js +7 -39
  303. package/dist/cli/python/workspace_secrets.js +4 -177
  304. package/dist/cli/registry.js +5 -2
  305. package/dist/cli-delegate/archive_completed_roadmaps.js +3 -2
  306. package/dist/cli-delegate/check_update_banner.js +635 -266
  307. package/dist/cli-delegate/{chunk-AED2VQGM.js → chunk-2CX7NWRB.js} +233 -437
  308. package/dist/cli-delegate/{chunk-F3QDG2GT.js → chunk-2SFOOFJJ.js} +259 -159
  309. package/dist/cli-delegate/chunk-2Y5AMLMY.js +136 -0
  310. package/dist/cli-delegate/{chunk-OKJUIAPS.js → chunk-4E2W63DA.js} +1 -62
  311. package/dist/cli-delegate/{chunk-6SRJTYJS.js → chunk-4SHNERBL.js} +37 -16
  312. package/dist/cli-delegate/chunk-5VO3RTMV.js +208 -0
  313. package/dist/cli-delegate/chunk-6E2LDY4F.js +27 -0
  314. package/dist/cli-delegate/{chunk-XQTPXKFA.js → chunk-6ZD2QZMN.js} +8 -17
  315. package/dist/cli-delegate/{chunk-6V5FMA3P.js → chunk-7CEI2YPS.js} +1 -1
  316. package/dist/cli-delegate/{chunk-DMSZHXZS.js → chunk-7DRWULEQ.js} +80 -7
  317. package/dist/cli-delegate/chunk-7NXCZSDL.js +54 -0
  318. package/dist/cli-delegate/chunk-AX3U3UWJ.js +328 -0
  319. package/dist/cli-delegate/{chunk-WOKWX5PL.js → chunk-BKALSTBZ.js} +18 -3
  320. package/dist/cli-delegate/chunk-BMGUGSY6.js +103 -0
  321. package/dist/cli-delegate/chunk-BYV46VRM.js +3309 -0
  322. package/dist/cli-delegate/{chunk-5GPULQBE.js → chunk-CAL76ADI.js} +4215 -682
  323. package/dist/cli-delegate/chunk-DSY6LLCQ.js +127 -0
  324. package/dist/cli-delegate/chunk-E6XNBVE4.js +581 -0
  325. package/dist/cli-delegate/{chunk-ZUZKZYCN.js → chunk-ESUNQ5XR.js} +46 -10
  326. package/dist/cli-delegate/{chunk-G5VVIZRC.js → chunk-F7HLSW6P.js} +1 -1
  327. package/dist/cli-delegate/chunk-FIEEOH5C.js +133 -0
  328. package/dist/cli-delegate/chunk-FKYZOWVD.js +719 -0
  329. package/dist/cli-delegate/chunk-GOMILC3O.js +918 -0
  330. package/dist/cli-delegate/chunk-I4KJYVPB.js +69 -0
  331. package/dist/cli-delegate/{chunk-JQOM7TTM.js → chunk-IDAOTDPE.js} +1 -100
  332. package/dist/cli-delegate/chunk-IROAQ77A.js +137 -0
  333. package/dist/cli-delegate/chunk-J2SJZICO.js +698 -0
  334. package/dist/cli-delegate/{chunk-6YQC2HLF.js → chunk-JHMMWNJ2.js} +54 -40
  335. package/dist/cli-delegate/{chunk-WQWXGIWB.js → chunk-M6CRG5O6.js} +165 -15
  336. package/dist/cli-delegate/{chunk-PHD7OOLE.js → chunk-MQ2UDEGV.js} +14 -3
  337. package/dist/cli-delegate/chunk-NTM7G2V4.js +220 -0
  338. package/dist/cli-delegate/chunk-PV7S5DPJ.js +175 -0
  339. package/dist/cli-delegate/{chunk-F7DQWYR5.js → chunk-RAXQOETZ.js} +6 -2
  340. package/dist/cli-delegate/{chunk-T7XSJSUQ.js → chunk-SIOMDAKL.js} +980 -784
  341. package/dist/cli-delegate/{chunk-KR6EM23A.js → chunk-TULVDQ4L.js} +3 -48
  342. package/dist/cli-delegate/chunk-UUYEKXKR.js +20 -0
  343. package/dist/cli-delegate/{chunk-7XGD2OEU.js → chunk-UXWHY6CQ.js} +2 -1
  344. package/dist/cli-delegate/{chunk-PWX7CKMD.js → chunk-VC3ECUEK.js} +1 -1
  345. package/dist/cli-delegate/{chunk-KXXWJTDO.js → chunk-WMNYVIYX.js} +1 -1
  346. package/dist/cli-delegate/chunk-XCY5KKUC.js +181 -0
  347. package/dist/cli-delegate/{chunk-H76PHZBI.js → chunk-XLY5G3CM.js} +14 -19
  348. package/dist/cli-delegate/cmd_adr_effective.js +41 -2
  349. package/dist/cli-delegate/cmd_analyze_session.js +7 -7
  350. package/dist/cli-delegate/cmd_brand_status.js +1287 -10
  351. package/dist/cli-delegate/cmd_ci_settle.js +330 -0
  352. package/dist/cli-delegate/cmd_conformance.js +669 -822
  353. package/dist/cli-delegate/cmd_doctor.js +26 -16
  354. package/dist/cli-delegate/cmd_doctor_neighbours.js +10 -7
  355. package/dist/cli-delegate/cmd_explain.js +9 -24
  356. package/dist/cli-delegate/cmd_export.js +14 -11
  357. package/dist/cli-delegate/cmd_fleet.js +5 -3
  358. package/dist/cli-delegate/cmd_git_convention.js +8 -4
  359. package/dist/cli-delegate/cmd_handoff.js +79 -242
  360. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  361. package/dist/cli-delegate/cmd_memory_get.js +4 -2
  362. package/dist/cli-delegate/cmd_migrate.js +2 -2
  363. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  364. package/dist/cli-delegate/cmd_preflight.js +7 -5
  365. package/dist/cli-delegate/cmd_prune.js +16 -13
  366. package/dist/cli-delegate/cmd_route_audit.js +11 -8
  367. package/dist/cli-delegate/cmd_route_explain.js +649 -16
  368. package/dist/cli-delegate/cmd_session_recycle.js +15 -6
  369. package/dist/cli-delegate/cmd_settings_check.js +2 -2
  370. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  371. package/dist/cli-delegate/cmd_settings_migrate.js +14 -11
  372. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  373. package/dist/cli-delegate/cmd_sync.js +16 -13
  374. package/dist/cli-delegate/cmd_uninstall.js +185 -31
  375. package/dist/cli-delegate/cmd_update.js +67 -3
  376. package/dist/cli-delegate/cmd_upgrade.js +38 -7
  377. package/dist/cli-delegate/cmd_validate.js +16 -13
  378. package/dist/cli-delegate/cmd_versions.js +1 -1
  379. package/dist/cli-delegate/dashboard_mode.js +1 -1
  380. package/dist/cli-delegate/gate_execute.js +4 -3
  381. package/dist/cli-delegate/roadmap_age.js +22 -0
  382. package/dist/cli-delegate/roadmap_gates.js +4 -3
  383. package/dist/cli-delegate/update_roadmap_progress.js +3 -2
  384. package/dist/cli-delegate/upgrade_unattended-VVL6JLSX.js +541 -0
  385. package/dist/discovery/deprecation-report.md +1 -1
  386. package/dist/discovery/discovery-manifest.json +409 -201
  387. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  388. package/dist/discovery/discovery-manifest.summary.md +8 -8
  389. package/dist/discovery/dormancy-report.md +1 -1
  390. package/dist/discovery/orphan-report.md +1 -1
  391. package/dist/discovery/packs.json +36 -27
  392. package/dist/discovery/trust-report.md +3 -3
  393. package/dist/discovery/workspaces.json +25 -16
  394. package/dist/hooks/chat_history.chunk.cjs +6852 -0
  395. package/dist/hooks/chat_history.chunk.cjs.sha256 +1 -0
  396. package/dist/hooks/dispatch.js +17706 -18627
  397. package/dist/hooks/dispatch.sha256 +1 -1
  398. package/dist/hooks/egress_engine.chunk.cjs +915 -0
  399. package/dist/hooks/egress_engine.chunk.cjs.sha256 +1 -0
  400. package/dist/hooks/svg_rules.chunk.cjs +1858 -0
  401. package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
  402. package/dist/install/conflict.js +36 -6
  403. package/dist/install/conflictTracker.js +81 -7
  404. package/dist/install/detect.js +3 -3
  405. package/dist/install/hostPermissionsAdapter.js +106 -0
  406. package/dist/install/install.mjs +3117 -1949
  407. package/dist/install/installThinLayer.js +1 -1
  408. package/dist/install/manifestFiles.js +21 -0
  409. package/dist/install/noGoDenyRows.js +300 -0
  410. package/dist/install/noGoRules.js +368 -0
  411. package/dist/install/ownershipLedger.js +133 -0
  412. package/dist/install/plan.js +1 -1
  413. package/dist/install/preflight.js +39 -8
  414. package/dist/install/preserve.js +74 -12
  415. package/dist/install/recordedOwnership.js +88 -5
  416. package/dist/install/rule_scope.js +20 -3
  417. package/dist/install/stagedRuntime.js +455 -0
  418. package/dist/install/toolsArg.js +19 -0
  419. package/dist/install/userPin.js +47 -0
  420. package/dist/install/wizard-plan.js +26 -4
  421. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  422. package/dist/mcp/mcp-cloudflare-catalogue.json +3 -2
  423. package/dist/mcp/registry-manifest.json +6 -5
  424. package/dist/mcp/server.json +3 -3
  425. package/dist/mcp/server.mjs +9814 -5333
  426. package/dist/router.json +1 -1
  427. package/dist/scripts/_lib/agent_settings.js +7 -12
  428. package/dist/scripts/_lib/asset_render_record.js +219 -0
  429. package/dist/scripts/_lib/claude_builtin_names.js +9 -4
  430. package/dist/scripts/_lib/claude_settings_hooks.js +102 -34
  431. package/dist/scripts/_lib/egress_rules.js +766 -0
  432. package/dist/scripts/_lib/environment_detector.js +24 -33
  433. package/dist/scripts/_lib/global_deploy_inventory.js +146 -9
  434. package/dist/scripts/_lib/guidelines_lane.js +10 -1
  435. package/dist/scripts/_lib/identifier_redaction.js +24 -0
  436. package/dist/scripts/_lib/installed_layer.js +17 -0
  437. package/dist/scripts/_lib/installed_layer_normalise.js +72 -0
  438. package/dist/scripts/_lib/lean_projection_mode.js +34 -152
  439. package/dist/scripts/_lib/project_tree_form.js +118 -0
  440. package/dist/scripts/_lib/scan_scope.js +105 -0
  441. package/dist/scripts/_lib/scoped_projection.js +133 -3
  442. package/dist/scripts/_lib/settings_removed_keys.js +29 -0
  443. package/dist/scripts/_lib/settings_renamed_keys.js +17 -5
  444. package/dist/scripts/_lib/subagent_native_fields.js +35 -0
  445. package/dist/scripts/_lib/svg_dom.js +284 -0
  446. package/dist/scripts/_lib/svg_filled_counter.js +285 -0
  447. package/dist/scripts/_lib/svg_geometry.js +477 -0
  448. package/dist/scripts/_lib/svg_motion.js +179 -0
  449. package/dist/scripts/_lib/svg_rules.js +1339 -0
  450. package/dist/scripts/_lib/svg_urls.js +67 -0
  451. package/dist/scripts/_lib/ui_surface.js +19 -0
  452. package/dist/scripts/_lib/verification_command.js +364 -0
  453. package/dist/scripts/_lib/workspace_secrets.js +229 -0
  454. package/dist/scripts/ai_council/seat_policy.js +27 -0
  455. package/dist/scripts/ai_council/transport_resolver.js +9 -10
  456. package/dist/scripts/condense.js +25 -29
  457. package/dist/scripts/lint_svg_asset.js +324 -0
  458. package/dist/server/io/substituteTemplate.js +2 -2
  459. package/dist/server/io/yamlIO.js +2 -2
  460. package/dist/server/routes/install.js +5 -1
  461. package/dist/server/routes/settings.js +2 -2
  462. package/dist/server/routes/wizard.js +1 -1
  463. package/dist/server/schemas/settings.js +22 -16
  464. package/dist/server/serverInfo.js +1 -1
  465. package/dist/shared/brandTokenDocument.js +47 -0
  466. package/dist/shared/brandTokenPaths.js +43 -0
  467. package/dist/shared/settingsCarveOut.js +0 -7
  468. package/dist/shared/skillRanking.js +103 -5
  469. package/dist/shared/userMd/formAdapter.js +16 -0
  470. package/dist/shared/userMd/schema.js +17 -0
  471. package/dist/ui/assets/index-w70Ado09.js +23 -0
  472. package/dist/ui/index.html +1 -1
  473. package/docs/MIGRATION.md +89 -2
  474. package/docs/THIRD-PARTY-NOTICES.md +27 -0
  475. package/docs/contracts/settings-classes.md +27 -9
  476. package/docs/guidelines/agent-infra/api-cost-levers.md +4 -3
  477. package/docs/guidelines/agent-infra/model-recommendation.md +11 -5
  478. package/docs/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
  479. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
  480. package/docs/guidelines/design-antipatterns.md +6 -1
  481. package/docs/guidelines/design-asset-discipline.md +17 -0
  482. package/docs/guidelines/design-fidelity-routing.md +1 -0
  483. package/docs/guidelines/php/api-design.md +10 -1
  484. package/llms.txt +12 -10
  485. package/package.json +15 -5
  486. package/src/agent-src/scripts/dashboard_mode.ts +4 -1
  487. package/src/agent-src/scripts/roadmap_age.ts +175 -0
  488. package/src/agent-src/scripts/update_roadmap_progress.ts +10 -2
  489. package/src/agent-src/templates/AGENTS.md +1 -1
  490. package/src/agent-src/templates/scripts/check_memory.ts +2 -2
  491. package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
  492. package/src/agent-src/templates/scripts/work_engine/cli.ts +17 -0
  493. package/src/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
  494. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
  495. package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
  496. package/src/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
  497. package/src/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
  498. package/src/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
  499. package/src/agent-src/templates/scripts/work_engine/state.ts +3 -0
  500. package/src/config/agent-settings.template.yml +120 -57
  501. package/src/config/agents-paths.yml +13 -7
  502. package/src/config/ci-local-parity.yml +44 -0
  503. package/src/config/continuity-surface.json +51 -2
  504. package/src/config/depth-audit-samples.json +5 -0
  505. package/src/config/discovery/command-verbs.yml +1 -0
  506. package/src/config/dispatch-economy-metrics.json +1 -0
  507. package/src/config/egress-mutations/class-precedence-swapped.json +7 -0
  508. package/src/config/egress-mutations/credential-token-restores.json +7 -0
  509. package/src/config/egress-mutations/iban-checksum-disabled.json +7 -0
  510. package/src/config/egress-mutations/raw-value-in-the-count-record.json +7 -0
  511. package/src/config/evaluator-budgets.json +4 -4
  512. package/src/config/gate-coverage.yml +149 -3
  513. package/src/config/gate-reachability-exemptions.json +3 -5
  514. package/src/config/gate-violation-baselines.json +29 -25
  515. package/src/config/gitignore-block.txt +6 -3
  516. package/src/config/hook-bundle-budget.json +34 -3
  517. package/src/config/hook-carrier-probes.json +30 -0
  518. package/src/config/hook-latency-budget.json +4 -2
  519. package/src/config/host-injection-effect.json +8 -1
  520. package/src/config/host-skill-frontmatter-keys.json +56 -0
  521. package/src/config/layer-form-brakes.json +4 -0
  522. package/src/config/layer-form-comparison-corpus.json +42 -0
  523. package/src/config/loop-surfaces.yaml +28 -47
  524. package/src/config/memory-twin-verdicts.yml +9 -1
  525. package/src/config/metric-registry.yml +40 -3
  526. package/src/config/pack-size-budget.json +15 -0
  527. package/src/config/procedure-core-budget.json +21 -0
  528. package/src/config/profiles/minimal.ini +1 -1
  529. package/src/config/project-tree-form.json +24 -0
  530. package/src/config/reach-channels.yml +3 -3
  531. package/src/config/reach-prescriptions-intake.yml +1 -1
  532. package/src/config/roadmap-step-size-baseline.json +118 -0
  533. package/src/config/routing-coverage-seed.json +100 -2
  534. package/src/config/skill-body-budget.json +686 -0
  535. package/src/config/skill-fork-pilot.json +17 -0
  536. package/src/config/skill-lifecycle-probes-codex.json +57 -0
  537. package/src/config/skill-lifecycle-probes.json +57 -0
  538. package/src/config/skill-output-shape.json +316 -0
  539. package/src/config/step-depth-table.json +58 -0
  540. package/src/config/turnaround-budget.json +90 -0
  541. package/src/install/conflict.ts +38 -6
  542. package/src/install/conflictTracker.ts +126 -8
  543. package/src/install/detect.ts +3 -3
  544. package/src/install/hostPermissionsAdapter.ts +136 -0
  545. package/src/install/installThinLayer.ts +6 -1
  546. package/src/install/manifestFiles.ts +24 -0
  547. package/src/install/noGoDenyRows.ts +368 -0
  548. package/src/install/noGoRules.ts +438 -0
  549. package/src/install/ownershipLedger.ts +180 -0
  550. package/src/install/plan.ts +1 -1
  551. package/src/install/preflight.ts +42 -10
  552. package/src/install/preserve.ts +94 -12
  553. package/src/install/recordedOwnership.ts +121 -3
  554. package/src/install/rule_scope.ts +20 -3
  555. package/src/install/stagedRuntime.ts +528 -0
  556. package/src/install/toolsArg.ts +16 -0
  557. package/src/install/types.ts +23 -2
  558. package/src/install/userPin.ts +54 -0
  559. package/src/install/wizard-plan.ts +25 -4
  560. package/src/scripts/_cli/_doctor_emit.ts +24 -0
  561. package/src/scripts/_cli/cmd_brand_status.ts +223 -12
  562. package/src/scripts/_cli/cmd_ci_settle.ts +32 -0
  563. package/src/scripts/_cli/cmd_doctor.ts +23 -44
  564. package/src/scripts/_cli/cmd_route_explain.ts +176 -2
  565. package/src/scripts/_cli/cmd_uninstall.ts +270 -26
  566. package/src/scripts/_cli/cmd_update.ts +34 -1
  567. package/src/scripts/_cli/cmd_upgrade.ts +38 -2
  568. package/src/scripts/_cli/detection_report.ts +7 -0
  569. package/src/scripts/_cli/doctor_execution.ts +1 -2
  570. package/src/scripts/_cli/doctor_install_mode.ts +39 -0
  571. package/src/scripts/_cli/doctor_network_posture.ts +3 -3
  572. package/src/scripts/_cli/doctor_ownership_ledger.ts +126 -0
  573. package/src/scripts/_cli/doctor_update_verdict.ts +104 -0
  574. package/src/scripts/_cli/explain_last/scrubber.ts +9 -21
  575. package/src/scripts/_cli/upgrade_unattended.ts +548 -0
  576. package/src/scripts/_dispatch.bash +42 -9
  577. package/src/scripts/_lib/activation_ladder.ts +1 -1
  578. package/src/scripts/_lib/advisory_inventory.ts +405 -0
  579. package/src/scripts/_lib/advisory_notice.ts +270 -0
  580. package/src/scripts/_lib/advisory_sources.ts +752 -0
  581. package/src/scripts/_lib/advisory_verdicts.ts +363 -0
  582. package/src/scripts/_lib/agent_artifact_location.ts +177 -0
  583. package/src/scripts/_lib/agent_settings.ts +7 -12
  584. package/src/scripts/_lib/arrival_record.ts +217 -0
  585. package/src/scripts/_lib/asset_render_record.ts +247 -0
  586. package/src/scripts/_lib/billing_grant.ts +4 -2
  587. package/src/scripts/_lib/brand_voice_slot.ts +258 -0
  588. package/src/scripts/_lib/canary_status.ts +24 -0
  589. package/src/scripts/_lib/cc_transcript.ts +276 -0
  590. package/src/scripts/_lib/changelog_eras.ts +83 -0
  591. package/src/scripts/_lib/claim_phrases.ts +71 -0
  592. package/src/scripts/_lib/classify_update.ts +171 -0
  593. package/src/scripts/_lib/claude_builtin_names.ts +9 -4
  594. package/src/scripts/_lib/claude_hook_scope.ts +195 -0
  595. package/src/scripts/_lib/claude_settings_hooks.ts +118 -34
  596. package/src/scripts/_lib/codex_resident_set.ts +460 -0
  597. package/src/scripts/_lib/codex_skill_finder.ts +225 -0
  598. package/src/scripts/_lib/confusables.ts +19 -0
  599. package/src/scripts/_lib/consumer_impact.ts +199 -0
  600. package/src/scripts/_lib/content_class.ts +127 -0
  601. package/src/scripts/_lib/counted_probe.ts +68 -1
  602. package/src/scripts/_lib/credential_deny_rows.ts +151 -0
  603. package/src/scripts/_lib/credential_files.ts +367 -0
  604. package/src/scripts/_lib/delivery_arm_experiment.ts +2 -2
  605. package/src/scripts/_lib/depth_flip.ts +141 -0
  606. package/src/scripts/_lib/design_lock.ts +117 -0
  607. package/src/scripts/_lib/design_sync_ledger.ts +142 -0
  608. package/src/scripts/_lib/design_sync_plan.ts +177 -0
  609. package/src/scripts/_lib/design_sync_reconcile.ts +159 -0
  610. package/src/scripts/_lib/design_sync_verify.ts +99 -0
  611. package/src/scripts/_lib/design_system_claude_design.ts +323 -0
  612. package/src/scripts/_lib/design_system_import.ts +84 -6
  613. package/src/scripts/_lib/dispatch_import_closure.ts +42 -11
  614. package/src/scripts/_lib/egress_credential_env.ts +35 -0
  615. package/src/scripts/_lib/egress_engine.ts +22 -0
  616. package/src/scripts/_lib/egress_known_values.ts +223 -0
  617. package/src/scripts/_lib/egress_normalize.ts +67 -0
  618. package/src/scripts/_lib/egress_prefixes.ts +42 -0
  619. package/src/scripts/_lib/egress_rules.ts +896 -0
  620. package/src/scripts/_lib/egress_rules_linearity.ts +56 -0
  621. package/src/scripts/_lib/egress_sender_scan.ts +290 -0
  622. package/src/scripts/_lib/egress_session_table.ts +510 -0
  623. package/src/scripts/_lib/egress_text.ts +63 -0
  624. package/src/scripts/_lib/egress_token.ts +252 -0
  625. package/src/scripts/_lib/empty_cycles.ts +1 -1
  626. package/src/scripts/_lib/environment_detector.ts +45 -30
  627. package/src/scripts/_lib/exemption_shape.ts +75 -1
  628. package/src/scripts/_lib/floor_posture.ts +185 -0
  629. package/src/scripts/_lib/forge_protection.ts +140 -2
  630. package/src/scripts/_lib/global_deploy_inventory.ts +159 -6
  631. package/src/scripts/_lib/guidelines_lane.ts +12 -1
  632. package/src/scripts/_lib/hand_kinds.ts +65 -0
  633. package/src/scripts/_lib/headless_invocation.ts +3 -3
  634. package/src/scripts/_lib/host_capability.ts +34 -2
  635. package/src/scripts/_lib/host_env_write.ts +39 -18
  636. package/src/scripts/_lib/host_listing_model.ts +14 -7
  637. package/src/scripts/_lib/identifier_redaction.ts +26 -0
  638. package/src/scripts/_lib/impact_bump.ts +70 -0
  639. package/src/scripts/_lib/install_reach_checks.ts +53 -1
  640. package/src/scripts/_lib/installed_layer.ts +31 -0
  641. package/src/scripts/_lib/installed_layer_normalise.ts +75 -0
  642. package/src/scripts/_lib/instructions_loaded_classify.ts +75 -0
  643. package/src/scripts/_lib/instructions_loaded_event.ts +53 -0
  644. package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
  645. package/src/scripts/_lib/layer_form_corpus.ts +165 -0
  646. package/src/scripts/_lib/layer_form_decision.ts +248 -0
  647. package/src/scripts/_lib/layer_form_evidence.ts +112 -0
  648. package/src/scripts/_lib/lean_projection_mode.ts +32 -161
  649. package/src/scripts/_lib/llm_proposer_transport.ts +1 -0
  650. package/src/scripts/_lib/loop_guards.ts +8 -120
  651. package/src/scripts/_lib/major_surface.ts +207 -0
  652. package/src/scripts/_lib/mcp_bridge.ts +30 -69
  653. package/src/scripts/_lib/merge_clearance_record.ts +384 -0
  654. package/src/scripts/_lib/neighbour_census.ts +18 -1
  655. package/src/scripts/_lib/orchestration_record.ts +61 -0
  656. package/src/scripts/_lib/outcome_vocabularies.ts +15 -23
  657. package/src/scripts/_lib/pin_advice.ts +49 -0
  658. package/src/scripts/_lib/platform_anchor.ts +222 -0
  659. package/src/scripts/_lib/procedure_checks.ts +5 -0
  660. package/src/scripts/_lib/project_tree_form.ts +134 -0
  661. package/src/scripts/_lib/projection_key_migration.ts +122 -0
  662. package/src/scripts/_lib/prompt_shape.ts +13 -2
  663. package/src/scripts/_lib/provenance_verify.ts +272 -0
  664. package/src/scripts/_lib/quota_parked.ts +27 -1
  665. package/src/scripts/_lib/ratification_artifact.ts +64 -1
  666. package/src/scripts/_lib/ratification_subject.ts +508 -46
  667. package/src/scripts/_lib/release_findings_ingest.ts +52 -5
  668. package/src/scripts/_lib/release_highlights.ts +72 -2
  669. package/src/scripts/_lib/release_settings_surface.ts +392 -0
  670. package/src/scripts/_lib/review_round.ts +134 -0
  671. package/src/scripts/_lib/roadmap_checkboxes.ts +1 -1
  672. package/src/scripts/_lib/roadmap_slug_lock.ts +254 -0
  673. package/src/scripts/_lib/roadmap_step_size.ts +75 -0
  674. package/src/scripts/_lib/run_checkpoint.ts +60 -3
  675. package/src/scripts/_lib/runtime_wiring_checks.ts +15 -1
  676. package/src/scripts/_lib/scope_guard.sh +64 -5
  677. package/src/scripts/_lib/scoped_projection.ts +136 -3
  678. package/src/scripts/_lib/secret_detector.ts +24 -103
  679. package/src/scripts/_lib/security_fix.ts +429 -0
  680. package/src/scripts/_lib/security_fix_context.ts +133 -0
  681. package/src/scripts/_lib/self_repair.ts +69 -39
  682. package/src/scripts/_lib/self_repair_outgoing.ts +209 -0
  683. package/src/scripts/_lib/self_repair_payload.ts +86 -0
  684. package/src/scripts/_lib/session_eol.ts +3 -0
  685. package/src/scripts/_lib/session_pr_watch.ts +207 -0
  686. package/src/scripts/_lib/session_register.ts +51 -1
  687. package/src/scripts/_lib/session_tag.ts +51 -0
  688. package/src/scripts/_lib/settings_removed_keys.ts +30 -0
  689. package/src/scripts/_lib/settings_renamed_keys.ts +19 -5
  690. package/src/scripts/_lib/skill_catalogue.ts +66 -25
  691. package/src/scripts/_lib/skill_fork_pilot.ts +121 -0
  692. package/src/scripts/_lib/skill_leases.ts +203 -0
  693. package/src/scripts/_lib/skill_listing_overrides.ts +294 -0
  694. package/src/scripts/_lib/skill_materialisation.ts +388 -0
  695. package/src/scripts/_lib/skill_materialisation_gate.ts +210 -0
  696. package/src/scripts/_lib/skill_materialisation_lock.ts +149 -0
  697. package/src/scripts/_lib/skill_materialisation_triggers.ts +96 -0
  698. package/src/scripts/_lib/skill_origin.ts +21 -1
  699. package/src/scripts/_lib/skill_reach.ts +342 -0
  700. package/src/scripts/_lib/source_shape.ts +7 -2
  701. package/src/scripts/_lib/sqlite_guard.ts +1 -1
  702. package/src/scripts/_lib/step_anatomy.ts +330 -0
  703. package/src/scripts/_lib/subagent_capsule.ts +8 -2
  704. package/src/scripts/_lib/subagent_native_fields.ts +30 -0
  705. package/src/scripts/_lib/subagent_spawn.ts +36 -0
  706. package/src/scripts/_lib/subagent_steering.ts +367 -0
  707. package/src/scripts/_lib/svg_dom.ts +318 -0
  708. package/src/scripts/_lib/svg_filled_counter.ts +287 -0
  709. package/src/scripts/_lib/svg_geometry.ts +480 -0
  710. package/src/scripts/_lib/svg_motion.ts +208 -0
  711. package/src/scripts/_lib/svg_rules.ts +1455 -0
  712. package/src/scripts/_lib/svg_urls.ts +72 -0
  713. package/src/scripts/_lib/test_delta.ts +89 -6
  714. package/src/scripts/_lib/tier_downshift_verdict.ts +222 -0
  715. package/src/scripts/_lib/tool_result_census.ts +62 -0
  716. package/src/scripts/_lib/trigger_routers.ts +1 -0
  717. package/src/scripts/_lib/turnaround_throughput.ts +378 -0
  718. package/src/scripts/_lib/ui_surface.ts +22 -0
  719. package/src/scripts/_lib/unattended_gates.ts +100 -0
  720. package/src/scripts/_lib/undeployed_fixes.ts +34 -0
  721. package/src/scripts/_lib/update_check.ts +143 -12
  722. package/src/scripts/_lib/update_invite.ts +116 -0
  723. package/src/scripts/_lib/update_notice.ts +259 -0
  724. package/src/scripts/_lib/verification_command.ts +59 -0
  725. package/src/scripts/_lib/verify_clause.ts +31 -19
  726. package/src/scripts/_lib/version_order.ts +146 -0
  727. package/src/scripts/_lib/worker_reuse.ts +191 -0
  728. package/src/scripts/_lib/workspace_secrets.ts +273 -0
  729. package/src/scripts/_lib/worktree_git.ts +67 -0
  730. package/src/scripts/_lib/worktree_ignored.ts +116 -0
  731. package/src/scripts/adoption_status.ts +330 -3
  732. package/src/scripts/adr_cite_check.ts +93 -0
  733. package/src/scripts/advisories.ts +803 -0
  734. package/src/scripts/ai-image/adapters/flux.sh +1 -0
  735. package/src/scripts/ai-image/adapters/gemini-image.sh +1 -0
  736. package/src/scripts/ai-image/adapters/ideogram.sh +1 -0
  737. package/src/scripts/ai-image/adapters/recraft.sh +1 -0
  738. package/src/scripts/ai-video/adapters/comfyui.sh +1 -0
  739. package/src/scripts/ai-video/adapters/fal.sh +1 -0
  740. package/src/scripts/ai-video/adapters/gemini-veo.sh +1 -0
  741. package/src/scripts/ai-video/adapters/higgsfield.sh +1 -0
  742. package/src/scripts/ai-video/adapters/kling.sh +1 -0
  743. package/src/scripts/ai-video/adapters/musetalk.sh +1 -0
  744. package/src/scripts/ai-video/adapters/openai-images.sh +1 -0
  745. package/src/scripts/ai-video/adapters/replicate.sh +1 -0
  746. package/src/scripts/ai-video/adapters/sora.sh +1 -0
  747. package/src/scripts/ai-video/adapters/syncso.sh +1 -0
  748. package/src/scripts/ai-video/stitch.sh +115 -2
  749. package/src/scripts/ai_council/airgap.ts +1 -0
  750. package/src/scripts/ai_council/api_transport.ts +27 -4
  751. package/src/scripts/ai_council/budget_guard.ts +300 -11
  752. package/src/scripts/ai_council/bundler.ts +20 -29
  753. package/src/scripts/ai_council/chairman.ts +17 -2
  754. package/src/scripts/ai_council/cli_agency_bounds.ts +158 -0
  755. package/src/scripts/ai_council/cli_launch_env.ts +54 -0
  756. package/src/scripts/ai_council/cli_least_agency_canary.ts +18 -2
  757. package/src/scripts/ai_council/clients.ts +55 -73
  758. package/src/scripts/ai_council/config.ts +16 -22
  759. package/src/scripts/ai_council/council_egress.ts +167 -0
  760. package/src/scripts/ai_council/exposure_ledger.ts +117 -0
  761. package/src/scripts/ai_council/free_hand_shadow.ts +276 -0
  762. package/src/scripts/ai_council/free_route.ts +216 -0
  763. package/src/scripts/ai_council/free_route_catalog.ts +173 -0
  764. package/src/scripts/ai_council/free_route_client.ts +95 -0
  765. package/src/scripts/ai_council/free_rung.ts +61 -0
  766. package/src/scripts/ai_council/hand_payload.ts +230 -0
  767. package/src/scripts/ai_council/hand_schemas.ts +123 -0
  768. package/src/scripts/ai_council/jury_aggregate.ts +155 -1
  769. package/src/scripts/ai_council/kind_flip.ts +221 -0
  770. package/src/scripts/ai_council/kind_flip_state.ts +19 -0
  771. package/src/scripts/ai_council/learn_low_impact_preview.ts +50 -22
  772. package/src/scripts/ai_council/modification_review.ts +98 -5
  773. package/src/scripts/ai_council/necessity.ts +7 -0
  774. package/src/scripts/ai_council/orchestrator.ts +16 -16
  775. package/src/scripts/ai_council/pricing.ts +10 -0
  776. package/src/scripts/ai_council/redact_low_impact_entry.ts +5 -2
  777. package/src/scripts/ai_council/response_render.ts +27 -4
  778. package/src/scripts/ai_council/round_reservations.ts +119 -0
  779. package/src/scripts/ai_council/route_chooser.ts +161 -0
  780. package/src/scripts/ai_council/route_liveness.ts +152 -0
  781. package/src/scripts/ai_council/route_member.ts +52 -0
  782. package/src/scripts/ai_council/seat_policy.ts +40 -0
  783. package/src/scripts/ai_council/seat_resume.ts +40 -0
  784. package/src/scripts/ai_council/shadow_dispatch.ts +13 -3
  785. package/src/scripts/ai_council/spend_gate.ts +18 -2
  786. package/src/scripts/ai_council/status_surface.ts +37 -0
  787. package/src/scripts/ai_council/transport_resolver.ts +15 -18
  788. package/src/scripts/analysis_analysts.ts +226 -0
  789. package/src/scripts/analysis_anchors.ts +140 -0
  790. package/src/scripts/analysis_and_optimize.ts +44 -0
  791. package/src/scripts/analysis_emit.ts +150 -0
  792. package/src/scripts/analysis_exchange.ts +186 -0
  793. package/src/scripts/analysis_gate.ts +158 -0
  794. package/src/scripts/analysis_inbox_final.ts +173 -0
  795. package/src/scripts/analysis_ledger.ts +119 -0
  796. package/src/scripts/analysis_pr_optimize.ts +219 -0
  797. package/src/scripts/analysis_pr_review.ts +240 -0
  798. package/src/scripts/analysis_pr_target.ts +121 -0
  799. package/src/scripts/analysis_prompts.ts +130 -0
  800. package/src/scripts/analysis_publish.ts +358 -0
  801. package/src/scripts/analysis_questions.ts +78 -0
  802. package/src/scripts/analysis_run.ts +248 -0
  803. package/src/scripts/analysis_run_record.ts +210 -0
  804. package/src/scripts/analysis_target.ts +343 -0
  805. package/src/scripts/analysis_validate.ts +161 -0
  806. package/src/scripts/anchor_eval_falsify.ts +1 -1
  807. package/src/scripts/arrival_report.ts +115 -0
  808. package/src/scripts/ask_transport.ts +284 -35
  809. package/src/scripts/backfill_model_tier.ts +4 -5
  810. package/src/scripts/before_complete_hook.ts +48 -2
  811. package/src/scripts/bench_hook_latency.ts +3 -3
  812. package/src/scripts/bench_procedure_cursor.ts +440 -0
  813. package/src/scripts/bootstrap.sh +3 -3
  814. package/src/scripts/build_exit_code_register.ts +440 -0
  815. package/src/scripts/build_proof.ts +23 -1
  816. package/src/scripts/cache_realization_report.ts +155 -14
  817. package/src/scripts/canary_liveness.ts +117 -0
  818. package/src/scripts/chat_history.ts +12 -15
  819. package/src/scripts/check_account_surface.ts +318 -0
  820. package/src/scripts/check_agent_artifact_location.ts +17 -160
  821. package/src/scripts/check_bundle_path_leakage.ts +6 -0
  822. package/src/scripts/check_ci_local_parity.ts +21 -13
  823. package/src/scripts/check_claims.ts +77 -2
  824. package/src/scripts/check_completion_review.ts +34 -1
  825. package/src/scripts/check_concern_admissions.ts +41 -5
  826. package/src/scripts/check_consumer_scope_flip.ts +1 -1
  827. package/src/scripts/check_context_paths.ts +2 -0
  828. package/src/scripts/check_council_layout.ts +9 -0
  829. package/src/scripts/check_credential_spelling.ts +267 -0
  830. package/src/scripts/check_egress_mutations.ts +239 -0
  831. package/src/scripts/check_enforcement_coverage.ts +16 -3
  832. package/src/scripts/check_estate_count.ts +16 -1
  833. package/src/scripts/check_finding_dispositions.ts +147 -0
  834. package/src/scripts/check_gate_coverage.ts +123 -21
  835. package/src/scripts/check_gate_reachability.ts +16 -2
  836. package/src/scripts/check_generator_sync.ts +46 -0
  837. package/src/scripts/check_hook_bundle_composition.ts +139 -1
  838. package/src/scripts/check_host_docs_digest.ts +142 -5
  839. package/src/scripts/check_kernel_edit_ratified.ts +301 -76
  840. package/src/scripts/check_kernel_rule_bundle.ts +14 -10
  841. package/src/scripts/check_knowledge_cards.ts +83 -3
  842. package/src/scripts/check_memory.ts +13 -3
  843. package/src/scripts/check_pack_size.ts +1 -1
  844. package/src/scripts/check_permission_deny_syntax.ts +247 -0
  845. package/src/scripts/check_platform_anchor.ts +243 -0
  846. package/src/scripts/check_proposal.ts +183 -1
  847. package/src/scripts/check_reach_channels.ts +5 -3
  848. package/src/scripts/check_references.ts +5 -2
  849. package/src/scripts/check_release_manifest_content.ts +33 -0
  850. package/src/scripts/check_release_pr_shape.ts +5 -0
  851. package/src/scripts/check_rule_invariants.ts +9 -1
  852. package/src/scripts/check_skill_body_budget.ts +343 -0
  853. package/src/scripts/check_skill_requires.ts +137 -1
  854. package/src/scripts/check_step_receipts.ts +246 -0
  855. package/src/scripts/check_structural_breaking.ts +7 -1
  856. package/src/scripts/check_suppression_hygiene.ts +8 -0
  857. package/src/scripts/check_test_weakening.ts +14 -0
  858. package/src/scripts/check_token_quality_golden.ts +5 -1
  859. package/src/scripts/check_update_banner.ts +50 -3
  860. package/src/scripts/check_verify_expectation_delta.ts +2 -1
  861. package/src/scripts/check_voice_lexicon.ts +531 -0
  862. package/src/scripts/ci_os_attribution.ts +327 -0
  863. package/src/scripts/ci_platform_scope.ts +69 -0
  864. package/src/scripts/ci_settle.ts +4 -1
  865. package/src/scripts/ci_status.ts +0 -1
  866. package/src/scripts/ci_time_to_green.ts +748 -0
  867. package/src/scripts/classify_merge_risk.ts +407 -19
  868. package/src/scripts/code_graph/sqlite_store.ts +1 -1
  869. package/src/scripts/compile_trigger_evals.ts +353 -0
  870. package/src/scripts/condense.ts +25 -31
  871. package/src/scripts/consumer_matrix.ts +61 -3
  872. package/src/scripts/council_availability_hook.ts +12 -4
  873. package/src/scripts/council_cli.ts +48 -38
  874. package/src/scripts/cross_repo_retrieve.ts +9 -72
  875. package/src/scripts/design_lock.ts +106 -0
  876. package/src/scripts/design_slop_rules.ts +30 -0
  877. package/src/scripts/design_sync.ts +264 -0
  878. package/src/scripts/design_system_import.ts +30 -13
  879. package/src/scripts/dispatch_economy_report.ts +46 -1
  880. package/src/scripts/dispatch_r2_reviewer.ts +41 -5
  881. package/src/scripts/egress_canary.ts +166 -0
  882. package/src/scripts/egress_sender_census.ts +101 -0
  883. package/src/scripts/external_sources_denylist.json +94 -12
  884. package/src/scripts/generate_catalog.ts +6 -2
  885. package/src/scripts/generate_owned_digest.ts +163 -0
  886. package/src/scripts/generate_reference_toc.ts +143 -0
  887. package/src/scripts/generate_subagent_floor.ts +11 -1
  888. package/src/scripts/handoff_context_hook.ts +34 -0
  889. package/src/scripts/hook_carrier_census.ts +263 -0
  890. package/src/scripts/hook_chunks.d.mts +12 -0
  891. package/src/scripts/hook_chunks.mjs +114 -0
  892. package/src/scripts/hook_manifest.json +1 -1
  893. package/src/scripts/hook_manifest.yaml +65 -42
  894. package/src/scripts/hooks/block_config_weakening.ts +127 -3
  895. package/src/scripts/hooks/block_credential_reads.ts +165 -0
  896. package/src/scripts/hooks/block_no_verify.ts +47 -23
  897. package/src/scripts/hooks/block_speaking_inbox_dir.ts +54 -8
  898. package/src/scripts/hooks/category_a.ts +202 -25
  899. package/src/scripts/hooks/concern_failure_policy.ts +6 -6
  900. package/src/scripts/hooks/concern_registry.ts +31 -6
  901. package/src/scripts/hooks/concern_registry_types.ts +11 -0
  902. package/src/scripts/hooks/delegation_nudge_hook.ts +105 -15
  903. package/src/scripts/hooks/design_pass_hook.ts +199 -13
  904. package/src/scripts/hooks/dispatch_hook.ts +13 -12
  905. package/src/scripts/hooks/egress_engine_loader.ts +125 -0
  906. package/src/scripts/hooks/egress_stage.ts +440 -0
  907. package/src/scripts/hooks/hook_stdin.ts +29 -4
  908. package/src/scripts/hooks/host_docs_pages.ts +194 -0
  909. package/src/scripts/hooks/host_docs_pages.yaml +75 -0
  910. package/src/scripts/hooks/host_lowering.json +1 -1
  911. package/src/scripts/hooks/host_lowering.yaml +22 -21
  912. package/src/scripts/hooks/host_rate_marker_hook.ts +73 -0
  913. package/src/scripts/hooks/instructions_observer_hook.ts +170 -0
  914. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -1
  915. package/src/scripts/hooks/lazy_concern.ts +148 -0
  916. package/src/scripts/hooks/orchestration_record_hook.ts +80 -2
  917. package/src/scripts/hooks/payload_stub.ts +16 -6
  918. package/src/scripts/hooks/permission_gate.ts +7 -7
  919. package/src/scripts/hooks/push_settle_hook.ts +32 -3
  920. package/src/scripts/hooks/replay_hook.ts +43 -0
  921. package/src/scripts/hooks/reread_guard_hook.ts +87 -10
  922. package/src/scripts/hooks/rtk_wrap_hook.ts +4 -3
  923. package/src/scripts/hooks/rule_inject_hook.ts +8 -1
  924. package/src/scripts/hooks/session_eol_hook.ts +48 -1
  925. package/src/scripts/hooks/source_first_gate_hook.ts +6 -8
  926. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +203 -10
  927. package/src/scripts/hooks/state_io.ts +2 -2
  928. package/src/scripts/hooks/svg_obligation.ts +553 -0
  929. package/src/scripts/hooks/svg_rules_loader.ts +133 -0
  930. package/src/scripts/hooks/tool_result_bytes_hook.ts +14 -5
  931. package/src/scripts/hooks/turn_end_gate_hook.ts +5 -3
  932. package/src/scripts/hooks/ui_route_nudge_hook.ts +2 -12
  933. package/src/scripts/hooks_doctor.ts +31 -0
  934. package/src/scripts/hooks_status.ts +58 -3
  935. package/src/scripts/inbox_source_census.ts +74 -13
  936. package/src/scripts/install +25 -3
  937. package/src/scripts/install.ts +60 -91
  938. package/src/scripts/interruption_report.ts +11 -1
  939. package/src/scripts/layer_baseline_report.ts +267 -0
  940. package/src/scripts/learning_sidecar.ts +1 -1
  941. package/src/scripts/lint_agents_layout.ts +3 -0
  942. package/src/scripts/lint_blocker_citations.ts +104 -0
  943. package/src/scripts/lint_breaking_changes_index.ts +40 -7
  944. package/src/scripts/lint_consolidation_lineage.ts +150 -19
  945. package/src/scripts/lint_consumer_internal_refs.ts +90 -42
  946. package/src/scripts/lint_context_spine_usage.ts +21 -0
  947. package/src/scripts/lint_design_antipattern_parity.ts +39 -7
  948. package/src/scripts/lint_design_quality.ts +60 -12
  949. package/src/scripts/lint_evidence_artifacts.ts +31 -0
  950. package/src/scripts/lint_example_fences.ts +11 -2
  951. package/src/scripts/lint_ghostwriter_source.ts +42 -10
  952. package/src/scripts/lint_hook_manifest.ts +94 -0
  953. package/src/scripts/lint_marketplace_install_completeness.ts +4 -0
  954. package/src/scripts/lint_mcp_config_security.ts +9 -11
  955. package/src/scripts/lint_motion_authority_drift.ts +27 -0
  956. package/src/scripts/lint_plan_risk_register.ts +28 -1
  957. package/src/scripts/lint_positioning.ts +4 -4
  958. package/src/scripts/lint_provenance.ts +1 -0
  959. package/src/scripts/lint_roadmap_blockers.ts +65 -4
  960. package/src/scripts/lint_roadmap_complexity.ts +98 -0
  961. package/src/scripts/lint_skill_link_reach.ts +251 -9
  962. package/src/scripts/lint_skill_procedures.ts +252 -0
  963. package/src/scripts/lint_skill_scripts_readonly.ts +12 -1
  964. package/src/scripts/lint_subagent_determinism.ts +14 -1
  965. package/src/scripts/lint_svg_asset.ts +365 -0
  966. package/src/scripts/lint_ticked_unmet_criteria.ts +300 -21
  967. package/src/scripts/mcp_registry_submit.sh +2 -2
  968. package/src/scripts/mcp_server/consumer_tool_catalog.json +4 -4
  969. package/src/scripts/mcp_server/suggest_skill.ts +89 -4
  970. package/src/scripts/mcp_server/tools.ts +2 -33
  971. package/src/scripts/measure_skill_ranker_baseline.ts +203 -5
  972. package/src/scripts/measure_turn_end_gate.ts +61 -1
  973. package/src/scripts/merge_clearance.ts +225 -0
  974. package/src/scripts/migrate_command_suggestions.ts +1 -1
  975. package/src/scripts/network_sources.ts +236 -0
  976. package/src/scripts/no_go_deny_rows.ts +225 -0
  977. package/src/scripts/orchestration_record.ts +15 -2
  978. package/src/scripts/plan_test_shards.ts +103 -0
  979. package/src/scripts/pr_url_reminder_hook.ts +10 -0
  980. package/src/scripts/print_required_checks.ts +5 -5
  981. package/src/scripts/probe_depth_shadow.ts +406 -0
  982. package/src/scripts/probe_turnaround.ts +342 -10
  983. package/src/scripts/ratification_subject.ts +176 -0
  984. package/src/scripts/rdp_gate_classify.ts +1 -0
  985. package/src/scripts/rdp_quality_eval.ts +1 -0
  986. package/src/scripts/release.ts +26 -55
  987. package/src/scripts/release_drill.ts +52 -23
  988. package/src/scripts/release_env.ts +37 -0
  989. package/src/scripts/release_publication.ts +11 -1
  990. package/src/scripts/report_consumer_gate_reach.ts +233 -0
  991. package/src/scripts/report_merge_gate_load.ts +295 -0
  992. package/src/scripts/report_project_contract.ts +123 -0
  993. package/src/scripts/report_reducible_classes.ts +342 -0
  994. package/src/scripts/report_required_checks_drift.ts +5 -3
  995. package/src/scripts/report_skill_host_census.ts +199 -0
  996. package/src/scripts/report_standing_payload_by_host.ts +7 -7
  997. package/src/scripts/retro.ts +758 -0
  998. package/src/scripts/retro_facts.ts +575 -0
  999. package/src/scripts/retro_queue.ts +739 -0
  1000. package/src/scripts/retro_session_facts.ts +218 -0
  1001. package/src/scripts/retro_sweep.ts +493 -0
  1002. package/src/scripts/retro_triage.ts +126 -0
  1003. package/src/scripts/roadmap_context.ts +2 -2
  1004. package/src/scripts/roadmap_drain_queue.ts +601 -0
  1005. package/src/scripts/run_supervise.ts +24 -2
  1006. package/src/scripts/schemas/agent-settings.schema.json +0 -16
  1007. package/src/scripts/schemas/command.schema.json +3 -3
  1008. package/src/scripts/schemas/review-findings.schema.json +8 -0
  1009. package/src/scripts/schemas/skill.schema.json +7 -6
  1010. package/src/scripts/schemas/subagent.schema.json +33 -2
  1011. package/src/scripts/score_skill_selection.ts +5 -2
  1012. package/src/scripts/second_brain_retrieval.ts +1 -0
  1013. package/src/scripts/second_brain_run.ts +1 -0
  1014. package/src/scripts/self_repair_cli.ts +563 -87
  1015. package/src/scripts/self_review_gate.ts +59 -4
  1016. package/src/scripts/session_register_hook.ts +91 -4
  1017. package/src/scripts/sessions_cli.ts +100 -5
  1018. package/src/scripts/skill_collision_clusters.ts +1 -1
  1019. package/src/scripts/skill_tools/score_skill_relevance.ts +31 -2
  1020. package/src/scripts/skill_trigger_eval.ts +4 -2
  1021. package/src/scripts/source_adapters.ts +183 -0
  1022. package/src/scripts/step_receipt.ts +100 -0
  1023. package/src/scripts/sync_pr_branch.ts +4 -0
  1024. package/src/scripts/test_council_qualification.ts +1 -1
  1025. package/src/scripts/trigger_eval_grandfather.json +3 -49
  1026. package/src/scripts/trigger_eval_rotation.ts +31 -3
  1027. package/src/scripts/ui_conformance_probe.ts +405 -1
  1028. package/src/scripts/update_counts.ts +230 -11
  1029. package/src/scripts/update_invite_hook.ts +245 -0
  1030. package/src/scripts/update_notice_hook.ts +298 -0
  1031. package/src/scripts/validate_frontmatter.ts +85 -0
  1032. package/src/scripts/worker_reuse_shadow_report.ts +121 -0
  1033. package/src/scripts/worktree_cleanup_check.ts +915 -121
  1034. package/src/server/io/yamlIO.ts +2 -2
  1035. package/src/server/schemas/settings.ts +37 -23
  1036. package/src/shared/brandTokenDocument.ts +46 -0
  1037. package/src/shared/brandTokenPaths.ts +43 -0
  1038. package/src/shared/settingsCarveOut.ts +0 -8
  1039. package/src/shared/skillRanking.ts +106 -5
  1040. package/src/shared/userMd/formAdapter.ts +15 -1
  1041. package/src/shared/userMd/schema.ts +22 -0
  1042. package/src/templates/agent-user.md +4 -0
  1043. package/src/templates/agent-user.yml +4 -0
  1044. package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
  1045. package/dist/cli-delegate/chunk-AL3RZ22D.js +0 -74
  1046. package/dist/cli-delegate/chunk-KB5FZ655.js +0 -208
  1047. package/dist/cli-delegate/chunk-MDPPKQCQ.js +0 -875
  1048. package/dist/cli-delegate/chunk-MSUL5NYP.js +0 -1123
  1049. package/dist/cli-delegate/chunk-OAFSJBHH.js +0 -272
  1050. package/dist/ui/assets/index-C3djEJah.js +0 -23
  1051. package/src/scripts/_lib/continuation_ladder.ts +0 -335
  1052. package/src/scripts/hooks/run_continuation_hook.ts +0 -1524
@@ -0,0 +1,1316 @@
1
+ /**
2
+ * `agent-config ui:render <file> --profile asset` — the engine witness for one
3
+ * hand-authored SVG. Step 2.1 and step 2.6 of `road-to-svg-with-a-witness`.
4
+ *
5
+ * The PAGE profile is untouched. Its `VIEWPORTS` contract, its capture loop and
6
+ * its manifest keys are the same bytes they were before this file existed —
7
+ * step 2.2 pins that, and the pin is the reason the asset code lives here
8
+ * rather than inside `uiRender.ts`'s loop.
9
+ *
10
+ * CLASS A, inherited from `uiRender.ts` and not weakened: the browser this
11
+ * module is handed is closed by its caller in a `finally`, nothing is cached
12
+ * between invocations, and no listener or watch mode exists.
13
+ *
14
+ * WHAT THIS READS, and why each reading is here rather than in the static
15
+ * linter (`src/scripts/lint_svg_asset.ts`):
16
+ *
17
+ * - fill ratio, per asset class — a global threshold read a 24-grid
18
+ * hamburger's designed padding as a loose viewBox (R12). The threshold
19
+ * comes from the fixture manifest's `fill_ratio_thresholds` when one is
20
+ * supplied, from the per-class defaults below otherwise. Never global.
21
+ * - the resolved font family — a `<text>` with no `font-family` resolves to
22
+ * `Times` in Chromium (R1). Only a renderer knows that.
23
+ * - draw-on dead time — `getTotalLength()` against the dash. Deliberately
24
+ * NOT a static rule: the prototype's regex fired on an intentional spinner
25
+ * (R9, R12), so the dash is measured against the geometry it actually runs
26
+ * on or it is not measured at all.
27
+ * - frames at a declared time — `pauseAnimations()` + `setCurrentTime()`.
28
+ * `screenshot({ animations: 'disabled' })` does NOT freeze SMIL: three
29
+ * captures 300 ms apart read `cx` 21.3, 46.3, 70.9, while the pause-and-seek
30
+ * pair held 100 and 100 (R6).
31
+ * - a near-white region enclosed by paint where the source shows a hole (S5).
32
+ * - `img` / CSS-background delivery: the emulated preference does not reach an
33
+ * image document (R5), so the reading is `not_witnessable` and the HOST is
34
+ * checked for a `<picture>` route instead.
35
+ *
36
+ * NO NETWORK, NO SCRIPT, NO FILE OUTSIDE THE PROJECT — `uiRenderAssetIsolation.ts`.
37
+ */
38
+ import * as crypto from 'node:crypto';
39
+ import * as fs from 'node:fs';
40
+ import * as path from 'node:path';
41
+ import { elementExtent, parseElements, readViewBox, vectorVerdict } from '../../scripts/lint_svg_asset.js';
42
+ import { hasCssAnimation, hasSmilMarkup } from '../../scripts/_lib/svg_motion.js';
43
+ import { tokenDocumentError } from '../../shared/brandTokenDocument.js';
44
+ import { compareGeometry, sampleSource } from './uiRenderAssetCompare.js';
45
+ import { applyFaceStates, faceFindings } from './uiRenderAssetFonts.js';
46
+ import { readGrounds } from './uiRenderAssetGrounds.js';
47
+ import { gradeIconGrid } from './uiRenderAssetGrid.js';
48
+ import { confinePage, fileRootsFor, injectStyle } from './uiRenderAssetIsolation.js';
49
+ export * from './uiRenderAssetGrid.js';
50
+ import { ASSET_CLASSES, BRAND_TOKEN_PATHS, DEFAULT_FILL_RATIO_THRESHOLDS, DEFAULT_GEOMETRY_TOLERANCES, DRAW_ON_DEAD_TIME_THRESHOLD, FALLBACK_BACKGROUNDS, BLEED_SHARE_THRESHOLD, FOREIGN_CONTENT_SHARE_THRESHOLD, HOLE_ATTRIBUTE, HOST_BASENAME, ICON_SIZES, LOW_CONTRAST_SHARE_THRESHOLD, MARK_SMALL_SIZES, NEAR_WHITE_CHANNEL, } from './uiRenderAssetTypes.js';
51
+ export * from './uiRenderAssetTypes.js';
52
+ export * from './uiRenderAssetCompare.js';
53
+ // ---------------------------------------------------------------------------
54
+ // Pure readings — no browser
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * The cost reading — step 3.2 of `road-to-svg-from-a-live-session`.
58
+ *
59
+ * Counted from the bytes, so it needs no renderer and is the same number on
60
+ * every machine. `coordinates` counts the numbers inside `d` and `points`,
61
+ * which is the axis that makes a traced file hostile to edit: one accepted
62
+ * mark went 5.3 KB to 49.5 KB in a conversion and nothing measured it.
63
+ */
64
+ export function costReading(content, elements) {
65
+ let coordinates = 0;
66
+ for (const el of elements) {
67
+ if (el.closing)
68
+ continue;
69
+ for (const key of ['d', 'points']) {
70
+ const v = el.attrs[key];
71
+ if (!v)
72
+ continue;
73
+ coordinates += (v.match(/-?\d*\.?\d+(?:[eE][-+]?\d+)?/g) ?? []).length;
74
+ }
75
+ }
76
+ const open = elements.filter((el) => !el.closing);
77
+ return {
78
+ bytes: Buffer.byteLength(content, 'utf8'),
79
+ elements: open.length,
80
+ paths: open.filter((el) => el.name === 'path').length,
81
+ gradients: open.filter((el) => el.name === 'lineargradient' || el.name === 'radialgradient').length,
82
+ coordinates,
83
+ };
84
+ }
85
+ export function sha256(buf) {
86
+ return crypto.createHash('sha256').update(buf).digest('hex');
87
+ }
88
+ /**
89
+ * The class when `--class` was not given. Recorded as `asset_class_inferred`
90
+ * so a reader never mistakes a guess for a declaration.
91
+ */
92
+ export function inferAssetClass(content) {
93
+ if (hasSmilMarkup(content) || hasCssAnimation(content))
94
+ return 'animated';
95
+ const elements = parseElements(content);
96
+ const root = elements.find((el) => el.name === 'svg' && !el.closing);
97
+ const vb = readViewBox(root);
98
+ const texts = elements.filter((el) => el.name === 'text' && !el.closing).length;
99
+ const markers = elements.filter((el) => el.name === 'marker' && !el.closing).length;
100
+ if (vb && vb.w === vb.h && Math.max(vb.w, vb.h) <= 64)
101
+ return 'icon';
102
+ if (markers > 0 || texts >= 2)
103
+ return 'diagram';
104
+ if (texts >= 1)
105
+ return 'illustration';
106
+ return 'mark';
107
+ }
108
+ /** The declared intrinsic size: `width`/`height` first, the viewBox otherwise. */
109
+ export function intrinsicSize(root, vb) {
110
+ const num = (raw) => {
111
+ if (!raw)
112
+ return null;
113
+ const m = /^\s*(-?[\d.]+)\s*(px)?\s*$/i.exec(raw);
114
+ const v = m ? Number(m[1]) : Number.NaN;
115
+ return Number.isFinite(v) && v > 0 ? v : null;
116
+ };
117
+ const w = num(root?.attrs['width']) ?? vb?.w ?? 48;
118
+ const h = num(root?.attrs['height']) ?? vb?.h ?? 48;
119
+ return { width: w, height: h };
120
+ }
121
+ /**
122
+ * Icons at 16/24/48; a MARK additionally at 16 and 32; every other class at 1x
123
+ * and 2x its intrinsic size.
124
+ *
125
+ * Step 4.3 of `road-to-svg-from-a-live-session`. A review sent an accepted
126
+ * mark back because its face turned to mush at 32 px, and the only way anybody
127
+ * could know that was to look — there was no capture at a small size to look
128
+ * AT. Legibility stays a look; the capture is the evidence that the look
129
+ * happened, which is the same split the rest of this profile keeps.
130
+ *
131
+ * The small sizes come FIRST so a reader scanning the manifest meets them
132
+ * before the 1x the file was designed at.
133
+ */
134
+ /**
135
+ * The LARGEST capture, which is not the last one.
136
+ *
137
+ * Finding 6 of the third completion review. `assetSizes` PREPENDS
138
+ * `MARK_SMALL_SIZES` for a mark — so a reader taking `sizes[sizes.length - 1]`
139
+ * gets the 2x scaled size, which is smaller than 32 whenever the intrinsic
140
+ * width is under 16. Reproduced: intrinsic width 10 gives a last entry of 20
141
+ * against a maximum of 32, so the geometry pass read the asset at a size it
142
+ * was not biggest at and the grounds reading used a capture that was not the
143
+ * largest taken.
144
+ *
145
+ * A named function rather than an inline `reduce`, because the defect was
146
+ * exactly that the selection looked obvious enough not to be read — and an
147
+ * inline expression is not something a test can hold.
148
+ */
149
+ export function biggestSize(sizes) {
150
+ let best = null;
151
+ for (const s of sizes)
152
+ if (best === null || s.width > best.width)
153
+ best = s;
154
+ return best ?? { label: '1x', width: 64, height: 64 };
155
+ }
156
+ export function assetSizes(cls, intrinsic) {
157
+ if (cls === 'icon') {
158
+ return ICON_SIZES.map((px) => ({ label: `${px}`, width: px, height: px }));
159
+ }
160
+ const ratio = intrinsic.height / intrinsic.width;
161
+ const scaled = [1, 2].map((k) => ({
162
+ label: `${k}x`,
163
+ width: Math.round(intrinsic.width * k),
164
+ height: Math.round(intrinsic.width * k * ratio),
165
+ }));
166
+ if (cls !== 'mark')
167
+ return scaled;
168
+ const small = MARK_SMALL_SIZES.map((px) => ({
169
+ label: `${px}`,
170
+ width: px,
171
+ height: Math.max(1, Math.round(px * ratio)),
172
+ }));
173
+ return [...small, ...scaled];
174
+ }
175
+ /**
176
+ * Thresholds from a fixture manifest when one is supplied, the per-class
177
+ * defaults otherwise. The SOURCE travels with the number: a threshold a reader
178
+ * cannot trace is a threshold they cannot argue with.
179
+ */
180
+ export function readThresholds(file) {
181
+ const out = {
182
+ fillRatio: DEFAULT_FILL_RATIO_THRESHOLDS,
183
+ fillRatioSource: 'default',
184
+ geometry: DEFAULT_GEOMETRY_TOLERANCES,
185
+ geometrySource: 'default',
186
+ };
187
+ if (!file || !fs.existsSync(file))
188
+ return out;
189
+ let parsed;
190
+ try {
191
+ parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
192
+ }
193
+ catch {
194
+ return out;
195
+ }
196
+ const obj = parsed;
197
+ const fr = obj.fill_ratio_thresholds;
198
+ if (fr && ASSET_CLASSES.every((c) => typeof fr[c] === 'number')) {
199
+ out.fillRatio = { ...DEFAULT_FILL_RATIO_THRESHOLDS, ...fr };
200
+ out.fillRatioSource = 'manifest';
201
+ }
202
+ const gt = obj.geometry_tolerances;
203
+ // EVERY SUPPLIED FIELD IS A NUMBER, not just the one the guard used to
204
+ // name. Finding 5 of the review of this branch: the merge closed the
205
+ // missing-key hole and left the wrong-TYPE one, so
206
+ // `max_boundary_distance_units: "lots"` was accepted as manifest-sourced
207
+ // and returned verbatim — and `0 <= "lots"` is false, which is the same
208
+ // fail-closed comparison the missing key produced. A threshold that is not
209
+ // a number is not a threshold.
210
+ const wellTyped = (t) => t !== undefined &&
211
+ typeof t.silhouette_iou_min === 'number' &&
212
+ Object.values(t).every((v) => typeof v === 'number' && Number.isFinite(v));
213
+ if (gt && ASSET_CLASSES.every((c) => wellTyped(gt[c]))) {
214
+ // MERGED PER CLASS, not spread over the class. Finding 3 of the sixth
215
+ // completion review: the validation checks one field per class and the
216
+ // spread then replaced the whole class object, so a manifest naming
217
+ // every class but supplying only `silhouette_iou_min` was accepted as
218
+ // `geometrySource: manifest` with `max_boundary_distance_units`
219
+ // UNDEFINED.
220
+ //
221
+ // THE DIRECTION, corrected — the first version of this comment had it
222
+ // backwards and the review of this branch caught it. `undefined` does
223
+ // not make the boundary check vanish: `maxDistance <= undefined` is
224
+ // FALSE, so every comparison failed it, and a pixel-perfect render
225
+ // (iou 1.0, boundary distance 0.0) scored `fail`. It was fail-CLOSED,
226
+ // not silently absent. That is the better of the two directions and
227
+ // still wrong: a manifest the reader was told to trust refused every
228
+ // file it was applied to.
229
+ const merged = {};
230
+ for (const c of ASSET_CLASSES) {
231
+ merged[c] = { ...DEFAULT_GEOMETRY_TOLERANCES[c], ...gt[c] };
232
+ }
233
+ out.geometry = merged;
234
+ out.geometrySource = 'manifest';
235
+ }
236
+ return out;
237
+ }
238
+ /**
239
+ * The light and dark background from the project's tokens, or the stated
240
+ * fallback. Never a silent fallback — the caller records which it was.
241
+ */
242
+ export function readBackgroundTokens(projectRoot) {
243
+ for (const rel of BRAND_TOKEN_PATHS) {
244
+ const abs = path.join(projectRoot, rel);
245
+ if (!fs.existsSync(abs))
246
+ continue;
247
+ let doc;
248
+ try {
249
+ const text = fs.readFileSync(abs, 'utf8');
250
+ // The validity `brand:status` reports, not merely parseable JSON:
251
+ // `findToken` takes a bare `value`, so a non-DTCG file would win.
252
+ if (tokenDocumentError(text) !== null)
253
+ continue;
254
+ doc = JSON.parse(text);
255
+ }
256
+ catch {
257
+ continue;
258
+ }
259
+ const light = findToken(doc, ['background', 'bg', 'surface'], ['light', 'default', 'base']);
260
+ const dark = findToken(doc, ['background', 'bg', 'surface'], ['dark', 'inverse', 'inverted']);
261
+ if (light || dark) {
262
+ return {
263
+ light: light ?? FALLBACK_BACKGROUNDS.light,
264
+ dark: dark ?? FALLBACK_BACKGROUNDS.dark,
265
+ source: 'tokens',
266
+ tokens_file: rel,
267
+ };
268
+ }
269
+ }
270
+ return { ...FALLBACK_BACKGROUNDS, source: 'fallback', tokens_file: null };
271
+ }
272
+ /** A depth-first walk for a DTCG `$value` whose path carries both hints. */
273
+ function findToken(doc, nameHints, modeHints) {
274
+ const stack = [{ node: doc, keys: [] }];
275
+ let best = null;
276
+ while (stack.length > 0) {
277
+ const top = stack.pop();
278
+ if (!top || typeof top.node !== 'object' || top.node === null)
279
+ continue;
280
+ const rec = top.node;
281
+ const value = rec['$value'] ?? rec['value'];
282
+ if (typeof value === 'string' && /^#[0-9a-f]{3,8}$/i.test(value)) {
283
+ const joined = top.keys.join('.').toLowerCase();
284
+ if (nameHints.some((h) => joined.includes(h)) && modeHints.some((h) => joined.includes(h))) {
285
+ best = value;
286
+ }
287
+ }
288
+ for (const [k, v] of Object.entries(rec)) {
289
+ if (k.startsWith('$'))
290
+ continue;
291
+ stack.push({ node: v, keys: [...top.keys, k] });
292
+ }
293
+ }
294
+ return best;
295
+ }
296
+ /**
297
+ * The fraction of a draw-on animation's duration during which the drawn length
298
+ * does not change — the R8 defect, stated as a number.
299
+ *
300
+ * With a dash of `D` real units on a path of real length `L`, a dash offset of
301
+ * `o` paints `clamp(D - o, 0, L)`. When `D > L` the paint reaches `L` while `o`
302
+ * is still above zero, and every further step of the animation draws nothing.
303
+ */
304
+ export function drawOnDeadFraction(dashUnits, from, to, totalLength) {
305
+ const span = Math.abs(from - to);
306
+ if (span <= 0 || totalLength <= 0 || dashUnits <= 0)
307
+ return 0;
308
+ const drawn = (o) => Math.min(Math.max(dashUnits - o, 0), totalLength);
309
+ const lo = Math.min(from, to);
310
+ const hi = Math.max(from, to);
311
+ const STEPS = 400;
312
+ let live = 0;
313
+ let prev = drawn(hi);
314
+ for (let i = 1; i <= STEPS; i++) {
315
+ const o = hi - ((hi - lo) * i) / STEPS;
316
+ const now = drawn(o);
317
+ if (Math.abs(now - prev) > 1e-6)
318
+ live += 1;
319
+ prev = now;
320
+ }
321
+ return 1 - live / STEPS;
322
+ }
323
+ /**
324
+ * One screenshot, with exactly one retry on a protocol error.
325
+ *
326
+ * Measured on a GitHub-hosted ubuntu runner with `chromium_headless_shell`:
327
+ * `page.screenshot` failed with `Protocol error (Page.captureScreenshot):
328
+ * Unable to capture screenshot` on one asset while the same asset captured
329
+ * cleanly in another test of the same run — a compositor surface that was not
330
+ * ready, not a property of the file. ONE retry, deliberately: a genuine failure
331
+ * fails twice and still surfaces, while a loop would turn a real break into a
332
+ * slow one. A `path` write also creates its parent directories, so a missing
333
+ * `outDir` is not what this is for.
334
+ */
335
+ async function captureWithOneRetry(page, shot) {
336
+ try {
337
+ await page.screenshot({ path: shot });
338
+ }
339
+ catch (first) {
340
+ if (!/Unable to capture screenshot|Protocol error/i.test(String(first)))
341
+ throw first;
342
+ await page.waitForTimeout(250);
343
+ await page.screenshot({ path: shot });
344
+ }
345
+ }
346
+ /** Does this element declare itself less than fully opaque? */
347
+ export function isDeclaredTranslucent(el) {
348
+ const style = el.attrs['style'] ?? '';
349
+ const read = (key) => {
350
+ const fromStyle = new RegExp(`(?:^|;)\\s*${key}\\s*:\\s*([^;]+)`).exec(style)?.[1];
351
+ const raw = (fromStyle ?? el.attrs[key] ?? '').trim();
352
+ if (raw === '')
353
+ return null;
354
+ // A PERCENTAGE IS LEGAL CSS AND `Number()` CANNOT READ IT.
355
+ //
356
+ // Finding 8 of the third completion review: `Number('50%')` is NaN, so
357
+ // `fill-opacity="50%"` read as "not declared translucent" and every
358
+ // pixel of that half-transparent shape was counted as background
359
+ // bleeding through the author's paint — the exact false warning the
360
+ // comment above this function says the declaration prevents.
361
+ const pct = /^([+-]?(?:\d*\.\d+|\d+\.?))\s*%$/.exec(raw);
362
+ const v = pct ? Number(pct[1]) / 100 : Number(raw);
363
+ return Number.isFinite(v) ? v : null;
364
+ };
365
+ // `stroke-opacity` belongs here for the same reason the other two do: a
366
+ // stroke the author made translucent is a declaration, not a seam. It was
367
+ // missing from the list, which finding 8 also names.
368
+ for (const key of ['opacity', 'fill-opacity', 'stroke-opacity']) {
369
+ const v = read(key);
370
+ if (v !== null && v < 0.99)
371
+ return true;
372
+ }
373
+ return false;
374
+ }
375
+ /** Boxes, in user units, of every element matching `pick`. */
376
+ function extentsOf(elements, pick) {
377
+ const out = [];
378
+ for (const el of elements) {
379
+ if (el.closing || !pick(el))
380
+ continue;
381
+ const b = elementExtent(el);
382
+ if (b)
383
+ out.push({ x: b.minX, y: b.minY, w: b.maxX - b.minX, h: b.maxY - b.minY });
384
+ }
385
+ return out;
386
+ }
387
+ /** A reading pass over one asset. The caller owns the browser's lifetime. */
388
+ export async function runAssetRender(browser, opts) {
389
+ const bytes = fs.readFileSync(opts.file);
390
+ const content = bytes.toString('utf8');
391
+ const isHost = /\.html?$/i.test(opts.file);
392
+ const dir = path.dirname(opts.file);
393
+ const elements = isHost ? [] : parseElements(content);
394
+ const root = elements.find((el) => el.name === 'svg' && !el.closing);
395
+ const vb = isHost ? null : readViewBox(root);
396
+ const intrinsic = intrinsicSize(root, vb);
397
+ const declaredClass = opts.assetClass;
398
+ const assetClass = declaredClass ?? inferAssetClass(content);
399
+ const delivery = opts.delivery ?? 'inline';
400
+ const thresholds = readThresholds(opts.thresholdsFile);
401
+ const backgrounds = readBackgroundTokens(opts.projectRoot);
402
+ const blocked = [];
403
+ const reading = {
404
+ profile: 'asset',
405
+ file: path.relative(opts.projectRoot, opts.file).split(path.sep).join('/'),
406
+ digest: sha256(bytes),
407
+ asset_class: assetClass,
408
+ asset_class_inferred: declaredClass === undefined,
409
+ delivery,
410
+ view_box: vb,
411
+ intrinsic,
412
+ backgrounds,
413
+ sizes: [],
414
+ readings_at: null,
415
+ true_vector: isHost ? false : vectorVerdict(elements).trueVector,
416
+ painted_box: null,
417
+ fill_ratio: null,
418
+ fill_ratio_threshold: thresholds.fillRatio[assetClass],
419
+ fill_ratio_threshold_source: thresholds.fillRatioSource,
420
+ outside_view_box: [],
421
+ texts: [],
422
+ accessible_names: [],
423
+ duplicate_accessible_names: [],
424
+ frames: [],
425
+ animation_duration_s: 0,
426
+ distinct_frames: 0,
427
+ draw_on: [],
428
+ icon_grid: null,
429
+ near_white_regions: [],
430
+ cost: costReading(content, elements),
431
+ grounds: [],
432
+ network: { aborted: 0, blocked_urls: blocked },
433
+ findings: [],
434
+ reduced_motion: { witnessable: false, frames_equal: null, reason: 'not read' },
435
+ };
436
+ const hostHtml = isHost ? null : inlineHost(content);
437
+ const targetUrl = isHost ? `file://${opts.file}` : `file://${path.join(dir, HOST_BASENAME)}`;
438
+ const fileRoots = fileRootsFor(opts.projectRoot, opts.file);
439
+ const context = await browser.newContext({ javaScriptEnabled: false });
440
+ // A transpiler shim, and it belongs here rather than in a test helper.
441
+ // Running this file through `tsx` — which is how `./scripts-run` and every
442
+ // consumer script reach it — emits `__name(...)` wrappers around the
443
+ // functions handed to `page.evaluate`. The browser has no such global, so
444
+ // the first evaluate dies with `ReferenceError: __name is not defined`
445
+ // while the same code passes under vitest, whose transform does not add it.
446
+ // Defining an identity shim before any page script runs makes both paths
447
+ // behave the same; it is a no-op where the wrapper was never emitted.
448
+ await context.addInitScript(() => {
449
+ const g = globalThis;
450
+ if (typeof g.__name !== 'function')
451
+ g.__name = (fn) => fn;
452
+ });
453
+ try {
454
+ // Sizes x backgrounds. Icons get 16/24/48; everything else 1x and 2x.
455
+ const sizes = isHost
456
+ ? [{ label: 'host', width: 800, height: 600 }]
457
+ : assetSizes(assetClass, intrinsic);
458
+ for (const size of sizes) {
459
+ for (const mode of ['light', 'dark']) {
460
+ const colour = backgrounds[mode];
461
+ const page = await openPage(context, {
462
+ url: targetUrl,
463
+ hostHtml,
464
+ hostBasename: HOST_BASENAME,
465
+ width: Math.max(size.width, 64),
466
+ height: Math.max(size.height, 64),
467
+ background: colour,
468
+ cssWidth: size.width,
469
+ blocked,
470
+ fileRoots,
471
+ });
472
+ const shot = path.join(opts.outDir, `asset-${size.label}-${mode}.png`);
473
+ await captureWithOneRetry(page, shot);
474
+ reading.sizes.push({
475
+ label: size.label,
476
+ css_width: size.width,
477
+ css_height: size.height,
478
+ background: mode,
479
+ background_color: colour,
480
+ screenshot: path.relative(opts.projectRoot, shot).split(path.sep).join('/'),
481
+ });
482
+ await page.close();
483
+ }
484
+ }
485
+ reading.network.aborted = blocked.length;
486
+ // One geometry pass. Every reading below is in viewBox units, which do
487
+ // not move with the render size — so reading them once and SAYING where
488
+ // beats re-reading them six times and implying they might differ.
489
+ const biggest = biggestSize(sizes);
490
+ // The moment the geometry was read, named rather than implied: an
491
+ // animated asset's painted box is a property of a time, and t = 0 is a
492
+ // declared one.
493
+ reading.readings_at = { css_width: biggest.width, css_height: biggest.height, background: 'light', t: 0 };
494
+ const page = await openPage(context, {
495
+ url: targetUrl,
496
+ hostHtml,
497
+ hostBasename: HOST_BASENAME,
498
+ width: Math.max(biggest.width, 64),
499
+ height: Math.max(biggest.height, 64),
500
+ background: backgrounds.light,
501
+ cssWidth: biggest.width,
502
+ blocked,
503
+ fileRoots,
504
+ });
505
+ if (!isHost) {
506
+ const raw = await page.evaluate(readAssetInPage, { nearWhite: NEAR_WHITE_CHANNEL });
507
+ applyGeometry(reading, raw, vb);
508
+ await applyFaceStates(page, reading);
509
+ }
510
+ // Accessible names across every graphic on the page (R7).
511
+ const names = await page.evaluate(readAccessibleNamesInPage);
512
+ const counts = new Map();
513
+ for (const n of names)
514
+ counts.set(n, (counts.get(n) ?? 0) + 1);
515
+ reading.accessible_names = [...counts].map(([name, count]) => ({ name, count }));
516
+ reading.duplicate_accessible_names = [...counts].filter(([, c]) => c > 1).map(([n]) => n);
517
+ // Frames at t = 0, mid, end. SMIL is paused and sought; CSS/WAAPI
518
+ // animations are paused and their currentTime is set (R6).
519
+ const duration = await page.evaluate(readAnimationEndInPage);
520
+ reading.animation_duration_s = duration;
521
+ if (duration > 0) {
522
+ const points = [
523
+ ['start', 0],
524
+ ['mid', duration / 2],
525
+ ['end', duration],
526
+ ];
527
+ for (const [label, t] of points) {
528
+ await page.evaluate(seekInPage, t);
529
+ const buf = await page.screenshot();
530
+ reading.frames.push({ label, t, digest: sha256(buf) });
531
+ }
532
+ reading.distinct_frames = new Set(reading.frames.map((f) => f.digest)).size;
533
+ }
534
+ await page.close();
535
+ // Reduced motion. Inline is witnessable; an image document is not (R5).
536
+ reading.reduced_motion = await readReducedMotion(context, {
537
+ url: targetUrl,
538
+ hostHtml,
539
+ width: Math.max(biggest.width, 64),
540
+ height: Math.max(biggest.height, 64),
541
+ background: backgrounds.light,
542
+ cssWidth: biggest.width,
543
+ blocked,
544
+ delivery,
545
+ duration,
546
+ isHost,
547
+ hostDir: path.dirname(path.resolve(opts.file)),
548
+ fileRoots,
549
+ });
550
+ if (opts.compareTo) {
551
+ reading.comparison = await compareGeometry(context, {
552
+ baseline: opts.file,
553
+ candidate: opts.compareTo,
554
+ assetClass,
555
+ tolerance: thresholds.geometry[assetClass],
556
+ toleranceSource: thresholds.geometrySource,
557
+ ...(opts.registration ? { registration: opts.registration } : {}),
558
+ blocked,
559
+ });
560
+ // Step 1.2: ask the SOURCE what is under each near-white region.
561
+ // Only reachable with a registration, which is the whole condition
562
+ // — without one the regions keep `no-source` and produce no
563
+ // finding, because the rule's claim is about the source and there
564
+ // is no source to make it against.
565
+ if (opts.registration && vb && reading.near_white_regions.length > 0) {
566
+ const points = reading.near_white_regions.map((n) => n.centre);
567
+ const samples = await sampleSource(context, opts.compareTo, vb, opts.registration, points, blocked);
568
+ if (samples !== null) {
569
+ reading.near_white_regions = reading.near_white_regions.map((n, i) => ({
570
+ ...n,
571
+ source_verdict: (samples[i]?.isBackground ?? false) ? 'hole' : 'paint',
572
+ }));
573
+ }
574
+ }
575
+ }
576
+ // Steps 4.1 and 4.2: the per-ground readings, taken at the biggest
577
+ // size so the counts are not dominated by anti-aliasing. Not for a
578
+ // host document — the silhouette of a page is the page.
579
+ if (!isHost) {
580
+ const confinedOpen = (ctx, spec) => openPage(ctx, { ...spec, fileRoots });
581
+ reading.grounds = await readGrounds(context, confinedOpen, {
582
+ url: targetUrl,
583
+ hostHtml,
584
+ width: Math.max(biggest.width, 64),
585
+ height: Math.max(biggest.height, 64),
586
+ cssWidth: biggest.width,
587
+ blocked,
588
+ backgrounds,
589
+ holeBoxes: extentsOf(elements, (el) => (el.attrs[HOLE_ATTRIBUTE] ?? '') !== ''),
590
+ // Finding 7: a shape the author made translucent is not a seam.
591
+ softBoxes: extentsOf(elements, isDeclaredTranslucent),
592
+ viewBox: vb,
593
+ });
594
+ }
595
+ }
596
+ finally {
597
+ await context.close();
598
+ }
599
+ if (!isHost && opts.iconSet && assetClass === 'icon') {
600
+ reading.icon_grid = gradeIconGrid(opts.file, vb, elements, opts.iconSet, reading.painted_box);
601
+ }
602
+ reading.network.aborted = blocked.length;
603
+ reading.findings = deriveFindings(reading);
604
+ return { reading, verification: 'verified' };
605
+ }
606
+ /** The host document for an inline delivery: one background, one sized graphic. */
607
+ function inlineHost(svg) {
608
+ const body = svg.replace(/<\?xml[^>]*\?>\s*/i, '').replace(/<!DOCTYPE[^>]*>\s*/i, '');
609
+ return `<!doctype html><html><head><meta charset="utf-8"><title>asset</title></head><body>${body}</body></html>`;
610
+ }
611
+ /**
612
+ * One page with the network closed. The synthetic host is fulfilled at a URL
613
+ * inside the asset's own directory, so the asset's relative references resolve
614
+ * from where it actually lives.
615
+ */
616
+ async function openPage(context, spec) {
617
+ const page = await context.newPage();
618
+ await page.setViewportSize({ width: Math.ceil(spec.width), height: Math.ceil(spec.height) });
619
+ if (spec.reducedMotion)
620
+ await page.emulateMedia({ reducedMotion: 'reduce' });
621
+ await confinePage(page, spec.blocked, spec.fileRoots, async (route) => {
622
+ if (!spec.hostHtml || !route.request().url().endsWith(`/${spec.hostBasename}`))
623
+ return false;
624
+ await route.fulfill({ status: 200, contentType: 'text/html; charset=utf-8', body: spec.hostHtml });
625
+ return true;
626
+ });
627
+ await page.goto(spec.url, { waitUntil: 'load', timeout: 30_000 });
628
+ await injectStyle(page, `html,body{margin:0;padding:0;background:${spec.background}}` +
629
+ `body>svg{display:block;width:${spec.cssWidth}px;height:auto}`);
630
+ return page;
631
+ }
632
+ function readAssetInPage(args) {
633
+ const svg = document.querySelector('svg');
634
+ if (!svg)
635
+ return { viewBox: null, elements: [], texts: [] };
636
+ const vbAttr = (svg.getAttribute('viewBox') ?? '').trim().split(/[\s,]+/).map(Number);
637
+ const viewBox = vbAttr.length === 4 && vbAttr.every((n) => Number.isFinite(n))
638
+ ? [vbAttr[0], vbAttr[1], vbAttr[2], vbAttr[3]]
639
+ : null;
640
+ const ctm = svg.getScreenCTM();
641
+ const inv = ctm ? ctm.inverse() : null;
642
+ const userBox = (el) => {
643
+ const r = el.getBoundingClientRect();
644
+ if (!inv)
645
+ return null;
646
+ const pts = [
647
+ [r.left, r.top],
648
+ [r.right, r.top],
649
+ [r.left, r.bottom],
650
+ [r.right, r.bottom],
651
+ ].map(([x, y]) => new DOMPoint(x, y).matrixTransform(inv));
652
+ const xs = pts.map((p) => p.x);
653
+ const ys = pts.map((p) => p.y);
654
+ const minX = Math.min(...xs);
655
+ const minY = Math.min(...ys);
656
+ return { x: minX, y: minY, w: Math.max(...xs) - minX, h: Math.max(...ys) - minY };
657
+ };
658
+ const SKIP = ['defs', 'title', 'desc', 'style', 'metadata', 'clippath', 'mask', 'marker', 'pattern', 'symbol'];
659
+ const inSkipped = (el) => {
660
+ let p = el.parentElement;
661
+ while (p && p !== svg) {
662
+ if (SKIP.includes(p.tagName.toLowerCase()))
663
+ return true;
664
+ p = p.parentElement;
665
+ }
666
+ return false;
667
+ };
668
+ const GENERIC = [
669
+ 'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy', 'system-ui',
670
+ 'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded', 'math', 'emoji', 'fangsong',
671
+ ];
672
+ const ctx = document.createElement('canvas').getContext('2d');
673
+ const resolves = (first, sample) => {
674
+ if (!first)
675
+ return false;
676
+ if (GENERIC.includes(first.toLowerCase()))
677
+ return true;
678
+ if (!ctx)
679
+ return true;
680
+ ctx.font = `32px "${first}", monospace`;
681
+ const a = ctx.measureText(sample).width;
682
+ ctx.font = '32px "__agent_config_absent_family__", monospace';
683
+ const b = ctx.measureText(sample).width;
684
+ return Math.abs(a - b) > 0.01;
685
+ };
686
+ // The document's own default family. A <text> that declares nothing lands
687
+ // on exactly this — which is how "no family was declared" is told apart
688
+ // from "a family was declared and did not resolve" (R1).
689
+ const defaultFamily = window.getComputedStyle(document.documentElement).fontFamily;
690
+ const all = Array.from(svg.querySelectorAll('*'));
691
+ const elements = [];
692
+ const texts = [];
693
+ for (let i = 0; i < all.length; i++) {
694
+ const el = all[i];
695
+ const tag = el.tagName.toLowerCase();
696
+ if (SKIP.includes(tag) || inSkipped(el))
697
+ continue;
698
+ if (!('getBBox' in el) || typeof el.getBBox !== 'function')
699
+ continue;
700
+ const g = el;
701
+ const cs = window.getComputedStyle(g);
702
+ if (cs.display === 'none' || cs.visibility === 'hidden')
703
+ continue;
704
+ let geom = null;
705
+ try {
706
+ const bb = g.getBBox();
707
+ geom = { x: bb.x, y: bb.y, w: bb.width, h: bb.height };
708
+ }
709
+ catch {
710
+ geom = null;
711
+ }
712
+ if (!geom || (geom.w === 0 && geom.h === 0))
713
+ continue;
714
+ let totalLength = null;
715
+ const geometry = g;
716
+ if (typeof geometry.getTotalLength === 'function') {
717
+ try {
718
+ totalLength = geometry.getTotalLength();
719
+ }
720
+ catch {
721
+ totalLength = null;
722
+ }
723
+ }
724
+ const pathLengthRaw = Number(el.getAttribute('pathLength'));
725
+ let from = null;
726
+ let to = null;
727
+ for (const anim of Array.from(el.children)) {
728
+ if (anim.tagName.toLowerCase() !== 'animate')
729
+ continue;
730
+ if ((anim.getAttribute('attributeName') ?? '') !== 'stroke-dashoffset')
731
+ continue;
732
+ const values = (anim.getAttribute('values') ?? '').split(';').map(Number).filter((n) => Number.isFinite(n));
733
+ if (values.length >= 2) {
734
+ from = values[0];
735
+ to = values[values.length - 1];
736
+ }
737
+ else {
738
+ const f = Number(anim.getAttribute('from'));
739
+ const t = Number(anim.getAttribute('to'));
740
+ if (Number.isFinite(f))
741
+ from = f;
742
+ if (Number.isFinite(t))
743
+ to = t;
744
+ }
745
+ }
746
+ const fillOpacity = Number(cs.fillOpacity || '1');
747
+ const opacity = Number(cs.opacity || '1');
748
+ elements.push({
749
+ index: i,
750
+ id: el.getAttribute('id') ?? '',
751
+ tag,
752
+ box: userBox(el),
753
+ geom,
754
+ fill: cs.fill,
755
+ opaque: fillOpacity >= 0.99 && opacity >= 0.99 && cs.fill !== 'none',
756
+ strokeWidth: Number.parseFloat(cs.strokeWidth || '0') || 0,
757
+ dash: cs.strokeDasharray,
758
+ totalLength,
759
+ pathLengthAttr: Number.isFinite(pathLengthRaw) && pathLengthRaw > 0 ? pathLengthRaw : null,
760
+ containedBy: [],
761
+ dashOffsetFrom: from,
762
+ dashOffsetTo: to,
763
+ });
764
+ if (tag === 'text') {
765
+ const attrFamily = el.getAttribute('font-family');
766
+ const cssFamily = cs.fontFamily;
767
+ const hasDeclaration = attrFamily !== null || cssFamily !== defaultFamily;
768
+ const declared = hasDeclaration ? (attrFamily ?? cssFamily) : '';
769
+ const list = (declared || cssFamily).split(',');
770
+ const first = (list[0] ?? '').trim().replace(/^["']|["']$/g, '');
771
+ const boxRefId = el.getAttribute('data-box');
772
+ const clip = /url\(['"]?#([^)'"]+)/.exec(el.getAttribute('clip-path') ?? '');
773
+ const refId = boxRefId ?? (clip ? clip[1] : null);
774
+ let declaredBox = null;
775
+ if (refId) {
776
+ const ref = svg.querySelector(`#${CSS.escape(refId)}`);
777
+ if (ref && typeof ref.getBBox === 'function') {
778
+ const rb = ref.getBBox();
779
+ declaredBox = { x: rb.x, y: rb.y, w: rb.width, h: rb.height };
780
+ }
781
+ }
782
+ const sample = el.textContent ?? '';
783
+ texts.push({
784
+ index: i,
785
+ id: el.getAttribute('id') ?? '',
786
+ text: sample,
787
+ box: geom,
788
+ declaredBoxId: refId,
789
+ declaredBox,
790
+ declaredFamily: declared,
791
+ firstFamily: first,
792
+ resolvedFamily: cssFamily,
793
+ firstFamilyResolved: hasDeclaration && resolves(first, sample || 'Hamburgefonstiv'),
794
+ });
795
+ }
796
+ }
797
+ // Containment by SAMPLED FILL (step 1.2). A second pass rather than a
798
+ // branch in the loop above, because it needs every element to exist first.
799
+ // `isPointInFill` is what the renderer itself answers with, so a near-white
800
+ // shape beside a ring is no longer "inside" it for having a smaller box.
801
+ // Finding 9: the OUTER loop is restricted to the only consumer. The pass
802
+ // used to call `isPointInFill` for every ordered pair of geometry-bearing
803
+ // elements and `applyGeometry` then read `containedBy` for opaque
804
+ // near-white elements alone — on the 195 KB, 355-gradient trace this change
805
+ // cites as its motivation that is 10^5-10^6 cross-process calls whose
806
+ // results are discarded. The reading is identical; only the pairs nobody
807
+ // asks about are gone.
808
+ //
809
+ // The channel floor is PASSED, not spelled twice. Finding 10 of this
810
+ // change's second completion review: a literal `237` on this side of the
811
+ // page boundary and `NEAR_WHITE_CHANNEL` on the other, bound only by a
812
+ // trailing comment, is the same shape as the dead constants this branch
813
+ // fixes elsewhere — one of them changes and nothing says so. A
814
+ // `page.evaluate` body cannot close over module scope, so it arrives as an
815
+ // argument, exactly as `minContrast` does two files away.
816
+ const NEAR_WHITE = args.nearWhite;
817
+ const candidates = elements.filter((el) => {
818
+ if (el.geom === null || !el.opaque)
819
+ return false;
820
+ const m = /rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(el.fill);
821
+ return m !== null && [m[1], m[2], m[3]].every((c) => Number(c) >= NEAR_WHITE);
822
+ });
823
+ for (const inner of candidates) {
824
+ if (!inner.geom)
825
+ continue;
826
+ const cx = inner.geom.x + inner.geom.w / 2;
827
+ const cy = inner.geom.y + inner.geom.h / 2;
828
+ for (const outer of elements) {
829
+ if (outer.index === inner.index)
830
+ continue;
831
+ const node = all[outer.index];
832
+ if (typeof node.isPointInFill !== 'function')
833
+ continue;
834
+ try {
835
+ if (node.isPointInFill({ x: cx, y: cy }))
836
+ inner.containedBy.push(outer.index);
837
+ }
838
+ catch {
839
+ // A node that refuses the question answers "not contained",
840
+ // which is the safe direction: it produces no finding.
841
+ }
842
+ }
843
+ }
844
+ return { viewBox, elements, texts };
845
+ }
846
+ function readAccessibleNamesInPage() {
847
+ const out = [];
848
+ for (const svg of Array.from(document.querySelectorAll('svg'))) {
849
+ const role = svg.getAttribute('role') ?? '';
850
+ if (svg.getAttribute('aria-hidden') === 'true')
851
+ continue;
852
+ if (!/^(img|graphics-document|graphics-symbol)$/.test(role))
853
+ continue;
854
+ const label = svg.getAttribute('aria-label');
855
+ if (label) {
856
+ out.push(label.trim());
857
+ continue;
858
+ }
859
+ const by = svg.getAttribute('aria-labelledby');
860
+ if (by) {
861
+ // EVERY id, joined by a space. Finding 9 of the fifth completion
862
+ // review: this read the first id only, while the static rule in
863
+ // `svg_rules.ts` resolves the whole list — so for
864
+ // `aria-labelledby="a b"` the two halves of one change disagreed
865
+ // about what the accessible name IS, and the rendered reading
866
+ // reported a shorter name than the file actually exposes. The
867
+ // accname spec concatenates the referenced elements in order.
868
+ const parts = by
869
+ .split(/\s+/)
870
+ .filter((id) => id !== '')
871
+ .map((id) => (document.getElementById(id)?.textContent ?? '').trim())
872
+ .filter((t) => t !== '');
873
+ out.push(parts.join(' '));
874
+ continue;
875
+ }
876
+ const title = svg.querySelector(':scope > title');
877
+ if (title)
878
+ out.push((title.textContent ?? '').trim());
879
+ }
880
+ for (const el of Array.from(document.querySelectorAll('[role="img"]:not(svg)'))) {
881
+ const label = el.getAttribute('aria-label');
882
+ if (label)
883
+ out.push(label.trim());
884
+ }
885
+ return out.filter((n) => n !== '');
886
+ }
887
+ /** Seconds to the end of one iteration of the longest animation; 0 when static. */
888
+ function readAnimationEndInPage() {
889
+ let end = 0;
890
+ const seconds = (raw) => {
891
+ if (!raw)
892
+ return 0;
893
+ const m = /^\s*([\d.]+)\s*(ms|s)?\s*$/.exec(raw);
894
+ if (!m)
895
+ return 0;
896
+ const v = Number(m[1]);
897
+ return m[2] === 'ms' ? v / 1000 : v;
898
+ };
899
+ for (const el of Array.from(document.querySelectorAll('animate,animateTransform,animateMotion,animateColor,set'))) {
900
+ const dur = seconds(el.getAttribute('dur'));
901
+ const rc = el.getAttribute('repeatCount');
902
+ const reps = rc && rc !== 'indefinite' && Number.isFinite(Number(rc)) ? Number(rc) : 1;
903
+ end = Math.max(end, dur * reps);
904
+ }
905
+ for (const anim of document.getAnimations()) {
906
+ const timing = anim.effect?.getComputedTiming();
907
+ const d = typeof timing?.duration === 'number' ? timing.duration / 1000 : 0;
908
+ end = Math.max(end, d);
909
+ }
910
+ return end;
911
+ }
912
+ /**
913
+ * A declared time, held. `screenshot({ animations: 'disabled' })` does NOT
914
+ * freeze SMIL (R6) — `pauseAnimations()` plus `setCurrentTime()` does.
915
+ */
916
+ function seekInPage(t) {
917
+ for (const svg of Array.from(document.querySelectorAll('svg'))) {
918
+ const s = svg;
919
+ if (typeof s.pauseAnimations === 'function') {
920
+ s.pauseAnimations();
921
+ s.setCurrentTime(t);
922
+ }
923
+ }
924
+ for (const anim of document.getAnimations()) {
925
+ anim.pause();
926
+ anim.currentTime = t * 1000;
927
+ }
928
+ }
929
+ // ---------------------------------------------------------------------------
930
+ // Assembling the reading
931
+ // ---------------------------------------------------------------------------
932
+ function applyGeometry(reading, raw, vb) {
933
+ const EPS = 1e-6;
934
+ let box = null;
935
+ for (const el of raw.elements) {
936
+ const b = el.box ?? el.geom;
937
+ if (!b)
938
+ continue;
939
+ box = box
940
+ ? {
941
+ x: Math.min(box.x, b.x),
942
+ y: Math.min(box.y, b.y),
943
+ w: Math.max(box.x + box.w, b.x + b.w) - Math.min(box.x, b.x),
944
+ h: Math.max(box.y + box.h, b.y + b.h) - Math.min(box.y, b.y),
945
+ }
946
+ : { ...b };
947
+ if (vb) {
948
+ const outLeft = b.x < vb.x - EPS;
949
+ const outTop = b.y < vb.y - EPS;
950
+ const outRight = b.x + b.w > vb.x + vb.w + EPS;
951
+ const outBottom = b.y + b.h > vb.y + vb.h + EPS;
952
+ if (outLeft || outTop || outRight || outBottom) {
953
+ reading.outside_view_box.push({
954
+ index: el.index,
955
+ id: el.id,
956
+ tag: el.tag,
957
+ box: b,
958
+ wholly_outside: b.x + b.w <= vb.x || b.y + b.h <= vb.y || b.x >= vb.x + vb.w || b.y >= vb.y + vb.h,
959
+ });
960
+ }
961
+ }
962
+ }
963
+ reading.painted_box = box;
964
+ if (box && vb && vb.w > 0 && vb.h > 0) {
965
+ const clipped = {
966
+ x0: Math.max(box.x, vb.x),
967
+ y0: Math.max(box.y, vb.y),
968
+ x1: Math.min(box.x + box.w, vb.x + vb.w),
969
+ y1: Math.min(box.y + box.h, vb.y + vb.h),
970
+ };
971
+ const area = Math.max(0, clipped.x1 - clipped.x0) * Math.max(0, clipped.y1 - clipped.y0);
972
+ reading.fill_ratio = area / (vb.w * vb.h);
973
+ }
974
+ for (const t of raw.texts) {
975
+ const declaredBox = t.declaredBox ?? (vb ? { x: vb.x, y: vb.y, w: vb.w, h: vb.h } : t.box);
976
+ reading.texts.push({
977
+ index: t.index,
978
+ id: t.id,
979
+ text: t.text,
980
+ box: t.box,
981
+ declared_box_id: t.declaredBoxId,
982
+ declared_box: declaredBox,
983
+ fits: t.box.x >= declaredBox.x - 0.5 &&
984
+ t.box.y >= declaredBox.y - 0.5 &&
985
+ t.box.x + t.box.w <= declaredBox.x + declaredBox.w + 0.5 &&
986
+ t.box.y + t.box.h <= declaredBox.y + declaredBox.h + 0.5,
987
+ declared_family: t.declaredFamily,
988
+ first_family: t.firstFamily,
989
+ resolved_family: t.resolvedFamily,
990
+ first_family_resolved: t.firstFamilyResolved,
991
+ });
992
+ }
993
+ for (const el of raw.elements) {
994
+ if (el.dashOffsetFrom === null || el.dashOffsetTo === null)
995
+ continue;
996
+ if (!el.totalLength || el.totalLength <= 0)
997
+ continue;
998
+ const dashFirst = Number.parseFloat(el.dash.split(/[\s,]+/)[0] ?? '');
999
+ if (!Number.isFinite(dashFirst) || dashFirst <= 0)
1000
+ continue;
1001
+ const scale = el.pathLengthAttr ? el.totalLength / el.pathLengthAttr : 1;
1002
+ reading.draw_on.push({
1003
+ index: el.index,
1004
+ id: el.id,
1005
+ total_length: el.totalLength,
1006
+ path_length_attr: el.pathLengthAttr,
1007
+ dash_units: dashFirst * scale,
1008
+ offset_from: el.dashOffsetFrom * scale,
1009
+ offset_to: el.dashOffsetTo * scale,
1010
+ dead_fraction: drawOnDeadFraction(dashFirst * scale, el.dashOffsetFrom * scale, el.dashOffsetTo * scale, el.totalLength),
1011
+ });
1012
+ }
1013
+ // Near-white paint where the source shows a hole (S5). Geometry, not pixels:
1014
+ // an opaque near-white shape wholly inside a non-near-white painted shape is
1015
+ // a filled hole, on any background — which is why no render is needed to
1016
+ // decide it and why the dark capture above is confirmation rather than input.
1017
+ const isNearWhite = (fill) => {
1018
+ const m = /rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(fill);
1019
+ if (!m)
1020
+ return false;
1021
+ return [m[1], m[2], m[3]].every((c) => Number(c) >= NEAR_WHITE_CHANNEL);
1022
+ };
1023
+ for (const inner of raw.elements) {
1024
+ if (!inner.opaque || !isNearWhite(inner.fill))
1025
+ continue;
1026
+ if (!inner.geom)
1027
+ continue;
1028
+ // Step 1.2: containment is the SAMPLED fill, computed in-page by
1029
+ // `isPointInFill`, not a bounding-box comparison. A box test calls a
1030
+ // near-white shape "inside" a ring, an L or a crescent it never
1031
+ // touches, which is how this rule came to fire six times on paint an
1032
+ // owner had deliberately chosen.
1033
+ const host = raw.elements.find((o) => inner.containedBy.includes(o.index) && o.opaque && !isNearWhite(o.fill));
1034
+ if (host) {
1035
+ reading.near_white_regions.push({
1036
+ index: inner.index,
1037
+ id: inner.id,
1038
+ fill: inner.fill,
1039
+ enclosed_by: host.id || `${host.tag}@${host.index}`,
1040
+ centre: { x: inner.geom.x + inner.geom.w / 2, y: inner.geom.y + inner.geom.h / 2 },
1041
+ // Filled in by the source sampling when a registered raster is
1042
+ // supplied. Absent evidence stays absent.
1043
+ source_verdict: 'no-source',
1044
+ });
1045
+ }
1046
+ }
1047
+ }
1048
+ function deriveFindings(r) {
1049
+ const out = faceFindings(r);
1050
+ if (r.fill_ratio !== null && r.fill_ratio < r.fill_ratio_threshold) {
1051
+ out.push({
1052
+ rule: 'structure/loose-viewbox',
1053
+ severity: 'warning',
1054
+ detail: `fill ratio ${r.fill_ratio.toFixed(3)} is below the ${r.asset_class} threshold ` +
1055
+ `${r.fill_ratio_threshold} (${r.fill_ratio_threshold_source}) — the painted box leaves the rest of the viewBox empty`,
1056
+ });
1057
+ }
1058
+ for (const t of r.texts) {
1059
+ if (!t.fits) {
1060
+ out.push({
1061
+ rule: 'geometry/text-overflows-box',
1062
+ severity: 'warning',
1063
+ detail: `<text>${t.id ? ` #${t.id}` : ''} renders ${t.box.w.toFixed(1)} x ${t.box.h.toFixed(1)} units at ` +
1064
+ `(${t.box.x.toFixed(1)}, ${t.box.y.toFixed(1)}), outside its declared box ` +
1065
+ `${t.declared_box_id ? `#${t.declared_box_id} ` : '(the viewBox) '}` +
1066
+ `${t.declared_box.w.toFixed(1)} x ${t.declared_box.h.toFixed(1)}`,
1067
+ });
1068
+ }
1069
+ if (!t.first_family_resolved) {
1070
+ out.push({
1071
+ rule: 'geometry/default-font-fallback',
1072
+ severity: 'warning',
1073
+ detail: t.declared_family
1074
+ ? `declared family "${t.first_family}" did not resolve; the renderer used "${t.resolved_family}"`
1075
+ : `no font-family is declared, so the label resolved to the renderer default "${t.resolved_family}"`,
1076
+ });
1077
+ }
1078
+ }
1079
+ for (const d of r.draw_on) {
1080
+ if (d.dead_fraction >= DRAW_ON_DEAD_TIME_THRESHOLD) {
1081
+ out.push({
1082
+ rule: 'motion/draw-on-dead-time',
1083
+ severity: 'warning',
1084
+ detail: `${(d.dead_fraction * 100).toFixed(1)}% of the draw-on duration paints nothing new: a ` +
1085
+ `${d.dash_units.toFixed(1)}-unit dash on a ${d.total_length.toFixed(2)}-unit path` +
1086
+ `${d.path_length_attr === null ? ' with no pathLength declared' : ''}`,
1087
+ });
1088
+ }
1089
+ }
1090
+ // Steps 4.1 and 4.2. Both name the GROUND they were read on, because
1091
+ // "the mark is hard to see" is not a property of the mark.
1092
+ for (const g of r.grounds) {
1093
+ if (g.background === 'dark' && g.silhouette_px > 0 && g.bleed_share > BLEED_SHARE_THRESHOLD) {
1094
+ out.push({
1095
+ rule: 'geometry/background-bleed-inside-silhouette',
1096
+ severity: 'warning',
1097
+ detail: `${g.bleed_px} of ${g.silhouette_px} pixels inside the silhouette read as the ${g.background} ` +
1098
+ `ground (${g.background_color}) — background showing THROUGH the graphic, which is what a ` +
1099
+ 'hairline seam between two abutting shapes looks like. Let the earlier surface reach about a ' +
1100
+ `pixel under its neighbour, or declare the gap with ${HOLE_ATTRIBUTE} if it is meant to be there`,
1101
+ });
1102
+ }
1103
+ if (g.silhouette_px > 0 && g.low_contrast_share > LOW_CONTRAST_SHARE_THRESHOLD) {
1104
+ out.push({
1105
+ rule: 'accessibility/low-contrast-on-background',
1106
+ severity: 'warning',
1107
+ detail: `${(g.low_contrast_share * 100).toFixed(0)} % of the painted pixels fall below a 3:1 contrast ` +
1108
+ `ratio against the ${g.background} ground (${g.background_color}) — build a variant for that ` +
1109
+ 'ground, or name it as missing',
1110
+ });
1111
+ }
1112
+ }
1113
+ // Step 2.1: the two readings the subject-only comparison separates out.
1114
+ // Neither is folded into IoU, and neither is silent.
1115
+ const raster = r.comparison?.raster;
1116
+ if (raster) {
1117
+ if (raster.frame_edge_contact.length > 0) {
1118
+ out.push({
1119
+ rule: 'geometry/source-cut-by-frame',
1120
+ severity: 'warning',
1121
+ detail: `the registered source runs into its frame on the ${raster.frame_edge_contact.join(', ')} ` +
1122
+ 'edge(s) — content cut by a crop agrees with a trace of that crop exactly, so the silhouette ' +
1123
+ 'reading cannot see the cut. Widen the crop and re-register before trusting the numbers',
1124
+ });
1125
+ }
1126
+ if (raster.foreign_content_share > FOREIGN_CONTENT_SHARE_THRESHOLD) {
1127
+ out.push({
1128
+ rule: 'geometry/foreign-content-in-frame',
1129
+ severity: 'warning',
1130
+ detail: `${(raster.foreign_content_share * 100).toFixed(1)} % of the registered source's painted pixels ` +
1131
+ 'lie outside the subject — a neighbouring mark, a glow or a shadow inside the registration ' +
1132
+ 'frame. It is reported here and kept out of the silhouette and colour readings',
1133
+ });
1134
+ }
1135
+ }
1136
+ for (const n of r.near_white_regions) {
1137
+ // Step 1.2: a finding needs EVIDENCE of a hole. Without a registered
1138
+ // source the region is recorded in the manifest and nothing is pushed —
1139
+ // the rule's message was always conditional on what the source shows,
1140
+ // and nothing was reading it.
1141
+ if (n.source_verdict !== 'hole')
1142
+ continue;
1143
+ out.push({
1144
+ rule: 'geometry/near-white-hole',
1145
+ severity: 'warning',
1146
+ detail: `${n.fill} is painted opaquely inside ${n.enclosed_by}, and the registered source shows its own ` +
1147
+ 'background there — a hole must be cut out, not painted near-white, or it reads white on a dark ' +
1148
+ 'background (S5)',
1149
+ });
1150
+ }
1151
+ if (r.icon_grid?.status === 'read') {
1152
+ const g = r.icon_grid;
1153
+ const strokeOff = g.stroke_width !== null &&
1154
+ g.reference_stroke_widths.length > 0 &&
1155
+ !g.reference_stroke_widths.some((s) => Math.abs(s - g.stroke_width) < 0.01);
1156
+ const minRefPadding = Math.min(...g.reference_padding);
1157
+ const paddingOff = g.padding !== null && g.padding < minRefPadding - 0.01;
1158
+ if (strokeOff || paddingOff) {
1159
+ out.push({
1160
+ rule: 'geometry/icon-off-grid',
1161
+ severity: 'warning',
1162
+ detail: `stroke ${g.stroke_width ?? 'none'} / padding ${g.padding?.toFixed(2) ?? 'none'} against the incumbent set's ` +
1163
+ `stroke ${g.reference_stroke_widths.join('/')} and padding ${g.reference_padding.join('/')} ` +
1164
+ `(read from ${g.reference_files.join(', ')})`,
1165
+ });
1166
+ }
1167
+ }
1168
+ // Measured, and previously derived nothing: an inline asset whose route was
1169
+ // read in a real browser and did NOT stop the motion produced an empty
1170
+ // findings array, so the one layer that can actually see the failure stayed
1171
+ // silent about it.
1172
+ if (r.reduced_motion.witnessable && r.reduced_motion.frames_equal === false) {
1173
+ out.push({
1174
+ rule: 'motion/reduced-motion-route-does-not-stop-it',
1175
+ severity: 'error',
1176
+ detail: 'under an emulated prefers-reduced-motion: reduce the frames still differ — the route this ' +
1177
+ 'file declares does not stop its animation, which is the R4 failure measured rather than inferred',
1178
+ });
1179
+ }
1180
+ // Step 1.1: gated on the duration, not only on the host's route. A host
1181
+ // with no `<picture>` route is correct for a file that does not move, and
1182
+ // this used to fire on all six files of a real conversion session — none
1183
+ // of which carries `<animate`, `@keyframes` or `animation`. A warning that
1184
+ // appears on every file is a warning an operator learns to scroll past,
1185
+ // which is Risk 1 of the parent roadmap arriving by a different door.
1186
+ const delivered = r.reduced_motion.delivered_animates;
1187
+ const unread = r.reduced_motion.delivered_unreadable ?? [];
1188
+ // Finding 13. An unreadable delivered file is UNKNOWN, and unknown is
1189
+ // reported rather than passed: the page-duration fallback reads 0 for a
1190
+ // spinner and a static logo alike, so falling back to it here would be the
1191
+ // absent-is-not-clean failure the rest of this change argues against.
1192
+ const moves = unread.length > 0
1193
+ ? true
1194
+ : delivered === null || delivered === undefined
1195
+ ? r.animation_duration_s > 0
1196
+ : delivered;
1197
+ if (r.reduced_motion.host_picture_route === false && moves) {
1198
+ out.push({
1199
+ rule: 'motion/img-delivery-no-static-route',
1200
+ severity: 'warning',
1201
+ detail: (unread.length > 0
1202
+ ? `${unread.join(', ')} could not be read, so whether it animates is unknown — reported ` +
1203
+ 'rather than passed. '
1204
+ : '') +
1205
+ 'an animated SVG is delivered through <img> or a CSS background and the host carries no ' +
1206
+ '<picture><source media="(prefers-reduced-motion: reduce)"> route — the emulated preference ' +
1207
+ 'does not reach an image document (R5), so this is the only place the route can live',
1208
+ });
1209
+ }
1210
+ for (const name of r.duplicate_accessible_names) {
1211
+ out.push({
1212
+ rule: 'accessibility/duplicate-accessible-name',
1213
+ severity: 'warning',
1214
+ detail: `"${name}" names more than one graphic on this page (R7)`,
1215
+ });
1216
+ }
1217
+ return out;
1218
+ }
1219
+ async function readReducedMotion(context, spec) {
1220
+ const R5 = 'an image document is unreachable by media emulation; the host\'s <picture> route is the thing to check';
1221
+ const page = await openPage(context, {
1222
+ url: spec.url,
1223
+ hostHtml: spec.hostHtml,
1224
+ hostBasename: HOST_BASENAME,
1225
+ width: spec.width,
1226
+ height: spec.height,
1227
+ background: spec.background,
1228
+ cssWidth: spec.cssWidth,
1229
+ blocked: spec.blocked,
1230
+ fileRoots: spec.fileRoots,
1231
+ reducedMotion: true,
1232
+ });
1233
+ try {
1234
+ if (spec.delivery === 'img' || spec.delivery === 'css-bg') {
1235
+ const seen = await page.evaluate(() => {
1236
+ const sources = Array.from(document.querySelectorAll('picture > source'));
1237
+ const route = sources.some((s) => /prefers-reduced-motion\s*:\s*reduce/i.test(s.getAttribute('media') ?? ''));
1238
+ // Every file this host DELIVERS, by its own reference — the
1239
+ // `<img>` src, each `<source srcset>`, and any CSS
1240
+ // background-image url. Names only; they are resolved on disk.
1241
+ const refs = new Set();
1242
+ for (const img of Array.from(document.querySelectorAll('img'))) {
1243
+ const src = img.getAttribute('src');
1244
+ if (src)
1245
+ refs.add(src);
1246
+ }
1247
+ for (const s of sources) {
1248
+ for (const part of (s.getAttribute('srcset') ?? '').split(',')) {
1249
+ const url = part.trim().split(/\s+/)[0];
1250
+ if (url)
1251
+ refs.add(url);
1252
+ }
1253
+ }
1254
+ for (const el of Array.from(document.querySelectorAll('*'))) {
1255
+ const bg = window.getComputedStyle(el).backgroundImage;
1256
+ const m = /url\((['"]?)([^)'"]+)\1\)/.exec(bg);
1257
+ if (m?.[2])
1258
+ refs.add(m[2]);
1259
+ }
1260
+ return { route, refs: [...refs] };
1261
+ });
1262
+ // Step 1.1: the question is about the DELIVERED file, and the host
1263
+ // page cannot answer it — its own duration is 0 for a spinner and
1264
+ // for a static logo alike.
1265
+ let animates = null;
1266
+ const unreadable = [];
1267
+ for (const ref of seen.refs) {
1268
+ if (/^(?:https?:|data:)/i.test(ref))
1269
+ continue;
1270
+ const abs = path.resolve(spec.hostDir, ref.replace(/^file:\/\//, ''));
1271
+ if (!/\.svg$/i.test(abs))
1272
+ continue;
1273
+ let body;
1274
+ try {
1275
+ body = fs.readFileSync(abs, 'utf8');
1276
+ }
1277
+ catch {
1278
+ // Finding 13: an `.svg` this host DELIVERS that could not
1279
+ // be read is absent evidence, and absent is not clean. It
1280
+ // used to `continue` into the page-duration fallback, which
1281
+ // that duration's own doc calls useless for an image
1282
+ // delivery — so an animating file behind an unreadable path
1283
+ // produced no warning at all.
1284
+ unreadable.push(ref);
1285
+ continue;
1286
+ }
1287
+ const moves = hasSmilMarkup(body) || hasCssAnimation(body);
1288
+ animates = (animates ?? false) || moves;
1289
+ }
1290
+ return {
1291
+ witnessable: false,
1292
+ frames_equal: null,
1293
+ reason: R5,
1294
+ host_picture_route: seen.route,
1295
+ delivered_animates: animates,
1296
+ ...(unreadable.length > 0 ? { delivered_unreadable: unreadable } : {}),
1297
+ };
1298
+ }
1299
+ if (spec.duration <= 0) {
1300
+ return { witnessable: true, frames_equal: true, reason: 'nothing animates in this file' };
1301
+ }
1302
+ await page.evaluate(seekInPage, 0);
1303
+ const a = sha256(await page.screenshot());
1304
+ await page.evaluate(seekInPage, spec.duration / 2);
1305
+ const b = sha256(await page.screenshot());
1306
+ return {
1307
+ witnessable: true,
1308
+ frames_equal: a === b,
1309
+ reason: 'inline delivery: the emulated preference reaches this document',
1310
+ };
1311
+ }
1312
+ finally {
1313
+ await page.close();
1314
+ }
1315
+ }
1316
+ //# sourceMappingURL=uiRenderAsset.js.map