madarx 2.13.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +544 -551
  3. package/.next/standalone/.next/app-path-routes-manifest.json +76 -77
  4. package/.next/standalone/.next/build-manifest.json +5 -5
  5. package/.next/standalone/.next/prerender-manifest.json +3 -3
  6. package/.next/standalone/.next/react-loadable-manifest.json +1 -1
  7. package/.next/standalone/.next/routes-manifest.json +0 -6
  8. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  10. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  11. package/.next/standalone/.next/server/app/activity/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/admin/page.js +2 -2
  13. package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/agents/[id]/page.js +4 -4
  15. package/.next/standalone/.next/server/app/agents/[id]/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/agents/page.js +1 -1
  17. package/.next/standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/api/activity/route_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/api/admin/audit-export/route_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/api/admin/share-links/route_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/api/agent-memory/route_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/api/agent-runs/[id]/cancel/route_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/api/agent-runs/[id]/events/route_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/api/agent-runs/[id]/log/route_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/api/agent-runs/[id]/route_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/api/agent-runs/route_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/api/agents/[id]/chain/route_client-reference-manifest.js +1 -1
  28. package/.next/standalone/.next/server/app/api/agents/[id]/memory/route_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/api/agents/[id]/reports/route_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/api/agents/[id]/run/route_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/api/agents/[id]/skills/route_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/api/agents/create/route_client-reference-manifest.js +1 -1
  33. package/.next/standalone/.next/server/app/api/agents/ops/route_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/api/approvals/[id]/route_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/api/approvals/route_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/api/artifacts/[id]/acl/route_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/api/artifacts/[id]/protect/route_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/api/artifacts/[id]/raw/route_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/api/artifacts/[id]/route_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/api/artifacts/[id]/share-link/[linkId]/route_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/api/artifacts/[id]/share-link/route_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/api/artifacts/upload/route_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/api/audit/list/route_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/api/audit/search/route_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/api/auth/config/route_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/api/auth/join-bootstrap/route_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/api/auth/session/route_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/api/brand/route_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/api/chat/sessions/[id]/route_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/api/chat/sessions/route_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/api/config/env/route_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/api/config/route_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/api/connections/[service]/route_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/api/connections/[service]/verify/route_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/api/connections/route_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/api/cron/tick/route_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/api/dashboard/spaces/[id]/move/route_client-reference-manifest.js +1 -1
  59. package/.next/standalone/.next/server/app/api/dashboard/spaces/[id]/route_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/api/dashboard/spaces/[id]/share-link/[linkId]/route_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/api/dashboard/spaces/[id]/share-link/route_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/api/dashboard/spaces/import/route_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/api/dashboard/spaces/route_client-reference-manifest.js +1 -1
  64. package/.next/standalone/.next/server/app/api/disk/files/[id]/blob/route_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/app/api/disk/files/[id]/route_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/api/disk/files/[id]/transcribe/route_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/api/disk/files/route_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/api/disk/folders/route_client-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/app/api/events/since/[cursor]/route_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/api/events/stream/route_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/api/fs/create-folder/route_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/api/fs/pick-folder/route_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/blueprint/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/blueprint/route_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/diagnostic/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/diagnostic/route_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/governance/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/governance/route_client-reference-manifest.js +1 -1
  79. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/interview/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/interview/route_client-reference-manifest.js +1 -1
  81. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/pilot/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/pilot/route_client-reference-manifest.js +1 -1
  83. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/quarterly/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/quarterly/route_client-reference-manifest.js +1 -1
  85. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/route_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/setup-package/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/hail/engagements/[id]/setup-package/route_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app/api/hail/engagements/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/hail/engagements/route_client-reference-manifest.js +1 -1
  91. package/.next/standalone/.next/server/app/api/hail/interviews/[id]/responses/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/hail/interviews/[id]/responses/route_client-reference-manifest.js +1 -1
  93. package/.next/standalone/.next/server/app/api/hail/interviews/[id]/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/hail/interviews/[id]/route_client-reference-manifest.js +1 -1
  95. package/.next/standalone/.next/server/app/api/hail/setup-packages/[id]/apply/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/hail/setup-packages/[id]/apply/route_client-reference-manifest.js +1 -1
  97. package/.next/standalone/.next/server/app/api/hail/setup-packages/validate/route_client-reference-manifest.js +1 -1
  98. package/.next/standalone/.next/server/app/api/heartbeat/tick/route_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/api/heartbeat/worker/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/heartbeat/worker/route_client-reference-manifest.js +1 -1
  101. package/.next/standalone/.next/server/app/api/help/route_client-reference-manifest.js +1 -1
  102. package/.next/standalone/.next/server/app/api/hermes/jobs/[id]/events/route_client-reference-manifest.js +1 -1
  103. package/.next/standalone/.next/server/app/api/hermes/jobs/[id]/route_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/api/hermes/jobs/route_client-reference-manifest.js +1 -1
  105. package/.next/standalone/.next/server/app/api/integrations/google/callback/route_client-reference-manifest.js +1 -1
  106. package/.next/standalone/.next/server/app/api/integrations/google/oauth/route_client-reference-manifest.js +1 -1
  107. package/.next/standalone/.next/server/app/api/marketplace/[id]/route_client-reference-manifest.js +1 -1
  108. package/.next/standalone/.next/server/app/api/marketplace/open-design/route_client-reference-manifest.js +1 -1
  109. package/.next/standalone/.next/server/app/api/marketplace/route_client-reference-manifest.js +1 -1
  110. package/.next/standalone/.next/server/app/api/mines/import-roots/route_client-reference-manifest.js +1 -1
  111. package/.next/standalone/.next/server/app/api/mines/portfolio/route_client-reference-manifest.js +1 -1
  112. package/.next/standalone/.next/server/app/api/mines/projects/[id]/chunks/route_client-reference-manifest.js +1 -1
  113. package/.next/standalone/.next/server/app/api/mines/projects/[id]/diligence/route_client-reference-manifest.js +1 -1
  114. package/.next/standalone/.next/server/app/api/mines/projects/[id]/import/route_client-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/app/api/mines/projects/[id]/publish/route_client-reference-manifest.js +1 -1
  116. package/.next/standalone/.next/server/app/api/mines/projects/route_client-reference-manifest.js +1 -1
  117. package/.next/standalone/.next/server/app/api/missions/route_client-reference-manifest.js +1 -1
  118. package/.next/standalone/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
  119. package/.next/standalone/.next/server/app/api/onboarding/blueprint/route_client-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/app/api/onboarding/launch/route_client-reference-manifest.js +1 -1
  121. package/.next/standalone/.next/server/app/api/orchestrator/command/route_client-reference-manifest.js +1 -1
  122. package/.next/standalone/.next/server/app/api/orchestrator/stream/route_client-reference-manifest.js +1 -1
  123. package/.next/standalone/.next/server/app/api/orchestrator/upload/route_client-reference-manifest.js +1 -1
  124. package/.next/standalone/.next/server/app/api/org/route_client-reference-manifest.js +1 -1
  125. package/.next/standalone/.next/server/app/api/orgs/[id]/invites/[inviteId]/route_client-reference-manifest.js +1 -1
  126. package/.next/standalone/.next/server/app/api/orgs/[id]/invites/route_client-reference-manifest.js +1 -1
  127. package/.next/standalone/.next/server/app/api/orgs/[id]/members/[userId]/role/route_client-reference-manifest.js +1 -1
  128. package/.next/standalone/.next/server/app/api/orgs/[id]/members/[userId]/route_client-reference-manifest.js +1 -1
  129. package/.next/standalone/.next/server/app/api/orgs/[id]/members/route_client-reference-manifest.js +1 -1
  130. package/.next/standalone/.next/server/app/api/orgs/[id]/route_client-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/app/api/orgs/invites/pending/route_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/api/orgs/join/route_client-reference-manifest.js +1 -1
  133. package/.next/standalone/.next/server/app/api/orgs/join-complete/route_client-reference-manifest.js +1 -1
  134. package/.next/standalone/.next/server/app/api/orgs/route_client-reference-manifest.js +1 -1
  135. package/.next/standalone/.next/server/app/api/printing-press/clis/route_client-reference-manifest.js +1 -1
  136. package/.next/standalone/.next/server/app/api/printing-press/install/route_client-reference-manifest.js +1 -1
  137. package/.next/standalone/.next/server/app/api/printing-press/security-mode/route_client-reference-manifest.js +1 -1
  138. package/.next/standalone/.next/server/app/api/privacy/config/route_client-reference-manifest.js +1 -1
  139. package/.next/standalone/.next/server/app/api/privacy/verify/route_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/api/processes/[id]/route.js.nft.json +1 -1
  141. package/.next/standalone/.next/server/app/api/processes/[id]/route_client-reference-manifest.js +1 -1
  142. package/.next/standalone/.next/server/app/api/processes/[id]/share-link/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/processes/[id]/share-link/route_client-reference-manifest.js +1 -1
  144. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/override/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/override/route_client-reference-manifest.js +1 -1
  146. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/retry/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/retry/route_client-reference-manifest.js +1 -1
  148. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/submit/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/processes/[id]/stages/[stageId]/submit/route_client-reference-manifest.js +1 -1
  150. package/.next/standalone/.next/server/app/api/processes/definitions/[slug]/route_client-reference-manifest.js +1 -1
  151. package/.next/standalone/.next/server/app/api/processes/definitions/[slug]/settings/route_client-reference-manifest.js +1 -1
  152. package/.next/standalone/.next/server/app/api/processes/definitions/route_client-reference-manifest.js +1 -1
  153. package/.next/standalone/.next/server/app/api/processes/definitions/validate/route_client-reference-manifest.js +1 -1
  154. package/.next/standalone/.next/server/app/api/processes/route.js.nft.json +1 -1
  155. package/.next/standalone/.next/server/app/api/processes/route_client-reference-manifest.js +1 -1
  156. package/.next/standalone/.next/server/app/api/processes/start-and-route/route.js +1 -1
  157. package/.next/standalone/.next/server/app/api/processes/start-and-route/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/processes/start-and-route/route_client-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/app/api/projects/[slug]/library/route_client-reference-manifest.js +1 -1
  160. package/.next/standalone/.next/server/app/api/projects/[slug]/route_client-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  162. package/.next/standalone/.next/server/app/api/runs/approve-claude-run/route_client-reference-manifest.js +1 -1
  163. package/.next/standalone/.next/server/app/api/runs/claude-code-dry-run/route_client-reference-manifest.js +1 -1
  164. package/.next/standalone/.next/server/app/api/runs/competitor-report/route_client-reference-manifest.js +1 -1
  165. package/.next/standalone/.next/server/app/api/runs/engine-ping/route_client-reference-manifest.js +1 -1
  166. package/.next/standalone/.next/server/app/api/runs/marketing-plan/route_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/api/schedules/upsert/route_client-reference-manifest.js +1 -1
  168. package/.next/standalone/.next/server/app/api/secrets/[name]/route_client-reference-manifest.js +1 -1
  169. package/.next/standalone/.next/server/app/api/secrets/route_client-reference-manifest.js +1 -1
  170. package/.next/standalone/.next/server/app/api/settings/trust-mode/route_client-reference-manifest.js +1 -1
  171. package/.next/standalone/.next/server/app/api/share/[token]/otp/route_client-reference-manifest.js +1 -1
  172. package/.next/standalone/.next/server/app/api/share/[token]/route_client-reference-manifest.js +1 -1
  173. package/.next/standalone/.next/server/app/api/share/[token]/verify/route_client-reference-manifest.js +1 -1
  174. package/.next/standalone/.next/server/app/api/share/space/[token]/otp/route_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/api/share/space/[token]/route_client-reference-manifest.js +1 -1
  176. package/.next/standalone/.next/server/app/api/share/space/[token]/verify/route_client-reference-manifest.js +1 -1
  177. package/.next/standalone/.next/server/app/api/shared/spaces/[id]/acl/route_client-reference-manifest.js +1 -1
  178. package/.next/standalone/.next/server/app/api/shared/spaces/publish/route_client-reference-manifest.js +1 -1
  179. package/.next/standalone/.next/server/app/api/shared/spaces/route_client-reference-manifest.js +1 -1
  180. package/.next/standalone/.next/server/app/api/shared/spaces/status/route_client-reference-manifest.js +1 -1
  181. package/.next/standalone/.next/server/app/api/shared/spaces/unpublish/route_client-reference-manifest.js +1 -1
  182. package/.next/standalone/.next/server/app/api/state/route_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/api/system/update/route_client-reference-manifest.js +1 -1
  184. package/.next/standalone/.next/server/app/api/tasks/[id]/active-run/route_client-reference-manifest.js +1 -1
  185. package/.next/standalone/.next/server/app/api/tasks/[id]/attachments/route_client-reference-manifest.js +1 -1
  186. package/.next/standalone/.next/server/app/api/tasks/[id]/checklist/[itemId]/route_client-reference-manifest.js +1 -1
  187. package/.next/standalone/.next/server/app/api/tasks/[id]/checklist/route_client-reference-manifest.js +1 -1
  188. package/.next/standalone/.next/server/app/api/tasks/[id]/checkout/route_client-reference-manifest.js +1 -1
  189. package/.next/standalone/.next/server/app/api/tasks/[id]/children/route_client-reference-manifest.js +1 -1
  190. package/.next/standalone/.next/server/app/api/tasks/[id]/comments/route_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/api/tasks/[id]/events/route_client-reference-manifest.js +1 -1
  192. package/.next/standalone/.next/server/app/api/tasks/[id]/live-runs/route_client-reference-manifest.js +1 -1
  193. package/.next/standalone/.next/server/app/api/tasks/[id]/release/route_client-reference-manifest.js +1 -1
  194. package/.next/standalone/.next/server/app/api/tasks/[id]/route_client-reference-manifest.js +1 -1
  195. package/.next/standalone/.next/server/app/api/tasks/route_client-reference-manifest.js +1 -1
  196. package/.next/standalone/.next/server/app/api/tool-allowlists/[id]/route_client-reference-manifest.js +1 -1
  197. package/.next/standalone/.next/server/app/api/tool-allowlists/route_client-reference-manifest.js +1 -1
  198. package/.next/standalone/.next/server/app/api/tool-egress/route_client-reference-manifest.js +1 -1
  199. package/.next/standalone/.next/server/app/api/tools/[name]/approve/route_client-reference-manifest.js +1 -1
  200. package/.next/standalone/.next/server/app/api/tools/[name]/route_client-reference-manifest.js +1 -1
  201. package/.next/standalone/.next/server/app/api/tools/route_client-reference-manifest.js +1 -1
  202. package/.next/standalone/.next/server/app/api/transcripts/route_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/api/voice/providers/route_client-reference-manifest.js +1 -1
  204. package/.next/standalone/.next/server/app/api/voice/realtime/context/route_client-reference-manifest.js +1 -1
  205. package/.next/standalone/.next/server/app/api/voice/realtime/session/route_client-reference-manifest.js +1 -1
  206. package/.next/standalone/.next/server/app/api/voice/realtime/tool-result/route_client-reference-manifest.js +1 -1
  207. package/.next/standalone/.next/server/app/api/voice/realtime/tools/route_client-reference-manifest.js +1 -1
  208. package/.next/standalone/.next/server/app/api/voice/tts/route_client-reference-manifest.js +1 -1
  209. package/.next/standalone/.next/server/app/api/whatsapp/allowlist/route_client-reference-manifest.js +1 -1
  210. package/.next/standalone/.next/server/app/api/whatsapp/disconnect/route_client-reference-manifest.js +1 -1
  211. package/.next/standalone/.next/server/app/api/whatsapp/messages/route_client-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/app/api/whatsapp/qr/route_client-reference-manifest.js +1 -1
  213. package/.next/standalone/.next/server/app/api/whatsapp/send/route_client-reference-manifest.js +1 -1
  214. package/.next/standalone/.next/server/app/api/whatsapp/status/route_client-reference-manifest.js +1 -1
  215. package/.next/standalone/.next/server/app/approvals/page.js +2 -2
  216. package/.next/standalone/.next/server/app/approvals/page_client-reference-manifest.js +1 -1
  217. package/.next/standalone/.next/server/app/architecture/page_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/architecture.html +2 -2
  219. package/.next/standalone/.next/server/app/architecture.rsc +2 -2
  220. package/.next/standalone/.next/server/app/audit/live/page_client-reference-manifest.js +1 -1
  221. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/app/brand/page_client-reference-manifest.js +1 -1
  223. package/.next/standalone/.next/server/app/brand.html +1 -1
  224. package/.next/standalone/.next/server/app/brand.rsc +2 -2
  225. package/.next/standalone/.next/server/app/disk/page_client-reference-manifest.js +1 -1
  226. package/.next/standalone/.next/server/app/federated-ai/page_client-reference-manifest.js +1 -1
  227. package/.next/standalone/.next/server/app/federated-ai.html +2 -2
  228. package/.next/standalone/.next/server/app/federated-ai.rsc +2 -2
  229. package/.next/standalone/.next/server/app/hail/[id]/governance/page.js.nft.json +1 -1
  230. package/.next/standalone/.next/server/app/hail/[id]/governance/page_client-reference-manifest.js +1 -1
  231. package/.next/standalone/.next/server/app/hail/[id]/interview/page.js +2 -2
  232. package/.next/standalone/.next/server/app/hail/[id]/interview/page.js.nft.json +1 -1
  233. package/.next/standalone/.next/server/app/hail/[id]/interview/page_client-reference-manifest.js +1 -1
  234. package/.next/standalone/.next/server/app/hail/[id]/page.js +1 -1
  235. package/.next/standalone/.next/server/app/hail/[id]/page.js.nft.json +1 -1
  236. package/.next/standalone/.next/server/app/hail/[id]/page_client-reference-manifest.js +1 -1
  237. package/.next/standalone/.next/server/app/hail/[id]/setup/page.js +2 -2
  238. package/.next/standalone/.next/server/app/hail/[id]/setup/page.js.nft.json +1 -1
  239. package/.next/standalone/.next/server/app/hail/[id]/setup/page_client-reference-manifest.js +1 -1
  240. package/.next/standalone/.next/server/app/hail/page.js +3 -3
  241. package/.next/standalone/.next/server/app/hail/page.js.nft.json +1 -1
  242. package/.next/standalone/.next/server/app/hail/page_client-reference-manifest.js +1 -1
  243. package/.next/standalone/.next/server/app/help/[slug]/page_client-reference-manifest.js +1 -1
  244. package/.next/standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
  245. package/.next/standalone/.next/server/app/index.html +2 -2
  246. package/.next/standalone/.next/server/app/index.rsc +2 -2
  247. package/.next/standalone/.next/server/app/join/page_client-reference-manifest.js +1 -1
  248. package/.next/standalone/.next/server/app/join.html +1 -1
  249. package/.next/standalone/.next/server/app/join.rsc +2 -2
  250. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  251. package/.next/standalone/.next/server/app/marketplace/page.js +2 -2
  252. package/.next/standalone/.next/server/app/marketplace/page_client-reference-manifest.js +1 -1
  253. package/.next/standalone/.next/server/app/mines/[projectId]/page_client-reference-manifest.js +1 -1
  254. package/.next/standalone/.next/server/app/mines/[projectId]/results/page_client-reference-manifest.js +1 -1
  255. package/.next/standalone/.next/server/app/mines/page_client-reference-manifest.js +1 -1
  256. package/.next/standalone/.next/server/app/missions/page.js +1 -1
  257. package/.next/standalone/.next/server/app/missions/page_client-reference-manifest.js +1 -1
  258. package/.next/standalone/.next/server/app/onboarding/org/page_client-reference-manifest.js +1 -1
  259. package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  260. package/.next/standalone/.next/server/app/onboarding.html +2 -2
  261. package/.next/standalone/.next/server/app/onboarding.rsc +2 -2
  262. package/.next/standalone/.next/server/app/org/page.js +1 -1
  263. package/.next/standalone/.next/server/app/org/page.js.nft.json +1 -1
  264. package/.next/standalone/.next/server/app/org/page_client-reference-manifest.js +1 -1
  265. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  266. package/.next/standalone/.next/server/app/projects/[slug]/log/page_client-reference-manifest.js +1 -1
  267. package/.next/standalone/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  268. package/.next/standalone/.next/server/app/projects/new/page.js +1 -1
  269. package/.next/standalone/.next/server/app/projects/new/page_client-reference-manifest.js +1 -1
  270. package/.next/standalone/.next/server/app/projects/new.html +1 -1
  271. package/.next/standalone/.next/server/app/projects/new.rsc +3 -3
  272. package/.next/standalone/.next/server/app/projects/page.js +20 -20
  273. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  274. package/.next/standalone/.next/server/app/reports/[file]/route_client-reference-manifest.js +1 -1
  275. package/.next/standalone/.next/server/app/reports/page_client-reference-manifest.js +1 -1
  276. package/.next/standalone/.next/server/app/runtime/page_client-reference-manifest.js +1 -1
  277. package/.next/standalone/.next/server/app/schedules/page.js +2 -2
  278. package/.next/standalone/.next/server/app/schedules/page.js.nft.json +1 -1
  279. package/.next/standalone/.next/server/app/schedules/page_client-reference-manifest.js +1 -1
  280. package/.next/standalone/.next/server/app/settings/account/page_client-reference-manifest.js +1 -1
  281. package/.next/standalone/.next/server/app/settings/advanced/page_client-reference-manifest.js +1 -1
  282. package/.next/standalone/.next/server/app/settings/appearance/page_client-reference-manifest.js +1 -1
  283. package/.next/standalone/.next/server/app/settings/brand/page_client-reference-manifest.js +1 -1
  284. package/.next/standalone/.next/server/app/settings/brand.html +2 -2
  285. package/.next/standalone/.next/server/app/settings/brand.rsc +2 -2
  286. package/.next/standalone/.next/server/app/settings/connectors/page_client-reference-manifest.js +1 -1
  287. package/.next/standalone/.next/server/app/settings/engines/page_client-reference-manifest.js +1 -1
  288. package/.next/standalone/.next/server/app/settings/onboarding/page_client-reference-manifest.js +1 -1
  289. package/.next/standalone/.next/server/app/settings/onboarding.html +2 -2
  290. package/.next/standalone/.next/server/app/settings/onboarding.rsc +2 -2
  291. package/.next/standalone/.next/server/app/settings/organization/page.js +1 -1
  292. package/.next/standalone/.next/server/app/settings/organization/page.js.nft.json +1 -1
  293. package/.next/standalone/.next/server/app/settings/organization/page_client-reference-manifest.js +1 -1
  294. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  295. package/.next/standalone/.next/server/app/settings/runtime/page_client-reference-manifest.js +1 -1
  296. package/.next/standalone/.next/server/app/settings/team/page_client-reference-manifest.js +1 -1
  297. package/.next/standalone/.next/server/app/settings/tools/page_client-reference-manifest.js +1 -1
  298. package/.next/standalone/.next/server/app/settings.html +2 -2
  299. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  300. package/.next/standalone/.next/server/app/share/[token]/page_client-reference-manifest.js +1 -1
  301. package/.next/standalone/.next/server/app/share/space/[token]/page_client-reference-manifest.js +1 -1
  302. package/.next/standalone/.next/server/app/tasks/[id]/page.js +1 -1
  303. package/.next/standalone/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  304. package/.next/standalone/.next/server/app/tasks/page.js +2 -2
  305. package/.next/standalone/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  306. package/.next/standalone/.next/server/app/team/[agentId]/page_client-reference-manifest.js +1 -1
  307. package/.next/standalone/.next/server/app/team/page_client-reference-manifest.js +1 -1
  308. package/.next/standalone/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  309. package/.next/standalone/.next/server/app/whatsapp/page.js +1 -1
  310. package/.next/standalone/.next/server/app/whatsapp/page_client-reference-manifest.js +1 -1
  311. package/.next/standalone/.next/server/app/whatsapp.html +1 -1
  312. package/.next/standalone/.next/server/app/whatsapp.rsc +3 -3
  313. package/.next/standalone/.next/server/app/workflows/[caseId]/page.js +1 -1
  314. package/.next/standalone/.next/server/app/workflows/[caseId]/page.js.nft.json +1 -1
  315. package/.next/standalone/.next/server/app/workflows/[caseId]/page_client-reference-manifest.js +1 -1
  316. package/.next/standalone/.next/server/app/workflows/new/[caseId]/page.js +1 -1
  317. package/.next/standalone/.next/server/app/workflows/new/[caseId]/page.js.nft.json +1 -1
  318. package/.next/standalone/.next/server/app/workflows/new/[caseId]/page_client-reference-manifest.js +1 -1
  319. package/.next/standalone/.next/server/app/workflows/new/definition/page_client-reference-manifest.js +1 -1
  320. package/.next/standalone/.next/server/app/workflows/page.js +1 -1
  321. package/.next/standalone/.next/server/app/workflows/page.js.nft.json +1 -1
  322. package/.next/standalone/.next/server/app/workflows/page_client-reference-manifest.js +1 -1
  323. package/.next/standalone/.next/server/app/workflows/share/[caseId]/page.js +1 -1
  324. package/.next/standalone/.next/server/app/workflows/share/[caseId]/page.js.nft.json +1 -1
  325. package/.next/standalone/.next/server/app/workflows/share/[caseId]/page_client-reference-manifest.js +1 -1
  326. package/.next/standalone/.next/server/app-paths-manifest.json +76 -77
  327. package/.next/standalone/.next/server/chunks/1699.js +19 -19
  328. package/.next/standalone/.next/server/chunks/51.js +1 -0
  329. package/.next/standalone/.next/server/chunks/5185.js +4 -27
  330. package/.next/standalone/.next/server/chunks/5257.js +1 -1
  331. package/.next/standalone/.next/server/chunks/6355.js +1 -0
  332. package/.next/standalone/.next/server/functions-config-manifest.json +15 -15
  333. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  334. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  335. package/.next/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  336. package/.next/standalone/.next/server/pages/404.html +1 -1
  337. package/.next/standalone/.next/server/pages/500.html +1 -1
  338. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  339. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  340. package/.next/standalone/.next/static/chunks/4119-cfb6260557a0a3d2.js +1 -0
  341. package/.next/standalone/.next/static/chunks/app/projects/page-f136822590202f9f.js +1 -0
  342. package/.next/standalone/.next/static/chunks/app/workflows/[caseId]/page-9949ff1c223e771d.js +1 -0
  343. package/.next/{static/chunks/app/workflows/page-25cb2c4cb90273a8.js → standalone/.next/static/chunks/app/workflows/page-d0484521369bce4c.js} +1 -1
  344. package/.next/standalone/.next/static/chunks/{webpack-0cfb048137bd7fce.js → webpack-f916d679fe38a701.js} +1 -1
  345. package/.next/standalone/.next/static/css/0bd4c357d4f0c4f2.css +1 -0
  346. package/.next/standalone/.next/static/tMcPS9JR5cRXSe0u5ne95/_buildManifest.js +1 -0
  347. package/.next/standalone/CHANGELOG.md +28 -0
  348. package/.next/standalone/data/.artifacts-migrated-v1 +1 -1
  349. package/.next/standalone/data/.default-project-seeded +1 -1
  350. package/.next/standalone/data/madarx.sqlite +0 -0
  351. package/.next/standalone/data/madarx.sqlite-shm +0 -0
  352. package/.next/standalone/data/madarx.sqlite-wal +0 -0
  353. package/.next/standalone/lib/process/seeds/specs/mine-project-intake.json +12 -4
  354. package/.next/standalone/lib/process/seeds/specs/mine-valuation.json +6 -2
  355. package/.next/standalone/lib/process/stages/policy-dsl-legacy.js +178 -0
  356. package/.next/standalone/lib/process/stages/policy-gate.js +24 -168
  357. package/.next/standalone/package.json +2 -2
  358. package/.next/static/chunks/4119-cfb6260557a0a3d2.js +1 -0
  359. package/.next/static/chunks/app/projects/page-f136822590202f9f.js +1 -0
  360. package/.next/static/chunks/app/workflows/[caseId]/page-9949ff1c223e771d.js +1 -0
  361. package/.next/{standalone/.next/static/chunks/app/workflows/page-25cb2c4cb90273a8.js → static/chunks/app/workflows/page-d0484521369bce4c.js} +1 -1
  362. package/.next/static/chunks/{webpack-0cfb048137bd7fce.js → webpack-f916d679fe38a701.js} +1 -1
  363. package/.next/static/css/0bd4c357d4f0c4f2.css +1 -0
  364. package/.next/static/tMcPS9JR5cRXSe0u5ne95/_buildManifest.js +1 -0
  365. package/CHANGELOG.md +28 -0
  366. package/ai-docs/process-engine.md +33 -1
  367. package/app/api/processes/start-and-route/route.js +5 -3
  368. package/app/components/dashboard/whatsapp-section.jsx +54 -13
  369. package/app/workflows/[caseId]/case-detail-client.jsx +2 -2
  370. package/app/workflows/definition-card.jsx +12 -18
  371. package/app/workflows/new/[caseId]/page.js +8 -8
  372. package/app/workflows/page.js +0 -5
  373. package/app/workflows/share/[caseId]/page.js +0 -1
  374. package/lib/cli/prompt.js +110 -0
  375. package/lib/cli/setup.js +152 -87
  376. package/lib/process/artifacts.js +12 -60
  377. package/lib/process/engine.js +5 -5
  378. package/lib/process/policy-predicates.js +116 -0
  379. package/lib/process/seeds/specs/mine-project-intake.json +12 -4
  380. package/lib/process/seeds/specs/mine-valuation.json +6 -2
  381. package/lib/process/spec-validator.js +46 -1
  382. package/lib/process/stages/policy-dsl-legacy.js +178 -0
  383. package/lib/process/stages/policy-gate.js +24 -168
  384. package/lib/runtime.js +8 -2
  385. package/package.json +2 -2
  386. package/scripts/postbuild-standalone.mjs +9 -0
  387. package/scripts/whatsapp-reset.mjs +15 -0
  388. package/.next/standalone/.next/server/app/workflows/new/page.js +0 -2
  389. package/.next/standalone/.next/server/app/workflows/new/page.js.nft.json +0 -1
  390. package/.next/standalone/.next/server/app/workflows/new/page_client-reference-manifest.js +0 -1
  391. package/.next/standalone/.next/server/chunks/1092.js +0 -1
  392. package/.next/standalone/.next/static/cR6E_4o8_rHXujVNesWiZ/_buildManifest.js +0 -1
  393. package/.next/standalone/.next/static/chunks/4119-3b6adff3c7187ef3.js +0 -1
  394. package/.next/standalone/.next/static/chunks/app/projects/page-2166c214f854766e.js +0 -1
  395. package/.next/standalone/.next/static/chunks/app/workflows/[caseId]/page-423e4c194c7f5bf5.js +0 -1
  396. package/.next/standalone/.next/static/chunks/app/workflows/new/page-1eda41616cbfc4f3.js +0 -1
  397. package/.next/standalone/.next/static/css/0bfed9e12afa1dc1.css +0 -1
  398. package/.next/static/cR6E_4o8_rHXujVNesWiZ/_buildManifest.js +0 -1
  399. package/.next/static/chunks/4119-3b6adff3c7187ef3.js +0 -1
  400. package/.next/static/chunks/app/projects/page-2166c214f854766e.js +0 -1
  401. package/.next/static/chunks/app/workflows/[caseId]/page-423e4c194c7f5bf5.js +0 -1
  402. package/.next/static/chunks/app/workflows/new/page-1eda41616cbfc4f3.js +0 -1
  403. package/.next/static/css/0bfed9e12afa1dc1.css +0 -1
  404. package/app/workflows/new/new-case-flow.jsx +0 -256
  405. package/app/workflows/new/page.js +0 -27
  406. /package/.next/standalone/.next/static/{cR6E_4o8_rHXujVNesWiZ → tMcPS9JR5cRXSe0u5ne95}/_ssgManifest.js +0 -0
  407. /package/.next/static/{cR6E_4o8_rHXujVNesWiZ → tMcPS9JR5cRXSe0u5ne95}/_ssgManifest.js +0 -0
package/lib/cli/setup.js CHANGED
@@ -1,10 +1,17 @@
1
1
  /**
2
2
  * `madarx setup` — interactive first-run wizard.
3
3
  *
4
- * Walks the operator through: data home, secrets-vault master key, the folder
5
- * permissions the bundled agent may read/write (MADARX_ALLOWED_ROOTS), optional
6
- * API keys (stored in the encrypted vault), the WhatsApp toggle, and the weekly
7
- * auto-update preference (consumed by T3's self-update).
4
+ * An arrow-key guided setup that decides the things that shape the whole
5
+ * install up front, then fills in credentials and preferences:
6
+ *
7
+ * 1. Usage mode personal (local-only) vs team (Supabase shared layer)
8
+ * 2. Main agent which model/engine the orchestrator runs on
9
+ * 3. Sub-agents default model/engine new agents inherit
10
+ * 4. Secrets vault master key (generated + persisted on first run)
11
+ * 5. API keys Anthropic / OpenAI → encrypted vault
12
+ * 6. Folder grants MADARX_ALLOWED_ROOTS (the agent's file/exec boundary)
13
+ * 7. WhatsApp bridge on/off
14
+ * 8. Auto-update weekly notify / hands-off / off
8
15
  *
9
16
  * Sets MADARX_DISABLE_INPROC_DAEMON=1 before importing the runtime — a setup run
10
17
  * must not spin up cron/heartbeat loops.
@@ -13,42 +20,33 @@
13
20
  import { createInterface } from 'node:readline/promises';
14
21
  import { applyHomeEnv } from './home.js';
15
22
  import { upsertEnvVar, removeEnvVar, readEnvFile } from './env-file.js';
16
- import { renderHeader } from './banner.js';
23
+ import { renderHeader, _palette as P, fg, bold, dim } from './banner.js';
17
24
  import { readVersion } from './dispatch.js';
25
+ import { select, confirm } from './prompt.js';
18
26
 
19
27
  function isInteractive() {
20
28
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
21
29
  }
22
30
 
23
- /** readline with a muted variant for secret entry (echoes `*`). */
24
- function makeReader() {
25
- const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
26
- rl.stdoutMuted = false;
27
- rl._writeToOutput = function (str) {
28
- if (rl.stdoutMuted) rl.output.write('*');
29
- else rl.output.write(str);
30
- };
31
- return rl;
32
- }
33
-
34
- async function ask(rl, prompt, dflt = '') {
35
- const suffix = dflt ? ` [${dflt}]` : '';
36
- const ans = (await rl.question(`${prompt}${suffix}: `)).trim();
37
- return ans || dflt;
38
- }
39
-
40
- async function askYesNo(rl, prompt, dfltYes = true) {
41
- const ans = (await rl.question(`${prompt} ${dfltYes ? '[Y/n]' : '[y/N]'}: `)).trim().toLowerCase();
42
- if (!ans) return dfltYes;
43
- return ans === 'y' || ans === 'yes';
44
- }
31
+ const h2 = (s) => console.log('\n' + bold(fg(P.platinum, s)));
32
+ const note = (s) => console.log(' ' + dim(fg(P.muted, s)));
33
+ const ok = (s) => console.log(' ' + fg(P.mars, '●') + ' ' + fg(P.bone, s));
45
34
 
46
- async function askSecret(rl, prompt) {
47
- rl.stdoutMuted = true;
48
- const val = (await rl.question(`${prompt}: `)).trim();
35
+ /** Open an ephemeral readline for one text prompt, then close it (so it never
36
+ * competes with the raw-mode arrow menus). `secret` echoes `*`. */
37
+ async function ask(prompt, { dflt = '', secret = false } = {}) {
38
+ const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
49
39
  rl.stdoutMuted = false;
50
- rl.output.write('\n');
51
- return val;
40
+ rl._writeToOutput = function (str) { rl.output.write(rl.stdoutMuted ? '*' : str); };
41
+ try {
42
+ rl.stdoutMuted = secret;
43
+ const suffix = dflt ? ` [${dflt}]` : '';
44
+ const ans = (await rl.question(` ${fg(P.bone, prompt)}${dim(suffix)}: `)).trim();
45
+ if (secret) rl.output.write('\n');
46
+ return ans || dflt;
47
+ } finally {
48
+ rl.close();
49
+ }
52
50
  }
53
51
 
54
52
  export async function setup() {
@@ -57,87 +55,154 @@ export async function setup() {
57
55
  return 1;
58
56
  }
59
57
 
60
- // Management command — never run the in-process daemons.
61
- process.env.MADARX_DISABLE_INPROC_DAEMON = '1';
62
-
58
+ process.env.MADARX_DISABLE_INPROC_DAEMON = '1'; // management command — no daemons
63
59
  const layout = applyHomeEnv();
64
- const rl = makeReader();
65
60
 
66
61
  try {
67
62
  console.log(renderHeader('setup', readVersion()));
68
- console.log(`Data home: ${layout.home}`);
69
- console.log('(override anytime with the MADARX_HOME env var)\n');
63
+ console.log(`Data home: ${fg(P.bone, layout.home)}`);
64
+ note('override anytime with the MADARX_HOME env var');
70
65
 
71
- // 1. Master key delegate to the canonical resolver (generates + persists
72
- // to $MADARX_HOME/.env.local on first run, prints the backup instruction).
73
- console.log('1) Secrets vault');
74
- const { resolveMasterKey } = await import('../master-key.js');
66
+ // Open the DB once so vault + config tables exist for the steps below.
75
67
  const { getDb } = await import('../db.js');
76
- getDb(); // open/create the DB so the vault + config tables exist
77
- resolveMasterKey({ allowGenerate: true });
78
- console.log(' Master key ready.\n');
68
+ getDb();
69
+ const { setConfig } = await import('../config.js');
79
70
 
80
- // 2. Folder permissions for the bundled agent.
81
- console.log('2) Folder permissions');
82
- console.log(' The agent can read/write/run commands ONLY inside roots you grant here.');
83
- console.log(' (The repo root and workspace/ are always allowed. Leave blank to skip.)');
84
- const existingRoots = readEnvFile(layout.envFile).MADARX_ALLOWED_ROOTS || '';
85
- const roots = await ask(rl, ' Extra allowed roots (comma-separated absolute paths)', existingRoots);
86
- if (roots) {
87
- const cleaned = roots.split(',').map((r) => r.trim()).filter(Boolean).join(',');
88
- upsertEnvVar(layout.envFile, 'MADARX_ALLOWED_ROOTS', cleaned);
89
- console.log(` Granted: ${cleaned}\n`);
71
+ // ── 1. Usage mode ────────────────────────────────────────────────────────
72
+ h2('1 · How will you use madarX?');
73
+ const mode = await select('Choose a setup', [
74
+ { label: 'Personal', value: 'local', tag: 'recommended', hint: 'local-only, everything on this machine' },
75
+ { label: 'Team', value: 'supabase', hint: 'shared with a team via Supabase (auth, orgs, sharing)' },
76
+ ], { default: 0 });
77
+
78
+ if (mode === 'supabase') {
79
+ setConfig('auth_mode', 'supabase');
80
+ note('Enter your Supabase project credentials (stored in ' + layout.envFile + ').');
81
+ const existing = readEnvFile(layout.envFile);
82
+ const url = await ask('Supabase URL', { dflt: existing.SUPABASE_URL || existing.NEXT_PUBLIC_SUPABASE_URL || '' });
83
+ const anon = await ask('Supabase anon key', { dflt: existing.SUPABASE_ANON_KEY || '' });
84
+ const service = await ask('Supabase service-role key', { secret: true });
85
+ if (url) { upsertEnvVar(layout.envFile, 'SUPABASE_URL', url); upsertEnvVar(layout.envFile, 'NEXT_PUBLIC_SUPABASE_URL', url); }
86
+ if (anon) { upsertEnvVar(layout.envFile, 'SUPABASE_ANON_KEY', anon); upsertEnvVar(layout.envFile, 'NEXT_PUBLIC_SUPABASE_ANON_KEY', anon); }
87
+ if (service) upsertEnvVar(layout.envFile, 'SUPABASE_SERVICE_ROLE_KEY', service);
88
+ ok('Team mode (Supabase) configured.');
89
+ note('Apply the cloud schema once: see supabase/README.md.');
90
+ } else {
91
+ setConfig('auth_mode', 'local');
92
+ ok('Personal mode — local-only.');
93
+ }
94
+
95
+ // ── Model catalog (probes installed CLIs + Ollama; Anthropic always listed) ─
96
+ const { getModels, setModel, getModel } = await import('../agent-config.js');
97
+ const { defaultModelForEngine } = await import('../agent-engines.js');
98
+ let models = [];
99
+ try { models = await getModels(); } catch { models = []; }
100
+ const recommendedId = models.find((m) => m.engine === 'claude-code') ? 'claude-code'
101
+ : (models.find((m) => m.id === 'claude-sonnet-4-6') ? 'claude-sonnet-4-6' : models[0]?.id);
102
+ const modelOption = (m) => ({
103
+ label: m.label,
104
+ value: { id: m.id, engine: m.engine },
105
+ hint: m.engine,
106
+ tag: m.id === recommendedId ? 'recommended' : undefined,
107
+ });
108
+ const orderedModels = [
109
+ ...models.filter((m) => m.id === recommendedId),
110
+ ...models.filter((m) => m.id !== recommendedId),
111
+ ];
112
+
113
+ // ── 2. Main agent model ──────────────────────────────────────────────────
114
+ h2('2 · Main agent model');
115
+ note('the orchestrator that plans your work and dispatches sub-agents');
116
+ const current = getModel();
117
+ const mainChoice = await select('Select the main agent model', [
118
+ ...orderedModels.map(modelOption),
119
+ { label: `Keep current (${current})`, value: { keep: true } },
120
+ ], { default: 0 });
121
+ if (!mainChoice.keep) { setModel(mainChoice.id); ok(`Main agent → ${mainChoice.id}`); }
122
+ else ok(`Main agent unchanged (${current})`);
123
+ const mainEngine = mainChoice.keep ? null : mainChoice.engine;
124
+
125
+ // ── 3. Sub-agent default model ───────────────────────────────────────────
126
+ h2('3 · Sub-agent default model');
127
+ note('what newly created agents inherit unless you pick another at creation');
128
+ const subChoice = await select('Select the default sub-agent model', [
129
+ { label: 'Same as main agent', value: { same: true }, tag: 'recommended' },
130
+ ...orderedModels.map(modelOption),
131
+ ], { default: 0 });
132
+ let subEngine, subModel;
133
+ if (subChoice.same) {
134
+ subEngine = mainEngine || (orderedModels.find((m) => m.id === current)?.engine) || 'claude-code';
135
+ subModel = mainChoice.keep ? current : mainChoice.id;
90
136
  } else {
91
- console.log(' No extra roots granted.\n');
137
+ subEngine = subChoice.engine;
138
+ subModel = subChoice.engine === 'anthropic' ? subChoice.id : defaultModelForEngine(subChoice.engine);
92
139
  }
140
+ setConfig('default_agent_engine', subEngine);
141
+ setConfig('default_agent_model', subModel);
142
+ ok(`Sub-agents → ${subEngine}${subModel ? ' · ' + subModel : ''}`);
143
+
144
+ // ── 4. Secrets vault master key ──────────────────────────────────────────
145
+ h2('4 · Secrets vault');
146
+ const { resolveMasterKey } = await import('../master-key.js');
147
+ resolveMasterKey({ allowGenerate: true });
148
+ ok('Master key ready (AES-256-GCM).');
93
149
 
94
- // 3. API keys → encrypted vault.
95
- console.log('3) API keys (stored encrypted in the vault; press Enter to skip any)');
96
- const { setSecret } = await import('../secrets.js');
150
+ // ── 5. API keys → encrypted vault ────────────────────────────────────────
151
+ h2('5 · API keys');
152
+ note('stored encrypted in the vault · press Enter to skip any');
153
+ const { setSecret, getSecret } = await import('../secrets.js');
154
+ const usesAnthropic = [mainEngine, subEngine].includes('anthropic');
97
155
  const keyPrompts = [
98
- ['ANTHROPIC_API_KEY', 'Anthropic API key (Claude)'],
156
+ ['ANTHROPIC_API_KEY', 'Anthropic API key (Claude)' + (usesAnthropic ? ' — required for your selection' : '')],
99
157
  ['OPENAI_API_KEY', 'OpenAI API key (voice/realtime, optional)'],
100
158
  ];
101
159
  for (const [name, label] of keyPrompts) {
102
- const val = await askSecret(rl, ` ${label}`);
160
+ let have = false;
161
+ try { have = Boolean(getSecret(name)); } catch { /* vault may be empty */ }
162
+ const val = await ask(label + (have ? ' (set — Enter to keep)' : ''), { secret: true });
103
163
  if (val) {
104
- try { setSecret(name, val, { scope: 'global' }); console.log(` Stored ${name}.`); }
105
- catch (err) { console.error(` Could not store ${name}: ${err.message}`); }
164
+ try { setSecret(name, val, { scope: 'global' }); ok(`Stored ${name}.`); }
165
+ catch (err) { console.error(' ' + fg(P.mars, '✗') + ` Could not store ${name}: ${err.message}`); }
106
166
  }
107
167
  }
108
- console.log('');
109
-
110
- // 4. WhatsApp bridge toggle.
111
- console.log('4) WhatsApp bridge');
112
- const enableWa = await askYesNo(rl, ' Run the WhatsApp bridge with `madarx`?', true);
113
- if (enableWa) {
114
- removeEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP');
115
- console.log(' Enabled (idles until you pair a dedicated number).\n');
168
+
169
+ // ── 6. Folder permissions ────────────────────────────────────────────────
170
+ h2('6 · Folder permissions');
171
+ note('the agent can read/write/run ONLY inside roots you grant (repo + workspace/ always allowed)');
172
+ const existingRoots = readEnvFile(layout.envFile).MADARX_ALLOWED_ROOTS || '';
173
+ const roots = await ask('Extra allowed roots (comma-separated absolute paths)', { dflt: existingRoots });
174
+ if (roots) {
175
+ const cleaned = roots.split(',').map((r) => r.trim()).filter(Boolean).join(',');
176
+ upsertEnvVar(layout.envFile, 'MADARX_ALLOWED_ROOTS', cleaned);
177
+ ok(`Granted: ${cleaned}`);
116
178
  } else {
117
- upsertEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP', '1');
118
- console.log(' Disabled.\n');
179
+ note('no extra roots granted');
119
180
  }
120
181
 
121
- // 5. Auto-update preference (consumed by T3 self-update).
122
- console.log('5) Auto-update');
123
- const weekly = await askYesNo(rl, ' Check weekly for updates?', true);
124
- const { setConfig } = await import('../config.js');
125
- if (weekly) {
126
- const handsOff = await askYesNo(rl, ' Apply updates automatically (hands-off) instead of just notifying?', false);
182
+ // ── 7. WhatsApp bridge ───────────────────────────────────────────────────
183
+ h2('7 · WhatsApp bridge');
184
+ const enableWa = await confirm('Run the WhatsApp bridge with `madarx`?', { default: true });
185
+ if (enableWa) { removeEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP'); ok('Enabled idles until you pair a dedicated number.'); }
186
+ else { upsertEnvVar(layout.envFile, 'MADARX_DISABLE_WHATSAPP', '1'); ok('Disabled.'); }
187
+
188
+ // ── 8. Auto-update ───────────────────────────────────────────────────────
189
+ h2('8 · Auto-update');
190
+ const upd = await select('How should madarX handle updates?', [
191
+ { label: 'Notify weekly', value: 'notify', tag: 'recommended', hint: 'check weekly, tell me — I apply' },
192
+ { label: 'Auto-apply weekly', value: 'auto', hint: 'hands-off, gated by the approval/trust tier' },
193
+ { label: 'Off', value: 'off', hint: 'I will run `madarx update` myself' },
194
+ ], { default: 0 });
195
+ if (upd === 'off') { setConfig('auto_update_mode', 'off'); ok('Auto-update off.'); }
196
+ else {
127
197
  setConfig('auto_update_mode', 'weekly');
128
- setConfig('auto_update_apply', handsOff ? 'auto' : 'notify');
129
- console.log(` Weekly check on; updates will ${handsOff ? 'auto-apply (gated by the approval/trust tier)' : 'notify only'}.\n`);
130
- } else {
131
- setConfig('auto_update_mode', 'off');
132
- console.log(' Auto-update off. Run `madarx update` manually.\n');
198
+ setConfig('auto_update_apply', upd === 'auto' ? 'auto' : 'notify');
199
+ ok(`Weekly check on ${upd === 'auto' ? 'auto-apply' : 'notify only'}.`);
133
200
  }
134
201
 
135
- console.log('Setup complete. Start everything with: madarx\n');
202
+ console.log('\n' + bold(fg(P.platinum, 'Setup complete.')) + ' Start everything with: ' + fg(P.mars, 'madarx') + '\n');
136
203
  return 0;
137
204
  } catch (err) {
138
205
  console.error(`\nsetup failed: ${err?.stack || err}`);
139
206
  return 1;
140
- } finally {
141
- rl.close();
142
207
  }
143
208
  }
@@ -230,59 +230,12 @@ function htmlShell({ title, kicker, bodyHtml }) {
230
230
 
231
231
  // ── Renderers ───────────────────────────────────────────────────────────────
232
232
 
233
- export function renderIntakeFormHtml({ definition, schema, caseRow, settings = null, mode = 'preview', submit_endpoint = null, submit_token = null }) {
234
- if (mode === 'interactive') {
235
- return renderIntakeFormInteractiveHtml({ definition, schema, caseRow, settings, submit_endpoint, submit_token });
236
- }
237
- // Preview (Phase 1 / no flag) read-only artifact.
238
- const fields = Array.isArray(schema?.fields) ? schema.fields : [];
239
- const fieldsHtml = fields
240
- .map((f) => {
241
- const req = f.required ? '<span class="req"></span>' : '';
242
- const help = f.help ? `<p class="field-help">${escapeHtml(f.help)}</p>` : '';
243
- let preview = '<em class="muted">Field will be captured at intake.</em>';
244
- if (f.type === 'select' && Array.isArray(f.options)) {
245
- preview = `<span class="muted">Choose one of:</span> ${f.options.map((o) => `<span class="pill">${escapeHtml(o)}</span>`).join(' ')}`;
246
- } else if (f.type === 'shareholders') {
247
- preview = '<span class="muted">Repeatable rows: shareholder name + percentage (must sum to 100).</span>';
248
- } else if (f.placeholder) {
249
- preview = `<span class="muted">${escapeHtml(f.placeholder)}</span>`;
250
- } else if (f.type) {
251
- preview = `<span class="muted">Type: ${escapeHtml(f.type)}</span>`;
252
- }
253
- return `
254
- <div class="field">
255
- <span class="field-label">${escapeHtml(f.label || f.name)}${req}</span>
256
- ${help}
257
- <div class="field-value">${preview}</div>
258
- </div>`;
259
- })
260
- .join('');
261
-
262
- const body = `
263
- <h1>${escapeHtml(schema?.title || `${definition?.name || 'Process'} — intake`)}</h1>
264
- <div class="meta">
265
- <span><strong>Process:</strong>&nbsp;${escapeHtml(definition?.name || definition?.slug || '')}</span>
266
- <span><strong>Case:</strong>&nbsp;${escapeHtml(caseRow?.title || '')}</span>
267
- <span class="pill">awaiting submission</span>
268
- </div>
269
- ${schema?.description ? `<p class="muted">${escapeHtml(schema.description)}</p>` : ''}
270
- <div class="note">
271
- This artifact is the source-of-record intake page for case <code>${escapeHtml(caseRow?.id || '')}</code>.
272
- Submit the live form via the workflows dashboard; on submit a companion <em>intake submission</em> artifact
273
- is generated and linked to this case.
274
- </div>
275
- <h2>Fields</h2>
276
- ${fieldsHtml || '<p class="muted">No fields configured.</p>'}
277
- <div class="art-footer">
278
- Generated by Madarx OS process engine · definition <code>${escapeHtml(definition?.slug || '')}</code>
279
- </div>
280
- `;
281
- return htmlShell({
282
- title: schema?.title || `Intake — ${definition?.name || ''}`,
283
- kicker: 'Intake form · awaiting submission',
284
- bodyHtml: body,
285
- });
233
+ // Renders the branded interactive intake form a single self-contained HTML
234
+ // document with REAL form controls that POSTs to `submit_endpoint`. This is the
235
+ // only intake-form shape as of v2.14.0; the legacy read-only "preview" renderer
236
+ // and its MADARX_BRANDED_INTAKE flag were removed.
237
+ export function renderIntakeFormHtml({ definition, schema, caseRow, settings = null, submit_endpoint = null, submit_token = null }) {
238
+ return renderIntakeFormInteractiveHtml({ definition, schema, caseRow, settings, submit_endpoint, submit_token });
286
239
  }
287
240
 
288
241
  // ── Branded interactive renderer (Phase 2) ──────────────────────────────────
@@ -713,19 +666,18 @@ function safeCreate(opts) {
713
666
  }
714
667
  }
715
668
 
716
- export function createIntakeFormArtifact({ definition, schema, caseRow, settings = null, mode = 'preview', submit_endpoint = null, submit_token = null }) {
669
+ export function createIntakeFormArtifact({ definition, schema, caseRow, settings = null, submit_endpoint = null, submit_token = null }) {
717
670
  if (!definition || !caseRow) return null;
718
- const html = renderIntakeFormHtml({ definition, schema, caseRow, settings, mode, submit_endpoint, submit_token });
719
- const modeSuffix = mode === 'interactive' ? ' (branded)' : '';
720
- const title = `${definition.name || definition.slug || 'Process'} — intake form${modeSuffix} — ${caseRow.title || caseRow.id.slice(-8)}`;
671
+ const html = renderIntakeFormHtml({ definition, schema, caseRow, settings, submit_endpoint, submit_token });
672
+ const title = `${definition.name || definition.slug || 'Process'} intake form — ${caseRow.title || caseRow.id.slice(-8)}`;
721
673
  return safeCreate({
722
674
  title,
723
675
  kind: 'html',
724
676
  content: html,
725
677
  project_id: caseRow.project_id,
726
- // Dedupe keyed on case + mode so re-rendering with a fresh token (share-
727
- // link mint) replaces rather than spawns a new artifact.
728
- dedupe_key: `process_intake_form:${caseRow.id}:${mode}`,
678
+ // Dedupe keyed on case so re-rendering with a fresh token (share-link mint)
679
+ // replaces rather than spawns a new artifact.
680
+ dedupe_key: `process_intake_form:${caseRow.id}`,
729
681
  });
730
682
  }
731
683
 
@@ -104,20 +104,20 @@ function appendProcessAudit({ case_id, stage_id = null, action, status = 'succes
104
104
 
105
105
  // Render the case-level intake-form artifact at startCase time. Failure is
106
106
  // observation-only — engine state stays the source of truth and the case can
107
- // still progress without a presentation artifact. MADARX_BRANDED_INTAKE=1
108
- // switches to the interactive (in-document form) shape; off renders preview.
107
+ // still progress without a presentation artifact. The artifact is always the
108
+ // branded interactive (in-document form) shape; it posts to the stage submit
109
+ // endpoint. (The legacy read-only "preview" shape and its MADARX_BRANDED_INTAKE
110
+ // flag were removed in v2.14.0 — branded intake is the only start path.)
109
111
  function seedIntakeArtifact({ definition, firstStage, caseRow, snapshot }) {
110
112
  if (firstStage.kind !== 'intake_form') return null;
111
113
  try {
112
114
  const schema = parseIntakeFormSchema(definition);
113
- const branded = process.env.MADARX_BRANDED_INTAKE === '1';
114
115
  return createIntakeFormArtifact({
115
116
  definition,
116
117
  schema,
117
118
  caseRow,
118
119
  settings: snapshot,
119
- mode: branded ? 'interactive' : 'preview',
120
- submit_endpoint: branded ? `/api/processes/${caseRow.id}/stages/${firstStage.slug}/submit` : null,
120
+ submit_endpoint: `/api/processes/${caseRow.id}/stages/${firstStage.slug}/submit`,
121
121
  });
122
122
  } catch { return null; }
123
123
  }
@@ -0,0 +1,116 @@
1
+ // lib/process/policy-predicates.js — JSON predicate evaluator for policy_gate.
2
+ //
3
+ // Replaces the hand-rolled string DSL (`stages/policy-dsl-legacy.js`) with a
4
+ // declarative predicate tree. No tokenizer, no parser, no escaping bugs — a
5
+ // predicate is plain JSON that the spec-validator can validate structurally
6
+ // and an agent can author without learning an expression grammar.
7
+ //
8
+ // Shape:
9
+ // { "op": "and", "rules": [ <predicate>, ... ] }
10
+ // { "op": "or", "rules": [ <predicate>, ... ] }
11
+ // { "op": "not", "rule": <predicate> }
12
+ // { "op": "eq", "path": "intake.country", "value": "US" }
13
+ // { "op": "gte", "path": "prior_stage.kyc-risk.risk_score", "value": 0.3 }
14
+ // { "op": "in", "path": "intake.type", "value": ["MSA", "SOW", "NDA"] }
15
+ //
16
+ // Path resolution (read-only):
17
+ // intake.<field…> → case intake payload
18
+ // prior_stage.<slug>.<field…> → that stage's accumulated context output
19
+ // context.<field…> → raw context bag
20
+ // <bare> → resolved against the whole ctx object
21
+ //
22
+ // Equality (`eq`/`neq`) is intentionally loose (`==`/`!=`) so a `neq null`
23
+ // check treats a missing path the same as an explicit null — matching the
24
+ // "field must be provided" idiom the legacy DSL expressed as `x != null`.
25
+
26
+ const MAX_DEPTH = 20;
27
+
28
+ export const LOGICAL_OPS = new Set(['and', 'or', 'not']);
29
+ export const COMPARE_OPS = new Set(['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in', 'nin']);
30
+
31
+ const COMPARATORS = {
32
+ eq: (a, b) => a == b, // eslint-disable-line eqeqeq
33
+ neq: (a, b) => a != b, // eslint-disable-line eqeqeq
34
+ lt: (a, b) => Number(a) < Number(b),
35
+ lte: (a, b) => Number(a) <= Number(b),
36
+ gt: (a, b) => Number(a) > Number(b),
37
+ gte: (a, b) => Number(a) >= Number(b),
38
+ in: (a, b) => Array.isArray(b) && b.some((v) => v === a),
39
+ nin: (a, b) => Array.isArray(b) && !b.some((v) => v === a),
40
+ };
41
+
42
+ function isPlainObject(v) {
43
+ return v != null && typeof v === 'object' && !Array.isArray(v);
44
+ }
45
+
46
+ function readDeep(obj, path) {
47
+ if (!path) return obj;
48
+ return path.split('.').reduce((acc, key) => (acc == null ? acc : acc[key]), obj);
49
+ }
50
+
51
+ // Resolve a `path` string against the evaluation context. `ctx` carries
52
+ // `intake` and `context` (the accumulated per-stage output bag).
53
+ export function resolvePath(path, ctx) {
54
+ if (typeof path !== 'string' || !path) return undefined;
55
+ const dot = path.indexOf('.');
56
+ const head = dot === -1 ? path : path.slice(0, dot);
57
+ const rest = dot === -1 ? '' : path.slice(dot + 1);
58
+ if (head === 'intake') return readDeep(ctx?.intake, rest);
59
+ if (head === 'context') return readDeep(ctx?.context, rest);
60
+ if (head === 'prior_stage') {
61
+ const slugDot = rest.indexOf('.');
62
+ const slug = slugDot === -1 ? rest : rest.slice(0, slugDot);
63
+ const field = slugDot === -1 ? '' : rest.slice(slugDot + 1);
64
+ return readDeep(ctx?.context?.[slug], field);
65
+ }
66
+ return readDeep(ctx, path);
67
+ }
68
+
69
+ // True when a rule entry is a JSON predicate (vs a legacy string / { expr }).
70
+ export function isPredicateRule(rule) {
71
+ return isPlainObject(rule) && typeof rule.op === 'string';
72
+ }
73
+
74
+ // Evaluate a predicate tree against { intake, context }. Throws on a malformed
75
+ // predicate so the caller can surface the error in the gate trace.
76
+ export function evaluatePredicate(pred, ctx, depth = 0) {
77
+ if (depth > MAX_DEPTH) throw new Error('policy-predicate: maximum nesting depth exceeded');
78
+ if (!isPlainObject(pred)) throw new Error('policy-predicate: predicate must be an object');
79
+ const op = pred.op;
80
+ if (op === 'and' || op === 'or') {
81
+ if (!Array.isArray(pred.rules)) throw new Error(`policy-predicate: "${op}" requires a rules[] array`);
82
+ const results = pred.rules.map((r) => evaluatePredicate(r, ctx, depth + 1));
83
+ return op === 'and' ? results.every(Boolean) : results.some(Boolean);
84
+ }
85
+ if (op === 'not') {
86
+ if (!isPlainObject(pred.rule)) throw new Error('policy-predicate: "not" requires a rule object');
87
+ return !evaluatePredicate(pred.rule, ctx, depth + 1);
88
+ }
89
+ const cmp = COMPARATORS[op];
90
+ if (!cmp) throw new Error(`policy-predicate: unknown op "${op}"`);
91
+ if (typeof pred.path !== 'string' || !pred.path) {
92
+ throw new Error(`policy-predicate: "${op}" requires a path`);
93
+ }
94
+ const left = resolvePath(pred.path, ctx);
95
+ return Boolean(cmp(left, pred.value));
96
+ }
97
+
98
+ // Non-throwing wrapper mirroring the legacy `evaluateRule` return shape.
99
+ export function evaluatePredicateSafe(pred, ctx) {
100
+ try {
101
+ return { result: Boolean(evaluatePredicate(pred, ctx)), error: null };
102
+ } catch (err) {
103
+ return { result: false, error: err?.message || String(err) };
104
+ }
105
+ }
106
+
107
+ // Short human-readable label for a predicate when the author supplied none.
108
+ export function describePredicate(pred) {
109
+ if (!isPlainObject(pred)) return String(pred);
110
+ if (pred.label) return pred.label;
111
+ if (pred.op === 'and' || pred.op === 'or') {
112
+ return `(${(pred.rules || []).map(describePredicate).join(` ${pred.op} `)})`;
113
+ }
114
+ if (pred.op === 'not') return `not ${describePredicate(pred.rule)}`;
115
+ return `${pred.path} ${pred.op} ${JSON.stringify(pred.value)}`;
116
+ }
@@ -64,12 +64,20 @@
64
64
  "config": {
65
65
  "rules": [
66
66
  {
67
- "expr": "intake.project_name != null && intake.project_slug != null",
68
- "label": "Project name and slug must be provided"
67
+ "label": "Project name and slug must be provided",
68
+ "op": "and",
69
+ "rules": [
70
+ { "op": "neq", "path": "intake.project_name", "value": null },
71
+ { "op": "neq", "path": "intake.project_slug", "value": null }
72
+ ]
69
73
  },
70
74
  {
71
- "expr": "intake.data_directory_path != null && intake.data_directory_path != ''",
72
- "label": "Data directory path must be non-empty"
75
+ "label": "Data directory path must be non-empty",
76
+ "op": "and",
77
+ "rules": [
78
+ { "op": "neq", "path": "intake.data_directory_path", "value": null },
79
+ { "op": "neq", "path": "intake.data_directory_path", "value": "" }
80
+ ]
73
81
  }
74
82
  ]
75
83
  },
@@ -50,8 +50,12 @@
50
50
  "config": {
51
51
  "rules": [
52
52
  {
53
- "expr": "intake.project_id != null && intake.project_id != ''",
54
- "label": "Project ID must be provided"
53
+ "label": "Project ID must be provided",
54
+ "op": "and",
55
+ "rules": [
56
+ { "op": "neq", "path": "intake.project_id", "value": null },
57
+ { "op": "neq", "path": "intake.project_id", "value": "" }
58
+ ]
55
59
  }
56
60
  ]
57
61
  },
@@ -116,6 +116,46 @@ function validateAgentRun(stage, errors, prefix, opts, stageSlugs) {
116
116
  }
117
117
  }
118
118
 
119
+ // Predicate operator sets (mirror lib/process/policy-predicates.js).
120
+ const PREDICATE_LOGICAL_OPS = new Set(['and', 'or']);
121
+ const PREDICATE_COMPARE_OPS = new Set(['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in', 'nin']);
122
+ const PREDICATE_MAX_DEPTH = 20;
123
+
124
+ // Validate a JSON predicate tree structurally. Mirrors the evaluator so an
125
+ // invalid predicate is rejected at authoring time, not at case run time.
126
+ function validatePredicate(pred, errors, prefix, depth = 0) {
127
+ if (depth > PREDICATE_MAX_DEPTH) {
128
+ pushErr(errors, prefix, 'predicate nesting too deep');
129
+ return;
130
+ }
131
+ if (!isPlainObject(pred)) {
132
+ pushErr(errors, prefix, 'predicate must be an object');
133
+ return;
134
+ }
135
+ const op = pred.op;
136
+ if (PREDICATE_LOGICAL_OPS.has(op)) {
137
+ if (!Array.isArray(pred.rules) || pred.rules.length === 0) {
138
+ pushErr(errors, `${prefix}.rules`, `"${op}" requires a non-empty rules[] array`);
139
+ } else {
140
+ pred.rules.forEach((r, i) => validatePredicate(r, errors, `${prefix}.rules[${i}]`, depth + 1));
141
+ }
142
+ } else if (op === 'not') {
143
+ if (!isPlainObject(pred.rule)) pushErr(errors, `${prefix}.rule`, '"not" requires a rule object');
144
+ else validatePredicate(pred.rule, errors, `${prefix}.rule`, depth + 1);
145
+ } else if (PREDICATE_COMPARE_OPS.has(op)) {
146
+ if (typeof pred.path !== 'string' || !pred.path.trim()) {
147
+ pushErr(errors, `${prefix}.path`, 'required (non-empty string)');
148
+ }
149
+ if (!('value' in pred)) {
150
+ pushErr(errors, `${prefix}.value`, 'required');
151
+ } else if ((op === 'in' || op === 'nin') && !Array.isArray(pred.value)) {
152
+ pushErr(errors, `${prefix}.value`, `"${op}" requires an array value`);
153
+ }
154
+ } else {
155
+ pushErr(errors, `${prefix}.op`, `unknown predicate op "${op}"`);
156
+ }
157
+ }
158
+
119
159
  function validatePolicyGate(stage, errors, prefix) {
120
160
  const config = stage.config || {};
121
161
  if (!Array.isArray(config.rules) || config.rules.length === 0) {
@@ -125,13 +165,18 @@ function validatePolicyGate(stage, errors, prefix) {
125
165
  config.rules.forEach((rule, i) => {
126
166
  const rpath = `${prefix}.config.rules[${i}]`;
127
167
  if (typeof rule === 'string') {
168
+ // Legacy string DSL (deprecated; accepted one release for migration).
128
169
  if (!rule.trim()) pushErr(errors, rpath, 'empty rule expression');
170
+ } else if (isPlainObject(rule) && typeof rule.op === 'string') {
171
+ // JSON predicate (canonical form).
172
+ validatePredicate(rule, errors, rpath);
129
173
  } else if (isPlainObject(rule)) {
174
+ // Legacy { expr, label } wrapper.
130
175
  if (!rule.expr || typeof rule.expr !== 'string' || !rule.expr.trim()) {
131
176
  pushErr(errors, `${rpath}.expr`, 'required (non-empty string)');
132
177
  }
133
178
  } else {
134
- pushErr(errors, rpath, 'rule must be a string or { expr, label } object');
179
+ pushErr(errors, rpath, 'rule must be a JSON predicate, a string, or { expr, label }');
135
180
  }
136
181
  });
137
182
  }