@rubytech/create-maxy-code 0.1.376 → 0.1.378

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 (164) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +25 -4
  3. package/payload/platform/plugins/docs/references/admin-ui.md +24 -3
  4. package/payload/platform/scripts/lib/read-brand-json.sh +19 -0
  5. package/payload/platform/scripts/seed-neo4j.sh +44 -3
  6. package/payload/platform/services/claude-session-manager/dist/config.d.ts +9 -0
  7. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/config.js +15 -1
  9. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  10. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  11. package/payload/platform/services/claude-session-manager/dist/http-server.js +100 -13
  12. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  13. package/payload/platform/services/claude-session-manager/dist/index.js +29 -5
  14. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  15. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +6 -3
  16. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -1
  17. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +2 -2
  18. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -1
  19. package/payload/server/{chunk-Y4SHSFGK.js → chunk-AQO6KLIH.js} +22 -0
  20. package/payload/server/maxy-edge.js +1 -1
  21. package/payload/server/public/assets/AdminLoginScreens-B9u1V35g.js +1 -0
  22. package/payload/server/public/assets/AdminShell-C2UXTLSB.js +1 -0
  23. package/payload/server/public/assets/{Checkbox-C3efsnUI.js → Checkbox-B2g2SCpw.js} +1 -1
  24. package/payload/server/public/assets/admin-CRBQgWsm.js +1 -0
  25. package/payload/server/public/assets/{arc-Crkz45LN.js → arc-JgkiMDpu.js} +1 -1
  26. package/payload/server/public/assets/architecture-YZFGNWBL-Dh5BzVzk.js +1 -0
  27. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-C9JThHgP.js → architectureDiagram-Q4EWVU46-CyIbl1bD.js} +1 -1
  28. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DpsV_HXT.js → blockDiagram-DXYQGD6D-CkcZVblf.js} +1 -1
  29. package/payload/server/public/assets/{browser-CCUgMt_X.js → browser-B8omhYsK.js} +1 -1
  30. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CTm_6aKi.js → c4Diagram-AHTNJAMY-VByNuobb.js} +1 -1
  31. package/payload/server/public/assets/calendar-Blb-5arm.js +1 -0
  32. package/payload/server/public/assets/channel-CFHc3PQ7.js +1 -0
  33. package/payload/server/public/assets/chat--1ajLxwi.js +1 -0
  34. package/payload/server/public/assets/{chunk-2KRD3SAO-1KSJW1q6.js → chunk-2KRD3SAO-BFwiGcqo.js} +1 -1
  35. package/payload/server/public/assets/{chunk-336JU56O-C3t08Ip-.js → chunk-336JU56O-BMCBU-vf.js} +2 -2
  36. package/payload/server/public/assets/chunk-426QAEUC-De9_O1hi.js +1 -0
  37. package/payload/server/public/assets/{chunk-4BX2VUAB-kl1ze33n.js → chunk-4BX2VUAB-RfOeo8_F.js} +1 -1
  38. package/payload/server/public/assets/{chunk-4TB4RGXK-DxpoDoHg.js → chunk-4TB4RGXK-B5xbgonc.js} +1 -1
  39. package/payload/server/public/assets/{chunk-55IACEB6-WM9VJzha.js → chunk-55IACEB6-K8U55ikJ.js} +1 -1
  40. package/payload/server/public/assets/{chunk-5FUZZQ4R-CLH63ZH3.js → chunk-5FUZZQ4R-DgmmsrAc.js} +1 -1
  41. package/payload/server/public/assets/{chunk-5PVQY5BW-DCTb8IAT.js → chunk-5PVQY5BW-DQ6rtehF.js} +1 -1
  42. package/payload/server/public/assets/{chunk-67CJDMHE-BSYzyaoH.js → chunk-67CJDMHE-CC2kfpmQ.js} +1 -1
  43. package/payload/server/public/assets/{chunk-7N4EOEYR-CarJ7O2P.js → chunk-7N4EOEYR-BClZ5bzw.js} +1 -1
  44. package/payload/server/public/assets/{chunk-AA7GKIK3-DTNLyBpH.js → chunk-AA7GKIK3-adtwAFKX.js} +1 -1
  45. package/payload/server/public/assets/{chunk-BSJP7CBP-BFmHflHY.js → chunk-BSJP7CBP-fKY1UWEd.js} +1 -1
  46. package/payload/server/public/assets/{chunk-CIAEETIT-BpjG0IzU.js → chunk-CIAEETIT-knPAMmjG.js} +1 -1
  47. package/payload/server/public/assets/{chunk-EDXVE4YY-2fSowhlW.js → chunk-EDXVE4YY-C7FRKZ5e.js} +1 -1
  48. package/payload/server/public/assets/{chunk-ENJZ2VHE-ClcranGV.js → chunk-ENJZ2VHE-0cgFfv3z.js} +1 -1
  49. package/payload/server/public/assets/{chunk-FMBD7UC4-DLq4BItQ.js → chunk-FMBD7UC4-Dm_Hcblb.js} +1 -1
  50. package/payload/server/public/assets/{chunk-FOC6F5B3-B9QI3Guz.js → chunk-FOC6F5B3-CfCJNXmK.js} +1 -1
  51. package/payload/server/public/assets/{chunk-ICPOFSXX-BAr-Mv1Z.js → chunk-ICPOFSXX-xeu6qrZj.js} +2 -2
  52. package/payload/server/public/assets/{chunk-K5T4RW27-8PvAHasY.js → chunk-K5T4RW27-BQDCSuTh.js} +1 -1
  53. package/payload/server/public/assets/{chunk-KGLVRYIC--aGaDRH5.js → chunk-KGLVRYIC-D6fFAgbM.js} +1 -1
  54. package/payload/server/public/assets/{chunk-LIHQZDEY-BrWj7mw2.js → chunk-LIHQZDEY-Dskwlc-K.js} +1 -1
  55. package/payload/server/public/assets/{chunk-ORNJ4GCN-kYQmkMTi.js → chunk-ORNJ4GCN-CnHIrJeA.js} +1 -1
  56. package/payload/server/public/assets/{chunk-OYMX7WX6-CIsryCWH.js → chunk-OYMX7WX6-B4bnsPkv.js} +1 -1
  57. package/payload/server/public/assets/chunk-QZHKN3VN-COwe7oXR.js +1 -0
  58. package/payload/server/public/assets/{chunk-U2HBQHQK-68X653e3.js → chunk-U2HBQHQK-BeEXzOqV.js} +1 -1
  59. package/payload/server/public/assets/{chunk-X2U36JSP-v3v9soX3.js → chunk-X2U36JSP-D2rpgOqd.js} +1 -1
  60. package/payload/server/public/assets/{chunk-XPW4576I-CW5DPpop.js → chunk-XPW4576I-D-yT82Xf.js} +1 -1
  61. package/payload/server/public/assets/{chunk-YZCP3GAM-B1VP7Rl2.js → chunk-YZCP3GAM-DqxlLBm1.js} +1 -1
  62. package/payload/server/public/assets/{chunk-ZZ45TVLE-DiJrujNY.js → chunk-ZZ45TVLE-CA_Ep0OM.js} +1 -1
  63. package/payload/server/public/assets/classDiagram-6PBFFD2Q-wjL65qaU.js +1 -0
  64. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D_EIplVd.js +1 -0
  65. package/payload/server/public/assets/clone-CEczy_Ef.js +1 -0
  66. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-BscXxLMc.js → cose-bilkent-S5V4N54A-DWb9mxTa.js} +1 -1
  67. package/payload/server/public/assets/{dagre-MBv6WlCS.js → dagre-B3K7jxOZ.js} +1 -1
  68. package/payload/server/public/assets/{dagre-KV5264BT-DVgGlTQ1.js → dagre-KV5264BT-BhiTISRq.js} +1 -1
  69. package/payload/server/public/assets/data-BYUmu98z.js +1 -0
  70. package/payload/server/public/assets/{diagram-5BDNPKRD-BmhCaO0a.js → diagram-5BDNPKRD-D5yBIDpm.js} +1 -1
  71. package/payload/server/public/assets/{diagram-G4DWMVQ6-ChU9L8vz.js → diagram-G4DWMVQ6-CSTE1S4d.js} +1 -1
  72. package/payload/server/public/assets/{diagram-MMDJMWI5-Oy409Zc_.js → diagram-MMDJMWI5-D8llv4XY.js} +1 -1
  73. package/payload/server/public/assets/{diagram-TYMM5635-Cn1YByqk.js → diagram-TYMM5635-CITQ7aDM.js} +1 -1
  74. package/payload/server/public/assets/{erDiagram-SMLLAGMA-e17yfLvr.js → erDiagram-SMLLAGMA-BjR5nlmv.js} +1 -1
  75. package/payload/server/public/assets/{flatten-Cl1Bc3dR.js → flatten-DhYYI_lo.js} +1 -1
  76. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-Dqt7sCVZ.js → flowDiagram-DWJPFMVM-Dl6e-E0f.js} +1 -1
  77. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B4IhwS2r.js → ganttDiagram-T4ZO3ILL-CppkrFAl.js} +1 -1
  78. package/payload/server/public/assets/gitGraph-7Q5UKJZL-KHAc7IxG.js +1 -0
  79. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BDw-PKcI.js → gitGraphDiagram-UUTBAWPF-clV_tnwa.js} +1 -1
  80. package/payload/server/public/assets/{graph-mt6Y1RAt.js → graph-DJOKFr_s.js} +3 -3
  81. package/payload/server/public/assets/{graph-labels-BuKswZHJ.js → graph-labels-DFdBydWC.js} +1 -1
  82. package/payload/server/public/assets/{graphlib-DPIYk_sg.js → graphlib-Cnk6WL-8.js} +1 -1
  83. package/payload/server/public/assets/info-OMHHGYJF-C6nm3sYf.js +1 -0
  84. package/payload/server/public/assets/infoDiagram-42DDH7IO-DhwCejsr.js +2 -0
  85. package/payload/server/public/assets/{isEmpty-D1pGOD1J.js → isEmpty-DGhq_DBP.js} +1 -1
  86. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BRIHsB3G.js → ishikawaDiagram-UXIWVN3A-DUqusmP1.js} +1 -1
  87. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-aKNgmoHd.js → journeyDiagram-VCZTEJTY-RMEvGtDJ.js} +1 -1
  88. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-cwBwT-nm.js → kanban-definition-6JOO6SKY-BxkwQPCP.js} +1 -1
  89. package/payload/server/public/assets/{line-DVtVRzUA.js → line-CiOuSBlJ.js} +1 -1
  90. package/payload/server/public/assets/{linear-DtoOFPO2.js → linear-D22sItNm.js} +1 -1
  91. package/payload/server/public/assets/{mermaid-parser.core-G7YD_zO3.js → mermaid-parser.core-kvN8ajT-.js} +2 -2
  92. package/payload/server/public/assets/{mermaid.core-DpFyndHm.js → mermaid.core-DKHTTwbg.js} +3 -3
  93. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CYXK_Pvz.js → mindmap-definition-QFDTVHPH-CKUJxwdG.js} +1 -1
  94. package/payload/server/public/assets/operator-DUVqlubZ.js +1 -0
  95. package/payload/server/public/assets/{ordinal-CBZeH4Yp.js → ordinal-CibZU3PM.js} +1 -1
  96. package/payload/server/public/assets/packet-4T2RLAQJ-z-APhyNH.js +1 -0
  97. package/payload/server/public/assets/page-BMeSKYGZ.js +32 -0
  98. package/payload/server/public/assets/page-DBkTNfei.js +1 -0
  99. package/payload/server/public/assets/pie-ZZUOXDRM-D_HVZjir.js +1 -0
  100. package/payload/server/public/assets/{pieDiagram-DEJITSTG-DFo4N6WH.js → pieDiagram-DEJITSTG-CRMabeJN.js} +1 -1
  101. package/payload/server/public/assets/{public-CHqiiZCo.js → public-CGl0i1f-.js} +1 -1
  102. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BlH5iIhl.js → quadrantDiagram-34T5L4WZ-DcrlhDuj.js} +1 -1
  103. package/payload/server/public/assets/radar-PYXPWWZC-DtKBIb3o.js +1 -0
  104. package/payload/server/public/assets/{reduce-PuPlFPRX.js → reduce-Da0RBva0.js} +1 -1
  105. package/payload/server/public/assets/{requirementDiagram-MS252O5E-D5WLty8A.js → requirementDiagram-MS252O5E-DP231rM_.js} +1 -1
  106. package/payload/server/public/assets/{rotate-ccw-BkFK-J9e.js → rotate-ccw-Cg_V4XIU.js} +1 -1
  107. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-vB85IxHG.js → sankeyDiagram-XADWPNL6--HM5_dC8.js} +1 -1
  108. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Cxraa0Ee.js → sequenceDiagram-FGHM5R23-BsiVmDR9.js} +1 -1
  109. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BBPssYBx.js → stateDiagram-FHFEXIEX-Cjdhqdjh.js} +1 -1
  110. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-6v4alr7n.js +1 -0
  111. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Bgk6PT62.js → timeline-definition-GMOUNBTQ-Cf5xPmSA.js} +1 -1
  112. package/payload/server/public/assets/treeView-SZITEDCU-DbXWs029.js +1 -0
  113. package/payload/server/public/assets/treemap-W4RFUUIX-DUGgqAs9.js +1 -0
  114. package/payload/server/public/assets/useSubAccountSwitcher-DAgBUed_.js +9 -0
  115. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-B-APTs3L.js → vennDiagram-DHZGUBPP-PCor55Sw.js} +1 -1
  116. package/payload/server/public/assets/wardley-RL74JXVD-Cjn85RON.js +1 -0
  117. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CkXJSs_i.js → wardleyDiagram-NUSXRM2D-bokCHsim.js} +1 -1
  118. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-BkyshPMV.js → xychartDiagram-5P7HB3ND-B2YnsUoQ.js} +1 -1
  119. package/payload/server/public/browser.html +3 -3
  120. package/payload/server/public/calendar.html +3 -3
  121. package/payload/server/public/chat.html +6 -6
  122. package/payload/server/public/data.html +4 -3
  123. package/payload/server/public/graph.html +6 -6
  124. package/payload/server/public/index.html +7 -5
  125. package/payload/server/public/operator.html +8 -8
  126. package/payload/server/public/public.html +6 -6
  127. package/payload/server/server.js +49 -36
  128. package/payload/server/public/assets/AdminLoginScreens-C-LlR7j1.js +0 -1
  129. package/payload/server/public/assets/AdminShell-B7rclo3t.js +0 -1
  130. package/payload/server/public/assets/admin-DVYD__OE.js +0 -1
  131. package/payload/server/public/assets/architecture-YZFGNWBL-Dma4Bgha.js +0 -1
  132. package/payload/server/public/assets/calendar-B3jQEPFX.js +0 -1
  133. package/payload/server/public/assets/channel-B_-5bau1.js +0 -1
  134. package/payload/server/public/assets/chat-IcD9N2mi.js +0 -1
  135. package/payload/server/public/assets/chunk-426QAEUC-Dirxdwjh.js +0 -1
  136. package/payload/server/public/assets/chunk-QZHKN3VN-Duipo1kI.js +0 -1
  137. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B3kX5SuB.js +0 -1
  138. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D761c7Lr.js +0 -1
  139. package/payload/server/public/assets/clone-BrhFv6Tb.js +0 -1
  140. package/payload/server/public/assets/data-Z84n0KXb.js +0 -1
  141. package/payload/server/public/assets/gitGraph-7Q5UKJZL-BCQAqtLy.js +0 -1
  142. package/payload/server/public/assets/info-OMHHGYJF-qU7hK50T.js +0 -1
  143. package/payload/server/public/assets/infoDiagram-42DDH7IO-KGdcJeTs.js +0 -2
  144. package/payload/server/public/assets/operator-CDQ6eQ5M.js +0 -1
  145. package/payload/server/public/assets/packet-4T2RLAQJ-DiU2yS9m.js +0 -1
  146. package/payload/server/public/assets/page-CjhCRrp2.js +0 -32
  147. package/payload/server/public/assets/pie-ZZUOXDRM-zHUKKlVv.js +0 -1
  148. package/payload/server/public/assets/radar-PYXPWWZC-BUnVoaPg.js +0 -1
  149. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BWmmUwDt.js +0 -1
  150. package/payload/server/public/assets/treeView-SZITEDCU-C3Y-Q52h.js +0 -1
  151. package/payload/server/public/assets/treemap-W4RFUUIX-Dk0qZpAg.js +0 -1
  152. package/payload/server/public/assets/useSubAccountSwitcher-BCOl64pj.js +0 -9
  153. package/payload/server/public/assets/wardley-RL74JXVD-BAWI02OA.js +0 -1
  154. /package/payload/server/public/assets/{_baseFor-brRjpUOX.js → _baseFor-BFYpZGkN.js} +0 -0
  155. /package/payload/server/public/assets/{array-BGFCBI0e.js → array-CYkMkqnU.js} +0 -0
  156. /package/payload/server/public/assets/{cytoscape.esm-TvRJ2tGX.js → cytoscape.esm-DqlHsaog.js} +0 -0
  157. /package/payload/server/public/assets/{defaultLocale-CRZydyG6.js → defaultLocale-Beh6XjaL.js} +0 -0
  158. /package/payload/server/public/assets/{dist-B0CkUodR.js → dist-BMqkacmt.js} +0 -0
  159. /package/payload/server/public/assets/{init-B8gtcn7T.js → init-Rr1s_RiX.js} +0 -0
  160. /package/payload/server/public/assets/{katex-RxgSu_dy.js → katex-pVJiI_rc.js} +0 -0
  161. /package/payload/server/public/assets/{path-DZF-JdEe.js → path-BAQ3hXlG.js} +0 -0
  162. /package/payload/server/public/assets/{preload-helper-CQ36nxok.js → preload-helper-B_l5jfgx.js} +0 -0
  163. /package/payload/server/public/assets/{rough.esm-6CnTHTkH.js → rough.esm-nHaDi0Kw.js} +0 -0
  164. /package/payload/server/public/assets/{src-CR_MU8uy.js → src-CsEKjNXD.js} +0 -0
@@ -33,7 +33,7 @@ import { buildRcChildEnv, reapplyAdminLevers } from './rc-daemon.js';
33
33
  import { runConnectorAuthLogin } from './connector-auth.js';
34
34
  import { isEffortLevel, isNewSessionEffortLevel, isPermissionMode, SONNET_MODEL } from '../../../lib/models/dist/index.js';
35
35
  import { spawnClaudeSession, stopSession, writeInterruptToPty, isLive, onPtyExit, livePtyCount, liveSessionIds, getPtyTrackerForTests, livePidForSession, classifyLiveness, priorExitedCountForSession, PERMISSION_MODES, openFdCount, registerRcSpawnPty, } from './pty-spawner.js';
36
- import { writeScopeRecord, removeScopeRecord } from './scope-record.js';
36
+ import { writeScopeRecord, removeScopeRecord, readAllScopeRecords } from './scope-record.js';
37
37
  import { writeReseatMarker, resolveReseatChain, clearReseatMarker } from './reseat-ledger.js';
38
38
  import { getScopeMainPid, defaultProcessSignals, defaultSystemctlRunner } from './systemd-scope.js';
39
39
  import { readSidecar, updateSidecar, appendBridgeId, writeSidecar } from './session-sidecar.js';
@@ -319,6 +319,22 @@ 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
+ }
322
338
  function resolveRow(watcher, id) {
323
339
  const direct = watcher.getBySessionId(id);
324
340
  if (direct)
@@ -1573,12 +1589,45 @@ export function buildHttpApp(deps) {
1573
1589
  timed(deps.logger, 'POST', `/${id}/stop`, 400, Date.now() - start);
1574
1590
  return c.json({ error: 'invalid-session-id' }, 400);
1575
1591
  }
1592
+ const accountId = c.req.query('accountId') || undefined;
1576
1593
  const row = resolveRow(deps.watcher, id);
1594
+ const sessionId = row?.sessionId ?? id;
1595
+ // Task 1324 — account-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;
1604
+ let scopeTokenFromRecord = null;
1577
1605
  if (!row && !isLive(id)) {
1578
- timed(deps.logger, 'POST', `/${id}/stop`, 404, Date.now() - start);
1579
- return c.json({ error: 'session-not-found' }, 404);
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 {
1627
+ timed(deps.logger, 'POST', `/${id}/stop`, 404, Date.now() - start);
1628
+ return c.json({ error: 'session-not-found' }, 404);
1629
+ }
1580
1630
  }
1581
- const sessionId = row?.sessionId ?? id;
1582
1631
  // Task 455 — snapshot the live pid and prior-exited-count BEFORE
1583
1632
  // stopSession runs (the call mutates module state). When prior history
1584
1633
  // exists, emit a single observability line naming the pid the lookup
@@ -1597,7 +1646,9 @@ export function buildHttpApp(deps) {
1597
1646
  // Task 427 — when the row was reattached after a manager restart,
1598
1647
  // `livePtys` has no entry but `row.scopeUnitToken` is set; pass it
1599
1648
  // so stopSession can take the row-scope fallback path.
1600
- rowScopeUnitToken: row?.scopeUnitToken ?? null,
1649
+ // Task 1324 — for a cross-account session there is no row; the token
1650
+ // comes from the on-disk scope record instead, resolved above.
1651
+ rowScopeUnitToken: row?.scopeUnitToken ?? scopeTokenFromRecord,
1601
1652
  // Task 451 — paired with rowScopeUnitToken so the row-scope branch
1602
1653
  // can post-flight verify the kill via kill(pid, 0).
1603
1654
  rowPid: row?.pid ?? null,
@@ -1607,6 +1658,13 @@ export function buildHttpApp(deps) {
1607
1658
  // formatting (Task 250 contract); this is the single audit line the
1608
1659
  // operator and tests can grep against to confirm which branch ran.
1609
1660
  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
+ }
1610
1668
  // Task 250 — surface scope-stop failures as 500 so the operator sees
1611
1669
  // the End-click fail when systemd cannot stop the unit. The liveptys
1612
1670
  // happy path keeps its original 204 response (Task 250 contract).
@@ -1660,6 +1718,7 @@ export function buildHttpApp(deps) {
1660
1718
  timed(deps.logger, 'DELETE', `/${id}`, 400, Date.now() - start);
1661
1719
  return c.json({ error: 'invalid-session-id' }, 400);
1662
1720
  }
1721
+ const accountId = c.req.query('accountId') || undefined;
1663
1722
  const row = resolveRow(deps.watcher, id);
1664
1723
  const sessionId = row?.sessionId ?? id;
1665
1724
  if (isLive(sessionId)) {
@@ -1669,20 +1728,48 @@ export function buildHttpApp(deps) {
1669
1728
  }
1670
1729
  // Task 260 — purge from BOTH locations: a row may have its JSONL
1671
1730
  // at the top level (live or just-ended) or under archive/ (archived).
1672
- // Task 1298resolve the slug that actually holds the JSONL first;
1673
- // the list (sidebar-sessions.ts) walks every slug, so delete must too.
1674
- // Fall back to spawnCwd's slug only when nothing is found anywhere —
1675
- // hasTop/hasArchived will both be false regardless, so the fallback
1676
- // only affects which (nonexistent) paths appear in the 404 case.
1677
- const resolvedSlug = slugForExistingJsonl(deps.claudeConfigDir, sessionId) ?? projectSlugForCwd(deps.spawnCwd);
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
+ }
1678
1756
  const topJsonl = jsonlPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId);
1679
1757
  const archivedJsonl = jsonlPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId, { archived: true });
1680
1758
  const topSidecar = sidecarPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId);
1681
1759
  const archivedSidecar = sidecarPathForSlug(deps.claudeConfigDir, resolvedSlug, sessionId, { archived: true });
1682
1760
  const hasTop = existsSync(topJsonl);
1683
1761
  const hasArchived = existsSync(archivedJsonl);
1684
- if (!row || (!hasTop && !hasArchived)) {
1685
- deps.logger(`delete-not-found sessionId=${sessionId.slice(0, 8)} reason=not-found-anywhere`);
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
+ }
1686
1773
  timed(deps.logger, 'DELETE', `/${id}`, 404, Date.now() - start);
1687
1774
  return c.json({ error: 'session-not-found' }, 404);
1688
1775
  }