@event4u/agent-config 14.10.0 → 14.11.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 (399) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +335 -0
  5. package/README.md +1 -1
  6. package/dist/agent-src/commands/design.md +88 -0
  7. package/dist/agent-src/commands/project/analyze.md +47 -0
  8. package/dist/agent-src/commands/review/changes.md +67 -6
  9. package/dist/agent-src/commands/roadmap/create.md +49 -0
  10. package/dist/agent-src/commands/roadmap/next.md +27 -11
  11. package/dist/agent-src/commands/roadmap/process-full.md +14 -0
  12. package/dist/agent-src/commands/video/from-script.md +60 -3
  13. package/dist/agent-src/commands/video/stitch.md +14 -0
  14. package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
  15. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  16. package/dist/agent-src/rules/active-remediation.md +3 -3
  17. package/dist/agent-src/rules/code-provenance.md +2 -2
  18. package/dist/agent-src/rules/context-hygiene.md +13 -33
  19. package/dist/agent-src/rules/council-availability.md +2 -2
  20. package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
  21. package/dist/agent-src/rules/design-fidelity.md +18 -0
  22. package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
  23. package/dist/agent-src/rules/evaluator-independence.md +56 -44
  24. package/dist/agent-src/rules/fix-what-you-see.md +9 -1
  25. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
  26. package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
  27. package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
  28. package/dist/agent-src/rules/playbook-precedence.md +105 -0
  29. package/dist/agent-src/rules/recurring-criticism.md +3 -1
  30. package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
  31. package/dist/agent-src/rules/scale-discipline.md +24 -0
  32. package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
  33. package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
  34. package/dist/agent-src/rules/ui-audit-gate.md +27 -15
  35. package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
  36. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  37. package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
  38. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
  39. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
  40. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
  41. package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
  42. package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
  43. package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +17 -0
  44. package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
  45. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
  46. package/dist/agent-src/skills/brand/SKILL.md +3 -0
  47. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
  48. package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
  49. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
  50. package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
  51. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
  52. package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
  53. package/dist/agent-src/skills/code-review/SKILL.md +11 -0
  54. package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
  55. package/dist/agent-src/skills/condense-memory/SKILL.md +3 -0
  56. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  57. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +3 -0
  58. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
  59. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
  60. package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
  61. package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
  62. package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
  63. package/dist/agent-src/skills/design-review/SKILL.md +79 -1
  64. package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
  65. package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
  66. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
  67. package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
  68. package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
  69. package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
  70. package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
  71. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +20 -3
  72. package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
  73. package/dist/agent-src/skills/fe-design/evals/triggers.json +65 -53
  74. package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
  75. package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
  76. package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
  77. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
  78. package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
  79. package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
  80. package/dist/agent-src/skills/iconography/SKILL.md +3 -0
  81. package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
  82. package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
  83. package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
  84. package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
  85. package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
  86. package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +17 -0
  87. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
  88. package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
  89. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
  90. package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
  91. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
  92. package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
  93. package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
  94. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
  95. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
  96. package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +17 -0
  97. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -0
  98. package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
  99. package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
  100. package/dist/agent-src/skills/operational-readiness/evals/triggers.json +17 -0
  101. package/dist/agent-src/skills/override-management/SKILL.md +3 -0
  102. package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
  103. package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
  104. package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
  105. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
  106. package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
  107. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
  108. package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
  109. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +52 -21
  110. package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
  111. package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
  112. package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
  113. package/dist/agent-src/skills/receiving-code-review/SKILL.md +2 -2
  114. package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
  115. package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
  116. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  117. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  118. package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
  119. package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
  120. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
  121. package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
  122. package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
  123. package/dist/agent-src/skills/secrets-management/SKILL.md +4 -0
  124. package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
  125. package/dist/agent-src/skills/server-hardening/evals/triggers.json +17 -0
  126. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
  127. package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
  128. package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
  129. package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
  130. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
  131. package/dist/agent-src/skills/storybook-workshop/SKILL.md +194 -0
  132. package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +17 -0
  133. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
  134. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  135. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
  136. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
  137. package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
  138. package/dist/agent-src/skills/terraform/SKILL.md +3 -0
  139. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
  140. package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
  141. package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
  142. package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
  143. package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -1
  144. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
  145. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
  146. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
  147. package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
  148. package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
  149. package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
  150. package/dist/agent-src/skills/workspace-link/evals/triggers.json +17 -0
  151. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  152. package/dist/agent-src/templates/playbook.md +75 -0
  153. package/dist/agent-src/templates/roadmaps.md +37 -0
  154. package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  155. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  156. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  157. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  158. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  159. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  160. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  161. package/dist/cli/commands/uiAudit.js +221 -0
  162. package/dist/cli/commands/uiAudit.js.map +1 -0
  163. package/dist/cli/commands/uiRender.js +206 -0
  164. package/dist/cli/commands/uiRender.js.map +1 -0
  165. package/dist/cli/main.js +22 -1
  166. package/dist/cli/main.js.map +1 -1
  167. package/dist/cli/mcp/content.js +64 -1
  168. package/dist/cli/mcp/content.js.map +1 -1
  169. package/dist/cli/mcp/dispatch.js +175 -10
  170. package/dist/cli/mcp/dispatch.js.map +1 -1
  171. package/dist/cli/registry.js +3 -0
  172. package/dist/cli/registry.js.map +1 -1
  173. package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-236PNQZK.js} +413 -391
  174. package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
  175. package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
  176. package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
  177. package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-L43NCYPB.js} +5 -0
  178. package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
  179. package/dist/cli-delegate/cmd_brand_status.js +8 -6
  180. package/dist/cli-delegate/cmd_conformance.js +3 -3
  181. package/dist/cli-delegate/cmd_doctor.js +3 -3
  182. package/dist/cli-delegate/cmd_export.js +4 -4
  183. package/dist/cli-delegate/cmd_handoff.js +1 -1
  184. package/dist/cli-delegate/cmd_preflight.js +2 -2
  185. package/dist/cli-delegate/cmd_prune.js +4 -4
  186. package/dist/cli-delegate/cmd_session_recycle.js +70 -9
  187. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  188. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  189. package/dist/cli-delegate/cmd_sync.js +4 -4
  190. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  191. package/dist/cli-delegate/cmd_validate.js +4 -4
  192. package/dist/discovery/deprecation-report.md +1 -1
  193. package/dist/discovery/discovery-manifest.json +359 -124
  194. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  195. package/dist/discovery/discovery-manifest.summary.md +4 -4
  196. package/dist/discovery/dormancy-report.md +1 -1
  197. package/dist/discovery/orphan-report.md +1 -1
  198. package/dist/discovery/packs.json +18 -8
  199. package/dist/discovery/trust-report.md +3 -3
  200. package/dist/discovery/workspaces.json +16 -6
  201. package/dist/hooks/dispatch.js +2337 -1436
  202. package/dist/install/install.mjs +795 -708
  203. package/dist/mcp/registry-manifest.json +3 -3
  204. package/dist/mcp/server.json +2 -2
  205. package/dist/mcp/server.mjs +1685 -1250
  206. package/dist/router.json +1 -1
  207. package/dist/scripts/_lib/lean_projection_mode.js +40 -0
  208. package/dist/scripts/_lib/lean_projection_mode.js.map +1 -0
  209. package/dist/scripts/_lib/scoped_projection.js +84 -0
  210. package/dist/scripts/_lib/scoped_projection.js.map +1 -1
  211. package/dist/scripts/_lib/ui_surface.js +89 -0
  212. package/dist/scripts/_lib/ui_surface.js.map +1 -0
  213. package/dist/scripts/condense.js +6 -10
  214. package/dist/scripts/condense.js.map +1 -1
  215. package/dist/scripts/project_thin_rules.js +40 -2
  216. package/dist/scripts/project_thin_rules.js.map +1 -1
  217. package/dist/server/schemas/settings.js +3 -0
  218. package/dist/server/schemas/settings.js.map +1 -1
  219. package/dist/shared/skillRanking.js +159 -0
  220. package/dist/shared/skillRanking.js.map +1 -0
  221. package/docs/contracts/provider-lifecycle.md +47 -18
  222. package/docs/contracts/settings-classes.md +14 -4
  223. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
  224. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  225. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
  226. package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  227. package/docs/guidelines/design-antipatterns.md +4 -2
  228. package/docs/guidelines/design-asset-discipline.md +38 -0
  229. package/docs/guidelines/design-fidelity-mechanics.md +45 -29
  230. package/docs/guidelines/design-handover-extraction.md +35 -5
  231. package/docs/guidelines/design-modes.md +41 -1
  232. package/docs/guidelines/monorepo-antipatterns.md +141 -0
  233. package/llms.txt +50 -39
  234. package/package.json +1 -1
  235. package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  236. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  237. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  238. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  239. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  240. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  241. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  242. package/src/config/agent-settings.template.yml +28 -0
  243. package/src/config/assurance-capability-registry.json +223 -0
  244. package/src/config/assurance-threshold-budget.json +65 -0
  245. package/src/config/ci-local-parity.yml +14 -0
  246. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  247. package/src/config/dispatch-economy-metrics.json +4 -2
  248. package/src/config/evaluator-budgets.json +14 -14
  249. package/src/config/gate-coverage.yml +207 -8
  250. package/src/config/gate-violation-baselines.json +76 -72
  251. package/src/config/hook-latency-budget.json +1 -0
  252. package/src/config/hook-token-budget.json +137 -125
  253. package/src/config/pack-size-budget.json +4 -2
  254. package/src/config/quorum-attendance-budget.json +12 -4
  255. package/src/config/rule-activation-census.json +7 -3
  256. package/src/config/rule-enforcement-baseline.json +0 -1
  257. package/src/config/rule-stub-ceilings.json +112 -91
  258. package/src/scripts/_cli/cmd_doctor.ts +15 -16
  259. package/src/scripts/_cli/doctor_install_mode.ts +49 -0
  260. package/src/scripts/_cli/doctor_overrides.ts +154 -0
  261. package/src/scripts/_dispatch.bash +17 -0
  262. package/src/scripts/_lib/as_of.ts +412 -0
  263. package/src/scripts/_lib/exec_evidence.ts +7 -0
  264. package/src/scripts/_lib/hook_settings.ts +33 -0
  265. package/src/scripts/_lib/host_listing_model.ts +192 -0
  266. package/src/scripts/_lib/lean_projection_mode.ts +44 -0
  267. package/src/scripts/_lib/mcp_bridge.ts +199 -0
  268. package/src/scripts/_lib/review_independence.ts +62 -10
  269. package/src/scripts/_lib/rule_injection.ts +239 -0
  270. package/src/scripts/_lib/run_checkpoint.ts +54 -1
  271. package/src/scripts/_lib/scoped_projection.ts +96 -0
  272. package/src/scripts/_lib/session_register.ts +44 -2
  273. package/src/scripts/_lib/skill_catalogue.ts +38 -2
  274. package/src/scripts/_lib/transcript_reads.ts +207 -0
  275. package/src/scripts/_lib/ui_authority.test.ts +251 -0
  276. package/src/scripts/_lib/ui_authority.ts +343 -0
  277. package/src/scripts/ai-video/adapters/fal.sh +8 -3
  278. package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
  279. package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
  280. package/src/scripts/ai-video/adapters/kling.sh +10 -0
  281. package/src/scripts/ai-video/adapters/sora.sh +10 -0
  282. package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
  283. package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
  284. package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
  285. package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
  286. package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
  287. package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
  288. package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
  289. package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
  290. package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
  291. package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
  292. package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
  293. package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
  294. package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
  295. package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
  296. package/src/scripts/ai-video/smoke-trace.sh +450 -2
  297. package/src/scripts/ai-video/stitch.sh +191 -10
  298. package/src/scripts/ai-video/test-pipeline.sh +84 -6
  299. package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
  300. package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
  301. package/src/scripts/ai_council/clients.ts +3 -2
  302. package/src/scripts/ai_council/consensus.ts +63 -6
  303. package/src/scripts/ai_council/events_log.ts +46 -1
  304. package/src/scripts/ai_council/orchestrator.ts +103 -108
  305. package/src/scripts/ai_council/orchestrator_results.ts +166 -0
  306. package/src/scripts/ai_council/prompts.ts +12 -5
  307. package/src/scripts/ai_council/quorum.ts +82 -1
  308. package/src/scripts/ai_council/quorum_wiring.ts +82 -5
  309. package/src/scripts/ai_council/stance_tally.ts +22 -0
  310. package/src/scripts/bench_hook_latency.ts +62 -0
  311. package/src/scripts/build_proof.ts +12 -1
  312. package/src/scripts/capture_skill_catalogue.ts +21 -0
  313. package/src/scripts/check_always_budget.ts +2 -1
  314. package/src/scripts/check_augmentignore.ts +2 -1
  315. package/src/scripts/check_beta_review_markers.ts +2 -1
  316. package/src/scripts/check_composite_arming.ts +364 -0
  317. package/src/scripts/check_corpus_staleness.ts +2 -1
  318. package/src/scripts/check_council_pin_staleness.ts +3 -1
  319. package/src/scripts/check_enforcement_coverage.ts +116 -3
  320. package/src/scripts/check_enforcement_denominator.ts +365 -0
  321. package/src/scripts/check_gate_coverage.ts +2 -1
  322. package/src/scripts/check_hook_bundle_freshness.ts +13 -1
  323. package/src/scripts/check_knowledge_cards.ts +2 -1
  324. package/src/scripts/check_knowledge_pages.ts +3 -2
  325. package/src/scripts/check_memory.ts +2 -1
  326. package/src/scripts/check_no_automerge_key.ts +287 -0
  327. package/src/scripts/check_pack_conformance_fixture.ts +565 -0
  328. package/src/scripts/check_proposal.ts +2 -1
  329. package/src/scripts/check_reach_staleness.ts +2 -1
  330. package/src/scripts/check_release_adjacent_health.ts +2 -1
  331. package/src/scripts/check_release_pr_shape.ts +5 -0
  332. package/src/scripts/check_review_schema.ts +34 -1
  333. package/src/scripts/check_roadmap_trackable.ts +48 -3
  334. package/src/scripts/check_source_size_budget.ts +2 -1
  335. package/src/scripts/check_standing_payload_delta.ts +505 -0
  336. package/src/scripts/check_trigger_evals.ts +2 -1
  337. package/src/scripts/classify_change_risk.ts +281 -0
  338. package/src/scripts/compute_skill_tiers.ts +186 -0
  339. package/src/scripts/condense.ts +8 -13
  340. package/src/scripts/council_attendance_metrics.ts +183 -0
  341. package/src/scripts/council_cli.ts +10 -8
  342. package/src/scripts/council_parse_rate.ts +116 -0
  343. package/src/scripts/derive_playbooks.ts +406 -0
  344. package/src/scripts/design_slop_rules.test.ts +7 -0
  345. package/src/scripts/design_slop_rules.ts +56 -2
  346. package/src/scripts/dispatch_r2_reviewer.ts +16 -0
  347. package/src/scripts/frontend_corpus_hash.ts +116 -0
  348. package/src/scripts/grade_target_readiness.ts +478 -0
  349. package/src/scripts/hook_manifest.json +1 -1
  350. package/src/scripts/hook_manifest.yaml +97 -16
  351. package/src/scripts/hooks/concern_registry.ts +4 -0
  352. package/src/scripts/hooks/design_pass_hook.ts +356 -0
  353. package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
  354. package/src/scripts/hooks/rule_inject_hook.ts +318 -0
  355. package/src/scripts/hot_context_hook.ts +74 -7
  356. package/src/scripts/install.ts +40 -89
  357. package/src/scripts/lint_adapter_tier.ts +663 -0
  358. package/src/scripts/lint_archived_skills.ts +93 -0
  359. package/src/scripts/lint_budget_ownership.ts +2 -1
  360. package/src/scripts/lint_deterministic_time.ts +470 -0
  361. package/src/scripts/lint_framework_leakage.ts +5 -0
  362. package/src/scripts/lint_handoffs.ts +525 -1
  363. package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
  364. package/src/scripts/lint_marketplace.ts +88 -0
  365. package/src/scripts/lint_media_policy_linkage.ts +140 -1
  366. package/src/scripts/lint_one_off_age.ts +6 -1
  367. package/src/scripts/lint_override_kernel_guard.ts +87 -5
  368. package/src/scripts/lint_roadmap_complexity.ts +56 -0
  369. package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
  370. package/src/scripts/lint_rule_norm_pin.ts +321 -0
  371. package/src/scripts/lint_spawn_payload.ts +42 -5
  372. package/src/scripts/lint_symptom_intake.ts +2 -1
  373. package/src/scripts/mcp_parity_smoke.ts +30 -4
  374. package/src/scripts/mcp_render.ts +66 -1
  375. package/src/scripts/mcp_tool_fingerprint.ts +241 -0
  376. package/src/scripts/measure_risk_class_drift.ts +140 -0
  377. package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
  378. package/src/scripts/media/lib/adapter-common.sh +211 -1
  379. package/src/scripts/media/lib/adapter-contract.md +74 -6
  380. package/src/scripts/model_rule_injection.ts +907 -0
  381. package/src/scripts/project_thin_rules.ts +45 -2
  382. package/src/scripts/release.ts +66 -860
  383. package/src/scripts/release_drill.ts +59 -3
  384. package/src/scripts/release_env.ts +298 -0
  385. package/src/scripts/release_publication.ts +720 -0
  386. package/src/scripts/roadmap_context.ts +778 -0
  387. package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
  388. package/src/scripts/schemas/rule.schema.json +24 -2
  389. package/src/scripts/schemas/skill.schema.json +39 -0
  390. package/src/scripts/schemas/ui-authority.schema.json +114 -0
  391. package/src/scripts/session_register_hook.ts +29 -3
  392. package/src/scripts/sessions_cli.ts +67 -3
  393. package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
  394. package/src/scripts/token_sink_report.ts +239 -0
  395. package/src/scripts/trigger_coverage.ts +122 -3
  396. package/src/scripts/update_counts.ts +7 -3
  397. package/src/scripts/validate_frontmatter.ts +66 -0
  398. package/src/server/schemas/settings.ts +5 -0
  399. package/src/shared/skillRanking.ts +183 -0
@@ -42,10 +42,17 @@
42
42
  * label is recoverable (audit catches it, user can override), but a
43
43
  * crash mid-dispatch is not.
44
44
  *
45
- * Root manifests only, by design: a monorepo caller passes the workspace
46
- * root that carries the manifest it cares about. Note the consequence —
47
- * a caller that always passes the repository root gets `plain` for a
48
- * monorepo, so the caller owns scope selection, not the detector.
45
+ * Workspace-aware since `road-to-monorepo-scope-and-detection`: a repository
46
+ * whose root declares workspaces (`package.json#workspaces`, a
47
+ * `pnpm-workspace.yaml`, a `turbo.json`, an `nx.json`, a `lerna.json`) and
48
+ * whose root manifest is not itself an application is descended into, and the
49
+ * workspace that was chosen is reported as {@link StackResult.scope_root}.
50
+ *
51
+ * The detector still never guesses **between** workspaces: two workspaces on
52
+ * mutually exclusive reactivity layers produce `unknown` plus both names, the
53
+ * same refusal a single conflicted manifest produces. What it no longer does is
54
+ * report `plain` for a monorepo — the previous behaviour, and the reason the
55
+ * repository was handed the generic directive.
49
56
  */
50
57
  import * as fs from 'node:fs';
51
58
  import * as path from 'node:path';
@@ -90,6 +97,8 @@ export const DEFAULT_STACK = 'plain';
90
97
  export const UNSUPPORTED_STACK = 'unknown';
91
98
 
92
99
  const _SHADCN_RADIX_PREFIX = '@radix-ui/';
100
+ /** The unified Radix package (February 2026) that replaced the `@radix-ui/*` scope. */
101
+ const _SHADCN_RADIX_UNIFIED = 'radix-ui';
93
102
  const _SHADCN_PACKAGE_NAMES: ReadonlySet<string> = new Set(['shadcn-ui', 'shadcn']);
94
103
  const _FLUX_PACKAGE = 'livewire/flux';
95
104
  const _LIVEWIRE_PACKAGE = 'livewire/livewire';
@@ -193,16 +202,36 @@ export class StackResult {
193
202
  */
194
203
  readonly ambiguity: ReadonlyArray<string>;
195
204
 
205
+ /**
206
+ * The workspace this result describes, **relative to the project root**.
207
+ *
208
+ * `''` means the project root itself — a non-monorepo, or a monorepo whose
209
+ * scope could not be resolved. Empty rather than `'.'` because that is
210
+ * already what `directives/ui/scaffold.ts` defaults to when the field is
211
+ * absent, so every non-monorepo project keeps byte-identical behaviour.
212
+ *
213
+ * Relative, not absolute, for two reasons that are both load-bearing. The
214
+ * field is serialized into `state.stack` and read back on a later run,
215
+ * possibly from a different absolute location (a container, a worktree, a
216
+ * moved checkout). And its one existing consumer — the playbook scope match
217
+ * at `scaffold.ts` — compares it against a playbook's declared `scope`,
218
+ * which is a repo-relative workspace path like `packages/ui`; an absolute
219
+ * path would silently match nothing but `scope: repo`.
220
+ */
221
+ readonly scope_root: string;
222
+
196
223
  constructor(args: {
197
224
  frontend: string;
198
225
  mtime: number;
199
226
  axes?: StackAxes;
200
227
  ambiguity?: ReadonlyArray<string>;
228
+ scope_root?: string;
201
229
  }) {
202
230
  this.frontend = args.frontend;
203
231
  this.mtime = args.mtime;
204
232
  this.axes = args.axes ?? _EMPTY_AXES;
205
233
  this.ambiguity = args.ambiguity ?? [];
234
+ this.scope_root = args.scope_root ?? '';
206
235
  }
207
236
  }
208
237
 
@@ -241,6 +270,24 @@ export function detect_stack(project_root: string): StackResult {
241
270
  return _r(UNSUPPORTED_STACK);
242
271
  }
243
272
 
273
+ // Workspace root WITH a root manifest — the shape this detector was written
274
+ // for and never reached. The old guard was `mtime === 0.0`, i.e. "no
275
+ // manifest at the repository root at all", but a root `package.json` is the
276
+ // defining file of an npm/pnpm/yarn/bun workspace, so the branch was skipped
277
+ // for every repository it was meant to serve.
278
+ //
279
+ // The second half of the predicate is what keeps a root application out:
280
+ // a root that ships `react` in `dependencies` IS the app and must not be
281
+ // abandoned for one of its own packages. A root that ships `react` only in
282
+ // `devDependencies` beside a workspace declaration is shared test tooling,
283
+ // which is why the check reads runtime sections only.
284
+ if (_is_workspace_root(project_root, pkg) && !_root_carries_frontend(composer, pkg)) {
285
+ const scoped = _resolve_workspace_scope(project_root, mtime, axes);
286
+ if (scoped !== null) {
287
+ return scoped;
288
+ }
289
+ }
290
+
244
291
  if (_is_blade_livewire_flux(composer)) {
245
292
  return _r('blade-livewire-flux');
246
293
  }
@@ -279,39 +326,16 @@ export function detect_stack(project_root: string): StackResult {
279
326
  return _r(UNSUPPORTED_STACK);
280
327
  }
281
328
 
282
- // Monorepo: no manifest at the root, but one sits in a workspace directory.
283
- // That is a wrong-scope call, not a plain project — the caller owns scope
284
- // selection, so say so instead of labelling the whole repo `plain` and
285
- // dispatching generic tooling at it.
329
+ // No manifest at the repository root, but one sits in a workspace
330
+ // directory. Not a monorepo in the declarative sense — nothing declares the
331
+ // workspaces — but a scaffold in progress, and descending is still right.
286
332
  //
287
333
  // A repo with no manifest ANYWHERE stays `plain`: that is greenfield, and
288
334
  // the scaffold path depends on it.
289
335
  if (mtime === 0.0) {
290
- const roots = _nested_frontend_roots(project_root);
291
- if (roots.length === 1) {
292
- // Unambiguous scope: descend once and keep the workspace's own
293
- // axes. Refusing here would punish the common monorepo shape for a
294
- // scope decision the layout already makes.
295
- const inner = detect_stack(roots[0] as string);
296
- return new StackResult({
297
- frontend: inner.frontend,
298
- mtime: inner.mtime,
299
- axes: inner.axes,
300
- ambiguity: inner.ambiguity,
301
- });
302
- }
303
- if (roots.length > 1) {
304
- // Several frontend roots: the caller owns scope selection, so name
305
- // them and let the step ask. Picking the first would be the silent
306
- // guess this detector exists to avoid.
307
- return new StackResult({
308
- frontend: UNSUPPORTED_STACK,
309
- mtime,
310
- axes,
311
- ambiguity: [
312
- `workspace roots: ${roots.map((r) => path.basename(r)).join(' + ')}`,
313
- ],
314
- });
336
+ const scoped = _resolve_workspace_scope(project_root, mtime, axes);
337
+ if (scoped !== null) {
338
+ return scoped;
315
339
  }
316
340
  }
317
341
 
@@ -356,6 +380,13 @@ const _CACHE_KEY_FILES: ReadonlyArray<string> = [
356
380
  'nuxt.config.ts',
357
381
  'nuxt.config.js',
358
382
  'astro.config.mjs',
383
+ // Workspace declarations, for exactly the reason `components.json` is here:
384
+ // adding a `pnpm-workspace.yaml` changes which manifest the result is
385
+ // computed from, while leaving both root manifests untouched — and the
386
+ // cache would otherwise serve the pre-workspace answer indefinitely.
387
+ 'pnpm-workspace.yaml',
388
+ 'turbo.json',
389
+ 'nx.json',
359
390
  ];
360
391
 
361
392
  /**
@@ -469,13 +500,35 @@ const _AXIS_SIGNALS: ReadonlyArray<{
469
500
 
470
501
  // component_lib — marker file beats dependency
471
502
  { axis: 'component_lib', value: 'shadcn', npm: ['shadcn-ui', 'shadcn'], files: ['components.json'] },
472
- { axis: 'component_lib', value: 'radix', npm_prefix: ['@radix-ui/'] },
503
+ // `radix-ui` (no slash) is the unified package shadcn's `new-york` style
504
+ // moved to in February 2026; the scoped `@radix-ui/*` packages are the
505
+ // pre-unification shape and both are still in the wild.
506
+ { axis: 'component_lib', value: 'radix', npm: ['radix-ui'], npm_prefix: ['@radix-ui/'] },
507
+ // Base UI is the other primitive layer shadcn accepts. `@base-ui/react` is
508
+ // the name since Base UI 1.0; `@base-ui-components/react` is what it was
509
+ // called before the rename, and projects pinned to it still exist.
510
+ { axis: 'component_lib', value: 'base-ui', npm: ['@base-ui/react', '@base-ui-components/react'] },
473
511
  { axis: 'component_lib', value: 'flux', composer: ['livewire/flux'] },
474
512
  { axis: 'component_lib', value: 'nuxt-ui', npm: ['@nuxt/ui'] },
475
513
  { axis: 'component_lib', value: 'vuetify', npm: ['vuetify'] },
476
514
  { axis: 'component_lib', value: 'mui', npm: ['@mui/material'] },
477
515
 
478
- // css
516
+ // css — the major is a marker-file question, never a version string.
517
+ // v4 dropped `tailwind.config.*` in favour of CSS-first configuration, so
518
+ // the two majors are told apart by which artefact exists, and a project
519
+ // carrying neither marker stays on the undifferentiated `tailwind` value
520
+ // rather than being guessed into a major.
521
+ { axis: 'css', value: 'tailwind-v4', npm: ['@tailwindcss/vite', '@tailwindcss/postcss'] },
522
+ {
523
+ axis: 'css',
524
+ value: 'tailwind-v3',
525
+ files: [
526
+ 'tailwind.config.js',
527
+ 'tailwind.config.cjs',
528
+ 'tailwind.config.mjs',
529
+ 'tailwind.config.ts',
530
+ ],
531
+ },
479
532
  { axis: 'css', value: 'tailwind', npm: ['tailwindcss'] },
480
533
  { axis: 'css', value: 'bootstrap', npm: ['bootstrap'] },
481
534
  ];
@@ -564,6 +617,238 @@ function _detect_ambiguity(composer: Manifest, pkg: Manifest): string[] {
564
617
  return found;
565
618
  }
566
619
 
620
+ /** Files that declare a workspace root even when `package.json` does not. */
621
+ const _WORKSPACE_MARKER_FILES: ReadonlyArray<string> = [
622
+ 'pnpm-workspace.yaml',
623
+ 'pnpm-workspace.yml',
624
+ 'turbo.json',
625
+ 'nx.json',
626
+ 'lerna.json',
627
+ ];
628
+
629
+ /**
630
+ * True when `project_root` declares itself the root of a workspace.
631
+ *
632
+ * Declaration, not convention: the presence of an `apps/` directory is a guess,
633
+ * whereas `workspaces`, `pnpm-workspace.yaml`, `turbo.json`, `nx.json` and
634
+ * `lerna.json` are the repository saying so itself. The conventional-directory
635
+ * scan still exists one layer down in {@link _nested_frontend_roots}, as a
636
+ * fallback for the roots this predicate has already admitted.
637
+ */
638
+ function _is_workspace_root(project_root: string, pkg: Manifest): boolean {
639
+ if (_workspace_globs(project_root, pkg).length > 0) {
640
+ return true;
641
+ }
642
+ return _WORKSPACE_MARKER_FILES.some((f) => _is_file(path.join(project_root, f)));
643
+ }
644
+
645
+ /**
646
+ * The declared workspace globs, from every declarative source.
647
+ *
648
+ * Three shapes, all real: npm/bun/yarn-modern's `workspaces: [...]`, yarn
649
+ * classic's `workspaces: { packages: [...] }`, and pnpm's `packages:` list in
650
+ * `pnpm-workspace.yaml` — the last of which a pnpm repository frequently has
651
+ * *instead of* any `workspaces` key at all.
652
+ */
653
+ function _workspace_globs(project_root: string, pkg: Manifest): string[] {
654
+ const out: string[] = [];
655
+ const declared = pkg['workspaces'];
656
+ if (Array.isArray(declared)) {
657
+ out.push(...declared.filter((g): g is string => typeof g === 'string'));
658
+ } else if (_isDict(declared) && Array.isArray(declared['packages'])) {
659
+ out.push(
660
+ ...(declared['packages'] as unknown[]).filter((g): g is string => typeof g === 'string'),
661
+ );
662
+ }
663
+ out.push(..._pnpm_workspace_globs(project_root));
664
+ return out;
665
+ }
666
+
667
+ /** Read the `packages:` globs out of `pnpm-workspace.yaml`. */
668
+ function _pnpm_workspace_globs(project_root: string): string[] {
669
+ for (const name of ['pnpm-workspace.yaml', 'pnpm-workspace.yml']) {
670
+ const p = path.join(project_root, name);
671
+ if (!_is_file(p)) {
672
+ continue;
673
+ }
674
+ let text: string;
675
+ try {
676
+ text = fs.readFileSync(p, { encoding: 'utf-8' });
677
+ } catch {
678
+ return [];
679
+ }
680
+ return _parse_pnpm_packages(text);
681
+ }
682
+ return [];
683
+ }
684
+
685
+ /**
686
+ * Extract `packages:` from a `pnpm-workspace.yaml` body.
687
+ *
688
+ * Prefers the `yaml` package, lazily required exactly as
689
+ * `_lib/agent_settings.ts` does, so an exotic file (anchors, flow sequences,
690
+ * block scalars) parses properly. Falls back to a line scanner when `yaml`
691
+ * cannot be resolved — this module ships into consumer repositories that carry
692
+ * their own `node_modules`, and silently reading no globs there would
693
+ * reintroduce the very defect this branch exists to fix, for precisely the
694
+ * pnpm users it was written for.
695
+ */
696
+ function _parse_pnpm_packages(text: string): string[] {
697
+ try {
698
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
699
+ const YAML = require('yaml') as { parse(input: string): unknown };
700
+ const data = YAML.parse(text);
701
+ if (_isDict(data) && Array.isArray(data['packages'])) {
702
+ return (data['packages'] as unknown[]).filter((g): g is string => typeof g === 'string');
703
+ }
704
+ return [];
705
+ } catch {
706
+ // `yaml` unresolvable, or the document did not parse — scan instead.
707
+ }
708
+ return _scan_yaml_string_list(text, 'packages');
709
+ }
710
+
711
+ /**
712
+ * Read a top-level block sequence of strings out of a YAML document.
713
+ *
714
+ * Deliberately not a YAML parser. pnpm's own schema makes `packages` a flat
715
+ * list of glob strings, so the shape is fixed and a scanner cannot silently
716
+ * mis-read it the way a partial parser could.
717
+ */
718
+ function _scan_yaml_string_list(text: string, key: string): string[] {
719
+ const out: string[] = [];
720
+ let inside = false;
721
+ for (const raw of text.split('\n')) {
722
+ const line = raw.replace(/\s+$/, '');
723
+ if (line === '' || line.trimStart().startsWith('#')) {
724
+ continue;
725
+ }
726
+ if (!inside) {
727
+ inside = line === `${key}:`;
728
+ continue;
729
+ }
730
+ const item = /^\s*-\s*(.+)$/.exec(line);
731
+ if (item === null) {
732
+ break; // the block ended
733
+ }
734
+ const value = (item[1] ?? '').trim().replace(/^['"]|['"]$/g, '');
735
+ if (value !== '') {
736
+ out.push(value);
737
+ }
738
+ }
739
+ return out;
740
+ }
741
+
742
+ /**
743
+ * True when the root manifest describes an application rather than a container.
744
+ *
745
+ * Runtime sections only for `package.json`. A workspace root routinely carries
746
+ * a shared test or build setup in `devDependencies` — a Testing-Library stack,
747
+ * a bundler — and reading that as "the root is a React app" is how a Vue
748
+ * monorepo was handed a React lane before this check existed.
749
+ */
750
+ function _root_carries_frontend(composer: Manifest, pkg: Manifest): boolean {
751
+ const php = _all_dependencies(composer, 'require', 'require-dev');
752
+ if (_LIVEWIRE_PACKAGE in php || _FILAMENT_PACKAGE in php) {
753
+ return true;
754
+ }
755
+ const runtime = _all_dependencies(pkg, 'dependencies', 'peerDependencies');
756
+ if ('react' in runtime || 'vue' in runtime) {
757
+ return true;
758
+ }
759
+ if (_UNMODELLED_MARKERS.some((marker) => marker in runtime || marker in php)) {
760
+ return true;
761
+ }
762
+ return Object.keys(runtime).some((name) => name.startsWith(_SHADCN_RADIX_PREFIX));
763
+ }
764
+
765
+ /**
766
+ * Label specificity, most specific first — the label chain's own order.
767
+ *
768
+ * Used only to choose between workspaces that do NOT conflict. A monorepo whose
769
+ * app is `react` and whose design system is `react-shadcn` is one stack seen at
770
+ * two depths, and the deeper signal is the better scope for the UI lane: it is
771
+ * the package that owns `components.json`, which is where components are
772
+ * authored.
773
+ */
774
+ const _LABEL_SPECIFICITY: ReadonlyArray<string> = [
775
+ 'blade-livewire-flux',
776
+ 'filament',
777
+ 'blade-livewire',
778
+ 'react-shadcn',
779
+ 'react',
780
+ 'vue',
781
+ UNSUPPORTED_STACK,
782
+ DEFAULT_STACK,
783
+ ];
784
+
785
+ function _label_rank(label: string): number {
786
+ const i = _LABEL_SPECIFICITY.indexOf(label);
787
+ return i === -1 ? _LABEL_SPECIFICITY.length : i;
788
+ }
789
+
790
+ /**
791
+ * Pick the frontend scope inside a workspace repository, or refuse.
792
+ *
793
+ * `null` means "no workspace carries a frontend" — the caller falls through to
794
+ * its own label, which keeps a backend-only monorepo `plain` instead of
795
+ * inventing a scope for it.
796
+ *
797
+ * Workspaces that resolve to {@link DEFAULT_STACK} are dropped before anything
798
+ * else is decided. That is not a tidy-up: a normal Turborepo ships
799
+ * `packages/eslint-config` and `packages/typescript-config` beside the real
800
+ * ones, and counting those as "frontend roots" made the multi-root refusal fire
801
+ * on repositories that have exactly one frontend.
802
+ */
803
+ function _resolve_workspace_scope(
804
+ project_root: string,
805
+ mtime: number,
806
+ root_axes: StackAxes,
807
+ ): StackResult | null {
808
+ const candidates = _nested_frontend_roots(project_root)
809
+ .map((dir) => ({ dir, result: detect_stack(dir) }))
810
+ .filter((c) => c.result.frontend !== DEFAULT_STACK);
811
+ if (candidates.length === 0) {
812
+ return null;
813
+ }
814
+
815
+ // Two workspaces on mutually exclusive reactivity layers are two stacks, and
816
+ // the standing contract for conflicting signals is to name them rather than
817
+ // pick one. Reuses `_EXCLUSIVE_REACTIVITY` so scope ambiguity and manifest
818
+ // ambiguity cannot drift apart: Alpine beside React is still one stack here,
819
+ // exactly as it is inside a single manifest.
820
+ const layers = new Set(
821
+ candidates
822
+ .map((c) => c.result.axes.reactivity)
823
+ .filter((value) => _EXCLUSIVE_REACTIVITY.has(value)),
824
+ );
825
+ if (layers.size > 1) {
826
+ const names = candidates
827
+ .map((c) => path.basename(c.dir))
828
+ .sort()
829
+ .join(' + ');
830
+ return new StackResult({
831
+ frontend: UNSUPPORTED_STACK,
832
+ mtime,
833
+ axes: root_axes,
834
+ ambiguity: [`workspace roots: ${names}`],
835
+ });
836
+ }
837
+
838
+ const best = [...candidates].sort((a, b) => {
839
+ const delta = _label_rank(a.result.frontend) - _label_rank(b.result.frontend);
840
+ return delta !== 0 ? delta : a.dir.localeCompare(b.dir);
841
+ })[0] as { dir: string; result: StackResult };
842
+
843
+ return new StackResult({
844
+ frontend: best.result.frontend,
845
+ mtime: best.result.mtime,
846
+ axes: best.result.axes,
847
+ ambiguity: best.result.ambiguity,
848
+ scope_root: path.relative(project_root, best.dir),
849
+ });
850
+ }
851
+
567
852
  /** Workspace directories a monorepo conventionally puts its packages in. */
568
853
  const _WORKSPACE_DIRS: ReadonlyArray<string> = ['packages', 'apps', 'services', 'libs'];
569
854
 
@@ -584,10 +869,7 @@ function _nested_frontend_roots(project_root: string): string[] {
584
869
  // `workspaces` is the declarative answer when present; the conventional
585
870
  // directories are the fallback for repos that do not declare them.
586
871
  const root_pkg = _read_json(path.join(project_root, 'package.json'));
587
- const declared = root_pkg['workspaces'];
588
- const globs: string[] = Array.isArray(declared)
589
- ? (declared as unknown[]).filter((g): g is string => typeof g === 'string')
590
- : [];
872
+ const globs = _workspace_globs(project_root, root_pkg);
591
873
  const dirs = new Set<string>(_WORKSPACE_DIRS);
592
874
  for (const g of globs) {
593
875
  const head = g.split('/')[0];
@@ -640,7 +922,10 @@ function _is_react_shadcn(pkg: Manifest, components_json: boolean): boolean {
640
922
  return false;
641
923
  }
642
924
  const names = Object.keys(deps);
643
- const has_radix = names.some((name) => name.startsWith(_SHADCN_RADIX_PREFIX));
925
+ // The unified `radix-ui` package counts exactly like the scoped `@radix-ui/*`
926
+ // prefix it replaced — same primitives, one entry in the manifest.
927
+ const has_radix =
928
+ _SHADCN_RADIX_UNIFIED in deps || names.some((name) => name.startsWith(_SHADCN_RADIX_PREFIX));
644
929
  const has_shadcn_pkg = names.some((name) => _SHADCN_PACKAGE_NAMES.has(name));
645
930
  return has_radix || has_shadcn_pkg || components_json;
646
931
  }
@@ -572,6 +572,7 @@ roadmap:
572
572
  # inter-step beat is.
573
573
  dashboard_regen_cadence: every_5_steps
574
574
 
575
+
575
576
  # Visible-horizon framing in roadmap authoring (integer weeks, default 0).
576
577
  # 0 = off (default). Time-boxed plate / horizon framing is forbidden:
577
578
  # no `## Horizon (N-week visible plate)` sections, no
@@ -1275,6 +1276,33 @@ hooks:
1275
1276
  design_slop:
1276
1277
  enabled: false
1277
1278
 
1279
+ # PostToolUse + stop design pass (road-to-frontend-power E1.1 / E1.2 / E1.3).
1280
+ # Default-OFF. One concern on two slots. On post_tool_use, a write to a UI
1281
+ # surface delivers the design findings as context and NEVER blocks. On stop,
1282
+ # the same pass runs over every UI file touched this session, deduped against
1283
+ # what the post pass already surfaced, and a P0 OBJECTIVE FLOOR (contrast,
1284
+ # font size, heading skip, focus) blocks with a continuation. P1-P3 never
1285
+ # block on either slot.
1286
+ #
1287
+ # post_tool_use rather than pre_tool_use, and the reason is measured rather
1288
+ # than stylistic (internal/bench/frontend-power/BASELINE-2026-08-23.md):
1289
+ # pre_tool_use is declared by three hosts and honoured by one while
1290
+ # post_tool_use is declared by six, and _lib/ui_surface.ts is a PATH
1291
+ # predicate — so a pre-write gate cannot fire on the first write of a NEW
1292
+ # surface, which is the write it most wants.
1293
+ #
1294
+ # A pass that could not fully run reports verification: degraded with a
1295
+ # reason (no render artefact => the viewport-dependent floors were not
1296
+ # checked) instead of passing silently. Run `agent-config ui:render` to lift
1297
+ # it, and `agent-config ui:audit` to satisfy the audit-freshness line.
1298
+ #
1299
+ # This does NOT replace design_slop above. Two design keys is the honest
1300
+ # state until the tiering experiment has a number: retiring the older
1301
+ # carrier on the assumption that this one covers it is the build-then-justify
1302
+ # pattern the parent roadmap's Risk 2 names.
1303
+ design_pass:
1304
+ enabled: false
1305
+
1278
1306
  # PreToolUse UI-route nudge (road-to-frontend-skill-application Phase 4).
1279
1307
  # Default-OFF. When enabled, a Write/Edit to a UI surface with no design
1280
1308
  # consultation latched this session WARNS (exit 2, never blocks) naming the