monomind 2.5.1 → 2.5.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 (324) hide show
  1. package/README.md +1 -1
  2. package/package.json +2 -1
  3. package/packages/@monomind/cli/.claude/agents/design/design-monodesign.md +6 -6
  4. package/packages/@monomind/cli/.claude/agents/github/repo-architect.md +3 -3
  5. package/packages/@monomind/cli/.claude/agents/github/sync-coordinator.md +2 -2
  6. package/packages/@monomind/cli/.claude/agents/specialists/integration-architect.md +4 -4
  7. package/packages/@monomind/cli/.claude/commands/github/repo-architect.md +4 -4
  8. package/packages/@monomind/cli/.claude/commands/github/sync-coordinator.md +2 -2
  9. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -4
  10. package/packages/@monomind/cli/.claude/commands/mastermind/approvev1.md +4 -4
  11. package/packages/@monomind/cli/.claude/commands/mastermind/architect.md +6 -6
  12. package/packages/@monomind/cli/.claude/commands/mastermind/autodev.md +5 -5
  13. package/packages/@monomind/cli/.claude/commands/mastermind/brain.md +2 -2
  14. package/packages/@monomind/cli/.claude/commands/mastermind/build.md +6 -6
  15. package/packages/@monomind/cli/.claude/commands/mastermind/code-review.md +2 -2
  16. package/packages/@monomind/cli/.claude/commands/mastermind/content.md +6 -6
  17. package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +4 -4
  18. package/packages/@monomind/cli/.claude/commands/mastermind/createtask.md +3 -3
  19. package/packages/@monomind/cli/.claude/commands/mastermind/debug.md +5 -5
  20. package/packages/@monomind/cli/.claude/commands/mastermind/design.md +5 -5
  21. package/packages/@monomind/cli/.claude/commands/mastermind/do.md +2 -2
  22. package/packages/@monomind/cli/.claude/commands/mastermind/execute.md +5 -5
  23. package/packages/@monomind/cli/.claude/commands/mastermind/finance.md +6 -6
  24. package/packages/@monomind/cli/.claude/commands/mastermind/finish.md +5 -5
  25. package/packages/@monomind/cli/.claude/commands/mastermind/idea.md +6 -6
  26. package/packages/@monomind/cli/.claude/commands/mastermind/ideate.md +5 -5
  27. package/packages/@monomind/cli/.claude/commands/mastermind/improve.md +6 -6
  28. package/packages/@monomind/cli/.claude/commands/mastermind/marketing.md +6 -6
  29. package/packages/@monomind/cli/.claude/commands/mastermind/master.md +54 -54
  30. package/packages/@monomind/cli/.claude/commands/mastermind/ops.md +6 -6
  31. package/packages/@monomind/cli/.claude/commands/mastermind/orgs.md +2 -2
  32. package/packages/@monomind/cli/.claude/commands/mastermind/orgstatus.md +2 -2
  33. package/packages/@monomind/cli/.claude/commands/mastermind/plan.md +5 -5
  34. package/packages/@monomind/cli/.claude/commands/mastermind/receive-review.md +5 -5
  35. package/packages/@monomind/cli/.claude/commands/mastermind/release.md +6 -6
  36. package/packages/@monomind/cli/.claude/commands/mastermind/research.md +6 -6
  37. package/packages/@monomind/cli/.claude/commands/mastermind/review.md +6 -6
  38. package/packages/@monomind/cli/.claude/commands/mastermind/runorg.md +4 -4
  39. package/packages/@monomind/cli/.claude/commands/mastermind/runorgv1.md +5 -5
  40. package/packages/@monomind/cli/.claude/commands/mastermind/sales.md +6 -6
  41. package/packages/@monomind/cli/.claude/commands/mastermind/skill-builder.md +5 -5
  42. package/packages/@monomind/cli/.claude/commands/mastermind/stoporg.md +3 -3
  43. package/packages/@monomind/cli/.claude/commands/mastermind/taskdev.md +5 -5
  44. package/packages/@monomind/cli/.claude/commands/mastermind/tdd.md +5 -5
  45. package/packages/@monomind/cli/.claude/commands/mastermind/techport.md +5 -5
  46. package/packages/@monomind/cli/.claude/commands/mastermind/verify.md +5 -5
  47. package/packages/@monomind/cli/.claude/commands/mastermind/worktree.md +5 -5
  48. package/packages/@monomind/cli/.claude/helpers/control-start.cjs +30 -0
  49. package/packages/@monomind/cli/.claude/helpers/event-logger.cjs +2 -2
  50. package/packages/@monomind/cli/.claude/helpers/extras-registry.json +1 -1
  51. package/packages/@monomind/cli/.claude/helpers/handlers/agent-start-handler.cjs +2 -2
  52. package/packages/@monomind/cli/.claude/helpers/handlers/edit-handler.cjs +2 -2
  53. package/packages/@monomind/cli/.claude/helpers/handlers/gates-handler.cjs +1 -1
  54. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +1 -1
  55. package/packages/@monomind/cli/.claude/helpers/handlers/session-handler.cjs +1 -1
  56. package/packages/@monomind/cli/.claude/helpers/handlers/session-restore-handler.cjs +11 -11
  57. package/packages/@monomind/cli/.claude/helpers/handlers/task-handler.cjs +2 -2
  58. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +8 -8
  59. package/packages/@monomind/cli/.claude/helpers/utils/monograph.cjs +44 -12
  60. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/access.md → mastermind-access/SKILL.md} +2 -2
  61. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/activity.md → mastermind-activity/SKILL.md} +2 -2
  62. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/adapter-manager.md → mastermind-adapter-manager/SKILL.md} +2 -2
  63. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/adapters.md → mastermind-adapters/SKILL.md} +2 -2
  64. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/agent-detail.md → mastermind-agent-detail/SKILL.md} +2 -2
  65. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/agents.md → mastermind-agents/SKILL.md} +2 -2
  66. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/approval-detail.md → mastermind-approval-detail/SKILL.md} +2 -2
  67. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/approvev1.md → mastermind-approvev1/SKILL.md} +2 -2
  68. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/architect.md → mastermind-architect/SKILL.md} +7 -7
  69. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/autodev.md → mastermind-autodev/SKILL.md} +10 -10
  70. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/backup.md → mastermind-backup/SKILL.md} +2 -2
  71. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/bootstrap.md → mastermind-bootstrap/SKILL.md} +2 -2
  72. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/budgets.md → mastermind-budgets/SKILL.md} +2 -2
  73. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/build.md → mastermind-build/SKILL.md} +5 -5
  74. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/companies.md → mastermind-companies/SKILL.md} +2 -2
  75. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/content.md → mastermind-content/SKILL.md} +5 -5
  76. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/costs.md → mastermind-costs/SKILL.md} +2 -2
  77. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/createorg.md → mastermind-createorg/SKILL.md} +3 -3
  78. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/debug.md → mastermind-debug/SKILL.md} +4 -4
  79. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/_delegation.md → mastermind-delegation/SKILL.md} +1 -1
  80. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/design.md → mastermind-design/SKILL.md} +9 -9
  81. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/diagnose.md → mastermind-diagnose/SKILL.md} +2 -2
  82. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/env.md → mastermind-env/SKILL.md} +2 -2
  83. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/environments.md → mastermind-environments/SKILL.md} +2 -2
  84. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/execute.md → mastermind-execute/SKILL.md} +10 -10
  85. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/export.md → mastermind-export/SKILL.md} +2 -2
  86. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/finance.md → mastermind-finance/SKILL.md} +5 -5
  87. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/goal-detail.md → mastermind-goal-detail/SKILL.md} +2 -2
  88. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/goals.md → mastermind-goals/SKILL.md} +2 -2
  89. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/heartbeatv1.md → mastermind-heartbeatv1/SKILL.md} +2 -2
  90. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/idea.md → mastermind-idea/SKILL.md} +7 -7
  91. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/import.md → mastermind-import/SKILL.md} +2 -2
  92. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/inbox.md → mastermind-inbox/SKILL.md} +2 -2
  93. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/instance.md → mastermind-instance/SKILL.md} +2 -2
  94. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/instance-settings.md → mastermind-instance-settings/SKILL.md} +2 -2
  95. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/invite-landing.md → mastermind-invite-landing/SKILL.md} +2 -2
  96. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/invites.md → mastermind-invites/SKILL.md} +2 -2
  97. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/issue-detail.md → mastermind-issue-detail/SKILL.md} +2 -2
  98. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/issues.md → mastermind-issues/SKILL.md} +2 -2
  99. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/join-queue.md → mastermind-join-queue/SKILL.md} +2 -2
  100. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/liveness.md → mastermind-liveness/SKILL.md} +2 -2
  101. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/marketing.md → mastermind-marketing/SKILL.md} +8 -8
  102. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/memory.md → mastermind-memory/SKILL.md} +2 -2
  103. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/monitor.md → mastermind-monitor/SKILL.md} +2 -2
  104. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/my-issues.md → mastermind-my-issues/SKILL.md} +2 -2
  105. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/new-agent.md → mastermind-new-agent/SKILL.md} +2 -2
  106. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/ops.md → mastermind-ops/SKILL.md} +5 -5
  107. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/org-chart.md → mastermind-org-chart/SKILL.md} +2 -2
  108. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/org-settings.md → mastermind-org-settings/SKILL.md} +2 -2
  109. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/orgs.md → mastermind-orgs/SKILL.md} +1 -1
  110. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/orgstatus.md → mastermind-orgstatus/SKILL.md} +2 -2
  111. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/plan.md → mastermind-plan/SKILL.md} +7 -7
  112. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/plan-to-tasks.md → mastermind-plan-to-tasks/SKILL.md} +2 -2
  113. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/plugin-manager.md → mastermind-plugin-manager/SKILL.md} +2 -2
  114. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/plugin-settings.md → mastermind-plugin-settings/SKILL.md} +2 -2
  115. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/plugins.md → mastermind-plugins/SKILL.md} +2 -2
  116. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/profile.md → mastermind-profile/SKILL.md} +2 -2
  117. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/project-detail.md → mastermind-project-detail/SKILL.md} +2 -2
  118. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/project-workspace.md → mastermind-project-workspace/SKILL.md} +2 -2
  119. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/projects.md → mastermind-projects/SKILL.md} +2 -2
  120. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/_protocol.md → mastermind-protocol/SKILL.md} +3 -3
  121. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/release.md → mastermind-release/SKILL.md} +5 -5
  122. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/_repeat.md → mastermind-repeat/SKILL.md} +2 -2
  123. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/research.md → mastermind-research/SKILL.md} +5 -5
  124. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/review.md → mastermind-review/SKILL.md} +5 -5
  125. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/routine-detail.md → mastermind-routine-detail/SKILL.md} +2 -2
  126. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/routines.md → mastermind-routines/SKILL.md} +2 -2
  127. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/runorgv1.md → mastermind-runorgv1/SKILL.md} +2 -2
  128. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/sales.md → mastermind-sales/SKILL.md} +5 -5
  129. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/search.md → mastermind-search/SKILL.md} +2 -2
  130. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/secrets.md → mastermind-secrets/SKILL.md} +2 -2
  131. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/skill-builder.md → mastermind-skill-builder/SKILL.md} +16 -14
  132. package/packages/@monomind/cli/.claude/skills/mastermind-skills/{skills.md → SKILL.md} +2 -2
  133. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/stoporg.md → mastermind-stoporg/SKILL.md} +2 -2
  134. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/taskdev.md → mastermind-taskdev/SKILL.md} +6 -6
  135. package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-taskdev}/implementer-prompt.md +1 -1
  136. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/tasks.md → mastermind-tasks/SKILL.md} +2 -2
  137. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/tdd.md → mastermind-tdd/SKILL.md} +4 -4
  138. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/techport.md → mastermind-techport/SKILL.md} +6 -6
  139. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/threads.md → mastermind-threads/SKILL.md} +2 -2
  140. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/tree-control.md → mastermind-tree-control/SKILL.md} +2 -2
  141. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/verify.md → mastermind-verify/SKILL.md} +1 -1
  142. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/wiki.md → mastermind-wiki/SKILL.md} +2 -2
  143. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/workspace-detail.md → mastermind-workspace-detail/SKILL.md} +2 -2
  144. package/packages/@monomind/cli/.claude/skills/{mastermind-skills/workspaces.md → mastermind-workspaces/SKILL.md} +2 -2
  145. package/packages/@monomind/cli/.claude/skills/monodesign/SKILL.md +114 -190
  146. package/packages/@monomind/cli/.claude/skills/monodesign/adapt.md +1 -1
  147. package/packages/@monomind/cli/.claude/skills/monodesign/agents/monodesign-asset-producer.md +4 -4
  148. package/packages/@monomind/cli/.claude/skills/monodesign/agents/monodesign-manual-edit-applier.md +103 -0
  149. package/packages/@monomind/cli/.claude/skills/monodesign/audit.md +1 -1
  150. package/packages/@monomind/cli/.claude/skills/monodesign/craft.md +2 -2
  151. package/packages/@monomind/cli/.claude/skills/monodesign/critique.md +1 -1
  152. package/packages/@monomind/cli/.claude/skills/monodesign/init.md +30 -0
  153. package/packages/@monomind/cli/.claude/skills/monodesign/layout.md +36 -0
  154. package/packages/@monomind/cli/.claude/skills/monodesign/live.md +19 -44
  155. package/packages/@monomind/cli/.claude/skills/monodesign/reference/adapt.md +122 -0
  156. package/packages/@monomind/cli/.claude/skills/monodesign/reference/adapt.native.md +58 -0
  157. package/packages/@monomind/cli/.claude/skills/monodesign/reference/android.md +40 -0
  158. package/packages/@monomind/cli/.claude/skills/monodesign/reference/animate.md +39 -11
  159. package/packages/@monomind/cli/.claude/skills/monodesign/reference/antipatterns-catalog.md +67 -16
  160. package/packages/@monomind/cli/.claude/skills/monodesign/reference/audit.md +5 -3
  161. package/packages/@monomind/cli/.claude/skills/monodesign/reference/audit.native.md +139 -0
  162. package/packages/@monomind/cli/.claude/skills/monodesign/reference/bolder.md +71 -64
  163. package/packages/@monomind/cli/.claude/skills/monodesign/reference/brand.md +12 -18
  164. package/packages/@monomind/cli/.claude/skills/monodesign/reference/clarify.md +114 -0
  165. package/packages/@monomind/cli/.claude/skills/monodesign/reference/codex.md +4 -6
  166. package/packages/@monomind/cli/.claude/skills/monodesign/reference/colorize.md +108 -5
  167. package/packages/@monomind/cli/.claude/skills/monodesign/reference/craft.md +70 -143
  168. package/packages/@monomind/cli/.claude/skills/monodesign/reference/critique.md +635 -68
  169. package/packages/@monomind/cli/.claude/skills/monodesign/reference/delight.md +1 -1
  170. package/packages/@monomind/cli/.claude/skills/monodesign/reference/distill.md +1 -1
  171. package/packages/@monomind/cli/.claude/skills/monodesign/reference/document.md +24 -22
  172. package/packages/@monomind/cli/.claude/skills/monodesign/reference/extract.md +1 -1
  173. package/packages/@monomind/cli/.claude/skills/monodesign/reference/hooks.md +22 -29
  174. package/packages/@monomind/cli/.claude/skills/monodesign/reference/init.md +221 -0
  175. package/packages/@monomind/cli/.claude/skills/monodesign/reference/interaction-design.md +0 -6
  176. package/packages/@monomind/cli/.claude/skills/monodesign/reference/ios.md +45 -0
  177. package/packages/@monomind/cli/.claude/skills/monodesign/reference/layout.md +57 -13
  178. package/packages/@monomind/cli/.claude/skills/monodesign/reference/live.md +159 -71
  179. package/packages/@monomind/cli/.claude/skills/monodesign/reference/overdrive.md +1 -1
  180. package/packages/@monomind/cli/.claude/skills/monodesign/reference/personas.md +1 -1
  181. package/packages/@monomind/cli/.claude/skills/monodesign/reference/polish.md +16 -8
  182. package/packages/@monomind/cli/.claude/skills/monodesign/reference/pre-delivery-checklist.md +1 -1
  183. package/packages/@monomind/cli/.claude/skills/monodesign/reference/product.md +1 -3
  184. package/packages/@monomind/cli/.claude/skills/monodesign/reference/quieter.md +1 -1
  185. package/packages/@monomind/cli/.claude/skills/monodesign/reference/shape.md +27 -13
  186. package/packages/@monomind/cli/.claude/skills/monodesign/reference/teach.md +6 -152
  187. package/packages/@monomind/cli/.claude/skills/monodesign/reference/typeset.md +180 -3
  188. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/command-metadata.json +94 -0
  189. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/context-signals.mjs +260 -0
  190. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/context.mjs +1061 -0
  191. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/critique-storage.mjs +416 -0
  192. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detect-csp.mjs +198 -0
  193. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detect.mjs +33 -0
  194. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +1962 -0
  195. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/cli/main.mjs +321 -0
  196. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/design-system.mjs +814 -0
  197. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +5601 -0
  198. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/detect-antipatterns.mjs +50 -0
  199. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/browser/detect-url.mjs +259 -0
  200. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/browser/drivers.mjs +258 -0
  201. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +636 -0
  202. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +1015 -0
  203. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +253 -0
  204. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/engines/visual/screenshot-contrast.mjs +198 -0
  205. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/findings.mjs +12 -0
  206. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/fix/css-regions.mjs +181 -0
  207. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/fix/fixers.mjs +373 -0
  208. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/fix/index.mjs +426 -0
  209. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +198 -0
  210. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/profile/profiler.mjs +166 -0
  211. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +563 -0
  212. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +2995 -0
  213. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/shared/color.mjs +124 -0
  214. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +101 -0
  215. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/shared/fonts.mjs +30 -0
  216. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +148 -0
  217. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/detector/shared/page.mjs +7 -0
  218. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/hook-admin.mjs +661 -0
  219. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/hook-before-edit.mjs +516 -0
  220. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/hook-lib.mjs +1776 -0
  221. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/hook.mjs +61 -0
  222. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/design-parser.mjs +842 -0
  223. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/is-generated.mjs +69 -0
  224. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +640 -0
  225. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +129 -0
  226. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/provider.mjs +4 -0
  227. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/lib/target-args.mjs +42 -0
  228. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/browser-script-parts.mjs +50 -0
  229. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/completion.mjs +19 -0
  230. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/event-validation.mjs +137 -0
  231. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/insert-ui.mjs +458 -0
  232. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/manual-apply.mjs +939 -0
  233. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/manual-edit-routes.mjs +357 -0
  234. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +152 -0
  235. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/session-store.mjs +293 -0
  236. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/svelte-component.mjs +826 -0
  237. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +274 -0
  238. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/ui-core.mjs +180 -0
  239. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live/vocabulary.mjs +36 -0
  240. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-accept.mjs +812 -0
  241. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-browser-dom.js +146 -0
  242. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-browser-session.js +123 -0
  243. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-browser.js +11240 -0
  244. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +1241 -0
  245. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-complete.mjs +75 -0
  246. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +683 -0
  247. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +51 -0
  248. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-inject.mjs +583 -0
  249. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-insert.mjs +272 -0
  250. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +363 -0
  251. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-poll.mjs +384 -0
  252. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-resume.mjs +94 -0
  253. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-server.mjs +1137 -0
  254. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-status.mjs +61 -0
  255. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-target.mjs +30 -0
  256. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live-wrap.mjs +894 -0
  257. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/live.mjs +297 -0
  258. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/modern-screenshot.umd.js +14 -0
  259. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/palette.mjs +633 -0
  260. package/packages/@monomind/cli/.claude/skills/monodesign/scripts/pin.mjs +221 -0
  261. package/packages/@monomind/cli/.claude/skills/monodesign/teach.md +7 -58
  262. package/packages/@monomind/cli/README.md +1 -1
  263. package/packages/@monomind/cli/dist/src/commands/design-detect.d.ts +7 -1
  264. package/packages/@monomind/cli/dist/src/commands/design-detect.js +131 -38
  265. package/packages/@monomind/cli/dist/src/commands/design-palette.d.ts +0 -1
  266. package/packages/@monomind/cli/dist/src/commands/design-palette.js +2 -3
  267. package/packages/@monomind/cli/dist/src/commands/doc.js +72 -15
  268. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +5 -1
  269. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +24 -1
  270. package/packages/@monomind/cli/dist/src/commands/doctor.js +3 -3
  271. package/packages/@monomind/cli/dist/src/commands/hooks-workers.d.ts +1 -1
  272. package/packages/@monomind/cli/dist/src/commands/hooks-workers.js +8 -8
  273. package/packages/@monomind/cli/dist/src/commands/init.js +2 -2
  274. package/packages/@monomind/cli/dist/src/commands/org.js +109 -9
  275. package/packages/@monomind/cli/dist/src/index.d.ts +1 -1
  276. package/packages/@monomind/cli/dist/src/index.js +3 -3
  277. package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +5 -5
  278. package/packages/@monomind/cli/dist/src/init/executor.js +17 -6
  279. package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.d.ts +2 -0
  280. package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.js +4 -1
  281. package/packages/@monomind/cli/dist/src/mcp-server.js +2 -2
  282. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.d.ts +1 -1
  283. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.js +1 -1
  284. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.js +2 -2
  285. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +1 -1
  286. package/packages/@monomind/cli/dist/src/mcp-tools/knowledge-tools.js +38 -7
  287. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.d.ts +8 -3
  288. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +193 -31
  289. package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +33 -0
  290. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +166 -17
  291. package/packages/@monomind/cli/dist/src/memory/memory-kg.d.ts +186 -0
  292. package/packages/@monomind/cli/dist/src/memory/memory-kg.js +450 -0
  293. package/packages/@monomind/cli/dist/src/memory/query-router.d.ts +44 -0
  294. package/packages/@monomind/cli/dist/src/memory/query-router.js +113 -0
  295. package/packages/@monomind/cli/dist/src/orgrt/daemon.d.ts +18 -0
  296. package/packages/@monomind/cli/dist/src/orgrt/daemon.js +249 -12
  297. package/packages/@monomind/cli/dist/src/orgrt/migrate.js +7 -0
  298. package/packages/@monomind/cli/dist/src/orgrt/policy.js +7 -0
  299. package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +24 -1
  300. package/packages/@monomind/cli/dist/src/orgrt/session.js +18 -3
  301. package/packages/@monomind/cli/dist/src/orgrt/templates.d.ts +1 -0
  302. package/packages/@monomind/cli/dist/src/orgrt/templates.js +9 -4
  303. package/packages/@monomind/cli/dist/src/orgrt/types.d.ts +15 -0
  304. package/packages/@monomind/cli/dist/src/orgrt/types.js +2 -0
  305. package/packages/@monomind/cli/dist/src/routing/embed-worker.js +1 -1
  306. package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -1
  307. package/packages/@monomind/cli/dist/src/routing/route-layer-factory.js +1 -1
  308. package/packages/@monomind/cli/dist/src/ui/dashboard.html +176 -26
  309. package/packages/@monomind/cli/dist/src/ui/orgs.html +24 -0
  310. package/packages/@monomind/cli/dist/src/ui/server.mjs +162 -12
  311. package/packages/@monomind/cli/dist/src/update/checker.js +3 -3
  312. package/packages/@monomind/cli/package.json +8 -6
  313. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/_agent-select.md → mastermind-agent-select/SKILL.md} +0 -0
  314. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/finish.md → mastermind-finish/SKILL.md} +0 -0
  315. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/_intake.md → mastermind-intake/SKILL.md} +0 -0
  316. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-marketing}/references/copywriting-frameworks.md +0 -0
  317. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-marketing}/references/persuasion-psychology.md +0 -0
  318. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/monotask.md → mastermind-monotask/SKILL.md} +0 -0
  319. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/receive-review.md → mastermind-receive-review/SKILL.md} +0 -0
  320. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/runorg.md → mastermind-runorg/SKILL.md} +0 -0
  321. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-taskdev}/code-quality-reviewer-prompt.md +0 -0
  322. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-taskdev}/final-reviewer-prompt.md +0 -0
  323. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills → mastermind-taskdev}/spec-reviewer-prompt.md +0 -0
  324. /package/packages/@monomind/cli/.claude/skills/{mastermind-skills/worktree.md → mastermind-worktree/SKILL.md} +0 -0
@@ -0,0 +1,939 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { getLiveDir } from '../lib/monodesign-paths.mjs';
5
+ import { readBuffer as readManualEditsBuffer } from './manual-edits-buffer.mjs';
6
+
7
+ const APPLY_EVENT_HARD_TIMEOUT_MS = Number(process.env.MONODESIGN_LIVE_APPLY_EVENT_HARD_TIMEOUT_MS || 150_000);
8
+ const APPLY_EVENT_SOFT_DEADLINE_MS = Number(process.env.MONODESIGN_LIVE_APPLY_EVENT_SOFT_DEADLINE_MS || 120_000);
9
+ const DEFAULT_MANUAL_EDIT_APPLY_CHUNK_SIZE = 3;
10
+ const MIN_MANUAL_EDIT_APPLY_CHUNK_SIZE = 1;
11
+ const MAX_MANUAL_EDIT_APPLY_CHUNK_SIZE = 20;
12
+ const MANUAL_APPLY_COMPACT_TEXT_LIMIT = 240;
13
+ const MANUAL_APPLY_COMPACT_NEARBY_LIMIT = 4;
14
+
15
+ export function createManualApplyController({
16
+ pendingEvents,
17
+ pendingApplyDeferreds,
18
+ timedOutApplyIds,
19
+ enqueueEvent,
20
+ acknowledgePendingEvent,
21
+ flushPendingPolls,
22
+ recordManualEditActivity,
23
+ cwd = () => process.cwd(),
24
+ } = {}) {
25
+ const projectCwd = () => typeof cwd === 'function' ? cwd() : cwd || process.cwd();
26
+
27
+ function tombstoneTimedOutApplyId(eventId, details = {}) {
28
+ if (!eventId) return;
29
+ timedOutApplyIds.set(eventId, details);
30
+ if (timedOutApplyIds.size <= 200) return;
31
+ const oldest = timedOutApplyIds.keys().next().value;
32
+ timedOutApplyIds.delete(oldest);
33
+ }
34
+
35
+ function pushApplyEventAndWait(batch, pageUrl, chunk = null, repair = null) {
36
+ const cwdValue = projectCwd();
37
+ const eventId = randomUUID().replace(/-/g, '').slice(0, 8);
38
+ const evidencePath = writeManualApplyEvidence(eventId, batch, cwdValue);
39
+ const event = {
40
+ type: 'manual_edit_apply',
41
+ id: eventId,
42
+ pageUrl,
43
+ batch: compactManualApplyBatch(batch, cwdValue),
44
+ evidencePath,
45
+ agentAction: buildManualApplyAgentAction(eventId),
46
+ schemaVersion: 1,
47
+ deadlineMs: APPLY_EVENT_SOFT_DEADLINE_MS,
48
+ };
49
+ if (chunk) event.chunk = chunk;
50
+ if (repair) event.repair = repair;
51
+ const rollbackSnapshot = snapshotApplyEventFiles(batch, cwdValue);
52
+ recordManualEditActivity('manual_edit_apply_dispatched', {
53
+ id: eventId,
54
+ pageUrl,
55
+ chunk,
56
+ repair,
57
+ entryCount: Array.isArray(batch.entries) ? batch.entries.length : 0,
58
+ opCount: countManualApplyOps(batch),
59
+ fileCount: collectManualApplyFiles(batch, [], cwdValue).length,
60
+ });
61
+ return new Promise((resolve, reject) => {
62
+ const timer = setTimeout(() => {
63
+ pendingApplyDeferreds.delete(eventId);
64
+ tombstoneTimedOutApplyId(eventId, { batch, rollbackSnapshot, cwd: cwdValue });
65
+ acknowledgePendingEvent(eventId);
66
+ removeManualApplyEvidence(evidencePath, cwdValue);
67
+ recordManualEditActivity('manual_edit_apply_timeout', {
68
+ id: eventId,
69
+ pageUrl,
70
+ chunk,
71
+ entryCount: Array.isArray(batch.entries) ? batch.entries.length : 0,
72
+ opCount: countManualApplyOps(batch),
73
+ });
74
+ reject(new Error('chat_agent_timeout'));
75
+ }, APPLY_EVENT_HARD_TIMEOUT_MS);
76
+ pendingApplyDeferreds.set(eventId, { resolve, reject, timer, event, batch, pageUrl, rollbackSnapshot, cwd: cwdValue });
77
+ enqueueEvent(event);
78
+ });
79
+ }
80
+
81
+ async function pushBatchInChunksAndWait(batch, pageUrl, context = {}) {
82
+ const repair = context?.repair || batch?.repair || null;
83
+ if (repair) return pushApplyEventAndWait(batch, pageUrl, null, repair);
84
+ const chunks = splitManualApplyBatch(batch, manualEditApplyChunkSize());
85
+ if (chunks.length <= 1) return pushApplyEventAndWait(batch, pageUrl);
86
+
87
+ const expectedOpsByEntry = new Map();
88
+ for (const entry of batch?.entries || []) {
89
+ expectedOpsByEntry.set(entry.id, Array.isArray(entry.ops) ? entry.ops.length : 0);
90
+ }
91
+
92
+ const appliedOpsByEntry = new Map();
93
+ const failedByEntry = new Map();
94
+ const files = new Set();
95
+ const notes = [];
96
+ let aborted = false;
97
+
98
+ for (const chunk of chunks) {
99
+ if (aborted) {
100
+ markChunkEntriesFailed(failedByEntry, chunk, 'manual_edit_chunk_aborted');
101
+ continue;
102
+ }
103
+
104
+ let result;
105
+ try {
106
+ result = normalizeApplyChunkResult(await pushApplyEventAndWait(chunk.batch, pageUrl, chunk.meta));
107
+ } catch (err) {
108
+ markChunkEntriesFailed(failedByEntry, chunk, err.message || 'chat_agent_error');
109
+ aborted = true;
110
+ continue;
111
+ }
112
+
113
+ for (const file of result.files) files.add(file);
114
+ notes.push(...result.notes);
115
+
116
+ const chunkFailedIds = new Set();
117
+ for (const item of result.failed) {
118
+ const entryId = item.entryId || item.id;
119
+ if (!entryId) continue;
120
+ chunkFailedIds.add(entryId);
121
+ if (!failedByEntry.has(entryId)) {
122
+ failedByEntry.set(entryId, {
123
+ entryId,
124
+ reason: item.reason || item.message || 'failed',
125
+ candidates: Array.isArray(item.candidates) ? item.candidates : [],
126
+ });
127
+ }
128
+ }
129
+
130
+ if (result.status === 'error') {
131
+ markChunkEntriesFailed(failedByEntry, chunk, result.message || firstFailureReason(result) || 'chat_agent_error');
132
+ aborted = true;
133
+ continue;
134
+ }
135
+
136
+ const reportedAppliedIds = new Set(result.appliedEntryIds);
137
+ for (const entryId of reportedAppliedIds) {
138
+ if (!chunk.entryIds.has(entryId) || chunkFailedIds.has(entryId)) continue;
139
+ appliedOpsByEntry.set(entryId, (appliedOpsByEntry.get(entryId) || 0) + (chunk.opCountsByEntry.get(entryId) || 0));
140
+ }
141
+
142
+ for (const entryId of chunk.entryIds) {
143
+ if (reportedAppliedIds.has(entryId) || chunkFailedIds.has(entryId)) continue;
144
+ if (!failedByEntry.has(entryId)) {
145
+ failedByEntry.set(entryId, { entryId, reason: 'not_reported_applied', candidates: [] });
146
+ }
147
+ }
148
+ }
149
+
150
+ const appliedEntryIds = [];
151
+ for (const [entryId, expectedOps] of expectedOpsByEntry.entries()) {
152
+ if (failedByEntry.has(entryId)) continue;
153
+ if ((appliedOpsByEntry.get(entryId) || 0) === expectedOps && expectedOps > 0) {
154
+ appliedEntryIds.push(entryId);
155
+ } else if (!failedByEntry.has(entryId)) {
156
+ failedByEntry.set(entryId, { entryId, reason: 'not_reported_applied', candidates: [] });
157
+ }
158
+ }
159
+
160
+ const failed = [...failedByEntry.values()];
161
+ return {
162
+ status: failed.length === 0 ? 'done' : appliedEntryIds.length > 0 ? 'partial' : 'error',
163
+ appliedEntryIds,
164
+ failed,
165
+ files: [...files],
166
+ notes,
167
+ };
168
+ }
169
+
170
+ function getDeferred(eventId) {
171
+ return pendingApplyDeferreds.get(eventId) || null;
172
+ }
173
+
174
+ function hasTimedOutId(eventId) {
175
+ return timedOutApplyIds.has(eventId);
176
+ }
177
+
178
+ function resolveDeferred(eventId, body) {
179
+ const deferred = pendingApplyDeferreds.get(eventId);
180
+ if (!deferred) return false;
181
+ pendingApplyDeferreds.delete(eventId);
182
+ clearTimeout(deferred.timer);
183
+ removeManualApplyEvidence(deferred.event?.evidencePath, deferred.cwd || projectCwd());
184
+ deferred.resolve(body);
185
+ return true;
186
+ }
187
+
188
+ function rejectDeferred(eventId, reason) {
189
+ const deferred = pendingApplyDeferreds.get(eventId);
190
+ if (!deferred) return false;
191
+ pendingApplyDeferreds.delete(eventId);
192
+ clearTimeout(deferred.timer);
193
+ removeManualApplyEvidence(deferred.event?.evidencePath, deferred.cwd || projectCwd());
194
+ deferred.reject(new Error(reason || 'chat_agent_error'));
195
+ return true;
196
+ }
197
+
198
+ function referencedManualApplyEvidencePaths(cwdValue = projectCwd()) {
199
+ const referenced = new Set();
200
+ const add = (event) => {
201
+ const fullPath = normalizeManualApplyEvidencePath(event?.evidencePath, cwdValue);
202
+ if (fullPath) referenced.add(fullPath);
203
+ };
204
+ for (const entry of pendingEvents) add(entry.event);
205
+ for (const deferred of pendingApplyDeferreds.values()) add(deferred.event);
206
+ return referenced;
207
+ }
208
+
209
+ function pruneStaleEvidence(cwdValue = projectCwd()) {
210
+ const dir = manualApplyEvidenceDir(cwdValue);
211
+ if (!fs.existsSync(dir)) return [];
212
+ const referenced = referencedManualApplyEvidencePaths(cwdValue);
213
+ const removed = [];
214
+ for (const name of fs.readdirSync(dir)) {
215
+ if (!name.endsWith('.json')) continue;
216
+ const fullPath = path.join(dir, name);
217
+ if (referenced.has(fullPath)) continue;
218
+ try {
219
+ fs.unlinkSync(fullPath);
220
+ removed.push(fullPath);
221
+ } catch {
222
+ // Stale evidence cleanup is best-effort; Apply verification never relies
223
+ // on deleting these files.
224
+ }
225
+ }
226
+ return removed;
227
+ }
228
+
229
+ function rollbackTimedOutReply(msg) {
230
+ const details = timedOutApplyIds.get(msg.id);
231
+ if (!details) return { rolledBackFiles: [], rollbackFailures: [] };
232
+ timedOutApplyIds.delete(msg.id);
233
+ return rollbackApplySnapshot(
234
+ details.batch,
235
+ details.rollbackSnapshot,
236
+ msg.data?.files || [],
237
+ 'stale_manual_edit_apply_reply',
238
+ details.cwd || projectCwd(),
239
+ );
240
+ }
241
+
242
+ function cancelPendingEvents(pageUrl, reason = 'manual_edit_discarded') {
243
+ const canceledById = new Map();
244
+ const shouldCancel = (event) => event?.type === 'manual_edit_apply' && (!pageUrl || event.pageUrl === pageUrl);
245
+
246
+ for (let i = pendingEvents.length - 1; i >= 0; i -= 1) {
247
+ const event = pendingEvents[i]?.event;
248
+ if (!shouldCancel(event)) continue;
249
+ pendingEvents.splice(i, 1);
250
+ removeManualApplyEvidence(event.evidencePath, projectCwd());
251
+ canceledById.set(event.id, {
252
+ id: event.id,
253
+ pageUrl: event.pageUrl,
254
+ entryCount: event.batch?.entries?.length || 0,
255
+ });
256
+ }
257
+
258
+ for (const [eventId, deferred] of [...pendingApplyDeferreds.entries()]) {
259
+ if (!shouldCancel(deferred.event)) continue;
260
+ pendingApplyDeferreds.delete(eventId);
261
+ clearTimeout(deferred.timer);
262
+ const cwdValue = deferred.cwd || projectCwd();
263
+ const rollback = rollbackApplySnapshot(deferred.batch, deferred.rollbackSnapshot, [], reason, cwdValue);
264
+ tombstoneTimedOutApplyId(eventId, {
265
+ batch: deferred.batch,
266
+ rollbackSnapshot: deferred.rollbackSnapshot,
267
+ reason,
268
+ cwd: cwdValue,
269
+ });
270
+ removeManualApplyEvidence(deferred.event?.evidencePath, cwdValue);
271
+ canceledById.set(eventId, {
272
+ id: eventId,
273
+ pageUrl: deferred.pageUrl,
274
+ entryCount: deferred.batch?.entries?.length || 0,
275
+ rolledBackFiles: rollback.rolledBackFiles,
276
+ rollbackFailures: rollback.rollbackFailures,
277
+ });
278
+ deferred.reject(new Error(reason));
279
+ }
280
+
281
+ if (canceledById.size > 0) flushPendingPolls();
282
+ return [...canceledById.values()];
283
+ }
284
+
285
+ return {
286
+ buildAgentAction: buildManualApplyAgentAction,
287
+ cancelPendingEvents,
288
+ clearTransaction: (transactionId = null) => clearManualApplyTransaction(projectCwd(), transactionId),
289
+ countOps: countManualApplyOps,
290
+ getDeferred,
291
+ hasTimedOutId,
292
+ pruneStaleEvidence,
293
+ pushBatchInChunksAndWait,
294
+ readTransaction: () => readManualApplyTransaction(projectCwd()),
295
+ rejectDeferred,
296
+ resolveDeferred,
297
+ rollbackTimedOutReply,
298
+ rollbackTransaction: (opts = {}) => rollbackManualApplyTransaction({
299
+ cwd: projectCwd(),
300
+ recordManualEditActivity,
301
+ ...opts,
302
+ }),
303
+ summarizeEvent: (event = {}, batch = event.batch) => summarizeManualApplyEvent(event, batch, projectCwd()),
304
+ validateResultMessage: validateManualApplyResultMessage,
305
+ writeTransaction: (opts = {}) => writeManualApplyTransaction({ cwd: projectCwd(), ...opts }),
306
+ };
307
+ }
308
+
309
+ export function manualEditApplyChunkSize(env = process.env) {
310
+ const raw = Number(env.MONODESIGN_LIVE_MANUAL_EDIT_CHUNK_SIZE);
311
+ if (!Number.isFinite(raw)) return DEFAULT_MANUAL_EDIT_APPLY_CHUNK_SIZE;
312
+ const size = Math.trunc(raw);
313
+ return Math.max(MIN_MANUAL_EDIT_APPLY_CHUNK_SIZE, Math.min(MAX_MANUAL_EDIT_APPLY_CHUNK_SIZE, size));
314
+ }
315
+
316
+ export function countManualApplyOps(entriesOrBatch) {
317
+ const entries = Array.isArray(entriesOrBatch)
318
+ ? entriesOrBatch
319
+ : Array.isArray(entriesOrBatch?.entries) ? entriesOrBatch.entries : [];
320
+ let count = 0;
321
+ for (const entry of entries) count += Array.isArray(entry.ops) ? entry.ops.length : 0;
322
+ return count;
323
+ }
324
+
325
+ export function writeManualApplyEvidence(eventId, batch, cwd = process.cwd()) {
326
+ const dir = manualApplyEvidenceDir(cwd);
327
+ fs.mkdirSync(dir, { recursive: true });
328
+ const evidencePath = path.join(dir, `${eventId}.json`);
329
+ fs.writeFileSync(evidencePath, JSON.stringify(batch, null, 2) + '\n', 'utf-8');
330
+ return evidencePath;
331
+ }
332
+
333
+ export function manualApplyEvidenceDir(cwd = process.cwd()) {
334
+ return path.join(getLiveDir(cwd), 'manual-edit-evidence');
335
+ }
336
+
337
+ export function normalizeManualApplyEvidencePath(evidencePath, cwd = process.cwd()) {
338
+ if (!evidencePath || typeof evidencePath !== 'string') return null;
339
+ const fullPath = path.isAbsolute(evidencePath) ? evidencePath : path.resolve(cwd, evidencePath);
340
+ const evidenceDir = manualApplyEvidenceDir(cwd);
341
+ const relative = path.relative(evidenceDir, fullPath);
342
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) return null;
343
+ if (path.extname(relative) !== '.json') return null;
344
+ return fullPath;
345
+ }
346
+
347
+ export function removeManualApplyEvidence(evidencePath, cwd = process.cwd()) {
348
+ const fullPath = normalizeManualApplyEvidencePath(evidencePath, cwd);
349
+ if (!fullPath) return false;
350
+ try {
351
+ fs.unlinkSync(fullPath);
352
+ return true;
353
+ } catch {
354
+ return false;
355
+ }
356
+ }
357
+
358
+ export function compactManualApplyBatch(batch = {}, cwd = process.cwd()) {
359
+ const entries = (batch.entries || []).map(compactManualApplyEntry);
360
+ const candidates = compactManualApplyCandidates(batch.candidates || [], cwd);
361
+ return {
362
+ version: batch.version,
363
+ pageUrl: batch.pageUrl || null,
364
+ count: batch.count,
365
+ entries,
366
+ ops: entries.flatMap((entry) => entry.ops.map((op) => ({ ...op, entryId: entry.id }))),
367
+ candidates: candidates.length > 0 ? candidates : undefined,
368
+ context: batch.context ? {
369
+ bufferPath: batch.context.bufferPath,
370
+ totalEntries: batch.context.totalEntries,
371
+ totalOps: batch.context.totalOps,
372
+ chunkIndex: batch.context.chunkIndex,
373
+ chunkTotal: batch.context.chunkTotal,
374
+ totalApplyOps: batch.context.totalApplyOps,
375
+ } : undefined,
376
+ };
377
+ }
378
+
379
+ export function compactManualApplyCandidates(candidates, cwd = process.cwd()) {
380
+ return (Array.isArray(candidates) ? candidates : [])
381
+ .slice(0, 24)
382
+ .map((candidate) => ({
383
+ entryId: candidate.entryId,
384
+ ref: candidate.ref,
385
+ sourceHint: compactManualApplySourceMatch(candidate.sourceHint, cwd),
386
+ textMatches: compactManualApplySourceMatches(candidate.textMatches, 8, cwd),
387
+ objectKeyMatches: compactManualApplySourceMatches(candidate.objectKeyMatches, 8, cwd),
388
+ contextTextMatches: compactManualApplySourceMatches(candidate.contextTextMatches, 8, cwd),
389
+ locatorMatches: compactManualApplySourceMatches(candidate.locatorMatches, 6, cwd),
390
+ }));
391
+ }
392
+
393
+ function compactManualApplySourceMatches(matches, limit, cwd) {
394
+ return (Array.isArray(matches) ? matches : [])
395
+ .slice(0, limit)
396
+ .map((match) => compactManualApplySourceMatch(match, cwd))
397
+ .filter(Boolean);
398
+ }
399
+
400
+ function compactManualApplySourceMatch(match, cwd) {
401
+ if (!match || typeof match !== 'object') return null;
402
+ const file = match.relativeFile || match.file;
403
+ if (!file && !match.line) return null;
404
+ return {
405
+ file: summarizeManualLogFile(file, cwd),
406
+ line: match.line || null,
407
+ column: match.column || null,
408
+ reason: match.reason || match.kind || undefined,
409
+ status: match.status || undefined,
410
+ };
411
+ }
412
+
413
+ function compactManualApplyEntry(entry = {}) {
414
+ return {
415
+ id: entry.id,
416
+ pageUrl: entry.pageUrl,
417
+ stagedAt: entry.stagedAt || null,
418
+ element: compactManualApplyContext(entry.element),
419
+ ops: (entry.ops || []).map(compactManualApplyOp),
420
+ };
421
+ }
422
+
423
+ function compactManualApplyOp(op = {}) {
424
+ return {
425
+ entryId: op.entryId,
426
+ ref: op.ref,
427
+ contextRef: op.contextRef,
428
+ tag: op.tag,
429
+ elementId: op.elementId,
430
+ classes: Array.isArray(op.classes) ? op.classes : [],
431
+ originalText: op.originalText,
432
+ newText: op.newText,
433
+ deleted: op.deleted === true || undefined,
434
+ sourceHint: op.sourceHint || null,
435
+ leaf: compactManualApplyContext(op.leaf),
436
+ nearbyEditableTexts: compactNearbyManualEditTexts(op.nearbyEditableTexts),
437
+ container: compactManualApplyContext(op.container),
438
+ contextHints: Array.isArray(op.contextHints) ? op.contextHints.slice(0, 8) : undefined,
439
+ };
440
+ }
441
+
442
+ function compactManualApplyContext(value) {
443
+ if (!value || typeof value !== 'object') return null;
444
+ return {
445
+ ref: value.ref,
446
+ tagName: value.tagName || value.tag || null,
447
+ id: value.id || null,
448
+ classes: Array.isArray(value.classes) ? value.classes : [],
449
+ textContent: truncateManualApplyText(value.textContent, MANUAL_APPLY_COMPACT_TEXT_LIMIT),
450
+ };
451
+ }
452
+
453
+ function compactNearbyManualEditTexts(items) {
454
+ return (Array.isArray(items) ? items : [])
455
+ .slice(0, MANUAL_APPLY_COMPACT_NEARBY_LIMIT)
456
+ .map((item) => typeof item === 'string' ? { text: truncateManualApplyText(item, MANUAL_APPLY_COMPACT_TEXT_LIMIT) } : {
457
+ ref: item?.ref,
458
+ tag: item?.tag,
459
+ classes: Array.isArray(item?.classes) ? item.classes : [],
460
+ text: truncateManualApplyText(item?.text, MANUAL_APPLY_COMPACT_TEXT_LIMIT),
461
+ });
462
+ }
463
+
464
+ function truncateManualApplyText(value, max) {
465
+ if (typeof value !== 'string') return value || null;
466
+ return value.length > max ? value.slice(0, max) : value;
467
+ }
468
+
469
+ function normalizeApplyChunkResult(result) {
470
+ const status = result?.status === 'partial' ? 'partial' : result?.status === 'error' ? 'error' : 'done';
471
+ return {
472
+ status,
473
+ message: typeof result?.message === 'string' ? result.message : null,
474
+ appliedEntryIds: Array.isArray(result?.appliedEntryIds) ? result.appliedEntryIds.filter((id) => typeof id === 'string') : [],
475
+ failed: Array.isArray(result?.failed) ? result.failed.filter(Boolean) : [],
476
+ files: Array.isArray(result?.files) ? result.files.filter((file) => typeof file === 'string') : [],
477
+ notes: Array.isArray(result?.notes) ? result.notes.filter((note) => typeof note === 'string') : [],
478
+ };
479
+ }
480
+
481
+ function manualApplyResultShapeHint(eventId = 'EVENT_ID') {
482
+ return `Use live-poll.mjs --reply ${eventId} done --data '{"status":"done","appliedEntryIds":["ENTRY_ID"],"failed":[],"files":["src/page.html"],"notes":[]}'`;
483
+ }
484
+
485
+ function invalidManualApplyResult(reason, eventId, extra = {}) {
486
+ return {
487
+ ok: false,
488
+ body: {
489
+ error: 'invalid_manual_apply_result',
490
+ reason,
491
+ hint: manualApplyResultShapeHint(eventId),
492
+ ...extra,
493
+ },
494
+ };
495
+ }
496
+
497
+ export function validateManualApplyResultMessage(msg, deferred) {
498
+ let data = msg?.data;
499
+ const eventId = msg?.id || deferred?.event?.id || 'EVENT_ID';
500
+ if (!data || typeof data !== 'object' || Array.isArray(data)) {
501
+ return invalidManualApplyResult('missing_result_data', eventId);
502
+ }
503
+ if ('entries' in data || 'ops' in data) {
504
+ return invalidManualApplyResult('summary_result_not_allowed', eventId);
505
+ }
506
+ if (!['done', 'partial', 'error'].includes(data.status)) {
507
+ return invalidManualApplyResult('invalid_status', eventId, { status: data.status ?? null });
508
+ }
509
+
510
+ for (const key of ['appliedEntryIds', 'failed', 'files', 'notes']) {
511
+ if (!Array.isArray(data[key])) {
512
+ return invalidManualApplyResult(`${key}_must_be_array`, eventId);
513
+ }
514
+ }
515
+
516
+ for (const [index, value] of data.appliedEntryIds.entries()) {
517
+ if (typeof value !== 'string' || !value) {
518
+ return invalidManualApplyResult('appliedEntryIds_must_contain_strings', eventId, { index });
519
+ }
520
+ }
521
+ for (const [index, value] of data.files.entries()) {
522
+ if (typeof value !== 'string' || !value) {
523
+ return invalidManualApplyResult('files_must_contain_strings', eventId, { index });
524
+ }
525
+ }
526
+ for (const [index, value] of data.notes.entries()) {
527
+ if (typeof value !== 'string') {
528
+ return invalidManualApplyResult('notes_must_contain_strings', eventId, { index });
529
+ }
530
+ }
531
+ for (const [index, item] of data.failed.entries()) {
532
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
533
+ return invalidManualApplyResult('failed_must_contain_objects', eventId, { index });
534
+ }
535
+ if (typeof item.entryId !== 'string' || !item.entryId) {
536
+ return invalidManualApplyResult('failed_entryId_required', eventId, { index });
537
+ }
538
+ if (typeof item.reason !== 'string' || !item.reason) {
539
+ return invalidManualApplyResult('failed_reason_required', eventId, { index });
540
+ }
541
+ }
542
+
543
+ const eventEntryIds = new Set((deferred?.batch?.entries || []).map((entry) => entry.id).filter(Boolean));
544
+ for (const entryId of data.appliedEntryIds) {
545
+ if (eventEntryIds.size > 0 && !eventEntryIds.has(entryId)) {
546
+ return invalidManualApplyResult('applied_entry_id_not_in_event', eventId, { entryId });
547
+ }
548
+ }
549
+ for (const item of data.failed) {
550
+ if (eventEntryIds.size > 0 && !eventEntryIds.has(item.entryId)) {
551
+ return invalidManualApplyResult('failed_entry_id_not_in_event', eventId, { entryId: item.entryId });
552
+ }
553
+ }
554
+
555
+ if (data.status === 'done') {
556
+ if (data.failed.length > 0) {
557
+ return invalidManualApplyResult('done_result_has_failed_entries', eventId);
558
+ }
559
+ if (countManualApplyOps(deferred?.batch) > 0 && data.appliedEntryIds.length === 0) {
560
+ return invalidManualApplyResult('done_result_missing_applied_entry_ids', eventId);
561
+ }
562
+ }
563
+ if (data.status === 'partial' && data.appliedEntryIds.length === 0 && data.failed.length === 0) {
564
+ return invalidManualApplyResult('partial_result_has_no_entries', eventId);
565
+ }
566
+ if (data.status === 'error' && data.appliedEntryIds.length > 0) {
567
+ return invalidManualApplyResult('error_result_has_applied_entries', eventId);
568
+ }
569
+
570
+ return {
571
+ ok: true,
572
+ result: {
573
+ status: data.status,
574
+ message: typeof data.message === 'string' ? data.message : undefined,
575
+ appliedEntryIds: data.appliedEntryIds,
576
+ failed: data.failed,
577
+ files: data.files,
578
+ notes: data.notes,
579
+ },
580
+ };
581
+ }
582
+
583
+ function firstFailureReason(result) {
584
+ const first = Array.isArray(result?.failed) ? result.failed.find(Boolean) : null;
585
+ return first?.reason || first?.message || null;
586
+ }
587
+
588
+ function markChunkEntriesFailed(failedByEntry, chunk, reason) {
589
+ for (const entryId of chunk.entryIds) {
590
+ if (failedByEntry.has(entryId)) continue;
591
+ failedByEntry.set(entryId, { entryId, reason, candidates: [] });
592
+ }
593
+ }
594
+
595
+ export function splitManualApplyBatch(batch, maxOps) {
596
+ const totalOpCount = countManualApplyOps(batch);
597
+ if (totalOpCount <= maxOps) {
598
+ return [{
599
+ batch,
600
+ meta: null,
601
+ entryIds: new Set((batch?.entries || []).map((entry) => entry.id).filter(Boolean)),
602
+ opCountsByEntry: new Map((batch?.entries || []).map((entry) => [entry.id, Array.isArray(entry.ops) ? entry.ops.length : 0])),
603
+ }];
604
+ }
605
+
606
+ const rawChunks = [];
607
+ let current = createManualApplyChunkBuilder();
608
+ for (const entry of batch?.entries || []) {
609
+ const ops = entry.ops || [];
610
+ if (ops.length <= maxOps) {
611
+ if (current.opCount > 0 && current.opCount + ops.length > maxOps) {
612
+ rawChunks.push(current);
613
+ current = createManualApplyChunkBuilder();
614
+ }
615
+ for (const op of ops) addOpToManualApplyChunk(current, entry, op);
616
+ continue;
617
+ }
618
+ if (current.opCount > 0) {
619
+ rawChunks.push(current);
620
+ current = createManualApplyChunkBuilder();
621
+ }
622
+ for (const op of ops) {
623
+ if (current.opCount >= maxOps) {
624
+ rawChunks.push(current);
625
+ current = createManualApplyChunkBuilder();
626
+ }
627
+ addOpToManualApplyChunk(current, entry, op);
628
+ }
629
+ }
630
+ if (current.opCount > 0) rawChunks.push(current);
631
+
632
+ return rawChunks.map((chunk, index) => ({
633
+ batch: {
634
+ ...batch,
635
+ count: chunk.opCount,
636
+ entries: chunk.entries,
637
+ ops: chunk.ops,
638
+ candidates: filterManualApplyChunkCandidates(batch, chunk.refsByEntry),
639
+ context: {
640
+ ...(batch?.context || {}),
641
+ totalEntries: chunk.entries.length,
642
+ totalOps: chunk.opCount,
643
+ chunkIndex: index + 1,
644
+ chunkTotal: rawChunks.length,
645
+ totalApplyOps: totalOpCount,
646
+ },
647
+ },
648
+ meta: {
649
+ index: index + 1,
650
+ total: rawChunks.length,
651
+ opCount: chunk.opCount,
652
+ totalOpCount,
653
+ },
654
+ entryIds: new Set(chunk.entries.map((entry) => entry.id).filter(Boolean)),
655
+ opCountsByEntry: chunk.opCountsByEntry,
656
+ }));
657
+ }
658
+
659
+ function createManualApplyChunkBuilder() {
660
+ return {
661
+ entries: [],
662
+ entryById: new Map(),
663
+ entryIds: new Set(),
664
+ ops: [],
665
+ refsByEntry: new Map(),
666
+ opCountsByEntry: new Map(),
667
+ opCount: 0,
668
+ };
669
+ }
670
+
671
+ function addOpToManualApplyChunk(chunk, entry, op) {
672
+ let chunkEntry = chunk.entryById.get(entry.id);
673
+ if (!chunkEntry) {
674
+ chunkEntry = { ...entry, ops: [] };
675
+ chunk.entryById.set(entry.id, chunkEntry);
676
+ chunk.entryIds.add(entry.id);
677
+ chunk.entries.push(chunkEntry);
678
+ }
679
+ chunkEntry.ops.push(op);
680
+ chunk.ops.push({ ...op, entryId: op.entryId || entry.id });
681
+ if (!chunk.refsByEntry.has(entry.id)) chunk.refsByEntry.set(entry.id, new Set());
682
+ if (op.ref) chunk.refsByEntry.get(entry.id).add(op.ref);
683
+ chunk.opCountsByEntry.set(entry.id, (chunk.opCountsByEntry.get(entry.id) || 0) + 1);
684
+ chunk.opCount += 1;
685
+ }
686
+
687
+ function filterManualApplyChunkCandidates(batch, refsByEntry) {
688
+ return (batch?.candidates || []).filter((candidate) => {
689
+ const refs = refsByEntry.get(candidate.entryId);
690
+ if (!refs) return false;
691
+ if (!candidate.ref) return true;
692
+ return refs.has(candidate.ref);
693
+ });
694
+ }
695
+
696
+ export function snapshotApplyEventFiles(batch, cwd = process.cwd()) {
697
+ const snapshot = new Map();
698
+ for (const relativeFile of collectManualApplyFiles(batch, [], cwd)) {
699
+ const absolute = path.resolve(cwd, relativeFile);
700
+ try {
701
+ snapshot.set(relativeFile, {
702
+ exists: fs.existsSync(absolute),
703
+ content: fs.existsSync(absolute) ? fs.readFileSync(absolute, 'utf-8') : '',
704
+ });
705
+ } catch {
706
+ // If a file cannot be read before dispatch, do not attempt late rollback.
707
+ }
708
+ }
709
+ return snapshot;
710
+ }
711
+
712
+ export function manualApplyTransactionPath(cwd = process.cwd()) {
713
+ return path.join(getLiveDir(cwd), 'manual-edit-apply-transaction.json');
714
+ }
715
+
716
+ export function readManualApplyTransaction(cwd = process.cwd()) {
717
+ const file = manualApplyTransactionPath(cwd);
718
+ if (!fs.existsSync(file)) return null;
719
+ try {
720
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
721
+ } catch {
722
+ return null;
723
+ }
724
+ }
725
+
726
+ export function writeManualApplyTransaction({ cwd = process.cwd(), pageUrl = null, batch }) {
727
+ const file = manualApplyTransactionPath(cwd);
728
+ const files = collectManualApplyFiles(batch, [], cwd);
729
+ const transaction = {
730
+ version: 1,
731
+ id: randomUUID().replace(/-/g, '').slice(0, 8),
732
+ createdAt: new Date().toISOString(),
733
+ pageUrl,
734
+ entryIds: (batch?.entries || []).map((entry) => entry.id).filter(Boolean),
735
+ files: files.map((relativeFile) => {
736
+ const absolute = path.resolve(cwd, relativeFile);
737
+ const exists = fs.existsSync(absolute);
738
+ return {
739
+ file: relativeFile,
740
+ exists,
741
+ content: exists ? fs.readFileSync(absolute, 'utf-8') : '',
742
+ };
743
+ }),
744
+ };
745
+ fs.mkdirSync(path.dirname(file), { recursive: true });
746
+ fs.writeFileSync(`${file}.tmp`, JSON.stringify(transaction, null, 2) + '\n', 'utf-8');
747
+ fs.renameSync(`${file}.tmp`, file);
748
+ return transaction;
749
+ }
750
+
751
+ export function clearManualApplyTransaction(cwd = process.cwd(), transactionId = null) {
752
+ const file = manualApplyTransactionPath(cwd);
753
+ if (!fs.existsSync(file)) return false;
754
+ if (transactionId) {
755
+ const existing = readManualApplyTransaction(cwd);
756
+ if (existing?.id && existing.id !== transactionId) return false;
757
+ }
758
+ try {
759
+ fs.unlinkSync(file);
760
+ return true;
761
+ } catch {
762
+ return false;
763
+ }
764
+ }
765
+
766
+ export function rollbackManualApplyTransaction({
767
+ cwd = process.cwd(),
768
+ pageUrl = null,
769
+ reason = 'manual_edit_transaction_rollback',
770
+ recordManualEditActivity = null,
771
+ } = {}) {
772
+ const transaction = readManualApplyTransaction(cwd);
773
+ if (!transaction) return null;
774
+ if (pageUrl && transaction.pageUrl && transaction.pageUrl !== pageUrl) return null;
775
+
776
+ let pendingIds = new Set();
777
+ try {
778
+ const buffer = readManualEditsBuffer(cwd);
779
+ pendingIds = new Set((buffer.entries || []).map((entry) => entry.id).filter(Boolean));
780
+ } catch {
781
+ pendingIds = new Set(transaction.entryIds || []);
782
+ }
783
+ const shouldRollback = (transaction.entryIds || []).some((id) => pendingIds.has(id));
784
+ if (!shouldRollback) {
785
+ clearManualApplyTransaction(cwd, transaction.id);
786
+ return { id: transaction.id, reason, rolledBackFiles: [], rollbackFailures: [], skipped: 'entries_not_pending' };
787
+ }
788
+
789
+ const rolledBackFiles = [];
790
+ const rollbackFailures = [];
791
+ for (const item of transaction.files || []) {
792
+ const relativeFile = normalizeProjectFile(item.file, cwd);
793
+ if (!relativeFile) continue;
794
+ const absolute = path.resolve(cwd, relativeFile);
795
+ try {
796
+ if (item.exists) {
797
+ fs.mkdirSync(path.dirname(absolute), { recursive: true });
798
+ fs.writeFileSync(absolute, item.content || '', 'utf-8');
799
+ } else if (fs.existsSync(absolute)) {
800
+ fs.rmSync(absolute);
801
+ }
802
+ rolledBackFiles.push(relativeFile);
803
+ } catch (err) {
804
+ rollbackFailures.push({ file: relativeFile, reason: 'restore_failed', message: err.message || String(err) });
805
+ }
806
+ }
807
+ clearManualApplyTransaction(cwd, transaction.id);
808
+ recordManualEditActivity?.('manual_edit_transaction_rolled_back', {
809
+ id: transaction.id,
810
+ pageUrl: transaction.pageUrl || null,
811
+ reason,
812
+ entryIds: transaction.entryIds || [],
813
+ rolledBackFiles: rolledBackFiles.map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean),
814
+ rollbackFailures: summarizeManualDiagnostics(rollbackFailures, cwd),
815
+ });
816
+ return { id: transaction.id, reason, rolledBackFiles, rollbackFailures };
817
+ }
818
+
819
+ export function collectManualApplyFiles(batch, extraFiles = [], cwd = process.cwd()) {
820
+ const files = [];
821
+ for (const entry of batch?.entries || []) {
822
+ for (const op of entry.ops || []) files.push(op.sourceHint?.file);
823
+ }
824
+ for (const candidate of batch?.candidates || []) {
825
+ files.push(candidate.sourceHint?.relativeFile, candidate.sourceHint?.file);
826
+ for (const item of candidate.textMatches || []) files.push(item.file);
827
+ for (const item of candidate.objectKeyMatches || []) files.push(item.file);
828
+ for (const item of candidate.locatorMatches || []) files.push(item.file);
829
+ for (const item of candidate.contextTextMatches || []) files.push(item.file);
830
+ }
831
+ files.push(...(extraFiles || []));
832
+ return [...new Set(files)]
833
+ .map((file) => normalizeProjectFile(file, cwd))
834
+ .filter(Boolean);
835
+ }
836
+
837
+ function normalizeProjectFile(file, cwd = process.cwd()) {
838
+ if (!file || typeof file !== 'string') return null;
839
+ const absolute = path.isAbsolute(file) ? file : path.resolve(cwd, file);
840
+ const relative = path.relative(cwd, absolute);
841
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) return null;
842
+ return relative;
843
+ }
844
+
845
+ export function rollbackApplySnapshot(
846
+ batch,
847
+ rollbackSnapshot,
848
+ extraFiles = [],
849
+ _reason = 'manual_edit_apply_snapshot_rollback',
850
+ cwd = process.cwd(),
851
+ ) {
852
+ const scope = collectManualApplyFiles(batch, extraFiles, cwd);
853
+ const rolledBackFiles = [];
854
+ const rollbackFailures = [];
855
+ for (const relativeFile of scope) {
856
+ const before = rollbackSnapshot?.get(relativeFile);
857
+ if (!before) continue;
858
+ const absolute = path.resolve(cwd, relativeFile);
859
+ try {
860
+ if (before.exists) {
861
+ fs.mkdirSync(path.dirname(absolute), { recursive: true });
862
+ fs.writeFileSync(absolute, before.content, 'utf-8');
863
+ } else if (fs.existsSync(absolute)) {
864
+ fs.rmSync(absolute);
865
+ }
866
+ rolledBackFiles.push(relativeFile);
867
+ } catch (err) {
868
+ rollbackFailures.push({ file: relativeFile, reason: 'restore_failed', message: err.message || String(err) });
869
+ }
870
+ }
871
+ return { rolledBackFiles, rollbackFailures };
872
+ }
873
+
874
+ function manualApplyReplyCommand(eventOrId = 'EVENT_ID') {
875
+ const id = typeof eventOrId === 'string' ? eventOrId : eventOrId?.id || 'EVENT_ID';
876
+ return `live-poll.mjs --reply ${id} done --data '<json>'`;
877
+ }
878
+
879
+ export function buildManualApplyAgentAction(eventOrId = 'EVENT_ID') {
880
+ return {
881
+ kind: 'manual_edit_apply',
882
+ required: 'apply_source_edits_then_reply',
883
+ replyCommand: manualApplyReplyCommand(eventOrId),
884
+ warning: 'Polling only leases this work item; it does not commit source edits.',
885
+ };
886
+ }
887
+
888
+ export function summarizeManualApplyEvent(event = {}, batch = event.batch, cwd = process.cwd()) {
889
+ const entries = Array.isArray(batch?.entries) ? batch.entries : [];
890
+ const opCount = entries.reduce((sum, entry) => sum + (Array.isArray(entry.ops) ? entry.ops.length : 0), 0);
891
+ return {
892
+ pageUrl: event.pageUrl || null,
893
+ chunk: event.chunk || null,
894
+ entryCount: entries.length,
895
+ opCount,
896
+ files: collectManualApplyFiles(batch, [], cwd),
897
+ };
898
+ }
899
+
900
+ export function summarizeManualApplyFailures(failed, cwd = process.cwd()) {
901
+ if (!Array.isArray(failed)) return [];
902
+ return failed.slice(0, 20).map((item) => ({
903
+ id: item.id || item.entryId || null,
904
+ reason: item.reason || item.message || 'failed',
905
+ message: compactManualLogText(item.message, 300),
906
+ files: Array.isArray(item.files) ? item.files.slice(0, 12).map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean) : undefined,
907
+ checks: summarizeManualDiagnostics(item.checks, cwd),
908
+ failures: summarizeManualDiagnostics(item.failures, cwd),
909
+ candidates: summarizeManualDiagnostics(item.candidates, cwd),
910
+ }));
911
+ }
912
+
913
+ export function summarizeManualDiagnostics(items, cwd = process.cwd()) {
914
+ if (!Array.isArray(items) || items.length === 0) return undefined;
915
+ return items.slice(0, 12).map((item) => ({
916
+ reason: item.reason || item.kind || undefined,
917
+ detail: compactManualLogText(item.detail, 220),
918
+ message: compactManualLogText(item.message, 300),
919
+ file: summarizeManualLogFile(item.file || item.relativeFile, cwd),
920
+ line: item.line || undefined,
921
+ ref: compactManualLogText(item.ref, 180),
922
+ marker: compactManualLogText(item.marker, 120),
923
+ files: Array.isArray(item.files) ? item.files.slice(0, 8).map((file) => summarizeManualLogFile(file, cwd)).filter(Boolean) : undefined,
924
+ }));
925
+ }
926
+
927
+ export function summarizeManualLogFile(file, cwd = process.cwd()) {
928
+ if (!file || typeof file !== 'string') return undefined;
929
+ if (!path.isAbsolute(file)) return file;
930
+ const relative = path.relative(cwd, file);
931
+ return relative && !relative.startsWith('..') && !path.isAbsolute(relative) ? relative : file;
932
+ }
933
+
934
+ export function compactManualLogText(value, max = 200) {
935
+ if (typeof value !== 'string') return undefined;
936
+ const normalized = value.replace(/\s+/g, ' ').trim();
937
+ if (normalized.length <= max) return normalized;
938
+ return normalized.slice(0, max) + `... [truncated ${normalized.length - max} chars]`;
939
+ }