openmeld 0.3.222 → 0.3.224

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 (177) hide show
  1. package/dist/{add-me-membership-Wc69O6rA.js → add-me-membership-CGISMRPF.js} +2 -2
  2. package/dist/{add-me-membership-Wc69O6rA.js.map → add-me-membership-CGISMRPF.js.map} +1 -1
  3. package/dist/{agents-B8zhQnGw.js → agents-CR7BebgO.js} +12 -12
  4. package/dist/{agents-B8zhQnGw.js.map → agents-CR7BebgO.js.map} +1 -1
  5. package/dist/{api-client-foundation-DTiFoGpI.js → api-client-foundation-CqbIn_de.js} +1 -1
  6. package/dist/{api-client-foundation-DnJ_JYli.js → api-client-foundation-DpVwrgh-.js} +3 -3
  7. package/dist/{api-client-foundation-DnJ_JYli.js.map → api-client-foundation-DpVwrgh-.js.map} +1 -1
  8. package/dist/auth-session-BJfKu74u.js +4 -0
  9. package/dist/{auth-session-nhS8jyux.js → auth-session-uEk_Tx6T.js} +8 -8
  10. package/dist/auth-session-uEk_Tx6T.js.map +1 -0
  11. package/dist/{base-url-CMBApK1J.js → base-url-DXrUiSMI.js} +1 -1
  12. package/dist/{base-url-D7uE_xTo.js → base-url-DvjOkKPs.js} +2 -2
  13. package/dist/{base-url-D7uE_xTo.js.map → base-url-DvjOkKPs.js.map} +1 -1
  14. package/dist/{channel-ggx0o_aG.js → channel-B2fD2_be.js} +4 -4
  15. package/dist/{channel-ggx0o_aG.js.map → channel-B2fD2_be.js.map} +1 -1
  16. package/dist/{cli-binary-manifest-DiUulkp0.js → cli-binary-manifest-CT5X05lk.js} +30 -4
  17. package/dist/cli-binary-manifest-CT5X05lk.js.map +1 -0
  18. package/dist/{command-Bz9x7V2T.js → command-CQ9XRwqf.js} +22 -165
  19. package/dist/command-CQ9XRwqf.js.map +1 -0
  20. package/dist/{computer-connection-M3N6plkj.js → computer-connection-Dm7iTnRK.js} +2 -2
  21. package/dist/{computer-connection-M3N6plkj.js.map → computer-connection-Dm7iTnRK.js.map} +1 -1
  22. package/dist/{computer-connection-review-DY5BK_27.js → computer-connection-review-RHAoddSS.js} +6 -6
  23. package/dist/{computer-connection-review-DY5BK_27.js.map → computer-connection-review-RHAoddSS.js.map} +1 -1
  24. package/dist/{computer-disconnect-DR1WDSPK.js → computer-disconnect-BWRsge_2.js} +10 -10
  25. package/dist/{computer-disconnect-DR1WDSPK.js.map → computer-disconnect-BWRsge_2.js.map} +1 -1
  26. package/dist/{computer-setup-continuation-2gs8z-nB.js → computer-setup-continuation-BOCRH0qq.js} +4 -4
  27. package/dist/{computer-setup-continuation-2gs8z-nB.js.map → computer-setup-continuation-BOCRH0qq.js.map} +1 -1
  28. package/dist/context-Bdh3nAzw.js +162 -0
  29. package/dist/context-Bdh3nAzw.js.map +1 -0
  30. package/dist/{control-plane-e3W6PD2M.js → control-plane-rTE2rHZ5.js} +2 -2
  31. package/dist/{control-plane-e3W6PD2M.js.map → control-plane-rTE2rHZ5.js.map} +1 -1
  32. package/dist/{daemon-device-id-DWO9_QW6.js → daemon-device-id-B1Af2Zmn.js} +344 -36
  33. package/dist/daemon-device-id-B1Af2Zmn.js.map +1 -0
  34. package/dist/{daemon-frame-transport-D2-tazuK.js → daemon-frame-transport-WiB73yhT.js} +519 -12
  35. package/dist/daemon-frame-transport-WiB73yhT.js.map +1 -0
  36. package/dist/{daemon-lifecycle-journal-DyKx1xzm.js → daemon-lifecycle-journal-CDZLWgMj.js} +11 -11
  37. package/dist/daemon-lifecycle-journal-CDZLWgMj.js.map +1 -0
  38. package/dist/{daemon-runtime-lease-BUr4qsLo.js → daemon-runtime-lease-1LMeZ6IS.js} +2 -2
  39. package/dist/{daemon-runtime-lease-BUr4qsLo.js.map → daemon-runtime-lease-1LMeZ6IS.js.map} +1 -1
  40. package/dist/{daemon-runtime-lease-C9X8xV_F.js → daemon-runtime-lease-Bz0ucJj3.js} +1 -1
  41. package/dist/{daemon-service-contract-BpOBMGX0.js → daemon-service-contract-GLmAxsq-.js} +4 -4
  42. package/dist/{daemon-service-contract-BpOBMGX0.js.map → daemon-service-contract-GLmAxsq-.js.map} +1 -1
  43. package/dist/{daemon-service-manager-HL4VKbIU.js → daemon-service-manager-C8RUCMDo.js} +9 -7
  44. package/dist/daemon-service-manager-C8RUCMDo.js.map +1 -0
  45. package/dist/{daemon-service-manager-B-QrDe5p.js → daemon-service-manager-CU-79a4z.js} +1 -1
  46. package/dist/{daemon-service-runtime-bKt0YjC7.js → daemon-service-runtime-CBJtgM4P.js} +397 -51
  47. package/dist/daemon-service-runtime-CBJtgM4P.js.map +1 -0
  48. package/dist/{daemon-service-update-coordinator-D8O1uTtu.js → daemon-service-update-coordinator-0LB_XGVZ.js} +48 -33
  49. package/dist/daemon-service-update-coordinator-0LB_XGVZ.js.map +1 -0
  50. package/dist/{daemon-state-B44aq2nm.js → daemon-state-Ca0WK5x0.js} +3 -3
  51. package/dist/{daemon-state-B44aq2nm.js.map → daemon-state-Ca0WK5x0.js.map} +1 -1
  52. package/dist/{dist-B07ziN_u.js → dist-BeJcIdCZ.js} +25 -17
  53. package/dist/dist-BeJcIdCZ.js.map +1 -0
  54. package/dist/dist-C32frPV2.js +4 -0
  55. package/dist/{dist-B2EauBG6.js → dist-YbTZ-Y-2.js} +16 -12
  56. package/dist/dist-YbTZ-Y-2.js.map +1 -0
  57. package/dist/{elapsed-time-Ooo4IC25.js → elapsed-time-q8lSPcfm.js} +6 -6
  58. package/dist/{elapsed-time-Ooo4IC25.js.map → elapsed-time-q8lSPcfm.js.map} +1 -1
  59. package/dist/{entry-DeIRMCiW.js → entry-CpS6tnIk.js} +12 -12
  60. package/dist/{entry-DeIRMCiW.js.map → entry-CpS6tnIk.js.map} +1 -1
  61. package/dist/{installation-inventory-DThnBEhV.js → installation-inventory-C5FsAvrf.js} +5 -5
  62. package/dist/{installation-inventory-DThnBEhV.js.map → installation-inventory-C5FsAvrf.js.map} +1 -1
  63. package/dist/{installer-D2bWZT88.js → installer-054NLJg6.js} +2 -2
  64. package/dist/{installer-D2bWZT88.js.map → installer-054NLJg6.js.map} +1 -1
  65. package/dist/io-DT66typ4.js +16 -0
  66. package/dist/io-DT66typ4.js.map +1 -0
  67. package/dist/{local-components-B6SCXZf9.js → local-components-DleLEzSU.js} +2 -1
  68. package/dist/local-components-DleLEzSU.js.map +1 -0
  69. package/dist/{lock-Bsl_ElWy.js → lock-iue1J2xy.js} +8 -5
  70. package/dist/lock-iue1J2xy.js.map +1 -0
  71. package/dist/{cli-space-api-CQtKu9Zt.js → meta-api-B1k3mwHN.js} +203 -19
  72. package/dist/meta-api-B1k3mwHN.js.map +1 -0
  73. package/dist/{openmeld-BQy0nMox.js → openmeld-BFO3sfC_.js} +93 -1027
  74. package/dist/openmeld-BFO3sfC_.js.map +1 -0
  75. package/dist/openmeld-dev.js +1 -1
  76. package/dist/{openmeld-environment-target-B6HqY0_a.js → openmeld-environment-target-BBn5Ko6p.js} +3 -3
  77. package/dist/{openmeld-environment-target-B6HqY0_a.js.map → openmeld-environment-target-BBn5Ko6p.js.map} +1 -1
  78. package/dist/{openmeld-maintenance-worker-BSODPHbn.js → openmeld-maintenance-worker-Ce4ehQ-c.js} +15 -14
  79. package/dist/openmeld-maintenance-worker-Ce4ehQ-c.js.map +1 -0
  80. package/dist/{openmeld-tools-update-join-BfY0GnDs.js → openmeld-tools-update-join-D24llJ9L.js} +4 -4
  81. package/dist/{openmeld-tools-update-join-BfY0GnDs.js.map → openmeld-tools-update-join-D24llJ9L.js.map} +1 -1
  82. package/dist/{openmeld-tools-update-process-frame-B-XB4dmO.js → openmeld-tools-update-process-frame-BtFKp70p.js} +2 -2
  83. package/dist/{openmeld-tools-update-process-frame-B-XB4dmO.js.map → openmeld-tools-update-process-frame-BtFKp70p.js.map} +1 -1
  84. package/dist/{openmeld-tools-update-process-frame-j-RXwFsK.js → openmeld-tools-update-process-frame-DbEZ3fEh.js} +1 -1
  85. package/dist/openmeld.js +9 -5
  86. package/dist/openmeld.js.map +1 -1
  87. package/dist/{prepare-provider-runtime-CWZcuMF6.js → prepare-provider-runtime-MB-BxOgt.js} +3342 -1327
  88. package/dist/prepare-provider-runtime-MB-BxOgt.js.map +1 -0
  89. package/dist/{prepare-session-executor-CkDxstsf.js → prepare-session-executor-zvSZ6jqy.js} +29 -28
  90. package/dist/prepare-session-executor-zvSZ6jqy.js.map +1 -0
  91. package/dist/{presenter-BcxiQyJg.js → presenter-MJ5YgsOT.js} +3 -13
  92. package/dist/presenter-MJ5YgsOT.js.map +1 -0
  93. package/dist/{process-channel-BQwtOlRc.js → process-channel-CgbduFCz.js} +2 -2
  94. package/dist/{process-channel-BQwtOlRc.js.map → process-channel-CgbduFCz.js.map} +1 -1
  95. package/dist/process-environment-BWSFeUu6.js +49 -0
  96. package/dist/process-environment-BWSFeUu6.js.map +1 -0
  97. package/dist/process-identity-BQLdaZdB.js +190 -0
  98. package/dist/process-identity-BQLdaZdB.js.map +1 -0
  99. package/dist/process-launch-B0pHlkV_.js +173 -0
  100. package/dist/process-launch-B0pHlkV_.js.map +1 -0
  101. package/dist/{published-production-safety-dp-fOmmB.js → published-production-safety-C40hKrBA.js} +2 -2
  102. package/dist/{published-production-safety-dp-fOmmB.js.map → published-production-safety-C40hKrBA.js.map} +1 -1
  103. package/dist/{runtime-BYaFkkLK.js → runtime-D6jItuQ-.js} +155 -702
  104. package/dist/runtime-D6jItuQ-.js.map +1 -0
  105. package/dist/{runtime-agent-controller-reporting-submission-BUUub9_1.js → runtime-agent-controller-reporting-submission-D9ysbi7R.js} +9 -9
  106. package/dist/{runtime-agent-controller-reporting-submission-BUUub9_1.js.map → runtime-agent-controller-reporting-submission-D9ysbi7R.js.map} +1 -1
  107. package/dist/{runtime-reporting-health-state-BgwfrH7f.js → runtime-reporting-health-state-DA-_vW-n.js} +2210 -60
  108. package/dist/runtime-reporting-health-state-DA-_vW-n.js.map +1 -0
  109. package/dist/{runtime-transport-Cc_RN-PL.js → runtime-transport-YIYHSJPn.js} +99 -14
  110. package/dist/runtime-transport-YIYHSJPn.js.map +1 -0
  111. package/dist/{service-CfO38_a-.js → service-Dz2MsvGr.js} +126 -550
  112. package/dist/service-Dz2MsvGr.js.map +1 -0
  113. package/dist/{service-account-admission-Dy2W3n3_.js → service-account-admission-BfdJ-kKR.js} +18 -10
  114. package/dist/service-account-admission-BfdJ-kKR.js.map +1 -0
  115. package/dist/{service-account-authorization-DKpIpxXo.js → service-account-authorization-DZbUOD29.js} +6 -6
  116. package/dist/{service-account-authorization-DKpIpxXo.js.map → service-account-authorization-DZbUOD29.js.map} +1 -1
  117. package/dist/{service-account-control-CCPQAZzn.js → service-account-control-DCMOKXDT.js} +16 -16
  118. package/dist/service-account-control-DCMOKXDT.js.map +1 -0
  119. package/dist/{service-control-capabilities-C9UHSMPz.js → service-control-capabilities-3_bdeHXu.js} +1 -1
  120. package/dist/{service-control-capabilities-xGylBNoH.js → service-control-capabilities-Bb738e_d.js} +19 -15
  121. package/dist/service-control-capabilities-Bb738e_d.js.map +1 -0
  122. package/dist/{service-control-carrier-capability-DDNyE5cB.js → service-control-carrier-capability-gMk5gMKU.js} +11 -4
  123. package/dist/service-control-carrier-capability-gMk5gMKU.js.map +1 -0
  124. package/dist/{state-CQG3k9eh.js → state-GxF_KAM1.js} +4 -4
  125. package/dist/{state-CQG3k9eh.js.map → state-GxF_KAM1.js.map} +1 -1
  126. package/dist/{upgrade-D5FxGbh1.js → upgrade-DfJwCD5H.js} +52 -32
  127. package/dist/upgrade-DfJwCD5H.js.map +1 -0
  128. package/dist/upgrade-DgmYWeNu.js +4 -0
  129. package/dist/windows/openmeld-windows-process.exe +0 -0
  130. package/dist/windows-artifact-DJ9DKjfc.js +16 -0
  131. package/dist/windows-artifact-DJ9DKjfc.js.map +1 -0
  132. package/dist/windows-task-command-COu_6Ke3.js +74 -0
  133. package/dist/windows-task-command-COu_6Ke3.js.map +1 -0
  134. package/dist/windows-task-entry-CtRpUbiK.js +50 -0
  135. package/dist/windows-task-entry-CtRpUbiK.js.map +1 -0
  136. package/dist/{windows-user-task-Bx2yYnOM.js → windows-user-task-B8NcRg_u.js} +1 -1
  137. package/dist/{windows-user-task-CRGbKggi.js → windows-user-task-Io5QuEVR.js} +108 -51
  138. package/dist/windows-user-task-Io5QuEVR.js.map +1 -0
  139. package/package.json +12 -12
  140. package/skills/openmeld-cli/playbooks/space-ops.md +9 -3
  141. package/skills/openmeld-cli/references/commands.md +0 -1
  142. package/dist/auth-session-D8dbMpaK.js +0 -4
  143. package/dist/auth-session-nhS8jyux.js.map +0 -1
  144. package/dist/cli-binary-manifest-DiUulkp0.js.map +0 -1
  145. package/dist/cli-space-api-CQtKu9Zt.js.map +0 -1
  146. package/dist/command-Bz9x7V2T.js.map +0 -1
  147. package/dist/context-l_31Mn4X.js +0 -473
  148. package/dist/context-l_31Mn4X.js.map +0 -1
  149. package/dist/daemon-device-id-DWO9_QW6.js.map +0 -1
  150. package/dist/daemon-frame-transport-D2-tazuK.js.map +0 -1
  151. package/dist/daemon-lifecycle-journal-DyKx1xzm.js.map +0 -1
  152. package/dist/daemon-service-manager-HL4VKbIU.js.map +0 -1
  153. package/dist/daemon-service-runtime-bKt0YjC7.js.map +0 -1
  154. package/dist/daemon-service-update-coordinator-D8O1uTtu.js.map +0 -1
  155. package/dist/dist-B07ziN_u.js.map +0 -1
  156. package/dist/dist-B2EauBG6.js.map +0 -1
  157. package/dist/dist-DhWI1iyi.js +0 -4
  158. package/dist/local-components-B6SCXZf9.js.map +0 -1
  159. package/dist/lock-Bsl_ElWy.js.map +0 -1
  160. package/dist/openmeld-BQy0nMox.js.map +0 -1
  161. package/dist/openmeld-maintenance-worker-BSODPHbn.js.map +0 -1
  162. package/dist/prepare-provider-runtime-CWZcuMF6.js.map +0 -1
  163. package/dist/prepare-session-executor-CkDxstsf.js.map +0 -1
  164. package/dist/presenter-BcxiQyJg.js.map +0 -1
  165. package/dist/process-identity-CNus0e6E.js +0 -146
  166. package/dist/process-identity-CNus0e6E.js.map +0 -1
  167. package/dist/runtime-BYaFkkLK.js.map +0 -1
  168. package/dist/runtime-reporting-health-state-BgwfrH7f.js.map +0 -1
  169. package/dist/runtime-transport-Cc_RN-PL.js.map +0 -1
  170. package/dist/service-CfO38_a-.js.map +0 -1
  171. package/dist/service-account-admission-Dy2W3n3_.js.map +0 -1
  172. package/dist/service-account-control-CCPQAZzn.js.map +0 -1
  173. package/dist/service-control-capabilities-xGylBNoH.js.map +0 -1
  174. package/dist/service-control-carrier-capability-DDNyE5cB.js.map +0 -1
  175. package/dist/upgrade-D5FxGbh1.js.map +0 -1
  176. package/dist/upgrade-DhFEu0k6.js +0 -4
  177. package/dist/windows-user-task-CRGbKggi.js.map +0 -1
@@ -1,28 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { g as toSpaceUpdatesUrl } from "./urls-CY2uzH2-.js";
4
- import { A as OPENMELD_HOME_ENV_KEY, lt as resolveOpenMeldRootDir, nt as organizationSkillReleaseDir, s as releaseLock, t as acquireLock } from "./lock-Bsl_ElWy.js";
5
- import { $n as getSpaceUpdatesResponseSchema, Lr as stringifyOrganizationSkillBundleCanonicalJson, Pr as organizationSkillBundleSchema, Xn as OPENMELD_HEADER_SPACE_ADDRESSING_VERSION, an as createRuntimeReportingApi, jt as createAgentActivityApi, qr as submitAgentControllerTaskLifecycleEventItemSchema, ri as observedLocalAgentSessionSchema, t as OpenMeldApiClientHttpError } from "./dist-B07ziN_u.js";
6
- import { Jn as buildCliLaunchInvocation, Tt as withAgentActivityLocalStateLock, _n as resolveInstalledGrokBuildLaunchCandidates, bn as resolveInstalledCodexLaunchCandidates, ft as listProjectBindings, ht as removeAgentActivityBindingsWhileDeliveryLocked, mn as resolveInstalledOpenCodeLaunchCandidates, vt as resolveProjectBindingForPath, wn as resolveInstalledClaudeCodeLaunchCandidates, wt as withAgentActivityDeliveryLock } from "./prepare-provider-runtime-CWZcuMF6.js";
7
- import { Ut as spaceWorkRelativePathSchema, Vt as SPACE_WORK_MAX_BYTES, Wt as spaceWorkSelectionSchema } from "./runtime-transport-Cc_RN-PL.js";
8
- import { d as getAuthSessionState } from "./auth-session-nhS8jyux.js";
9
- import { o as dirnamePath } from "./daemon-device-id-DWO9_QW6.js";
10
- import { C as readAgentActivityOutboxHealth, E as readRecentAgentActivityHookStatus, S as deferAgentActivityOutbox, T as removeProjectOutbox, _ as drainAgentActivityHookInbox, b as AgentActivitySubmissionResultsMismatchError, c as scanLocalAgentActivity, f as resolveOpenCodeDatabasePath, h as normalizeSharedSessionTitle, l as startAgentActivityTranscriptWatchers, m as resolveObservedAgentActivityBinding, u as readOpenCodeSessionRows, w as readDueAgentActivityOutbox, x as applyAgentActivitySubmissionResults, y as removeProjectInbox } from "./daemon-frame-transport-D2-tazuK.js";
4
+ import { A as OPENMELD_HOME_ENV_KEY, d as runWithHeldLock, rt as organizationSkillReleaseDir, s as releaseLock, t as acquireLock, ut as resolveOpenMeldRootDir } from "./lock-iue1J2xy.js";
5
+ import { Lr as stringifyOrganizationSkillBundleCanonicalJson, Mt as createAgentActivityApi, Pr as organizationSkillBundleSchema, Ti as signalTextEnvelopeSchema, Zn as OPENMELD_HEADER_SPACE_ADDRESSING_VERSION, _r as spaceTaskMutationReceiptSchema, er as getSpaceUpdatesResponseSchema, gr as spaceTaskIdSchema, hr as mutateSpaceTaskBodySchema, mr as createSpaceTaskBodySchema, on as createRuntimeReportingApi, qr as submitAgentControllerTaskLifecycleEventItemSchema, ri as observedLocalAgentSessionSchema, t as OpenMeldApiClientHttpError } from "./dist-BeJcIdCZ.js";
6
+ import { Jn as buildCliLaunchInvocation, Tt as withAgentActivityLocalStateLock, Xn as resolveExecutablePathsOnPath, Zn as listAgentControllerSupervisedProcessIds, _n as resolveInstalledGrokBuildLaunchCandidates, bn as resolveInstalledCodexLaunchCandidates, er as isDispatchSpaceActionDeliveryOnly, ft as listProjectBindings, ht as removeAgentActivityBindingsWhileDeliveryLocked, mn as resolveInstalledOpenCodeLaunchCandidates, qn as resolveDispatchSpaceActionMcpServer, vt as resolveProjectBindingForPath, wn as resolveInstalledClaudeCodeLaunchCandidates, wt as withAgentActivityDeliveryLock } from "./prepare-provider-runtime-MB-BxOgt.js";
7
+ import { Gt as spaceWorkSelectionSchema, Ht as SPACE_WORK_MAX_BYTES, Kt as spaceWorkingCopyResultSchema, Wt as spaceWorkRelativePathSchema, Yn as executionContextAssignmentSchema, Zn as executionContextTaskSchema, _n as spaceMessageFileReferenceSchema, fn as spaceFileEntryIdSchema, gn as spaceFileRevisionNumberSchema, rn as readSpaceFileTextResponseSchema } from "./runtime-transport-YIYHSJPn.js";
8
+ import { d as getAuthSessionState } from "./auth-session-uEk_Tx6T.js";
9
+ import { O as openMeldRuntimeProfileIdSchema } from "./control-plane-rTE2rHZ5.js";
10
+ import { C as readAgentActivityOutboxHealth, E as readRecentAgentActivityHookStatus, S as deferAgentActivityOutbox, T as removeProjectOutbox, _ as drainAgentActivityHookInbox, b as AgentActivitySubmissionResultsMismatchError, bn as cliJsonErrorEnvelopeSchema, c as scanLocalAgentActivity, f as resolveOpenCodeDatabasePath, h as normalizeSharedSessionTitle, l as startAgentActivityTranscriptWatchers, m as resolveObservedAgentActivityBinding, u as readOpenCodeSessionRows, w as readDueAgentActivityOutbox, x as applyAgentActivitySubmissionResults, y as removeProjectInbox } from "./daemon-frame-transport-WiB73yhT.js";
11
+ import { B as requireOpenMeldProfile, o as dirnamePath } from "./daemon-device-id-B1Af2Zmn.js";
12
+ import { a as resolveBaseUrl } from "./base-url-DvjOkKPs.js";
11
13
  import { n as writeDaemonLocalStateFile, t as readDaemonLocalStateFile } from "./daemon-local-state-file-jOXuXrky.js";
12
- import { _ as daemonRuntimeStateRootPath } from "./daemon-state-B44aq2nm.js";
13
- import { i as readDaemonServiceContract } from "./daemon-service-contract-BpOBMGX0.js";
14
- import { l as resolveUserFacingCliEntryCommand } from "./cli-entry-command-CR_9QU1i.js";
15
- import { l as canAttachAuthTokenToRequest, n as fetchSpaceRequestWithTimeout, s as buildOpenMeldRequestContextHeadersWithAuth, t as createCliApiClientFoundation } from "./api-client-foundation-DnJ_JYli.js";
16
- import { c as readGatewayTextResponse, u as parseJsonResponse } from "./cli-space-api-CQtKu9Zt.js";
17
- import { createHash, randomUUID } from "node:crypto";
14
+ import { _ as daemonRuntimeStateRootPath } from "./daemon-state-Ca0WK5x0.js";
15
+ import { i as readDaemonServiceContract } from "./daemon-service-contract-GLmAxsq-.js";
16
+ import { l as resolveUserFacingCliEntryCommand, n as formatOpenMeldCliCommand } from "./cli-entry-command-CR_9QU1i.js";
17
+ import { r as outLine } from "./io-DT66typ4.js";
18
+ import { d as buildOpenMeldRequestContextFromProfile, l as canAttachAuthTokenToRequest, n as fetchSpaceRequestWithTimeout, s as buildOpenMeldRequestContextHeadersWithAuth, t as createCliApiClientFoundation } from "./api-client-foundation-DpVwrgh-.js";
19
+ import { S as readDispatchSpaceActionRecord, _ as DispatchSpaceActionRejectedError, b as readDispatchSpaceActionContextForReceiptFromEnv, d as uploadPreparedSpaceFiles, f as createCliSpaceApi, g as DispatchSpaceActionClosedError, l as parseJsonResponse, s as readGatewayTextResponse, u as prepareRequestedSpaceSendFiles, w as writeDispatchSpaceActionRecord, x as readDispatchSpaceActionContextFromEnv } from "./meta-api-B1k3mwHN.js";
20
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
18
21
  import { homedir } from "node:os";
19
- import { basename, dirname, isAbsolute, join, resolve } from "node:path";
20
- import { appendFile, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
22
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
23
+ import { appendFile, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
21
24
  import * as z$1 from "zod/v4";
22
25
  import { z } from "zod/v4";
23
- import { constants, createReadStream } from "node:fs";
24
- import { spawn } from "node:child_process";
26
+ import { constants, createReadStream, readFileSync } from "node:fs";
27
+ import { execFile, spawn } from "node:child_process";
28
+ import { promisify } from "node:util";
25
29
  import { createInterface } from "node:readline";
30
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
31
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
32
+ import { performance } from "node:perf_hooks";
26
33
  //#region ../../packages/schemas/dist/schemas/config/agent-activity-route-registry.js
27
34
  const agentActivityRouteRegistrySchema = z$1.strictObject({
28
35
  routes: z$1.array(z$1.strictObject({ rootDir: z$1.string().trim().min(1).max(4096) })).max(64),
@@ -74,6 +81,87 @@ const runtimeReportingHealthStateSchema = z$1.strictObject({
74
81
  providerConversationProof: runtimeReportingChannelHealthSchema
75
82
  });
76
83
  //#endregion
84
+ //#region ../../packages/schemas/dist/schemas/space-mesh/dispatch-project-shell.js
85
+ const dispatchProjectShellInputSchema = z$1.strictObject({ command: z$1.string().trim().min(1).max(16e3) });
86
+ const dispatchProjectShellResultSchema = z$1.strictObject({
87
+ exitCode: z$1.number().int().min(0).max(255),
88
+ stdout: z$1.string().max(128 * 1024),
89
+ stderr: z$1.string().max(128 * 1024)
90
+ });
91
+ //#endregion
92
+ //#region ../../packages/schemas/dist/schemas/space-mesh/dispatch-space-action-receipt.js
93
+ const dispatchSpaceActionClosedReasonCodeSchema = z$1.enum(["space_action.context_expired", "space_action.context_mismatch"]);
94
+ const dispatchSpaceActionReceiptSchema = z$1.discriminatedUnion("status", [
95
+ z$1.strictObject({
96
+ status: z$1.literal("proposal_saved_locally"),
97
+ actionType: z$1.enum([
98
+ "post_message",
99
+ "post_status",
100
+ "stay_silent"
101
+ ]),
102
+ attemptId: z$1.string().min(1),
103
+ contextId: z$1.string().min(1),
104
+ dispatchId: z$1.string().min(1),
105
+ recordedAtMs: z$1.number().int().nonnegative(),
106
+ contextState: z$1.enum(["active", "expired"]),
107
+ coordinatorAcceptance: z$1.literal("unconfirmed"),
108
+ publication: z$1.literal("unconfirmed")
109
+ }),
110
+ z$1.strictObject({
111
+ status: z$1.literal("rejected_closed"),
112
+ reasonCode: dispatchSpaceActionClosedReasonCodeSchema,
113
+ coordinatorAcceptance: z$1.literal("unconfirmed"),
114
+ publication: z$1.literal("unconfirmed")
115
+ }),
116
+ z$1.strictObject({
117
+ status: z$1.literal("rejected_before_recording"),
118
+ reasonCode: z$1.enum([
119
+ "space_action.invalid_input",
120
+ "space_action.not_allowed",
121
+ "space_action.already_recorded",
122
+ "space_action.targets_unavailable"
123
+ ]),
124
+ coordinatorAcceptance: z$1.literal("unconfirmed"),
125
+ publication: z$1.literal("unconfirmed")
126
+ }),
127
+ z$1.strictObject({
128
+ status: z$1.literal("outcome_unknown"),
129
+ reasonCode: z$1.literal("space_action.recording_outcome_unknown"),
130
+ coordinatorAcceptance: z$1.literal("unconfirmed"),
131
+ publication: z$1.literal("unconfirmed")
132
+ })
133
+ ]);
134
+ const dispatchSpaceActionToolResultSchema = z$1.strictObject({ receipt: dispatchSpaceActionReceiptSchema });
135
+ //#endregion
136
+ //#region ../../packages/schemas/dist/schemas/space-mesh/dispatch-space-history.js
137
+ const dispatchSpaceHistoryRequestSchema = z$1.strictObject({});
138
+ const dispatchSpaceHistoryResultSchema = z$1.strictObject({
139
+ spaceId: z$1.string().min(1),
140
+ sourceSignalId: z$1.string().min(1),
141
+ beforeCount: z$1.literal(20),
142
+ afterCount: z$1.literal(0),
143
+ signals: z$1.array(z$1.record(z$1.string(), z$1.unknown())).max(21),
144
+ nextCursor: z$1.string().min(1).nullable()
145
+ });
146
+ //#endregion
147
+ //#region ../../packages/schemas/dist/schemas/space-mesh/dispatch-space-read-result.js
148
+ const dispatchSpaceReadResultRequestSchema = z$1.strictObject({
149
+ resultId: z$1.string().uuid(),
150
+ offset: z$1.number().int().nonnegative()
151
+ });
152
+ /** A byte cursor addresses one immutable JSON snapshot, not a local file. */
153
+ const dispatchSpaceReadResultPageSchema = z$1.strictObject({
154
+ resultId: z$1.string().uuid(),
155
+ offset: z$1.number().int().nonnegative(),
156
+ nextOffset: z$1.number().int().positive().nullable(),
157
+ totalBytes: z$1.number().int().positive(),
158
+ text: z$1.string()
159
+ });
160
+ const dispatchSpaceReadResultSchema = z$1.strictObject({
161
+ result: z$1.record(z$1.string(), z$1.unknown()).optional(),
162
+ page: dispatchSpaceReadResultPageSchema.optional()
163
+ }).refine((value) => value.result !== void 0 !== (value.page !== void 0), { message: "A read returns either the complete result or one continuation page." });
164
+ //#endregion
77
165
  //#region src/agent-activity/managed-integrations.ts
78
166
  const AGENT_ACTIVITY_INTEGRATION_OWNER = "openmeld-agent-activity-v1";
79
167
  const LEGACY_AGENT_ACTIVITY_INTEGRATION_OWNER = "openmeld-agent-activity-v0";
@@ -2783,6 +2871,2109 @@ async function readLocalReportingHealth(rootDir) {
2783
2871
  return await Promise.all([readAgentActivityOutboxHealth({ rootDir }), readControllerTaskLifecycleOutboxHealth({ rootDir })]);
2784
2872
  }
2785
2873
  //#endregion
2874
+ //#region src/local-service/file-access/claude-project-container.ts
2875
+ const execFileAsync$2 = promisify(execFile);
2876
+ const PROJECT_IMAGE = "node:24-bookworm@sha256:64af3819f9275802414d7cdc38c27e9d82bd564dec4d4da87d008255d36c63b4";
2877
+ const WORKSPACE_IN_CONTAINER = "/workspace";
2878
+ const COMMAND_TIMEOUT_MS = 12e4;
2879
+ const COMMAND_OUTPUT_BYTES = 128 * 1024;
2880
+ const CONTAINER_NAME_PREFIX = "openmeld-claude-project-";
2881
+ const CONTAINER_MISSING_RE = /no such container|no container with name|does not exist/iu;
2882
+ const LINE_BREAK_RE = /\r?\n/u;
2883
+ const CONTEXT_ID_RE = /^[a-f0-9-]{36}$/iu;
2884
+ async function resolveClaudeProjectContainerRuntime() {
2885
+ for (const kind of ["docker", "podman"]) {
2886
+ const binary = resolveExecutablePathsOnPath(kind)[0];
2887
+ if (!binary) continue;
2888
+ try {
2889
+ await execFileAsync$2(binary, [
2890
+ "version",
2891
+ "--format",
2892
+ "{{.Server.Version}}"
2893
+ ], {
2894
+ encoding: "utf8",
2895
+ maxBuffer: 4096,
2896
+ timeout: 5e3,
2897
+ windowsHide: true
2898
+ });
2899
+ return {
2900
+ binary,
2901
+ engineIdentity: await readContainerEngineIdentity({
2902
+ binary,
2903
+ kind
2904
+ }),
2905
+ kind
2906
+ };
2907
+ } catch {}
2908
+ }
2909
+ throw new Error("claude_project.container_runtime_unavailable");
2910
+ }
2911
+ async function prepareClaudeProjectContainer(input) {
2912
+ const runtime = await resolveClaudeProjectContainerRuntime();
2913
+ try {
2914
+ await execFileAsync$2(runtime.binary, [
2915
+ "image",
2916
+ "inspect",
2917
+ "--format",
2918
+ "{{.Id}}",
2919
+ PROJECT_IMAGE
2920
+ ], {
2921
+ encoding: "utf8",
2922
+ maxBuffer: 4096,
2923
+ timeout: 1e4,
2924
+ windowsHide: true
2925
+ });
2926
+ } catch {
2927
+ try {
2928
+ await execFileAsync$2(runtime.binary, ["pull", PROJECT_IMAGE], {
2929
+ encoding: "utf8",
2930
+ maxBuffer: 1024 * 1024,
2931
+ timeout: 3e5,
2932
+ windowsHide: true
2933
+ });
2934
+ } catch (error) {
2935
+ throw new Error("claude_project.image_unavailable", { cause: error });
2936
+ }
2937
+ }
2938
+ const workspacePath = await realpath(input.workspacePath);
2939
+ const boundaryRoot = await realpath(input.boundaryRoot);
2940
+ if (workspacePath !== input.workspacePath || boundaryRoot !== input.boundaryRoot) throw new Error("claude_project.workspace_path_changed");
2941
+ const relativeWorkspace = assertContainedWorkspace(boundaryRoot, workspacePath);
2942
+ const outsideDirectory = await mkdtemp(join(dirname(boundaryRoot), ".openmeld-container-probe-"));
2943
+ const marker = randomUUID();
2944
+ const insideName = `.openmeld-container-probe-${marker}`;
2945
+ const insidePath = join(workspacePath, insideName);
2946
+ const outsidePath = join(outsideDirectory, "outside");
2947
+ const writeName = `.openmeld-container-write-probe-${marker}`;
2948
+ const writePath = join(workspacePath, writeName);
2949
+ try {
2950
+ await writeFile(insidePath, `inside:${marker}`, {
2951
+ flag: "wx",
2952
+ mode: 384
2953
+ });
2954
+ await writeFile(outsidePath, `outside:${marker}`, {
2955
+ flag: "wx",
2956
+ mode: 384
2957
+ });
2958
+ const inside = await runClaudeProjectContainerCommand({
2959
+ command: `cat ${quoteShellArgument(`${WORKSPACE_IN_CONTAINER}/${relativeWorkspace}/${insideName}`)}`,
2960
+ contextId: input.contextId,
2961
+ runtime,
2962
+ boundaryRoot,
2963
+ workspacePath
2964
+ });
2965
+ if (inside.exitCode !== 0 || inside.stdout.trim() !== `inside:${marker}`) throw new Error("claude_project.inside_access_unverified");
2966
+ const outside = await runClaudeProjectContainerCommand({
2967
+ command: `cat ${quoteShellArgument(outsidePath)}`,
2968
+ contextId: input.contextId,
2969
+ runtime,
2970
+ boundaryRoot,
2971
+ workspacePath
2972
+ });
2973
+ if (outside.exitCode === 0 || outside.stdout.includes(`outside:${marker}`)) throw new Error("claude_project.outside_access_unverified");
2974
+ if ((await runClaudeProjectContainerCommand({
2975
+ command: `printf 'written:${marker}' > ${quoteShellArgument(`${WORKSPACE_IN_CONTAINER}/${relativeWorkspace}/${writeName}`)}`,
2976
+ contextId: input.contextId,
2977
+ runtime,
2978
+ boundaryRoot,
2979
+ workspacePath
2980
+ })).exitCode !== 0 || await readFile(writePath, "utf8") !== `written:${marker}`) throw new Error("claude_project.inside_write_unverified");
2981
+ return runtime;
2982
+ } finally {
2983
+ await rm(insidePath, { force: true });
2984
+ await rm(writePath, { force: true });
2985
+ await rm(outsideDirectory, {
2986
+ recursive: true,
2987
+ force: true
2988
+ });
2989
+ }
2990
+ }
2991
+ function quoteShellArgument(value) {
2992
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
2993
+ }
2994
+ async function runClaudeProjectContainerCommand(input) {
2995
+ await assertContainerEngineIdentity(input.runtime);
2996
+ const workspacePath = await realpath(input.workspacePath);
2997
+ const boundaryRoot = await realpath(input.boundaryRoot);
2998
+ if (workspacePath !== input.workspacePath || boundaryRoot !== input.boundaryRoot) throw new Error("claude_project.workspace_path_changed");
2999
+ const relativeWorkspace = assertContainedWorkspace(boundaryRoot, workspacePath);
3000
+ if (!isAbsolute(workspacePath) || boundaryRoot.includes(",") || boundaryRoot.includes("\n") || boundaryRoot.includes("\r")) throw new Error("claude_project.workspace_path_unsupported");
3001
+ if (!input.command.trim() || input.command.length > 16e3) throw new Error("claude_project.command_invalid");
3002
+ const name = `${containerNamePrefix(input.contextId)}${randomBytes(4).toString("hex")}`;
3003
+ const args = buildClaudeProjectContainerArgs({
3004
+ command: input.command,
3005
+ name,
3006
+ boundaryRoot,
3007
+ relativeWorkspace
3008
+ });
3009
+ let outcome;
3010
+ try {
3011
+ const result = await execFileAsync$2(input.runtime.binary, args, {
3012
+ encoding: "utf8",
3013
+ maxBuffer: COMMAND_OUTPUT_BYTES,
3014
+ timeout: 135e3,
3015
+ windowsHide: true
3016
+ });
3017
+ outcome = {
3018
+ exitCode: 0,
3019
+ stdout: result.stdout,
3020
+ stderr: result.stderr
3021
+ };
3022
+ } catch (error) {
3023
+ const commandError = error;
3024
+ if (typeof commandError.code === "number") outcome = {
3025
+ exitCode: commandError.code,
3026
+ stdout: commandError.stdout ?? "",
3027
+ stderr: commandError.stderr ?? ""
3028
+ };
3029
+ else outcome = /* @__PURE__ */ new Error(`claude_project.container_command_failed: ${commandError.message}`);
3030
+ }
3031
+ try {
3032
+ await execFileAsync$2(input.runtime.binary, [
3033
+ "rm",
3034
+ "-f",
3035
+ name
3036
+ ], {
3037
+ encoding: "utf8",
3038
+ maxBuffer: 4096,
3039
+ timeout: 15e3,
3040
+ windowsHide: true
3041
+ });
3042
+ } catch (error) {
3043
+ const message = error instanceof Error ? error.message : String(error);
3044
+ if (!CONTAINER_MISSING_RE.test(message)) throw new Error(`claude_project.container_cleanup_unconfirmed: ${message}`, { cause: outcome });
3045
+ }
3046
+ if (outcome instanceof Error) throw outcome;
3047
+ return outcome;
3048
+ }
3049
+ async function stopClaudeProjectContainersForContext(input) {
3050
+ await assertContainerEngineIdentity(input.runtime);
3051
+ const prefix = containerNamePrefix(input.contextId);
3052
+ let names;
3053
+ try {
3054
+ const { stdout } = await execFileAsync$2(input.runtime.binary, [
3055
+ "ps",
3056
+ "-a",
3057
+ "--filter",
3058
+ `name=${prefix}`,
3059
+ "--format",
3060
+ "{{.Names}}"
3061
+ ], {
3062
+ encoding: "utf8",
3063
+ maxBuffer: 16384,
3064
+ timeout: 15e3,
3065
+ windowsHide: true
3066
+ });
3067
+ names = stdout.split(LINE_BREAK_RE).filter((name) => name.startsWith(prefix));
3068
+ } catch (error) {
3069
+ throw new Error("claude_project.container_cleanup_unconfirmed", { cause: error });
3070
+ }
3071
+ for (const name of names) try {
3072
+ await execFileAsync$2(input.runtime.binary, [
3073
+ "rm",
3074
+ "-f",
3075
+ name
3076
+ ], {
3077
+ encoding: "utf8",
3078
+ maxBuffer: 4096,
3079
+ timeout: 15e3,
3080
+ windowsHide: true
3081
+ });
3082
+ } catch (error) {
3083
+ throw new Error("claude_project.container_cleanup_unconfirmed", { cause: error });
3084
+ }
3085
+ }
3086
+ async function assertContainerEngineIdentity(runtime) {
3087
+ if (await readContainerEngineIdentity(runtime) !== runtime.engineIdentity) throw new Error("claude_project.container_engine_changed");
3088
+ }
3089
+ async function readContainerEngineIdentity(input) {
3090
+ if (input.kind === "docker") {
3091
+ const { stdout } = await execFileAsync$2(input.binary, [
3092
+ "info",
3093
+ "--format",
3094
+ "{{.ID}}"
3095
+ ], {
3096
+ encoding: "utf8",
3097
+ maxBuffer: 4096,
3098
+ timeout: 5e3,
3099
+ windowsHide: true
3100
+ });
3101
+ const identity = stdout.trim();
3102
+ if (!identity) throw new Error("claude_project.container_engine_identity_missing");
3103
+ return identity;
3104
+ }
3105
+ const { stdout } = await execFileAsync$2(input.binary, [
3106
+ "info",
3107
+ "--format",
3108
+ "json"
3109
+ ], {
3110
+ encoding: "utf8",
3111
+ maxBuffer: 128 * 1024,
3112
+ timeout: 5e3,
3113
+ windowsHide: true
3114
+ });
3115
+ const info = JSON.parse(stdout);
3116
+ if (typeof info.host?.hostname !== "string" || typeof info.store?.graphRoot !== "string") throw new Error("claude_project.container_engine_identity_missing");
3117
+ return `${info.host.hostname}:${info.store.graphRoot}`;
3118
+ }
3119
+ function containerNamePrefix(contextId) {
3120
+ if (!CONTEXT_ID_RE.test(contextId)) throw new Error("claude_project.context_id_invalid");
3121
+ return `${CONTAINER_NAME_PREFIX}${contextId.replaceAll("-", "")}-`;
3122
+ }
3123
+ function buildClaudeProjectContainerArgs(input) {
3124
+ if (!input.name.startsWith(CONTAINER_NAME_PREFIX)) throw new Error("claude_project.container_name_invalid");
3125
+ const user = typeof process.getuid === "function" && typeof process.getgid === "function" ? `${process.getuid()}:${process.getgid()}` : "1000:1000";
3126
+ return [
3127
+ "run",
3128
+ "--rm",
3129
+ "--pull",
3130
+ "never",
3131
+ "--name",
3132
+ input.name,
3133
+ "--network",
3134
+ "none",
3135
+ "--read-only",
3136
+ "--cap-drop",
3137
+ "ALL",
3138
+ "--security-opt",
3139
+ "no-new-privileges",
3140
+ "--pids-limit",
3141
+ "128",
3142
+ "--memory",
3143
+ "1g",
3144
+ "--cpus",
3145
+ "2",
3146
+ "--user",
3147
+ user,
3148
+ "--mount",
3149
+ `type=bind,src=${input.boundaryRoot},dst=${WORKSPACE_IN_CONTAINER}`,
3150
+ "--workdir",
3151
+ `${WORKSPACE_IN_CONTAINER}/${input.relativeWorkspace}`,
3152
+ "--tmpfs",
3153
+ "/tmp:rw,nosuid,nodev,size=64m",
3154
+ "--env",
3155
+ "HOME=/tmp",
3156
+ "--env",
3157
+ `GIT_DIR=${WORKSPACE_IN_CONTAINER}/repository.git/worktrees/worktree`,
3158
+ "--env",
3159
+ `GIT_COMMON_DIR=${WORKSPACE_IN_CONTAINER}/repository.git`,
3160
+ "--env",
3161
+ `GIT_WORK_TREE=${WORKSPACE_IN_CONTAINER}/worktree`,
3162
+ PROJECT_IMAGE,
3163
+ "/usr/bin/timeout",
3164
+ `${Math.floor(COMMAND_TIMEOUT_MS / 1e3)}s`,
3165
+ "/bin/bash",
3166
+ "-lc",
3167
+ input.command
3168
+ ];
3169
+ }
3170
+ function assertContainedWorkspace(boundaryRoot, workspacePath) {
3171
+ const within = relative(boundaryRoot, workspacePath);
3172
+ if (!within || within === ".." || within.startsWith(`..${sep}`) || isAbsolute(within)) throw new Error("claude_project.workspace_outside_boundary");
3173
+ return within.split(sep).join("/");
3174
+ }
3175
+ //#endregion
3176
+ //#region src/local-service/state/ledger-io.ts
3177
+ function createLedgerIo() {
3178
+ return {
3179
+ appendFile: async (filePath, content, encoding) => {
3180
+ await mkdir(dirnamePath(filePath), { recursive: true });
3181
+ await appendFile(filePath, content, { encoding });
3182
+ },
3183
+ copyFile: async (fromPath, toPath) => {
3184
+ await mkdir(dirnamePath(toPath), { recursive: true });
3185
+ await copyFile(fromPath, toPath);
3186
+ },
3187
+ mkdir: async (dirPath, options) => {
3188
+ await mkdir(dirPath, options);
3189
+ },
3190
+ readFile: async (filePath, encoding) => {
3191
+ return await readFile(filePath, encoding);
3192
+ },
3193
+ rename: async (fromPath, toPath) => {
3194
+ await mkdir(dirnamePath(toPath), { recursive: true });
3195
+ await rename(fromPath, toPath);
3196
+ },
3197
+ syncPath: async (fileOrDirectoryPath) => {
3198
+ const isWindows = process.platform === "win32";
3199
+ if (isWindows && (await stat(fileOrDirectoryPath)).isDirectory()) return;
3200
+ const handle = await open(fileOrDirectoryPath, isWindows ? "r+" : "r");
3201
+ try {
3202
+ await handle.sync();
3203
+ } finally {
3204
+ await handle.close();
3205
+ }
3206
+ },
3207
+ rm: async (filePath, options) => {
3208
+ await rm(filePath, options);
3209
+ },
3210
+ writeFile: async (filePath, content, encoding) => {
3211
+ await mkdir(dirnamePath(filePath), { recursive: true });
3212
+ await writeFile(filePath, content, encoding);
3213
+ }
3214
+ };
3215
+ }
3216
+ //#endregion
3217
+ //#region src/local-service/dispatch/execution-context-workspace.ts
3218
+ const execFileAsync$1 = promisify(execFile);
3219
+ const syncDirectory = createLedgerIo().syncPath;
3220
+ const COMMIT_PATTERN = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u;
3221
+ const manifestSchema = z.strictObject({
3222
+ version: z.union([z.literal(1), z.literal(2)]),
3223
+ identity: executionContextAssignmentSchema,
3224
+ sourceWorkingDirectory: z.string().nullable(),
3225
+ baseCommit: z.string().regex(COMMIT_PATTERN).nullable(),
3226
+ boundaryRoot: z.string(),
3227
+ workingDirectory: z.string(),
3228
+ status: z.enum([
3229
+ "preparing",
3230
+ "restoring",
3231
+ "completed",
3232
+ "in_use",
3233
+ "retiring",
3234
+ "released"
3235
+ ]),
3236
+ pristineFingerprint: z.string().regex(/^[a-f0-9]{64}$/u).optional(),
3237
+ copiedUncommittedFiles: z.literal(false),
3238
+ processSupervisionId: z.uuid().optional(),
3239
+ activeDispatchId: z.string().min(1).optional(),
3240
+ activeAttemptId: z.string().min(1).optional(),
3241
+ containerRuntime: z.strictObject({
3242
+ binary: z.string().min(1),
3243
+ engineIdentity: z.string().min(1),
3244
+ kind: z.enum(["docker", "podman"])
3245
+ }).optional(),
3246
+ retirement: z.strictObject({
3247
+ path: z.string(),
3248
+ pristineFingerprint: z.string().regex(/^[a-f0-9]{64}$/u)
3249
+ }).optional()
3250
+ }).refine((manifest) => manifest.version === 2 || (manifest.status === "preparing" || manifest.status === "completed") && !manifest.pristineFingerprint && !manifest.processSupervisionId && !manifest.activeDispatchId && !manifest.activeAttemptId && !manifest.containerRuntime && !manifest.retirement).refine((manifest) => manifest.identity.access === "space_context" ? manifest.sourceWorkingDirectory === null && manifest.baseCommit === null : manifest.sourceWorkingDirectory !== null && isAbsolute(manifest.sourceWorkingDirectory) && manifest.baseCommit !== null && manifest.identity.workspace === "isolated");
3251
+ async function prepareExecutionContextWorkspace(input) {
3252
+ const parsed = executionContextTaskSchema.safeParse(input.context);
3253
+ if (!parsed.success) throw failure("invalid_workspace_context");
3254
+ const { nativeConversationId, runtimeWorkspaceFingerprint } = parsed.data;
3255
+ const identity = executionContextAssignmentSchema.strip().parse(parsed.data);
3256
+ const source = identity.access !== "space_context" ? await canonicalDirectory(input.currentWorkingDirectory) : null;
3257
+ if (source) {
3258
+ assertSourceAllowed(source, input.policy);
3259
+ if (identity.workspace === "current") return {
3260
+ workingDirectory: source,
3261
+ boundaryRoot: source
3262
+ };
3263
+ }
3264
+ const ledgerRoot = await ensureDirectory(input.ledgerRootPath, true);
3265
+ const workspaceRoot = await ensureDirectory(join(ledgerRoot, "execution-context-workspaces"));
3266
+ const recordsRoot = await ensureDirectory(join(ledgerRoot, "execution-context-workspace-records"));
3267
+ const boundaryRoot = join(workspaceRoot, identity.id);
3268
+ const workingDirectory = source ? join(boundaryRoot, "worktree") : boundaryRoot;
3269
+ const recordPath = join(recordsRoot, `${identity.id}.json`);
3270
+ return await withWorkspaceLock(ledgerRoot, identity.id, async () => {
3271
+ const stored = await readManifest(recordPath);
3272
+ if (stored) {
3273
+ if (JSON.stringify(stored.identity) !== JSON.stringify(identity) || stored.sourceWorkingDirectory !== source || stored.boundaryRoot !== boundaryRoot || stored.workingDirectory !== workingDirectory) throw failure("workspace_identity_mismatch");
3274
+ await reconcileRetainedWorkspace(stored, recordPath, Boolean(runtimeWorkspaceFingerprint || nativeConversationId), ledgerRoot);
3275
+ return await verifyRetainedWorkspace(stored);
3276
+ }
3277
+ if (runtimeWorkspaceFingerprint || nativeConversationId) throw failure("workspace_record_missing");
3278
+ if (await inspectPath(boundaryRoot)) throw failure("workspace_already_exists");
3279
+ const baseCommit = source ? await resolveSourceCommit(source) : null;
3280
+ const manifest = {
3281
+ version: 2,
3282
+ identity,
3283
+ sourceWorkingDirectory: source,
3284
+ baseCommit,
3285
+ boundaryRoot,
3286
+ workingDirectory,
3287
+ status: "preparing",
3288
+ copiedUncommittedFiles: false,
3289
+ processSupervisionId: randomUUID()
3290
+ };
3291
+ await writeManifest(recordPath, manifest, "wx");
3292
+ await finishWorkspacePreparation(manifest, recordPath, true);
3293
+ return workspaceResult(manifest);
3294
+ });
3295
+ }
3296
+ async function reconcileRetainedWorkspace(record, path, hasNativeIdentity, ledgerRoot) {
3297
+ if (record.status === "retiring") await runWithHeldLock({
3298
+ lock: await acquireWorkspaceExecutionLock(ledgerRoot, record.identity.id),
3299
+ run: async () => {
3300
+ if (!record.processSupervisionId || (await listAgentControllerSupervisedProcessIds({
3301
+ fresh: true,
3302
+ processId: null,
3303
+ supervisionId: record.processSupervisionId
3304
+ })).length > 0) throw failure("workspace_execution_quiescence_unconfirmed");
3305
+ const reconciled = await finishWorkspaceRetirement(record, path);
3306
+ if (reconciled.status === "released") await restoreReleasedWorkspace(reconciled, path);
3307
+ }
3308
+ });
3309
+ else if (record.status === "released") await restoreReleasedWorkspace(record, path);
3310
+ else if (record.status === "preparing" || record.status === "restoring") {
3311
+ if (record.status === "preparing" && hasNativeIdentity) throw failure("workspace_creation_incomplete");
3312
+ if (!record.processSupervisionId || (await listAgentControllerSupervisedProcessIds({
3313
+ fresh: true,
3314
+ processId: null,
3315
+ supervisionId: record.processSupervisionId
3316
+ })).length > 0) throw failure("workspace_preparation_quiescence_unconfirmed");
3317
+ await finishWorkspacePreparation(record, path);
3318
+ } else if (record.status === "in_use") await runWithHeldLock({
3319
+ lock: await acquireWorkspaceExecutionLock(ledgerRoot, record.identity.id),
3320
+ run: async () => {
3321
+ if (record.containerRuntime) await stopClaudeProjectContainersForContext({
3322
+ contextId: record.identity.id,
3323
+ runtime: record.containerRuntime
3324
+ });
3325
+ if (!record.processSupervisionId || (await listAgentControllerSupervisedProcessIds({
3326
+ fresh: true,
3327
+ processId: null,
3328
+ supervisionId: record.processSupervisionId
3329
+ })).length > 0) throw failure("workspace_execution_quiescence_unconfirmed");
3330
+ await verifyRetainedWorkspace(record);
3331
+ const { activeAttemptId: _activeAttemptId, activeDispatchId: _activeDispatchId, containerRuntime: _containerRuntime, ...reconciled } = record;
3332
+ await writeManifest(path, {
3333
+ ...reconciled,
3334
+ status: "completed"
3335
+ }, "r+");
3336
+ }
3337
+ });
3338
+ }
3339
+ async function finishWorkspacePreparation(manifest, recordPath, pristineCreation = false) {
3340
+ const { boundaryRoot, workingDirectory, sourceWorkingDirectory: source, baseCommit } = manifest;
3341
+ await ensureDirectory(boundaryRoot);
3342
+ const repository = join(boundaryRoot, "repository.git");
3343
+ if (source && baseCommit) {
3344
+ if (!await inspectPath(repository)) {
3345
+ if ((await readdir(boundaryRoot)).length > 0) throw failure("workspace_creation_incomplete");
3346
+ await git(boundaryRoot, [
3347
+ "init",
3348
+ "--bare",
3349
+ "--template=",
3350
+ `--object-format=${baseCommit.length === 64 ? "sha256" : "sha1"}`,
3351
+ repository
3352
+ ], manifest.processSupervisionId);
3353
+ }
3354
+ await canonicalDirectory(repository);
3355
+ await assertPrivateMetadata(repository);
3356
+ if ((await readdir(boundaryRoot)).some((name) => name !== "repository.git" && name !== "worktree")) throw failure("workspace_creation_incomplete");
3357
+ if (await inspectPath(join(repository, "objects", "info", "alternates"))) throw failure("workspace_git_metadata_changed");
3358
+ if (!await inspectPath(workingDirectory)) {
3359
+ await git(boundaryRoot, [
3360
+ `--git-dir=${repository}`,
3361
+ "fetch",
3362
+ "--no-tags",
3363
+ "--no-recurse-submodules",
3364
+ "--depth=1",
3365
+ "--no-write-fetch-head",
3366
+ source,
3367
+ `${baseCommit}:refs/openmeld/base`
3368
+ ], manifest.processSupervisionId);
3369
+ await git(boundaryRoot, [
3370
+ `--git-dir=${repository}`,
3371
+ "worktree",
3372
+ "add",
3373
+ "--detach",
3374
+ workingDirectory,
3375
+ baseCommit
3376
+ ], manifest.processSupervisionId);
3377
+ }
3378
+ await verifyOwnedRepository(manifest);
3379
+ await finishMissingCheckoutFiles(manifest);
3380
+ if (!await isUnchangedCheckout(manifest)) throw failure("workspace_creation_incomplete");
3381
+ } else if ((await readdir(boundaryRoot)).length > 0) throw failure("workspace_creation_incomplete");
3382
+ await writeManifest(recordPath, {
3383
+ ...manifest,
3384
+ status: "completed",
3385
+ pristineFingerprint: pristineCreation ? await fingerprintDirectory(boundaryRoot) : void 0
3386
+ }, "r+");
3387
+ }
3388
+ async function readExecutionContextWorkspace(input) {
3389
+ if (!executionContextAssignmentSchema.shape.id.safeParse(input.contextId).success) throw failure("invalid_workspace_context");
3390
+ if (!await inspectPath(input.ledgerRootPath)) return null;
3391
+ const ledgerRoot = await canonicalDirectory(input.ledgerRootPath);
3392
+ const recordsRoot = join(ledgerRoot, "execution-context-workspace-records");
3393
+ if (!await inspectPath(recordsRoot)) return null;
3394
+ await canonicalDirectory(recordsRoot);
3395
+ const manifest = await readManifest(join(recordsRoot, `${input.contextId}.json`));
3396
+ if (!manifest) return null;
3397
+ const boundaryRoot = join(await canonicalDirectory(join(ledgerRoot, "execution-context-workspaces")), input.contextId);
3398
+ const workingDirectory = manifest.identity.access !== "space_context" ? join(boundaryRoot, "worktree") : boundaryRoot;
3399
+ if (manifest.identity.id !== input.contextId || manifest.boundaryRoot !== boundaryRoot || manifest.workingDirectory !== workingDirectory) throw failure("workspace_identity_mismatch");
3400
+ if (manifest.status === "released" || manifest.status === "retiring") return workspaceResult(manifest);
3401
+ if (manifest.status === "preparing" || manifest.status === "restoring") throw failure("workspace_creation_incomplete");
3402
+ return await verifyRetainedWorkspace(manifest);
3403
+ }
3404
+ async function markExecutionContextWorkspaceInUse(input) {
3405
+ const context = input.context;
3406
+ if (!context || context.workspace !== "isolated" || context.access === "space_context") return null;
3407
+ const root = await canonicalDirectory(input.ledgerRootPath);
3408
+ const lock = await acquireWorkspaceExecutionLock(root, context.id);
3409
+ const processSupervisionId = randomUUID();
3410
+ try {
3411
+ await withWorkspaceLock(root, context.id, async () => {
3412
+ await readExecutionContextWorkspace({
3413
+ ledgerRootPath: root,
3414
+ contextId: context.id
3415
+ });
3416
+ const path = join(root, "execution-context-workspace-records", `${context.id}.json`);
3417
+ const record = await readManifest(path);
3418
+ if (record?.status !== "completed") throw failure("workspace_execution_quiescence_unconfirmed");
3419
+ await writeManifest(path, {
3420
+ ...record,
3421
+ status: "in_use",
3422
+ processSupervisionId,
3423
+ ...input.containerRuntime && input.dispatchId && input.attemptId ? {
3424
+ activeDispatchId: input.dispatchId,
3425
+ activeAttemptId: input.attemptId
3426
+ } : {},
3427
+ ...input.containerRuntime ? { containerRuntime: input.containerRuntime } : {}
3428
+ }, "r+");
3429
+ });
3430
+ return {
3431
+ lock,
3432
+ processSupervisionId
3433
+ };
3434
+ } catch (error) {
3435
+ await releaseLock(lock);
3436
+ throw error;
3437
+ }
3438
+ }
3439
+ async function releaseExecutionContextWorkspace(input) {
3440
+ const root = await canonicalDirectory(input.ledgerRootPath);
3441
+ try {
3442
+ return await withWorkspaceLock(root, input.context.id, async () => {
3443
+ await readExecutionContextWorkspace({
3444
+ ledgerRootPath: root,
3445
+ contextId: input.context.id
3446
+ });
3447
+ const path = join(root, "execution-context-workspace-records", `${input.context.id}.json`);
3448
+ let record = await readManifest(path);
3449
+ if (!(record && ["completed", "in_use"].includes(record.status))) throw failure("workspace_creation_incomplete");
3450
+ if (record.containerRuntime) await stopClaudeProjectContainersForContext({
3451
+ contextId: record.identity.id,
3452
+ runtime: record.containerRuntime
3453
+ });
3454
+ if (!input.ownedProcessesQuiescent) return {
3455
+ status: "retained",
3456
+ reason: "execution_quiescence_unconfirmed"
3457
+ };
3458
+ const { activeAttemptId: _activeAttemptId, activeDispatchId: _activeDispatchId, containerRuntime: _containerRuntime, ...quiescentRecord } = record;
3459
+ const completed = {
3460
+ ...quiescentRecord,
3461
+ status: "completed"
3462
+ };
3463
+ await writeManifest(path, completed, "r+");
3464
+ record = await removePristineRetirement(completed, path);
3465
+ if (record.retirement) return {
3466
+ status: "retained",
3467
+ reason: "cleanup_incomplete"
3468
+ };
3469
+ if (!record.pristineFingerprint) return {
3470
+ status: "retained",
3471
+ reason: "baseline_unverified"
3472
+ };
3473
+ await verifyRetainedWorkspace(record);
3474
+ if (await fingerprintDirectory(record.boundaryRoot) !== record.pristineFingerprint) return {
3475
+ status: "retained",
3476
+ reason: "workspace_changed"
3477
+ };
3478
+ if (record.sourceWorkingDirectory && !await sourceHasCommit(record)) return {
3479
+ status: "retained",
3480
+ reason: "source_commit_unavailable"
3481
+ };
3482
+ return (await retirePristineWorkspace(record, path)).status === "released" ? { status: "released" } : {
3483
+ status: "retained",
3484
+ reason: "workspace_changed"
3485
+ };
3486
+ });
3487
+ } finally {
3488
+ if (input.use) await releaseLock(input.use.lock);
3489
+ }
3490
+ }
3491
+ async function assertExecutionContextWorkspaceUse(input) {
3492
+ if (!executionContextAssignmentSchema.shape.id.safeParse(input.contextId).success) throw failure("workspace_identity_mismatch");
3493
+ const record = await readManifest(join(await canonicalDirectory(input.ledgerRootPath), "execution-context-workspace-records", `${input.contextId}.json`));
3494
+ if (record?.status !== "in_use" || record.identity.id !== input.contextId || record.activeDispatchId !== input.dispatchId || record.activeAttemptId !== input.attemptId || !record.containerRuntime) throw failure("workspace_execution_authority_mismatch");
3495
+ }
3496
+ async function runExecutionContextWorkspaceProjectShell(input) {
3497
+ const root = await canonicalDirectory(input.ledgerRootPath);
3498
+ return await withWorkspaceLock(root, input.contextId, async () => {
3499
+ await assertExecutionContextWorkspaceUse({
3500
+ ledgerRootPath: root,
3501
+ contextId: input.contextId,
3502
+ dispatchId: input.dispatchId,
3503
+ attemptId: input.attemptId
3504
+ });
3505
+ const record = await readManifest(join(root, "execution-context-workspace-records", `${input.contextId}.json`));
3506
+ if (record?.boundaryRoot !== input.boundaryRoot || record.workingDirectory !== input.workspacePath || record.containerRuntime?.binary !== input.runtime.binary || record.containerRuntime.engineIdentity !== input.runtime.engineIdentity || record.containerRuntime.kind !== input.runtime.kind) throw failure("workspace_execution_authority_mismatch");
3507
+ return await runClaudeProjectContainerCommand({
3508
+ command: input.command,
3509
+ contextId: input.contextId,
3510
+ runtime: input.runtime,
3511
+ boundaryRoot: input.boundaryRoot,
3512
+ workspacePath: input.workspacePath
3513
+ });
3514
+ });
3515
+ }
3516
+ async function retirePristineWorkspace(record, recordPath) {
3517
+ if (!record.pristineFingerprint || await fingerprintDirectory(record.boundaryRoot) !== record.pristineFingerprint) throw failure("workspace_release_incomplete");
3518
+ const retiring = {
3519
+ ...record,
3520
+ status: "retiring",
3521
+ retirement: {
3522
+ path: `${recordPath}.retired-${randomUUID()}`,
3523
+ pristineFingerprint: record.pristineFingerprint
3524
+ }
3525
+ };
3526
+ await writeManifest(recordPath, retiring, "r+");
3527
+ return await finishWorkspaceRetirement(retiring, recordPath);
3528
+ }
3529
+ async function finishWorkspaceRetirement(record, recordPath) {
3530
+ const retirement = record.retirement;
3531
+ if (!retirement) throw failure("workspace_release_incomplete");
3532
+ const live = await inspectPath(record.boundaryRoot);
3533
+ const retired = await inspectPath(retirement.path);
3534
+ if (live && retired || !(live || retired)) throw failure("workspace_release_incomplete");
3535
+ if (live) await moveWorkspace(record.boundaryRoot, retirement.path);
3536
+ if (await fingerprintDirectory(retirement.path) !== retirement.pristineFingerprint) {
3537
+ if (await inspectPath(record.boundaryRoot)) throw failure("workspace_release_incomplete");
3538
+ await moveWorkspace(retirement.path, record.boundaryRoot);
3539
+ const retained = {
3540
+ ...record,
3541
+ retirement: void 0,
3542
+ status: "completed"
3543
+ };
3544
+ await writeManifest(recordPath, retained, "r+");
3545
+ return retained;
3546
+ }
3547
+ const released = {
3548
+ ...record,
3549
+ status: "released"
3550
+ };
3551
+ await writeManifest(recordPath, released, "r+");
3552
+ return await removePristineRetirement(released, recordPath);
3553
+ }
3554
+ async function removePristineRetirement(record, recordPath) {
3555
+ const retirement = record.retirement;
3556
+ if (!retirement) return record;
3557
+ if (await inspectPath(retirement.path)) {
3558
+ if (await fingerprintDirectory(retirement.path) !== retirement.pristineFingerprint) return record;
3559
+ await rm(retirement.path, { recursive: true });
3560
+ }
3561
+ const removed = {
3562
+ ...record,
3563
+ retirement: void 0
3564
+ };
3565
+ await writeManifest(recordPath, removed, "r+");
3566
+ return removed;
3567
+ }
3568
+ async function restoreReleasedWorkspace(record, recordPath) {
3569
+ if (record.sourceWorkingDirectory && !await sourceHasCommit(record)) throw failure("workspace_base_commit_unavailable");
3570
+ if (await inspectPath(record.boundaryRoot)) throw failure("workspace_already_exists");
3571
+ const restoring = {
3572
+ ...record,
3573
+ status: "restoring",
3574
+ processSupervisionId: randomUUID()
3575
+ };
3576
+ await writeManifest(recordPath, restoring, "r+");
3577
+ await finishWorkspacePreparation(restoring, recordPath, true);
3578
+ }
3579
+ async function sourceHasCommit(record) {
3580
+ if (!(record.sourceWorkingDirectory && record.baseCommit)) return false;
3581
+ try {
3582
+ await git(record.sourceWorkingDirectory, [
3583
+ "cat-file",
3584
+ "-e",
3585
+ `${record.baseCommit}^{commit}`
3586
+ ]);
3587
+ return true;
3588
+ } catch {
3589
+ return false;
3590
+ }
3591
+ }
3592
+ async function isUnchangedCheckout(record) {
3593
+ return await git(record.workingDirectory, ["rev-parse", "HEAD"]) === record.baseCommit && await git(record.workingDirectory, [
3594
+ "status",
3595
+ "--porcelain",
3596
+ "--untracked-files=all",
3597
+ "--ignored"
3598
+ ]) === "";
3599
+ }
3600
+ async function finishMissingCheckoutFiles(record) {
3601
+ if (await git(record.workingDirectory, ["rev-parse", "HEAD"]) !== record.baseCommit) throw failure("workspace_creation_incomplete");
3602
+ if ((await git(record.workingDirectory, [
3603
+ "ls-files",
3604
+ "-v",
3605
+ "-z"
3606
+ ])).split("\0").some((entry) => entry && !entry.startsWith("H "))) throw failure("workspace_creation_incomplete");
3607
+ const status = await git(record.workingDirectory, [
3608
+ "status",
3609
+ "--porcelain",
3610
+ "-z",
3611
+ "--untracked-files=all",
3612
+ "--ignored"
3613
+ ]);
3614
+ if (!status) return;
3615
+ const changes = status.split("\0").filter(Boolean);
3616
+ if (changes.some((entry) => !entry.startsWith(" D "))) throw failure("workspace_creation_incomplete");
3617
+ const paths = changes.map((entry) => entry.slice(3));
3618
+ for (let offset = 0; offset < paths.length; offset += 100) await git(record.workingDirectory, [
3619
+ "checkout-index",
3620
+ "--",
3621
+ ...paths.slice(offset, offset + 100)
3622
+ ], record.processSupervisionId);
3623
+ }
3624
+ async function fingerprintDirectory(root) {
3625
+ const hash = createHash("sha256");
3626
+ const visit = async (directory) => {
3627
+ for (const name of (await readdir(directory)).sort()) {
3628
+ const path = join(directory, name);
3629
+ const info = await lstat(path);
3630
+ hash.update(JSON.stringify([
3631
+ relative(root, path),
3632
+ info.mode,
3633
+ info.nlink
3634
+ ]));
3635
+ if (info.isSymbolicLink()) hash.update(JSON.stringify(await readlink(path)));
3636
+ else if (info.isDirectory()) await visit(path);
3637
+ else if (info.isFile() && info.nlink === 1) {
3638
+ hash.update(String(info.size));
3639
+ hash.update(await fingerprintFile(path));
3640
+ } else throw failure("workspace_git_metadata_changed");
3641
+ }
3642
+ };
3643
+ await visit(root);
3644
+ return hash.digest("hex");
3645
+ }
3646
+ async function fingerprintFile(path) {
3647
+ const hash = createHash("sha256");
3648
+ const file = await open(path, "r");
3649
+ try {
3650
+ const buffer = Buffer.alloc(64 * 1024);
3651
+ for (;;) {
3652
+ const { bytesRead } = await file.read(buffer);
3653
+ if (!bytesRead) break;
3654
+ hash.update(buffer.subarray(0, bytesRead));
3655
+ }
3656
+ } finally {
3657
+ await file.close();
3658
+ }
3659
+ return hash.digest("hex");
3660
+ }
3661
+ async function withWorkspaceLock(root, contextId, run) {
3662
+ if (!executionContextAssignmentSchema.shape.id.safeParse(contextId).success) throw failure("invalid_workspace_context");
3663
+ return await runWithHeldLock({
3664
+ lock: await acquireLock({
3665
+ openMeldProfileId: "execution-context-workspaces",
3666
+ key: contextId,
3667
+ pathResolution: { env: { OPENMELD_HOME: root } }
3668
+ }),
3669
+ run
3670
+ });
3671
+ }
3672
+ async function verifyRetainedWorkspace(manifest) {
3673
+ await canonicalDirectory(manifest.boundaryRoot);
3674
+ await canonicalDirectory(manifest.workingDirectory);
3675
+ if (manifest.sourceWorkingDirectory) await verifyOwnedRepository(manifest);
3676
+ return workspaceResult(manifest);
3677
+ }
3678
+ async function acquireWorkspaceExecutionLock(root, contextId) {
3679
+ return await acquireLock({
3680
+ openMeldProfileId: "execution-context-workspaces",
3681
+ key: `${contextId}-execution`,
3682
+ pathResolution: { env: { OPENMELD_HOME: root } }
3683
+ });
3684
+ }
3685
+ function workspaceResult(manifest) {
3686
+ return {
3687
+ workingDirectory: manifest.workingDirectory,
3688
+ boundaryRoot: manifest.boundaryRoot,
3689
+ ...manifest.sourceWorkingDirectory ? { sourceWorkingDirectory: manifest.sourceWorkingDirectory } : {},
3690
+ ...manifest.baseCommit ? { baseCommit: manifest.baseCommit } : {}
3691
+ };
3692
+ }
3693
+ function assertSourceAllowed(source, policy) {
3694
+ if (policy.mode === "only_selected_folders" && !policy.folders.some((folder) => within(source, folder))) throw failure("workspace_outside_computer_policy");
3695
+ if (policy.mode === "block_selected_folders" && policy.folders.some((folder) => within(source, folder) || within(folder, source))) throw failure("workspace_overlaps_blocked_folder");
3696
+ }
3697
+ async function resolveSourceCommit(source) {
3698
+ if (!await inspectPath(join(source, ".git"))) throw failure("project_repository_required");
3699
+ if (await realpath(await git(source, ["rev-parse", "--show-toplevel"])) !== source) throw failure("project_repository_root_required");
3700
+ const commit = await git(source, [
3701
+ "rev-parse",
3702
+ "--verify",
3703
+ "HEAD^{commit}"
3704
+ ]).catch((cause) => {
3705
+ throw new Error("execution_context.project_commit_required", { cause });
3706
+ });
3707
+ if (!COMMIT_PATTERN.test(commit)) throw failure("project_commit_required");
3708
+ return commit;
3709
+ }
3710
+ async function verifyOwnedRepository(manifest) {
3711
+ const repository = join(manifest.boundaryRoot, "repository.git");
3712
+ await canonicalDirectory(repository);
3713
+ await assertPrivateMetadata(repository);
3714
+ if (await inspectPath(join(repository, "objects", "info", "alternates"))) throw failure("workspace_git_metadata_changed");
3715
+ const gitFile = join(manifest.workingDirectory, ".git");
3716
+ const gitFileInfo = await inspectPath(gitFile);
3717
+ if (!gitFileInfo?.isFile() || gitFileInfo.size > 4096) throw failure("workspace_git_metadata_changed");
3718
+ const expectedGitDir = join(repository, "worktrees", "worktree");
3719
+ const gitDirLine = (await readFile(gitFile, "utf8")).trim();
3720
+ const gitDir = gitDirLine.startsWith("gitdir: ") ? gitDirLine.slice(8) : null;
3721
+ if (!(gitDir && isAbsolute(gitDir)) || relative(expectedGitDir, gitDir)) throw failure("workspace_git_metadata_changed");
3722
+ if (await realpath(join(expectedGitDir, (await readFile(join(expectedGitDir, "commondir"), "utf8")).trim())) !== repository) throw failure("workspace_git_metadata_changed");
3723
+ if (await git(manifest.boundaryRoot, [
3724
+ `--git-dir=${repository}`,
3725
+ "rev-parse",
3726
+ "--verify",
3727
+ "refs/openmeld/base^{commit}"
3728
+ ]) !== manifest.baseCommit) throw failure("workspace_base_commit_changed");
3729
+ }
3730
+ async function assertPrivateMetadata(path) {
3731
+ for (const entry of await readdir(path, { withFileTypes: true })) {
3732
+ if (entry.isSymbolicLink()) throw failure("workspace_is_symlink");
3733
+ if (entry.isDirectory()) await assertPrivateMetadata(join(path, entry.name));
3734
+ else if ((await lstat(join(path, entry.name))).nlink !== 1) throw failure("workspace_git_metadata_changed");
3735
+ }
3736
+ }
3737
+ async function readManifest(path) {
3738
+ const info = await inspectPath(path);
3739
+ if (!info) return null;
3740
+ if (!info.isFile() || info.size > 32768) throw failure("workspace_record_invalid");
3741
+ let content;
3742
+ try {
3743
+ content = JSON.parse(await readFile(path, "utf8"));
3744
+ } catch {
3745
+ throw failure("workspace_record_invalid");
3746
+ }
3747
+ const parsed = manifestSchema.safeParse(content);
3748
+ if (!parsed.success) throw failure("workspace_record_invalid");
3749
+ const retirement = parsed.data.retirement;
3750
+ const prefix = `${path}.retired-`;
3751
+ if (parsed.data.status === "retiring" && !retirement || retirement && !(retirement.path.startsWith(prefix) && z.uuid().safeParse(retirement.path.slice(prefix.length)).success)) throw failure("workspace_record_invalid");
3752
+ return parsed.data;
3753
+ }
3754
+ async function writeManifest(path, manifest, flags) {
3755
+ const temporaryPath = flags === "wx" ? path : `${path}.${randomUUID()}.tmp`;
3756
+ const file = await open(temporaryPath, "wx", 384);
3757
+ try {
3758
+ await file.writeFile(`${JSON.stringify({
3759
+ ...manifest,
3760
+ version: 2
3761
+ })}\n`, "utf8");
3762
+ await file.sync();
3763
+ } finally {
3764
+ await file.close();
3765
+ }
3766
+ if (flags !== "wx") await rename(temporaryPath, path);
3767
+ await syncDirectory(dirname(path));
3768
+ }
3769
+ async function moveWorkspace(from, to) {
3770
+ await rename(from, to);
3771
+ await syncDirectory(dirname(from));
3772
+ await syncDirectory(dirname(to));
3773
+ }
3774
+ async function inspectPath(path) {
3775
+ const info = await lstat(path).catch((error) => {
3776
+ if (error.code === "ENOENT") return null;
3777
+ throw error;
3778
+ });
3779
+ if (info?.isSymbolicLink()) throw failure("workspace_is_symlink");
3780
+ return info;
3781
+ }
3782
+ async function canonicalDirectory(path) {
3783
+ if (!(await inspectPath(path))?.isDirectory()) throw failure("workspace_directory_unavailable");
3784
+ return await realpath(path);
3785
+ }
3786
+ async function ensureDirectory(path, recursive = false) {
3787
+ await inspectPath(path);
3788
+ await mkdir(path, {
3789
+ recursive,
3790
+ mode: 448
3791
+ }).catch((error) => {
3792
+ if (error.code !== "EEXIST") throw error;
3793
+ });
3794
+ return await canonicalDirectory(path);
3795
+ }
3796
+ function within(child, parent) {
3797
+ const path = relative(resolve(parent), child);
3798
+ return path === "" || path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute(path);
3799
+ }
3800
+ const GIT_SETTINGS = {
3801
+ "core.hooksPath": "/dev/null",
3802
+ "core.attributesFile": "/dev/null",
3803
+ "core.fsmonitor": "false",
3804
+ "credential.helper": "",
3805
+ "protocol.allow": "never",
3806
+ "protocol.file.allow": "always",
3807
+ "fetch.recurseSubmodules": "false",
3808
+ "submodule.recurse": "false",
3809
+ "uploadpack.packObjectsHook": "",
3810
+ "gc.auto": "0",
3811
+ "maintenance.auto": "false"
3812
+ };
3813
+ async function git(cwd, args, processSupervisionId) {
3814
+ const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_")));
3815
+ Object.assign(env, {
3816
+ ...processSupervisionId ? { OPENMELD_PROCESS_SUPERVISION_ID: processSupervisionId } : {},
3817
+ GIT_CONFIG_NOSYSTEM: "1",
3818
+ GIT_CONFIG_SYSTEM: "/dev/null",
3819
+ GIT_CONFIG_GLOBAL: "/dev/null",
3820
+ GIT_ATTR_NOSYSTEM: "1",
3821
+ GIT_NO_REPLACE_OBJECTS: "1",
3822
+ GIT_NO_LAZY_FETCH: "1",
3823
+ GIT_ALLOW_PROTOCOL: "file",
3824
+ GIT_TERMINAL_PROMPT: "0",
3825
+ GIT_CONFIG_COUNT: String(Object.keys(GIT_SETTINGS).length)
3826
+ });
3827
+ for (const [index, [key, value]] of Object.entries(GIT_SETTINGS).entries()) {
3828
+ env[`GIT_CONFIG_KEY_${index}`] = key;
3829
+ env[`GIT_CONFIG_VALUE_${index}`] = value;
3830
+ }
3831
+ return (await execFileAsync$1("git", args, {
3832
+ cwd,
3833
+ env,
3834
+ encoding: "utf8",
3835
+ timeout: 3e4,
3836
+ maxBuffer: 1024 * 1024
3837
+ })).stdout.trimEnd();
3838
+ }
3839
+ function failure(code) {
3840
+ return /* @__PURE__ */ new Error(`execution_context.${code}`);
3841
+ }
3842
+ //#endregion
3843
+ //#region src/space/action-command.ts
3844
+ const FINAL_SAFE_STATUSES = /* @__PURE__ */ new Set([
3845
+ "blocked",
3846
+ "done",
3847
+ "handoff",
3848
+ "needs_input"
3849
+ ]);
3850
+ const DISPATCH_ACTION_CLI_PLACEHOLDER = "<DISPATCH_ACTION_CLI>";
3851
+ const SPACE_ACTION_REPLY_TIMING_EVENT = "openmeld.space_action.reply_timing";
3852
+ function runSpaceActionReply(input) {
3853
+ const text = resolveReplyMessageText(input);
3854
+ const result = recordDispatchSpaceReply({
3855
+ filePaths: input.filePaths,
3856
+ messagePartCount: input.messageParts.length,
3857
+ mentionTargets: input.mentionTargets,
3858
+ referenceTargets: input.referenceTargets,
3859
+ text,
3860
+ wakeTargets: input.wakeTargets
3861
+ });
3862
+ if (result instanceof Promise) return result.then((record) => {
3863
+ emitActionRecorded(record);
3864
+ });
3865
+ emitActionRecorded(result);
3866
+ }
3867
+ function recordDispatchSpaceReply(input) {
3868
+ const timing = createSpaceActionReplyTiming();
3869
+ timing.emit("command_start", void 0, {
3870
+ messagePartCount: input.messagePartCount ?? 0,
3871
+ mentionTargetCount: input.mentionTargets?.length ?? 0,
3872
+ referenceTargetCount: input.referenceTargets?.length ?? 0,
3873
+ wakeTargetCount: input.wakeTargets?.length ?? 0
3874
+ });
3875
+ const filePaths = input.filePaths ?? [];
3876
+ if (filePaths.length && input.files?.length) throw new DispatchSpaceActionRejectedError("space_action.invalid_input", "Choose uploaded paths or saved file revisions for this reply.");
3877
+ const context = filePaths.length > 0 ? readDispatchSpaceActionContextFromEnv(input.env) : readDispatchSpaceActionContextForReceiptFromEnv(input.env);
3878
+ timing.emit("context_ready", context);
3879
+ assertAllowedAction(context, "post_message");
3880
+ const text = normalizeRequiredText(input.text, "Reply message is required.");
3881
+ const targetIds = resolveMessageEnvelopeTargetIds({
3882
+ context,
3883
+ mentionTargets: input.mentionTargets ?? [],
3884
+ wakeTargets: input.wakeTargets ?? [],
3885
+ referenceTargets: input.referenceTargets ?? []
3886
+ });
3887
+ timing.emit("targets_resolved", context, {
3888
+ activationTargetCount: targetIds.activationTargets.length,
3889
+ messageLength: text.length,
3890
+ mentionTargetCount: targetIds.mentionTargets.length,
3891
+ referenceTargetCount: targetIds.referenceTargets.length
3892
+ });
3893
+ if (filePaths.length === 0) return writeSpaceActionReplyRecord({
3894
+ context,
3895
+ files: input.files ? [...input.files] : [],
3896
+ targetIds,
3897
+ text,
3898
+ timing
3899
+ });
3900
+ return uploadAndRecordSpaceActionReply({
3901
+ context,
3902
+ filePaths,
3903
+ targetIds,
3904
+ text,
3905
+ timing
3906
+ });
3907
+ }
3908
+ function resolveReplyMessageText(input) {
3909
+ const hasInlineMessage = input.messageParts.length > 0;
3910
+ const messageFilePath = input.messageFilePath?.trim();
3911
+ if (hasInlineMessage && messageFilePath) throw new Error("Choose either a reply message or --message-file, not both.");
3912
+ if (!messageFilePath) return normalizeRequiredJoinedText(input.messageParts, "Reply message is required.");
3913
+ return normalizeRequiredText(readFileSync(messageFilePath === "-" ? 0 : messageFilePath, { encoding: "utf8" }), "Reply message is required.");
3914
+ }
3915
+ async function uploadAndRecordSpaceActionReply(input) {
3916
+ const files = await uploadSpaceActionReplyFiles({
3917
+ context: input.context,
3918
+ filePaths: input.filePaths
3919
+ });
3920
+ return writeSpaceActionReplyRecord({
3921
+ ...input,
3922
+ files
3923
+ });
3924
+ }
3925
+ function writeSpaceActionReplyRecord(input) {
3926
+ const record = recordAction({
3927
+ action: {
3928
+ type: "post_message",
3929
+ ...input.files.length > 0 ? { files: [...input.files] } : {},
3930
+ messageEnvelope: {
3931
+ activationTargets: input.targetIds.activationTargets,
3932
+ mentionTargets: input.targetIds.mentionTargets,
3933
+ referenceTargets: input.targetIds.referenceTargets,
3934
+ ...input.context.replyToSignalId ? { replyToSignalId: input.context.replyToSignalId } : {},
3935
+ text: input.text
3936
+ }
3937
+ },
3938
+ command: "reply",
3939
+ context: input.context
3940
+ });
3941
+ input.timing.emit("record_written", input.context, { actionType: record.action.type });
3942
+ input.timing.emit("done", input.context, { actionType: record.action.type });
3943
+ return record;
3944
+ }
3945
+ async function uploadSpaceActionReplyFiles(input) {
3946
+ const prepared = await prepareRequestedSpaceSendFiles({ filePaths: input.filePaths });
3947
+ if (prepared.length === 0) return [];
3948
+ return await uploadPreparedSpaceFiles({
3949
+ files: prepared,
3950
+ requestContext: buildOpenMeldRequestContextFromProfile({ openMeldProfile: await requireOpenMeldProfile({
3951
+ openMeldProfileId: input.context.targetProfileId,
3952
+ persistSelection: false,
3953
+ authAction: "sharing files in a Space reply"
3954
+ }) }),
3955
+ spaceApi: createCliSpaceApi(await resolveBaseUrl()),
3956
+ spaceId: input.context.spaceId
3957
+ });
3958
+ }
3959
+ function runSpaceActionWake(input) {
3960
+ const context = readDispatchSpaceActionContextForReceiptFromEnv();
3961
+ assertAllowedAction(context, "post_message");
3962
+ const text = normalizeRequiredJoinedText(input.messageParts, "Wake handoff message is required.");
3963
+ recordAction({
3964
+ action: {
3965
+ type: "post_message",
3966
+ messageEnvelope: {
3967
+ activationTargets: resolveTargetProfileIds({
3968
+ context,
3969
+ relation: "wake",
3970
+ targets: [input.target]
3971
+ }),
3972
+ mentionTargets: [],
3973
+ referenceTargets: [],
3974
+ ...context.replyToSignalId ? { replyToSignalId: context.replyToSignalId } : {},
3975
+ text
3976
+ }
3977
+ },
3978
+ command: "wake",
3979
+ context
3980
+ });
3981
+ }
3982
+ function runSpaceActionStatus(input) {
3983
+ emitActionRecorded(recordDispatchSpaceStatus({
3984
+ status: input.status,
3985
+ text: normalizeRequiredJoinedText(input.textParts, "Status text is required.")
3986
+ }));
3987
+ }
3988
+ /** Legacy CLI/in-flight compatibility only; not offered to current Agent tool catalogs. */
3989
+ function recordDispatchSpaceStatus(input) {
3990
+ const context = readDispatchSpaceActionContextForReceiptFromEnv();
3991
+ assertAllowedAction(context, "post_status");
3992
+ return recordAction({
3993
+ action: {
3994
+ type: "post_status",
3995
+ status: normalizeStatus(input.status),
3996
+ text: normalizeRequiredText(input.text, "Status text is required.")
3997
+ },
3998
+ command: "status",
3999
+ context
4000
+ });
4001
+ }
4002
+ function runSpaceActionSilent(input) {
4003
+ emitActionRecorded(recordDispatchSpaceSilent(input));
4004
+ }
4005
+ function recordDispatchSpaceSilent(input) {
4006
+ const context = readDispatchSpaceActionContextForReceiptFromEnv(input.env);
4007
+ assertAllowedAction(context, "stay_silent");
4008
+ return recordAction({
4009
+ action: {
4010
+ type: "stay_silent",
4011
+ reason: normalizeRequiredText(input.reason, "A silent action requires --reason.")
4012
+ },
4013
+ command: "silent",
4014
+ context
4015
+ });
4016
+ }
4017
+ function runSpaceActionTargets() {
4018
+ const targetReference = requireLoadedTargets(readDispatchSpaceActionContextFromEnv().sendTargetReference);
4019
+ const wakeTargets = targetReference.projection.filter((target) => target.allowedRelations.wake);
4020
+ const referenceTargets = targetReference.projection.filter((target) => target.allowedRelations.reference);
4021
+ const mentionTargets = targetReference.projection.filter((target) => target.allowedRelations.mention);
4022
+ outLine("Wake targets:");
4023
+ if (wakeTargets.length === 0) outLine("- none");
4024
+ else for (const target of wakeTargets) outLine(`- ${formatTargetLine(target, "wake")}`);
4025
+ outLine("");
4026
+ outLine("Mention targets:");
4027
+ if (mentionTargets.length === 0) outLine("- none");
4028
+ else for (const target of mentionTargets) outLine(`- ${formatTargetLine(target, "mention")}`);
4029
+ outLine("");
4030
+ outLine("Reference targets:");
4031
+ if (referenceTargets.length === 0) outLine("- none");
4032
+ else for (const target of referenceTargets) outLine(`- ${formatTargetLine(target, "reference")}`);
4033
+ }
4034
+ function runSpaceActionHelp() {
4035
+ let context = null;
4036
+ try {
4037
+ context = readDispatchSpaceActionContextFromEnv();
4038
+ } catch {
4039
+ context = null;
4040
+ }
4041
+ outLine("OpenMeld Space Action commands:");
4042
+ outLine(formatSpaceActionHelpExample("Reply", "reply \"message\"", context));
4043
+ outLine(formatSpaceActionHelpExample("Handoff and wake another agent", "wake <agent-profile-id> \"summary and request\"", context));
4044
+ outLine(formatSpaceActionHelpExample("Reply and also wake another agent", "reply --wake <agent-profile-id> \"message\"", context));
4045
+ outLine(formatSpaceActionHelpExample("Reply and reference another agent", "reply --reference <agent-profile-id> \"message\"", context));
4046
+ outLine(formatSpaceActionHelpExample("Reply and mention a person", "reply --mention <human-profile-id> \"message\"", context));
4047
+ outLine(formatSpaceActionHelpExample("Stay silent", "silent --reason \"No public reply is needed.\"", context));
4048
+ outLine(formatSpaceActionHelpExample("Current targets", "targets", context));
4049
+ outLine(formatSpaceActionHelpExample("Help", "help", context));
4050
+ outLine("");
4051
+ outLine("Run exactly one final action for the current Wake. OpenMeld posts the accepted action to the Space.");
4052
+ if (!context) {
4053
+ outLine("");
4054
+ outLine(`No active dispatch context was found. ${DISPATCH_ACTION_CLI_PLACEHOLDER} is a placeholder for the exact Space Action command prefix printed in an OpenMeld Space Wake dispatch prompt.`);
4055
+ outLine("Write actions and targets require an active OpenMeld Space Wake dispatch. Do not guess the command prefix or rewrite it to npx.");
4056
+ return;
4057
+ }
4058
+ outLine("");
4059
+ outLine(`Active dispatch: ${context.dispatchId}`);
4060
+ outLine(`Current target profile: ${context.targetProfileId}`);
4061
+ }
4062
+ function formatSpaceActionHelpExample(label, action, context) {
4063
+ return `- ${label}: ${formatSpaceActionHelpCommand(action, context)}`;
4064
+ }
4065
+ function formatSpaceActionHelpCommand(action, context) {
4066
+ if (!context) return `${DISPATCH_ACTION_CLI_PLACEHOLDER} space action ${action}`;
4067
+ return formatOpenMeldCliCommand(`openmeld space action ${action}`);
4068
+ }
4069
+ function recordAction(input) {
4070
+ return writeDispatchSpaceActionRecord(input);
4071
+ }
4072
+ function emitActionRecorded(record) {
4073
+ outLine(`Action recorded: OpenMeld saved this unpublished Space action proposal (${record.action.type}) for the current Wake.`);
4074
+ }
4075
+ function createSpaceActionReplyTiming() {
4076
+ const startedAt = performance.now();
4077
+ let previousAt = startedAt;
4078
+ const commandStartProcessUptimeMs = Math.round(startedAt);
4079
+ return { emit: (phase, context, fields = {}) => {
4080
+ const now = performance.now();
4081
+ const elapsedMs = Math.max(0, Math.round(now - startedAt));
4082
+ const durationMs = Math.max(0, Math.round(now - previousAt));
4083
+ previousAt = now;
4084
+ process.stderr.write(`[${SPACE_ACTION_REPLY_TIMING_EVENT}] ${JSON.stringify({
4085
+ event: SPACE_ACTION_REPLY_TIMING_EVENT,
4086
+ phase,
4087
+ elapsedMs,
4088
+ durationMs,
4089
+ commandStartProcessUptimeMs,
4090
+ attemptId: context?.attemptId ?? null,
4091
+ dispatchId: context?.dispatchId ?? null,
4092
+ spaceId: context?.spaceId ?? null,
4093
+ targetProfileId: context?.targetProfileId ?? null,
4094
+ taskId: context?.taskId ?? null,
4095
+ ...fields
4096
+ })}\n`);
4097
+ } };
4098
+ }
4099
+ function resolveMessageEnvelopeTargetIds(input) {
4100
+ const targets = {
4101
+ activationTargets: resolveTargetProfileIds({
4102
+ context: input.context,
4103
+ relation: "wake",
4104
+ targets: input.wakeTargets
4105
+ }),
4106
+ mentionTargets: resolveTargetProfileIds({
4107
+ context: input.context,
4108
+ relation: "mention",
4109
+ targets: input.mentionTargets
4110
+ }),
4111
+ referenceTargets: resolveTargetProfileIds({
4112
+ context: input.context,
4113
+ relation: "reference",
4114
+ targets: input.referenceTargets
4115
+ })
4116
+ };
4117
+ assertDistinctMessageEnvelopeTargets(targets);
4118
+ return targets;
4119
+ }
4120
+ function assertDistinctMessageEnvelopeTargets(input) {
4121
+ const seen = /* @__PURE__ */ new Map();
4122
+ const relationTargets = [
4123
+ ["wake", input.activationTargets],
4124
+ ["reference", input.referenceTargets],
4125
+ ["mention", input.mentionTargets]
4126
+ ];
4127
+ for (const [relation, profileIds] of relationTargets) for (const profileId of profileIds) {
4128
+ const existingRelation = seen.get(profileId);
4129
+ if (!existingRelation) {
4130
+ seen.set(profileId, relation);
4131
+ continue;
4132
+ }
4133
+ if (existingRelation === relation) throw new DispatchSpaceActionRejectedError("space_action.invalid_input", `The same target (${profileId}) was listed more than once as ${formatRelation(relation)}. Choose it once, or send separate messages.`);
4134
+ throw new DispatchSpaceActionRejectedError("space_action.invalid_input", `The same target (${profileId}) cannot be both ${formatRelation(existingRelation)} and ${formatRelation(relation)} in one Space Action. Choose one relationship, or send separate messages.`);
4135
+ }
4136
+ }
4137
+ function assertAllowedAction(context, actionType) {
4138
+ const allowedActions = context.spaceContractSnapshot?.allowedActions ?? null;
4139
+ if (allowedActions && !allowedActions.includes(actionType)) throw new DispatchSpaceActionRejectedError("space_action.not_allowed", `This Space does not allow ${actionType}. Do not retry it through another tool or transport.`);
4140
+ }
4141
+ function normalizeStatus(value) {
4142
+ const normalized = value.trim().toLowerCase();
4143
+ if (normalized === "working") throw new Error("`working` would close the current Wake. Non-final progress updates are not supported by OpenMeld Space Action yet.");
4144
+ if (normalized === "blocked" || normalized === "done" || normalized === "handoff" || normalized === "needs_input") return normalized;
4145
+ if (!FINAL_SAFE_STATUSES.has(normalized)) throw new Error("Status must be one of: done, blocked, needs_input, handoff.");
4146
+ return normalized;
4147
+ }
4148
+ function resolveTargetProfileIds(input) {
4149
+ return [...new Set(input.targets)].map((target) => resolveTargetProfileId({
4150
+ context: input.context,
4151
+ relation: input.relation,
4152
+ target
4153
+ }));
4154
+ }
4155
+ function resolveTargetProfileId(input) {
4156
+ const targetReference = requireLoadedTargets(input.context.sendTargetReference);
4157
+ const query = normalizeRequiredText(input.target, "Target is required.");
4158
+ const selected = targetReference.projection.find((target) => target.profileId === query);
4159
+ if (!selected) throw new DispatchSpaceActionRejectedError("space_action.invalid_input", `No current Space target has Profile ID "${query}". Use a full Profile ID from this Wake's current send target reference, or omit the target for a plain reply.`);
4160
+ if (!selected.allowedRelations[input.relation]) throw new DispatchSpaceActionRejectedError("space_action.not_allowed", `${formatRelation(input.relation)} is not allowed for ${selected.primaryMentionLabel}. Do not bypass this restriction through another transport.`);
4161
+ return selected.profileId;
4162
+ }
4163
+ function requireLoadedTargets(targetReference) {
4164
+ if (targetReference.status === "loaded") return targetReference;
4165
+ throw new DispatchSpaceActionRejectedError("space_action.targets_unavailable", `Current Space targets are not available for this dispatch: ${targetReference.errorMessage}. Do not guess recipients. A plain reply needs no recipients.`);
4166
+ }
4167
+ function formatTargetLine(target, relation) {
4168
+ const relationLabel = formatRelation(relation);
4169
+ return `${target.primaryMentionLabel} · ${target.profileKind} · ${relationLabel} · ${target.profileId}`;
4170
+ }
4171
+ function formatRelation(relation) {
4172
+ switch (relation) {
4173
+ case "wake": return "Wake";
4174
+ case "reference": return "Reference";
4175
+ default: return relation;
4176
+ }
4177
+ }
4178
+ function normalizeRequiredJoinedText(parts, errorMessage) {
4179
+ return normalizeRequiredText(parts.join(" "), errorMessage);
4180
+ }
4181
+ function normalizeRequiredText(value, errorMessage) {
4182
+ const normalized = String(value ?? "").trim();
4183
+ if (normalized.length === 0) throw new DispatchSpaceActionRejectedError("space_action.invalid_input", errorMessage);
4184
+ return normalized;
4185
+ }
4186
+ //#endregion
4187
+ //#region src/space/dispatch-file-read.ts
4188
+ const execFileAsync = promisify(execFile);
4189
+ /** Keep file access outside the controller sandbox, under the existing CLI auth contract. */
4190
+ async function readDispatchSpaceFile(input) {
4191
+ const env = input.env ?? process.env;
4192
+ if (env["OPENMELD_DISPATCH_RUNTIME_MODE"] !== "dispatch-owned-runtime") throw new Error("Space file tools require an active OpenMeld dispatch runtime.");
4193
+ const context = readDispatchSpaceActionContextFromEnv(env);
4194
+ const command = resolveDispatchSpaceActionMcpServer(env);
4195
+ if (!command) throw new Error("No active OpenMeld dispatch file reader was found.");
4196
+ const fileId = spaceFileEntryIdSchema.parse(input.fileId);
4197
+ const revision = spaceFileRevisionNumberSchema.optional().parse(input.revision);
4198
+ const args = [
4199
+ "space",
4200
+ "files",
4201
+ "read",
4202
+ "--profile",
4203
+ context.targetProfileId,
4204
+ "--json",
4205
+ "--view",
4206
+ "agent",
4207
+ ...revision === void 0 ? [] : ["--revision", String(revision)],
4208
+ "--",
4209
+ context.spaceId,
4210
+ fileId
4211
+ ];
4212
+ const { stdout } = await execFileAsync(command.commandPath, args, {
4213
+ env,
4214
+ encoding: "utf8",
4215
+ maxBuffer: 8 * 1024 * 1024,
4216
+ timeout: 3e4
4217
+ }).catch((error) => {
4218
+ if (error && typeof error === "object" && "stdout" in error && typeof error.stdout === "string") {
4219
+ let value;
4220
+ try {
4221
+ value = JSON.parse(error.stdout);
4222
+ } catch {}
4223
+ const parsed = cliJsonErrorEnvelopeSchema.safeParse(value);
4224
+ if (parsed.success) throw new Error(JSON.stringify(parsed.data), { cause: error });
4225
+ }
4226
+ throw error;
4227
+ });
4228
+ const result = readSpaceFileTextResponseSchema.parse(JSON.parse(stdout));
4229
+ if (result.file.spaceId !== context.spaceId || result.file.id !== fileId || revision !== void 0 && result.revision !== revision) throw new Error("The Space file response does not match the requested file revision.");
4230
+ return result;
4231
+ }
4232
+ //#endregion
4233
+ //#region src/space/dispatch-history-read.ts
4234
+ /** Read the current Wake's bounded Space history through the existing member API. */
4235
+ async function readDispatchSpaceHistory(env = process.env) {
4236
+ if (env["OPENMELD_DISPATCH_RUNTIME_MODE"] !== "dispatch-owned-runtime") throw new Error("Space history tools require an active OpenMeld dispatch runtime.");
4237
+ const context = readDispatchSpaceActionContextFromEnv(env);
4238
+ const profile = await requireOpenMeldProfile({
4239
+ openMeldProfileId: context.targetProfileId,
4240
+ persistSelection: false,
4241
+ authAction: "reading the current Wake's Space history"
4242
+ });
4243
+ if (profile.openMeldProfileId !== context.targetProfileId || profile.profileKind !== "agent") throw new Error("The Space history reader does not match the current Agent.");
4244
+ const result = await createCliSpaceApi(await resolveBaseUrl()).listSignals({
4245
+ spaceId: context.spaceId,
4246
+ requestContext: buildOpenMeldRequestContextFromProfile({ openMeldProfile: profile }),
4247
+ query: {
4248
+ aroundSignalId: context.sourceEventId,
4249
+ beforeCount: 20,
4250
+ afterCount: 0,
4251
+ kinds: ["text"]
4252
+ }
4253
+ });
4254
+ const current = readDispatchSpaceActionContextFromEnv(env);
4255
+ if (current.contextId !== context.contextId || current.nonce !== context.nonce || current.spaceId !== context.spaceId || current.sourceEventId !== context.sourceEventId || current.targetProfileId !== context.targetProfileId) throw new Error("The dispatch context changed during the Space history read.");
4256
+ const output = dispatchSpaceHistoryResultSchema.parse({
4257
+ spaceId: context.spaceId,
4258
+ sourceSignalId: context.sourceEventId,
4259
+ beforeCount: 20,
4260
+ afterCount: 0,
4261
+ signals: result.signals,
4262
+ nextCursor: result.nextCursor
4263
+ });
4264
+ const signals = output.signals.map((signal) => signalTextEnvelopeSchema.parse(signal));
4265
+ if (signals.some((signal) => signal.spaceId !== context.spaceId)) throw new Error("The Space history response does not match the current Space.");
4266
+ return {
4267
+ ...output,
4268
+ signals
4269
+ };
4270
+ }
4271
+ //#endregion
4272
+ //#region src/space/dispatch-read-result.ts
4273
+ const PAGE_BYTES = 8 * 1024;
4274
+ const SNAPSHOT_BYTES = 32 * 1024 * 1024;
4275
+ const SNAPSHOT_COUNT = 4;
4276
+ var DispatchReadResults = class {
4277
+ #snapshots = /* @__PURE__ */ new Map();
4278
+ #bytes = 0;
4279
+ wrap(result) {
4280
+ if (result.isError) return result;
4281
+ const value = result.structuredContent ?? JSON.parse(result.content.map((item) => item.text).join("\n"));
4282
+ const complete = dispatchSpaceReadResultSchema.parse({ result: value });
4283
+ if (Buffer.byteLength(JSON.stringify(complete)) <= PAGE_BYTES) return this.#result(complete);
4284
+ const bytes = Buffer.from(JSON.stringify(value));
4285
+ if (bytes.length > SNAPSHOT_BYTES) throw new Error("The read exceeds this Wake's in-memory result budget. Request a smaller source; no local file was created.");
4286
+ while (this.#snapshots.size >= SNAPSHOT_COUNT || this.#bytes + bytes.length > SNAPSHOT_BYTES) {
4287
+ const oldest = this.#snapshots.keys().next().value;
4288
+ if (oldest === void 0) break;
4289
+ this.#bytes -= this.#snapshots.get(oldest)?.bytes.length ?? 0;
4290
+ this.#snapshots.delete(oldest);
4291
+ }
4292
+ const resultId = randomUUID();
4293
+ this.#snapshots.set(resultId, {
4294
+ bytes,
4295
+ offsets: /* @__PURE__ */ new Set([0])
4296
+ });
4297
+ this.#bytes += bytes.length;
4298
+ return this.read(resultId, 0);
4299
+ }
4300
+ read(resultId, offset) {
4301
+ const snapshot = this.#snapshots.get(resultId);
4302
+ if (!snapshot?.offsets.has(offset)) throw new Error("This result or offset is unavailable in the current tool invocation. Use a returned nextOffset, or read the source again; do not open a local file.");
4303
+ const { bytes } = snapshot;
4304
+ let end = Math.min(offset + PAGE_BYTES, bytes.length);
4305
+ while (true) {
4306
+ while (end < bytes.length && isUtf8Continuation(bytes[end])) end -= 1;
4307
+ const nextOffset = end === bytes.length ? null : end;
4308
+ const value = dispatchSpaceReadResultSchema.parse({ page: {
4309
+ resultId,
4310
+ offset,
4311
+ nextOffset,
4312
+ totalBytes: bytes.length,
4313
+ text: bytes.subarray(offset, end).toString("utf8")
4314
+ } });
4315
+ if (Buffer.byteLength(JSON.stringify(value)) <= PAGE_BYTES) {
4316
+ if (nextOffset !== null) snapshot.offsets.add(nextOffset);
4317
+ return this.#result(value);
4318
+ }
4319
+ end = offset + Math.floor((end - offset) * .8);
4320
+ }
4321
+ }
4322
+ clear() {
4323
+ this.#snapshots.clear();
4324
+ this.#bytes = 0;
4325
+ }
4326
+ #result(value) {
4327
+ return {
4328
+ structuredContent: value,
4329
+ content: [{
4330
+ type: "text",
4331
+ text: JSON.stringify(value)
4332
+ }]
4333
+ };
4334
+ }
4335
+ };
4336
+ function isUtf8Continuation(byte) {
4337
+ return byte !== void 0 && byte >= 128 && byte < 192;
4338
+ }
4339
+ //#endregion
4340
+ //#region src/space/dispatch-task.ts
4341
+ async function listDispatchSpaceTasks(phase, env = process.env) {
4342
+ return await withDispatchTaskContext(async ({ actionContext, api, requestContext }) => await api.listTasks({
4343
+ spaceId: actionContext.spaceId,
4344
+ requestContext,
4345
+ ...phase ? { phase } : {}
4346
+ }), env);
4347
+ }
4348
+ async function createDispatchSpaceTask(body, env = process.env) {
4349
+ return await withDispatchTaskContext(async ({ actionContext, api, requestContext }) => await api.createTask({
4350
+ spaceId: actionContext.spaceId,
4351
+ requestContext,
4352
+ body: createSpaceTaskBodySchema.parse({
4353
+ ...body,
4354
+ operationId: crypto.randomUUID(),
4355
+ sourceSignalId: actionContext.sourceEventId,
4356
+ assigneeProfileId: body.assigneeProfileId === void 0 ? actionContext.targetProfileId : body.assigneeProfileId
4357
+ })
4358
+ }), env);
4359
+ }
4360
+ async function mutateDispatchSpaceTask(input, env = process.env) {
4361
+ const taskId = spaceTaskIdSchema.parse(input.taskId);
4362
+ const body = mutateSpaceTaskBodySchema.parse({
4363
+ ...input.body,
4364
+ operationId: crypto.randomUUID()
4365
+ });
4366
+ return await withDispatchTaskContext(async ({ actionContext, api, requestContext }) => await api.mutateTask({
4367
+ spaceId: actionContext.spaceId,
4368
+ requestContext,
4369
+ taskId,
4370
+ body
4371
+ }), env);
4372
+ }
4373
+ async function withDispatchTaskContext(operation, env) {
4374
+ if (env["OPENMELD_DISPATCH_RUNTIME_MODE"] !== "dispatch-owned-runtime") throw new Error("Space Task tools require an active OpenMeld dispatch runtime.");
4375
+ const actionContext = readDispatchSpaceActionContextFromEnv(env);
4376
+ const profile = await requireOpenMeldProfile({
4377
+ openMeldProfileId: actionContext.targetProfileId,
4378
+ persistSelection: false,
4379
+ authAction: "working with Tasks in the current OpenMeld Space"
4380
+ });
4381
+ if (profile.openMeldProfileId !== actionContext.targetProfileId || profile.profileKind !== "agent") throw new Error("The Space Task actor does not match the current Agent.");
4382
+ const result = await operation({
4383
+ actionContext,
4384
+ api: createCliSpaceApi(await resolveBaseUrl()),
4385
+ requestContext: buildOpenMeldRequestContextFromProfile({ openMeldProfile: profile })
4386
+ });
4387
+ const current = readDispatchSpaceActionContextFromEnv(env);
4388
+ if (current.contextId !== actionContext.contextId || current.nonce !== actionContext.nonce || current.spaceId !== actionContext.spaceId || current.sourceEventId !== actionContext.sourceEventId || current.targetProfileId !== actionContext.targetProfileId) throw new Error("The dispatch context changed during the Space Task action.");
4389
+ return result;
4390
+ }
4391
+ //#endregion
4392
+ //#region src/space/dispatch-working-copy.ts
4393
+ const run = promisify(execFile);
4394
+ async function runDispatchWorkingCopy(action, resolution, env = process.env) {
4395
+ const context = readDispatchSpaceActionContextFromEnv(env);
4396
+ const command = resolveDispatchSpaceActionMcpServer(env);
4397
+ if (!(command && context.workingCopyId)) throw new Error("This Wake has no prepared working copy.");
4398
+ const { stdout } = await run(command.commandPath, [
4399
+ "space",
4400
+ "files",
4401
+ "working-copy",
4402
+ action,
4403
+ "--profile",
4404
+ context.targetProfileId,
4405
+ "--json",
4406
+ "--view",
4407
+ "agent",
4408
+ ...action === "resolve" ? [
4409
+ "--file-id",
4410
+ resolution?.fileId ?? "",
4411
+ "--revision",
4412
+ String(resolution?.revision ?? 0)
4413
+ ] : [],
4414
+ "--",
4415
+ context.spaceId,
4416
+ context.workingCopyId
4417
+ ], {
4418
+ encoding: "utf8",
4419
+ env,
4420
+ maxBuffer: 1024 * 1024,
4421
+ timeout: 12e4
4422
+ }).catch((error) => {
4423
+ if (error && typeof error === "object" && "stdout" in error && typeof error.stdout === "string") {
4424
+ let value;
4425
+ try {
4426
+ value = JSON.parse(error.stdout);
4427
+ } catch {}
4428
+ const parsed = cliJsonErrorEnvelopeSchema.safeParse(value);
4429
+ if (parsed.success) throw new Error(JSON.stringify(parsed.data), { cause: error });
4430
+ }
4431
+ throw error;
4432
+ });
4433
+ return spaceWorkingCopyResultSchema.parse(JSON.parse(stdout));
4434
+ }
4435
+ //#endregion
4436
+ //#region src/space/action-mcp-server.ts
4437
+ const DISPATCH_SPACE_TOOL_INSTRUCTIONS = "Use read_history for the bounded text history around the current Wake, and read_file for shared text files in the current Space. Use Space Task tools only when a clear deliverable needs durable ownership, progress, review, or later closure; questions and tiny same-turn actions stay in Messages. Task operations are non-final. Then choose exactly one permitted final OpenMeld Space Action: reply for an answer, limitation, error explanation, or request for help; stay_silent only when no public communication is appropriate. Do not create a Task just to acknowledge a message. Parameter validation errors record no action and may be corrected. Use read_receipt to reconcile an unknown outcome before resending. Private assistant output is not posted to the Space.";
4438
+ /** Every carrier uses the same schemas, validation, authority and recorder. */
4439
+ var DispatchSpaceTools = class {
4440
+ tools = [];
4441
+ deliveryOnly;
4442
+ #env;
4443
+ #context;
4444
+ #handlers = /* @__PURE__ */ new Map();
4445
+ #closed = false;
4446
+ #readResults = new DispatchReadResults();
4447
+ constructor(env) {
4448
+ this.#env = Object.freeze({ ...env });
4449
+ this.#context = readDispatchSpaceActionContextForReceiptFromEnv(this.#env);
4450
+ this.deliveryOnly = isDispatchSpaceActionDeliveryOnly(this.#env);
4451
+ }
4452
+ registerTool(name, config, handler) {
4453
+ if (this.deliveryOnly && ![
4454
+ "reply",
4455
+ "stay_silent",
4456
+ "read_receipt"
4457
+ ].includes(name)) return;
4458
+ const inputSchema = config.inputSchema instanceof z.ZodObject ? config.inputSchema : z.strictObject(config.inputSchema);
4459
+ const pagedRead = [
4460
+ "read_history",
4461
+ "read_file",
4462
+ "list_tasks"
4463
+ ].includes(name);
4464
+ this.tools.push({
4465
+ ...config,
4466
+ name,
4467
+ inputSchema,
4468
+ ...pagedRead ? {
4469
+ outputSchema: dispatchSpaceReadResultSchema,
4470
+ description: `${config.description} Small reads return result; large reads return page. Continue with read_result using page.resultId and page.nextOffset; no local file is needed.`
4471
+ } : {}
4472
+ });
4473
+ this.#handlers.set(name, (args) => {
4474
+ const parsed = inputSchema.safeParse(args);
4475
+ if (!parsed.success) return executeSpaceAction(() => {
4476
+ throw new DispatchSpaceActionRejectedError("space_action.invalid_input", parsed.error.message);
4477
+ }, this.#env);
4478
+ return handler(parsed.data);
4479
+ });
4480
+ }
4481
+ async call(name, args) {
4482
+ const context = readDispatchSpaceActionContextForReceiptFromEnv(this.#env);
4483
+ if (this.#closed || context.contextId !== this.#context.contextId || context.nonce !== this.#context.nonce) return executeSpaceAction(() => {
4484
+ throw new DispatchSpaceActionClosedError("space_action.context_mismatch", "This tool invocation no longer owns the active Wake. Do not retry through another transport.");
4485
+ }, this.#env);
4486
+ const handler = this.#handlers.get(name);
4487
+ if (!handler) return executeSpaceAction(() => {
4488
+ throw new DispatchSpaceActionRejectedError("space_action.not_allowed", "This tool is not available in the current invocation. Final communication uses reply or stay_silent, subject to the existing Space policy.");
4489
+ }, this.#env);
4490
+ const pagedRead = [
4491
+ "read_history",
4492
+ "read_file",
4493
+ "list_tasks"
4494
+ ].includes(name);
4495
+ if (pagedRead || name === "read_result") try {
4496
+ readDispatchSpaceActionContextFromEnv(this.#env);
4497
+ const result = await handler(args);
4498
+ const active = readDispatchSpaceActionContextFromEnv(this.#env);
4499
+ if (this.#closed || active.contextId !== this.#context.contextId || active.nonce !== this.#context.nonce) throw new Error("The Wake changed or closed during this read. No result is available.");
4500
+ return pagedRead ? this.#readResults.wrap(result) : result;
4501
+ } catch (error) {
4502
+ return {
4503
+ isError: true,
4504
+ content: [{
4505
+ type: "text",
4506
+ text: error instanceof Error ? error.message : "The Space read failed."
4507
+ }]
4508
+ };
4509
+ }
4510
+ return await handler(args);
4511
+ }
4512
+ registerResultReader() {
4513
+ this.registerTool("read_result", {
4514
+ title: "Continue reading a large Space tool result",
4515
+ description: "Read the next page of a large read_history, read_file, or list_tasks result. Pass the returned resultId and nextOffset exactly; append page.text in order to reconstruct the complete JSON. No local path or shell is needed. The snapshot belongs only to this active Wake and tool connection; after expiry or eviction, read the source again. Does not publish or repeat an operation.",
4516
+ inputSchema: dispatchSpaceReadResultRequestSchema,
4517
+ outputSchema: dispatchSpaceReadResultSchema,
4518
+ annotations: {
4519
+ readOnlyHint: true,
4520
+ destructiveHint: false,
4521
+ idempotentHint: true,
4522
+ openWorldHint: false
4523
+ }
4524
+ }, async ({ resultId, offset }) => this.#readResults.read(resultId, offset));
4525
+ }
4526
+ close() {
4527
+ this.#closed = true;
4528
+ this.#readResults.clear();
4529
+ }
4530
+ };
4531
+ function createDispatchSpaceTools(input = {}) {
4532
+ const env = Object.freeze({ ...input.env ?? process.env });
4533
+ const server = new DispatchSpaceTools(env);
4534
+ const projectShell = readDispatchSpaceActionContextForReceiptFromEnv(env).projectShell;
4535
+ if (projectShell) server.registerTool("project_shell", {
4536
+ title: "Run a command in this task's project worktree",
4537
+ description: "Run one Bash command inside this task's isolated project container. Only its private worktree is mounted. The container has no network, host credentials, or Docker socket. This tool does not submit the final Space action.",
4538
+ inputSchema: dispatchProjectShellInputSchema,
4539
+ outputSchema: dispatchProjectShellResultSchema,
4540
+ annotations: {
4541
+ readOnlyHint: false,
4542
+ destructiveHint: true,
4543
+ idempotentHint: false,
4544
+ openWorldHint: false
4545
+ }
4546
+ }, async ({ command }) => {
4547
+ try {
4548
+ const context = readDispatchSpaceActionContextForReceiptFromEnv(env);
4549
+ if (!context.projectShell || context.projectShell.executionContextId !== projectShell.executionContextId || context.projectShell.boundaryRoot !== projectShell.boundaryRoot || context.projectShell.ledgerRootPath !== projectShell.ledgerRootPath || context.projectShell.workspacePath !== projectShell.workspacePath || context.projectShell.runtime.binary !== projectShell.runtime.binary || context.projectShell.runtime.engineIdentity !== projectShell.runtime.engineIdentity || context.projectShell.runtime.kind !== projectShell.runtime.kind) throw new Error("claude_project.context_mismatch");
4550
+ const result = dispatchProjectShellResultSchema.parse(await runExecutionContextWorkspaceProjectShell({
4551
+ ledgerRootPath: projectShell.ledgerRootPath,
4552
+ contextId: projectShell.executionContextId,
4553
+ dispatchId: context.dispatchId,
4554
+ attemptId: context.attemptId,
4555
+ command,
4556
+ runtime: projectShell.runtime,
4557
+ boundaryRoot: projectShell.boundaryRoot,
4558
+ workspacePath: projectShell.workspacePath
4559
+ }));
4560
+ return {
4561
+ structuredContent: result,
4562
+ content: [{
4563
+ type: "text",
4564
+ text: JSON.stringify(result)
4565
+ }]
4566
+ };
4567
+ } catch (error) {
4568
+ return {
4569
+ isError: true,
4570
+ content: [{
4571
+ type: "text",
4572
+ text: error instanceof Error && error.message.startsWith("claude_project.") ? error.message.split(":")[0] ?? "claude_project.execution_failed" : "claude_project.execution_failed"
4573
+ }]
4574
+ };
4575
+ }
4576
+ });
4577
+ server.registerTool("working_copy", {
4578
+ title: "Save or inspect this handoff's files",
4579
+ description: "Inspect or commit this handoff's files; reconcile retries an unknown save. On conflict, refresh downloads the shared version, then status shows its path and revision. Merge it into the original working file, then resolve with fileId and incoming revision before committing again. No automatic merge or overwrite. Does not deliver or close the Wake. No Space, profile or path overrides.",
4580
+ inputSchema: {
4581
+ action: z.enum([
4582
+ "status",
4583
+ "commit",
4584
+ "reconcile",
4585
+ "refresh",
4586
+ "resolve"
4587
+ ]),
4588
+ fileId: z.string().optional(),
4589
+ revision: z.number().int().positive().optional()
4590
+ }
4591
+ }, async ({ action, fileId, revision }) => {
4592
+ try {
4593
+ return { content: [{
4594
+ type: "text",
4595
+ text: JSON.stringify(await runDispatchWorkingCopy(action, {
4596
+ fileId,
4597
+ revision
4598
+ }, env))
4599
+ }] };
4600
+ } catch (error) {
4601
+ return {
4602
+ isError: true,
4603
+ content: [{
4604
+ type: "text",
4605
+ text: error instanceof Error ? error.message : String(error)
4606
+ }]
4607
+ };
4608
+ }
4609
+ });
4610
+ server.registerTool("read_history", {
4611
+ title: "Read the current Wake's Space history",
4612
+ description: "Read up to 20 text messages before the current Wake, plus its source message. Space, Agent identity and source are fixed by the active dispatch. Use this instead of terminal CLI history. This read does not submit a reply or close the Wake.",
4613
+ inputSchema: dispatchSpaceHistoryRequestSchema,
4614
+ annotations: {
4615
+ readOnlyHint: true,
4616
+ destructiveHint: false,
4617
+ idempotentHint: true,
4618
+ openWorldHint: false
4619
+ }
4620
+ }, async () => {
4621
+ try {
4622
+ const result = await readDispatchSpaceHistory(env);
4623
+ return {
4624
+ structuredContent: result,
4625
+ content: [{
4626
+ type: "text",
4627
+ text: JSON.stringify(result)
4628
+ }]
4629
+ };
4630
+ } catch (error) {
4631
+ return {
4632
+ isError: true,
4633
+ content: [{
4634
+ type: "text",
4635
+ text: error instanceof Error ? error.message : String(error)
4636
+ }]
4637
+ };
4638
+ }
4639
+ });
4640
+ server.registerTool("read_file", {
4641
+ title: "Read a file in the current OpenMeld Space",
4642
+ description: "Read a shared text file as the Agent in the current Wake. Use this for attached CSV, text, Markdown, or JSON files instead of running the CLI in a terminal. Pass the attachment's file ID and revision. This is a context read; it does not submit a reply or close the Wake.",
4643
+ inputSchema: {
4644
+ fileId: spaceFileEntryIdSchema,
4645
+ revision: spaceFileRevisionNumberSchema.optional()
4646
+ },
4647
+ annotations: {
4648
+ readOnlyHint: true,
4649
+ destructiveHint: false,
4650
+ idempotentHint: true,
4651
+ openWorldHint: false
4652
+ }
4653
+ }, async (input) => {
4654
+ try {
4655
+ const result = await readDispatchSpaceFile({
4656
+ ...input,
4657
+ env
4658
+ });
4659
+ return { content: [{
4660
+ type: "text",
4661
+ text: JSON.stringify(result)
4662
+ }] };
4663
+ } catch (error) {
4664
+ return {
4665
+ content: [{
4666
+ type: "text",
4667
+ text: error instanceof Error ? error.message : String(error)
4668
+ }],
4669
+ isError: true
4670
+ };
4671
+ }
4672
+ });
4673
+ server.registerTool("list_tasks", {
4674
+ title: "List Tasks in the current OpenMeld Space",
4675
+ description: "Read durable collaboration Tasks for this Space. Use the returned revision before changing a Task. Task phase is collaboration state, not Agent execution truth.",
4676
+ inputSchema: { phase: z.enum([
4677
+ "to_do",
4678
+ "in_progress",
4679
+ "in_review",
4680
+ "done",
4681
+ "canceled"
4682
+ ]).optional() },
4683
+ annotations: {
4684
+ readOnlyHint: true,
4685
+ destructiveHint: false,
4686
+ idempotentHint: true,
4687
+ openWorldHint: false
4688
+ }
4689
+ }, async ({ phase }) => executeTaskAction(() => listDispatchSpaceTasks(phase, env)));
4690
+ server.registerTool("create_task", {
4691
+ title: "Create a Task from the current Space message",
4692
+ description: "Create a durable Task only for a clear deliverable that needs ownership, progress, review, or later closure. The source message and Space are fixed by this Wake. The Task is assigned to the current Agent by default and remains To do until start_task is called.",
4693
+ inputSchema: {
4694
+ title: z.string().trim().min(1).max(200),
4695
+ description: z.string().trim().min(1).max(8e3).nullable().optional(),
4696
+ completionConditions: z.array(z.string().trim().min(1).max(500)).max(12).optional(),
4697
+ assigneeProfileId: openMeldRuntimeProfileIdSchema.nullable().optional(),
4698
+ reviewerProfileId: openMeldRuntimeProfileIdSchema.nullable().optional()
4699
+ },
4700
+ outputSchema: spaceTaskMutationReceiptSchema,
4701
+ annotations: {
4702
+ readOnlyHint: false,
4703
+ destructiveHint: false,
4704
+ idempotentHint: false,
4705
+ openWorldHint: false
4706
+ }
4707
+ }, async (body) => executeTaskAction(() => createDispatchSpaceTask(body, env)));
4708
+ server.registerTool("start_task", {
4709
+ title: "Mark a Space Task in progress",
4710
+ description: "Record that the current assigned Agent has begun advancing this Task. This changes collaboration state and does not start a separate Agent execution.",
4711
+ inputSchema: {
4712
+ taskId: spaceTaskIdSchema,
4713
+ expectedRevision: z.number().int().min(1)
4714
+ },
4715
+ outputSchema: spaceTaskMutationReceiptSchema,
4716
+ annotations: {
4717
+ readOnlyHint: false,
4718
+ destructiveHint: false,
4719
+ idempotentHint: false,
4720
+ openWorldHint: false
4721
+ }
4722
+ }, async ({ expectedRevision, taskId }) => executeTaskAction(() => mutateDispatchSpaceTask({
4723
+ taskId,
4724
+ body: {
4725
+ action: "mark_in_progress",
4726
+ expectedRevision
4727
+ }
4728
+ }, env)));
4729
+ server.registerTool("submit_task_result", {
4730
+ title: "Submit a result for a Space Task",
4731
+ description: "Submit the concrete result and verification for an in-progress Task. A Task with a reviewer moves to In review; otherwise the stated completion boundary moves it to Done. The Space delivers the review handoff to the reviewer.",
4732
+ inputSchema: {
4733
+ taskId: spaceTaskIdSchema,
4734
+ expectedRevision: z.number().int().min(1),
4735
+ summary: z.string().trim().min(1).max(8e3)
4736
+ },
4737
+ outputSchema: spaceTaskMutationReceiptSchema,
4738
+ annotations: {
4739
+ readOnlyHint: false,
4740
+ destructiveHint: false,
4741
+ idempotentHint: false,
4742
+ openWorldHint: false
4743
+ }
4744
+ }, async ({ expectedRevision, summary, taskId }) => executeTaskAction(() => mutateDispatchSpaceTask({
4745
+ taskId,
4746
+ body: {
4747
+ action: "submit_result",
4748
+ expectedRevision,
4749
+ summary
4750
+ }
4751
+ }, env)));
4752
+ server.registerTool("review_task", {
4753
+ title: "Review a Space Task result",
4754
+ description: "Accept the exact result you read or request specific changes as this Task's reviewer. Pass that result's resultRevision as expectedResultRevision and the Task's revision as expectedRevision. A conflict requires reading the current Task and deciding again. Change requests require feedback. The Space delivers review and rework handoffs. Agent-to-Agent rework stops for a human decision after two automatic rounds.",
4755
+ inputSchema: {
4756
+ taskId: spaceTaskIdSchema,
4757
+ expectedRevision: z.number().int().min(1),
4758
+ expectedResultRevision: z.number().int().min(1),
4759
+ decision: z.enum(["accepted", "changes_requested"]),
4760
+ feedback: z.string().trim().min(1).max(8e3).nullable().optional()
4761
+ },
4762
+ outputSchema: spaceTaskMutationReceiptSchema,
4763
+ annotations: {
4764
+ readOnlyHint: false,
4765
+ destructiveHint: false,
4766
+ idempotentHint: false,
4767
+ openWorldHint: false
4768
+ }
4769
+ }, async ({ decision, expectedRevision, expectedResultRevision, feedback, taskId }) => executeTaskAction(() => mutateDispatchSpaceTask({
4770
+ taskId,
4771
+ body: {
4772
+ action: "review",
4773
+ expectedRevision,
4774
+ expectedResultRevision,
4775
+ decision,
4776
+ ...feedback === void 0 ? {} : { feedback }
4777
+ }
4778
+ }, env)));
4779
+ server.registerTool("cancel_task", {
4780
+ title: "Cancel a Space Task",
4781
+ description: "Cancel a Task when its accepted commitment should no longer be done. Cancellation fences later Task progress; it does not by itself prove that an Agent execution stopped.",
4782
+ inputSchema: {
4783
+ taskId: spaceTaskIdSchema,
4784
+ expectedRevision: z.number().int().min(1),
4785
+ reason: z.string().trim().min(1).max(1e3)
4786
+ },
4787
+ outputSchema: spaceTaskMutationReceiptSchema,
4788
+ annotations: {
4789
+ readOnlyHint: false,
4790
+ destructiveHint: false,
4791
+ idempotentHint: false,
4792
+ openWorldHint: false
4793
+ }
4794
+ }, async ({ expectedRevision, reason, taskId }) => executeTaskAction(() => mutateDispatchSpaceTask({
4795
+ taskId,
4796
+ body: {
4797
+ action: "cancel",
4798
+ expectedRevision,
4799
+ reason
4800
+ }
4801
+ }, env)));
4802
+ server.registerTool("reply", {
4803
+ title: "Reply in the current OpenMeld Space",
4804
+ description: "Record the exact final public message for the active Wake: answers, known limitations, errors, and requests for help all belong here. Use real newlines. No shell, local repository, CLI, or Skill is needed to explain that you cannot complete a task. Omit recipient fields for a plain reply; use full Profile IDs from this Wake's send target reference when addressing recipients. Correct invalid arguments and retry; do not bypass denials or blindly resend an unknown outcome.",
4805
+ inputSchema: {
4806
+ message: z.string().min(1),
4807
+ files: z.array(spaceMessageFileReferenceSchema).max(10).optional(),
4808
+ mentionTargets: z.array(z.string().min(1)).optional(),
4809
+ referenceTargets: z.array(z.string().min(1)).optional(),
4810
+ wakeTargets: z.array(z.string().min(1)).optional()
4811
+ },
4812
+ outputSchema: dispatchSpaceActionToolResultSchema,
4813
+ annotations: {
4814
+ destructiveHint: false,
4815
+ idempotentHint: false,
4816
+ openWorldHint: false,
4817
+ readOnlyHint: false
4818
+ }
4819
+ }, async ({ files, mentionTargets, message, referenceTargets, wakeTargets }) => executeSpaceAction(() => recordDispatchSpaceReply({
4820
+ env,
4821
+ files,
4822
+ mentionTargets,
4823
+ referenceTargets,
4824
+ text: message,
4825
+ wakeTargets
4826
+ }), env));
4827
+ server.registerTool("stay_silent", {
4828
+ title: "Stay silent in the current OpenMeld Space",
4829
+ description: "Record that the active OpenMeld Wake intentionally needs no public reply. Use this only after deciding that silence is the correct final outcome.",
4830
+ inputSchema: { reason: z.string().min(1) },
4831
+ outputSchema: dispatchSpaceActionToolResultSchema,
4832
+ annotations: {
4833
+ destructiveHint: false,
4834
+ idempotentHint: false,
4835
+ openWorldHint: false,
4836
+ readOnlyHint: false
4837
+ }
4838
+ }, async ({ reason }) => executeSpaceAction(() => recordDispatchSpaceSilent({
4839
+ reason,
4840
+ env
4841
+ }), env));
4842
+ server.registerResultReader();
4843
+ server.registerTool("read_receipt", {
4844
+ title: "Check this Wake's recorded final action",
4845
+ description: "Reconcile an uncertain final tool result without posting, replacing, or repeating the action. A saved receipt is a local proposal, not confirmation of publication. A missing record is an observation, not permission to bypass a denial or expiry.",
4846
+ inputSchema: {},
4847
+ annotations: {
4848
+ readOnlyHint: true,
4849
+ destructiveHint: false,
4850
+ idempotentHint: true,
4851
+ openWorldHint: false
4852
+ }
4853
+ }, async () => {
4854
+ const record = readDispatchSpaceActionRecord({ context: readDispatchSpaceActionContextForReceiptFromEnv(env) });
4855
+ if (record.status === "loaded") return await executeSpaceAction(() => record.record, env);
4856
+ if (record.status === "missing") return { content: [{
4857
+ type: "text",
4858
+ text: "No local final action record is present. Correct invalid arguments and use a permitted final tool only while this Wake is still authorized. This read does not reserve a write or override a denial."
4859
+ }] };
4860
+ return executeSpaceAction(() => {
4861
+ throw new Error("The existing final action record cannot be verified. Do not overwrite it or resend through another transport.");
4862
+ }, env);
4863
+ });
4864
+ return server;
4865
+ }
4866
+ function createSpaceActionMcpServer() {
4867
+ const context = readDispatchSpaceActionContextForReceiptFromEnv();
4868
+ const tools = createDispatchSpaceTools();
4869
+ const server = new McpServer({
4870
+ name: "openmeld-dispatch-space-action",
4871
+ version: "1.0.0"
4872
+ }, { instructions: DISPATCH_SPACE_TOOL_INSTRUCTIONS });
4873
+ for (const { name, ...definition } of tools.tools) server.registerTool(name, definition, async (args) => {
4874
+ try {
4875
+ const active = readDispatchSpaceActionContextForReceiptFromEnv();
4876
+ if (active.contextId !== context.contextId || active.nonce !== context.nonce) throw new DispatchSpaceActionClosedError("space_action.context_mismatch", "This MCP server cannot be rebound to another Wake.");
4877
+ return await tools.call(name, args);
4878
+ } catch (error) {
4879
+ return executeSpaceAction(() => {
4880
+ throw error;
4881
+ });
4882
+ }
4883
+ });
4884
+ server.server.onclose = () => tools.close();
4885
+ return server;
4886
+ }
4887
+ async function runSpaceActionMcpServer() {
4888
+ readDispatchSpaceActionContextForReceiptFromEnv();
4889
+ await createSpaceActionMcpServer().connect(new StdioServerTransport());
4890
+ }
4891
+ async function executeSpaceAction(action, env = process.env) {
4892
+ try {
4893
+ const context = readDispatchSpaceActionContextForReceiptFromEnv(env);
4894
+ const record = await action();
4895
+ if (record.contextId !== context.contextId || record.nonce !== context.nonce) throw new DispatchSpaceActionClosedError("space_action.context_mismatch", "The saved action does not match the current dispatch context.");
4896
+ const contextState = Date.now() > context.expiresAtMs ? "expired" : "active";
4897
+ return {
4898
+ structuredContent: dispatchSpaceActionToolResultSchema.parse({ receipt: {
4899
+ status: "proposal_saved_locally",
4900
+ actionType: record.action.type,
4901
+ attemptId: context.attemptId,
4902
+ contextId: context.contextId,
4903
+ dispatchId: context.dispatchId,
4904
+ recordedAtMs: record.createdAtMs,
4905
+ contextState,
4906
+ coordinatorAcceptance: "unconfirmed",
4907
+ publication: "unconfirmed"
4908
+ } }),
4909
+ content: [{
4910
+ type: "text",
4911
+ text: `Local proposal saved (receipt: proposal_saved_locally, action: ${record.action.type}). OpenMeld has recorded this unpublished Space action proposal on this computer. ${contextState === "expired" ? "The local context has expired. This receipt identifies the existing record and does not extend action authority. " : ""}Coordinator acceptance and Space publication are NOT yet confirmed; do not report it as posted.`
4912
+ }]
4913
+ };
4914
+ } catch (error) {
4915
+ if (error instanceof DispatchSpaceActionRejectedError) return {
4916
+ structuredContent: dispatchSpaceActionToolResultSchema.parse({ receipt: {
4917
+ status: "rejected_before_recording",
4918
+ reasonCode: error.reasonCode,
4919
+ coordinatorAcceptance: "unconfirmed",
4920
+ publication: "unconfirmed"
4921
+ } }),
4922
+ content: [{
4923
+ type: "text",
4924
+ text: `Action rejected (receipt: rejected_before_recording, reason: ${error.reasonCode}). This call did not record an action. ${error.message} ${error.reasonCode === "space_action.invalid_input" ? "Correct the indicated arguments and call the same permitted tool again. " : ""}Any earlier records are preserved; Coordinator acceptance and Space publication are unconfirmed.`
4925
+ }],
4926
+ isError: true
4927
+ };
4928
+ if (error instanceof DispatchSpaceActionClosedError) return {
4929
+ structuredContent: dispatchSpaceActionToolResultSchema.parse({ receipt: {
4930
+ status: "rejected_closed",
4931
+ reasonCode: error.reasonCode,
4932
+ coordinatorAcceptance: "unconfirmed",
4933
+ publication: "unconfirmed"
4934
+ } }),
4935
+ content: [{
4936
+ type: "text",
4937
+ text: `Action rejected (receipt: rejected_closed, reason: ${error.reasonCode}). ${error.message} New actions are not permitted in this context. Existing records are preserved; Coordinator acceptance and Space publication are unconfirmed.`
4938
+ }],
4939
+ isError: true
4940
+ };
4941
+ return {
4942
+ structuredContent: dispatchSpaceActionToolResultSchema.parse({ receipt: {
4943
+ status: "outcome_unknown",
4944
+ reasonCode: "space_action.recording_outcome_unknown",
4945
+ coordinatorAcceptance: "unconfirmed",
4946
+ publication: "unconfirmed"
4947
+ } }),
4948
+ content: [{
4949
+ type: "text",
4950
+ text: `Action receipt unavailable (receipt: outcome_unknown). ${error instanceof Error ? error.message : String(error)} Existing records are preserved; Coordinator acceptance and Space publication are unconfirmed.`
4951
+ }],
4952
+ isError: true
4953
+ };
4954
+ }
4955
+ }
4956
+ async function executeTaskAction(action) {
4957
+ try {
4958
+ const result = await action();
4959
+ return {
4960
+ structuredContent: result,
4961
+ content: [{
4962
+ type: "text",
4963
+ text: JSON.stringify(result)
4964
+ }]
4965
+ };
4966
+ } catch (error) {
4967
+ return {
4968
+ isError: true,
4969
+ content: [{
4970
+ type: "text",
4971
+ text: error instanceof Error ? error.message : String(error)
4972
+ }]
4973
+ };
4974
+ }
4975
+ }
4976
+ //#endregion
2786
4977
  //#region src/organization-skills/cache.ts
2787
4978
  const CACHE_MARKER_FILENAME = ".openmeld-organization-skill.json";
2788
4979
  const DIRECTORY_READ_ONLY_MODE = 365;
@@ -2965,47 +5156,6 @@ async function downloadWorkingCopyFile(api, input) {
2965
5156
  };
2966
5157
  }
2967
5158
  //#endregion
2968
- //#region src/local-service/state/ledger-io.ts
2969
- function createLedgerIo() {
2970
- return {
2971
- appendFile: async (filePath, content, encoding) => {
2972
- await mkdir(dirnamePath(filePath), { recursive: true });
2973
- await appendFile(filePath, content, { encoding });
2974
- },
2975
- copyFile: async (fromPath, toPath) => {
2976
- await mkdir(dirnamePath(toPath), { recursive: true });
2977
- await copyFile(fromPath, toPath);
2978
- },
2979
- mkdir: async (dirPath, options) => {
2980
- await mkdir(dirPath, options);
2981
- },
2982
- readFile: async (filePath, encoding) => {
2983
- return await readFile(filePath, encoding);
2984
- },
2985
- rename: async (fromPath, toPath) => {
2986
- await mkdir(dirnamePath(toPath), { recursive: true });
2987
- await rename(fromPath, toPath);
2988
- },
2989
- syncPath: async (fileOrDirectoryPath) => {
2990
- const isWindows = process.platform === "win32";
2991
- if (isWindows && (await stat(fileOrDirectoryPath)).isDirectory()) return;
2992
- const handle = await open(fileOrDirectoryPath, isWindows ? "r+" : "r");
2993
- try {
2994
- await handle.sync();
2995
- } finally {
2996
- await handle.close();
2997
- }
2998
- },
2999
- rm: async (filePath, options) => {
3000
- await rm(filePath, options);
3001
- },
3002
- writeFile: async (filePath, content, encoding) => {
3003
- await mkdir(dirnamePath(filePath), { recursive: true });
3004
- await writeFile(filePath, content, encoding);
3005
- }
3006
- };
3007
- }
3008
- //#endregion
3009
5159
  //#region src/local-service/file-access/space-working-copy.ts
3010
5160
  const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
3011
5161
  const O_NOFOLLOW_ANY = 536870912;
@@ -3508,6 +5658,6 @@ function isSameServiceIdentity(left, right) {
3508
5658
  return left?.deviceId === right.deviceId && left.contractGeneration === right.contractGeneration;
3509
5659
  }
3510
5660
  //#endregion
3511
- export { defaultManagedIntegrationPaths as C, uninstallAgentActivityIntegrations as D, resolveAgentActivityDispatcherCommand as E, AGENT_ACTIVITY_INTEGRATION_OWNER as S, readAgentActivityIntegrationStatus as T, readControllerTaskLifecycleOutboxHealth as _, fetchSpaceUpdates as a, resolveAgentActivityRouteForPath as b, downloadWorkingCopyFile as c, syncLocalAgentActivity as d, discoverLocalAgentSessionProviders as f, enqueueControllerTaskLifecycleEventWhileLocked as g, removeAgentActivityContextCache as h, recordRuntimeReportingSuccess as i, materializeOrganizationSkillRelease as l, readAgentActivityContextForPath as m, recordRuntimeReportingFailure as n, createSpaceWorkingCopies as o, recordOpenMeldCreatedLocalAgentSession as p, recordRuntimeReportingNotApplicable as r, createLedgerIo as s, readRuntimeReportingHealthState as t, startLocalAgentActivitySyncLoop as u, isAgentActivityRouteRegistered as v, installAgentActivityIntegrations as w, unregisterAgentActivityRoute as x, registerAgentActivityRoute as y };
5661
+ export { readControllerTaskLifecycleOutboxHealth as A, uninstallAgentActivityIntegrations as B, startLocalAgentActivitySyncLoop as C, readAgentActivityContextForPath as D, recordOpenMeldCreatedLocalAgentSession as E, AGENT_ACTIVITY_INTEGRATION_OWNER as F, defaultManagedIntegrationPaths as I, installAgentActivityIntegrations as L, registerAgentActivityRoute as M, resolveAgentActivityRouteForPath as N, removeAgentActivityContextCache as O, unregisterAgentActivityRoute as P, readAgentActivityIntegrationStatus as R, prepareClaudeProjectContainer as S, discoverLocalAgentSessionProviders as T, markExecutionContextWorkspaceInUse as _, fetchSpaceUpdates as a, releaseExecutionContextWorkspace as b, materializeOrganizationSkillRelease as c, runSpaceActionHelp as d, runSpaceActionReply as f, runSpaceActionWake as g, runSpaceActionTargets as h, recordRuntimeReportingSuccess as i, isAgentActivityRouteRegistered as j, enqueueControllerTaskLifecycleEventWhileLocked as k, createDispatchSpaceTools as l, runSpaceActionStatus as m, recordRuntimeReportingFailure as n, createSpaceWorkingCopies as o, runSpaceActionSilent as p, recordRuntimeReportingNotApplicable as r, downloadWorkingCopyFile as s, readRuntimeReportingHealthState as t, runSpaceActionMcpServer as u, prepareExecutionContextWorkspace as v, syncLocalAgentActivity as w, createLedgerIo as x, readExecutionContextWorkspace as y, resolveAgentActivityDispatcherCommand as z };
3512
5662
 
3513
- //# sourceMappingURL=runtime-reporting-health-state-BgwfrH7f.js.map
5663
+ //# sourceMappingURL=runtime-reporting-health-state-DA-_vW-n.js.map