@rubytech/create-maxy-code 0.1.382 → 0.1.384

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 (196) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/mcp/dist/index.js +37 -9
  3. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  4. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +48 -0
  5. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
  6. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +51 -0
  7. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
  8. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -24
  9. package/payload/platform/plugins/cloudflare/references/hosting-sites.md +7 -4
  10. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +9 -6
  11. package/payload/platform/plugins/docs/references/admin-ui.md +33 -22
  12. package/payload/platform/plugins/docs/references/attachments.md +5 -1
  13. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +1 -1
  14. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +2 -0
  15. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.d.ts +2 -0
  16. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.d.ts.map +1 -0
  17. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.js +23 -0
  18. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.js.map +1 -0
  19. package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.d.ts +12 -0
  20. package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.d.ts.map +1 -0
  21. package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.js +14 -0
  22. package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.js.map +1 -0
  23. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +3 -1
  24. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
  25. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +2 -0
  26. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
  27. package/payload/platform/scripts/__tests__/check-plugin-references.test.sh +83 -0
  28. package/payload/platform/scripts/check-plugin-references.mjs +60 -11
  29. package/payload/platform/services/claude-session-manager/dist/account-title-stores.d.ts +21 -0
  30. package/payload/platform/services/claude-session-manager/dist/account-title-stores.d.ts.map +1 -0
  31. package/payload/platform/services/claude-session-manager/dist/account-title-stores.js +71 -0
  32. package/payload/platform/services/claude-session-manager/dist/account-title-stores.js.map +1 -0
  33. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +2 -2
  34. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  35. package/payload/platform/services/claude-session-manager/dist/http-server.js +46 -103
  36. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/index.js +40 -10
  38. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.d.ts +35 -0
  40. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.d.ts.map +1 -0
  41. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js +114 -0
  42. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js.map +1 -0
  43. package/payload/platform/services/claude-session-manager/package.json +2 -1
  44. package/payload/server/package.json +2 -1
  45. package/payload/server/public/assets/{AdminLoginScreens-C_Qn0UPy.js → AdminLoginScreens-C_h8V0Xs.js} +1 -1
  46. package/payload/server/public/assets/AdminShell-Dqnxpn7U.js +1 -0
  47. package/payload/server/public/assets/{Checkbox-B76SHnPC.js → Checkbox-Bl1WRVGb.js} +1 -1
  48. package/payload/server/public/assets/Transcript-C93Lifnb.js +1 -0
  49. package/payload/server/public/assets/admin-ByoqNaSf.js +1 -0
  50. package/payload/server/public/assets/admin-types-hioowVct.js +1 -0
  51. package/payload/server/public/assets/{arc-JgkiMDpu.js → arc-C6-nr5UV.js} +1 -1
  52. package/payload/server/public/assets/architecture-YZFGNWBL-DdgmZ93B.js +1 -0
  53. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CyIbl1bD.js → architectureDiagram-Q4EWVU46-DIdho_T6.js} +1 -1
  54. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CkcZVblf.js → blockDiagram-DXYQGD6D-D5rTTBSy.js} +1 -1
  55. package/payload/server/public/assets/{browser-Chmp3Xfv.js → browser-BXY1sNxv.js} +1 -1
  56. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-VByNuobb.js → c4Diagram-AHTNJAMY-pfUVHdmy.js} +1 -1
  57. package/payload/server/public/assets/calendar-CObRTPpU.js +1 -0
  58. package/payload/server/public/assets/channel-Da-UUyqx.js +1 -0
  59. package/payload/server/public/assets/chat-Dq-VHp7a.js +1 -0
  60. package/payload/server/public/assets/chevron-left-DjbK_wdQ.js +1 -0
  61. package/payload/server/public/assets/{chunk-2KRD3SAO-BFwiGcqo.js → chunk-2KRD3SAO-EF6cdj8U.js} +1 -1
  62. package/payload/server/public/assets/{chunk-336JU56O-BMCBU-vf.js → chunk-336JU56O-DE-lcZAc.js} +2 -2
  63. package/payload/server/public/assets/chunk-426QAEUC-B1kFAxo1.js +1 -0
  64. package/payload/server/public/assets/{chunk-4BX2VUAB-RfOeo8_F.js → chunk-4BX2VUAB--ANCzzyn.js} +1 -1
  65. package/payload/server/public/assets/{chunk-4TB4RGXK-B5xbgonc.js → chunk-4TB4RGXK-DTO_X80J.js} +1 -1
  66. package/payload/server/public/assets/{chunk-55IACEB6-K8U55ikJ.js → chunk-55IACEB6-4J3nrz44.js} +1 -1
  67. package/payload/server/public/assets/{chunk-5FUZZQ4R-DgmmsrAc.js → chunk-5FUZZQ4R-jH_eqAHL.js} +1 -1
  68. package/payload/server/public/assets/{chunk-5PVQY5BW-DQ6rtehF.js → chunk-5PVQY5BW-C-qU6p6k.js} +1 -1
  69. package/payload/server/public/assets/{chunk-67CJDMHE-CC2kfpmQ.js → chunk-67CJDMHE-DXxH9Snb.js} +1 -1
  70. package/payload/server/public/assets/{chunk-7N4EOEYR-BClZ5bzw.js → chunk-7N4EOEYR-CCkxuP7A.js} +1 -1
  71. package/payload/server/public/assets/{chunk-AA7GKIK3-adtwAFKX.js → chunk-AA7GKIK3-CyItuM8d.js} +1 -1
  72. package/payload/server/public/assets/{chunk-BSJP7CBP-fKY1UWEd.js → chunk-BSJP7CBP-Bg7gxYNf.js} +1 -1
  73. package/payload/server/public/assets/{chunk-CIAEETIT-knPAMmjG.js → chunk-CIAEETIT-BAXbOqv5.js} +1 -1
  74. package/payload/server/public/assets/{chunk-EDXVE4YY-C7FRKZ5e.js → chunk-EDXVE4YY-vdoErQoc.js} +1 -1
  75. package/payload/server/public/assets/{chunk-ENJZ2VHE-0cgFfv3z.js → chunk-ENJZ2VHE-Cz_z_6GK.js} +1 -1
  76. package/payload/server/public/assets/{chunk-FMBD7UC4-Dm_Hcblb.js → chunk-FMBD7UC4-Ck2jvOgW.js} +1 -1
  77. package/payload/server/public/assets/{chunk-FOC6F5B3-CfCJNXmK.js → chunk-FOC6F5B3-DucR0Qo8.js} +1 -1
  78. package/payload/server/public/assets/{chunk-ICPOFSXX-xeu6qrZj.js → chunk-ICPOFSXX-DolYDD7g.js} +2 -2
  79. package/payload/server/public/assets/{chunk-K5T4RW27-BQDCSuTh.js → chunk-K5T4RW27-FRzx7E5I.js} +1 -1
  80. package/payload/server/public/assets/{chunk-KGLVRYIC-D6fFAgbM.js → chunk-KGLVRYIC-Bb5S4Bmc.js} +1 -1
  81. package/payload/server/public/assets/{chunk-LIHQZDEY-Dskwlc-K.js → chunk-LIHQZDEY-c8VZJ-lU.js} +1 -1
  82. package/payload/server/public/assets/{chunk-ORNJ4GCN-CnHIrJeA.js → chunk-ORNJ4GCN-BAeh-LZ1.js} +1 -1
  83. package/payload/server/public/assets/{chunk-OYMX7WX6-B4bnsPkv.js → chunk-OYMX7WX6-BUg7Kysh.js} +1 -1
  84. package/payload/server/public/assets/chunk-QZHKN3VN-BjE-Glwf.js +1 -0
  85. package/payload/server/public/assets/{chunk-U2HBQHQK-BeEXzOqV.js → chunk-U2HBQHQK-K4r17UTk.js} +1 -1
  86. package/payload/server/public/assets/{chunk-X2U36JSP-D2rpgOqd.js → chunk-X2U36JSP-Byh-CyxC.js} +1 -1
  87. package/payload/server/public/assets/{chunk-XPW4576I-D-yT82Xf.js → chunk-XPW4576I-DC7lhr93.js} +1 -1
  88. package/payload/server/public/assets/{chunk-YZCP3GAM-DqxlLBm1.js → chunk-YZCP3GAM-B2cu7AEP.js} +1 -1
  89. package/payload/server/public/assets/{chunk-ZZ45TVLE-CA_Ep0OM.js → chunk-ZZ45TVLE-DH_p8sFX.js} +1 -1
  90. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Dol3Ogeh.js +1 -0
  91. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-VUMj7gWH.js +1 -0
  92. package/payload/server/public/assets/clone-m7oGrdBC.js +1 -0
  93. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-DWb9mxTa.js → cose-bilkent-S5V4N54A-DeM6JI00.js} +1 -1
  94. package/payload/server/public/assets/{dagre-B3K7jxOZ.js → dagre-3drs3e4F.js} +1 -1
  95. package/payload/server/public/assets/{dagre-KV5264BT-BhiTISRq.js → dagre-KV5264BT-C6S-VUtN.js} +1 -1
  96. package/payload/server/public/assets/data-BXOoK8Ci.js +1 -0
  97. package/payload/server/public/assets/{diagram-5BDNPKRD-D5yBIDpm.js → diagram-5BDNPKRD-BkvA32I3.js} +1 -1
  98. package/payload/server/public/assets/{diagram-G4DWMVQ6-CSTE1S4d.js → diagram-G4DWMVQ6-CVwtRMPB.js} +1 -1
  99. package/payload/server/public/assets/{diagram-MMDJMWI5-D8llv4XY.js → diagram-MMDJMWI5-DJ1JVMbd.js} +1 -1
  100. package/payload/server/public/assets/{diagram-TYMM5635-CITQ7aDM.js → diagram-TYMM5635-rfj-crtX.js} +1 -1
  101. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BjR5nlmv.js → erDiagram-SMLLAGMA-TJPuweS5.js} +1 -1
  102. package/payload/server/public/assets/{flatten-DhYYI_lo.js → flatten-BZkoyJ4e.js} +1 -1
  103. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-Dl6e-E0f.js → flowDiagram-DWJPFMVM-LQWEUjbV.js} +1 -1
  104. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CppkrFAl.js → ganttDiagram-T4ZO3ILL-DdYsxKRw.js} +1 -1
  105. package/payload/server/public/assets/gitGraph-7Q5UKJZL-cJEaiQq4.js +1 -0
  106. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-clV_tnwa.js → gitGraphDiagram-UUTBAWPF-sx8-fokM.js} +1 -1
  107. package/payload/server/public/assets/{graph-DEHmvpNl.js → graph-BCL0fVDH.js} +3 -3
  108. package/payload/server/public/assets/{graph-labels-CYAjU3rz.js → graph-labels-C0nn9nQi.js} +1 -1
  109. package/payload/server/public/assets/{graphlib-Cnk6WL-8.js → graphlib-DixeJdCf.js} +1 -1
  110. package/payload/server/public/assets/info-OMHHGYJF-BUxfOTKa.js +1 -0
  111. package/payload/server/public/assets/infoDiagram-42DDH7IO-CD-d3Rgf.js +2 -0
  112. package/payload/server/public/assets/{isEmpty-DGhq_DBP.js → isEmpty-VRKFml5R.js} +1 -1
  113. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DUqusmP1.js → ishikawaDiagram-UXIWVN3A-BKUCuKhZ.js} +1 -1
  114. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-RMEvGtDJ.js → journeyDiagram-VCZTEJTY-BafZP6pM.js} +1 -1
  115. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BxkwQPCP.js → kanban-definition-6JOO6SKY-DQ4c6wRv.js} +1 -1
  116. package/payload/server/public/assets/{line-CiOuSBlJ.js → line-0_x1Wivu.js} +1 -1
  117. package/payload/server/public/assets/{linear-D22sItNm.js → linear-CZrU-J2V.js} +1 -1
  118. package/payload/server/public/assets/{mermaid-parser.core-kvN8ajT-.js → mermaid-parser.core-DwJ1cyfO.js} +2 -2
  119. package/payload/server/public/assets/{mermaid.core-DKHTTwbg.js → mermaid.core-DnUst0He.js} +3 -3
  120. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CKUJxwdG.js → mindmap-definition-QFDTVHPH-oc-GwerE.js} +1 -1
  121. package/payload/server/public/assets/operator-B_1qYO7m.js +1 -0
  122. package/payload/server/public/assets/{ordinal-CibZU3PM.js → ordinal-v4prQcuq.js} +1 -1
  123. package/payload/server/public/assets/packet-4T2RLAQJ-B9U_2639.js +1 -0
  124. package/payload/server/public/assets/page-BQEl7aZO.js +1 -0
  125. package/payload/server/public/assets/page-Dck23z9U.js +32 -0
  126. package/payload/server/public/assets/pdf-render-NQmflZ7K.js +11 -0
  127. package/payload/server/public/assets/pdf.worker.min-yatZIOMy.mjs +21 -0
  128. package/payload/server/public/assets/pie-ZZUOXDRM-Glh-lJOT.js +1 -0
  129. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CRMabeJN.js → pieDiagram-DEJITSTG-BnBtQNHM.js} +1 -1
  130. package/payload/server/public/assets/public-BzvwPHM0.js +1 -0
  131. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DcrlhDuj.js → quadrantDiagram-34T5L4WZ-CkNqtzHI.js} +1 -1
  132. package/payload/server/public/assets/radar-PYXPWWZC-CTSgob8w.js +1 -0
  133. package/payload/server/public/assets/{reduce-Da0RBva0.js → reduce-0Mm1v1Rr.js} +1 -1
  134. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DP231rM_.js → requirementDiagram-MS252O5E-D7qc27KT.js} +1 -1
  135. package/payload/server/public/assets/{rotate-ccw-K1xZvf3B.js → rotate-ccw-CHep9vl5.js} +1 -1
  136. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6--HM5_dC8.js → sankeyDiagram-XADWPNL6-2Y4sqRY7.js} +1 -1
  137. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BsiVmDR9.js → sequenceDiagram-FGHM5R23-hXOiSHuT.js} +1 -1
  138. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-Cjdhqdjh.js → stateDiagram-FHFEXIEX-Dq4hhkLA.js} +1 -1
  139. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DTj9o2vZ.js +1 -0
  140. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Cf5xPmSA.js → timeline-definition-GMOUNBTQ-Dn9wBUEw.js} +1 -1
  141. package/payload/server/public/assets/treeView-SZITEDCU-CXApkW1l.js +1 -0
  142. package/payload/server/public/assets/treemap-W4RFUUIX-DzvTXAcT.js +1 -0
  143. package/payload/server/public/assets/useSubAccountSwitcher-B1Kf32uG.js +9 -0
  144. package/payload/server/public/assets/{useSubAccountSwitcher-B44qYovc.css → useSubAccountSwitcher-CfI3J2IX.css} +1 -1
  145. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-PCor55Sw.js → vennDiagram-DHZGUBPP-BKVHJiIt.js} +1 -1
  146. package/payload/server/public/assets/wardley-RL74JXVD-BExXV4oI.js +1 -0
  147. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-bokCHsim.js → wardleyDiagram-NUSXRM2D-Bn9vvpdK.js} +1 -1
  148. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-B2YnsUoQ.js → xychartDiagram-5P7HB3ND-FIoMdPB3.js} +1 -1
  149. package/payload/server/public/browser.html +5 -4
  150. package/payload/server/public/calendar.html +6 -4
  151. package/payload/server/public/chat.html +11 -8
  152. package/payload/server/public/data.html +8 -5
  153. package/payload/server/public/graph.html +9 -7
  154. package/payload/server/public/index.html +11 -9
  155. package/payload/server/public/operator.html +13 -10
  156. package/payload/server/public/public.html +10 -8
  157. package/payload/server/server.js +150 -21
  158. package/payload/server/public/assets/AdminShell-iHdYhspw.js +0 -1
  159. package/payload/server/public/assets/admin-RTEhnrPk.js +0 -1
  160. package/payload/server/public/assets/admin-types-DJoj6VJv.js +0 -1
  161. package/payload/server/public/assets/architecture-YZFGNWBL-Dh5BzVzk.js +0 -1
  162. package/payload/server/public/assets/calendar-CjE7hiqV.js +0 -1
  163. package/payload/server/public/assets/channel-CFHc3PQ7.js +0 -1
  164. package/payload/server/public/assets/chat-DiKmCMO1.js +0 -1
  165. package/payload/server/public/assets/chunk-426QAEUC-De9_O1hi.js +0 -1
  166. package/payload/server/public/assets/chunk-QZHKN3VN-COwe7oXR.js +0 -1
  167. package/payload/server/public/assets/classDiagram-6PBFFD2Q-wjL65qaU.js +0 -1
  168. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D_EIplVd.js +0 -1
  169. package/payload/server/public/assets/clone-CEczy_Ef.js +0 -1
  170. package/payload/server/public/assets/data-5PpEsUR3.js +0 -1
  171. package/payload/server/public/assets/gitGraph-7Q5UKJZL-KHAc7IxG.js +0 -1
  172. package/payload/server/public/assets/info-OMHHGYJF-C6nm3sYf.js +0 -1
  173. package/payload/server/public/assets/infoDiagram-42DDH7IO-DhwCejsr.js +0 -2
  174. package/payload/server/public/assets/operator-BDTnuQhB.js +0 -1
  175. package/payload/server/public/assets/packet-4T2RLAQJ-z-APhyNH.js +0 -1
  176. package/payload/server/public/assets/page-D8FFXoI9.js +0 -1
  177. package/payload/server/public/assets/page-HeiBebPq.js +0 -32
  178. package/payload/server/public/assets/pie-ZZUOXDRM-D_HVZjir.js +0 -1
  179. package/payload/server/public/assets/public-BIOxrxZK.js +0 -1
  180. package/payload/server/public/assets/radar-PYXPWWZC-DtKBIb3o.js +0 -1
  181. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-6v4alr7n.js +0 -1
  182. package/payload/server/public/assets/treeView-SZITEDCU-DbXWs029.js +0 -1
  183. package/payload/server/public/assets/treemap-W4RFUUIX-DUGgqAs9.js +0 -1
  184. package/payload/server/public/assets/useSubAccountSwitcher-DPEkYkYd.js +0 -9
  185. package/payload/server/public/assets/wardley-RL74JXVD-Cjn85RON.js +0 -1
  186. /package/payload/server/public/assets/{_baseFor-BFYpZGkN.js → _baseFor-C0Y1mc3g.js} +0 -0
  187. /package/payload/server/public/assets/{array-CYkMkqnU.js → array-DqLCdDFv.js} +0 -0
  188. /package/payload/server/public/assets/{cytoscape.esm-DqlHsaog.js → cytoscape.esm-Cn5b4Cdu.js} +0 -0
  189. /package/payload/server/public/assets/{defaultLocale-Beh6XjaL.js → defaultLocale-CrJzLgRD.js} +0 -0
  190. /package/payload/server/public/assets/{dist-BMqkacmt.js → dist-Dlks0Bfw.js} +0 -0
  191. /package/payload/server/public/assets/{init-Rr1s_RiX.js → init-C0r9Gk5G.js} +0 -0
  192. /package/payload/server/public/assets/{katex-pVJiI_rc.js → katex-BFwFoEts.js} +0 -0
  193. /package/payload/server/public/assets/{path-BAQ3hXlG.js → path-DIKpVbHL.js} +0 -0
  194. /package/payload/server/public/assets/{preload-helper-B_l5jfgx.js → preload-helper-C5gCWwwF.js} +0 -0
  195. /package/payload/server/public/assets/{rough.esm-nHaDi0Kw.js → rough.esm-DsHEmXUZ.js} +0 -0
  196. /package/payload/server/public/assets/{src-CsEKjNXD.js → src-Bv7ZWAzF.js} +0 -0
@@ -319,22 +319,6 @@ export function tailIsOpenTurn(jsonlPath) {
319
319
  /** Resolve any of the 4 keys to the canonical (sessionId, row) pair.
320
320
  * Tries: intrinsic sessionId, bridgeSessionId, bridgeSuffix, numeric pid.
321
321
  * Returns undefined when nothing matches. */
322
- /** Task 1324 — resolve the on-disk project slug for a supplied `accountId`,
323
- * mirroring the /rc-spawn account derivation (`accountsRoot =
324
- * dirname(platformRoot)/data/accounts`) and config.ts's
325
- * `accountIdFromSessionCwd` invariant that an account's spawn cwd is
326
- * `<accountsRoot>/<accountId>`. Returns null when the accountId names no
327
- * account dir in the registry, so the caller can 400 the mismatch instead of
328
- * scanning a slug that cannot exist. The caller is responsible for
329
- * shape-validating `accountId` (UUID) BEFORE calling — the value is joined
330
- * into a filesystem path here, so an unvalidated caller would open a path
331
- * traversal. */
332
- function accountSlugForId(platformRoot, accountId) {
333
- const accountDir = join(dirname(platformRoot), 'data', 'accounts', accountId);
334
- if (!existsSync(join(accountDir, 'account.json')))
335
- return null;
336
- return projectSlugForCwd(accountDir);
337
- }
338
322
  function resolveRow(watcher, id) {
339
323
  const direct = watcher.getBySessionId(id);
340
324
  if (direct)
@@ -841,7 +825,7 @@ export function buildHttpApp(deps) {
841
825
  let model = null;
842
826
  let enrichedStartedAt = null;
843
827
  if (hasJsonl) {
844
- const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, LIST_TAIL_BYTES, deps.logger, deps.userTitleStore);
828
+ const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, LIST_TAIL_BYTES, deps.logger, deps.titleStores.forSessionCwd(row.cwd));
845
829
  if (enriched) {
846
830
  displayName = enriched.displayName;
847
831
  titleSource = enriched.titleSource;
@@ -854,14 +838,14 @@ export function buildHttpApp(deps) {
854
838
  }
855
839
  }
856
840
  else {
857
- const userTitle = deps.userTitleStore.get(row.sessionId)?.title;
841
+ const userTitle = deps.titleStores.forSessionCwd(row.cwd).get(row.sessionId)?.title;
858
842
  if (userTitle) {
859
843
  displayName = userTitle;
860
844
  titleSource = 'user';
861
845
  }
862
846
  }
863
847
  // Task 624 — standing reconciliation. A LIVE role=public row whose title did
864
- // not resolve from the user-override tier means the /spawn userTitleStore.set
848
+ // not resolve from the user-override tier means the /spawn titleStores.set
865
849
  // silently failed or was evicted. Fires on the next list read while the
866
850
  // session is live, so a missing write is caught without a live repro. Gated
867
851
  // to live rows so pre-Task-624 public sessions (no title, forward-only — the
@@ -1118,7 +1102,7 @@ export function buildHttpApp(deps) {
1118
1102
  // field so a dropped name is visible without reproducing.
1119
1103
  if (role === 'public') {
1120
1104
  if (publicTitle) {
1121
- deps.userTitleStore.set(result.session.sessionId, publicTitle);
1105
+ deps.titleStores.forSessionCwd(deps.spawnCwd).set(result.session.sessionId, publicTitle);
1122
1106
  deps.logger(`[spawn] role=public senderId=${senderId} sessionId=${result.session.sessionId.slice(0, 8)} title="${publicTitle}"`);
1123
1107
  }
1124
1108
  else {
@@ -1163,7 +1147,7 @@ export function buildHttpApp(deps) {
1163
1147
  let titleSource = null;
1164
1148
  const jsonlPath = jsonlPathForSessionId(deps.spawnCwd, row.sessionId);
1165
1149
  if (existsSync(jsonlPath)) {
1166
- const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, LIST_TAIL_BYTES, deps.logger, deps.userTitleStore);
1150
+ const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, LIST_TAIL_BYTES, deps.logger, deps.titleStores.forSessionCwd(row.cwd));
1167
1151
  if (enriched) {
1168
1152
  firstPrompt = enriched.displayName;
1169
1153
  titleSource = enriched.titleSource;
@@ -1171,7 +1155,7 @@ export function buildHttpApp(deps) {
1171
1155
  }
1172
1156
  else {
1173
1157
  // Pre-jsonl / post-purge: only the user-title store can answer.
1174
- const userTitle = deps.userTitleStore.get(row.sessionId)?.title;
1158
+ const userTitle = deps.titleStores.forSessionCwd(row.cwd).get(row.sessionId)?.title;
1175
1159
  if (userTitle) {
1176
1160
  firstPrompt = userTitle;
1177
1161
  titleSource = 'user';
@@ -1337,7 +1321,7 @@ export function buildHttpApp(deps) {
1337
1321
  // /events handler re-emits the row so every browser tab sees the new
1338
1322
  // label without re-fetching the sidebar route. The row lookup goes through the
1339
1323
  // watcher (canonical row index); rowToPayload then re-reads the user
1340
- // title from `deps.userTitleStore`, picking up the freshly-set value.
1324
+ // title from `deps.titleStores`, picking up the freshly-set value.
1341
1325
  const renameListener = (sessionId) => {
1342
1326
  if (!active)
1343
1327
  return;
@@ -1395,7 +1379,7 @@ export function buildHttpApp(deps) {
1395
1379
  ? jsonlPathForSessionId(deps.spawnCwd, row.sessionId, { archived: true })
1396
1380
  : jsonlPathForSessionId(deps.spawnCwd, row.sessionId);
1397
1381
  if (existsSync(candidatePath)) {
1398
- const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, deps.jsonlReadMaxBytes, deps.logger, deps.userTitleStore);
1382
+ const enriched = readJsonlSession(deps.spawnCwd, row.sessionId, deps.jsonlReadMaxBytes, deps.logger, deps.titleStores.forSessionCwd(row.cwd));
1399
1383
  if (enriched) {
1400
1384
  payload = {
1401
1385
  ...payload,
@@ -1539,7 +1523,7 @@ export function buildHttpApp(deps) {
1539
1523
  timed(deps.logger, 'POST', `/${id}/rename`, 400, Date.now() - start);
1540
1524
  return c.json({ error: 'invalid-title', reason: result.reason }, 400);
1541
1525
  }
1542
- const entry = deps.userTitleStore.set(sessionId, result.title);
1526
+ const entry = deps.titleStores.forSessionCwd(row?.cwd ?? null).set(sessionId, result.title);
1543
1527
  // Title content is never logged — operator names may contain customer
1544
1528
  // data. Byte count is enough for forensic recovery of bulk-rename surges.
1545
1529
  const titleBytes = Buffer.byteLength(entry.title, 'utf-8');
@@ -1589,44 +1573,28 @@ export function buildHttpApp(deps) {
1589
1573
  timed(deps.logger, 'POST', `/${id}/stop`, 400, Date.now() - start);
1590
1574
  return c.json({ error: 'invalid-session-id' }, 400);
1591
1575
  }
1592
- const accountId = c.req.query('accountId') || undefined;
1593
1576
  const row = resolveRow(deps.watcher, id);
1594
1577
  const sessionId = row?.sessionId ?? id;
1595
- // Task 1324account-scoped resolution for the `!row` branch. On a
1596
- // multi-account install the watcher is armed only on the house slug, so a
1597
- // cross-account session has no row. When the admin UI forwards the caller's
1598
- // canonical accountId, resolve the session from `sessionId + accountId`
1599
- // instead of the watcher, so a false 404 no longer swallows the stop. The
1600
- // token to actually terminate a scope unit that survived a manager restart
1601
- // comes from the on-disk scope record (keyed by sessionId, account-agnostic)
1602
- // the watcher row is the only other source and it is absent here.
1603
- let accountScoped = false;
1578
+ // Task 1357when there is no watcher row and nothing live under this id,
1579
+ // resolve the session the SAME way the sidebar list does: locate its JSONL
1580
+ // by scanning every slug under projects/ (slugForExistingJsonl checks both
1581
+ // the top level and archive/), plus the on-disk scope record that names a
1582
+ // scope unit surviving a manager restart. If none of these exist, the
1583
+ // session is genuinely gone 404. This replaces the Task 1324
1584
+ // accountId-derived slug: account scope is a view filter, not a stop gate
1585
+ // (admin access is install-wide), and deriving the slug from the caller's
1586
+ // accountId 404'd any session living under a non-house slug with no row —
1587
+ // a false not-found that silently swallowed the stop.
1604
1588
  let scopeTokenFromRecord = null;
1605
1589
  if (!row && !isLive(id)) {
1606
- if (accountId) {
1607
- // Resolve the slug once (UUID gate first accountId is joined into a
1608
- // path). A null result means the id names no account in the registry.
1609
- const slug = UUID_PATTERN.test(accountId) ? accountSlugForId(deps.platformRoot, accountId) : null;
1610
- if (slug === null) {
1611
- deps.logger(`stop-account-mismatch sessionId=${sessionId.slice(0, 8)} accountId=${accountId.slice(0, 8)}`);
1612
- timed(deps.logger, 'POST', `/${id}/stop`, 400, Date.now() - start);
1613
- return c.json({ error: 'accountId not in this install registry' }, 400);
1614
- }
1615
- const hasTop = existsSync(jsonlPathForSlug(deps.claudeConfigDir, slug, sessionId));
1616
- const hasArchived = existsSync(jsonlPathForSlug(deps.claudeConfigDir, slug, sessionId, { archived: true }));
1617
- const rec = readAllScopeRecords(sessionsDir, deps.logger).find((r) => r.sessionId === sessionId);
1618
- if (!hasTop && !hasArchived && !rec) {
1619
- deps.logger(`stop-not-found sessionId=${sessionId.slice(0, 8)} accountId=${accountId.slice(0, 8)} reason=file-missing`);
1620
- timed(deps.logger, 'POST', `/${id}/stop`, 404, Date.now() - start);
1621
- return c.json({ error: 'session-not-found' }, 404);
1622
- }
1623
- accountScoped = true;
1624
- scopeTokenFromRecord = rec?.scopeUnitToken ?? null;
1625
- }
1626
- else {
1590
+ const onDisk = slugForExistingJsonl(deps.claudeConfigDir, sessionId) !== null;
1591
+ const rec = readAllScopeRecords(sessionsDir, deps.logger).find((r) => r.sessionId === sessionId);
1592
+ if (!onDisk && !rec) {
1593
+ deps.logger(`stop-not-found sessionId=${sessionId.slice(0, 8)} reason=not-found-anywhere`);
1627
1594
  timed(deps.logger, 'POST', `/${id}/stop`, 404, Date.now() - start);
1628
1595
  return c.json({ error: 'session-not-found' }, 404);
1629
1596
  }
1597
+ scopeTokenFromRecord = rec?.scopeUnitToken ?? null;
1630
1598
  }
1631
1599
  // Task 455 — snapshot the live pid and prior-exited-count BEFORE
1632
1600
  // stopSession runs (the call mutates module state). When prior history
@@ -1658,13 +1626,6 @@ export function buildHttpApp(deps) {
1658
1626
  // formatting (Task 250 contract); this is the single audit line the
1659
1627
  // operator and tests can grep against to confirm which branch ran.
1660
1628
  deps.logger(`[stop-session] path=${outcome.path} outcome=${outcome.scopeOutcome} sessionId=${sessionId.slice(0, 8)} unit=${row?.scopeUnitToken ?? 'none'} pid=${row?.pid ?? 'unknown'}`);
1661
- // Task 1324 — one diffable audit line whenever the stop resolved from the
1662
- // caller's accountId rather than a watcher row. Distinct from the unified
1663
- // line above so a log read can tell the account-scoped path from the
1664
- // house-account row/liveptys paths.
1665
- if (accountScoped) {
1666
- deps.logger(`[stop-session] path=account-scoped outcome=${outcome.scopeOutcome} sessionId=${sessionId.slice(0, 8)} accountId=${accountId.slice(0, 8)}`);
1667
- }
1668
1629
  // Task 250 — surface scope-stop failures as 500 so the operator sees
1669
1630
  // the End-click fail when systemd cannot stop the unit. The liveptys
1670
1631
  // happy path keeps its original 204 response (Task 250 contract).
@@ -1718,7 +1679,6 @@ export function buildHttpApp(deps) {
1718
1679
  timed(deps.logger, 'DELETE', `/${id}`, 400, Date.now() - start);
1719
1680
  return c.json({ error: 'invalid-session-id' }, 400);
1720
1681
  }
1721
- const accountId = c.req.query('accountId') || undefined;
1722
1682
  const row = resolveRow(deps.watcher, id);
1723
1683
  const sessionId = row?.sessionId ?? id;
1724
1684
  if (isLive(sessionId)) {
@@ -1726,50 +1686,29 @@ export function buildHttpApp(deps) {
1726
1686
  timed(deps.logger, 'DELETE', `/${id}`, 409, Date.now() - start);
1727
1687
  return c.json({ error: 'pty-still-alive', detail: 'stop the session before deleting' }, 409);
1728
1688
  }
1729
- // Task 260 — purge from BOTH locations: a row may have its JSONL
1730
- // at the top level (live or just-ended) or under archive/ (archived).
1731
- // Task 1324when the admin UI forwards the caller's canonical accountId,
1732
- // derive the slug from it and gate ONLY on file existence, bypassing the
1733
- // watcher row (which is single-account-scoped and absent for any session
1734
- // outside the manager's house account). When accountId is absent, keep the
1735
- // Task 1298 watcher-row path unchanged for back-compat, but log the
1736
- // degraded fallback so the account-less path is visible in the log.
1737
- let resolvedSlug;
1738
- if (accountId) {
1739
- // Resolve the slug once (UUID gate first accountId is joined into a
1740
- // path). A null result means the id names no account in the registry.
1741
- const acctSlug = UUID_PATTERN.test(accountId) ? accountSlugForId(deps.platformRoot, accountId) : null;
1742
- if (acctSlug === null) {
1743
- deps.logger(`delete-account-mismatch sessionId=${sessionId.slice(0, 8)} accountId=${accountId.slice(0, 8)}`);
1744
- timed(deps.logger, 'DELETE', `/${id}`, 400, Date.now() - start);
1745
- return c.json({ error: 'accountId not in this install registry' }, 400);
1746
- }
1747
- resolvedSlug = acctSlug;
1748
- }
1749
- else {
1750
- deps.logger(`delete-fallback sessionId=${sessionId.slice(0, 8)} reason=no-accountId-supplied`);
1751
- // Task 1298 — resolve the slug that actually holds the JSONL; the list
1752
- // (sidebar-sessions.ts) walks every slug, so delete must too. Fall back
1753
- // to spawnCwd's slug only when nothing is found anywhere.
1754
- resolvedSlug = slugForExistingJsonl(deps.claudeConfigDir, sessionId) ?? projectSlugForCwd(deps.spawnCwd);
1755
- }
1689
+ // Task 260 — purge from BOTH locations: a row may have its JSONL at the top
1690
+ // level (live or just-ended) or under archive/ (archived).
1691
+ // Task 1357resolve the holding slug the SAME way the sidebar list does:
1692
+ // locate `<sessionId>.jsonl` by scanning every slug under projects/
1693
+ // (slugForExistingJsonl mirrors enumerateJsonls in sidebar-sessions.ts, and
1694
+ // checks archive/ too). The list narrows resolution by nothing, so delete
1695
+ // must not either a session the list shows must be deletable. Gate on file
1696
+ // existence alone. This removes the Task 1324 accountId-derived slug and the
1697
+ // Task 1298 `!row` term, both of which narrowed resolution below what the
1698
+ // list enumerates: a session under a non-house slug with no watcher row
1699
+ // (e.g. a legacy `-home-admin` session on a single-account install) was
1700
+ // listed yet un-deletable. Account scope is a view filter, not a delete gate
1701
+ // admin access is install-wide. Fall back to spawnCwd's slug only when the
1702
+ // JSONL exists nowhere, so a genuinely-absent id still 404s.
1703
+ const resolvedSlug = slugForExistingJsonl(deps.claudeConfigDir, sessionId) ?? projectSlugForCwd(deps.spawnCwd);
1756
1704
  const topJsonl = jsonlPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId);
1757
1705
  const archivedJsonl = jsonlPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId, { archived: true });
1758
1706
  const topSidecar = sidecarPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId);
1759
1707
  const archivedSidecar = sidecarPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId, { archived: true });
1760
1708
  const hasTop = existsSync(topJsonl);
1761
1709
  const hasArchived = existsSync(archivedJsonl);
1762
- // Account-scoped path gates on file existence alone (the row is expected to
1763
- // be absent). Fallback path keeps the `!row` term so a bare id with no row
1764
- // still 404s as `not-found-anywhere` (Task 1298 contract).
1765
- const notFound = accountId ? (!hasTop && !hasArchived) : (!row || (!hasTop && !hasArchived));
1766
- if (notFound) {
1767
- if (accountId) {
1768
- deps.logger(`delete-not-found sessionId=${sessionId.slice(0, 8)} accountId=${accountId.slice(0, 8)} reason=file-missing`);
1769
- }
1770
- else {
1771
- deps.logger(`delete-not-found sessionId=${sessionId.slice(0, 8)} reason=not-found-anywhere`);
1772
- }
1710
+ if (!hasTop && !hasArchived) {
1711
+ deps.logger(`delete-not-found sessionId=${sessionId.slice(0, 8)} reason=not-found-anywhere`);
1773
1712
  timed(deps.logger, 'DELETE', `/${id}`, 404, Date.now() - start);
1774
1713
  return c.json({ error: 'session-not-found' }, 404);
1775
1714
  }
@@ -1803,7 +1742,11 @@ export function buildHttpApp(deps) {
1803
1742
  // session-titles.json doesn't accrete orphans. Best-effort; the store
1804
1743
  // logs its own failure and reads still serve from the in-memory map
1805
1744
  // until next boot.
1806
- deps.userTitleStore.remove(sessionId);
1745
+ // Task 1354 — remove from the SESSION's account file, not the boot file.
1746
+ // Resolve the account from the row's spawn cwd; an absent/cwd-less row
1747
+ // (legacy non-account-scoped session) falls back to the boot store, which
1748
+ // is where such a session's title would have been written anyway.
1749
+ deps.titleStores.forSessionCwd(row?.cwd ?? null).remove(sessionId);
1807
1750
  // Task 683 — drop the channel binding too so wa-channel-bindings.json
1808
1751
  // doesn't accrete orphans and a recreated session can't inherit a stale
1809
1752
  // binding. Best-effort; the store logs its own failure.