@monoes/monomindcli 2.16.1 → 2.16.3

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 (1009) hide show
  1. package/.claude/agents/architecture/system-design/arch-system-design.md +4 -1
  2. package/.claude/agents/consensus/quorum-manager.md +3 -0
  3. package/.claude/agents/consensus/security-manager.md +4 -1
  4. package/.claude/agents/core/coder.md +4 -1
  5. package/.claude/agents/core/coordinator.md +3 -0
  6. package/.claude/agents/core/planner.md +4 -1
  7. package/.claude/agents/core/researcher.md +4 -1
  8. package/.claude/agents/core/reviewer.md +4 -1
  9. package/.claude/agents/core/tester.md +4 -1
  10. package/.claude/agents/design/design-monodesign.md +4 -1
  11. package/.claude/agents/engineering/engineering-ai-data-remediation-engineer.md +4 -1
  12. package/.claude/agents/engineering/engineering-ai-engineer.md +4 -1
  13. package/.claude/agents/engineering/engineering-autonomous-optimization-architect.md +3 -0
  14. package/.claude/agents/engineering/engineering-backend-architect.md +4 -1
  15. package/.claude/agents/engineering/engineering-code-reviewer.md +5 -0
  16. package/.claude/agents/engineering/engineering-data-engineer.md +4 -1
  17. package/.claude/agents/engineering/engineering-database-optimizer.md +4 -1
  18. package/.claude/agents/engineering/engineering-devops-automator.md +3 -0
  19. package/.claude/agents/engineering/engineering-embedded-firmware-engineer.md +3 -0
  20. package/.claude/agents/engineering/engineering-feishu-integration-developer.md +4 -1
  21. package/.claude/agents/engineering/engineering-frontend-developer.md +3 -0
  22. package/.claude/agents/engineering/engineering-git-workflow-master.md +4 -1
  23. package/.claude/agents/engineering/engineering-incident-response-commander.md +4 -1
  24. package/.claude/agents/engineering/engineering-mobile-app-builder.md +3 -0
  25. package/.claude/agents/engineering/engineering-rapid-prototyper.md +3 -0
  26. package/.claude/agents/engineering/engineering-security-engineer.md +4 -1
  27. package/.claude/agents/engineering/engineering-senior-developer.md +3 -0
  28. package/.claude/agents/engineering/engineering-software-architect.md +4 -1
  29. package/.claude/agents/engineering/engineering-solidity-smart-contract-engineer.md +4 -1
  30. package/.claude/agents/engineering/engineering-sre.md +3 -0
  31. package/.claude/agents/engineering/engineering-technical-writer.md +4 -1
  32. package/.claude/agents/engineering/engineering-threat-detection-engineer.md +4 -1
  33. package/.claude/agents/engineering/engineering-wechat-mini-program-developer.md +4 -1
  34. package/.claude/agents/github/github-modes.md +4 -2
  35. package/.claude/agents/github/issue-tracker.md +4 -2
  36. package/.claude/agents/github/monoswarm-code-review.md +4 -2
  37. package/.claude/agents/github/monoswarm-issue.md +5 -0
  38. package/.claude/agents/github/monoswarm-multi-repo.md +4 -1
  39. package/.claude/agents/github/monoswarm-pr.md +5 -0
  40. package/.claude/agents/github/pr-manager.md +4 -2
  41. package/.claude/agents/github/project-board-sync.md +4 -2
  42. package/.claude/agents/github/release-manager.md +4 -2
  43. package/.claude/agents/github/repo-architect.md +4 -2
  44. package/.claude/agents/github/sync-coordinator.md +4 -2
  45. package/.claude/agents/github/workflow-automation.md +4 -2
  46. package/.claude/agents/goal/goal-planner.md +16 -2
  47. package/.claude/agents/marketing/marketing-competitive-content.md +4 -1
  48. package/.claude/agents/marketing/marketing-cro-specialist.md +4 -1
  49. package/.claude/agents/marketing/marketing-email-specialist.md +4 -1
  50. package/.claude/agents/marketing/marketing-launch-strategist.md +4 -1
  51. package/.claude/agents/marketing/marketing-pricing-strategist.md +4 -1
  52. package/.claude/agents/monoswarm/collective-intelligence-coordinator.md +3 -0
  53. package/.claude/agents/monoswarm/mesh-coordinator.md +3 -0
  54. package/.claude/agents/monoswarm/monoswarm-memory-manager.md +4 -2
  55. package/.claude/agents/monoswarm/scout-explorer.md +4 -2
  56. package/.claude/agents/monoswarm/worker-specialist.md +3 -0
  57. package/.claude/agents/optimization/benchmark-suite.md +3 -0
  58. package/.claude/agents/optimization/load-balancer.md +3 -0
  59. package/.claude/agents/optimization/performance-monitor.md +3 -0
  60. package/.claude/agents/optimization/resource-allocator.md +3 -0
  61. package/.claude/agents/optimization/topology-optimizer.md +3 -0
  62. package/.claude/agents/specialists/integration-architect.md +4 -2
  63. package/.claude/agents/specialized/agentic-identity-trust.md +4 -1
  64. package/.claude/agents/specialized/agents-orchestrator.md +3 -0
  65. package/.claude/agents/specialized/automation-governance-architect.md +3 -0
  66. package/.claude/agents/specialized/blockchain-security-auditor.md +4 -1
  67. package/.claude/agents/specialized/compliance-auditor.md +4 -1
  68. package/.claude/agents/specialized/identity-graph-operator.md +4 -1
  69. package/.claude/agents/specialized/lsp-index-engineer.md +3 -0
  70. package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +5 -0
  71. package/.claude/agents/specialized/specialized-cultural-intelligence-strategist.md +3 -0
  72. package/.claude/agents/specialized/specialized-developer-advocate.md +4 -1
  73. package/.claude/agents/specialized/specialized-document-generator.md +4 -1
  74. package/.claude/agents/specialized/specialized-mcp-builder.md +3 -0
  75. package/.claude/agents/specialized/specialized-model-qa.md +4 -1
  76. package/.claude/agents/specialized/specialized-workflow-architect.md +4 -1
  77. package/.claude/agents/specialized/zk-steward.md +4 -1
  78. package/.claude/agents/templates/automation-smart-agent.md +4 -1
  79. package/.claude/agents/templates/coordinator-monoswarm-init.md +4 -1
  80. package/.claude/agents/testing/production-validator.md +3 -0
  81. package/.claude/agents/testing/tdd-london-monoswarm.md +3 -0
  82. package/.claude/agents/testing/testing-accessibility-auditor.md +4 -1
  83. package/.claude/agents/testing/testing-api-tester.md +4 -1
  84. package/.claude/agents/testing/testing-evidence-collector.md +3 -0
  85. package/.claude/agents/testing/testing-performance-benchmarker.md +4 -1
  86. package/.claude/agents/testing/testing-test-results-analyzer.md +4 -1
  87. package/.claude/agents/testing/testing-tool-evaluator.md +4 -1
  88. package/.claude/agents/testing/testing-workflow-optimizer.md +4 -1
  89. package/.claude/commands/agents/agent-types.md +7 -5
  90. package/.claude/commands/mastermind/code-review.md +5 -5
  91. package/.claude/commands/mastermind/content.md +8 -2
  92. package/.claude/commands/mastermind/createtask.md +2 -2
  93. package/.claude/commands/mastermind/do.md +18 -36
  94. package/.claude/commands/mastermind/finance.md +8 -2
  95. package/.claude/commands/mastermind/ideate.md +4 -4
  96. package/.claude/commands/mastermind/improve.md +3 -3
  97. package/.claude/commands/mastermind/marketing.md +8 -2
  98. package/.claude/commands/mastermind/master.md +63 -45
  99. package/.claude/commands/mastermind/monoswarm.md +7 -5
  100. package/.claude/commands/mastermind/ops.md +8 -2
  101. package/.claude/commands/mastermind/sales.md +8 -2
  102. package/.claude/commands/mastermind.md +7 -7
  103. package/.claude/commands/monoswarm/analysis.md +1 -1
  104. package/.claude/commands/monoswarm/development.md +1 -1
  105. package/.claude/commands/monoswarm/maintenance.md +1 -1
  106. package/.claude/commands/monoswarm/optimization.md +2 -1
  107. package/.claude/commands/monoswarm/research.md +1 -1
  108. package/.claude/commands/monoswarm/testing.md +1 -1
  109. package/.claude/commands/pair/examples.md +3 -2
  110. package/.claude/commands/pair/modes.md +3 -3
  111. package/.claude/helpers/build-skill-registry.cjs +186 -26
  112. package/.claude/helpers/handlers/agent-start-handler.cjs +3 -0
  113. package/.claude/helpers/handlers/capture-handler.cjs +22 -14
  114. package/.claude/helpers/handlers/edit-handler.cjs +15 -13
  115. package/.claude/helpers/handlers/pick-core.cjs +445 -0
  116. package/.claude/helpers/handlers/route-handler.cjs +87 -180
  117. package/.claude/helpers/handlers/session-handler.cjs +44 -62
  118. package/.claude/helpers/handlers/session-restore-handler.cjs +5 -1
  119. package/.claude/helpers/handlers/task-handler.cjs +11 -6
  120. package/.claude/helpers/hook-handler.cjs +9 -2
  121. package/.claude/helpers/jev-catalog.cjs +225 -0
  122. package/.claude/helpers/jev-picker.cjs +36 -147
  123. package/.claude/helpers/monograph-freshen.cjs +31 -113
  124. package/.claude/helpers/org-skill-index.cjs +230 -0
  125. package/.claude/helpers/pick-rank.cjs +221 -0
  126. package/.claude/helpers/pick-stats.cjs +413 -0
  127. package/.claude/helpers/router.cjs +7 -379
  128. package/.claude/helpers/utils/monograph-resolve.cjs +505 -0
  129. package/.claude/helpers/utils/monograph.cjs +8 -51
  130. package/.claude/settings.json +51 -41
  131. package/.claude/skills/hooks-automation/SKILL.md +4 -4
  132. package/.claude/skills/mastermind-access/SKILL.md +4 -3
  133. package/.claude/skills/mastermind-activity/SKILL.md +3 -2
  134. package/.claude/skills/mastermind-adapter-manager/SKILL.md +2 -1
  135. package/.claude/skills/mastermind-adapters/SKILL.md +2 -1
  136. package/.claude/skills/mastermind-agent-detail/SKILL.md +5 -4
  137. package/.claude/skills/mastermind-agent-select/SKILL.md +99 -100
  138. package/.claude/skills/mastermind-agents/SKILL.md +2 -1
  139. package/.claude/skills/mastermind-approval-detail/SKILL.md +2 -1
  140. package/.claude/skills/mastermind-backup/SKILL.md +2 -1
  141. package/.claude/skills/mastermind-bootstrap/SKILL.md +2 -2
  142. package/.claude/skills/mastermind-budgets/SKILL.md +4 -3
  143. package/.claude/skills/mastermind-createorg/SKILL.md +23 -5
  144. package/.claude/skills/mastermind-delegation/SKILL.md +11 -19
  145. package/.claude/skills/mastermind-diagnose/SKILL.md +3 -3
  146. package/.claude/skills/mastermind-env/SKILL.md +2 -1
  147. package/.claude/skills/mastermind-environments/SKILL.md +2 -1
  148. package/.claude/skills/mastermind-execute/SKILL.md +1 -1
  149. package/.claude/skills/mastermind-export/SKILL.md +2 -1
  150. package/.claude/skills/mastermind-goal-detail/SKILL.md +3 -2
  151. package/.claude/skills/mastermind-goals/SKILL.md +3 -2
  152. package/.claude/skills/mastermind-idea/SKILL.md +52 -92
  153. package/.claude/skills/mastermind-import/SKILL.md +2 -1
  154. package/.claude/skills/mastermind-inbox/SKILL.md +3 -2
  155. package/.claude/skills/mastermind-instance/SKILL.md +3 -2
  156. package/.claude/skills/mastermind-invite-landing/SKILL.md +3 -2
  157. package/.claude/skills/mastermind-invites/SKILL.md +3 -2
  158. package/.claude/skills/mastermind-issue-detail/SKILL.md +4 -3
  159. package/.claude/skills/mastermind-issues/SKILL.md +4 -3
  160. package/.claude/skills/mastermind-join-queue/SKILL.md +5 -4
  161. package/.claude/skills/mastermind-liveness/SKILL.md +5 -4
  162. package/.claude/skills/mastermind-monitor/SKILL.md +15 -15
  163. package/.claude/skills/mastermind-my-issues/SKILL.md +2 -1
  164. package/.claude/skills/mastermind-new-agent/SKILL.md +120 -137
  165. package/.claude/skills/mastermind-org-settings/SKILL.md +6 -5
  166. package/.claude/skills/mastermind-orgs/SKILL.md +1 -0
  167. package/.claude/skills/mastermind-orgstatus/SKILL.md +2 -1
  168. package/.claude/skills/mastermind-plan-to-tasks/SKILL.md +1 -1
  169. package/.claude/skills/mastermind-plugin-manager/SKILL.md +4 -3
  170. package/.claude/skills/mastermind-plugin-settings/SKILL.md +5 -4
  171. package/.claude/skills/mastermind-plugins/SKILL.md +3 -2
  172. package/.claude/skills/mastermind-profile/SKILL.md +2 -1
  173. package/.claude/skills/mastermind-protocol/SKILL.md +3 -3
  174. package/.claude/skills/mastermind-release/SKILL.md +13 -8
  175. package/.claude/skills/mastermind-research/SKILL.md +10 -8
  176. package/.claude/skills/mastermind-review/SKILL.md +16 -11
  177. package/.claude/skills/mastermind-routine-detail/SKILL.md +2 -1
  178. package/.claude/skills/mastermind-routines/SKILL.md +3 -2
  179. package/.claude/skills/mastermind-search/SKILL.md +2 -1
  180. package/.claude/skills/mastermind-secrets/SKILL.md +3 -2
  181. package/.claude/skills/mastermind-skills/SKILL.md +2 -1
  182. package/.claude/skills/mastermind-stoporg/SKILL.md +1 -0
  183. package/.claude/skills/mastermind-tasks/SKILL.md +3 -2
  184. package/.claude/skills/mastermind-threads/SKILL.md +4 -3
  185. package/.claude/skills/mastermind-tree-control/SKILL.md +5 -4
  186. package/.claude/skills/mastermind-workspace-detail/SKILL.md +4 -3
  187. package/.claude/skills/mastermind-workspaces/SKILL.md +2 -1
  188. package/.claude/skills/monoswarm/SKILL.md +7 -5
  189. package/.claude/skills/specialagent/SKILL.md +32 -51
  190. package/README.md +1 -1
  191. package/dist/src/agents/registry-builder.d.ts +23 -2
  192. package/dist/src/agents/registry-builder.d.ts.map +1 -1
  193. package/dist/src/agents/registry-builder.js +64 -11
  194. package/dist/src/agents/registry-builder.js.map +1 -1
  195. package/dist/src/agents/registry-freshness.d.ts +21 -0
  196. package/dist/src/agents/registry-freshness.d.ts.map +1 -0
  197. package/dist/src/agents/registry-freshness.js +94 -0
  198. package/dist/src/agents/registry-freshness.js.map +1 -0
  199. package/dist/src/commands/agent-lifecycle.d.ts +11 -5
  200. package/dist/src/commands/agent-lifecycle.d.ts.map +1 -1
  201. package/dist/src/commands/agent-lifecycle.js +78 -42
  202. package/dist/src/commands/agent-lifecycle.js.map +1 -1
  203. package/dist/src/commands/doctor-env-checks.d.ts +18 -3
  204. package/dist/src/commands/doctor-env-checks.d.ts.map +1 -1
  205. package/dist/src/commands/doctor-env-checks.js +35 -16
  206. package/dist/src/commands/doctor-env-checks.js.map +1 -1
  207. package/dist/src/commands/doctor-fresh-install.d.ts +9 -0
  208. package/dist/src/commands/doctor-fresh-install.d.ts.map +1 -0
  209. package/dist/src/commands/doctor-fresh-install.js +43 -0
  210. package/dist/src/commands/doctor-fresh-install.js.map +1 -0
  211. package/dist/src/commands/doctor-hook-monograph-checks.d.ts +10 -0
  212. package/dist/src/commands/doctor-hook-monograph-checks.d.ts.map +1 -0
  213. package/dist/src/commands/doctor-hook-monograph-checks.js +88 -0
  214. package/dist/src/commands/doctor-hook-monograph-checks.js.map +1 -0
  215. package/dist/src/commands/doctor-hook-settings-checks.d.ts +5 -0
  216. package/dist/src/commands/doctor-hook-settings-checks.d.ts.map +1 -0
  217. package/dist/src/commands/doctor-hook-settings-checks.js +50 -0
  218. package/dist/src/commands/doctor-hook-settings-checks.js.map +1 -0
  219. package/dist/src/commands/doctor-json.d.ts +41 -0
  220. package/dist/src/commands/doctor-json.d.ts.map +1 -0
  221. package/dist/src/commands/doctor-json.js +60 -0
  222. package/dist/src/commands/doctor-json.js.map +1 -0
  223. package/dist/src/commands/doctor-mode.d.ts +28 -0
  224. package/dist/src/commands/doctor-mode.d.ts.map +1 -0
  225. package/dist/src/commands/doctor-mode.js +109 -0
  226. package/dist/src/commands/doctor-mode.js.map +1 -0
  227. package/dist/src/commands/doctor-monoes-checks.d.ts.map +1 -1
  228. package/dist/src/commands/doctor-monoes-checks.js +3 -1
  229. package/dist/src/commands/doctor-monoes-checks.js.map +1 -1
  230. package/dist/src/commands/doctor-pick-checks.d.ts +19 -0
  231. package/dist/src/commands/doctor-pick-checks.d.ts.map +1 -0
  232. package/dist/src/commands/doctor-pick-checks.js +164 -0
  233. package/dist/src/commands/doctor-pick-checks.js.map +1 -0
  234. package/dist/src/commands/doctor-project-checks.d.ts +3 -1
  235. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  236. package/dist/src/commands/doctor-project-checks.js +67 -20
  237. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  238. package/dist/src/commands/doctor.d.ts.map +1 -1
  239. package/dist/src/commands/doctor.js +325 -333
  240. package/dist/src/commands/doctor.js.map +1 -1
  241. package/dist/src/commands/hooks-coverage-routing.js +1 -1
  242. package/dist/src/commands/hooks-coverage-routing.js.map +1 -1
  243. package/dist/src/commands/hooks-coverage-utils.js +1 -1
  244. package/dist/src/commands/hooks-coverage-utils.js.map +1 -1
  245. package/dist/src/commands/hooks-routing-commands.js +1 -1
  246. package/dist/src/commands/init-upgrade.d.ts.map +1 -1
  247. package/dist/src/commands/init-upgrade.js +4 -0
  248. package/dist/src/commands/init-upgrade.js.map +1 -1
  249. package/dist/src/commands/monograph.d.ts.map +1 -1
  250. package/dist/src/commands/monograph.js +16 -1
  251. package/dist/src/commands/monograph.js.map +1 -1
  252. package/dist/src/commands/monoswarm.d.ts.map +1 -1
  253. package/dist/src/commands/monoswarm.js +16 -10
  254. package/dist/src/commands/monoswarm.js.map +1 -1
  255. package/dist/src/commands/pick.d.ts.map +1 -1
  256. package/dist/src/commands/pick.js +66 -16
  257. package/dist/src/commands/pick.js.map +1 -1
  258. package/dist/src/commands/route.d.ts +2 -1
  259. package/dist/src/commands/route.d.ts.map +1 -1
  260. package/dist/src/commands/route.js +73 -117
  261. package/dist/src/commands/route.js.map +1 -1
  262. package/dist/src/decision/catalogs.d.ts +24 -3
  263. package/dist/src/decision/catalogs.d.ts.map +1 -1
  264. package/dist/src/decision/catalogs.js +100 -22
  265. package/dist/src/decision/catalogs.js.map +1 -1
  266. package/dist/src/decision/jev.d.ts +26 -6
  267. package/dist/src/decision/jev.d.ts.map +1 -1
  268. package/dist/src/decision/jev.js +15 -4
  269. package/dist/src/decision/jev.js.map +1 -1
  270. package/dist/src/decision/pick-eval.d.ts +67 -0
  271. package/dist/src/decision/pick-eval.d.ts.map +1 -0
  272. package/dist/src/decision/pick-eval.js +113 -0
  273. package/dist/src/decision/pick-eval.js.map +1 -0
  274. package/dist/src/decision/pick-stats.d.ts +49 -0
  275. package/dist/src/decision/pick-stats.d.ts.map +1 -0
  276. package/dist/src/decision/pick-stats.js +68 -0
  277. package/dist/src/decision/pick-stats.js.map +1 -0
  278. package/dist/src/decision/picks.d.ts +37 -6
  279. package/dist/src/decision/picks.d.ts.map +1 -1
  280. package/dist/src/decision/picks.js +67 -32
  281. package/dist/src/decision/picks.js.map +1 -1
  282. package/dist/src/index.d.ts +5 -0
  283. package/dist/src/index.d.ts.map +1 -1
  284. package/dist/src/index.js +43 -22
  285. package/dist/src/index.js.map +1 -1
  286. package/dist/src/init/agent-refresh.d.ts +8 -0
  287. package/dist/src/init/agent-refresh.d.ts.map +1 -0
  288. package/dist/src/init/agent-refresh.js +89 -0
  289. package/dist/src/init/agent-refresh.js.map +1 -0
  290. package/dist/src/init/claudemd-generator.d.ts.map +1 -1
  291. package/dist/src/init/claudemd-generator.js +27 -9
  292. package/dist/src/init/claudemd-generator.js.map +1 -1
  293. package/dist/src/init/helpers-generator.d.ts +4 -1
  294. package/dist/src/init/helpers-generator.d.ts.map +1 -1
  295. package/dist/src/init/helpers-generator.js +84 -55
  296. package/dist/src/init/helpers-generator.js.map +1 -1
  297. package/dist/src/init/hook-settings.d.ts +57 -0
  298. package/dist/src/init/hook-settings.d.ts.map +1 -0
  299. package/dist/src/init/hook-settings.js +133 -0
  300. package/dist/src/init/hook-settings.js.map +1 -0
  301. package/dist/src/init/settings-generator.d.ts.map +1 -1
  302. package/dist/src/init/settings-generator.js +44 -25
  303. package/dist/src/init/settings-generator.js.map +1 -1
  304. package/dist/src/init/shared.d.ts +9 -0
  305. package/dist/src/init/shared.d.ts.map +1 -1
  306. package/dist/src/init/shared.js +22 -0
  307. package/dist/src/init/shared.js.map +1 -1
  308. package/dist/src/init/upgrade.d.ts +4 -0
  309. package/dist/src/init/upgrade.d.ts.map +1 -1
  310. package/dist/src/init/upgrade.js +123 -129
  311. package/dist/src/init/upgrade.js.map +1 -1
  312. package/dist/src/init/write-capabilities.d.ts.map +1 -1
  313. package/dist/src/init/write-capabilities.js +10 -33
  314. package/dist/src/init/write-capabilities.js.map +1 -1
  315. package/dist/src/init/write-claude.d.ts.map +1 -1
  316. package/dist/src/init/write-claude.js +5 -2
  317. package/dist/src/init/write-claude.js.map +1 -1
  318. package/dist/src/mcp-client.d.ts.map +1 -1
  319. package/dist/src/mcp-client.js +4 -0
  320. package/dist/src/mcp-client.js.map +1 -1
  321. package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
  322. package/dist/src/mcp-tools/agent-tools.js +3 -0
  323. package/dist/src/mcp-tools/agent-tools.js.map +1 -1
  324. package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -1
  325. package/dist/src/mcp-tools/guidance-tools.js +19 -10
  326. package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
  327. package/dist/src/mcp-tools/hooks-embedding.d.ts +1 -32
  328. package/dist/src/mcp-tools/hooks-embedding.d.ts.map +1 -1
  329. package/dist/src/mcp-tools/hooks-embedding.js +22 -200
  330. package/dist/src/mcp-tools/hooks-embedding.js.map +1 -1
  331. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  332. package/dist/src/mcp-tools/hooks-routing.js +77 -192
  333. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  334. package/dist/src/mcp-tools/index.d.ts +1 -0
  335. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  336. package/dist/src/mcp-tools/index.js +1 -0
  337. package/dist/src/mcp-tools/index.js.map +1 -1
  338. package/dist/src/mcp-tools/org-skill-tools.d.ts +4 -0
  339. package/dist/src/mcp-tools/org-skill-tools.d.ts.map +1 -0
  340. package/dist/src/mcp-tools/org-skill-tools.js +42 -0
  341. package/dist/src/mcp-tools/org-skill-tools.js.map +1 -0
  342. package/dist/src/mcp-tools/pick-tools.d.ts +4 -0
  343. package/dist/src/mcp-tools/pick-tools.d.ts.map +1 -0
  344. package/dist/src/mcp-tools/pick-tools.js +53 -0
  345. package/dist/src/mcp-tools/pick-tools.js.map +1 -0
  346. package/dist/src/monovector/coverage-router.d.ts +2 -1
  347. package/dist/src/monovector/coverage-router.d.ts.map +1 -1
  348. package/dist/src/monovector/coverage-router.js +6 -5
  349. package/dist/src/monovector/coverage-router.js.map +1 -1
  350. package/dist/src/monovector/coverage-tools.js +1 -1
  351. package/dist/src/monovector/coverage-tools.js.map +1 -1
  352. package/dist/src/monovector/index.d.ts +1 -1
  353. package/dist/src/monovector/index.d.ts.map +1 -1
  354. package/dist/src/monovector/index.js +11 -35
  355. package/dist/src/monovector/index.js.map +1 -1
  356. package/dist/src/monovector/route-outcomes.d.ts.map +1 -1
  357. package/dist/src/monovector/route-outcomes.js +89 -34
  358. package/dist/src/monovector/route-outcomes.js.map +1 -1
  359. package/dist/src/orgrt/bash-timeout.d.ts +14 -0
  360. package/dist/src/orgrt/bash-timeout.d.ts.map +1 -0
  361. package/dist/src/orgrt/bash-timeout.js +18 -0
  362. package/dist/src/orgrt/bash-timeout.js.map +1 -0
  363. package/dist/src/orgrt/block-recheck.d.ts +30 -0
  364. package/dist/src/orgrt/block-recheck.d.ts.map +1 -0
  365. package/dist/src/orgrt/block-recheck.js +81 -0
  366. package/dist/src/orgrt/block-recheck.js.map +1 -0
  367. package/dist/src/orgrt/completion-gate.d.ts +4 -0
  368. package/dist/src/orgrt/completion-gate.d.ts.map +1 -1
  369. package/dist/src/orgrt/completion-gate.js +22 -2
  370. package/dist/src/orgrt/completion-gate.js.map +1 -1
  371. package/dist/src/orgrt/daemon.d.ts +7 -13
  372. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  373. package/dist/src/orgrt/daemon.js +18 -27
  374. package/dist/src/orgrt/daemon.js.map +1 -1
  375. package/dist/src/orgrt/decisions.d.ts +4 -9
  376. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  377. package/dist/src/orgrt/decisions.js +44 -47
  378. package/dist/src/orgrt/decisions.js.map +1 -1
  379. package/dist/src/orgrt/dispatch-hold.d.ts +34 -0
  380. package/dist/src/orgrt/dispatch-hold.d.ts.map +1 -0
  381. package/dist/src/orgrt/dispatch-hold.js +75 -0
  382. package/dist/src/orgrt/dispatch-hold.js.map +1 -0
  383. package/dist/src/orgrt/mailbox.d.ts +14 -0
  384. package/dist/src/orgrt/mailbox.d.ts.map +1 -1
  385. package/dist/src/orgrt/mailbox.js +31 -1
  386. package/dist/src/orgrt/mailbox.js.map +1 -1
  387. package/dist/src/orgrt/runner-registry.d.ts +20 -0
  388. package/dist/src/orgrt/runner-registry.d.ts.map +1 -1
  389. package/dist/src/orgrt/runner-registry.js +39 -0
  390. package/dist/src/orgrt/runner-registry.js.map +1 -1
  391. package/dist/src/orgrt/sandbox-deny-write.d.ts +11 -1
  392. package/dist/src/orgrt/sandbox-deny-write.d.ts.map +1 -1
  393. package/dist/src/orgrt/sandbox-deny-write.js +23 -2
  394. package/dist/src/orgrt/sandbox-deny-write.js.map +1 -1
  395. package/dist/src/orgrt/sandbox-fault.d.ts +21 -7
  396. package/dist/src/orgrt/sandbox-fault.d.ts.map +1 -1
  397. package/dist/src/orgrt/sandbox-fault.js +92 -35
  398. package/dist/src/orgrt/sandbox-fault.js.map +1 -1
  399. package/dist/src/orgrt/session.d.ts +20 -10
  400. package/dist/src/orgrt/session.d.ts.map +1 -1
  401. package/dist/src/orgrt/session.js +60 -72
  402. package/dist/src/orgrt/session.js.map +1 -1
  403. package/dist/src/orgrt/skill-library.d.ts +4 -0
  404. package/dist/src/orgrt/skill-library.d.ts.map +1 -1
  405. package/dist/src/orgrt/skill-library.js +12 -0
  406. package/dist/src/orgrt/skill-library.js.map +1 -1
  407. package/dist/src/orgrt/skill-tools.d.ts +11 -0
  408. package/dist/src/orgrt/skill-tools.d.ts.map +1 -0
  409. package/dist/src/orgrt/skill-tools.js +40 -0
  410. package/dist/src/orgrt/skill-tools.js.map +1 -0
  411. package/dist/src/orgrt/task-cancel.d.ts +64 -0
  412. package/dist/src/orgrt/task-cancel.d.ts.map +1 -0
  413. package/dist/src/orgrt/task-cancel.js +134 -0
  414. package/dist/src/orgrt/task-cancel.js.map +1 -0
  415. package/dist/src/orgrt/task-dag.d.ts +18 -3
  416. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  417. package/dist/src/orgrt/task-dag.js +10 -4
  418. package/dist/src/orgrt/task-dag.js.map +1 -1
  419. package/dist/src/orgrt/task-match.d.ts +121 -0
  420. package/dist/src/orgrt/task-match.d.ts.map +1 -0
  421. package/dist/src/orgrt/task-match.js +241 -0
  422. package/dist/src/orgrt/task-match.js.map +1 -0
  423. package/dist/src/orgrt/task-provenance.d.ts +26 -0
  424. package/dist/src/orgrt/task-provenance.d.ts.map +1 -0
  425. package/dist/src/orgrt/task-provenance.js +93 -0
  426. package/dist/src/orgrt/task-provenance.js.map +1 -0
  427. package/dist/src/orgrt/task-tools.d.ts +24 -0
  428. package/dist/src/orgrt/task-tools.d.ts.map +1 -0
  429. package/dist/src/orgrt/task-tools.js +75 -0
  430. package/dist/src/orgrt/task-tools.js.map +1 -0
  431. package/dist/src/orgrt/types.d.ts +11 -0
  432. package/dist/src/orgrt/types.d.ts.map +1 -1
  433. package/dist/src/orgrt/types.js +18 -0
  434. package/dist/src/orgrt/types.js.map +1 -1
  435. package/dist/src/output.d.ts +6 -0
  436. package/dist/src/output.d.ts.map +1 -1
  437. package/dist/src/output.js +13 -2
  438. package/dist/src/output.js.map +1 -1
  439. package/dist/src/protocol-capabilities.d.ts +8 -1
  440. package/dist/src/protocol-capabilities.d.ts.map +1 -1
  441. package/dist/src/protocol-capabilities.js +10 -0
  442. package/dist/src/protocol-capabilities.js.map +1 -1
  443. package/dist/src/routing/agent-pick.d.ts +44 -0
  444. package/dist/src/routing/agent-pick.d.ts.map +1 -0
  445. package/dist/src/routing/agent-pick.js +114 -0
  446. package/dist/src/routing/agent-pick.js.map +1 -0
  447. package/dist/src/routing/pick-step.d.ts +26 -0
  448. package/dist/src/routing/pick-step.d.ts.map +1 -0
  449. package/dist/src/routing/pick-step.js +40 -0
  450. package/dist/src/routing/pick-step.js.map +1 -0
  451. package/dist/src/routing/route-layer-factory.d.ts.map +1 -1
  452. package/dist/src/routing/route-layer-factory.js +19 -17
  453. package/dist/src/routing/route-layer-factory.js.map +1 -1
  454. package/dist/src/utils/resource-governor.d.ts.map +1 -1
  455. package/dist/src/utils/resource-governor.js +55 -2
  456. package/dist/src/utils/resource-governor.js.map +1 -1
  457. package/dist/tsconfig.tsbuildinfo +1 -1
  458. package/org-skills/SOURCES.md +6 -6
  459. package/org-skills/TAGS.md +146 -0
  460. package/org-skills/ab-testing/SKILL.md +2 -2
  461. package/org-skills/accessibility-compliance/SKILL.md +2 -2
  462. package/org-skills/account-strategist/SKILL.md +2 -2
  463. package/org-skills/accounts-payable/SKILL.md +2 -2
  464. package/org-skills/ad-creative/SKILL.md +2 -2
  465. package/org-skills/adaptive-coordinator/SKILL.md +2 -2
  466. package/org-skills/adaptive-coordinator2/SKILL.md +2 -2
  467. package/org-skills/advanced-evaluation/SKILL.md +2 -2
  468. package/org-skills/adversarial-reviewer/SKILL.md +2 -2
  469. package/org-skills/agent-evaluation/SKILL.md +2 -2
  470. package/org-skills/agent-memory-systems/SKILL.md +2 -2
  471. package/org-skills/agent-tool-design/SKILL.md +2 -2
  472. package/org-skills/agile-product-owner/SKILL.md +2 -2
  473. package/org-skills/ai-citation/SKILL.md +2 -2
  474. package/org-skills/ai-engineer/SKILL.md +2 -2
  475. package/org-skills/ai-seo/SKILL.md +2 -2
  476. package/org-skills/analytics-reporter/SKILL.md +2 -2
  477. package/org-skills/analytics-tracking/SKILL.md +2 -2
  478. package/org-skills/android-clean-architecture/SKILL.md +2 -2
  479. package/org-skills/angular-architect/SKILL.md +2 -2
  480. package/org-skills/api-design/SKILL.md +2 -2
  481. package/org-skills/api-designer/SKILL.md +2 -2
  482. package/org-skills/api-tester/SKILL.md +2 -2
  483. package/org-skills/app-store-optimization/SKILL.md +2 -2
  484. package/org-skills/architecture-decision-records/SKILL.md +2 -2
  485. package/org-skills/architecture-designer/SKILL.md +2 -2
  486. package/org-skills/architecture-patterns/SKILL.md +2 -2
  487. package/org-skills/article-writing/SKILL.md +2 -2
  488. package/org-skills/auth-implementation-patterns/SKILL.md +2 -2
  489. package/org-skills/automation-governance/SKILL.md +2 -2
  490. package/org-skills/avoid-ai-writing/SKILL.md +2 -2
  491. package/org-skills/backend-dev/SKILL.md +2 -2
  492. package/org-skills/backend-patterns/SKILL.md +2 -2
  493. package/org-skills/bash-defensive-patterns/SKILL.md +2 -2
  494. package/org-skills/before-you-build/SKILL.md +2 -2
  495. package/org-skills/benchmark-methodology/SKILL.md +2 -2
  496. package/org-skills/benchmarker/SKILL.md +2 -2
  497. package/org-skills/blockchain-auditor/SKILL.md +2 -2
  498. package/org-skills/board-deck-builder/SKILL.md +2 -2
  499. package/org-skills/business-investment-advisor/SKILL.md +2 -2
  500. package/org-skills/byzantine-coord/SKILL.md +2 -2
  501. package/org-skills/canvas-design/SKILL.md +2 -2
  502. package/org-skills/carrier-relationship-management/SKILL.md +2 -2
  503. package/org-skills/case-analyst/SKILL.md +2 -2
  504. package/org-skills/ceo-advisor/SKILL.md +2 -2
  505. package/org-skills/cfo-advisor/SKILL.md +2 -2
  506. package/org-skills/change-management/SKILL.md +2 -2
  507. package/org-skills/changelog-automation/SKILL.md +2 -2
  508. package/org-skills/chro-advisor/SKILL.md +2 -2
  509. package/org-skills/churn-prevention/SKILL.md +2 -2
  510. package/org-skills/cicd-engineer/SKILL.md +2 -2
  511. package/org-skills/ciso-advisor/SKILL.md +2 -2
  512. package/org-skills/click-path-audit/SKILL.md +2 -2
  513. package/org-skills/cloud-architect/SKILL.md +2 -2
  514. package/org-skills/cloud-architecture/SKILL.md +2 -2
  515. package/org-skills/cmo-advisor/SKILL.md +2 -2
  516. package/org-skills/co-marketing/SKILL.md +2 -2
  517. package/org-skills/code-documenter/SKILL.md +2 -2
  518. package/org-skills/code-review-swarm/SKILL.md +2 -2
  519. package/org-skills/code-reviewer/SKILL.md +2 -2
  520. package/org-skills/coder/SKILL.md +2 -2
  521. package/org-skills/coding-standards/SKILL.md +2 -2
  522. package/org-skills/cold-email/SKILL.md +2 -2
  523. package/org-skills/collective-coord/SKILL.md +2 -2
  524. package/org-skills/community-marketing/SKILL.md +2 -2
  525. package/org-skills/competitive-landscape/SKILL.md +2 -2
  526. package/org-skills/competitive-platform-analysis/SKILL.md +2 -2
  527. package/org-skills/competitive-report-structure/SKILL.md +2 -2
  528. package/org-skills/competitive-teardown/SKILL.md +2 -2
  529. package/org-skills/competitor-comparison-pages/SKILL.md +2 -2
  530. package/org-skills/compliance-auditor/SKILL.md +2 -2
  531. package/org-skills/consensus-coordinator/SKILL.md +2 -2
  532. package/org-skills/content-creator/SKILL.md +2 -2
  533. package/org-skills/content-engine/SKILL.md +2 -2
  534. package/org-skills/content-strategy/SKILL.md +2 -2
  535. package/org-skills/context-compression/SKILL.md +2 -2
  536. package/org-skills/context-degradation/SKILL.md +2 -2
  537. package/org-skills/context-fundamentals/SKILL.md +2 -2
  538. package/org-skills/context-optimization/SKILL.md +2 -2
  539. package/org-skills/contract-and-proposal-writer/SKILL.md +1 -1
  540. package/org-skills/contract-first/SKILL.md +2 -2
  541. package/org-skills/coo-advisor/SKILL.md +2 -2
  542. package/org-skills/copy-editing/SKILL.md +2 -2
  543. package/org-skills/copywriting/SKILL.md +2 -2
  544. package/org-skills/cost-aware-llm-pipeline/SKILL.md +2 -2
  545. package/org-skills/cost-optimization/SKILL.md +2 -2
  546. package/org-skills/cpp-coding-standards/SKILL.md +2 -2
  547. package/org-skills/cpp-pro/SKILL.md +2 -2
  548. package/org-skills/cro-advisor/SKILL.md +2 -2
  549. package/org-skills/cro-specialist/SKILL.md +2 -2
  550. package/org-skills/csharp-developer/SKILL.md +2 -2
  551. package/org-skills/cto-advisor/SKILL.md +2 -2
  552. package/org-skills/culture-architect/SKILL.md +2 -2
  553. package/org-skills/customer-research/SKILL.md +2 -2
  554. package/org-skills/customs-trade-compliance/SKILL.md +2 -2
  555. package/org-skills/dart-flutter-patterns/SKILL.md +2 -2
  556. package/org-skills/dashboard-builder/SKILL.md +2 -2
  557. package/org-skills/data-consolidator/SKILL.md +2 -2
  558. package/org-skills/data-engineer/SKILL.md +2 -2
  559. package/org-skills/data-quality-frameworks/SKILL.md +2 -2
  560. package/org-skills/data-storytelling/SKILL.md +2 -2
  561. package/org-skills/database-migrations/SKILL.md +2 -2
  562. package/org-skills/database-optimizer/SKILL.md +2 -2
  563. package/org-skills/dbt-transformation-patterns/SKILL.md +2 -2
  564. package/org-skills/deal-strategist/SKILL.md +2 -2
  565. package/org-skills/debugging-wizard/SKILL.md +2 -2
  566. package/org-skills/deep-research/SKILL.md +2 -2
  567. package/org-skills/defender/SKILL.md +2 -2
  568. package/org-skills/dependency-upgrade/SKILL.md +2 -2
  569. package/org-skills/deployment-patterns/SKILL.md +2 -2
  570. package/org-skills/deployment-pipeline-design/SKILL.md +2 -2
  571. package/org-skills/design-system/SKILL.md +2 -2
  572. package/org-skills/design-system-patterns/SKILL.md +2 -2
  573. package/org-skills/devops-automator/SKILL.md +2 -2
  574. package/org-skills/devops-engineer/SKILL.md +2 -2
  575. package/org-skills/discovery-coach/SKILL.md +2 -2
  576. package/org-skills/django-expert/SKILL.md +2 -2
  577. package/org-skills/django-patterns/SKILL.md +2 -2
  578. package/org-skills/docker-patterns/SKILL.md +2 -2
  579. package/org-skills/dotnet-patterns/SKILL.md +2 -2
  580. package/org-skills/e2e-testing/SKILL.md +2 -2
  581. package/org-skills/email-marketing/SKILL.md +2 -2
  582. package/org-skills/email-sequences/SKILL.md +2 -2
  583. package/org-skills/embedded-firmware/SKILL.md +2 -2
  584. package/org-skills/embedded-systems/SKILL.md +2 -2
  585. package/org-skills/employment-contract-templates/SKILL.md +2 -2
  586. package/org-skills/energy-procurement/SKILL.md +2 -2
  587. package/org-skills/error-handling/SKILL.md +2 -2
  588. package/org-skills/event-marketing/SKILL.md +2 -2
  589. package/org-skills/evidence-collector/SKILL.md +2 -2
  590. package/org-skills/experiment-designer/SKILL.md +2 -2
  591. package/org-skills/experiment-tracker/SKILL.md +2 -2
  592. package/org-skills/experimental-design/SKILL.md +2 -2
  593. package/org-skills/fastapi-expert/SKILL.md +2 -2
  594. package/org-skills/fastapi-patterns/SKILL.md +2 -2
  595. package/org-skills/feedback-synthesizer/SKILL.md +2 -2
  596. package/org-skills/finance-tracker/SKILL.md +2 -2
  597. package/org-skills/finishing-a-development-branch/SKILL.md +2 -2
  598. package/org-skills/flutter-expert/SKILL.md +2 -2
  599. package/org-skills/focused-fix/SKILL.md +2 -2
  600. package/org-skills/free-tool-strategy/SKILL.md +2 -2
  601. package/org-skills/frontend-design/SKILL.md +2 -2
  602. package/org-skills/frontend-design-direction/SKILL.md +2 -2
  603. package/org-skills/frontend-developer/SKILL.md +2 -2
  604. package/org-skills/frontend-patterns/SKILL.md +2 -2
  605. package/org-skills/game-audio-engineer/SKILL.md +2 -2
  606. package/org-skills/game-designer/SKILL.md +2 -2
  607. package/org-skills/gdpr-data-handling/SKILL.md +2 -2
  608. package/org-skills/general-counsel-advisor/SKILL.md +2 -2
  609. package/org-skills/git-advanced-workflows/SKILL.md +2 -2
  610. package/org-skills/git-workflow/SKILL.md +2 -2
  611. package/org-skills/golang-patterns/SKILL.md +2 -2
  612. package/org-skills/golang-pro/SKILL.md +2 -2
  613. package/org-skills/harness-engineering/SKILL.md +2 -2
  614. package/org-skills/healthcare-phi-compliance/SKILL.md +2 -2
  615. package/org-skills/hexagonal-architecture/SKILL.md +2 -2
  616. package/org-skills/hierarchical-coord/SKILL.md +2 -2
  617. package/org-skills/huggingface-transformers/SKILL.md +2 -2
  618. package/org-skills/hypothesis-generation/SKILL.md +2 -2
  619. package/org-skills/incident-command-playbook/SKILL.md +2 -2
  620. package/org-skills/incident-commander/SKILL.md +2 -2
  621. package/org-skills/incident-runbook-templates/SKILL.md +2 -2
  622. package/org-skills/influencer-marketing/SKILL.md +2 -2
  623. package/org-skills/infrastructure/SKILL.md +2 -2
  624. package/org-skills/input-validator/SKILL.md +2 -2
  625. package/org-skills/intent-driven-development/SKILL.md +2 -2
  626. package/org-skills/inventory-demand-planning/SKILL.md +2 -2
  627. package/org-skills/investor-materials/SKILL.md +2 -2
  628. package/org-skills/ios-developer/SKILL.md +2 -2
  629. package/org-skills/isms-audit-expert/SKILL.md +2 -2
  630. package/org-skills/issue-tracker/SKILL.md +2 -2
  631. package/org-skills/java-architect/SKILL.md +2 -2
  632. package/org-skills/java-coding-standards/SKILL.md +2 -2
  633. package/org-skills/judge/SKILL.md +2 -2
  634. package/org-skills/kotlin-patterns/SKILL.md +2 -2
  635. package/org-skills/kotlin-specialist/SKILL.md +2 -2
  636. package/org-skills/kpi-dashboard-design/SKILL.md +2 -2
  637. package/org-skills/kubernetes-patterns/SKILL.md +2 -2
  638. package/org-skills/kubernetes-specialist/SKILL.md +2 -2
  639. package/org-skills/laravel-patterns/SKILL.md +2 -2
  640. package/org-skills/launch-strategist/SKILL.md +2 -2
  641. package/org-skills/launch-strategy/SKILL.md +2 -2
  642. package/org-skills/lead-magnets/SKILL.md +2 -2
  643. package/org-skills/legacy-modernizer/SKILL.md +2 -2
  644. package/org-skills/legal-compliance/SKILL.md +2 -2
  645. package/org-skills/level-designer/SKILL.md +2 -2
  646. package/org-skills/llm-cost-optimizer/SKILL.md +2 -2
  647. package/org-skills/llm-evaluation/SKILL.md +2 -2
  648. package/org-skills/llm-project-development/SKILL.md +2 -2
  649. package/org-skills/load-balancer/SKILL.md +2 -2
  650. package/org-skills/logistics-exception-management/SKILL.md +2 -2
  651. package/org-skills/long-horizon-prompting/SKILL.md +2 -2
  652. package/org-skills/make-interfaces-feel-better/SKILL.md +2 -2
  653. package/org-skills/markdown-mermaid-writing/SKILL.md +2 -2
  654. package/org-skills/market-research/SKILL.md +2 -2
  655. package/org-skills/market-research-reports/SKILL.md +2 -2
  656. package/org-skills/market-sizing-analysis/SKILL.md +2 -2
  657. package/org-skills/marketing-attribution/SKILL.md +2 -2
  658. package/org-skills/marketing-campaign/SKILL.md +2 -2
  659. package/org-skills/marketing-council/SKILL.md +2 -2
  660. package/org-skills/marketing-demand-acquisition/SKILL.md +2 -2
  661. package/org-skills/marketing-loops/SKILL.md +2 -2
  662. package/org-skills/marketing-plan/SKILL.md +2 -2
  663. package/org-skills/marketing-psychology/SKILL.md +2 -2
  664. package/org-skills/marketing-strategy-pmm/SKILL.md +2 -2
  665. package/org-skills/markitdown-document-conversion/SKILL.md +2 -2
  666. package/org-skills/mcp-builder/SKILL.md +2 -2
  667. package/org-skills/mcp-server-builder/SKILL.md +2 -2
  668. package/org-skills/mcp-server-patterns/SKILL.md +2 -2
  669. package/org-skills/memory-coordinator/SKILL.md +2 -2
  670. package/org-skills/mesh-coordinator/SKILL.md +2 -2
  671. package/org-skills/ml-developer/SKILL.md +2 -2
  672. package/org-skills/ml-pipeline/SKILL.md +2 -2
  673. package/org-skills/mle-workflow/SKILL.md +2 -2
  674. package/org-skills/mobile-app-builder/SKILL.md +2 -2
  675. package/org-skills/mobile-dev/SKILL.md +2 -2
  676. package/org-skills/model-qa/SKILL.md +2 -2
  677. package/org-skills/monitoring-expert/SKILL.md +2 -2
  678. package/org-skills/monodesign-ui-quality/SKILL.md +2 -2
  679. package/org-skills/monograph-code-navigation/SKILL.md +2 -2
  680. package/org-skills/monolean-minimal-change/SKILL.md +2 -2
  681. package/org-skills/multi-agent-patterns/SKILL.md +2 -2
  682. package/org-skills/mysql-patterns/SKILL.md +2 -2
  683. package/org-skills/narrative-designer/SKILL.md +2 -2
  684. package/org-skills/nextjs-developer/SKILL.md +2 -2
  685. package/org-skills/offer-design/SKILL.md +2 -2
  686. package/org-skills/onboarding-cro/SKILL.md +2 -2
  687. package/org-skills/outbound-strategist/SKILL.md +2 -2
  688. package/org-skills/page-cro/SKILL.md +2 -2
  689. package/org-skills/paid-ads/SKILL.md +2 -2
  690. package/org-skills/pandas-pro/SKILL.md +2 -2
  691. package/org-skills/path-validator/SKILL.md +2 -2
  692. package/org-skills/payment-agent/SKILL.md +2 -2
  693. package/org-skills/pci-compliance/SKILL.md +2 -2
  694. package/org-skills/perf-analyzer/SKILL.md +2 -2
  695. package/org-skills/php-pro/SKILL.md +2 -2
  696. package/org-skills/pipeline-analyst/SKILL.md +2 -2
  697. package/org-skills/planner/SKILL.md +2 -2
  698. package/org-skills/playwright-expert/SKILL.md +2 -2
  699. package/org-skills/postgres-patterns/SKILL.md +2 -2
  700. package/org-skills/postgresql-table-design/SKILL.md +2 -2
  701. package/org-skills/postmortem-writing/SKILL.md +2 -2
  702. package/org-skills/pr-manager/SKILL.md +2 -2
  703. package/org-skills/pricing-strategist/SKILL.md +2 -2
  704. package/org-skills/pricing-strategy/SKILL.md +2 -2
  705. package/org-skills/prisma-patterns/SKILL.md +2 -2
  706. package/org-skills/product-capability/SKILL.md +2 -2
  707. package/org-skills/product-discovery/SKILL.md +2 -2
  708. package/org-skills/product-lens/SKILL.md +2 -2
  709. package/org-skills/product-manager/SKILL.md +2 -2
  710. package/org-skills/product-marketing-context/SKILL.md +2 -2
  711. package/org-skills/production-audit/SKILL.md +2 -2
  712. package/org-skills/production-scheduling/SKILL.md +2 -2
  713. package/org-skills/production-validator/SKILL.md +2 -2
  714. package/org-skills/programmatic-seo/SKILL.md +2 -2
  715. package/org-skills/project-shepherd/SKILL.md +2 -2
  716. package/org-skills/prompt-engineer/SKILL.md +2 -2
  717. package/org-skills/proposal-strategist/SKILL.md +2 -2
  718. package/org-skills/prosecutor/SKILL.md +2 -2
  719. package/org-skills/public-relations/SKILL.md +2 -2
  720. package/org-skills/pymc-bayesian-modeling/SKILL.md +2 -2
  721. package/org-skills/python-patterns/SKILL.md +2 -2
  722. package/org-skills/python-pro/SKILL.md +2 -2
  723. package/org-skills/python-testing/SKILL.md +2 -2
  724. package/org-skills/quality-nonconformance/SKILL.md +2 -2
  725. package/org-skills/queen-coordinator/SKILL.md +2 -2
  726. package/org-skills/quorum-manager/SKILL.md +2 -2
  727. package/org-skills/raft-manager/SKILL.md +2 -2
  728. package/org-skills/rag-architect/SKILL.md +2 -2
  729. package/org-skills/rails-patterns/SKILL.md +2 -2
  730. package/org-skills/react-expert/SKILL.md +2 -2
  731. package/org-skills/react-native-expert/SKILL.md +2 -2
  732. package/org-skills/react-native-patterns/SKILL.md +2 -2
  733. package/org-skills/react-patterns/SKILL.md +2 -2
  734. package/org-skills/react-performance/SKILL.md +2 -2
  735. package/org-skills/react-testing/SKILL.md +2 -2
  736. package/org-skills/reality-checker/SKILL.md +2 -2
  737. package/org-skills/receiving-code-review/SKILL.md +2 -2
  738. package/org-skills/recruitment/SKILL.md +2 -2
  739. package/org-skills/redis-patterns/SKILL.md +2 -2
  740. package/org-skills/referral-programs/SKILL.md +2 -2
  741. package/org-skills/release-manager/SKILL.md +2 -2
  742. package/org-skills/repo-architect/SKILL.md +2 -2
  743. package/org-skills/researcher/SKILL.md +2 -2
  744. package/org-skills/resource-allocator/SKILL.md +2 -2
  745. package/org-skills/responsive-design/SKILL.md +2 -2
  746. package/org-skills/returns-reverse-logistics/SKILL.md +2 -2
  747. package/org-skills/reviewer/SKILL.md +2 -2
  748. package/org-skills/revops/SKILL.md +2 -2
  749. package/org-skills/roadmap-communicator/SKILL.md +2 -2
  750. package/org-skills/rust-engineer/SKILL.md +2 -2
  751. package/org-skills/rust-patterns/SKILL.md +2 -2
  752. package/org-skills/safe-executor/SKILL.md +2 -2
  753. package/org-skills/sales-coach/SKILL.md +2 -2
  754. package/org-skills/sales-enablement/SKILL.md +2 -2
  755. package/org-skills/sales-engineer/SKILL.md +2 -2
  756. package/org-skills/sales-prospecting/SKILL.md +2 -2
  757. package/org-skills/schema-markup/SKILL.md +2 -2
  758. package/org-skills/scientific-brainstorming/SKILL.md +2 -2
  759. package/org-skills/scientific-critical-thinking/SKILL.md +2 -2
  760. package/org-skills/scientific-thinking-literature-review/SKILL.md +2 -2
  761. package/org-skills/scientific-thinking-scholar-evaluation/SKILL.md +2 -2
  762. package/org-skills/scientific-visualization/SKILL.md +2 -2
  763. package/org-skills/scientific-writing/SKILL.md +2 -2
  764. package/org-skills/scout-explorer/SKILL.md +2 -2
  765. package/org-skills/secrets-vault-manager/SKILL.md +2 -2
  766. package/org-skills/secure-code-guardian/SKILL.md +2 -2
  767. package/org-skills/security-architect/SKILL.md +2 -2
  768. package/org-skills/security-auditor/SKILL.md +2 -2
  769. package/org-skills/security-review/SKILL.md +2 -2
  770. package/org-skills/security-reviewer/SKILL.md +2 -2
  771. package/org-skills/senior-data-scientist/SKILL.md +2 -2
  772. package/org-skills/senior-developer/SKILL.md +2 -2
  773. package/org-skills/senior-pm/SKILL.md +2 -2
  774. package/org-skills/senior-pm-playbook/SKILL.md +2 -2
  775. package/org-skills/seo/SKILL.md +2 -2
  776. package/org-skills/seo-audit/SKILL.md +2 -2
  777. package/org-skills/seo-specialist/SKILL.md +2 -2
  778. package/org-skills/shap-model-explainability/SKILL.md +2 -2
  779. package/org-skills/signup-flow-cro/SKILL.md +2 -2
  780. package/org-skills/site-architecture/SKILL.md +2 -2
  781. package/org-skills/sms-marketing/SKILL.md +2 -2
  782. package/org-skills/soc2-compliance/SKILL.md +2 -2
  783. package/org-skills/social-content/SKILL.md +2 -2
  784. package/org-skills/social-media/SKILL.md +2 -2
  785. package/org-skills/social-media-manager/SKILL.md +2 -2
  786. package/org-skills/solidity-engineer/SKILL.md +2 -2
  787. package/org-skills/spark-engineer/SKILL.md +2 -2
  788. package/org-skills/spec-driven-workflow/SKILL.md +2 -2
  789. package/org-skills/springboot-patterns/SKILL.md +2 -2
  790. package/org-skills/sprint-prioritizer/SKILL.md +2 -2
  791. package/org-skills/sql-pro/SKILL.md +2 -2
  792. package/org-skills/sre/SKILL.md +2 -2
  793. package/org-skills/sre-engineer/SKILL.md +2 -2
  794. package/org-skills/startup-financial-modeling/SKILL.md +2 -2
  795. package/org-skills/startup-metrics-framework/SKILL.md +2 -2
  796. package/org-skills/statistical-analysis/SKILL.md +2 -2
  797. package/org-skills/statistical-power/SKILL.md +2 -2
  798. package/org-skills/stride-analysis-patterns/SKILL.md +2 -2
  799. package/org-skills/stripe-integration/SKILL.md +2 -2
  800. package/org-skills/studio-operations/SKILL.md +2 -2
  801. package/org-skills/studio-producer/SKILL.md +2 -2
  802. package/org-skills/support-responder/SKILL.md +2 -2
  803. package/org-skills/swift-expert/SKILL.md +2 -2
  804. package/org-skills/swiftui-patterns/SKILL.md +2 -2
  805. package/org-skills/system-architect/SKILL.md +2 -2
  806. package/org-skills/systematic-debugging/SKILL.md +2 -2
  807. package/org-skills/task-orchestrator/SKILL.md +2 -2
  808. package/org-skills/team-communications/SKILL.md +2 -2
  809. package/org-skills/team-composition-analysis/SKILL.md +2 -2
  810. package/org-skills/technical-artist/SKILL.md +2 -2
  811. package/org-skills/technical-writer/SKILL.md +2 -2
  812. package/org-skills/terraform-engineer/SKILL.md +2 -2
  813. package/org-skills/test-driven-development/SKILL.md +2 -2
  814. package/org-skills/test-master/SKILL.md +2 -2
  815. package/org-skills/tester/SKILL.md +2 -2
  816. package/org-skills/the-fool/SKILL.md +2 -2
  817. package/org-skills/theme-factory/SKILL.md +2 -2
  818. package/org-skills/threat-detection/SKILL.md +2 -2
  819. package/org-skills/threat-mitigation-mapping/SKILL.md +2 -2
  820. package/org-skills/trend-researcher/SKILL.md +2 -2
  821. package/org-skills/trial-director/SKILL.md +2 -2
  822. package/org-skills/typescript-pro/SKILL.md +2 -2
  823. package/org-skills/unity-architect/SKILL.md +2 -2
  824. package/org-skills/using-git-worktrees/SKILL.md +2 -2
  825. package/org-skills/ux-researcher-designer/SKILL.md +2 -2
  826. package/org-skills/verification-before-completion/SKILL.md +2 -2
  827. package/org-skills/visionos-engineer/SKILL.md +2 -2
  828. package/org-skills/visual-design-foundations/SKILL.md +2 -2
  829. package/org-skills/vue-expert/SKILL.md +2 -2
  830. package/org-skills/vue-patterns/SKILL.md +2 -2
  831. package/org-skills/worker-specialist/SKILL.md +2 -2
  832. package/org-skills/workflow-architect/SKILL.md +2 -2
  833. package/org-skills/workflow-automation/SKILL.md +2 -2
  834. package/org-skills/writing-plans/SKILL.md +2 -2
  835. package/org-skills/zk-steward/SKILL.md +2 -2
  836. package/package.json +7 -7
  837. package/.claude/helpers/skill-registry.json +0 -5997
  838. package/.claude/skills/monodesign/SKILL.md +0 -257
  839. package/.claude/skills/monodesign/adapt.md +0 -53
  840. package/.claude/skills/monodesign/agents/monodesign-asset-producer.md +0 -100
  841. package/.claude/skills/monodesign/agents/monodesign-manual-edit-applier.md +0 -103
  842. package/.claude/skills/monodesign/animate.md +0 -65
  843. package/.claude/skills/monodesign/audit.md +0 -89
  844. package/.claude/skills/monodesign/bolder.md +0 -50
  845. package/.claude/skills/monodesign/clarify.md +0 -64
  846. package/.claude/skills/monodesign/colorize.md +0 -68
  847. package/.claude/skills/monodesign/craft.md +0 -51
  848. package/.claude/skills/monodesign/critique.md +0 -66
  849. package/.claude/skills/monodesign/delight.md +0 -47
  850. package/.claude/skills/monodesign/distill.md +0 -56
  851. package/.claude/skills/monodesign/document.md +0 -83
  852. package/.claude/skills/monodesign/extract.md +0 -74
  853. package/.claude/skills/monodesign/harden.md +0 -65
  854. package/.claude/skills/monodesign/init.md +0 -30
  855. package/.claude/skills/monodesign/layout.md +0 -36
  856. package/.claude/skills/monodesign/live.md +0 -34
  857. package/.claude/skills/monodesign/onboard.md +0 -50
  858. package/.claude/skills/monodesign/optimize.md +0 -64
  859. package/.claude/skills/monodesign/overdrive.md +0 -56
  860. package/.claude/skills/monodesign/polish.md +0 -68
  861. package/.claude/skills/monodesign/quieter.md +0 -57
  862. package/.claude/skills/monodesign/reference/adapt.md +0 -312
  863. package/.claude/skills/monodesign/reference/adapt.native.md +0 -58
  864. package/.claude/skills/monodesign/reference/android.md +0 -40
  865. package/.claude/skills/monodesign/reference/animate.md +0 -203
  866. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +0 -410
  867. package/.claude/skills/monodesign/reference/audit.md +0 -135
  868. package/.claude/skills/monodesign/reference/audit.native.md +0 -139
  869. package/.claude/skills/monodesign/reference/bolder.md +0 -120
  870. package/.claude/skills/monodesign/reference/brand-workflow.md +0 -180
  871. package/.claude/skills/monodesign/reference/brand.md +0 -108
  872. package/.claude/skills/monodesign/reference/clarify.md +0 -288
  873. package/.claude/skills/monodesign/reference/codex.md +0 -105
  874. package/.claude/skills/monodesign/reference/cognitive-load.md +0 -106
  875. package/.claude/skills/monodesign/reference/color-and-contrast.md +0 -105
  876. package/.claude/skills/monodesign/reference/colorize.md +0 -257
  877. package/.claude/skills/monodesign/reference/component-specs.md +0 -260
  878. package/.claude/skills/monodesign/reference/component-states.md +0 -274
  879. package/.claude/skills/monodesign/reference/component-system.md +0 -358
  880. package/.claude/skills/monodesign/reference/copy-formulas.md +0 -160
  881. package/.claude/skills/monodesign/reference/craft.md +0 -123
  882. package/.claude/skills/monodesign/reference/critique.md +0 -780
  883. package/.claude/skills/monodesign/reference/delight.md +0 -302
  884. package/.claude/skills/monodesign/reference/design-principles.md +0 -246
  885. package/.claude/skills/monodesign/reference/distill.md +0 -111
  886. package/.claude/skills/monodesign/reference/document.md +0 -429
  887. package/.claude/skills/monodesign/reference/extract.md +0 -69
  888. package/.claude/skills/monodesign/reference/harden.md +0 -347
  889. package/.claude/skills/monodesign/reference/heuristics-scoring.md +0 -234
  890. package/.claude/skills/monodesign/reference/hooks.md +0 -92
  891. package/.claude/skills/monodesign/reference/image-prompts.md +0 -130
  892. package/.claude/skills/monodesign/reference/init.md +0 -221
  893. package/.claude/skills/monodesign/reference/interaction-design.md +0 -189
  894. package/.claude/skills/monodesign/reference/ios.md +0 -45
  895. package/.claude/skills/monodesign/reference/layout.md +0 -185
  896. package/.claude/skills/monodesign/reference/live.md +0 -710
  897. package/.claude/skills/monodesign/reference/motion-design.md +0 -109
  898. package/.claude/skills/monodesign/reference/onboard.md +0 -234
  899. package/.claude/skills/monodesign/reference/optimize.md +0 -258
  900. package/.claude/skills/monodesign/reference/overdrive.md +0 -130
  901. package/.claude/skills/monodesign/reference/personas.md +0 -179
  902. package/.claude/skills/monodesign/reference/polish.md +0 -241
  903. package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +0 -108
  904. package/.claude/skills/monodesign/reference/product.md +0 -60
  905. package/.claude/skills/monodesign/reference/quieter.md +0 -99
  906. package/.claude/skills/monodesign/reference/responsive-design.md +0 -114
  907. package/.claude/skills/monodesign/reference/shape.md +0 -165
  908. package/.claude/skills/monodesign/reference/spatial-design.md +0 -100
  909. package/.claude/skills/monodesign/reference/teach.md +0 -10
  910. package/.claude/skills/monodesign/reference/token-architecture.md +0 -222
  911. package/.claude/skills/monodesign/reference/typeset.md +0 -301
  912. package/.claude/skills/monodesign/reference/typography.md +0 -159
  913. package/.claude/skills/monodesign/reference/ux-research.md +0 -143
  914. package/.claude/skills/monodesign/reference/ux-rules.md +0 -211
  915. package/.claude/skills/monodesign/reference/ux-writing.md +0 -107
  916. package/.claude/skills/monodesign/scripts/command-metadata.json +0 -94
  917. package/.claude/skills/monodesign/scripts/context-signals.mjs +0 -260
  918. package/.claude/skills/monodesign/scripts/context.mjs +0 -1065
  919. package/.claude/skills/monodesign/scripts/critique-storage.mjs +0 -416
  920. package/.claude/skills/monodesign/scripts/detect-csp.mjs +0 -193
  921. package/.claude/skills/monodesign/scripts/detect.mjs +0 -33
  922. package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +0 -1960
  923. package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +0 -321
  924. package/.claude/skills/monodesign/scripts/detector/design-system.mjs +0 -814
  925. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +0 -5628
  926. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns.mjs +0 -50
  927. package/.claude/skills/monodesign/scripts/detector/engines/browser/detect-url.mjs +0 -259
  928. package/.claude/skills/monodesign/scripts/detector/engines/browser/drivers.mjs +0 -339
  929. package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +0 -636
  930. package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +0 -1016
  931. package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +0 -253
  932. package/.claude/skills/monodesign/scripts/detector/engines/visual/screenshot-contrast.mjs +0 -198
  933. package/.claude/skills/monodesign/scripts/detector/findings.mjs +0 -12
  934. package/.claude/skills/monodesign/scripts/detector/fix/css-regions.mjs +0 -181
  935. package/.claude/skills/monodesign/scripts/detector/fix/fixers.mjs +0 -373
  936. package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +0 -426
  937. package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +0 -198
  938. package/.claude/skills/monodesign/scripts/detector/profile/profiler.mjs +0 -166
  939. package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +0 -563
  940. package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +0 -3024
  941. package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +0 -124
  942. package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +0 -101
  943. package/.claude/skills/monodesign/scripts/detector/shared/fonts.mjs +0 -30
  944. package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +0 -148
  945. package/.claude/skills/monodesign/scripts/detector/shared/page.mjs +0 -7
  946. package/.claude/skills/monodesign/scripts/hook-admin.mjs +0 -694
  947. package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +0 -516
  948. package/.claude/skills/monodesign/scripts/hook-lib.mjs +0 -1785
  949. package/.claude/skills/monodesign/scripts/hook.mjs +0 -61
  950. package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +0 -809
  951. package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +0 -69
  952. package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +0 -640
  953. package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +0 -129
  954. package/.claude/skills/monodesign/scripts/lib/provider.mjs +0 -4
  955. package/.claude/skills/monodesign/scripts/lib/target-args.mjs +0 -42
  956. package/.claude/skills/monodesign/scripts/live/browser-script-parts.mjs +0 -50
  957. package/.claude/skills/monodesign/scripts/live/completion.mjs +0 -19
  958. package/.claude/skills/monodesign/scripts/live/event-validation.mjs +0 -137
  959. package/.claude/skills/monodesign/scripts/live/insert-ui.mjs +0 -458
  960. package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +0 -939
  961. package/.claude/skills/monodesign/scripts/live/manual-edit-routes.mjs +0 -357
  962. package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +0 -152
  963. package/.claude/skills/monodesign/scripts/live/session-store.mjs +0 -293
  964. package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +0 -826
  965. package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +0 -279
  966. package/.claude/skills/monodesign/scripts/live/ui-core.mjs +0 -180
  967. package/.claude/skills/monodesign/scripts/live/vocabulary.mjs +0 -36
  968. package/.claude/skills/monodesign/scripts/live-accept.mjs +0 -812
  969. package/.claude/skills/monodesign/scripts/live-browser-dom.js +0 -147
  970. package/.claude/skills/monodesign/scripts/live-browser-session.js +0 -124
  971. package/.claude/skills/monodesign/scripts/live-browser.js +0 -11213
  972. package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +0 -1241
  973. package/.claude/skills/monodesign/scripts/live-complete.mjs +0 -75
  974. package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +0 -683
  975. package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +0 -51
  976. package/.claude/skills/monodesign/scripts/live-inject.mjs +0 -596
  977. package/.claude/skills/monodesign/scripts/live-insert.mjs +0 -272
  978. package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +0 -363
  979. package/.claude/skills/monodesign/scripts/live-poll.mjs +0 -384
  980. package/.claude/skills/monodesign/scripts/live-resume.mjs +0 -94
  981. package/.claude/skills/monodesign/scripts/live-server.mjs +0 -1210
  982. package/.claude/skills/monodesign/scripts/live-status.mjs +0 -61
  983. package/.claude/skills/monodesign/scripts/live-target.mjs +0 -30
  984. package/.claude/skills/monodesign/scripts/live-wrap.mjs +0 -884
  985. package/.claude/skills/monodesign/scripts/live.mjs +0 -297
  986. package/.claude/skills/monodesign/scripts/modern-screenshot.umd.js +0 -14
  987. package/.claude/skills/monodesign/scripts/palette.mjs +0 -635
  988. package/.claude/skills/monodesign/scripts/pin.mjs +0 -221
  989. package/.claude/skills/monodesign/shape.md +0 -71
  990. package/.claude/skills/monodesign/teach.md +0 -18
  991. package/.claude/skills/monodesign/typeset.md +0 -59
  992. package/dist/src/routing/jev-step.d.ts +0 -17
  993. package/dist/src/routing/jev-step.d.ts.map +0 -1
  994. package/dist/src/routing/jev-step.js +0 -27
  995. package/dist/src/routing/jev-step.js.map +0 -1
  996. package/org-skills/accessibility/LICENSE.txt +0 -21
  997. package/org-skills/accessibility/SKILL.md +0 -149
  998. package/org-skills/database-migration/LICENSE.txt +0 -21
  999. package/org-skills/database-migration/SKILL.md +0 -337
  1000. package/org-skills/database-migration/references/details.md +0 -76
  1001. package/org-skills/error-handling-patterns/LICENSE.txt +0 -21
  1002. package/org-skills/error-handling-patterns/SKILL.md +0 -126
  1003. package/org-skills/error-handling-patterns/references/details.md +0 -516
  1004. package/org-skills/internal-comms/LICENSE.txt +0 -202
  1005. package/org-skills/internal-comms/SKILL.md +0 -36
  1006. package/org-skills/internal-comms/examples/3p-updates.md +0 -47
  1007. package/org-skills/internal-comms/examples/company-newsletter.md +0 -65
  1008. package/org-skills/internal-comms/examples/faq-answers.md +0 -30
  1009. package/org-skills/internal-comms/examples/general-comms.md +0 -16
@@ -1,1785 +0,0 @@
1
- /**
2
- * Shared library for the Monodesign design hook.
3
- *
4
- * Pure-ish helpers split out from `hook.mjs` so unit tests can exercise
5
- * config parsing, finding filtering, dedup, render, and cache logic without
6
- * spawning a subprocess. `hook.mjs` itself is the thin stdin/stdout shim.
7
- *
8
- * Public surface (everything exported is part of the contract):
9
- * ENVELOPE_PREFIX, ALLOWED_EXTS, ACK_EXTS, SENSITIVE_PATH, GENERATED_PATH, TRUTHY
10
- * truthy(value)
11
- * readConfig(cwd) / DEFAULT_CONFIG / getConfigPath(cwd) / getLocalConfigPath(cwd)
12
- * resolveProjectPlatform(cwd) / isNativePlatform(platform)
13
- * normalizeIgnoreValue(value)
14
- * readCache(cwd) / persistCache(cwd, cache) / resolveCacheCwd(primaryFile, sessionCwd)
15
- * bumpEditCount(cache, sessionId, filePath) -> number
16
- * suppressionNotice(filePath)
17
- * filterFindings(findings, content, ext, config)
18
- * matchConfiguredExtension(filePath, extensions)
19
- * dedupeAgainstCache(findings, cache, sessionId, filePath)
20
- * renderTemplate(findings, filePath, config, opts)
21
- * renderCleanAck(filePath, opts) / renderPendingAck(filePath, known, opts)
22
- * shouldEmitAckForFile(filePath, config?)
23
- * writeAuditLog(env, entry)
24
- * loadDetector() -> Promise<{ detectText, detectHtml }>
25
- * matchesAnyGlob(filePath, globs)
26
- * normalizeScanTargets(primaryTargets, projectCwd)
27
- * runHook(deps) -> { exitCode, stdout, audit, reason? }
28
- *
29
- * Design notes:
30
- * - All errors are swallowed at the runHook seam. The detector throwing must
31
- * never break a turn. See PRD §5 "Failure modes".
32
- * - Cache shape is JSON-friendly; we gc the oldest sessions when there are
33
- * more than 8 to keep file size predictable across long-lived projects.
34
- * - The detector loader looks for `detector/detect-antipatterns.mjs` next to
35
- * this file first (built skill layout) and falls back to the repo root's
36
- * `cli/engine/detect-antipatterns.mjs` (running from source).
37
- */
38
-
39
- import fs from 'node:fs';
40
- import os from 'node:os';
41
- import path from 'node:path';
42
- import { createRequire } from 'node:module';
43
- import { pathToFileURL, fileURLToPath } from 'node:url';
44
- import { extractPlatform, loadContext } from './context.mjs';
45
- import { MONODESIGN_COMMAND } from './lib/provider.mjs';
46
-
47
- const __filename = fileURLToPath(import.meta.url);
48
- const __dirname = path.dirname(__filename);
49
-
50
- export const ENVELOPE_PREFIX = '[monodesign@1]';
51
-
52
- export const ALLOWED_EXTS = new Set([
53
- '.tsx', '.jsx', '.html', '.htm', '.vue', '.svelte', '.astro',
54
- '.css', '.scss', '.sass', '.less', '.ts', '.js',
55
- ]);
56
-
57
- export const ACK_EXTS = new Set([
58
- '.tsx', '.jsx', '.html', '.htm', '.vue', '.svelte', '.astro',
59
- '.css', '.scss', '.sass', '.less',
60
- ]);
61
-
62
- // Hard-skip regex for sensitive files. Cannot be turned off via config.
63
- // Match tokenized secret/credential filenames, not UI names such as
64
- // CredentialForm.tsx, SecretPage.jsx, or secretary-dashboard.vue.
65
- export const SENSITIVE_PATH = new RegExp([
66
- String.raw`(?:^|[/\\])\.env(?:\.|$)`,
67
- String.raw`(?:^|[/\\])\.git(?:[/\\]|$)`,
68
- String.raw`(?:^|[/\\])id_rsa(?:$|[._-])[^/\\]*$`,
69
- String.raw`(?:^|[/\\])[^/\\]*\.pem$`,
70
- String.raw`(?:^|[/\\])(?:[^/\\]*[._-])?(?:secret|secrets|credential|credentials)(?=[._-])[^/\\]*\.(?:json|ya?ml|toml|ini|conf|config|env|txt|key|cert|crt|pem|js|ts)$`,
71
- ].join('|'), 'i');
72
-
73
- // Hard-skip regex for generated, lock, minified, and build-output paths.
74
- export const GENERATED_PATH = /(?:\.generated\.[a-z]+$|\.d\.ts$|\.min\.[a-z]+$|[/\\]node_modules[/\\]|[/\\](?:dist|build|out|\.next|\.cache|coverage)[/\\]|[/\\]?[^/\\]+\.lock(?:\.json)?$)/i;
75
-
76
- // GENERATED_PATH checked against the path inside the project, so a project
77
- // that lives under e.g. ~/.cache/ or /srv/build/ is still scanned. Paths
78
- // outside the project root fall back to the absolute path.
79
- export function isGeneratedPath(filePath, projectRoot) {
80
- const rel = path.relative(path.resolve(projectRoot), path.resolve(filePath));
81
- const inside = rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
82
- return GENERATED_PATH.test(inside ? path.sep + rel : filePath);
83
- }
84
-
85
- export const TRUTHY = /^(1|true|yes|on)$/i;
86
-
87
- export const DEFAULT_CONFIG = Object.freeze({
88
- enabled: true,
89
- quiet: false,
90
- auditLog: null,
91
- designSystem: { enabled: true },
92
- ignoreRules: [],
93
- ignoreFiles: [],
94
- ignoreValues: [],
95
- extensions: [],
96
- limits: { maxFindings: 5, maxChars: 8000 },
97
- });
98
-
99
- export const HOOK_LOCAL_IGNORE_PATTERNS = Object.freeze([
100
- '.monodesign/hook.cache.json',
101
- '.monodesign/hook.pending.json',
102
- '.monodesign/config.local.json',
103
- ]);
104
-
105
- const HOOK_IGNORE_MARKER_OPEN = '# monodesign-hook-ignore-start';
106
- const HOOK_IGNORE_MARKER_CLOSE = '# monodesign-hook-ignore-end';
107
- const CACHE_MAX_SESSIONS = 8;
108
- export const EDIT_COUNT_THRESHOLD = 6;
109
-
110
- export function truthy(value) {
111
- return typeof value === 'string' && TRUTHY.test(value);
112
- }
113
-
114
- function depthIsSet(value) {
115
- if (value === undefined || value === null) return false;
116
- const text = String(value).trim();
117
- if (!text) return false;
118
- if (TRUTHY.test(text)) return true;
119
- return /^\d+$/.test(text) && Number(text) > 0;
120
- }
121
-
122
- function safeReadJson(filePath) {
123
- try {
124
- return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
125
- } catch {
126
- return null;
127
- }
128
- }
129
-
130
- export function getConfigPath(cwd) {
131
- return path.join(cwd, '.monodesign', 'config.json');
132
- }
133
-
134
- export function getLocalConfigPath(cwd) {
135
- return path.join(cwd, '.monodesign', 'config.local.json');
136
- }
137
-
138
- export function getCachePath(cwd) {
139
- return path.join(cwd, '.monodesign', 'hook.cache.json');
140
- }
141
-
142
- export function getPendingPath(cwd) {
143
- return path.join(cwd, '.monodesign', 'hook.pending.json');
144
- }
145
-
146
- export function resolveProjectCwd(event, fallback = process.cwd()) {
147
- return event?.cwd
148
- || (Array.isArray(event?.workspace_roots) && event.workspace_roots[0])
149
- || envProjectDir(fallback)
150
- || fallback;
151
- }
152
-
153
- function looksLikeProjectRoot(dir) {
154
- return ['.git', 'package.json', '.monodesign'].some((marker) => {
155
- try { return fs.existsSync(path.join(dir, marker)); } catch { return false; }
156
- });
157
- }
158
-
159
- // Where `.monodesign/` (cache + config) lives for this event. Normally the
160
- // session cwd, untouched. But when the agent was launched from an umbrella
161
- // directory that is not itself a project (no .git, package.json, or
162
- // .monodesign), key to the edited file's nearest project root instead, so a
163
- // multi-project launch dir doesn't accumulate a shared cross-project cache
164
- // (issue #305). Climbing stops at the home dir, falling back to the session
165
- // cwd when no marker is found.
166
- export function resolveCacheCwd(primaryFile, sessionCwd) {
167
- const base = path.resolve(sessionCwd || process.cwd());
168
- if (!primaryFile || typeof primaryFile !== 'string' || hasPathTraversal(primaryFile)) return base;
169
- if (looksLikeProjectRoot(base)) return base;
170
- let dir;
171
- try {
172
- dir = path.dirname(path.resolve(primaryFile));
173
- } catch {
174
- return base;
175
- }
176
- const home = path.resolve(os.homedir());
177
- while (true) {
178
- if (dir === home) return base;
179
- if (looksLikeProjectRoot(dir)) return dir;
180
- const parent = path.dirname(dir);
181
- if (parent === dir) return base;
182
- dir = parent;
183
- }
184
- }
185
-
186
- // The detector's rules are web rules (HTML/CSS shapes), but a React Native or
187
- // Flutter project is made of the exact extensions the hook watches (.tsx, .ts,
188
- // .js), so without this gate every native screen edit would draw web-shaped
189
- // findings that contradict the native platform references. PRODUCT.md's
190
- // `## Platform` field decides: `ios` / `android` / `adaptive` projects skip
191
- // the scan entirely. Resolution goes through loadContext so the hook reads the
192
- // same PRODUCT.md the skill does (alternate context dirs, monorepo fallback).
193
- export function resolveProjectPlatform(cwd) {
194
- try {
195
- const ctx = loadContext(cwd);
196
- return extractPlatform(ctx?.product);
197
- } catch {
198
- return null;
199
- }
200
- }
201
-
202
- export function isNativePlatform(platform) {
203
- return platform === 'ios' || platform === 'android' || platform === 'adaptive';
204
- }
205
-
206
- export function readConfig(cwd) {
207
- const config = cloneDefaultConfig();
208
- // Hook runtime settings live under `hook`; detector filters live under
209
- // `detector`. Back-compat: older configs stored detector filters in `hook`,
210
- // so read those first and let canonical `detector` settings win.
211
- for (const filePath of [getConfigPath(cwd), getLocalConfigPath(cwd)]) {
212
- const raw = safeReadJson(filePath);
213
- applyConfigSource(config, hookSection(raw));
214
- applyDetectorConfigSource(config, detectorSection(raw));
215
- }
216
- return config;
217
- }
218
-
219
- // The hook settings subtree of a unified config.json / config.local.json.
220
- function hookSection(raw) {
221
- if (!raw || typeof raw !== 'object') return null;
222
- return raw.hook && typeof raw.hook === 'object' && !Array.isArray(raw.hook) ? raw.hook : null;
223
- }
224
-
225
- function detectorSection(raw) {
226
- if (!raw || typeof raw !== 'object') return null;
227
- return raw.detector && typeof raw.detector === 'object' && !Array.isArray(raw.detector) ? raw.detector : null;
228
- }
229
-
230
- function numberOr(value, fallback) {
231
- return Number.isFinite(value) && value > 0 ? value : fallback;
232
- }
233
-
234
- function cloneDefaultConfig() {
235
- return {
236
- ...DEFAULT_CONFIG,
237
- ignoreRules: [],
238
- ignoreFiles: [],
239
- ignoreValues: [],
240
- extensions: [],
241
- designSystem: { ...DEFAULT_CONFIG.designSystem },
242
- limits: { ...DEFAULT_CONFIG.limits },
243
- };
244
- }
245
-
246
- function applyDetectorConfigSource(config, raw) {
247
- if (!raw || typeof raw !== 'object') return config;
248
- if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
249
- config.designSystem = {
250
- ...config.designSystem,
251
- enabled: raw.designSystem.enabled !== false,
252
- };
253
- }
254
- if (Array.isArray(raw.ignoreRules)) {
255
- config.ignoreRules = uniqueStrings([...config.ignoreRules, ...raw.ignoreRules]);
256
- }
257
- if (Array.isArray(raw.ignoreFiles)) {
258
- config.ignoreFiles = uniqueStrings([...config.ignoreFiles, ...raw.ignoreFiles]);
259
- }
260
- if (Array.isArray(raw.ignoreValues)) {
261
- config.ignoreValues = mergeIgnoreValues(config.ignoreValues, raw.ignoreValues);
262
- }
263
- if (Array.isArray(raw.extensions)) {
264
- config.extensions = mergeExtensions(config.extensions, raw.extensions);
265
- }
266
- return config;
267
- }
268
-
269
- // Extra scanned extensions from `detector.extensions` config. Entries are
270
- // `{ ext, engine }` (engine 'html' | 'text', default 'html' — the common case
271
- // for server-side templates) or bare strings as shorthand. Extensions are
272
- // matched against the end of the filename, not path.extname, so double
273
- // extensions like `.blade.php` and `.html.erb` work (issue #316).
274
- function normalizeExtensionEntries(entries) {
275
- if (!Array.isArray(entries)) return [];
276
- const out = [];
277
- for (const entry of entries) {
278
- const raw = typeof entry === 'string' ? entry : entry?.ext;
279
- if (typeof raw !== 'string') continue;
280
- let ext = raw.trim().toLowerCase();
281
- if (!ext) continue;
282
- if (!ext.startsWith('.')) ext = `.${ext}`;
283
- const engine = (!(typeof entry === 'string') && entry?.engine === 'text') ? 'text' : 'html';
284
- out.push({ ext, engine });
285
- }
286
- return out;
287
- }
288
-
289
- function mergeExtensions(existing, incoming) {
290
- const map = new Map();
291
- for (const entry of normalizeExtensionEntries(existing)) map.set(entry.ext, entry);
292
- for (const entry of normalizeExtensionEntries(incoming)) map.set(entry.ext, entry);
293
- return Array.from(map.values());
294
- }
295
-
296
- export function matchConfiguredExtension(filePath, extensions) {
297
- if (!Array.isArray(extensions) || extensions.length === 0) return null;
298
- const name = path.basename(String(filePath || '')).toLowerCase();
299
- if (!name) return null;
300
- // The longest matching suffix wins, so `.blade.php` beats a broader `.php`
301
- // entry regardless of config order.
302
- let best = null;
303
- for (const entry of normalizeExtensionEntries(extensions)) {
304
- if (name.length > entry.ext.length && name.endsWith(entry.ext)
305
- && (!best || entry.ext.length > best.ext.length)) {
306
- best = entry;
307
- }
308
- }
309
- return best;
310
- }
311
-
312
- function applyConfigSource(config, raw) {
313
- if (!raw || typeof raw !== 'object') return config;
314
- if (Object.hasOwn(raw, 'enabled')) {
315
- config.enabled = raw.enabled !== false;
316
- }
317
- if (Object.hasOwn(raw, 'quiet')) {
318
- config.quiet = raw.quiet === true;
319
- }
320
- if (typeof raw.auditLog === 'string' && raw.auditLog.trim()) {
321
- config.auditLog = raw.auditLog.trim();
322
- }
323
- applyDetectorConfigSource(config, raw);
324
- if (raw.limits && typeof raw.limits === 'object') {
325
- config.limits = {
326
- maxFindings: numberOr(raw.limits.maxFindings, config.limits.maxFindings),
327
- maxChars: numberOr(raw.limits.maxChars, config.limits.maxChars),
328
- };
329
- }
330
- return config;
331
- }
332
-
333
- function uniqueStrings(values) {
334
- return Array.from(new Set(values.map(String)));
335
- }
336
-
337
- export function normalizeIgnoreValue(value) {
338
- return String(value || '')
339
- .trim()
340
- .replace(/^["']|["']$/g, '')
341
- .replace(/\+/g, ' ')
342
- .replace(/\s+/g, ' ')
343
- .toLowerCase();
344
- }
345
-
346
- function normalizeIgnoreRule(rule) {
347
- return String(rule || '').trim().toLowerCase();
348
- }
349
-
350
- function colorIgnoreKey(value) {
351
- const color = parseIgnoreColor(value);
352
- if (!color) return '';
353
- return `${color.r},${color.g},${color.b},${Math.round(color.a * 255)}`;
354
- }
355
-
356
- function parseIgnoreColor(value) {
357
- const text = String(value || '').trim().toLowerCase();
358
- if (!text) return null;
359
-
360
- const hex = text.match(/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i);
361
- if (hex) return parseHexIgnoreColor(hex[1]);
362
-
363
- const rgb = text.match(/^rgba?\((.*)\)$/i);
364
- if (rgb) {
365
- const parts = splitColorArgs(rgb[1]);
366
- if (parts.length < 3 || parts.length > 4) return null;
367
- const r = parseRgbChannel(parts[0]);
368
- const g = parseRgbChannel(parts[1]);
369
- const b = parseRgbChannel(parts[2]);
370
- const a = parts[3] === undefined ? 1 : parseAlphaChannel(parts[3]);
371
- if ([r, g, b, a].some((v) => v === null)) return null;
372
- return { r, g, b, a };
373
- }
374
-
375
- const hsl = text.match(/^hsla?\((.*)\)$/i);
376
- if (hsl) {
377
- const parts = splitColorArgs(hsl[1]);
378
- if (parts.length < 3 || parts.length > 4) return null;
379
- const h = parseHueChannel(parts[0]);
380
- const s = parsePercentChannel(parts[1]);
381
- const l = parsePercentChannel(parts[2]);
382
- const a = parts[3] === undefined ? 1 : parseAlphaChannel(parts[3]);
383
- if ([h, s, l, a].some((v) => v === null)) return null;
384
- return hslToRgb(h, s, l, a);
385
- }
386
-
387
- return null;
388
- }
389
-
390
- function parseHexIgnoreColor(hex) {
391
- if (hex.length === 3 || hex.length === 4) {
392
- const r = parseInt(hex[0] + hex[0], 16);
393
- const g = parseInt(hex[1] + hex[1], 16);
394
- const b = parseInt(hex[2] + hex[2], 16);
395
- const a = hex.length === 4 ? parseInt(hex[3] + hex[3], 16) / 255 : 1;
396
- return { r, g, b, a };
397
- }
398
- const r = parseInt(hex.slice(0, 2), 16);
399
- const g = parseInt(hex.slice(2, 4), 16);
400
- const b = parseInt(hex.slice(4, 6), 16);
401
- const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
402
- return { r, g, b, a };
403
- }
404
-
405
- function splitColorArgs(body) {
406
- const text = String(body || '').trim();
407
- if (!text) return [];
408
- if (text.includes(',')) {
409
- const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
410
- const last = parts[parts.length - 1];
411
- if (last?.includes('/')) {
412
- const split = last.split('/').map((part) => part.trim()).filter(Boolean);
413
- return [...parts.slice(0, -1), ...split];
414
- }
415
- return parts;
416
- }
417
- return text.replace(/\s*\/\s*/g, ' / ').split(/\s+/).filter((part) => part && part !== '/');
418
- }
419
-
420
- function parseRgbChannel(raw) {
421
- const text = String(raw || '').trim();
422
- const match = text.match(/^(-?\d*\.?\d+)(%)?$/);
423
- if (!match) return null;
424
- const value = Number.parseFloat(match[1]);
425
- if (!Number.isFinite(value)) return null;
426
- const scaled = match[2] ? value * 2.55 : value;
427
- if (scaled < 0 || scaled > 255) return null;
428
- return Math.round(scaled);
429
- }
430
-
431
- function parseAlphaChannel(raw) {
432
- const text = String(raw || '').trim();
433
- const match = text.match(/^(-?\d*\.?\d+)(%)?$/);
434
- if (!match) return null;
435
- const value = Number.parseFloat(match[1]);
436
- if (!Number.isFinite(value)) return null;
437
- const alpha = match[2] ? value / 100 : value;
438
- return alpha >= 0 && alpha <= 1 ? alpha : null;
439
- }
440
-
441
- function parseHueChannel(raw) {
442
- const text = String(raw || '').trim();
443
- const match = text.match(/^(-?\d*\.?\d+)(deg|rad|turn|grad)?$/);
444
- if (!match) return null;
445
- const value = Number.parseFloat(match[1]);
446
- if (!Number.isFinite(value)) return null;
447
- const unit = match[2] || 'deg';
448
- if (unit === 'turn') return value * 360;
449
- if (unit === 'rad') return value * (180 / Math.PI);
450
- if (unit === 'grad') return value * 0.9;
451
- return value;
452
- }
453
-
454
- function parsePercentChannel(raw) {
455
- const text = String(raw || '').trim();
456
- const match = text.match(/^(-?\d*\.?\d+)%$/);
457
- if (!match) return null;
458
- const value = Number.parseFloat(match[1]);
459
- if (!Number.isFinite(value)) return null;
460
- return value >= 0 && value <= 100 ? value / 100 : null;
461
- }
462
-
463
- function hslToRgb(hue, saturation, lightness, alpha) {
464
- const h = (((hue % 360) + 360) % 360) / 360;
465
- if (saturation === 0) {
466
- const gray = clampByte(Math.round(lightness * 255));
467
- return { r: gray, g: gray, b: gray, a: alpha };
468
- }
469
- const q = lightness < 0.5
470
- ? lightness * (1 + saturation)
471
- : lightness + saturation - lightness * saturation;
472
- const p = 2 * lightness - q;
473
- const toRgb = (t) => {
474
- let channel = t;
475
- if (channel < 0) channel += 1;
476
- if (channel > 1) channel -= 1;
477
- if (channel < 1 / 6) return p + (q - p) * 6 * channel;
478
- if (channel < 1 / 2) return q;
479
- if (channel < 2 / 3) return p + (q - p) * (2 / 3 - channel) * 6;
480
- return p;
481
- };
482
- return {
483
- r: clampByte(Math.round(toRgb(h + 1 / 3) * 255)),
484
- g: clampByte(Math.round(toRgb(h) * 255)),
485
- b: clampByte(Math.round(toRgb(h - 1 / 3) * 255)),
486
- a: alpha,
487
- };
488
- }
489
-
490
- function clampByte(value) {
491
- return Math.min(255, Math.max(0, value));
492
- }
493
-
494
- function ignoreValueMatches(rule, entryValue, findingValue) {
495
- if (entryValue === findingValue) return true;
496
- if (rule !== 'design-system-color') return false;
497
- const entryColor = colorIgnoreKey(entryValue);
498
- return Boolean(entryColor && entryColor === colorIgnoreKey(findingValue));
499
- }
500
-
501
- export function normalizeIgnoreValueEntries(entries) {
502
- if (!Array.isArray(entries)) return [];
503
- const out = [];
504
- for (const entry of entries) {
505
- if (!entry || typeof entry !== 'object') continue;
506
- const rule = normalizeIgnoreRule(entry.rule);
507
- const value = normalizeIgnoreValue(entry.value);
508
- if (!rule || !value) continue;
509
- const normalized = { rule, value };
510
- const files = uniqueStrings([
511
- ...(typeof entry.file === 'string' && entry.file.trim() ? [entry.file.trim()] : []),
512
- ...(Array.isArray(entry.files) ? entry.files.filter(v => typeof v === 'string' && v.trim()).map(v => v.trim()) : []),
513
- ]);
514
- if (files.length > 0) normalized.files = files;
515
- if (typeof entry.reason === 'string' && entry.reason.trim()) {
516
- normalized.reason = entry.reason.trim();
517
- }
518
- if (typeof entry.createdAt === 'string' && entry.createdAt.trim()) {
519
- normalized.createdAt = entry.createdAt.trim();
520
- }
521
- out.push(normalized);
522
- }
523
- return out;
524
- }
525
-
526
- function mergeIgnoreValues(existing, incoming) {
527
- const map = new Map();
528
- for (const entry of normalizeIgnoreValueEntries(existing)) {
529
- map.set(`${entry.rule}\0${entry.value}\0${ignoreValueFilesKey(entry.files)}`, entry);
530
- }
531
- for (const entry of normalizeIgnoreValueEntries(incoming)) {
532
- map.set(`${entry.rule}\0${entry.value}\0${ignoreValueFilesKey(entry.files)}`, entry);
533
- }
534
- return Array.from(map.values());
535
- }
536
-
537
- function ignoreValueFilesKey(files) {
538
- return Array.isArray(files) && files.length > 0 ? files.join('\x1f') : '';
539
- }
540
-
541
- export function readCache(cwd) {
542
- const raw = safeReadJson(getCachePath(cwd));
543
- if (!raw || typeof raw !== 'object' || raw.version !== 1) {
544
- return { version: 1, sessions: {} };
545
- }
546
- return {
547
- version: 1,
548
- sessions: raw.sessions && typeof raw.sessions === 'object' ? raw.sessions : {},
549
- };
550
- }
551
-
552
- export function persistCache(cwd, cache) {
553
- const sessions = cache.sessions || {};
554
- const ids = Object.keys(sessions);
555
- if (ids.length > CACHE_MAX_SESSIONS) {
556
- // Garbage-collect oldest sessions by updatedAt.
557
- const ordered = ids
558
- .map((id) => [id, sessions[id]?.updatedAt || 0])
559
- .sort((a, b) => b[1] - a[1])
560
- .slice(0, CACHE_MAX_SESSIONS);
561
- const next = {};
562
- for (const [id] of ordered) next[id] = sessions[id];
563
- cache = { ...cache, sessions: next };
564
- }
565
- const target = getCachePath(cwd);
566
- try {
567
- ensureHookGitExcludes(cwd);
568
- fs.mkdirSync(path.dirname(target), { recursive: true });
569
- fs.writeFileSync(target, JSON.stringify(cache));
570
- return true;
571
- } catch {
572
- return false;
573
- }
574
- }
575
-
576
- export function ensureHookGitExcludes(cwd = process.cwd()) {
577
- try {
578
- const target = resolveHookGitExcludeTarget(cwd);
579
- if (!target) {
580
- return { mode: 'none', changed: false, patterns: [...HOOK_LOCAL_IGNORE_PATTERNS] };
581
- }
582
-
583
- const patterns = target.patternPrefix
584
- ? HOOK_LOCAL_IGNORE_PATTERNS.map((pattern) => `${target.patternPrefix}/${pattern}`)
585
- : [...HOOK_LOCAL_IGNORE_PATTERNS];
586
- const markerSuffix = target.patternPrefix || '.';
587
- const markerOpen = `${HOOK_IGNORE_MARKER_OPEN} ${markerSuffix}`;
588
- const markerClose = `${HOOK_IGNORE_MARKER_CLOSE} ${markerSuffix}`;
589
- const existing = fs.existsSync(target.path) ? fs.readFileSync(target.path, 'utf-8') : '';
590
- const block = [markerOpen, ...patterns, markerClose].join('\n');
591
- const markerRe = new RegExp(`${escapeRegExp(markerOpen)}[\\s\\S]*?${escapeRegExp(markerClose)}`);
592
-
593
- let updated;
594
- if (markerRe.test(existing)) {
595
- updated = existing.replace(markerRe, block);
596
- } else {
597
- const prefix = existing.length === 0 ? '' : existing.endsWith('\n') ? existing : `${existing}\n`;
598
- updated = `${prefix}${prefix.endsWith('\n\n') || prefix === '' ? '' : '\n'}${block}\n`;
599
- }
600
-
601
- if (updated !== existing) {
602
- fs.mkdirSync(path.dirname(target.path), { recursive: true });
603
- fs.writeFileSync(target.path, updated, 'utf-8');
604
- }
605
-
606
- return {
607
- mode: 'git-info-exclude',
608
- file: path.relative(path.resolve(cwd), target.path).split(path.sep).join('/'),
609
- changed: updated !== existing,
610
- patterns,
611
- };
612
- } catch {
613
- return { mode: 'error', changed: false, patterns: [...HOOK_LOCAL_IGNORE_PATTERNS] };
614
- }
615
- }
616
-
617
- function resolveHookGitExcludeTarget(cwd) {
618
- const start = path.resolve(cwd);
619
- let dir = start;
620
- while (true) {
621
- const dotGit = path.join(dir, '.git');
622
- if (fs.existsSync(dotGit)) {
623
- const gitDir = resolveGitDir(dotGit, dir);
624
- if (!gitDir) return null;
625
- const relPrefix = path.relative(dir, start).split(path.sep).join('/');
626
- return {
627
- path: path.join(gitDir, 'info', 'exclude'),
628
- patternPrefix: relPrefix && relPrefix !== '.' ? relPrefix : '',
629
- };
630
- }
631
- const parent = path.dirname(dir);
632
- if (parent === dir) return null;
633
- dir = parent;
634
- }
635
- }
636
-
637
- function resolveGitDir(dotGit, worktreeDir) {
638
- const stat = fs.statSync(dotGit);
639
- if (stat.isDirectory()) return dotGit;
640
- if (!stat.isFile()) return null;
641
-
642
- const body = fs.readFileSync(dotGit, 'utf-8').trim();
643
- const match = body.match(/^gitdir:\s*(.+)$/i);
644
- if (!match) return null;
645
- return path.isAbsolute(match[1]) ? match[1] : path.resolve(worktreeDir, match[1]);
646
- }
647
-
648
- function escapeRegExp(value) {
649
- return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
650
- }
651
-
652
- function ensureSession(cache, sessionId) {
653
- if (!cache.sessions[sessionId]) {
654
- cache.sessions[sessionId] = { updatedAt: Date.now(), files: {} };
655
- }
656
- return cache.sessions[sessionId];
657
- }
658
-
659
- function ensureFile(cache, sessionId, filePath) {
660
- const session = ensureSession(cache, sessionId);
661
- if (!session.files[filePath]) {
662
- session.files[filePath] = { editCount: 0, findings: [] };
663
- }
664
- return session.files[filePath];
665
- }
666
-
667
- export function bumpEditCount(cache, sessionId, filePath) {
668
- const fileEntry = ensureFile(cache, sessionId, filePath);
669
- fileEntry.editCount = (fileEntry.editCount || 0) + 1;
670
- ensureSession(cache, sessionId).updatedAt = Date.now();
671
- return fileEntry.editCount;
672
- }
673
-
674
- export function suppressionNotice(filePath) {
675
- return `${ENVELOPE_PREFIX} Suppressing further design hints on ${filePath}. More than ${EDIT_COUNT_THRESHOLD} edits in this session reached. Run ${MONODESIGN_COMMAND} audit to revisit.`;
676
- }
677
-
678
- // Glob → RegExp. Supports `**`, `*`, `?`, and `{a,b}` alternation.
679
- function globToRegex(glob) {
680
- let re = '^';
681
- let i = 0;
682
- while (i < glob.length) {
683
- const c = glob[i];
684
- if (c === '*') {
685
- if (glob[i + 1] === '*') {
686
- re += '.*';
687
- i += 2;
688
- if (glob[i] === '/') i += 1;
689
- } else {
690
- re += '[^/]*';
691
- i += 1;
692
- }
693
- } else if (c === '?') {
694
- re += '[^/]';
695
- i += 1;
696
- } else if (c === '{') {
697
- const end = glob.indexOf('}', i);
698
- if (end === -1) { re += '\\{'; i += 1; continue; }
699
- const parts = glob.slice(i + 1, end).split(',').map((p) => p.replace(/[.+^$()|[\]\\]/g, '\\$&'));
700
- re += `(?:${parts.join('|')})`;
701
- i = end + 1;
702
- } else if (/[.+^$()|[\]\\]/.test(c)) {
703
- re += `\\${c}`;
704
- i += 1;
705
- } else {
706
- re += c;
707
- i += 1;
708
- }
709
- }
710
- re += '$';
711
- return new RegExp(re);
712
- }
713
-
714
- export function matchesAnyGlob(filePath, globs) {
715
- if (!Array.isArray(globs) || globs.length === 0) return false;
716
- const normalized = filePath.split(path.sep).join('/');
717
- for (const glob of globs) {
718
- try {
719
- const re = globToRegex(String(glob));
720
- if (re.test(normalized)) return true;
721
- // Match against basename too for convenience: `*.generated.tsx` should
722
- // catch `src/foo.generated.tsx` without requiring `**/`.
723
- const base = normalized.split('/').pop();
724
- if (re.test(base)) return true;
725
- } catch {
726
- /* malformed glob, skip */
727
- }
728
- }
729
- return false;
730
- }
731
-
732
- export function filterFindings(findings, _content, _ext, config) {
733
- if (!Array.isArray(findings) || findings.length === 0) return [];
734
- const ignoreRules = new Set((config.ignoreRules || []).map((rule) => normalizeIgnoreRule(rule)));
735
- const ignoreValues = normalizeIgnoreValueEntries(config.ignoreValues || []);
736
- return findings.filter((f) => {
737
- if (!f || typeof f !== 'object') return false;
738
- if (ignoreRules.has(normalizeIgnoreRule(f.antipattern))) return false;
739
- if (isIgnoredFindingValue(f, ignoreValues)) return false;
740
- return true;
741
- });
742
- }
743
-
744
- function isIgnoredFindingValue(finding, ignoreValues) {
745
- if (!Array.isArray(ignoreValues) || ignoreValues.length === 0) return false;
746
- const rule = normalizeIgnoreRule(finding.antipattern);
747
- if (!rule) return false;
748
- // File-scoped wildcards suppress rules with no extractable value, such as side-tab.
749
- const value = extractFindingIgnoreValue(finding);
750
- return ignoreValues.some((entry) => {
751
- if (entry.rule !== rule) return false;
752
- const wildcardValue = entry.value === '*';
753
- if (!wildcardValue && (!value || !ignoreValueMatches(rule, entry.value, value))) return false;
754
- if (!Array.isArray(entry.files) || entry.files.length === 0) return !wildcardValue;
755
- return findingMatchesScopedIgnoreFile(finding, entry.files);
756
- });
757
- }
758
-
759
- function findingMatchesScopedIgnoreFile(finding, globs) {
760
- const filePath = String(finding?.file || '').trim();
761
- if (!filePath) return false;
762
- if (matchesAnyGlob(filePath, globs)) return true;
763
-
764
- const normalized = filePath.split(path.sep).join('/');
765
- const parts = normalized.split('/').filter(Boolean);
766
- for (let i = 0; i < parts.length; i++) {
767
- const suffix = parts.slice(i).join('/');
768
- if (matchesAnyGlob(suffix, globs)) return true;
769
- }
770
- return false;
771
- }
772
-
773
- export function extractFindingIgnoreValue(finding) {
774
- if (!finding || typeof finding !== 'object') return '';
775
- const rule = normalizeIgnoreRule(finding.antipattern);
776
- const directValueRules = new Set([
777
- 'overused-font',
778
- 'bounce-easing',
779
- 'design-system-font',
780
- 'design-system-color',
781
- 'design-system-radius',
782
- ]);
783
- if (!directValueRules.has(rule)) return '';
784
- return normalizeIgnoreValue(extractFindingIgnoreValueRaw(finding, rule));
785
- }
786
-
787
- function extractFindingIgnoreValueRaw(finding, rule = normalizeIgnoreRule(finding?.antipattern)) {
788
- const direct = cleanIgnoreValueDisplay(finding.ignoreValue || finding.value || '');
789
- if (direct) return direct;
790
-
791
- const candidates = [finding.detail, finding.snippet].filter((v) => typeof v === 'string' && v);
792
- for (const text of candidates) {
793
- if (rule === 'bounce-easing') {
794
- const motion = extractMotionIgnoreValue(text);
795
- if (motion) return motion;
796
- continue;
797
- }
798
-
799
- const primary = text.match(/Primary font:\s*([^()\n;]+)/i);
800
- if (primary) return cleanIgnoreValueDisplay(primary[1]);
801
-
802
- const family = text.match(/font-family\s*:\s*["']?([^'",;\n]+)/i);
803
- if (family) return cleanIgnoreValueDisplay(family[1]);
804
-
805
- const google = text.match(/[?&]family=([^&:;\n]+)/i);
806
- if (google) {
807
- try {
808
- return cleanIgnoreValueDisplay(decodeURIComponent(google[1]));
809
- } catch {
810
- return cleanIgnoreValueDisplay(google[1]);
811
- }
812
- }
813
- }
814
-
815
- return '';
816
- }
817
-
818
- function extractMotionIgnoreValue(text) {
819
- const tailwind = text.match(/\banimate-bounce\b/i);
820
- if (tailwind) return cleanIgnoreValueDisplay(tailwind[0]);
821
-
822
- const bezier = text.match(/cubic-bezier\([^)]+\)/i);
823
- if (bezier) return cleanIgnoreValueDisplay(bezier[0]);
824
-
825
- const animation = text.match(/animation(?:-name)?\s*:\s*([^;\n]+)/i);
826
- if (animation) {
827
- const token = animation[1]
828
- .split(/[,\s]+/)
829
- .find((part) => /bounce|elastic|wobble|jiggle|spring/i.test(part));
830
- if (token) return cleanIgnoreValueDisplay(token);
831
- }
832
-
833
- return '';
834
- }
835
-
836
- function cleanIgnoreValueDisplay(value) {
837
- return String(value || '')
838
- .trim()
839
- .replace(/^["']|["']$/g, '')
840
- .replace(/\+/g, ' ')
841
- .replace(/\s+/g, ' ');
842
- }
843
-
844
- export function dedupeAgainstCache(findings, cache, sessionId, filePath) {
845
- if (!Array.isArray(findings) || findings.length === 0) return [];
846
- const fileEntry = ensureFile(cache, sessionId, filePath);
847
- const known = new Set(fileEntry.findings || []);
848
- const fresh = [];
849
- for (const f of findings) {
850
- const key = findingCacheKey(f);
851
- if (known.has(key)) continue;
852
- known.add(key);
853
- fresh.push(f);
854
- }
855
- return fresh;
856
- }
857
-
858
- export function rememberFindings(cache, sessionId, filePath, findings) {
859
- const fileEntry = ensureFile(cache, sessionId, filePath);
860
- const known = new Set(fileEntry.findings || []);
861
- for (const f of findings) known.add(findingCacheKey(f));
862
- fileEntry.findings = Array.from(known);
863
- ensureSession(cache, sessionId).updatedAt = Date.now();
864
- }
865
-
866
- function findingCacheKey(finding) {
867
- const line = finding?.line || 0;
868
- const value = extractFindingIgnoreValue(finding);
869
- if (line > 0 && value) return `${finding.antipattern}:${line}:${value}`;
870
- if (line > 0) return `${finding.antipattern}:${line}`;
871
- if (value) return `${finding.antipattern}:0:${value}`;
872
- const snippet = String(finding?.snippet || '').trim().slice(0, 80);
873
- return snippet ? `${finding.antipattern}:0:${snippet}` : `${finding.antipattern}:0`;
874
- }
875
-
876
- export function renderTemplate(findings, filePath, config, opts = {}) {
877
- if (!Array.isArray(findings) || findings.length === 0) return '';
878
- const limits = config?.limits || DEFAULT_CONFIG.limits;
879
- const cap = Math.max(1, limits.maxFindings || DEFAULT_CONFIG.limits.maxFindings);
880
- const maxChars = Math.max(500, limits.maxChars || DEFAULT_CONFIG.limits.maxChars);
881
-
882
- const cwd = opts.cwd || process.cwd();
883
- const display = relativize(filePath, cwd);
884
- const total = findings.length;
885
- const shown = findings.slice(0, cap);
886
- const remaining = total - shown.length;
887
-
888
- const header = `${ENVELOPE_PREFIX} Design hook findings requiring review in ${display} (${total} issue(s)):`;
889
- const lines = shown.map((f) => formatFindingLine(f));
890
- const more = remaining > 0
891
- ? `... and ${remaining} more (see ${MONODESIGN_COMMAND} audit).`
892
- : null;
893
- const footer = directiveFooter(display);
894
-
895
- const blocks = [header, ...lines];
896
- if (more) blocks.push(more);
897
- blocks.push('');
898
- blocks.push(footer);
899
- let text = blocks.join('\n');
900
-
901
- if (text.length > maxChars) {
902
- text = clampToBudget(header, lines, more, footer, maxChars);
903
- }
904
- return text;
905
- }
906
-
907
- function renderGroupedTemplate(groups, config, opts = {}) {
908
- const realGroups = groups.filter((group) => Array.isArray(group.findings) && group.findings.length > 0);
909
- if (realGroups.length === 0) return '';
910
- if (realGroups.length === 1) {
911
- const [group] = realGroups;
912
- return renderTemplate(group.findings, group.filePath, config, opts);
913
- }
914
-
915
- const limits = config?.limits || DEFAULT_CONFIG.limits;
916
- const cap = Math.max(1, limits.maxFindings || DEFAULT_CONFIG.limits.maxFindings);
917
- const maxChars = Math.max(500, limits.maxChars || DEFAULT_CONFIG.limits.maxChars);
918
- const cwd = opts.cwd || process.cwd();
919
- const total = realGroups.reduce((sum, group) => sum + group.findings.length, 0);
920
- const header = `${ENVELOPE_PREFIX} Design hook findings requiring review across ${realGroups.length} files (${total} issue(s)):`;
921
- const lines = [];
922
- let shownCount = 0;
923
-
924
- for (const group of realGroups) {
925
- const display = relativize(group.filePath, cwd);
926
- lines.push(`${display} (${group.findings.length} issue(s)):`);
927
- const remainingCap = Math.max(0, cap - shownCount);
928
- const shown = group.findings.slice(0, remainingCap);
929
- for (const finding of shown) {
930
- lines.push(formatFindingLine(finding));
931
- }
932
- shownCount += shown.length;
933
- const hidden = group.findings.length - shown.length;
934
- if (hidden > 0) {
935
- lines.push(`- ... ${hidden} more in ${display} (see ${MONODESIGN_COMMAND} audit).`);
936
- }
937
- }
938
-
939
- const footer = directiveFooter('the affected files', { grouped: true });
940
- let text = [header, ...lines, '', footer].join('\n');
941
- if (text.length > maxChars) {
942
- text = clampGroupedToBudget(header, lines, footer, maxChars);
943
- }
944
- return text;
945
- }
946
-
947
- function clampGroupedToBudget(header, lines, footer, maxChars) {
948
- const assemble = (linesArr, omitted) => [
949
- header,
950
- ...linesArr,
951
- ...(omitted ? [`... and more (see ${MONODESIGN_COMMAND} audit).`] : []),
952
- '',
953
- footer,
954
- ].join('\n');
955
-
956
- const working = lines.slice();
957
- let omitted = false;
958
- let assembled = assemble(working, omitted);
959
- while (assembled.length > maxChars && working.length > 1) {
960
- working.pop();
961
- omitted = true;
962
- assembled = assemble(working, omitted);
963
- }
964
- if (assembled.length > maxChars) {
965
- assembled = `${assembled.slice(0, maxChars - 1)}…`;
966
- }
967
- return assembled;
968
- }
969
-
970
- function clampToBudget(header, lines, more, footer, maxChars) {
971
- const assemble = (linesArr, moreText) => {
972
- const blocks = [header, ...linesArr];
973
- if (moreText) blocks.push(moreText);
974
- blocks.push('');
975
- blocks.push(footer);
976
- return blocks.join('\n');
977
- };
978
-
979
- const working = lines.slice();
980
- let moreText = more;
981
- let assembled = assemble(working, moreText);
982
- while (assembled.length > maxChars && working.length > 1) {
983
- working.pop();
984
- moreText = `... and more (see ${MONODESIGN_COMMAND} audit).`;
985
- assembled = assemble(working, moreText);
986
- }
987
- if (assembled.length > maxChars) {
988
- assembled = `${assembled.slice(0, maxChars - 1)}…`;
989
- }
990
- return assembled;
991
- }
992
-
993
- function formatFindingLine(f) {
994
- const prefix = f.line && f.line > 0 ? `- L${f.line}` : '-';
995
- const desc = (f.description || '').trim();
996
- const name = (f.name || '').trim();
997
- // Description from the registry already ends in punctuation; join with a
998
- // single space. `name` may have a trailing period already, keep it clean.
999
- const nameSegment = name ? `${name.replace(/\.+\s*$/, '')}.` : '';
1000
- const ignoreCommand = formatFindingIgnoreCommand(f);
1001
- const ignoreSegment = ignoreCommand
1002
- ? ` If the user explicitly confirms this value is intentional: \`${ignoreCommand}\`.`
1003
- : '';
1004
- return `${prefix} [${f.antipattern}] ${nameSegment} ${desc}${ignoreSegment}`.replace(/\s+/g, ' ').trim();
1005
- }
1006
-
1007
- function formatFindingIgnoreCommand(finding) {
1008
- if (!finding || typeof finding !== 'object') return '';
1009
- const rule = normalizeIgnoreRule(finding.antipattern);
1010
- if (!rule) return '';
1011
- const normalizedValue = extractFindingIgnoreValue(finding);
1012
- if (!normalizedValue) return '';
1013
- const value = extractFindingIgnoreValueRaw(finding);
1014
- const valueArg = quoteCommandArg(value);
1015
- const reason = quoteCommandArg(`User confirmed ${value} is intentional`);
1016
- return `${MONODESIGN_COMMAND} hooks ignore-value ${rule} ${valueArg} --shared --reason ${reason}`;
1017
- }
1018
-
1019
- function quoteCommandArg(value) {
1020
- const text = String(value || '').trim();
1021
- if (/^[A-Za-z0-9._:-]+$/.test(text)) return text;
1022
- return `"${text.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
1023
- }
1024
-
1025
- function relativize(filePath, cwd) {
1026
- try {
1027
- const rel = path.relative(cwd, filePath).split(path.sep).join('/');
1028
- if (!rel || rel.startsWith('..')) return filePath;
1029
- return rel.split(path.sep).join('/');
1030
- } catch {
1031
- return filePath;
1032
- }
1033
- }
1034
-
1035
- // Codex `apply_patch` exposes the raw patch in `tool_input.command`, not
1036
- // `tool_input.file_path`. Claude Code may send both; parse the patch body
1037
- // so we can scan the file(s) the tool actually touched.
1038
- // https://developers.openai.com/codex/hooks#posttooluse
1039
- const APPLY_PATCH_FILE_RE = /^\*\*\* (?:Update|Add) File: (.+)$/gm;
1040
-
1041
- export function parseApplyPatchPaths(command, projectCwd) {
1042
- if (!command || typeof command !== 'string') return [];
1043
- const out = [];
1044
- for (const m of command.matchAll(APPLY_PATCH_FILE_RE)) {
1045
- let p = (m[1] || '').trim();
1046
- if (!p) continue;
1047
- if (!path.isAbsolute(p)) p = path.resolve(projectCwd, p);
1048
- out.push(p);
1049
- }
1050
- return out;
1051
- }
1052
-
1053
- export function resolveTargetFiles(event, projectCwd) {
1054
- const ti = event?.tool_input;
1055
- const out = [];
1056
- const add = (filePath) => {
1057
- if (typeof filePath !== 'string' || !filePath) return;
1058
- if (!out.includes(filePath)) out.push(filePath);
1059
- };
1060
-
1061
- if (event?.tool_name === 'apply_patch' && ti && typeof ti.command === 'string') {
1062
- for (const filePath of parseApplyPatchPaths(ti.command, projectCwd)) add(filePath);
1063
- }
1064
- if (ti && typeof ti.file_path === 'string' && ti.file_path) {
1065
- add(ti.file_path);
1066
- }
1067
- // Cursor Write / StrReplace use `path`, not `file_path`.
1068
- if (ti && typeof ti.path === 'string' && ti.path) {
1069
- add(ti.path);
1070
- }
1071
- if (typeof event?.file_path === 'string' && event.file_path) {
1072
- add(event.file_path);
1073
- }
1074
- return out;
1075
- }
1076
-
1077
- export function resolveHarness(env = {}, event = null) {
1078
- const explicit = env?.MONODESIGN_HOOK_HARNESS;
1079
- if (explicit === 'cursor') return 'cursor';
1080
- if (explicit === 'github') return 'github';
1081
- if (explicit === 'claude' || explicit === 'codex') return 'claude';
1082
- // GitHub Copilot's postToolUse event uses camelCase `toolName`/`toolArgs` and
1083
- // has no `tool_name`/`tool_input`. That shape is the discriminator.
1084
- if (event && typeof event === 'object'
1085
- && (typeof event.toolName === 'string' || event.toolArgs !== undefined)
1086
- && event.tool_name === undefined && event.tool_input === undefined) {
1087
- return 'github';
1088
- }
1089
- if (typeof event?.conversation_id === 'string' && event.conversation_id) return 'cursor';
1090
- return 'claude';
1091
- }
1092
-
1093
- // GitHub Copilot's postToolUse payload is
1094
- // { sessionId, timestamp, cwd, toolName, toolArgs, toolResult }
1095
- // mapped onto the internal `{ tool_name, tool_input, cwd, session_id }` shape.
1096
- // `toolArgs` shape depends on the tool: the `edit`/`create`/`view` tools send a
1097
- // JSON *string* (double-encoded) carrying the file under `path`, e.g.
1098
- // "{\"path\":\"/abs/app.tsx\",\"old_str\":\"...\",\"new_str\":\"...\"}",
1099
- // while `apply_patch` sends a raw OpenAI-format patch string (handled below in
1100
- // normalizeGitHubEvent). The detector reads the file from disk after the tool
1101
- // ran, so only the path (not the proposed content) is needed here.
1102
- export function parseGitHubToolArgs(toolArgs) {
1103
- if (toolArgs && typeof toolArgs === 'object' && !Array.isArray(toolArgs)) return toolArgs;
1104
- if (typeof toolArgs === 'string' && toolArgs.trim()) {
1105
- try {
1106
- const parsed = JSON.parse(toolArgs);
1107
- return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
1108
- } catch {
1109
- return {};
1110
- }
1111
- }
1112
- return {};
1113
- }
1114
-
1115
- // Copilot's `apply_patch` tool (used by interactive sessions and the cloud
1116
- // agent) sends a raw OpenAI-format patch string in toolArgs, not JSON:
1117
- // *** Begin Patch
1118
- // *** Add File: /abs/app.css
1119
- // +body { ... }
1120
- // *** End Patch
1121
- // The `view`/`edit`/`create` tools (seen in `copilot -p` runs) instead send a
1122
- // JSON string with the path under `path`. Both must map onto the internal shape.
1123
- const APPLY_PATCH_MARKER = /\*\*\* (?:Begin Patch|Add File:|Update File:|Delete File:)/;
1124
-
1125
- function looksLikeApplyPatch(rawArgs) {
1126
- if (typeof rawArgs !== 'string' || !APPLY_PATCH_MARKER.test(rawArgs)) return false;
1127
- // Guard against an edit/create payload whose edited *content* happens to
1128
- // contain patch markers: that payload is a JSON object string, whereas a real
1129
- // apply_patch payload is a raw patch string that does not parse as JSON. Only
1130
- // treat non-JSON-object strings as apply_patch so edit events still get their
1131
- // `path` extracted.
1132
- try {
1133
- const parsed = JSON.parse(rawArgs);
1134
- if (parsed && typeof parsed === 'object') return false;
1135
- } catch { /* not JSON → genuine raw patch */ }
1136
- return true;
1137
- }
1138
-
1139
- function applyPatchText(rawArgs) {
1140
- if (typeof rawArgs === 'string') {
1141
- if (APPLY_PATCH_MARKER.test(rawArgs)) return rawArgs;
1142
- // Defensive: a future Copilot build might JSON-wrap the patch.
1143
- const parsed = parseGitHubToolArgs(rawArgs);
1144
- return parsed.patch || parsed.input || parsed.command || '';
1145
- }
1146
- if (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs)) {
1147
- return rawArgs.patch || rawArgs.input || rawArgs.command || '';
1148
- }
1149
- return '';
1150
- }
1151
-
1152
- function normalizeGitHubEvent(event, projectCwd) {
1153
- const cwd = event.cwd || envProjectDir(projectCwd) || projectCwd;
1154
- const sessionId = event.sessionId || event.session_id || 'unknown';
1155
- const toolName = event.toolName || event.tool_name || null;
1156
- const toolInput = event.tool_input && typeof event.tool_input === 'object' ? { ...event.tool_input } : {};
1157
- const rawArgs = event.toolArgs;
1158
-
1159
- let normalizedToolName = toolName;
1160
- if (toolName === 'apply_patch' || looksLikeApplyPatch(rawArgs)) {
1161
- // resolveTargetFiles() reads the touched paths from tool_input.command when
1162
- // tool_name is 'apply_patch', so normalize the name even if a future build
1163
- // sends the patch under a different tool label.
1164
- const patch = applyPatchText(rawArgs);
1165
- if (patch) {
1166
- toolInput.command = patch;
1167
- normalizedToolName = 'apply_patch';
1168
- }
1169
- } else {
1170
- const args = parseGitHubToolArgs(rawArgs);
1171
- const filePath = args.path || args.file_path || args.filePath || args.target_file;
1172
- if (typeof filePath === 'string' && filePath) toolInput.file_path = filePath;
1173
- }
1174
-
1175
- return {
1176
- ...event,
1177
- cwd,
1178
- session_id: sessionId,
1179
- tool_name: normalizedToolName,
1180
- tool_input: toolInput,
1181
- };
1182
- }
1183
-
1184
- export function normalizeHookEvent(event, projectCwd, harness = 'claude') {
1185
- if (!event || typeof event !== 'object') return event;
1186
- if (harness === 'github') return normalizeGitHubEvent(event, projectCwd);
1187
- if (harness !== 'cursor') return event;
1188
-
1189
- const cwd = event.cwd
1190
- || (Array.isArray(event.workspace_roots) && event.workspace_roots[0])
1191
- || envProjectDir(projectCwd)
1192
- || projectCwd;
1193
- const sessionId = event.session_id || event.conversation_id || 'unknown';
1194
-
1195
- const ti = event.tool_input && typeof event.tool_input === 'object' ? event.tool_input : {};
1196
- const filePath = ti.file_path || ti.path || event.file_path;
1197
- if (filePath) {
1198
- return {
1199
- ...event,
1200
- cwd,
1201
- session_id: sessionId,
1202
- tool_input: { ...ti, file_path: filePath },
1203
- };
1204
- }
1205
-
1206
- return { ...event, cwd, session_id: sessionId };
1207
- }
1208
-
1209
- function envProjectDir(fallback) {
1210
- if (typeof process.env.CURSOR_PROJECT_DIR === 'string' && process.env.CURSOR_PROJECT_DIR) {
1211
- return process.env.CURSOR_PROJECT_DIR;
1212
- }
1213
- return fallback;
1214
- }
1215
-
1216
- // UI components often keep slop in a sibling/co-located stylesheet while the
1217
- // JSX edit is what triggered PostToolUse. Scan those styles too so an App.jsx
1218
- // patch doesn't report "clean" while styles.css still has Inter/bounce/etc.
1219
- const UI_CODE_EXTS = new Set(['.jsx', '.tsx', '.vue', '.svelte', '.astro']);
1220
- const STYLE_EXTS = new Set(['.css', '.scss', '.sass', '.less']);
1221
- const CO_SCAN_STYLE_NAMES = [
1222
- 'styles.css', 'styles.scss', 'styles.sass', 'styles.less',
1223
- 'index.css', 'index.scss', 'index.sass', 'index.less',
1224
- 'global.css', 'global.scss', 'global.sass', 'global.less',
1225
- 'globals.css', 'globals.scss', 'globals.sass', 'globals.less',
1226
- ];
1227
- const MAX_SCAN_TARGETS = 6;
1228
-
1229
- const STATIC_STYLE_IMPORT_RE = /import\s+(?:[\w*{}\s,$]+\s+from\s+)?['"]([^'"]+\.(?:css|scss|sass|less))['"]/gi;
1230
-
1231
- function hasPathTraversal(filePath) {
1232
- return typeof filePath === 'string' && filePath.includes('..');
1233
- }
1234
-
1235
- function isInsideProject(filePath, projectCwd) {
1236
- if (!filePath || !projectCwd || hasPathTraversal(filePath)) return false;
1237
- try {
1238
- const rel = path.relative(projectCwd, filePath).split(path.sep).join('/');
1239
- return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
1240
- } catch {
1241
- return false;
1242
- }
1243
- }
1244
-
1245
- export function parseStaticStyleImports(content, fromFile, projectCwd) {
1246
- if (!content || typeof content !== 'string') return [];
1247
- const dir = path.dirname(fromFile);
1248
- const out = [];
1249
- for (const m of content.matchAll(STATIC_STYLE_IMPORT_RE)) {
1250
- let p = (m[1] || '').trim();
1251
- if (!p) continue;
1252
- if (p.startsWith('.')) p = path.resolve(dir, p);
1253
- else if (!path.isAbsolute(p)) p = path.resolve(projectCwd, p);
1254
- if (!isInsideProject(p, projectCwd)) continue;
1255
- out.push(p);
1256
- }
1257
- return out;
1258
- }
1259
-
1260
- export function coLocatedStylesheets(filePath) {
1261
- const dir = path.dirname(filePath);
1262
- const base = path.basename(filePath, path.extname(filePath));
1263
- const candidates = new Set([
1264
- path.join(dir, `${base}.css`),
1265
- path.join(dir, `${base}.module.css`),
1266
- path.join(dir, `${base}.scss`),
1267
- path.join(dir, `${base}.module.scss`),
1268
- path.join(dir, `${base}.sass`),
1269
- path.join(dir, `${base}.module.sass`),
1270
- path.join(dir, `${base}.less`),
1271
- path.join(dir, `${base}.module.less`),
1272
- ]);
1273
- for (const name of CO_SCAN_STYLE_NAMES) {
1274
- candidates.add(path.join(dir, name));
1275
- }
1276
- return [...candidates].filter((p) => fs.existsSync(p));
1277
- }
1278
-
1279
- export function normalizeScanTargets(primaryTargets, projectCwd) {
1280
- if (!Array.isArray(primaryTargets) || primaryTargets.length === 0) return [];
1281
- const ordered = [];
1282
- const seen = new Set();
1283
- const baseCwd = projectCwd || process.cwd();
1284
- const normalizeTarget = (p) => {
1285
- // Preserve literal `..` segments so downstream sensitive-path checks
1286
- // still fire. path.resolve would collapse `/foo/../etc/passwd`.
1287
- if (hasPathTraversal(p)) return p;
1288
- return path.isAbsolute(p) ? p : path.resolve(baseCwd, p);
1289
- };
1290
- const add = (p) => {
1291
- if (ordered.length >= MAX_SCAN_TARGETS) return;
1292
- const abs = normalizeTarget(p);
1293
- if (seen.has(abs)) return;
1294
- seen.add(abs);
1295
- ordered.push(abs);
1296
- return abs;
1297
- };
1298
-
1299
- for (const p of primaryTargets) add(p);
1300
- return ordered;
1301
- }
1302
-
1303
- export function expandScanTargets(primaryTargets, projectCwd) {
1304
- const ordered = normalizeScanTargets(primaryTargets, projectCwd);
1305
- if (ordered.length === 0) return [];
1306
- const seen = new Set(ordered);
1307
- const baseCwd = projectCwd || process.cwd();
1308
- const add = (p) => {
1309
- if (ordered.length >= MAX_SCAN_TARGETS) return;
1310
- const abs = hasPathTraversal(p) ? p : (path.isAbsolute(p) ? p : path.resolve(baseCwd, p));
1311
- if (seen.has(abs)) return;
1312
- seen.add(abs);
1313
- ordered.push(abs);
1314
- return abs;
1315
- };
1316
-
1317
- const normalizedPrimaries = [];
1318
- for (const p of ordered) normalizedPrimaries.push(p);
1319
-
1320
- for (const p of normalizedPrimaries) {
1321
- if (ordered.length >= MAX_SCAN_TARGETS) break;
1322
- if (!isInsideProject(p, baseCwd)) continue;
1323
- const ext = path.extname(p).toLowerCase();
1324
- if (STYLE_EXTS.has(ext) || !UI_CODE_EXTS.has(ext)) continue;
1325
-
1326
- let content = '';
1327
- try { content = fs.readFileSync(p, 'utf-8'); } catch { /* unreadable primary */ }
1328
-
1329
- for (const imp of parseStaticStyleImports(content, p, projectCwd)) {
1330
- add(imp);
1331
- if (ordered.length >= MAX_SCAN_TARGETS) break;
1332
- }
1333
- for (const col of coLocatedStylesheets(p)) {
1334
- add(col);
1335
- if (ordered.length >= MAX_SCAN_TARGETS) break;
1336
- }
1337
- }
1338
-
1339
- return ordered;
1340
- }
1341
-
1342
- export function writeAuditLog(env, entry, cwd = process.cwd()) {
1343
- // The event's project root (entry.cwd) when present, else the passed cwd. Both
1344
- // config reads and relative log paths resolve against this, since the hook
1345
- // process cwd can differ from the project being edited.
1346
- const baseCwd = entry && typeof entry.cwd === 'string' && entry.cwd ? entry.cwd : cwd;
1347
- // Env wins; otherwise fall back to the unified config's hook.auditLog path.
1348
- let target = env?.MONODESIGN_HOOK_LOG;
1349
- if (!target || typeof target !== 'string') {
1350
- try { target = readConfig(baseCwd).auditLog; } catch { target = null; }
1351
- }
1352
- if (!target || typeof target !== 'string') return false;
1353
- try {
1354
- let expanded;
1355
- if (target.startsWith('~/')) {
1356
- expanded = path.join(process.env.HOME || process.env.USERPROFILE || '.', target.slice(2));
1357
- } else if (path.isAbsolute(target)) {
1358
- expanded = target;
1359
- } else {
1360
- expanded = path.resolve(baseCwd, target);
1361
- }
1362
- fs.mkdirSync(path.dirname(expanded), { recursive: true });
1363
- const line = `${JSON.stringify({ ts: new Date().toISOString(), ...entry })}\n`;
1364
- fs.appendFileSync(expanded, line);
1365
- return true;
1366
- } catch {
1367
- return false;
1368
- }
1369
- }
1370
-
1371
- // Packaged fallback: resolve the engine from an installed @monoes/monodesign.
1372
- function packagedDetectorPath() {
1373
- try {
1374
- return createRequire(import.meta.url).resolve('@monoes/monodesign/engine');
1375
- } catch {
1376
- return null;
1377
- }
1378
- }
1379
-
1380
- const DETECTOR_CANDIDATES = [
1381
- path.join(__dirname, 'detector', 'detect-antipatterns.mjs'),
1382
- path.join(__dirname, '..', '..', 'cli', 'engine', 'detect-antipatterns.mjs'),
1383
- path.join(__dirname, '..', '..', '..', 'cli', 'engine', 'detect-antipatterns.mjs'),
1384
- packagedDetectorPath(),
1385
- ].filter(Boolean);
1386
-
1387
- let detectorCache = null;
1388
- export async function loadDetector(candidates = DETECTOR_CANDIDATES) {
1389
- if (detectorCache) return detectorCache;
1390
- const found = candidates.find((c) => fs.existsSync(c));
1391
- if (!found) return null;
1392
- const mod = await import(pathToFileURL(found));
1393
- detectorCache = {
1394
- detectText: mod.detectText,
1395
- detectHtml: mod.detectHtml,
1396
- loadDesignSystemForCwd: mod.loadDesignSystemForCwd,
1397
- };
1398
- return detectorCache;
1399
- }
1400
-
1401
- // For tests: allow injecting a detector implementation.
1402
- export function setDetectorForTesting(impl) {
1403
- detectorCache = impl;
1404
- }
1405
-
1406
- // ────────────────────────────────────────────────────────────────────────
1407
- // Nudge/steer messages for the no-silent-fires policy.
1408
- //
1409
- // The hook is designed to be a conversational presence: every fire that
1410
- // actually scans a file emits a developer-role message into the model's
1411
- // next turn. Three states map to three templates:
1412
- //
1413
- // 1. **Fresh findings** → `renderTemplate` (existing, imperative).
1414
- // 2. **Pending findings** → `renderPendingAck` (re-nudge for issues the
1415
- // model was already told about in this
1416
- // session but hasn't fixed yet).
1417
- // 3. **Truly clean** → `renderCleanAck` (short positive nudge that
1418
- // keeps the design discipline in context).
1419
- //
1420
- // All three are short (≤ ~40 tokens each) so the cumulative cost stays
1421
- // bounded across a long active editing session. Users who explicitly want
1422
- // silence-on-clean can set `MONODESIGN_HOOK_QUIET=1` — runHook checks that
1423
- // env before emitting #2 or #3.
1424
- //
1425
- // Why not stay silent on dedup-clean? Earlier versions did. The model
1426
- // quickly forgets the prior reminder once tool output scrolls past it, so
1427
- // re-nudging on the same file with a short "still pending" line keeps the
1428
- // pressure on. The wording deliberately points back to "earlier this
1429
- // session" so the model knows it's a re-mind, not a new finding.
1430
- // ────────────────────────────────────────────────────────────────────────
1431
-
1432
- const STEER_LINE = 'That does not mean the design is good: keep following the project design system and the monodesign skill guidance.';
1433
-
1434
- export function renderCleanAck(filePath, opts = {}) {
1435
- const cwd = opts.cwd || process.cwd();
1436
- const display = relativize(filePath, cwd);
1437
- return `${ENVELOPE_PREFIX} Design hook scanned ${display}. No deterministic design-quality issues found. ${STEER_LINE}`;
1438
- }
1439
-
1440
- export function renderPendingAck(filePath, knownFindings, opts = {}) {
1441
- const cwd = opts.cwd || process.cwd();
1442
- const display = relativize(filePath, cwd);
1443
- const count = knownFindings.length;
1444
- // `knownFindings` here are the cache strings like "side-tab:3".
1445
- const sample = knownFindings.slice(0, 3).join(', ');
1446
- const more = count > 3 ? `, +${count - 3} more` : '';
1447
- return `${ENVELOPE_PREFIX} Design hook scanned ${display}. Still has ${count} finding(s) flagged earlier this session (${sample}${more}). Handle them before finalizing — the previous reminder still applies.`;
1448
- }
1449
-
1450
- export function shouldEmitAckForFile(filePath, config = null) {
1451
- if (ACK_EXTS.has(path.extname(String(filePath || '')).toLowerCase())) return true;
1452
- // Configured html-engine extensions are declared UI markup, so they get the
1453
- // clean/pending acks; text-engine ones stay quiet like plain .ts/.js.
1454
- const configured = matchConfiguredExtension(filePath, config?.extensions);
1455
- return Boolean(configured && configured.engine === 'html');
1456
- }
1457
-
1458
- export function designSystemOptions(config, detector, projectCwd) {
1459
- if (config?.designSystem?.enabled === false) return {};
1460
- if (!detector || typeof detector.loadDesignSystemForCwd !== 'function') return {};
1461
- try {
1462
- const designSystem = detector.loadDesignSystemForCwd(projectCwd);
1463
- return designSystem ? { designSystem } : {};
1464
- } catch {
1465
- return {};
1466
- }
1467
- }
1468
-
1469
- export function appendDesignSystemNote(text, scanOptions) {
1470
- if (!text || !scanOptions?.designSystem?.mdNewerThanJson) return text;
1471
- return `${text}\n\n${ENVELOPE_PREFIX} DESIGN.md is newer than .monodesign/design.json. Run ${MONODESIGN_COMMAND} document to refresh the design-system sidecar.`;
1472
- }
1473
-
1474
- // The directive footer is the part of the hook output that steers model
1475
- // behavior. Three intentional moves:
1476
- // 1. **Imperative, not advisory.** "Handle these..." beats "Consider
1477
- // revising..." which the model treats as a soft suggestion it can
1478
- // override when the user asked for any kind of throwaway / demo UI.
1479
- // 2. **Explicit judgment clause.** Without it, the model will try to
1480
- // "fix" intentional motion, bad fixtures, anti-pattern examples in
1481
- // docs, or test cases. Naming the judgment inline beats hoping the
1482
- // model infers it from context.
1483
- // 3. **Acknowledgement instruction.** Hook output is injected as
1484
- // developer-role context, not a chat turn, so the user never sees the
1485
- // raw envelope. Asking the model to surface the resolution in its
1486
- // reply is the cheapest way to make the feedback loop visible.
1487
- function directiveFooter(display, opts = {}) {
1488
- const ignoreFileCommand = `${MONODESIGN_COMMAND} hooks ignore-file ${quoteCommandArg(display)}`;
1489
- const fileIgnoreGuidance = opts.grouped
1490
- ? `run \`${MONODESIGN_COMMAND} hooks ignore-file <path>\` for the specific file`
1491
- : `run \`${ignoreFileCommand}\``;
1492
- return [
1493
- 'Handle these before finalizing: fix findings that are real design problems, or explicitly classify contextually intentional findings as false positives. Acknowledge what you changed or why you are leaving a finding unchanged.',
1494
- '',
1495
- 'Use context judgment before editing. A finding is not automatically a defect; literal or domain-appropriate motion, intentional demos or fixtures, documentation of bad design, and user-confirmed choices can be valid as-is.',
1496
- '',
1497
- `Do not change intentional design just to satisfy the hook, and do not silence a real finding with an inline ignore comment to skip fixing it. Suppress a finding only after the user explicitly confirms it is intentional. Prefer a config ignore (one reviewable place, the commands below); reach for an inline \`monodesign-disable <rule>\` comment only when the waiver must travel with a file that leaves the repo, such as an exported or standalone document. Prefer the narrowest persisted exception: run the exact \`${MONODESIGN_COMMAND} hooks ignore-value ... --shared\` command shown next to a value-specific finding. For \`overused-font\`, use \`ignore-value\` for a specific font and use \`${MONODESIGN_COMMAND} hooks ignore-rule overused-font --all-values\` only when the user asks to ignore overused fonts generally. For file-specific findings without an ignore-value command, ${fileIgnoreGuidance}; use \`${MONODESIGN_COMMAND} hooks ignore-rule <id>\` only when the user asks to suppress the whole non-value-specific rule. Run ${MONODESIGN_COMMAND} audit for the full pass.`,
1498
- ].join('\n');
1499
- }
1500
-
1501
- /**
1502
- * Run the hook with explicit dependencies. Returns a result object:
1503
- * { exitCode, stdout, audit, reason? }
1504
- *
1505
- * Never throws. All errors are converted to `exitCode: 0` + audit entry.
1506
- */
1507
- export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now = Date.now, detector } = {}) {
1508
- const audit = { ts: new Date(now()).toISOString(), event: 'PostToolUse' };
1509
- const result = (extra) => ({ exitCode: 0, stdout: '', audit: { ...audit, ...extra } });
1510
-
1511
- try {
1512
- // Re-entrancy guard.
1513
- if (depthIsSet(env.MONODESIGN_HOOK_DEPTH) || depthIsSet(env.CLAUDE_HOOK_DEPTH)) {
1514
- return result({ reentrant: true, durationMs: 0 });
1515
- }
1516
-
1517
- if (truthy(env.MONODESIGN_HOOK_DISABLED)) {
1518
- return result({ skipped: 'env-disabled', durationMs: 0 });
1519
- }
1520
-
1521
- const started = Date.now();
1522
-
1523
- let event;
1524
- try {
1525
- event = typeof stdinJson === 'string' ? JSON.parse(stdinJson) : stdinJson;
1526
- } catch {
1527
- return result({ skipped: 'stdin-malformed', durationMs: Date.now() - started });
1528
- }
1529
- if (!event || typeof event !== 'object') {
1530
- return result({ skipped: 'stdin-empty', durationMs: Date.now() - started });
1531
- }
1532
-
1533
- const harness = resolveHarness(env, event);
1534
- event = normalizeHookEvent(event, cwd, harness);
1535
- audit.harness = harness;
1536
-
1537
- const sessionCwd = event.cwd || cwd;
1538
- const primaryFiles = normalizeScanTargets(resolveTargetFiles(event, sessionCwd), sessionCwd);
1539
- const projectCwd = resolveCacheCwd(primaryFiles[0], sessionCwd);
1540
- audit.cwd = projectCwd;
1541
- const primaryFileSet = new Set(primaryFiles);
1542
- const targetFiles = expandScanTargets(primaryFiles, projectCwd);
1543
- audit.session = event.session_id || null;
1544
- if (event.tool_name) audit.tool = event.tool_name;
1545
-
1546
- if (targetFiles.length === 0) {
1547
- return result({ skipped: 'no-file-path', durationMs: Date.now() - started });
1548
- }
1549
-
1550
- const config = readConfig(projectCwd);
1551
- if (config.enabled === false) {
1552
- return result({ skipped: 'config-disabled', durationMs: Date.now() - started });
1553
- }
1554
-
1555
- const platform = resolveProjectPlatform(projectCwd);
1556
- if (isNativePlatform(platform)) {
1557
- return result({ skipped: 'native-platform', platform, durationMs: Date.now() - started });
1558
- }
1559
-
1560
- const cache = readCache(projectCwd);
1561
- const sessionId = event.session_id || 'unknown';
1562
- const det = detector || await loadDetector();
1563
- if (!det || typeof det.detectText !== 'function') {
1564
- // Cache is not mutated yet at this point; nothing to persist.
1565
- return result({ skipped: 'detector-missing', durationMs: Date.now() - started });
1566
- }
1567
- const scanOptions = designSystemOptions(config, det, projectCwd);
1568
-
1569
- let pendingWinner = null;
1570
- let cleanWinner = null;
1571
- const freshGroups = [];
1572
- let suppressionWinner = null;
1573
- let detectorThrewAny = false;
1574
- let lastSkip = 'no-scannable-file';
1575
- let suppressedHit = false;
1576
- let cacheDirty = false;
1577
-
1578
- for (const filePath of targetFiles) {
1579
- audit.file = filePath;
1580
-
1581
- if (hasPathTraversal(filePath) || SENSITIVE_PATH.test(filePath)) {
1582
- lastSkip = 'sensitive';
1583
- continue;
1584
- }
1585
- if (isGeneratedPath(filePath, projectCwd)) {
1586
- lastSkip = 'generated';
1587
- continue;
1588
- }
1589
-
1590
- const ext = path.extname(filePath).toLowerCase();
1591
- const configuredExt = matchConfiguredExtension(filePath, config.extensions);
1592
- audit.ext = configuredExt ? configuredExt.ext : ext;
1593
- if (!ALLOWED_EXTS.has(ext) && !configuredExt) {
1594
- lastSkip = 'extension';
1595
- continue;
1596
- }
1597
-
1598
- const relForMatch = relativize(filePath, projectCwd);
1599
- if (matchesAnyGlob(relForMatch, config.ignoreFiles) || matchesAnyGlob(filePath, config.ignoreFiles)) {
1600
- lastSkip = 'config-ignore-file';
1601
- continue;
1602
- }
1603
- if (!fs.existsSync(filePath)) {
1604
- lastSkip = 'file-missing';
1605
- continue;
1606
- }
1607
-
1608
- if (primaryFileSet.has(filePath)) {
1609
- const editCount = bumpEditCount(cache, sessionId, filePath);
1610
- cacheDirty = true;
1611
- audit.editCount = editCount;
1612
-
1613
- if (editCount > EDIT_COUNT_THRESHOLD) {
1614
- const wasJustCrossed = editCount === EDIT_COUNT_THRESHOLD + 1;
1615
- if (wasJustCrossed && !suppressionWinner) {
1616
- suppressionWinner = { filePath };
1617
- }
1618
- lastSkip = 'suppressed';
1619
- suppressedHit = true;
1620
- continue;
1621
- }
1622
- }
1623
-
1624
- const content = fs.readFileSync(filePath, 'utf-8');
1625
- let findings;
1626
- let detectorThrew = false;
1627
- const useHtmlEngine = configuredExt
1628
- ? configuredExt.engine === 'html'
1629
- : (ext === '.html' || ext === '.htm');
1630
- if (useHtmlEngine && typeof det.detectHtml === 'function') {
1631
- try { findings = await det.detectHtml(filePath, scanOptions); } catch { findings = []; detectorThrew = true; }
1632
- } else {
1633
- try { findings = await det.detectText(content, filePath, scanOptions); } catch { findings = []; detectorThrew = true; }
1634
- }
1635
-
1636
- const filtered = filterFindings(findings || [], content, ext, config);
1637
- const fresh = dedupeAgainstCache(filtered, cache, sessionId, filePath);
1638
- audit.findings = (findings || []).length;
1639
- audit.freshFindings = fresh.length;
1640
-
1641
- if (fresh.length > 0) {
1642
- rememberFindings(cache, sessionId, filePath, fresh);
1643
- cacheDirty = true;
1644
- freshGroups.push({ filePath, findings: fresh });
1645
- continue;
1646
- }
1647
-
1648
- if (detectorThrew) {
1649
- detectorThrewAny = true;
1650
- continue;
1651
- }
1652
-
1653
- if (filtered.length > 0 && !pendingWinner) {
1654
- const known = (ensureFile(cache, sessionId, filePath).findings || []).slice();
1655
- pendingWinner = { filePath, known };
1656
- } else if (filtered.length === 0 && !cleanWinner) {
1657
- cleanWinner = { filePath };
1658
- }
1659
- }
1660
-
1661
- // Persist only when the write is earned: fresh findings justify creating
1662
- // `.monodesign/` (dedup and suppression need it), and an already-present
1663
- // `.monodesign/` dir marks a project that opted in. A non-UI edit, or a
1664
- // clean UI edit in a project with no Monodesign footprint, must be a
1665
- // no-op on disk (issues #344, #305).
1666
- if (freshGroups.length > 0
1667
- || (cacheDirty && fs.existsSync(path.join(projectCwd, '.monodesign')))) {
1668
- persistCache(projectCwd, cache);
1669
- }
1670
-
1671
- if (freshGroups.length > 0) {
1672
- const firstGroup = freshGroups[0];
1673
- const text = appendDesignSystemNote(renderGroupedTemplate(freshGroups, config, { cwd: projectCwd }), scanOptions);
1674
- const allFindings = freshGroups.flatMap((group) => group.findings);
1675
- return {
1676
- exitCode: 0,
1677
- stdout: payload(text, 'PostToolUse', harness),
1678
- emission: {
1679
- kind: 'fresh',
1680
- file: firstGroup.filePath,
1681
- findings: firstGroup.findings,
1682
- groups: freshGroups,
1683
- },
1684
- audit: {
1685
- ...audit,
1686
- file: firstGroup.filePath,
1687
- emitted: true,
1688
- freshFiles: freshGroups.length,
1689
- freshFindings: allFindings.length,
1690
- chars: text.length,
1691
- durationMs: Date.now() - started,
1692
- },
1693
- };
1694
- }
1695
-
1696
- if (detectorThrewAny && !pendingWinner && !cleanWinner) {
1697
- return result({ emitted: false, error: 'detector-threw', durationMs: Date.now() - started });
1698
- }
1699
-
1700
- if (truthy(env.MONODESIGN_HOOK_QUIET) || config.quiet === true) {
1701
- return result({ emitted: false, quiet: true, durationMs: Date.now() - started });
1702
- }
1703
-
1704
- if (pendingWinner && shouldEmitAckForFile(pendingWinner.filePath, config)) {
1705
- const text = appendDesignSystemNote(renderPendingAck(pendingWinner.filePath, pendingWinner.known, { cwd: projectCwd }), scanOptions);
1706
- return {
1707
- exitCode: 0,
1708
- stdout: payload(text, 'PostToolUse', harness),
1709
- emission: { kind: 'pending', file: pendingWinner.filePath, known: pendingWinner.known },
1710
- audit: {
1711
- ...audit,
1712
- file: pendingWinner.filePath,
1713
- emitted: true,
1714
- kind: 'pending',
1715
- pending: pendingWinner.known.length,
1716
- chars: text.length,
1717
- durationMs: Date.now() - started,
1718
- },
1719
- };
1720
- }
1721
-
1722
- if (suppressionWinner) {
1723
- const text = suppressionNotice(relativize(suppressionWinner.filePath, projectCwd));
1724
- return {
1725
- exitCode: 0,
1726
- stdout: payload(text, 'PostToolUse', harness),
1727
- emission: { kind: 'suppression', file: suppressionWinner.filePath },
1728
- audit: {
1729
- ...audit,
1730
- file: suppressionWinner.filePath,
1731
- suppressed: true,
1732
- emitted: true,
1733
- durationMs: Date.now() - started,
1734
- },
1735
- };
1736
- }
1737
-
1738
- if (cleanWinner && shouldEmitAckForFile(cleanWinner.filePath, config)) {
1739
- const text = appendDesignSystemNote(renderCleanAck(cleanWinner.filePath, { cwd: projectCwd }), scanOptions);
1740
- return {
1741
- exitCode: 0,
1742
- stdout: payload(text, 'PostToolUse', harness),
1743
- emission: { kind: 'clean', file: cleanWinner.filePath },
1744
- audit: {
1745
- ...audit,
1746
- file: cleanWinner.filePath,
1747
- emitted: true,
1748
- kind: 'clean',
1749
- chars: text.length,
1750
- durationMs: Date.now() - started,
1751
- },
1752
- };
1753
- }
1754
-
1755
- if (pendingWinner || cleanWinner) {
1756
- return result({ emitted: false, skipped: 'non-ui-ack', durationMs: Date.now() - started });
1757
- }
1758
-
1759
- if (suppressedHit) {
1760
- return result({ suppressed: true, emitted: false, durationMs: Date.now() - started });
1761
- }
1762
-
1763
- return result({ skipped: lastSkip, durationMs: Date.now() - started });
1764
- } catch (err) {
1765
- return {
1766
- exitCode: 0,
1767
- stdout: '',
1768
- audit: { ...audit, error: String(err?.message ? err.message : err) },
1769
- };
1770
- }
1771
- }
1772
-
1773
- export function payload(text, eventName = 'PostToolUse', harness = 'claude') {
1774
- if (harness === 'cursor') {
1775
- return JSON.stringify({ additional_context: text });
1776
- }
1777
- // GitHub Copilot's postToolUse hook injects context via a top-level
1778
- // `additionalContext` string (alongside an optional `modifiedResult`).
1779
- if (harness === 'github') {
1780
- return JSON.stringify({ additionalContext: text });
1781
- }
1782
- return JSON.stringify({
1783
- hookSpecificOutput: { hookEventName: eventName, additionalContext: text },
1784
- });
1785
- }