@north-light/cli 0.3.532 → 0.3.534

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 (203) hide show
  1. package/dist/api/client.d.ts +6 -3
  2. package/dist/api/client.js +1 -1
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/canvas.d.ts +2 -0
  6. package/dist/api/dto/crons.d.ts +3 -1
  7. package/dist/builtin-memory/crouter-sdk/release-notes.md +13 -0
  8. package/dist/builtin-memory/northlight-apps/providers/README.md +2 -0
  9. package/dist/builtin-memory/northlight-apps/providers/sms.md +2 -0
  10. package/dist/clients/attach/chrome/inbox-strip.d.ts +6 -1
  11. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  12. package/dist/clients/attach/chrome/roster.js +1 -1
  13. package/dist/clients/attach/session/chrome-refresh.d.ts +12 -3
  14. package/dist/clients/attach/session/chrome-refresh.js +1 -1
  15. package/dist/clients/attach/session/document-links.js +1 -1
  16. package/dist/clients/attach/viewer.js +586 -587
  17. package/dist/commands/api-client.js +3 -3
  18. package/dist/commands/canvas.js +1 -1
  19. package/dist/commands/node/inspect.js +6 -6
  20. package/dist/commands/sys/context/expose.js +2 -2
  21. package/dist/commands/sys/db.d.ts +1 -0
  22. package/dist/commands/sys/db.js +1 -0
  23. package/dist/commands/sys.js +1 -1
  24. package/dist/core/bash-guard.js +9 -3
  25. package/dist/core/canvas/canvas.d.ts +12 -2
  26. package/dist/core/canvas/canvas.js +23 -20
  27. package/dist/core/canvas/daemon-actions.d.ts +0 -3
  28. package/dist/core/canvas/daemon-actions.js +7 -24
  29. package/dist/core/canvas/daemon-owner.d.ts +3 -0
  30. package/dist/core/canvas/daemon-owner.js +1 -6
  31. package/dist/core/canvas/db.d.ts +28 -20
  32. package/dist/core/canvas/db.js +4 -3
  33. package/dist/core/canvas/deliveries.d.ts +5 -0
  34. package/dist/core/canvas/deliveries.js +25 -30
  35. package/dist/core/canvas/export-sqlite.d.ts +14 -0
  36. package/dist/core/canvas/export-sqlite.js +3 -0
  37. package/dist/core/canvas/import-sqlite.d.ts +44 -0
  38. package/dist/core/canvas/import-sqlite.js +7 -0
  39. package/dist/core/canvas/node-tokens.js +3 -3
  40. package/dist/core/canvas/outcome-actions.js +4 -4
  41. package/dist/core/canvas/recovery.js +1 -1
  42. package/dist/core/canvas/schema-pg.sql +1022 -0
  43. package/dist/core/canvas/schema-version.d.ts +4 -0
  44. package/dist/core/canvas/schema-version.js +1 -0
  45. package/dist/core/canvas/sessions.js +3 -3
  46. package/dist/core/canvas/structured-requests.js +2 -2
  47. package/dist/core/canvas/tree.js +6 -6
  48. package/dist/core/canvas/waits.js +1 -1
  49. package/dist/core/feed/inbox.js +1 -1
  50. package/dist/core/feed/messages.js +5 -5
  51. package/dist/core/feed/reports.js +2 -2
  52. package/dist/core/grants/mirror.js +2 -2
  53. package/dist/core/graph/access.js +7 -7
  54. package/dist/core/graph/custom.js +10 -10
  55. package/dist/core/graph/deletion.js +6 -6
  56. package/dist/core/graph/documents.d.ts +1 -1
  57. package/dist/core/graph/documents.js +9 -9
  58. package/dist/core/graph/edges.d.ts +3 -3
  59. package/dist/core/graph/edges.js +3 -1
  60. package/dist/core/graph/events.js +7 -7
  61. package/dist/core/graph/exposures.d.ts +8 -8
  62. package/dist/core/graph/jobs.d.ts +1 -1
  63. package/dist/core/graph/jobs.js +2 -2
  64. package/dist/core/graph/kinds/custom.js +1 -1
  65. package/dist/core/graph/kinds/document.js +4 -4
  66. package/dist/core/graph/kinds/dto.js +1 -1
  67. package/dist/core/graph/kinds/job.js +2 -2
  68. package/dist/core/graph/kinds/kind.d.ts +2 -2
  69. package/dist/core/graph/kinds/kind.js +1 -1
  70. package/dist/core/graph/kinds/live-read.d.ts +5 -0
  71. package/dist/core/graph/kinds/live-read.js +1 -0
  72. package/dist/core/graph/kinds/node.js +5 -5
  73. package/dist/core/graph/kinds/owner.js +2 -2
  74. package/dist/core/graph/names.js +3 -3
  75. package/dist/core/graph/objects.d.ts +5 -5
  76. package/dist/core/graph/objects.js +10 -10
  77. package/dist/core/graph/package-docs.js +6 -5
  78. package/dist/core/graph/reader.d.ts +1 -1
  79. package/dist/core/graph/reader.js +2 -2
  80. package/dist/core/graph/receivers.js +4 -5
  81. package/dist/core/graph/repo-sync/exchange.js +2 -2
  82. package/dist/core/graph/repo-sync/repos.js +3 -3
  83. package/dist/core/graph/repo-sync/sync.js +1 -1
  84. package/dist/core/graph/rules.d.ts +3 -4
  85. package/dist/core/graph/rules.js +3 -3
  86. package/dist/core/graph/spaces/app.js +1 -1
  87. package/dist/core/graph/spaces/index.d.ts +1 -1
  88. package/dist/core/graph/spaces/index.js +1 -1
  89. package/dist/core/graph/spaces/own-memory.js +1 -1
  90. package/dist/core/graph/spaces/person.js +3 -3
  91. package/dist/core/graph/spaces/repo.d.ts +1 -1
  92. package/dist/core/graph/spaces/repo.js +1 -1
  93. package/dist/core/graph/types.d.ts +4 -3
  94. package/dist/core/graph/watches.d.ts +2 -2
  95. package/dist/core/graph/watches.js +17 -17
  96. package/dist/core/human/page-schema.js +5 -4
  97. package/dist/core/human/requests.d.ts +1 -1
  98. package/dist/core/human/requests.js +20 -23
  99. package/dist/core/peer/ingest.js +1 -1
  100. package/dist/core/peer/receiver.js +1 -1
  101. package/dist/core/peer/stubs.js +1 -1
  102. package/dist/core/providers/receipts.js +3 -2
  103. package/dist/core/review/comments.js +5 -4
  104. package/dist/core/runs/activity.js +4 -5
  105. package/dist/core/runs/confinement.d.ts +1 -1
  106. package/dist/core/runs/confinement.js +2 -2
  107. package/dist/core/runs/events.d.ts +1 -1
  108. package/dist/core/runs/events.js +5 -5
  109. package/dist/core/runs/operations.js +6 -4
  110. package/dist/core/runs/questions.d.ts +2 -0
  111. package/dist/core/runs/questions.js +1 -1
  112. package/dist/core/runtime/close.d.ts +3 -0
  113. package/dist/core/runtime/close.js +1 -1
  114. package/dist/core/runtime/host.d.ts +5 -1
  115. package/dist/core/runtime/host.js +3 -3
  116. package/dist/core/runtime/launch.js +2 -2
  117. package/dist/core/runtime/ledger.js +3 -3
  118. package/dist/core/runtime/lifecycle.d.ts +9 -0
  119. package/dist/core/runtime/lifecycle.js +2 -2
  120. package/dist/core/runtime/nodes.d.ts +1 -1
  121. package/dist/core/runtime/nodes.js +1 -1
  122. package/dist/core/runtime/roadmap.js +1 -1
  123. package/dist/core/spaces/stop.d.ts +1 -0
  124. package/dist/core/spaces/stop.js +2 -2
  125. package/dist/core/statements.d.ts +17 -0
  126. package/dist/core/statements.js +2 -0
  127. package/dist/core/substrate/delivery/corpus.js +3 -3
  128. package/dist/core/substrate/delivery/deliver.js +5 -5
  129. package/dist/core/substrate/delivery/listings.js +1 -1
  130. package/dist/core/substrate/delivery/match.d.ts +2 -2
  131. package/dist/core/substrate/delivery/match.js +1 -1
  132. package/dist/core/substrate/delivery/plan.js +3 -3
  133. package/dist/core/substrate/delivery/render-boot.js +5 -5
  134. package/dist/core/substrate/delivery/render-event.js +6 -6
  135. package/dist/core/usage/ledger.js +8 -8
  136. package/dist/core/worktree.js +8 -8
  137. package/dist/daemon/api/bridge.js +4 -4
  138. package/dist/daemon/api/document-listener.js +1 -1
  139. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  140. package/dist/daemon/api/handlers/canvas.js +1 -1
  141. package/dist/daemon/api/handlers/crons.js +1 -1
  142. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  143. package/dist/daemon/api/handlers/docs.js +1 -1
  144. package/dist/daemon/api/handlers/inbox.js +1 -1
  145. package/dist/daemon/api/handlers/memory.js +7 -7
  146. package/dist/daemon/api/handlers/messages.js +1 -1
  147. package/dist/daemon/api/handlers/nodes.js +1 -1
  148. package/dist/daemon/api/handlers/objects.js +3 -3
  149. package/dist/daemon/api/handlers/questions.js +1 -1
  150. package/dist/daemon/api/handlers/reviews.js +1 -1
  151. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  152. package/dist/daemon/api/reader.js +1 -1
  153. package/dist/daemon/broker-signals/bus.d.ts +14 -6
  154. package/dist/daemon/broker-signals/bus.js +1 -10
  155. package/dist/daemon/cron/ended.d.ts +3 -0
  156. package/dist/daemon/cron/ended.js +2 -2
  157. package/dist/daemon/cron/narrowed.d.ts +5 -0
  158. package/dist/daemon/cron/narrowed.js +2 -0
  159. package/dist/daemon/cron/settle.js +1 -1
  160. package/dist/daemon/crtrd-cli.js +1 -1
  161. package/dist/daemon/crtrd.js +12 -11
  162. package/dist/daemon/due.js +1 -1
  163. package/dist/daemon/export-sqlite-run.d.ts +1 -0
  164. package/dist/daemon/export-sqlite-run.js +4 -0
  165. package/dist/daemon/fleet.d.ts +1 -0
  166. package/dist/daemon/fleet.js +3 -3
  167. package/dist/daemon/human/settle.js +1 -1
  168. package/dist/daemon/manage.d.ts +10 -0
  169. package/dist/daemon/manage.js +3 -2
  170. package/dist/daemon/postgres/binary.d.ts +17 -0
  171. package/dist/daemon/postgres/binary.js +2 -0
  172. package/dist/daemon/postgres/cluster.d.ts +37 -0
  173. package/dist/daemon/postgres/cluster.js +6 -0
  174. package/dist/daemon/postgres/index.d.ts +2 -0
  175. package/dist/daemon/postgres/index.js +1 -0
  176. package/dist/daemon/postgres/pins.d.ts +7 -0
  177. package/dist/daemon/postgres/pins.js +1 -0
  178. package/dist/daemon/postgres/supervisor.d.ts +95 -0
  179. package/dist/daemon/postgres/supervisor.js +2 -0
  180. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  181. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  182. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +7 -3
  183. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  184. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  185. package/dist/daemon/reconcilers/storage-maintenance.d.ts +0 -6
  186. package/dist/daemon/reconcilers/storage-maintenance.js +1 -8
  187. package/dist/daemon/runs/observer.js +5 -4
  188. package/dist/migrations/004-canvas-documents/index.js +1 -1
  189. package/dist/pi-extensions/canvas-doc-substrate.d.ts +2 -0
  190. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  191. package/dist/pi-extensions/envelope-merge.d.ts +3 -2
  192. package/dist/pi-extensions/envelope-merge.js +9 -8
  193. package/dist/shared/env.d.ts +3 -0
  194. package/dist/shared/env.js +2 -2
  195. package/docs/apps/providers/README.md +2 -0
  196. package/docs/apps/providers/sms.md +2 -0
  197. package/docs/public-api.md +11 -2
  198. package/docs/sdk/release-notes.md +13 -0
  199. package/package.json +6 -6
  200. package/packages/crouter-identity/package.json +1 -1
  201. package/runtime.lock.json +13 -26
  202. package/scripts/install-runtime.mjs +53 -3
  203. package/scripts/lib/isolation-env.mjs +3 -1
@@ -1,4 +1,4 @@
1
- var m=Object.defineProperty;var a=(r,t)=>m(r,"name",{value:t,configurable:!0});import{closeSync as w,fstatSync as b,openSync as _,readSync as g}from"node:fs";import{join as S}from"node:path";import{gunzipSync as y}from"node:zlib";import{ApiError as l}from"../api/index.js";import{localClient as d}from"../api/node-transport.js";import{apiErrorToCliError as v}from"../core/io.js";import{autostartDisabled as C,daemonAutostartStartupFailure as N,ensureDaemon as T}from"../daemon/manage.js";import{DAEMON_STARTUP_WINDOW_MS as M}from"../daemon/startup-policy.js";import{readState as A}from"../core/config.js";import{resolveRemoteCanvasTarget as O}from"../core/remote-canvas-target.js";import{RemoteCanvasSource as R}from"../core/canvas/remote-canvas-source.js";import{crtrHome as I}from"../core/canvas/paths.js";import{isSandboxedNode as x}from"../shared/env.js";import{ownerOnly as D}from"../core/errors.js";function u(r){return{...r,fault:r.fault??null}}a(u,"withRowFault");function F(r,t){throw r instanceof l?v(r,t):r}a(F,"rethrowAsCliError");async function Z(r){try{return await h().getNode(r)}catch(t){if(t instanceof l&&t.status===404)return null;F(t)}}a(Z,"getNodeOrNull");const E=4096,L=20;function k(){let r;try{r=_(S(I(),"crtrd.log"),"r");const{size:t}=b(r),s=Math.max(0,t-E),n=t-s;if(n<=0)return;const e=Buffer.alloc(n);g(r,e,0,n,s);const o=e.toString("utf8").split(`
2
- `).filter(c=>c.trim()!=="").slice(-L).join(`
1
+ var b=Object.defineProperty;var a=(r,t)=>b(r,"name",{value:t,configurable:!0});import{closeSync as _,fstatSync as S,openSync as g,readSync as v}from"node:fs";import{join as y}from"node:path";import{gunzipSync as C}from"node:zlib";import{ApiError as l}from"../api/index.js";import{localClient as d}from"../api/node-transport.js";import{apiErrorToCliError as N}from"../core/io.js";import{autostartDisabled as h,daemonAutostartStartupFailure as M,ensureDaemon as T}from"../daemon/manage.js";import{DAEMON_STARTUP_WINDOW_MS as p}from"../daemon/startup-policy.js";import{readState as A}from"../core/config.js";import{resolveRemoteCanvasTarget as O}from"../core/remote-canvas-target.js";import{RemoteCanvasSource as R}from"../core/canvas/remote-canvas-source.js";import{crtrHome as I}from"../core/canvas/paths.js";import{envTestNodeSocketWindowMs as x,isSandboxedNode as D}from"../shared/env.js";import{ownerOnly as F}from"../core/errors.js";function u(r){return{...r,fault:r.fault??null}}a(u,"withRowFault");function E(r,t){throw r instanceof l?N(r,t):r}a(E,"rethrowAsCliError");async function tt(r){try{return await m().getNode(r)}catch(t){if(t instanceof l&&t.status===404)return null;E(t)}}a(tt,"getNodeOrNull");const L=4096,k=20;function W(){let r;try{r=g(y(I(),"crtrd.log"),"r");const{size:t}=S(r),s=Math.max(0,t-L),n=t-s;if(n<=0)return;const e=Buffer.alloc(n);v(r,e,0,n,s);const o=e.toString("utf8").split(`
2
+ `).filter(c=>c.trim()!=="").slice(-k).join(`
3
3
  `).trim();return o===""?void 0:`crtrd.log (tail):
4
- ${o}`}catch{return}finally{if(r!==void 0)try{w(r)}catch{}}}a(k,"readColdStartDiagnostic");function h(r){return process.env.CRTR_API_SOCKET?d({autostart:!1,...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{}}):C()?d({autostart:!1,...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{}}):d({...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{},onColdSocket:a(async()=>{T()},"onColdSocket"),coldStartDiagnostic:k,coldStartFailure:N,coldStartPollWindowMs:M})}a(h,"cliClient");const B=2e3;class p{static{a(this,"ApiCanvasSource")}client;rosterCache=null;rosterInFlight=null;constructor(t=h()){this.client=t}async roster(){const t=Date.now();return this.rosterCache!==null&&t-this.rosterCache.at<B?this.rosterCache.index:this.rosterInFlight!==null?this.rosterInFlight:(this.rosterInFlight=this.client.canvasRoster().then(s=>{const n={snapshot:s,subscriptions:new Map,subscribers:new Map};for(const e of s.edges){const i={node_id:e.to_id,active:e.active,created:e.created},o={node_id:e.from_id,active:e.active,created:e.created},c=n.subscriptions.get(e.from_id);c===void 0?n.subscriptions.set(e.from_id,[i]):c.push(i);const f=n.subscribers.get(e.to_id);f===void 0?n.subscribers.set(e.to_id,[o]):f.push(o)}return this.rosterCache={at:Date.now(),index:n},n}).finally(()=>{this.rosterInFlight=null}),this.rosterInFlight)}async orNull(t){try{return await t()}catch(s){if(s instanceof l&&s.status===404)return null;throw s}}async getNode(t){const s=await this.orNull(()=>this.client.getNode(t));return s===null?null:u(s)}async getRow(t){const s=await this.orNull(()=>this.client.getNode(t));return s===null?null:u(s)}async listNodes(t){const s=t?.status;let n;if(Array.isArray(s)){const e=new Set(s);n=(await this.client.listNodes()).filter(o=>e.has(o.status))}else s!==void 0?n=await this.client.listNodes({status:s}):n=await this.client.listNodes();return n.map(e=>u(e))}async browseSnapshot(){const t=await this.client.canvasBrowseCompressed(),s=JSON.parse(y(t).toString("utf8")),n={subscriptions:new Map,subscribers:new Map};for(const e of s.edges){const i=n.subscriptions.get(e.from_id)??[];i.push({node_id:e.to_id,active:e.active,created:e.created}),n.subscriptions.set(e.from_id,i);const o=n.subscribers.get(e.to_id)??[];o.push({node_id:e.from_id,active:e.active,created:e.created}),n.subscribers.set(e.to_id,o)}return this.rosterCache={at:Date.now(),index:n},s.nodes.map(e=>u(e))}async panelRoster(){const t=await this.roster();return t.snapshot!==void 0?t.snapshot:(this.rosterCache=null,(await this.roster()).snapshot)}async subscriptionsOf(t){return this.roster().then(s=>s.subscriptions.get(t)??[])}async subscribersOf(t){return this.roster().then(s=>s.subscribers.get(t)??[])}async view(t){const s=new Set([t]),n=[],e=(await this.subscriptionsOf(t)).map(i=>i.node_id);for(;e.length>0;){const i=e.shift();if(!s.has(i)){s.add(i),n.push(i);for(const o of await this.subscriptionsOf(i))s.has(o.node_id)||e.push(o.node_id)}}return n}async ticketCountsForNodes(t){return(await this.client.attentionCounts([...t])).counts}async ticketCountsForView(t){return this.ticketCountsForNodes([t,...await this.view(t)])}async newestReport(t){return(await this.client.getReports(t,{limit:1}))[0]??null}async hasActiveLiveSubscription(t){const s=(await this.subscriptionsOf(t)).filter(n=>n.active);for(const n of s){const e=await this.getRow(n.node_id);if(e&&(e.status==="active"||e.status==="idle"))return!0}return!1}}function tt(r,t=x()){const s=r?.scope??"user";if(t){if(r?.canvasName!==void 0)throw D("--canvas selects the person's remote canvas targets, which an app's node cannot reach","Omit --canvas; this node reads its own runtime's canvas.");return new p}const n=r?.canvasName??A(s).activeCanvas??null;if(!n)return new p;const{previewEndpoint:e,relayToken:i}=O(n,s);return new R(e,i)}a(tt,"cliCanvasSource");export{p as ApiCanvasSource,E as COLD_START_DIAGNOSTIC_TAIL_BYTES,tt as cliCanvasSource,h as cliClient,Z as getNodeOrNull,k as readColdStartDiagnostic,F as rethrowAsCliError};
4
+ ${o}`}catch{return}finally{if(r!==void 0)try{_(r)}catch{}}}a(W,"readColdStartDiagnostic");function m(r){return process.env.CRTR_API_SOCKET?d({autostart:!1,coldStartPollWindowMs:(h()?x():void 0)??p,...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{}}):h()?d({autostart:!1,...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{}}):d({...r?.timeoutMs!==void 0?{timeoutMs:r.timeoutMs}:{},onColdSocket:a(async()=>{T()},"onColdSocket"),coldStartDiagnostic:W,coldStartFailure:M,coldStartPollWindowMs:p})}a(m,"cliClient");const P=2e3;class w{static{a(this,"ApiCanvasSource")}client;rosterCache=null;rosterInFlight=null;constructor(t=m()){this.client=t}async roster(){const t=Date.now();return this.rosterCache!==null&&t-this.rosterCache.at<P?this.rosterCache.index:this.rosterInFlight!==null?this.rosterInFlight:(this.rosterInFlight=this.client.canvasRoster().then(s=>{const n={snapshot:s,subscriptions:new Map,subscribers:new Map};for(const e of s.edges){const i={node_id:e.to_id,active:e.active,created:e.created},o={node_id:e.from_id,active:e.active,created:e.created},c=n.subscriptions.get(e.from_id);c===void 0?n.subscriptions.set(e.from_id,[i]):c.push(i);const f=n.subscribers.get(e.to_id);f===void 0?n.subscribers.set(e.to_id,[o]):f.push(o)}return this.rosterCache={at:Date.now(),index:n},n}).finally(()=>{this.rosterInFlight=null}),this.rosterInFlight)}async orNull(t){try{return await t()}catch(s){if(s instanceof l&&s.status===404)return null;throw s}}async getNode(t){const s=await this.orNull(()=>this.client.getNode(t));return s===null?null:u(s)}async getRow(t){const s=await this.orNull(()=>this.client.getNode(t));return s===null?null:u(s)}async listNodes(t){const s=t?.status;let n;if(Array.isArray(s)){const e=new Set(s);n=(await this.client.listNodes()).filter(o=>e.has(o.status))}else s!==void 0?n=await this.client.listNodes({status:s}):n=await this.client.listNodes();return n.map(e=>u(e))}async browseSnapshot(){const t=await this.client.canvasBrowseCompressed(),s=JSON.parse(C(t).toString("utf8")),n={subscriptions:new Map,subscribers:new Map};for(const e of s.edges){const i=n.subscriptions.get(e.from_id)??[];i.push({node_id:e.to_id,active:e.active,created:e.created}),n.subscriptions.set(e.from_id,i);const o=n.subscribers.get(e.to_id)??[];o.push({node_id:e.from_id,active:e.active,created:e.created}),n.subscribers.set(e.to_id,o)}return this.rosterCache={at:Date.now(),index:n},s.nodes.map(e=>u(e))}async panelRoster(){const t=await this.roster();return t.snapshot!==void 0?t.snapshot:(this.rosterCache=null,(await this.roster()).snapshot)}async subscriptionsOf(t){return this.roster().then(s=>s.subscriptions.get(t)??[])}async subscribersOf(t){return this.roster().then(s=>s.subscribers.get(t)??[])}async view(t){const s=new Set([t]),n=[],e=(await this.subscriptionsOf(t)).map(i=>i.node_id);for(;e.length>0;){const i=e.shift();if(!s.has(i)){s.add(i),n.push(i);for(const o of await this.subscriptionsOf(i))s.has(o.node_id)||e.push(o.node_id)}}return n}async ticketCountsForNodes(t){return(await this.client.attentionCounts([...t])).counts}async ticketCountsForView(t){return this.ticketCountsForNodes([t,...await this.view(t)])}async newestReport(t){return(await this.client.getReports(t,{limit:1}))[0]??null}async hasActiveLiveSubscription(t){const s=(await this.subscriptionsOf(t)).filter(n=>n.active);for(const n of s){const e=await this.getRow(n.node_id);if(e&&(e.status==="active"||e.status==="idle"))return!0}return!1}}function et(r,t=D()){const s=r?.scope??"user";if(t){if(r?.canvasName!==void 0)throw F("--canvas selects the person's remote canvas targets, which an app's node cannot reach","Omit --canvas; this node reads its own runtime's canvas.");return new w}const n=r?.canvasName??A(s).activeCanvas??null;if(!n)return new w;const{previewEndpoint:e,relayToken:i}=O(n,s);return new R(e,i)}a(et,"cliCanvasSource");export{w as ApiCanvasSource,L as COLD_START_DIAGNOSTIC_TAIL_BYTES,et as cliCanvasSource,m as cliClient,tt as getNodeOrNull,W as readColdStartDiagnostic,E as rethrowAsCliError};
@@ -1 +1 @@
1
- var r=Object.defineProperty;var e=(o,t)=>r(o,"name",{value:t,configurable:!0});import{defineBranch as a}from"../core/command.js";import{dashboardLeaf as n}from"./dashboard.js";import{canvasSnapshotLeaf as s}from"./canvas-snapshot.js";import{canvasRosterLeaf as i}from"./canvas-roster.js";import{browseLeaf as d}from"./canvas-browse.js";import{reviveLeaf as c}from"./revive.js";import{attentionBranch as h}from"./attention.js";import{chordLeaf as m}from"./chord.js";import{canvasPruneLeaf as p}from"./canvas-prune.js";import{historyBranch as u}from"./canvas-history.js";import{issueNewLeaf as f}from"./canvas-issue.js";import{canvasConfigBranch as l}from"./canvas-config.js";import{canvasUseLeaf as g}from"./canvas-use.js";import{readLeaf as w}from"./canvas/read.js";import{listLeaf as v}from"./canvas/list.js";import{searchLeaf as b}from"./canvas/search.js";import{watchLeaf as y}from"./canvas/watch.js";import{unwatchLeaf as L}from"./canvas/unwatch.js";import{edgesLeaf as k}from"./canvas/edges.js";import{analyticsLeaf as j}from"./canvas-analytics.js";const x=a({name:"issue",description:"capture a quick todo/idea/bug into a GitHub issue (or a .todos/ note)",whenToUse:"the alt+c \u2192 i chord uses this; capture a passing thought without leaving your pane",tier:"hidden",help:{name:"canvas issue",summary:"capture a quick todo/idea/bug into a GitHub issue",model:"Quick brain-dump capture, bound to the alt+c \u2192 i \u2192 (idea|bug) prefix chord. `new` reads a free-text note, auto-generates the title via a headless pi call, and files it with `gh issue create --label <type>` when the pane\u2019s cwd is a GitHub repo, else writes `<git-root>/.todos/<slug>.md`. Meant for the chord/popup, not hand-running."},children:[f]});function J(){return a({name:"canvas",rootEntry:{concept:"every object in the agent graph \u2014 documents, nodes, jobs and their owners \u2014 read, listed, searched and watched by name, plus the whole-graph views: render it, see who is blocked, mass-revive disconnected nodes",desc:"read, list, search and watch objects; whole-graph views and supervision",useWhen:"reading a document, node or job by name, finding one you cannot name, watching an object for changes, surveying the full graph, finding blocked agents, or mass-reviving every disconnected node; documents are written with `crtr doc`; run `crtr canvas -h`"},help:{name:"canvas",summary:"read, find and watch objects; observe and supervise the whole agent graph",model:"Every document, node, bash job and owner (person, app, repo, plugin, profile) is an object with an id and a name, and the same verbs work on all of them. `read` returns one object by name or id and makes you a watcher of it; `list` filters objects by type, kind, owner, privacy or name prefix; `search` finds them by text; `edges` shows what an object links to, who acted on it and who watches it; `watch`/`unwatch` add or remove your watch without reading. `list`, `search` and `edges` record nothing. Documents are written, edited and moved with `crtr doc`, and pointed at as `[[name]]`. Canvas-wide views, distinct from per-node work (`node`) and a node's own spine write verb (`push`): `dashboard` renders the subscription forest as a tree; `browse` opens an interactive full-screen navigator over the whole canvas and resumes the chosen node; `attention` aggregates pending replies from the user across the graph; `revive --all` mass-reconnects every disconnected node (bringing back ONE named node is `node lifecycle revive <id>` instead); `history` searches past node conversations; `prune` bounds growth by deleting terminal nodes past a TTL; `analytics` opens the read-only Analytics page (graph sizes, agent time, document reads, API-price estimate) for a person. `config` registers/lists remote canvas targets (preview endpoint + relay token); `use` switches remote-capable read commands such as `node inspect` onto a configured target or back to local."},children:[w,v,b,y,L,k,n,s,i,d,h,c,u,m,x,p,l,g,j]})}e(J,"registerCanvas");export{x as issueBranch,J as registerCanvas};
1
+ var r=Object.defineProperty;var e=(t,o)=>r(t,"name",{value:o,configurable:!0});import{defineBranch as a}from"../core/command.js";import{dashboardLeaf as n}from"./dashboard.js";import{canvasSnapshotLeaf as s}from"./canvas-snapshot.js";import{canvasRosterLeaf as i}from"./canvas-roster.js";import{browseLeaf as d}from"./canvas-browse.js";import{reviveLeaf as c}from"./revive.js";import{attentionBranch as h}from"./attention.js";import{chordLeaf as m}from"./chord.js";import{canvasPruneLeaf as p}from"./canvas-prune.js";import{historyBranch as u}from"./canvas-history.js";import{issueNewLeaf as f}from"./canvas-issue.js";import{canvasConfigBranch as l}from"./canvas-config.js";import{canvasUseLeaf as g}from"./canvas-use.js";import{readLeaf as w}from"./canvas/read.js";import{listLeaf as v}from"./canvas/list.js";import{searchLeaf as b}from"./canvas/search.js";import{watchLeaf as y}from"./canvas/watch.js";import{unwatchLeaf as L}from"./canvas/unwatch.js";import{edgesLeaf as k}from"./canvas/edges.js";import{analyticsLeaf as j}from"./canvas-analytics.js";const x=a({name:"issue",description:"capture a quick todo/idea/bug into a GitHub issue (or a .todos/ note)",whenToUse:"the alt+c \u2192 i chord uses this; capture a passing thought without leaving your pane",tier:"hidden",help:{name:"canvas issue",summary:"capture a quick todo/idea/bug into a GitHub issue",model:"Quick brain-dump capture, bound to the alt+c \u2192 i \u2192 (idea|bug) prefix chord. `new` reads a free-text note, auto-generates the title via a headless pi call, and files it with `gh issue create --label <type>` when the pane\u2019s cwd is a GitHub repo, else writes `<git-root>/.todos/<slug>.md`. Meant for the chord/popup, not hand-running."},children:[f]});function J(){return a({name:"canvas",rootEntry:{concept:"every object in the agent graph \u2014 documents, nodes, jobs and their owners \u2014 read, listed, searched and watched by name, plus the whole-graph views: `dashboard` prints the subscription tree once, `browse` is the interactive navigator, `attention` shows who is blocked, `revive --all` mass-revives disconnected nodes",desc:"read, list, search and watch objects; whole-graph views and supervision",useWhen:"reading a document, node or job by name, finding one you cannot name, watching an object for changes, surveying the full graph, finding blocked agents, or mass-reviving every disconnected node; documents are written with `crtr doc`; run `crtr canvas -h`"},help:{name:"canvas",summary:"read, find and watch objects; observe and supervise the whole agent graph",model:"Every document, node, bash job and owner (person, app, repo, plugin, profile) is an object with an id and a name, and the same verbs work on all of them. `read` returns one object by name or id and makes you a watcher of it; `list` filters objects by type, kind, owner, privacy or name prefix; `search` finds them by text; `edges` shows what an object links to, who acted on it and who watches it; `watch`/`unwatch` add or remove your watch without reading. `list`, `search` and `edges` record nothing. Documents are written, edited and moved with `crtr doc`, and pointed at as `[[name]]`. Canvas-wide views, distinct from per-node work (`node`) and a node's own spine write verb (`push`): `dashboard` renders the subscription forest as a tree; `browse` opens an interactive full-screen navigator over the whole canvas and resumes the chosen node; `attention` aggregates pending replies from the user across the graph; `revive --all` mass-reconnects every disconnected node (bringing back ONE named node is `node lifecycle revive <id>` instead); `history` searches past node conversations; `prune` bounds growth by deleting terminal nodes past a TTL; `analytics` opens the read-only Analytics page (graph sizes, agent time, document reads, API-price estimate) for a person. `config` registers/lists remote canvas targets (preview endpoint + relay token); `use` switches remote-capable read commands such as `node inspect` onto a configured target or back to local."},children:[w,v,b,y,L,k,n,s,i,d,h,c,u,m,x,p,l,g,j]})}e(J,"registerCanvas");export{x as issueBranch,J as registerCanvas};
@@ -1,12 +1,12 @@
1
- var R=Object.defineProperty;var h=(n,e)=>R(n,"name",{value:e,configurable:!0});import{defineBranch as P,defineLeaf as k}from"../../core/command.js";import{InputError as y}from"../../core/io.js";import{requireScope as I}from"../../core/errors.js";import{isPidAlive as O}from"../../core/canvas/pid.js";import{fullName as $}from"../../core/canvas/labels.js";import{fuzzyMatch as F}from"../../core/tui/fuzzy.js";import{nodeSnapshotLeaf as L}from"../node-snapshot.js";import{nodeTranscriptLeaf as A}from"../node-transcript.js";import{nodeContextLeaf as C}from"../node-context.js";import{cliClient as _,cliCanvasSource as x,rethrowAsCliError as w}from"../api-client.js";import{RemoteCanvasSource as q}from"../../core/canvas/remote-canvas-source.js";import{kindsStateBlock as U,profilesStateBlock as D,resolveProfileViaDaemon as z}from"../profile/daemon-profiles.js";import{focusViewer as E,nodeInPane as B}from"../surface/node/placement.js";const M=k({name:"list",description:"list nodes on the canvas",whenToUse:"you want a flat roster of the nodes on the canvas, sliced by displayed name, status, kind, mode, lifecycle, profile, cwd, and graph scope (--under a node, for that node plus its subscription descendants). The filters AND together. Use `node inspect show` instead to drill into one node and its spine neighbors, `canvas dashboard` for the tree shape, and `canvas attention` to find nodes blocked on the user",help:{name:"node inspect list",summary:"list nodes on the canvas, filtered by any combination of attribute slices and a graph-scope (--under) that AND together",params:[{kind:"flag",name:"status",type:"string",required:!1,constraint:"Filter status (comma-separated for several; accepted values: active, idle, done, dead, canceled). NOTE: `active` means the engine process is live (never closed), NOT that the node is generating right now \u2014 an active node is usually dormant between turns. To tell working-vs-idle, check the pi session-file mtime or CPU, not status."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Filter by persona kind (comma-separated for several). The <kinds> list below names every top-level installable kind; a registered sub-kind filters too by exact path even though it is not listed."},{kind:"flag",name:"mode",type:"string",required:!1,constraint:"Filter by mode (comma-separated for several; accepted values: base, orchestrator)."},{kind:"flag",name:"lifecycle",type:"string",required:!1,constraint:"Filter by lifecycle (comma-separated for several; accepted values: terminal, resident)."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Filter by profile. On the local canvas, accepts a profile id or manifest name from the <profiles> list below, or a close-enough name that resolves to the nearest profile. Against a remote canvas, pass the exact profile id carried by its node rows."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Filter by the displayed node label (handle plus generated description) with the canvas browser\u2019s case-insensitive fuzzy subsequence match."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Filter to nodes pinned to this exact cwd (absolute path). Roster is canvas-wide (all cwds) by default."},{kind:"flag",name:"under",type:"string",required:!1,constraint:'Graph scope: restrict to this node and its subscription descendants (the sub-DAG reachable downward \u2014 its reports, theirs, \u2026). This is "one initiative / my subtree". ANDs with every attribute filter above, narrowing any of them to this subtree.'},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"nodes",type:"object[]",required:!0,constraint:"Rows include {node_id, name, kind, mode, lifecycle, status, cwd, profile_id, parent, created}. `name` is the displayed node label searched by --name and shown in canvas views. `profile_id` is the stable profile-directory id (null only for historical no-profile nodes)."}],outputKind:"object",effects:["Read-only: lists nodes through the daemon API."]},helpState:{leaf:h(async()=>(await Promise.all([U(),D()])).join(`
2
- `),"leaf")},run:h(async n=>{const e=h(r=>{const g=n[r];return g!==void 0&&g!==""?g.split(",").map(v=>v.trim()).filter(v=>v!==""):void 0},"csv"),o=e("status"),t=e("kind"),u=e("mode"),d=e("lifecycle"),m=n.profile,c=n.name,l=n.cwd,i=n.under,p=x({canvasName:n.canvas}),a=p instanceof q?m:m===void 0?void 0:(await z(m)).id;let s;if(i!==void 0&&i!==""){if(await p.getNode(i).catch(w)===null)throw new y({error:"not_found",message:`no node: ${i}`,next:"List nodes with `crtr node inspect list`, then pass a real id to --under."});s=new Set([i,...await p.view(i)])}return{nodes:(await p.listNodes(o!==void 0?{status:o}:void 0).catch(w)).filter(r=>!(s!==void 0&&!s.has(r.node_id)||t!==void 0&&!t.includes(r.kind)||u!==void 0&&!u.includes(r.mode)||d!==void 0&&!d.includes(r.lifecycle)||a!==void 0&&r.profile_id!==a||l!==void 0&&l!==""&&r.cwd!==l)).map(r=>({...r,name:$(r)})).filter(r=>c===void 0||c===""||F(c,r.name))}},"run")}),S=new WeakSet;async function j(n,e){const o=await n.getNode(e.node_id).catch(w);return{node_id:e.node_id,name:o?$(o):"(missing)",kind:o?.kind??"?",status:o?o.intent?`${o.status}/${o.intent}`:o.status:"?",active:e.active}}h(j,"enrichNeighbor");const K=k({name:"show",description:"show a node + its spine neighbors and drill-in pointers",whenToUse:"you want one node in depth \u2014 the debugging entrypoint: a glanceable meta slice, named spine neighbors, a pending-cron count, and exact drill-in paths. Use `node inspect list` for the flat roster or `canvas dashboard` for the whole-tree shape",help:{name:"node inspect show",summary:"show a node in depth \u2014 meta slice, named neighbors, pending-cron count, and drill-in pointers",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id."},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"node",type:"object",required:!0,constraint:"The full node meta (system prompt + every telemetry field). The render surfaces a glanceable slice; `--json` carries the complete dump."},{name:"fault",type:"object",required:!0,constraint:"The active runtime fault projection, or null: {link, kind, retry: {disposition}, since}."},{name:"reports",type:"object[]",required:!0,constraint:"Who this node subscribes to (its reports/down), each enriched with {node_id, name, kind, status, active} \u2014 these are typically its spawned children."},{name:"managers",type:"object[]",required:!0,constraint:"Who subscribes to this node (its managers/up), same enriched shape."},{name:"pending_crons",type:"number",required:!0,constraint:"How many pending crons were created by this node. Inspect with `crtr cron list`."},{name:"paths",type:"object",required:!0,constraint:"Resolved on-disk locations: {context_dir, session_file} \u2014 read these directly to debug. Reports are documents: `crtr canvas read <node>/reports/<name>`."},{name:"follow_up",type:"string",required:!0,constraint:"The concrete next commands to drill deeper."}],outputKind:"object",effects:["Read-only: reads the node, its edges, and pending crons through crtrd."],preview:{suppressOutput:!0}},run:h(async n=>{const e=n.node,o=n.canvas,t=x({canvasName:o});if(t instanceof q){const s=await t.rawShow(e);if(s===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list --canvas <name>`."});const f={...s};return S.add(f),f}const u=await t.getNode(e).catch(s=>w(s,"List nodes with `crtr node inspect list`."));if(u===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list`."});const d=u,m=_(),c=await Promise.all((await t.subscriptionsOf(e)).map(s=>j(t,s))),l=await Promise.all((await t.subscribersOf(e)).map(s=>j(t,s))),i=(await m.listCrons().catch(w)).filter(s=>s.created_by===e).length,p={context_dir:d.paths.context_dir,...d.pi_session_file!==void 0?{session_file:d.pi_session_file}:{}},a=[];return a.push(`List the documents it owns (reports, plans, notes): \`crtr canvas list --owner ${e}\`.`),a.push(`Browse its context dir (and its subscriptions') in nvim: \`crtr node inspect context ${e}\`.`),p.session_file&&a.push(`Read the raw conversation transcript: ${p.session_file}`),a.push(`On-disk context dir (ls/read directly): ${p.context_dir}`),i>0&&a.push(`It created ${i} pending cron(s): \`crtr cron list\`.`),c.length>0&&a.push(`Drill into a child/report: \`crtr node inspect show <node_id>\` (${c.map(s=>s.node_id).join(", ")}).`),a.push(`Full machine dump (system prompt + all telemetry): \`crtr --json node inspect show ${e}\`.`),{node:d,fault:d.fault??null,reports:c,managers:l,pending_crons:i,paths:p,follow_up:a.join(`
3
- `)}},"run"),render:h(n=>{const e=n.node,o=String(e.node_id),t=e.pi_pid,d=S.has(n)?"remote (liveness not checked locally)":O(t)?"alive":"dead",m=e.intent?`/${String(e.intent)}`:"",c=n.fault,l=[];l.push(`# ${$(e)} (${o})`);const i=[`- kind/mode/lifecycle: ${e.kind} / ${e.mode} / ${e.lifecycle}`,`- status: ${e.status}${m}`,...c==null?[]:[`- fault: ${String(c.kind)} / ${String(c.retry?.disposition)} since ${String(c.since)}`],`- broker pid: ${t??"(none)"} \u2014 ${d}`,`- cwd: ${e.cwd}`,`- host: ${e.host_kind}`+(e.profile_id?` \xB7 profile ${e.profile_id}`:""),`- cycles: ${e.cycles} \xB7 created ${e.created}`],p=e.machine;p&&i.push(`- machine: ${p.name??p.id}`),e.parent&&i.push(`- parent: ${e.parent}`),i.push(`- creator: ${e.creator??"an external process"}`),e.waiting_for&&i.push(`- waiting for message: ${e.waiting_for}`),l.push(i.join(`
4
- `));const a=h((s,f)=>{if(f.length===0)return`${s}: none`;const b=["node_id","name","kind","status","active"],r=`| ${b.join(" | ")} |`,g=`| ${b.map(()=>"---").join(" | ")} |`,v=f.map(T=>`| ${b.map(N=>String(T[N]??"").replace(/\|/g,"\\|").replace(/\n/g," ")).join(" | ")} |`).join(`
1
+ var R=Object.defineProperty;var h=(n,e)=>R(n,"name",{value:e,configurable:!0});import{defineBranch as P,defineLeaf as k}from"../../core/command.js";import{InputError as v}from"../../core/io.js";import{requireScope as I}from"../../core/errors.js";import{isPidAlive as O}from"../../core/canvas/pid.js";import{fullName as _}from"../../core/canvas/labels.js";import{fuzzyMatch as F}from"../../core/tui/fuzzy.js";import{nodeSnapshotLeaf as L}from"../node-snapshot.js";import{nodeTranscriptLeaf as A}from"../node-transcript.js";import{nodeContextLeaf as C}from"../node-context.js";import{cliClient as $,cliCanvasSource as x,rethrowAsCliError as w}from"../api-client.js";import{RemoteCanvasSource as q}from"../../core/canvas/remote-canvas-source.js";import{kindsStateBlock as U,profilesStateBlock as D,resolveProfileViaDaemon as z}from"../profile/daemon-profiles.js";import{focusViewer as E,nodeInPane as B}from"../surface/node/placement.js";const M=k({name:"list",description:"list nodes on the canvas",whenToUse:"you want a flat roster of the nodes on the canvas, sliced by displayed name, status, kind, mode, lifecycle, profile, cwd, and graph scope (--under a node, for that node plus its subscription descendants). The filters AND together. Use `node inspect show` instead to drill into one node and its spine neighbors, `canvas dashboard` for the tree shape, and `canvas attention` to find nodes blocked on the user",help:{name:"node inspect list",summary:"list nodes on the canvas, filtered by any combination of attribute slices and a graph-scope (--under) that AND together",params:[{kind:"flag",name:"status",type:"string",required:!1,constraint:"Filter status (comma-separated for several; accepted values: active, idle, done, dead, canceled). NOTE: `active` means the engine process is live (never closed), NOT that the node is generating right now \u2014 an active node is usually dormant between turns. To tell working-vs-idle, check the pi session-file mtime or CPU, not status."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Filter by persona kind (comma-separated for several). The <kinds> list below names every top-level installable kind; a registered sub-kind filters too by exact path even though it is not listed."},{kind:"flag",name:"mode",type:"string",required:!1,constraint:"Filter by mode (comma-separated for several; accepted values: base, orchestrator)."},{kind:"flag",name:"lifecycle",type:"string",required:!1,constraint:"Filter by lifecycle (comma-separated for several; accepted values: terminal, resident)."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Filter by profile. On the local canvas, accepts a profile id or manifest name from the <profiles> list below, or a close-enough name that resolves to the nearest profile. Against a remote canvas, pass the exact profile id carried by its node rows."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Filter by the displayed node label (handle plus generated description) with the canvas browser\u2019s case-insensitive fuzzy subsequence match."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Filter to nodes pinned to this exact cwd (absolute path). Roster is canvas-wide (all cwds) by default."},{kind:"flag",name:"under",type:"string",required:!1,constraint:'Graph scope: restrict to this node and its subscription descendants (the sub-DAG reachable downward \u2014 its reports, theirs, \u2026). This is "one initiative / my subtree". ANDs with every attribute filter above, narrowing any of them to this subtree.'},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"nodes",type:"object[]",required:!0,constraint:"Rows include {node_id, name, kind, mode, lifecycle, status, cwd, profile_id, parent, created}. `name` is the displayed node label searched by --name and shown in canvas views. `profile_id` is the stable profile-directory id (null only for historical no-profile nodes)."}],outputKind:"object",effects:["Read-only: lists nodes through the daemon API."]},helpState:{leaf:h(async()=>(await Promise.all([U(),D()])).join(`
2
+ `),"leaf")},run:h(async n=>{const e=h(r=>{const g=n[r];return g!==void 0&&g!==""?g.split(",").map(y=>y.trim()).filter(y=>y!==""):void 0},"csv"),o=e("status"),t=e("kind"),u=e("mode"),d=e("lifecycle"),m=n.profile,c=n.name,l=n.cwd,i=n.under,p=x({canvasName:n.canvas}),a=p instanceof q?m:m===void 0?void 0:(await z(m)).id;let s;if(i!==void 0&&i!==""){if(await p.getNode(i).catch(w)===null)throw new v({error:"not_found",message:`no node: ${i}`,next:"List nodes with `crtr node inspect list`, then pass a real id to --under."});s=new Set([i,...await p.view(i)])}return{nodes:(await p.listNodes(o!==void 0?{status:o}:void 0).catch(w)).filter(r=>!(s!==void 0&&!s.has(r.node_id)||t!==void 0&&!t.includes(r.kind)||u!==void 0&&!u.includes(r.mode)||d!==void 0&&!d.includes(r.lifecycle)||a!==void 0&&r.profile_id!==a||l!==void 0&&l!==""&&r.cwd!==l)).map(r=>({...r,name:_(r)})).filter(r=>c===void 0||c===""||F(c,r.name))}},"run")}),S=new WeakSet;async function j(n,e){const o=await n.getNode(e.node_id).catch(w);return{node_id:e.node_id,name:o?_(o):"(missing)",kind:o?.kind??"?",status:o?o.intent?`${o.status}/${o.intent}`:o.status:"?",active:e.active}}h(j,"enrichNeighbor");const K=k({name:"show",description:"show a node + its spine neighbors and drill-in pointers",whenToUse:"you want one node in depth \u2014 the debugging entrypoint: a glanceable meta slice, named spine neighbors, a pending-cron count, and exact drill-in paths. Use `node inspect list` for the flat roster or `canvas dashboard` for the whole-tree shape",help:{name:"node inspect show",summary:"show a node in depth \u2014 meta slice, named neighbors, pending-cron count, and drill-in pointers",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id."},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"node",type:"object",required:!0,constraint:"The full node meta (system prompt + every telemetry field). The render surfaces a glanceable slice; `--json` carries the complete dump."},{name:"fault",type:"object",required:!0,constraint:"The active runtime fault projection, or null: {link, kind, retry: {disposition}, since}."},{name:"reports",type:"object[]",required:!0,constraint:"Who this node subscribes to (its reports/down), each enriched with {node_id, name, kind, status, active} \u2014 these are typically its spawned children."},{name:"managers",type:"object[]",required:!0,constraint:"Who subscribes to this node (its managers/up), same enriched shape."},{name:"pending_crons",type:"number",required:!0,constraint:"How many pending crons were created by this node. Inspect with `crtr cron list`."},{name:"paths",type:"object",required:!0,constraint:"Resolved on-disk locations: {context_dir, session_file} \u2014 read these directly to debug. Reports are documents: `crtr canvas read <node>/reports/<name>`."},{name:"follow_up",type:"string",required:!0,constraint:"The concrete next commands to drill deeper."}],outputKind:"object",effects:["Read-only: reads the node, its edges, and pending crons through crtrd."],preview:{suppressOutput:!0}},run:h(async n=>{const e=n.node,o=n.canvas,t=x({canvasName:o});if(t instanceof q){const s=await t.rawShow(e);if(s===null)throw new v({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list --canvas <name>`."});const f={...s};return S.add(f),f}const u=await t.getNode(e).catch(s=>w(s,"List nodes with `crtr node inspect list`."));if(u===null)throw new v({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list`."});const d=u,m=$(),c=await Promise.all((await t.subscriptionsOf(e)).map(s=>j(t,s))),l=await Promise.all((await t.subscribersOf(e)).map(s=>j(t,s))),i=(await m.listCrons({created_by:e}).catch(w)).filter(s=>s.created_by===e).length,p={context_dir:d.paths.context_dir,...d.pi_session_file!==void 0?{session_file:d.pi_session_file}:{}},a=[];return a.push(`List the documents it owns (reports, plans, notes): \`crtr canvas list --owner ${e}\`.`),a.push(`Browse its context dir (and its subscriptions') in nvim: \`crtr node inspect context ${e}\`.`),p.session_file&&a.push(`Read the raw conversation transcript: ${p.session_file}`),a.push(`On-disk context dir (ls/read directly): ${p.context_dir}`),i>0&&a.push(`It created ${i} pending cron(s): \`crtr cron list\`.`),c.length>0&&a.push(`Drill into a child/report: \`crtr node inspect show <node_id>\` (${c.map(s=>s.node_id).join(", ")}).`),a.push(`Full machine dump (system prompt + all telemetry): \`crtr --json node inspect show ${e}\`.`),{node:d,fault:d.fault??null,reports:c,managers:l,pending_crons:i,paths:p,follow_up:a.join(`
3
+ `)}},"run"),render:h(n=>{const e=n.node,o=String(e.node_id),t=e.pi_pid,d=S.has(n)?"remote (liveness not checked locally)":O(t)?"alive":"dead",m=e.intent?`/${String(e.intent)}`:"",c=n.fault,l=[];l.push(`# ${_(e)} (${o})`);const i=[`- kind/mode/lifecycle: ${e.kind} / ${e.mode} / ${e.lifecycle}`,`- status: ${e.status}${m}`,...c==null?[]:[`- fault: ${String(c.kind)} / ${String(c.retry?.disposition)} since ${String(c.since)}`],`- broker pid: ${t??"(none)"} \u2014 ${d}`,`- cwd: ${e.cwd}`,`- host: ${e.host_kind}`+(e.profile_id?` \xB7 profile ${e.profile_id}`:""),`- cycles: ${e.cycles} \xB7 created ${e.created}`],p=e.machine;p&&i.push(`- machine: ${p.name??p.id}`),e.parent&&i.push(`- parent: ${e.parent}`),i.push(`- creator: ${e.creator??"an external process"}`),e.waiting_for&&i.push(`- waiting for message: ${e.waiting_for}`),l.push(i.join(`
4
+ `));const a=h((s,f)=>{if(f.length===0)return`${s}: none`;const b=["node_id","name","kind","status","active"],r=`| ${b.join(" | ")} |`,g=`| ${b.map(()=>"---").join(" | ")} |`,y=f.map(T=>`| ${b.map(N=>String(T[N]??"").replace(/\|/g,"\\|").replace(/\n/g," ")).join(" | ")} |`).join(`
5
5
  `);return`${f.length} ${s}:
6
6
 
7
7
  ${r}
8
8
  ${g}
9
- ${v}`},"table");return l.push(a("reports (down \u2014 subscriptions, usually children)",n.reports)),l.push(a("managers (up \u2014 subscribers)",n.managers)),l.push(`${n.pending_crons} pending cron(s)`),l.push(`Drill deeper:
9
+ ${y}`},"table");return l.push(a("reports (down \u2014 subscriptions, usually children)",n.reports)),l.push(a("managers (up \u2014 subscribers)",n.managers)),l.push(`${n.pending_crons} pending cron(s)`),l.push(`Drill deeper:
10
10
  ${String(n.follow_up)}`),l.join(`
11
11
 
12
- `)},"render")}),ie=k({name:"fork",description:"fork a node into an independent idle root with the same conversation and durable context",whenToUse:"a conversation has already accumulated the context you want, and you want a new user-driven branch beside it without sending a prompt or inheriting any graph-management responsibility. This copies the conversation and durable context, then waits for the fork\u2019s first real user message to supply its mandate. Use `node new --fork-from` instead when spawning a managed worker with an immediate task",help:{name:"node fork",summary:"create an independent resident root from a node\u2019s conversation and durable context, with no kickoff prompt or model turn",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Source node id. Mutually exclusive with --pane; one of them is required."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the source node. Mutually exclusive with --node; one of them is required. The prefix menu passes this for you and the new viewer splits beside this pane."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The new independent root id."},{name:"focused",type:"boolean",required:!0,constraint:"True when a new viewer pane opened beside the caller; false outside tmux."},{name:"session",type:"string",required:!1,constraint:"The tmux session containing the new viewer, when one opened."}],outputKind:"object",effects:["Creates a resident base-mode root with the source node\u2019s copied pi conversation, cwd, profile, kind, model override, and durable context files. Top-level initial-prompt.md, yield-message.md, result.json, and the jobs/ folder of background bash jobs are omitted.","Copies no parent, subscriptions, subscribers, children, crons, worktree, situational context, or lifecycle responsibility. Sends no prompt and consumes no model turn; the first real user message becomes the fork\u2019s mandate.","Inside tmux, opens and focuses a surface-attach viewer as an even-horizontal split in the source pane\u2019s window. Outside tmux, the root is still created but no interactive fallback opens."]},run:h(async n=>{I("crtr:act","crtr node fork");const e=n.pane,o=n.node;if(o!==void 0&&e!==void 0)throw new y({error:"conflicting_target",message:"--node and --pane are mutually exclusive",next:"Pass the source node id or its viewer pane, not both."});let t=o;if(t===void 0&&e!==void 0&&(t=B(e)),t===void 0||t==="")throw new y({error:"no_node",message:"no source node was provided or found in the pane",next:"Pass --node <id>, or --pane <pane-id> for a pane showing a node."});const u=await _().forkNode(t).catch(w),d=await E(u.node_id,{cwd:u.cwd,name:u.name,...e!==void 0?{pane:e}:{},newPane:!0});return{node_id:u.node_id,focused:d.focused,session:d.session}},"run"),render:h(n=>{const e=n.focused===!0?` Viewer opened beside the source${n.session?` in session ${n.session}`:""}.`:" No viewer opened because no tmux pane was available.";return`Forked independent idle root ${n.node_id}.${e} It will make no model call until its first real user message.`},"render")}),re=P({name:"inspect",description:"read one node \u2014 its graph position, conversation, and context dir",whenToUse:"reading everything about ONE node you can name: enumerate the roster (`list`), inspect a node and its spine neighbors (`show`), or browse its on-disk context dir (`context`). The documents a node owns are `crtr canvas list --owner <id>`. Use `canvas dashboard` instead to render the whole tree SHAPE, or `canvas attention` to find which nodes are blocked on the user",help:{name:"node inspect",summary:"read one node (or the roster) \u2014 topology, conversation, and context dir",model:"Inspection is read-only and never revives a node. The roster is the selection surface; one-node metadata points to progressively heavier views: a parsed broker snapshot, rendered conversation, or context browser."},children:[M,K,L,A,C]});export{ie as nodeFork,re as nodeInspect};
12
+ `)},"render")}),ie=k({name:"fork",description:"fork a node into an independent idle root with the same conversation and durable context",whenToUse:"a conversation has already accumulated the context you want, and you want a new user-driven branch beside it without sending a prompt or inheriting any graph-management responsibility. This copies the conversation and durable context, then waits for the fork\u2019s first real user message to supply its mandate. Use `node new --fork-from` instead when spawning a managed worker with an immediate task",help:{name:"node fork",summary:"create an independent resident root from a node\u2019s conversation and durable context, with no kickoff prompt or model turn",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Source node id. Mutually exclusive with --pane; one of them is required."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the source node. Mutually exclusive with --node; one of them is required. The prefix menu passes this for you and the new viewer splits beside this pane."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The new independent root id."},{name:"focused",type:"boolean",required:!0,constraint:"True when a new viewer pane opened beside the caller; false outside tmux."},{name:"session",type:"string",required:!1,constraint:"The tmux session containing the new viewer, when one opened."}],outputKind:"object",effects:["Creates a resident base-mode root with the source node\u2019s copied pi conversation, cwd, profile, kind, model override, and durable context files. Top-level initial-prompt.md, yield-message.md, result.json, and the jobs/ folder of background bash jobs are omitted.","Copies no parent, subscriptions, subscribers, children, crons, worktree, situational context, or lifecycle responsibility. Sends no prompt and consumes no model turn; the first real user message becomes the fork\u2019s mandate.","Inside tmux, opens and focuses a surface-attach viewer as an even-horizontal split in the source pane\u2019s window. Outside tmux, the root is still created but no interactive fallback opens."]},run:h(async n=>{I("crtr:act","crtr node fork");const e=n.pane,o=n.node;if(o!==void 0&&e!==void 0)throw new v({error:"conflicting_target",message:"--node and --pane are mutually exclusive",next:"Pass the source node id or its viewer pane, not both."});let t=o;if(t===void 0&&e!==void 0&&(t=B(e)),t===void 0||t==="")throw new v({error:"no_node",message:"no source node was provided or found in the pane",next:"Pass --node <id>, or --pane <pane-id> for a pane showing a node."});const u=await $().forkNode(t).catch(w),d=await E(u.node_id,{cwd:u.cwd,name:u.name,...e!==void 0?{pane:e}:{},newPane:!0});return{node_id:u.node_id,focused:d.focused,session:d.session}},"run"),render:h(n=>{const e=n.focused===!0?` Viewer opened beside the source${n.session?` in session ${n.session}`:""}.`:" No viewer opened because no tmux pane was available.";return`Forked independent idle root ${n.node_id}.${e} It will make no model call until its first real user message.`},"render")}),re=P({name:"inspect",description:"read one node \u2014 its graph position, conversation, and context dir",whenToUse:"reading everything about ONE node you can name: enumerate the roster (`list`), inspect a node and its spine neighbors (`show`), or browse its on-disk context dir (`context`). The documents a node owns are `crtr canvas list --owner <id>`. Use `canvas dashboard` instead to render the whole tree SHAPE, or `canvas attention` to find which nodes are blocked on the user",help:{name:"node inspect",summary:"read one node (or the roster) \u2014 topology, conversation, and context dir",model:"Inspection is read-only and never revives a node. The roster is the selection surface; one-node metadata points to progressively heavier views: a parsed broker snapshot, rendered conversation, or context browser."},children:[M,K,L,A,C]});export{ie as nodeFork,re as nodeInspect};
@@ -1,2 +1,2 @@
1
- var d=Object.defineProperty;var a=(n,t)=>d(n,"name",{value:t,configurable:!0});import{accessSync as l,constants as c,realpathSync as f,statSync as u}from"node:fs";import{resolve as h}from"node:path";import{defineLeaf as p}from"../../../core/command.js";import{expandTilde as m}from"../../../core/fs-utils.js";import{brokerDelivery as y}from"../../../core/runtime/broker/daemon-ops.js";import{envExecutionId as v,envNodeId as b}from"../../../shared/env.js";function g(n){const t=[],o=new Set;for(const s of n)try{const e=f(h(m(s)));if(l(e,c.R_OK),!u(e).isFile()||o.has(e))continue;o.add(e),t.push(e)}catch{}return t}a(g,"readableRegularFiles");const D=p({name:"expose",description:"deliver file-read documents for file content a local command displays",whenToUse:"a local command has successfully rendered file contents and must place the documents their file-read rules deliver in that same output",help:{name:"sys context expose",summary:"deliver file-read documents for files displayed by a command",params:[{kind:"flag",name:"file",type:"path",required:!0,repeatable:!0,constraint:"Files whose contents the caller displays. Relative paths resolve against this process\u2019s cwd; leading ~ expands as for Read. Symlinks resolve to their target. Missing, unreadable, and non-file paths contribute nothing."}],output:[{name:"content",type:"string",required:!1,constraint:"The delivered <auto-loaded-context> blocks, one per displayed file with new matches. Absent when nothing new matches or the caller is not inside a node. Prose output is the blocks alone, without a field label or acknowledgement."}],outputKind:"object",effects:["Delivers through the current node\u2019s file-read activity: records its exposures, and a watch and read event for each document delivered at content. Inherits node identity from CRTR_NODE_ID. The caller must include the returned blocks in the same output as the displayed files; this is not a preview operation."]},run:a(async n=>{const t=b()?.trim();if(t===void 0||t==="")return{};const o=g(n.file);if(o.length===0)return{};const s=v();if(s===void 0||s==="")return{};const e=[];for(const i of o){const r=await y(t,{activity:"file-read",subject:i});r.content!==""&&e.push(r.content)}return e.length===0?{}:{content:e.join(`
2
- `)}},"run"),render:a(n=>n.content??"","render")});export{D as exposeLeaf};
1
+ var d=Object.defineProperty;var i=(n,t)=>d(n,"name",{value:t,configurable:!0});import{accessSync as l,constants as c,realpathSync as u,statSync as f}from"node:fs";import{resolve as h}from"node:path";import{defineLeaf as p}from"../../../core/command.js";import{expandTilde as m}from"../../../core/fs-utils.js";import{cliClient as y}from"../../api-client.js";import{envExecutionId as v,envNodeId as g}from"../../../shared/env.js";function w(n){const t=[],o=new Set;for(const s of n)try{const e=u(h(m(s)));if(l(e,c.R_OK),!f(e).isFile()||o.has(e))continue;o.add(e),t.push(e)}catch{}return t}i(w,"readableRegularFiles");const _=p({name:"expose",description:"deliver file-read documents for file content a local command displays",whenToUse:"a local command has successfully rendered file contents and must place the documents their file-read rules deliver in that same output",help:{name:"sys context expose",summary:"deliver file-read documents for files displayed by a command",params:[{kind:"flag",name:"file",type:"path",required:!0,repeatable:!0,constraint:"Files whose contents the caller displays. Relative paths resolve against this process\u2019s cwd; leading ~ expands as for Read. Symlinks resolve to their target. Missing, unreadable, and non-file paths contribute nothing."}],output:[{name:"content",type:"string",required:!1,constraint:"The delivered <auto-loaded-context> blocks, one per displayed file with new matches. Absent when nothing new matches or the caller is not inside a node. Prose output is the blocks alone, without a field label or acknowledgement."}],outputKind:"object",effects:["Delivers through the current node\u2019s file-read activity: records its exposures, and a watch and read event for each document delivered at content. Inherits node identity from CRTR_NODE_ID. The caller must include the returned blocks in the same output as the displayed files; this is not a preview operation."]},run:i(async n=>{const t=g()?.trim();if(t===void 0||t==="")return{};const o=w(n.file);if(o.length===0)return{};const s=v();if(s===void 0||s==="")return{};const e=[];for(const r of o){const a=await y().nodeDelivery(t,{activity:"file-read",subject:r,expected_execution_id:s});a.content!==""&&e.push(a.content)}return e.length===0?{}:{content:e.join(`
2
+ `)}},"run"),render:i(n=>n.content??"","render")});export{_ as exposeLeaf};
@@ -0,0 +1 @@
1
+ export declare const sysDbBranch: import("../../core/command.js").BranchDef;
@@ -0,0 +1 @@
1
+ var n=Object.defineProperty;var a=(e,t)=>n(e,"name",{value:t,configurable:!0});import{existsSync as o}from"node:fs";import{defineBranch as i,defineLeaf as d}from"../../core/command.js";import{general as s}from"../../core/errors.js";import{canvasDbPath as m}from"../../core/canvas/paths.js";import{isDaemonRunning as c}from"../../daemon/pidfile.js";import{runDaemonExportSqlite as p}from"../../daemon/manage.js";const h=d({name:"export-sqlite",description:"write the Postgres canvas database back into a SQLite canvas.db, for rolling back to a generation that predates Postgres",whenToUse:"rolling back to a runtime generation that still uses SQLite, after `crtr sys daemon stop`. Not part of normal operation; the Postgres generation never needs it.",help:{name:"sys db export-sqlite",summary:"copy the Postgres canvas database into a new runtime/canvas.db at the SQLite schema version the previous generation expects",guide:"Rollback sequence: `crtr sys daemon stop` (drains the daemon, releases its claim, stops the supervised Postgres), `crtr sys db export-sqlite` (this command starts the supervised Postgres by itself, copies every table with object ids mapped back to rowids, verifies row counts, and renames the result into place as runtime/canvas.db), select the previous runtime generation, `crtr sys daemon start`. If the export fails before publishing, canvas.db is not created and the Postgres data is untouched (only the export mark may be left, which keeps a later Postgres boot from importing a restored canvas.db over newer data): rename `runtime/canvas.db.imported` back to `runtime/canvas.db` to start the previous generation from the database as it was before the first Postgres boot, which loses every write made since. This command does not do that rename for you.",params:[],output:[{name:"path",type:"string",required:!0,constraint:"The canvas.db that was written."},{name:"rows",type:"number",required:!0,constraint:"Rows copied across all tables."},{name:"user_version",type:"number",required:!0,constraint:"The SQLite schema version of the written file."},{name:"ms",type:"number",required:!0,constraint:"Wall time of the copy."}],outputKind:"object",effects:["Starts the supervised Postgres if it is not running (or uses CRTR_DATABASE_URL), reads it in one read-only transaction, and writes runtime/canvas.db.exporting-<pid>, then renames it to runtime/canvas.db. Stops the Postgres again afterwards if this command started it.","Records an exported_to_sqlite mark in the Postgres canvas_meta before publishing runtime/canvas.db, so a later boot of the Postgres generation refuses to import this canvas.db over newer Postgres data.","Refuses while a daemon is running, and when runtime/canvas.db already exists."]},run:a(async()=>{if(c())throw s("a daemon is running; an export taken under it would miss writes made after the copy",{next:"Run `crtr sys daemon stop`, then `crtr sys db export-sqlite`."});const e=m();if(o(e))throw s(`${e} already exists`,{next:`Move it aside (or delete it if it is a leftover) before exporting; ${e}.imported is the pre-Postgres database kept by the import.`});try{const t=await p();return{path:t.path,rows:t.rows,user_version:t.userVersion,ms:t.ms}}catch(t){const r=`export failed: ${t.message}`;throw o(e)?s(`${r}; ${e} was published before the failure`,{next:`${e} may be complete: inspect it before using it, or move it aside and rerun the export.`}):s(r,{next:`Nothing was written to ${e}. To start the previous generation from the pre-Postgres database instead, rename ${e}.imported to ${e}; every write made since the Postgres import is lost.`})}},"run")}),y=i({name:"db",description:"offline operations on the canvas database",whenToUse:"rolling the canvas database back to SQLite after a Postgres soak fails",help:{name:"sys db",summary:"offline canvas database operations",model:"The canvas lives in a supervised Postgres. These commands run with the daemon stopped and are for migration and rollback only."},children:[h]});export{y as sysDbBranch};
@@ -1 +1 @@
1
- var s=Object.defineProperty;var r=(o,m)=>s(o,"name",{value:m,configurable:!0});import{defineSysBranch as t}from"./sys/branch.js";import{configBranch as f}from"./sys/config.js";import{sysEnvBranch as e}from"./sys/env.js";import{daemonBranch as i}from"./sys/daemon.js";import{sysDoctorLeaf as a}from"./sys/doctor.js";import{sysFeedbackLeaf as p}from"./sys/feedback.js";import{sysLogsLeaf as n}from"./sys/logs.js";import{sysRetryDeliveryLeaf as y}from"./sys/retry-delivery.js";import{sysWorktreesLeaf as c}from"./sys/worktrees.js";import{sysSpacesLeaf as L}from"./sys/spaces.js";import{sysLimitsBranch as h}from"./sys/limits.js";import{sysSettingsLeaf as B}from"./sys/settings.js";import{sysConnectLeaf as S}from"./sys/connect.js";import{sysSetupLeaf as g}from"./sys/setup.js";import{tutorialBranch as u}from"./sys/tutorial/branch.js";import{supportBranch as d}from"./sys/support.js";import{contextBranch as k}from"./sys/context.js";import{sysSyncBranch as l}from"./sys/sync.js";import{sysMigrateLeaf as v}from"./sys/migrate.js";import{sysJoinLeaf as x}from"./sys/join.js";import{sysUpdateLeaf as D,sysVersionLeaf as b}from"./sys/update.js";function T(){return t([B,f,e,S,g,u,a,k,p,n,c,y,L,h,d,D,b,v,x,l,i])}r(T,"registerSys");export{T as registerSys};
1
+ var s=Object.defineProperty;var r=(o,m)=>s(o,"name",{value:m,configurable:!0});import{defineSysBranch as t}from"./sys/branch.js";import{configBranch as f}from"./sys/config.js";import{sysEnvBranch as e}from"./sys/env.js";import{daemonBranch as i}from"./sys/daemon.js";import{sysDoctorLeaf as a}from"./sys/doctor.js";import{sysFeedbackLeaf as p}from"./sys/feedback.js";import{sysLogsLeaf as n}from"./sys/logs.js";import{sysRetryDeliveryLeaf as y}from"./sys/retry-delivery.js";import{sysWorktreesLeaf as c}from"./sys/worktrees.js";import{sysSpacesLeaf as L}from"./sys/spaces.js";import{sysLimitsBranch as h}from"./sys/limits.js";import{sysSettingsLeaf as B}from"./sys/settings.js";import{sysConnectLeaf as S}from"./sys/connect.js";import{sysSetupLeaf as g}from"./sys/setup.js";import{tutorialBranch as u}from"./sys/tutorial/branch.js";import{supportBranch as d}from"./sys/support.js";import{contextBranch as D}from"./sys/context.js";import{sysSyncBranch as b}from"./sys/sync.js";import{sysMigrateLeaf as k}from"./sys/migrate.js";import{sysJoinLeaf as l}from"./sys/join.js";import{sysDbBranch as v}from"./sys/db.js";import{sysUpdateLeaf as x,sysVersionLeaf as C}from"./sys/update.js";function Y(){return t([B,f,e,S,g,u,a,D,p,n,c,y,L,h,d,x,C,k,l,b,v,i])}r(Y,"registerSys");export{Y as registerSys};
@@ -1,12 +1,18 @@
1
- var $=Object.defineProperty;var a=(n,t)=>$(n,"name",{value:t,configurable:!0});import{homedir as k,userInfo as I}from"node:os";import{isAbsolute as R,resolve as x,sep as v}from"node:path";import{commandSegments as L,stripHeredocs as O}from"./shell-segments.js";const h=10,W={s:1,m:60,h:3600,d:86400};function N(n){const t=/^\s*sleep(\s+[^;&|\n]+)/.exec(n);if(!t)return null;let e=0;for(const s of t[1].trim().split(/\s+/)){const r=/^([0-9]*\.?[0-9]+)([smhd]?)$/.exec(s);if(!r)return null;e+=Number(r[1])*W[r[2]||"s"]}return e}a(N,"leadingSleepSeconds");function z(n){const t=N(n);return t===null||t<=h?null:`Refused: this command starts by sleeping ${t}s, over the ${h}s inline limit.
1
+ var M=Object.defineProperty;var a=(t,n)=>M(t,"name",{value:n,configurable:!0});import{homedir as z,userInfo as N}from"node:os";import{isAbsolute as T,resolve as A,sep as $}from"node:path";import{commandSegments as q,stripHeredocs as H}from"./shell-segments.js";const v=10,P={s:1,m:60,h:3600,d:86400};function V(t){const n=/^\s*sleep(\s+[^;&|\n]+)/.exec(t);if(!n)return null;let e=0;for(const r of n[1].trim().split(/\s+/)){const s=/^([0-9]*\.?[0-9]+)([smhd]?)$/.exec(r);if(!s)return null;e+=Number(s[1])*P[s[2]||"s"]}return e}a(V,"leadingSleepSeconds");function Z(t){const n=V(t);return n===null||n<=v?null:`Refused: this command starts by sleeping ${n}s, over the ${v}s inline limit.
2
2
  Holding a live window on a clock is never how you wait here. Instead:
3
3
  - schedule the wake and end your turn: crtr cron -h (one-shot at a time, or recurring)
4
4
  - race an inbox message against a deadline: crtr node wait deadline -h
5
5
  - waiting on a command: crtr node bash run '<command>' starts it as a job and wakes you with its exit code
6
6
  - waiting on a child, a reply from the user, or any spine event: just stop \u2014 the runtime wakes you.
7
- If you truly need a short pause inline, sleep ${h}s or less.`}a(z,"longSleepRefusal");const D=["/","/Applications","/bin","/dev","/etc","/home","/Library","/opt","/private","/private/etc","/private/tmp","/private/var","/sbin","/System","/tmp","/usr","/Users","/var","/Volumes"];function M(n,t,e){return D.includes(n)?"a system directory":n===t?"your home directory":n===`${t}/.crouter`?"the canvas home \u2014 every node\u2019s conversation and state":e===n||!e.startsWith(n.endsWith(v)?n:n+v)?null:`a directory containing your working directory (${e})`}a(M,"protectedReason");function T(n,t){const e=I().username;return new Map([["HOME",n],["PWD",t],["USER",e],["LOGNAME",e]])}a(T,"initialVariables");function y(n,t){let e=n;if(e==="~"||e.startsWith("~/")){const s=t.get("HOME");if(s===void 0)return null;e=s+e.slice(1)}else if(e.startsWith("~"))return null;return e=e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g,(s,r,i)=>t.get(r??i)??s),/[$`*?[]/.test(e)?null:e}a(y,"expandText");function w(n,t,e){const s=y(n.replace(/\/+\*?\.?$/,"")||"/",t);return s===null?null:R(s)?x(s):e===null?null:x(e,s)}a(w,"resolveTarget");function d(n,t){for(const e of t){const s=e.indexOf("=");if(s<=0)continue;const r=e.slice(0,s);if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(r))continue;const i=y(e.slice(s+1),n);i===null?n.delete(r):n.set(r,i)}}a(d,"applyAssignments");const H=/^[0-9]*(&?>>?|<<?|>&|<&)/;function m(n){const t=[];let e=!1,s=!1;for(const r of n.slice(1)){if(s){s=!1;continue}const i=H.exec(r.text);if(i!==null&&!r.opaque){s=r.text===i[0];continue}if(!e&&r.text==="--"){e=!0;continue}!e&&r.text.startsWith("-")&&r.text!=="-"||t.push(r.text)}return t}a(m,"operands");function P(n){const t=new Set,e=new Set;for(const s of n.slice(1)){if(s.text==="--")break;if(s.text.startsWith("--"))e.add(s.text.slice(2));else if(s.text.startsWith("-")&&s.text.length>1)for(const r of s.text.slice(1))t.add(r)}return{letters:t,long:e}}a(P,"flagLetters");function E(n){const{letters:t,long:e}=P(n);return t.has("r")||t.has("R")||e.has("recursive")}a(E,"isRecursive");const C=/^\/dev\/r?(disk|sd[a-z]|nvme|hd[a-z]|vd[a-z]|mmcblk|md)/;function q(n){const t=[];let e=1;for(;e<n.length;){const s=n[e].text;if(s==="--"||/^-[HLPEdsx]$/.test(s))e+=1;else if(s==="-D"||s==="-O")e+=2;else if(s==="-f")e+1<n.length&&t.push(n[e+1].text),e+=2;else break}for(;e<n.length&&!n[e].text.startsWith("-");e+=1)t.push(n[e].text);return t}a(q,"findPaths");const Z=new Set(["sudo","doas","command","env","nice","nohup","time","stdbuf","xargs","exec","builtin"]);function V(n){let t=n;for(;t.length>0&&!t[0].opaque&&Z.has(t[0].text);){let e=1;for(;e<t.length&&t[e].text.startsWith("-");){const s=/^-[nu]$/.test(t[e].text);e+=s?2:1}for(;e<t.length&&/^[A-Za-z_][A-Za-z0-9_]*=/.test(t[e].text);)e+=1;if(e>=t.length)return[];t=t.slice(e)}return t}a(V,"stripCommandPrefixes");function U(n){const t={targets:[],named:null},e=n[0];if(e===void 0||e.opaque)return t;const s=e.text.slice(e.text.lastIndexOf("/")+1),r=m(n);switch(s){case"rm":return E(n)?{targets:r,named:null}:t;case"mv":return r.length>=2?{targets:r.slice(0,-1),named:null}:t;case"chmod":case"chown":case"chgrp":return E(n)&&r.length>=2?{targets:r.slice(1),named:null}:t;case"find":return n.some(o=>!o.opaque&&(o.text==="-delete"||o.text==="-exec"||o.text==="-execdir"))?{targets:q(n),named:null}:t;case"dd":{const i=n.find(l=>l.text.startsWith("of="));if(i===void 0)return t;const o=i.text.slice(3);return C.test(o)?{targets:[],named:o}:o.startsWith("/dev/")?t:{targets:[o],named:null}}default:if(/^(mkfs|newfs)([.-].+)?$/.test(s))return{targets:[],named:s};if(s==="diskutil"){const i=r[0];if(i!==void 0&&/^(erase|reformat|partition|zeroDisk|randomDisk|secureErase)/i.test(i))return{targets:[],named:`diskutil ${i}`}}return t}}a(U,"destructiveTargets");function j(n,t,e){const s=T(e,t);let r=[t];for(const i of L(O(n))){const o=V(i.tokens),l=o[0];if(l!==void 0){const u=new Map(s);d(u,i.assignments);const c=r[r.length-1];c!==void 0&&u.set("PWD",c);const{targets:S,named:p}=U(o);if(p!==null)return b(i.text,p,"a whole disk or volume \u2014 never a task boundary");for(const A of S)for(const _ of r.length===0?[null]:r){const f=w(A,u,_);if(f===null)continue;const g=M(f,e,t);if(g!==null)return b(i.text,f,g)}}if(!i.background){if(l===void 0)d(s,i.assignments);else if(!l.opaque&&B.has(l.text))d(s,i.assignments),d(s,m(o));else if(!l.opaque&&l.text==="cd"){const u=m(o)[0],c=u===void 0?s.get("HOME")??null:w(u,s,r[r.length-1]??null);r=c===null?[]:[...r,c]}}}return null}a(j,"destructiveCommandRefusal");const B=new Set(["export","declare","typeset","readonly"]);function b(n,t,e){return`Refused: \`${n}\` targets ${t}, which is ${e}.
7
+ If you truly need a short pause inline, sleep ${v}s or less.`}a(Z,"longSleepRefusal");const B=["/","/Applications","/bin","/dev","/etc","/home","/Library","/opt","/private","/private/etc","/private/tmp","/private/var","/sbin","/System","/tmp","/usr","/Users","/var","/Volumes"];function R(t,n){return t==="/"||t==="/Users"||t==="/home"||t==="/System/Volumes/Data"?"a filesystem root":t===n?"your home directory":t===`${n}/.crouter`?"the canvas home (a multi-gigabyte canvas.db, every node directory and worktree)":null}a(R,"broadSearchReason");function U(t,n,e){return B.includes(t)?"a system directory":t===n?"your home directory":t===`${n}/.crouter`?"the canvas home \u2014 every node\u2019s conversation and state":e===t||!e.startsWith(t.endsWith($)?t:t+$)?null:`a directory containing your working directory (${e})`}a(U,"protectedReason");function G(t,n){const e=N().username;return new Map([["HOME",t],["PWD",n],["USER",e],["LOGNAME",e]])}a(G,"initialVariables");function _(t,n){let e=t;if(e==="~"||e.startsWith("~/")){const r=n.get("HOME");if(r===void 0)return null;e=r+e.slice(1)}else if(e.startsWith("~"))return null;return e=e.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g,(r,s,o)=>n.get(s??o)??r),/[$`*?[]/.test(e)?null:e}a(_,"expandText");function y(t,n,e){const r=_(t.replace(/\/+\*?\.?$/,"")||"/",n);return r===null?null:T(r)?A(r):e===null?null:A(e,r)}a(y,"resolveTarget");function p(t,n){for(const e of n){const r=e.indexOf("=");if(r<=0)continue;const s=e.slice(0,r);if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(s))continue;const o=_(e.slice(r+1),t);o===null?t.delete(s):t.set(s,o)}}a(p,"applyAssignments");const C=/^[0-9]*(&?>>?|<<?|>&|<&)/;function g(t){const n=[];let e=!1,r=!1;for(const s of t.slice(1)){if(r){r=!1;continue}const o=C.exec(s.text);if(o!==null&&!s.opaque){r=s.text===o[0];continue}if(!e&&s.text==="--"){e=!0;continue}!e&&s.text.startsWith("-")&&s.text!=="-"||n.push(s.text)}return n}a(g,"operands");function j(t){const n=new Set,e=new Set;for(const r of t.slice(1)){if(r.text==="--")break;if(r.text.startsWith("--"))e.add(r.text.slice(2));else if(r.text.startsWith("-")&&r.text.length>1)for(const s of r.text.slice(1))n.add(s)}return{letters:n,long:e}}a(j,"flagLetters");function b(t){const{letters:n,long:e}=j(t);return n.has("r")||n.has("R")||e.has("recursive")}a(b,"isRecursive");const F=/^\/dev\/r?(disk|sd[a-z]|nvme|hd[a-z]|vd[a-z]|mmcblk|md)/;function I(t){const n=[];let e=1;for(;e<t.length;){const r=t[e].text;if(r==="--"||/^-[HLPEdsx]$/.test(r))e+=1;else if(r==="-D"||r==="-O")e+=2;else if(r==="-f")e+1<t.length&&n.push(t[e+1].text),e+=2;else break}for(;e<t.length&&!t[e].text.startsWith("-");e+=1)n.push(t[e].text);return n}a(I,"findPaths");const X=new Set(["sudo","doas","command","env","nice","nohup","time","stdbuf","xargs","exec","builtin"]);function Y(t){let n=t;for(;n.length>0&&!n[0].opaque&&X.has(n[0].text);){let e=1;for(;e<n.length&&n[e].text.startsWith("-");){const r=/^-[nu]$/.test(n[e].text);e+=r?2:1}for(;e<n.length&&/^[A-Za-z_][A-Za-z0-9_]*=/.test(n[e].text);)e+=1;if(e>=n.length)return[];n=n.slice(e)}return n}a(Y,"stripCommandPrefixes");function K(t){const n={targets:[],named:null},e=t[0];if(e===void 0||e.opaque)return n;const r=e.text.slice(e.text.lastIndexOf("/")+1),s=g(t);switch(r){case"rm":return b(t)?{targets:s,named:null}:n;case"mv":return s.length>=2?{targets:s.slice(0,-1),named:null}:n;case"chmod":case"chown":case"chgrp":return b(t)&&s.length>=2?{targets:s.slice(1),named:null}:n;case"find":return t.some(i=>!i.opaque&&(i.text==="-delete"||i.text==="-exec"||i.text==="-execdir"))?{targets:I(t),named:null}:n;case"dd":{const o=t.find(l=>l.text.startsWith("of="));if(o===void 0)return n;const i=o.text.slice(3);return F.test(i)?{targets:[],named:i}:i.startsWith("/dev/")?n:{targets:[i],named:null}}default:if(/^(mkfs|newfs)([.-].+)?$/.test(r))return{targets:[],named:r};if(r==="diskutil"){const o=s[0];if(o!==void 0&&/^(erase|reformat|partition|zeroDisk|randomDisk|secureErase)/i.test(o))return{targets:[],named:`diskutil ${o}`}}return n}}a(K,"destructiveTargets");const m={grep:new Set(["-e","-f","-A","-B","-C","-m","-d","-D","--regexp","--file","--max-count","--context","--after-context","--before-context","--include","--exclude","--exclude-dir","--directories","--devices","--label"]),rg:new Set(["-e","-f","-A","-B","-C","-m","-g","-t","-T","-j","-M","-E","-r","--regexp","--file","--max-count","--context","--after-context","--before-context","--glob","--iglob","--type","--type-not","--threads","--max-columns","--encoding","--replace","--max-depth","--max-filesize","--sort","--sortr","--type-add","--pre","--pre-glob","--ignore-file","--color","--colors","--engine"]),ag:new Set(["-A","-B","-C","-m","-G","-g","--depth","--ignore","--file-search-regex","--max-count","--context","--after","--before"])};function O(t,n){const e=[];let r=!1,s=!1;for(let o=1;o<t.length;o+=1){const i=t[o].text,l=C.exec(i);if(l!==null&&!t[o].opaque){i===l[0]&&(o+=1);continue}if(!s&&i==="--"){s=!0;continue}if(!s&&i.startsWith("-")&&i!=="-"){const c=i.includes("=")?i.slice(0,i.indexOf("=")):i;(c==="-e"||c==="-f"||c==="--regexp"||c==="--file"||/^-[^-]*[ef]/.test(i))&&(r=!0),!i.includes("=")&&n.has(i)&&(o+=1);continue}e.push(i)}return{words:e,patternGiven:r}}a(O,"searchOperands");function J(t){const n={roots:[],implicitCwd:!1},e=t[0];if(e===void 0||e.opaque)return n;const r=e.text.slice(e.text.lastIndexOf("/")+1),s=a(o=>{const{words:i,patternGiven:l}=O(t,o),c=l?i:i.slice(1);return{roots:c,implicitCwd:c.length===0}},"patternThenPaths");switch(r){case"grep":case"egrep":case"fgrep":return b(t)?s(m.grep):n;case"rgrep":return s(m.grep);case"rg":if(t.some(o=>o.text==="--files")){const{words:o}=O(t,m.rg);return{roots:o,implicitCwd:o.length===0}}return s(m.rg);case"ag":case"ack":return s(m.ag);case"find":{if(t.some(i=>i.text==="-maxdepth"))return n;const o=I(t);return{roots:o,implicitCwd:o.length===0}}case"du":{const o=g(t);return{roots:o,implicitCwd:o.length===0}}default:return n}}a(J,"searchRoots");function L(t,n,e){return`Refused: \`${t}\` searches ${n} recursively, which is ${e}.
8
+ A sweep that wide reads hundreds of gigabytes, starves crtrd of disk, and has crashed every open viewer on this machine before.
9
+ Search where the answer can actually be:
10
+ - a document (knowledge, preference, spec, report): crtr canvas search "<text>" or crtr canvas read <name> \u2014 documents live in canvas.db, never as files, so grep cannot find them.
11
+ - code: the one repo or directory you are working in, e.g. rg -l '<text>' <repo>.
12
+ - a node's files: its own context dir, e.g. ~/.crouter/apps/<app>/nodes/<id>/context.
13
+ If you believe a whole-tree search is genuinely required, ask the user \u2014 do not work around this refusal.`}a(L,"broadSearchRefusalMessage");function Q(t,n,e){const r=G(e,n);let s=[n];for(const o of q(H(t))){const i=Y(o.tokens),l=i[0];if(l!==void 0){const c=new Map(r);p(c,o.assignments);const f=s[s.length-1];f!==void 0&&c.set("PWD",f);const{targets:W,named:S}=K(i);if(S!==null)return k(o.text,S,"a whole disk or volume \u2014 never a task boundary");for(const d of W)for(const w of s.length===0?[null]:s){const u=y(d,c,w);if(u===null)continue;const h=U(u,e,n);if(h!==null)return k(o.text,u,h)}const E=J(i),D=s.length===0?[null]:s,x=s[s.length-1];if(E.implicitCwd&&x!==void 0){const d=R(x,e);if(d!==null)return L(o.text,x,d)}for(const d of E.roots)for(const w of D){const u=y(d,c,w);if(u===null)continue;const h=R(u,e);if(h!==null)return L(o.text,u,h)}}if(!o.background){if(l===void 0)p(r,o.assignments);else if(!l.opaque&&ee.has(l.text))p(r,o.assignments),p(r,g(i));else if(!l.opaque&&l.text==="cd"){const c=g(i)[0],f=c===void 0?r.get("HOME")??null:y(c,r,s[s.length-1]??null);s=f===null?[]:[...s,f]}}}return null}a(Q,"destructiveCommandRefusal");const ee=new Set(["export","declare","typeset","readonly"]);function k(t,n,e){return`Refused: \`${t}\` targets ${n}, which is ${e}.
8
14
  Nothing an agent is asked to do requires destroying that path, and it cannot be undone.
9
15
  If you meant somewhere else, name that path explicitly and run the command again. Two traps to check first:
10
16
  - a \`VAR=value cmd\` prefix applies ONLY to that one command, so a later \`$VAR\` in the same line is the SHELL's value \u2014 this is exactly how a node deleted a home directory.
11
17
  - \`~\` and \`$HOME\` are the real home directory, never a scratch dir; build scratch paths with mktemp -d and hold them in a variable of your own.
12
- If you believe this path genuinely must be destroyed, ask the user \u2014 do not work around this refusal.`}a(b,"refusalMessage");function K(n,t,e=k()){return z(n)??j(n,t,e)}a(K,"bashCommandRefusal");export{K as bashCommandRefusal,N as leadingSleepSeconds};
18
+ If you believe this path genuinely must be destroyed, ask the user \u2014 do not work around this refusal.`}a(k,"refusalMessage");function oe(t,n,e=z()){return Z(t)??Q(t,n,e)}a(oe,"bashCommandRefusal");export{oe as bashCommandRefusal,V as leadingSleepSeconds};
@@ -158,12 +158,21 @@ export declare function listNodes(filter?: {
158
158
  * preserve lastActivityMs's timestamp inputs and the teardown event fields;
159
159
  * unlike node_rows, the nodes table needs no execution/session/fault joins. */
160
160
  export type TerminalPlacementResidue = Pick<NodeRow, 'node_id' | 'created' | 'launched_at' | 'last_settled_at' | 'finalized_at' | 'outcome_at' | 'last_activity_at' | 'pane' | 'window' | 'tmux_session'>;
161
- export declare const terminalPlacementResidueSql = "SELECT\n node_id, created, launched_at, last_settled_at, finalized_at,\n outcome_at, last_activity_at, pane, \"window\", tmux_session\n FROM nodes INDEXED BY idx_nodes_terminal_placement_created\n WHERE node_id NOT IN (SELECT node_id FROM warm_pool)\n AND status IN ('done', 'canceled', 'dead')\n AND (pane IS NOT NULL OR \"window\" IS NOT NULL OR tmux_session IS NOT NULL)\n ORDER BY created";
161
+ export declare const terminalPlacementResidueSql = "SELECT\n node_id, created, launched_at, last_settled_at, finalized_at,\n outcome_at, last_activity_at, pane, \"window\", tmux_session\n FROM nodes\n WHERE node_id NOT IN (SELECT node_id FROM warm_pool)\n AND status IN ('done', 'canceled', 'dead')\n AND (pane IS NOT NULL OR \"window\" IS NOT NULL OR tmux_session IS NOT NULL)\n ORDER BY created";
162
162
  export declare function listTerminalPlacementResidue(): Promise<TerminalPlacementResidue[]>;
163
163
  /** The daemon's complete supervision set. Live rows participate regardless of
164
164
  * PID; terminal rows participate only while they retain a PID or freeze mark. */
165
- export declare const nodesForSupervisionSql = "WITH candidates AS MATERIALIZED (\n SELECT node_id FROM nodes WHERE status IN ('active', 'idle')\n UNION\n SELECT node_id FROM nodes INDEXED BY idx_nodes_supervision_frozen\n WHERE frozen_at IS NOT NULL AND status IN ('done', 'canceled', 'dead')\n UNION\n SELECT node_id FROM executions\n WHERE state != 'exited' AND state = 'running' AND pid IS NOT NULL\n )\n SELECT v.* FROM candidates c CROSS JOIN node_rows v\n WHERE v.node_id = c.node_id\n AND v.node_id NOT IN (SELECT node_id FROM warm_pool)\n AND v.kind != 'human'\n AND (v.status IN ('active', 'idle') OR (v.status IN ('done', 'canceled', 'dead') AND (v.pi_pid IS NOT NULL OR v.frozen_at IS NOT NULL)))\n ORDER BY v.created";
165
+ export declare const nodesForSupervisionSql = "WITH candidates AS MATERIALIZED (\n SELECT node_id FROM nodes WHERE status IN ('active', 'idle')\n UNION\n SELECT node_id FROM nodes\n WHERE frozen_at IS NOT NULL AND status IN ('done', 'canceled', 'dead')\n UNION\n SELECT node_id FROM executions\n WHERE state != 'exited' AND state = 'running' AND pid IS NOT NULL\n )\n SELECT v.* FROM candidates c CROSS JOIN node_rows v\n WHERE v.node_id = c.node_id\n AND v.node_id NOT IN (SELECT node_id FROM warm_pool)\n AND v.kind != 'human'\n AND (v.status IN ('active', 'idle') OR (v.status IN ('done', 'canceled', 'dead') AND (v.pi_pid IS NOT NULL OR v.frozen_at IS NOT NULL)))\n ORDER BY v.created";
166
166
  export declare function listNodesForSupervision(): Promise<NodeRow[]>;
167
+ /** A parked resident the runtime may reopen when wake mail reaches it: `done` +
168
+ * `intent='parked'`, resident, no final latch, and not being deleted. Finalized,
169
+ * canceled, dead, terminal-lifecycle and deleting nodes are never reopened by mail.
170
+ * The SQL form of `isParkedResident` (runtime/lifecycle.ts), which must change with it; `n` is a `nodes` row. */
171
+ export declare const PARKED_RESIDENT_SQL: (n: string) => string;
172
+ /** Parked residents with unseen wake mail (`UNSEEN_WAKE_MAIL_SQL`), which nothing else
173
+ * launches: the lifecycle tick reopens them. Each parked resident seeks its own mail
174
+ * through `deliveries_destination`. */
175
+ export declare function listParkedResidentsWithWakeMail(): Promise<NodeRow[]>;
167
176
  /** Identity-only projection of every user-visible row: the broker's report
168
177
  * resolver needs only "does this sender exist, and what is it called", and a
169
178
  * three-column read stays cheap against a canvas of thousands of rows where a
@@ -241,6 +250,7 @@ export interface RosterRow {
241
250
  host_kind: 'tmux' | 'broker' | null;
242
251
  parent: string | null;
243
252
  created: string;
253
+ description: string | null;
244
254
  }
245
255
  /** Every node's lean roster row, oldest first — a single scan indexed by
246
256
  * `idx_nodes_created`, with no per-row hydration or N+1 query. */
@@ -1,13 +1,13 @@
1
- var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});import{envNodeId as j}from"../../shared/env.js";import{rmdirSync as ee,rmSync as ne,statSync as te}from"node:fs";import{dirname as ae,join as U,resolve as ie}from"node:path";import{removeTreeBeneath as W}from"../spaces/open-beneath.js";import{emitEvent as oe}from"../events/emit.js";import{withCanvasWrite as p,openDb as s}from"./db.js";import{conversationStore as re,ConversationNotFoundError as se}from"../conversation-store/index.js";import{hasUnseenWakeMail as de}from"./deliveries.js";import{isAppRun as b}from"./app-run.js";import{registerOutcomeAction as I}from"./outcome-actions.js";import{publish as le}from"../graph/events.js";import{nodeObject as ue}from"../graph/objects.js";import{findNodeBySessionFileSql as ce}from"./sessions.js";import{hydrateFault as _e}from"./recovery.js";import{hasUnreconciledWorktree as pe,openWorktree as fe,readWorktree as Ee,worktreeFromRow as we}from"./worktrees.js";import{isPidAlive as ye,isPidPresent as F,recordedPidLiveness as me}from"./pid.js";import{ensureHome as Ne,jobDir as Re,nodeDir as Se,nodeRunDir as H}from"./paths.js";import{appForNode as he,ensureNodeDirs as Oe,nodeAgentDir as Te}from"./node-agent-paths.js";import{appSpace as C}from"../layout.js";import{createObject as Le,getById as M,ownerForGrantee as h,setObjectKind as ge,setObjectName as De}from"../graph/objects.js";import{deleteNodeWithOwned as ve}from"../graph/deletion.js";import{filterAsync as y,mapAsync as O}from"../async-array.js";function E(e,n){if(e==null)return null;const t=JSON.stringify(e);if(t===void 0)throw new TypeError(`${n} must be JSON-serializable`);return t}i(E,"jsonValue");async function on(e,n){if((await e.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(n))?.deleting_at)throw new Error("run is deleting")}i(on,"assertRunNotDeleting");async function Ae(e,n){const t=await h(n,e.grantee??"app:terminal");await Le(n,{id:e.node_id,type:"node",kind:e.kind,owner:t.rowid,privacy:"public",name:e.name,preview:""}),await n.prepare(`INSERT INTO nodes (node_id, description, title, icon, cycles, mode, lifecycle, cwd, host_kind, profile_id, parent, spawned_by, creator, fork_from, fork_source_file, created, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json, scopes_json, isolated, status, intent, final_report, finalized_at, deadline_at, "window", tmux_session, pane, sub, grant_id, client_id, metadata_json, run_id, event_cursor, usage_json, deleting_at) VALUES (${Array(40).fill("?").join(", ")})`).run(e.node_id,e.description??null,e.title??null,e.icon??null,e.cycles??null,e.mode,e.lifecycle,e.cwd,e.host_kind??null,e.profile_id??null,e.parent??null,e.spawned_by??null,e.creator??null,e.fork_from??null,e.fork_source_file??null,e.created,e.passive_default===!0?1:0,e.cycle_pending===!0?1:0,e.model_override??null,E(e.persona_ack,"persona_ack"),E(e.review_binding,"review_binding"),E(e.launch,"launch"),E(e.scopes,"scopes"),e.isolated===!0?1:0,e.status??"active",e.intent??null,e.final_report??null,e.finalized_at??null,e.deadline_at??null,e.window??null,e.tmux_session??null,e.pane??null,e.sub??null,e.grant_id??null,e.client_id??null,e.metadata_json??null,e.run_id??null,e.event_cursor??null,e.usage_json??null,e.deleting_at??null)}i(Ae,"seedRow");function P(e){if(e.fault_id==null)return null;const n=Object.entries(e).filter(([t])=>t.startsWith("fault_")).map(([t,a])=>[t==="fault_id"?t:t.slice(6),a]);return _e(Object.fromEntries(n))}i(P,"faultFrom");function f(e){const n={node_id:e.node_id,name:e.name,description:e.description??void 0,cycles:e.cycles??void 0,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),isolated:e.isolated===1,grantee:e.grantee,sub:e.sub??null,grant_id:e.grant_id??null,client_id:e.client_id??null,metadata_json:e.metadata_json??null,run_id:e.run_id??null,event_cursor:e.event_cursor??null,last_activity_at:e.last_activity_at??null,usage_json:e.usage_json??null,last_turn_error_json:e.last_turn_error_json??null,deleting_at:e.deleting_at??null,parent:e.parent??null,created:e.created,intent:e.intent??null,frozen_at:e.frozen_at??null,respawn_failures:e.respawn_failures??0,respawn_not_before:e.respawn_not_before??null,launched_at:e.launched_at??null,last_settled_at:e.last_settled_at??null,terminal_reason:e.terminal_reason??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,outcome_kind:e.outcome_kind??null,outcome_reason:e.outcome_reason??null,outcome_at:e.outcome_at??null,outcome_revision:e.outcome_revision??0,outcome_detail_json:e.outcome_detail_json??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,fault:null,streaming:!1},t=F(n.pi_pid),a=P(e);return n.fault=a?.link==="pi\u2192provider"&&a.retry.by==="daemon"&&a.retry.disposition==="auto"&&!t?null:a,n.streaming=e.turn_open_at!==null&&e.turn_closed_at===null&&t,n}i(f,"rowFrom");async function q(e,n){return n??=await Ee(e.node_id),{...f(e),title:e.title??void 0,icon:e.icon??void 0,spawned_by:e.spawned_by??null,creator:e.creator??null,fork_from:e.fork_from??null,fork_source_file:e.fork_source_file??null,passive_default:e.passive_default===1,cycle_pending:e.cycle_pending===1,model_override:e.model_override??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),persona_ack:e.persona_ack_json==null?void 0:JSON.parse(e.persona_ack_json),review_binding:e.review_binding_json==null?void 0:JSON.parse(e.review_binding_json),launch:e.launch_config_json==null?void 0:JSON.parse(e.launch_config_json),pi_session_id:e.pi_session_id??null,pi_session_file:e.pi_session_file??null,...n===null?{}:{managed_worktree:n}}}i(q,"metaFrom");async function rn(e,n={}){return Ne(),await p(async t=>{await Ae(e,t),e.managed_worktree!==void 0&&e.managed_worktree!==null&&await fe(e.node_id,e.managed_worktree,t),n.outcomeDelivery!==void 0&&await I(t,e.node_id,n.outcomeDelivery),await n.withinCreate?.(t,e)}),await Oe(e.node_id),await N(e.node_id)}i(rn,"createNode");async function N(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n===void 0?null:await q(n)}i(N,"getNode");const ke=1440*60*1e3;function $(e){return{requestKey:e.request_key,nodeId:e.node_id,state:e.state}}i($,"createRequestRecord");async function sn(e){const n=await(await s()).prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return n===void 0?null:$(n)}i(sn,"findCreateRequest");async function dn(e){return await p(async n=>{const t=Date.now();await n.prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(t);const a=await n.prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return a!==void 0?$(a):(await n.prepareUncached("INSERT INTO create_requests (request_key, node_id, expires_at, state) VALUES (?, NULL, ?, 'reserved')").run(e,t+ke),{requestKey:e,nodeId:null,state:"reserved"})})}i(dn,"reserveCreateRequest");async function ln(e=Date.now()){return Number((await(await s()).prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(e)).changes)}i(ln,"pruneExpiredCreateRequests");async function un(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'complete' WHERE request_key = ?").run(n,e)}i(un,"recordCreateRequestNode");async function cn(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'reserved' WHERE request_key = ?").run(n,e)}i(cn,"reserveCreateRequestNode");async function _n(e,n){await(await s()).prepareUncached("UPDATE create_requests SET state = 'complete' WHERE request_key = ? AND node_id = ?").run(e,n)}i(_n,"completeCreateRequest");async function pn(e,n){await p(async t=>{if(n===null){await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id IS NULL").run(e);return}await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id = ?").run(e,n)})}i(pn,"abandonCreateRequest");function fn(e){return ie(e)}i(fn,"canonicalSessionFile");async function En(e){const n=await ce(e);return n===null?null:await N(n)}i(En,"findNodeBySessionFile");async function wn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n?f(n):null}i(wn,"getRow");async function yn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE pane = ?").get(e);return n?f(n):null}i(yn,"getRowByPane");async function mn(e){return(await(await s()).prepare(`SELECT * FROM node_rows
1
+ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});import{envNodeId as U}from"../../shared/env.js";import{rmdirSync as ee,rmSync as ne,statSync as te}from"node:fs";import{dirname as ae,join as j,resolve as ie}from"node:path";import{removeTreeBeneath as W}from"../spaces/open-beneath.js";import{emitEvent as oe}from"../events/emit.js";import{withCanvasWrite as p,openDb as s}from"./db.js";import{conversationStore as re,ConversationNotFoundError as se}from"../conversation-store/index.js";import{hasUnseenWakeMail as de,UNSEEN_WAKE_MAIL_SQL as le}from"./deliveries.js";import{isAppRun as b}from"./app-run.js";import{registerOutcomeAction as I}from"./outcome-actions.js";import{publish as ce}from"../graph/events.js";import{nodeObject as ue}from"../graph/objects.js";import{findNodeBySessionFileSql as _e}from"./sessions.js";import{hydrateFault as pe}from"./recovery.js";import{hasUnreconciledWorktree as fe,openWorktree as Ee,readWorktree as we,worktreeFromRow as ye}from"./worktrees.js";import{isPidAlive as me,isPidPresent as F,recordedPidLiveness as Ne}from"./pid.js";import{ensureHome as Re,jobDir as Se,nodeDir as Oe,nodeRunDir as H}from"./paths.js";import{appForNode as he,ensureNodeDirs as Te,nodeAgentDir as Le}from"./node-agent-paths.js";import{appSpace as C}from"../layout.js";import{createObject as De,getById as M,ownerForGrantee as O,setObjectKind as ge,setObjectName as Ae}from"../graph/objects.js";import{deleteNodeWithOwned as ve}from"../graph/deletion.js";import{filterAsync as y,mapAsync as h}from"../async-array.js";function E(e,n){if(e==null)return null;const t=JSON.stringify(e);if(t===void 0)throw new TypeError(`${n} must be JSON-serializable`);return t}i(E,"jsonValue");async function sn(e,n){if((await e.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(n))?.deleting_at)throw new Error("run is deleting")}i(sn,"assertRunNotDeleting");async function ke(e,n){const t=await O(n,e.grantee??"app:terminal");await De(n,{id:e.node_id,type:"node",kind:e.kind,owner:t.id,privacy:"public",name:e.name,preview:""}),await n.prepare(`INSERT INTO nodes (node_id, description, title, icon, cycles, mode, lifecycle, cwd, host_kind, profile_id, parent, spawned_by, creator, fork_from, fork_source_file, created, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json, scopes_json, isolated, status, intent, final_report, finalized_at, deadline_at, "window", tmux_session, pane, sub, grant_id, client_id, metadata_json, run_id, event_cursor, usage_json, deleting_at) VALUES (${Array(40).fill("?").join(", ")})`).run(e.node_id,e.description??null,e.title??null,e.icon??null,e.cycles??null,e.mode,e.lifecycle,e.cwd,e.host_kind??null,e.profile_id??null,e.parent??null,e.spawned_by??null,e.creator??null,e.fork_from??null,e.fork_source_file??null,e.created,e.passive_default===!0?1:0,e.cycle_pending===!0?1:0,e.model_override??null,E(e.persona_ack,"persona_ack"),E(e.review_binding,"review_binding"),E(e.launch,"launch"),E(e.scopes,"scopes"),e.isolated===!0?1:0,e.status??"active",e.intent??null,e.final_report??null,e.finalized_at??null,e.deadline_at??null,e.window??null,e.tmux_session??null,e.pane??null,e.sub??null,e.grant_id??null,e.client_id??null,e.metadata_json??null,e.run_id??null,e.event_cursor??null,e.usage_json??null,e.deleting_at??null)}i(ke,"seedRow");function P(e){if(e.fault_id==null)return null;const n=Object.entries(e).filter(([t])=>t.startsWith("fault_")).map(([t,a])=>[t==="fault_id"?t:t.slice(6),a]);return pe(Object.fromEntries(n))}i(P,"faultFrom");function f(e){const n={node_id:e.node_id,name:e.name,description:e.description??void 0,cycles:e.cycles??void 0,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),isolated:e.isolated===1,grantee:e.grantee,sub:e.sub??null,grant_id:e.grant_id??null,client_id:e.client_id??null,metadata_json:e.metadata_json??null,run_id:e.run_id??null,event_cursor:e.event_cursor??null,last_activity_at:e.last_activity_at??null,usage_json:e.usage_json??null,last_turn_error_json:e.last_turn_error_json??null,deleting_at:e.deleting_at??null,parent:e.parent??null,created:e.created,intent:e.intent??null,frozen_at:e.frozen_at??null,respawn_failures:e.respawn_failures??0,respawn_not_before:e.respawn_not_before??null,launched_at:e.launched_at??null,last_settled_at:e.last_settled_at??null,terminal_reason:e.terminal_reason??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,outcome_kind:e.outcome_kind??null,outcome_reason:e.outcome_reason??null,outcome_at:e.outcome_at??null,outcome_revision:e.outcome_revision??0,outcome_detail_json:e.outcome_detail_json??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,fault:null,streaming:!1},t=F(n.pi_pid),a=P(e);return n.fault=a?.link==="pi\u2192provider"&&a.retry.by==="daemon"&&a.retry.disposition==="auto"&&!t?null:a,n.streaming=e.turn_open_at!==null&&e.turn_closed_at===null&&t,n}i(f,"rowFrom");async function $(e,n){return n??=await we(e.node_id),{...f(e),title:e.title??void 0,icon:e.icon??void 0,spawned_by:e.spawned_by??null,creator:e.creator??null,fork_from:e.fork_from??null,fork_source_file:e.fork_source_file??null,passive_default:e.passive_default===1,cycle_pending:e.cycle_pending===1,model_override:e.model_override??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),persona_ack:e.persona_ack_json==null?void 0:JSON.parse(e.persona_ack_json),review_binding:e.review_binding_json==null?void 0:JSON.parse(e.review_binding_json),launch:e.launch_config_json==null?void 0:JSON.parse(e.launch_config_json),pi_session_id:e.pi_session_id??null,pi_session_file:e.pi_session_file??null,...n===null?{}:{managed_worktree:n}}}i($,"metaFrom");async function dn(e,n={}){return Re(),await p(async t=>{await ke(e,t),e.managed_worktree!==void 0&&e.managed_worktree!==null&&await Ee(e.node_id,e.managed_worktree,t),n.outcomeDelivery!==void 0&&await I(t,e.node_id,n.outcomeDelivery),await n.withinCreate?.(t,e)}),await Te(e.node_id),await N(e.node_id)}i(dn,"createNode");async function N(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n===void 0?null:await $(n)}i(N,"getNode");const xe=1440*60*1e3;function q(e){return{requestKey:e.request_key,nodeId:e.node_id,state:e.state}}i(q,"createRequestRecord");async function ln(e){const n=await(await s()).prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return n===void 0?null:q(n)}i(ln,"findCreateRequest");async function cn(e){return await p(async n=>{const t=Date.now();await n.prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(t);const a=await n.prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return a!==void 0?q(a):(await n.prepareUncached("INSERT INTO create_requests (request_key, node_id, expires_at, state) VALUES (?, NULL, ?, 'reserved')").run(e,t+xe),{requestKey:e,nodeId:null,state:"reserved"})})}i(cn,"reserveCreateRequest");async function un(e=Date.now()){return Number((await(await s()).prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(e)).changes)}i(un,"pruneExpiredCreateRequests");async function _n(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'complete' WHERE request_key = ?").run(n,e)}i(_n,"recordCreateRequestNode");async function pn(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'reserved' WHERE request_key = ?").run(n,e)}i(pn,"reserveCreateRequestNode");async function fn(e,n){await(await s()).prepareUncached("UPDATE create_requests SET state = 'complete' WHERE request_key = ? AND node_id = ?").run(e,n)}i(fn,"completeCreateRequest");async function En(e,n){await p(async t=>{if(n===null){await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id IS NULL").run(e);return}await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id = ?").run(e,n)})}i(En,"abandonCreateRequest");function wn(e){return ie(e)}i(wn,"canonicalSessionFile");async function yn(e){const n=await _e(e);return n===null?null:await N(n)}i(yn,"findNodeBySessionFile");async function mn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n?f(n):null}i(mn,"getRow");async function Nn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE pane = ?").get(e);return n?f(n):null}i(Nn,"getRowByPane");async function Rn(e){return(await(await s()).prepare(`SELECT * FROM node_rows
2
2
  WHERE deadline_at IS NOT NULL AND outcome_at IS NULL
3
3
  AND deadline_at <= ? AND status IN ('active','idle') AND kind != 'human'
4
- ORDER BY deadline_at, created, node_id`).all(e)).map(f)}i(mn,"dueNodeDeadlines");async function Nn(e,n){return Number((await(await s()).prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ?").run(n,e)).changes)===1}i(Nn,"setNodeDeadline");async function Rn(e,n){return!Number.isFinite(n)||n<=0?0:await p(async t=>{const a=await t.prepare(`SELECT node_id, deadline_at FROM nodes
5
- WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),o=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let r=0;for(const d of a){const u=Date.parse(d.deadline_at);Number.isNaN(u)||(r+=Number((await o.run(new Date(u+n).toISOString(),d.node_id,d.deadline_at)).changes))}return r})}i(Rn,"shiftProfileNodeDeadlines");async function Sn(e,n,t){const a=`SELECT o.rowid FROM objects o JOIN identities i ON i.object = o.owner JOIN nodes n ON n.node_id = o.id
6
- WHERE o.type = 'node' AND i.scheme = 'local-user' AND i.external_id = 'user:local'`,r=await e.prepareUncached(`${a} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE rowid IN (${a})`).run((await h(e,"app:terminal")).rowid)).changes):0,d=`SELECT o.rowid FROM objects o JOIN peer_stubs s ON s.object = o.rowid JOIN identities i ON i.object = o.owner
7
- WHERE o.type = 'node' AND o.reception = 2 AND json_extract(s.envelope_json, '$.app') IS NULL
8
- AND i.scheme = 'app' AND i.external_id = 'app:terminal'`,u=await e.prepareUncached(`${d} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE rowid IN (${d})`).run((await h(e,"user:local")).rowid)).changes):0;return Number((await e.prepare("UPDATE nodes SET sub = ? WHERE sub = 'user:local'").run(n)).changes)+r+u+Number((await e.prepare(`UPDATE nodes SET sub = ? WHERE sub IS NULL AND node_id IN (
4
+ ORDER BY deadline_at, created, node_id`).all(e)).map(f)}i(Rn,"dueNodeDeadlines");async function Sn(e,n){return Number((await(await s()).prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ?").run(n,e)).changes)===1}i(Sn,"setNodeDeadline");async function On(e,n){return!Number.isFinite(n)||n<=0?0:await p(async t=>{const a=await t.prepare(`SELECT node_id, deadline_at FROM nodes
5
+ WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),o=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let r=0;for(const d of a){const c=Date.parse(d.deadline_at);Number.isNaN(c)||(r+=Number((await o.run(new Date(c+n).toISOString(),d.node_id,d.deadline_at)).changes))}return r})}i(On,"shiftProfileNodeDeadlines");async function hn(e,n,t){const a=`SELECT o.id FROM objects o JOIN identities i ON i.object = o.owner JOIN nodes n ON n.node_id = o.id
6
+ WHERE o.type = 'node' AND i.scheme = 'local-user' AND i.external_id = 'user:local'`,r=await e.prepareUncached(`${a} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE id IN (${a})`).run((await O(e,"app:terminal")).id)).changes):0,d=`SELECT o.id FROM objects o JOIN peer_stubs s ON s.object = o.id JOIN identities i ON i.object = o.owner
7
+ WHERE o.type = 'node' AND o.reception = 2 AND s.envelope_json ->> 'app' IS NULL
8
+ AND i.scheme = 'app' AND i.external_id = 'app:terminal'`,c=await e.prepareUncached(`${d} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE id IN (${d})`).run((await O(e,"user:local")).id)).changes):0;return Number((await e.prepare("UPDATE nodes SET sub = ? WHERE sub = 'user:local'").run(n)).changes)+r+c+Number((await e.prepare(`UPDATE nodes SET sub = ? WHERE sub IS NULL AND node_id IN (
9
9
  SELECT o.id FROM objects o JOIN identities i ON i.object = o.owner
10
- WHERE o.type = 'node' AND i.scheme = 'app' AND i.external_id = 'app:terminal')`).run(n)).changes)+Number((await e.prepare("UPDATE nodes SET grant_id = NULL WHERE grant_id = ?").run(t)).changes)}i(Sn,"rewriteLocalNodeIdentity");function T(e,n){if(e==null)return null;if(typeof e=="string"||typeof e=="number"||typeof e=="bigint"||e instanceof Uint8Array)return e;throw new TypeError(`${n} must be a SQLite scalar`)}i(T,"sqlInput");async function hn(e,n){const t=[],a=i((r,d=r)=>{Object.prototype.hasOwnProperty.call(n,r)&&t.push([d,T(n[r],r)])},"add");if(a("description"),a("title"),a("icon"),a("cycles"),a("mode"),a("lifecycle"),a("cwd"),a("host_kind"),a("profile_id"),a("parent"),a("spawned_by"),a("creator"),a("fork_from"),a("fork_source_file"),a("model_override"),Object.prototype.hasOwnProperty.call(n,"passive_default")&&t.push(["passive_default",n.passive_default===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"cycle_pending")&&t.push(["cycle_pending",n.cycle_pending===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"persona_ack")&&t.push(["persona_ack_json",E(n.persona_ack,"persona_ack")]),Object.prototype.hasOwnProperty.call(n,"review_binding")&&t.push(["review_binding_json",E(n.review_binding,"review_binding")]),Object.prototype.hasOwnProperty.call(n,"isolated"))throw new TypeError("isolated cannot change after node creation");Object.prototype.hasOwnProperty.call(n,"scopes")&&t.push(["scopes_json",E(n.scopes,"scopes")]),Object.prototype.hasOwnProperty.call(n,"launch")&&t.push(["launch_config_json",E(n.launch,"launch")]);const o=i(r=>Object.prototype.hasOwnProperty.call(n,r),"has");return await p(async r=>{const d=await M(r,e);if(d===null||d.type!=="node")throw new Error(`unknown node: ${e}`);if(o("name")&&await De(r,d,T(n.name,"name")),o("kind")&&await ge(r,d,T(n.kind,"kind")),t.length===0)return;if((await r.prepareUncached(`UPDATE nodes SET ${t.map(([l])=>`${l} = ?`).join(", ")} WHERE node_id = ?`).run(...t.map(([,l])=>l),e)).changes!==1)throw new Error(`unknown node: ${e}`)}),await N(e)}i(hn,"updateNode");async function On(e,n){await(await s()).prepare("UPDATE nodes SET status = ? WHERE node_id = ?").run(n,e)}i(On,"setStatus");async function Tn(e,n){await(await s()).prepare("UPDATE nodes SET intent = ? WHERE node_id = ?").run(n??null,e)}i(Tn,"setIntent");async function Ln(e,n,t={}){if(t.outcome===void 0){const o=[],r=[];Object.prototype.hasOwnProperty.call(n,"status")&&(o.push("status = ?"),r.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(o.push("intent = ?"),r.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(o.push("terminal_reason = ?"),r.push(n.terminal_reason??null));const d=["node_id = ?"];r.push(e),t.fromStatuses!==void 0&&(d.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),r.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&d.push("final_report IS NULL");const u=await(await s()).prepareUncached(`UPDATE nodes SET ${o.join(", ")} WHERE ${d.join(" AND ")}`).run(...r);return Number(u.changes)}const a=t.outcome;return await p(async o=>{const r=[],d=[];Object.prototype.hasOwnProperty.call(n,"status")&&(r.push("status = ?"),d.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(r.push("intent = ?"),d.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(r.push("terminal_reason = ?"),d.push(n.terminal_reason??null));const u=i((m,c)=>a.supersede===!0?"?":`CASE WHEN outcome_at IS NULL THEN ? ELSE ${c} END`,"outcomeValue");r.push(`outcome_kind = ${u(a.kind,"outcome_kind")}`,`outcome_reason = ${u(a.reason,"outcome_reason")}`,`outcome_detail_json = ${u(a.detailJson,"outcome_detail_json")}`,`outcome_revision = ${a.supersede===!0?"outcome_revision + 1":"CASE WHEN outcome_at IS NULL THEN outcome_revision + 1 ELSE outcome_revision END"}`,`outcome_at = ${u(a.at,"outcome_at")}`),d.push(a.kind,a.reason,a.detailJson,a.at);const l=["node_id = ?"];d.push(e),t.fromStatuses!==void 0&&(l.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),d.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&l.push("final_report IS NULL");const _=await o.prepareUncached(`UPDATE nodes SET ${r.join(", ")} WHERE ${l.join(" AND ")}`).run(...d);if(Number(_.changes)===0)return 0;const S=await o.prepare("SELECT outcome_at FROM nodes WHERE node_id = ?").get(e);return(a.supersede===!0||S.outcome_at===a.at)&&a.documentJson!==null&&a.documentJson!==void 0&&await le(o,{event:"outcome",object:await ue(o,e),actor:null,attrs:{revision:Number((await o.prepare("SELECT outcome_revision FROM nodes WHERE node_id = ?").get(e)).outcome_revision)},messageBody:JSON.parse(a.documentJson)}),Number(_.changes)})}i(Ln,"transitionStatusIntent");async function gn(e){return(await(await s()).prepare("SELECT final_report FROM nodes WHERE node_id = ?").get(e))?.final_report??null}i(gn,"getFinalReport");async function Dn(e,n){return(await(await s()).prepare("UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?").run(e,n)).changes>0}i(Dn,"clearFinalReportIfMatches");async function vn(e,n){await(await s()).prepare('UPDATE nodes SET tmux_session = ?, "window" = ?, pane = ? WHERE node_id = ?').run(n.tmux_session??null,n.window??null,n.pane??null,e)}i(vn,"setPresence");async function An(e,n){await(await s()).prepare("UPDATE nodes SET launched_at = ?, frozen_at = NULL, respawn_not_before = NULL WHERE node_id = ?").run(n,e)}i(An,"recordLaunch");async function kn(e,n){await(await s()).prepare("UPDATE nodes SET last_settled_at = ? WHERE node_id = ?").run(n,e)}i(kn,"recordSettledTurn");async function xn(e,n){await(await s()).prepare("UPDATE nodes SET frozen_at = ? WHERE node_id = ?").run(n,e)}i(xn,"setFrozen");async function jn(e){await(await s()).prepare("UPDATE nodes SET frozen_at = NULL WHERE node_id = ?").run(e)}i(jn,"clearFrozen");async function Un(e,n){await(await s()).prepare("UPDATE nodes SET respawn_failures = ?, respawn_not_before = ? WHERE node_id = ?").run(n.failures,n.notBefore,e)}i(Un,"recordRespawnAttempt");const w="node_id NOT IN (SELECT node_id FROM warm_pool)",z=["state","cleanup_state","path","branch","repo_root","base_ref","base_sha","created_at","closed_at","next_attempt_at","attempts","quarantined","sweep_reason","sweep_detail","sweep_last_at","sweep_observed_json","abandoned_json","land_intent_json","disposal_json"];function xe(e){return e.worktree_state===null?null:we(Object.fromEntries(z.map(n=>[n,e[`worktree_${n}`]])))}i(xe,"worktreeFromProjection");async function Wn(e){const n=z.map(a=>`w.${a} AS worktree_${a}`).join(", "),t=await(await s()).prepareUncached(`SELECT n.*, ${n} FROM node_rows n LEFT JOIN worktrees w ON w.node_id = n.node_id WHERE n.profile_id = ? ORDER BY n.created`).all(e);return await O(t,async a=>await q(a,xe(a)))}i(Wn,"listNodesByProfile");async function bn(){return(await(await s()).prepare(`SELECT
10
+ WHERE o.type = 'node' AND i.scheme = 'app' AND i.external_id = 'app:terminal')`).run(n)).changes)+Number((await e.prepare("UPDATE nodes SET grant_id = NULL WHERE grant_id = ?").run(t)).changes)}i(hn,"rewriteLocalNodeIdentity");function T(e,n){if(e==null)return null;if(typeof e=="string"||typeof e=="number"||typeof e=="bigint"||e instanceof Uint8Array)return e;throw new TypeError(`${n} must be a SQLite scalar`)}i(T,"sqlInput");async function Tn(e,n){const t=[],a=i((r,d=r)=>{Object.prototype.hasOwnProperty.call(n,r)&&t.push([d,T(n[r],r)])},"add");if(a("description"),a("title"),a("icon"),a("cycles"),a("mode"),a("lifecycle"),a("cwd"),a("host_kind"),a("profile_id"),a("parent"),a("spawned_by"),a("creator"),a("fork_from"),a("fork_source_file"),a("model_override"),Object.prototype.hasOwnProperty.call(n,"passive_default")&&t.push(["passive_default",n.passive_default===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"cycle_pending")&&t.push(["cycle_pending",n.cycle_pending===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"persona_ack")&&t.push(["persona_ack_json",E(n.persona_ack,"persona_ack")]),Object.prototype.hasOwnProperty.call(n,"review_binding")&&t.push(["review_binding_json",E(n.review_binding,"review_binding")]),Object.prototype.hasOwnProperty.call(n,"isolated"))throw new TypeError("isolated cannot change after node creation");Object.prototype.hasOwnProperty.call(n,"scopes")&&t.push(["scopes_json",E(n.scopes,"scopes")]),Object.prototype.hasOwnProperty.call(n,"launch")&&t.push(["launch_config_json",E(n.launch,"launch")]);const o=i(r=>Object.prototype.hasOwnProperty.call(n,r),"has");return await p(async r=>{const d=await M(r,e);if(d===null||d.type!=="node")throw new Error(`unknown node: ${e}`);if(o("name")&&await Ae(r,d,T(n.name,"name")),o("kind")&&await ge(r,d,T(n.kind,"kind")),t.length===0)return;if((await r.prepareUncached(`UPDATE nodes SET ${t.map(([l])=>`${l} = ?`).join(", ")} WHERE node_id = ?`).run(...t.map(([,l])=>l),e)).changes!==1)throw new Error(`unknown node: ${e}`)}),await N(e)}i(Tn,"updateNode");async function Ln(e,n){await(await s()).prepare("UPDATE nodes SET status = ? WHERE node_id = ?").run(n,e)}i(Ln,"setStatus");async function Dn(e,n){await(await s()).prepare("UPDATE nodes SET intent = ? WHERE node_id = ?").run(n??null,e)}i(Dn,"setIntent");async function gn(e,n,t={}){if(t.outcome===void 0){const o=[],r=[];Object.prototype.hasOwnProperty.call(n,"status")&&(o.push("status = ?"),r.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(o.push("intent = ?"),r.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(o.push("terminal_reason = ?"),r.push(n.terminal_reason??null));const d=["node_id = ?"];r.push(e),t.fromStatuses!==void 0&&(d.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),r.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&d.push("final_report IS NULL");const c=await(await s()).prepareUncached(`UPDATE nodes SET ${o.join(", ")} WHERE ${d.join(" AND ")}`).run(...r);return Number(c.changes)}const a=t.outcome;return await p(async o=>{const r=[],d=[];Object.prototype.hasOwnProperty.call(n,"status")&&(r.push("status = ?"),d.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(r.push("intent = ?"),d.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(r.push("terminal_reason = ?"),d.push(n.terminal_reason??null));const c=i((m,u)=>a.supersede===!0?"?":`CASE WHEN outcome_at IS NULL THEN ? ELSE ${u} END`,"outcomeValue");r.push(`outcome_kind = ${c(a.kind,"outcome_kind")}`,`outcome_reason = ${c(a.reason,"outcome_reason")}`,`outcome_detail_json = ${c(a.detailJson,"outcome_detail_json")}`,`outcome_revision = ${a.supersede===!0?"outcome_revision + 1":"CASE WHEN outcome_at IS NULL THEN outcome_revision + 1 ELSE outcome_revision END"}`,`outcome_at = ${c(a.at,"outcome_at")}`),d.push(a.kind,a.reason,a.detailJson,a.at);const l=["node_id = ?"];d.push(e),t.fromStatuses!==void 0&&(l.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),d.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&l.push("final_report IS NULL");const _=await o.prepareUncached(`UPDATE nodes SET ${r.join(", ")} WHERE ${l.join(" AND ")}`).run(...d);if(Number(_.changes)===0)return 0;const S=await o.prepare("SELECT outcome_at FROM nodes WHERE node_id = ?").get(e);return(a.supersede===!0||S.outcome_at===a.at)&&a.documentJson!==null&&a.documentJson!==void 0&&await ce(o,{event:"outcome",object:await ue(o,e),actor:null,attrs:{revision:Number((await o.prepare("SELECT outcome_revision FROM nodes WHERE node_id = ?").get(e)).outcome_revision)},messageBody:JSON.parse(a.documentJson)}),Number(_.changes)})}i(gn,"transitionStatusIntent");async function An(e){return(await(await s()).prepare("SELECT final_report FROM nodes WHERE node_id = ?").get(e))?.final_report??null}i(An,"getFinalReport");async function vn(e,n){return(await(await s()).prepare("UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?").run(e,n)).changes>0}i(vn,"clearFinalReportIfMatches");async function kn(e,n){await(await s()).prepare('UPDATE nodes SET tmux_session = ?, "window" = ?, pane = ? WHERE node_id = ?').run(n.tmux_session??null,n.window??null,n.pane??null,e)}i(kn,"setPresence");async function xn(e,n){await(await s()).prepare("UPDATE nodes SET launched_at = ?, frozen_at = NULL, respawn_not_before = NULL WHERE node_id = ?").run(n,e)}i(xn,"recordLaunch");async function Un(e,n){await(await s()).prepare("UPDATE nodes SET last_settled_at = ? WHERE node_id = ?").run(n,e)}i(Un,"recordSettledTurn");async function jn(e,n){await(await s()).prepare("UPDATE nodes SET frozen_at = ? WHERE node_id = ?").run(n,e)}i(jn,"setFrozen");async function Wn(e){await(await s()).prepare("UPDATE nodes SET frozen_at = NULL WHERE node_id = ?").run(e)}i(Wn,"clearFrozen");async function bn(e,n){await(await s()).prepare("UPDATE nodes SET respawn_failures = ?, respawn_not_before = ? WHERE node_id = ?").run(n.failures,n.notBefore,e)}i(bn,"recordRespawnAttempt");const w="node_id NOT IN (SELECT node_id FROM warm_pool)",z=["state","cleanup_state","path","branch","repo_root","base_ref","base_sha","created_at","closed_at","next_attempt_at","attempts","quarantined","sweep_reason","sweep_detail","sweep_last_at","sweep_observed_json","abandoned_json","land_intent_json","disposal_json"];function Ue(e){return e.worktree_state===null?null:ye(Object.fromEntries(z.map(n=>[n,e[`worktree_${n}`]])))}i(Ue,"worktreeFromProjection");async function In(e){const n=z.map(a=>`w.${a} AS worktree_${a}`).join(", "),t=await(await s()).prepareUncached(`SELECT n.*, ${n} FROM node_rows n LEFT JOIN worktrees w ON w.node_id = n.node_id WHERE n.profile_id = ? ORDER BY n.created`).all(e);return await h(t,async a=>await $(a,Ue(a)))}i(In,"listNodesByProfile");async function Fn(){return(await(await s()).prepare(`SELECT
11
11
  node_id, name, description, kind, mode, lifecycle, status, cwd, profile_id,
12
12
  grantee, parent, created, frozen_at, terminal_reason, final_report,
13
13
  telemetry_tokens_in, telemetry_updated_at, pi_pid, turn_open_at, turn_closed_at,
@@ -15,13 +15,13 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
15
15
  fault_operation_id, fault_anchor_entry_id, fault_retry_disposition,
16
16
  fault_retry_by, fault_retry_attempt, fault_retry_max, fault_retry_next_at,
17
17
  fault_provider_error_json
18
- FROM node_rows WHERE ${w} ORDER BY created`).all()).map(f)}i(bn,"browseNodes");async function In(e,n){await(await s()).prepare(`UPDATE nodes
18
+ FROM node_rows WHERE ${w} ORDER BY created`).all()).map(f)}i(Fn,"browseNodes");async function Hn(e,n){await(await s()).prepare(`UPDATE nodes
19
19
  SET telemetry_tokens_in = ?,
20
20
  telemetry_context_tokens = COALESCE(?, telemetry_context_tokens),
21
21
  telemetry_last_activity = COALESCE(?, telemetry_last_activity),
22
22
  telemetry_updated_at = ?
23
23
  WHERE node_id = ?
24
- AND (telemetry_updated_at IS NULL OR telemetry_updated_at < ?)`).run(n.tokensIn,n.contextTokens,n.lastActivity,n.updatedAt,e,n.updatedAt)}i(In,"updateNodeTelemetry");async function Fn(){return(await(await s()).prepare(`SELECT
24
+ AND (telemetry_updated_at IS NULL OR telemetry_updated_at < ?)`).run(n.tokensIn,n.contextTokens,n.lastActivity,n.updatedAt,e,n.updatedAt)}i(Hn,"updateNodeTelemetry");async function Cn(){return(await(await s()).prepare(`SELECT
25
25
  node_id, name, description, cycles, kind, status, frozen_at,
26
26
  telemetry_context_tokens, telemetry_last_activity,
27
27
  pi_pid, turn_open_at, turn_closed_at,
@@ -29,17 +29,17 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
29
29
  fault_operation_id, fault_anchor_entry_id, fault_retry_disposition,
30
30
  fault_retry_by, fault_retry_attempt, fault_retry_max, fault_retry_next_at,
31
31
  fault_provider_error_json
32
- FROM node_rows WHERE ${w} ORDER BY created`).all()).map(n=>{const t=n.pi_pid??null,a=F(t),o=P(n);return{node_id:n.node_id,name:n.name,description:n.description??null,cycles:n.cycles??null,kind:n.kind,status:n.status,frozen_at:n.frozen_at??null,pi_pid:t,telemetry_context_tokens:n.telemetry_context_tokens??null,telemetry_last_activity:n.telemetry_last_activity??null,fault:o?.link==="pi\u2192provider"&&o.retry.by==="daemon"&&o.retry.disposition==="auto"&&!a?null:o,streaming:n.turn_open_at!==null&&n.turn_closed_at===null&&a}})}i(Fn,"graphNodes");async function je(e){const n=[w],t=[];if(e?.status!==void 0){const o=Array.isArray(e.status)?e.status:[e.status];n.push(`status IN (${o.map(()=>"?").join(",")})`),t.push(...o)}return e?.withRecordedPid===!0&&n.push("pi_pid IS NOT NULL"),e?.withRecordedPidOrFrozen===!0&&n.push("(pi_pid IS NOT NULL OR frozen_at IS NOT NULL)"),(await(await s()).prepareUncached(`SELECT * FROM node_rows WHERE ${n.join(" AND ")} ORDER BY created`).all(...t)).map(f)}i(je,"listNodes");const Ue=`SELECT
32
+ FROM node_rows WHERE ${w} ORDER BY created`).all()).map(n=>{const t=n.pi_pid??null,a=F(t),o=P(n);return{node_id:n.node_id,name:n.name,description:n.description??null,cycles:n.cycles??null,kind:n.kind,status:n.status,frozen_at:n.frozen_at??null,pi_pid:t,telemetry_context_tokens:n.telemetry_context_tokens??null,telemetry_last_activity:n.telemetry_last_activity??null,fault:o?.link==="pi\u2192provider"&&o.retry.by==="daemon"&&o.retry.disposition==="auto"&&!a?null:o,streaming:n.turn_open_at!==null&&n.turn_closed_at===null&&a}})}i(Cn,"graphNodes");async function je(e){const n=[w],t=[];if(e?.status!==void 0){const o=Array.isArray(e.status)?e.status:[e.status];n.push(`status IN (${o.map(()=>"?").join(",")})`),t.push(...o)}return e?.withRecordedPid===!0&&n.push("pi_pid IS NOT NULL"),e?.withRecordedPidOrFrozen===!0&&n.push("(pi_pid IS NOT NULL OR frozen_at IS NOT NULL)"),(await(await s()).prepareUncached(`SELECT * FROM node_rows WHERE ${n.join(" AND ")} ORDER BY created`).all(...t)).map(f)}i(je,"listNodes");const We=`SELECT
33
33
  node_id, created, launched_at, last_settled_at, finalized_at,
34
34
  outcome_at, last_activity_at, pane, "window", tmux_session
35
- FROM nodes INDEXED BY idx_nodes_terminal_placement_created
35
+ FROM nodes
36
36
  WHERE ${w}
37
37
  AND status IN ('done', 'canceled', 'dead')
38
38
  AND (pane IS NOT NULL OR "window" IS NOT NULL OR tmux_session IS NOT NULL)
39
- ORDER BY created`;async function Hn(){return await(await s()).prepare(Ue).all()}i(Hn,"listTerminalPlacementResidue");const We=`WITH candidates AS MATERIALIZED (
39
+ ORDER BY created`;async function Mn(){return await(await s()).prepare(We).all()}i(Mn,"listTerminalPlacementResidue");const be=`WITH candidates AS MATERIALIZED (
40
40
  SELECT node_id FROM nodes WHERE status IN ('active', 'idle')
41
41
  UNION
42
- SELECT node_id FROM nodes INDEXED BY idx_nodes_supervision_frozen
42
+ SELECT node_id FROM nodes
43
43
  WHERE frozen_at IS NOT NULL AND status IN ('done', 'canceled', 'dead')
44
44
  UNION
45
45
  SELECT node_id FROM executions
@@ -50,16 +50,19 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
50
50
  AND v.node_id NOT IN (SELECT node_id FROM warm_pool)
51
51
  AND v.kind != 'human'
52
52
  AND (v.status IN ('active', 'idle') OR (v.status IN ('done', 'canceled', 'dead') AND (v.pi_pid IS NOT NULL OR v.frozen_at IS NOT NULL)))
53
- ORDER BY v.created`;async function Cn(){return(await(await s()).prepare(We).all()).map(f)}i(Cn,"listNodesForSupervision");async function Mn(){return await(await s()).prepare(`SELECT node_id, name, created, grantee FROM node_rows WHERE ${w} ORDER BY created`).all()}i(Mn,"listNodeIdentities");async function Pn(e,n){await(await s()).prepare("INSERT OR REPLACE INTO warm_pool (node_id, recipe_key, created) VALUES (?, ?, ?)").run(e,n,new Date().toISOString())}i(Pn,"registerWarmSpare");async function qn(e){return(await(await s()).prepare("DELETE FROM warm_pool WHERE node_id = ?").run(e)).changes>0}i(qn,"unregisterWarmSpare");async function L(e,n){const t=`SELECT w.node_id AS node_id, w.recipe_key AS recipe_key, w.created AS created,
53
+ ORDER BY v.created`;async function Pn(){return(await(await s()).prepare(be).all()).map(f)}i(Pn,"listNodesForSupervision");const Ie=i(e=>`(${e}.status = 'done' AND ${e}.intent = 'parked' AND ${e}.lifecycle = 'resident' AND ${e}.final_report IS NULL AND ${e}.deleting_at IS NULL)`,"PARKED_RESIDENT_SQL");async function $n(){return(await(await s()).prepare(`SELECT v.* FROM node_rows v
54
+ WHERE ${Ie("v")}
55
+ AND EXISTS (SELECT 1 FROM deliveries d WHERE d.destination_id = v.node_id AND ${le("d")}) AND v.kind != 'human' AND v.node_id NOT IN (SELECT node_id FROM warm_pool)
56
+ ORDER BY v.created`).all()).map(f)}i($n,"listParkedResidentsWithWakeMail");async function qn(){return await(await s()).prepare(`SELECT node_id, name, created, grantee FROM node_rows WHERE ${w} ORDER BY created`).all()}i(qn,"listNodeIdentities");async function zn(e,n){await(await s()).prepare("INSERT INTO warm_pool (node_id, recipe_key, created) VALUES (?, ?, ?) ON CONFLICT (node_id) DO UPDATE SET recipe_key = excluded.recipe_key, created = excluded.created").run(e,n,new Date().toISOString())}i(zn,"registerWarmSpare");async function Bn(e){return(await(await s()).prepare("DELETE FROM warm_pool WHERE node_id = ?").run(e)).changes>0}i(Bn,"unregisterWarmSpare");async function L(e,n){const t=`SELECT w.node_id AS node_id, w.recipe_key AS recipe_key, w.created AS created,
54
57
  n.status AS status, n.pi_pid AS pi_pid, n.pi_pid_identity AS pi_pid_identity
55
- FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?await e.prepareUncached(t).all():await e.prepareUncached(t).all(n)).map(o=>({node_id:o.node_id,recipe_key:o.recipe_key,created:o.created,status:o.status,pi_pid:o.pi_pid??null,pi_pid_identity:o.pi_pid_identity??null}))}i(L,"warmSpareRowsFor");async function $n(){return await L(await s())}i($n,"listWarmSpares");async function zn(e){return await(await s()).prepare("SELECT 1 FROM warm_pool WHERE node_id = ?").get(e)!==void 0}i(zn,"isWarmSpare");function B(e){return e.status!=="active"&&e.status!=="idle"?!1:me(e.pi_pid,e.pi_pid_identity)==="alive"}i(B,"spareIsClaimable");async function Bn(e,n,t={}){return await p(async a=>{const o=(await L(a,e)).find(B);return o===void 0||t.requestKey!==void 0&&(await a.prepareUncached("UPDATE create_requests SET node_id = ?, state = 'warm_claimed' WHERE request_key = ? AND node_id IS NULL").run(o.node_id,t.requestKey)).changes===0||(await a.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(o.node_id)).changes===0?null:(await a.prepare("UPDATE nodes SET created = ?, deadline_at = ? WHERE node_id = ?").run(n,t.deadlineAt??null,o.node_id),t.outcomeDelivery!==void 0&&await I(a,o.node_id,t.outcomeDelivery),o.node_id)})}i(Bn,"claimWarmSpare");async function Jn(e){return(await L(await s(),e)).filter(B).length}i(Jn,"warmSpareCount");async function Yn(e){return(await(await s()).prepare("SELECT node_id FROM nodes WHERE parent = ? ORDER BY created").all(e)).map(n=>n.node_id)}i(Yn,"childrenOf");async function Vn(){return(await(await s()).prepareUncached(`SELECT node_id, name, kind, mode, lifecycle, status, cwd, host_kind, parent, created
56
- FROM node_rows WHERE ${w} ORDER BY created`).all()).map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created}))}i(Vn,"rosterNodes");async function Xn(e){return(await(await s()).prepareUncached(`SELECT * FROM node_rows
58
+ FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?await e.prepareUncached(t).all():await e.prepareUncached(t).all(n)).map(o=>({node_id:o.node_id,recipe_key:o.recipe_key,created:o.created,status:o.status,pi_pid:o.pi_pid??null,pi_pid_identity:o.pi_pid_identity??null}))}i(L,"warmSpareRowsFor");async function Jn(){return await L(await s())}i(Jn,"listWarmSpares");async function Yn(e){return await(await s()).prepare("SELECT 1 FROM warm_pool WHERE node_id = ?").get(e)!==void 0}i(Yn,"isWarmSpare");function B(e){return e.status!=="active"&&e.status!=="idle"?!1:Ne(e.pi_pid,e.pi_pid_identity)==="alive"}i(B,"spareIsClaimable");async function Vn(e,n,t={}){return await p(async a=>{const o=(await L(a,e)).find(B);return o===void 0||t.requestKey!==void 0&&(await a.prepareUncached("UPDATE create_requests SET node_id = ?, state = 'warm_claimed' WHERE request_key = ? AND node_id IS NULL").run(o.node_id,t.requestKey)).changes===0||(await a.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(o.node_id)).changes===0?null:(await a.prepare("UPDATE nodes SET created = ?, deadline_at = ? WHERE node_id = ?").run(n,t.deadlineAt??null,o.node_id),t.outcomeDelivery!==void 0&&await I(a,o.node_id,t.outcomeDelivery),o.node_id)})}i(Vn,"claimWarmSpare");async function Qn(e){return(await L(await s(),e)).filter(B).length}i(Qn,"warmSpareCount");async function Kn(e){return(await(await s()).prepare("SELECT node_id FROM nodes WHERE parent = ? ORDER BY created").all(e)).map(n=>n.node_id)}i(Kn,"childrenOf");async function Gn(){return(await(await s()).prepareUncached(`SELECT node_id, name, kind, mode, lifecycle, status, cwd, host_kind, parent, created, description
59
+ FROM node_rows WHERE ${w} ORDER BY created`).all()).map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created,description:e.description??null}))}i(Gn,"rosterNodes");async function Xn(e){return(await(await s()).prepareUncached(`SELECT * FROM node_rows
57
60
  WHERE parent IS NULL AND kind != 'human'
58
61
  AND status IN ('active','idle') AND cwd = ?
59
62
  AND ${w}
60
- ORDER BY created DESC`).all(e)).map(f)}i(Xn,"listResumableRoots");export*from"./tree.js";async function Gn(e,n,t){return await p(async a=>{const o=await a.prepare("SELECT status, final_report, frozen_at FROM nodes WHERE node_id = ?").get(e);return o===void 0?{kind:"missing"}:n(o)?{kind:"terminal",status:o.status,final_report:o.final_report}:{kind:"ran",result:await t()}})}i(Gn,"withFreshTerminalGuard");async function R(e){return await pe(e)}i(R,"hasUnreconciledManagedWorktree");async function J(e,n={}){return!["done","dead","canceled"].includes(e.status)||e.pi_pid!==null||e.frozen_at!==null||await R(e.node_id)||e.node_id===j()||b(e)?!1:n.pastTtl===!0||!["crashed","stranded",null].includes(e.terminal_reason??null)}i(J,"isCollectible");async function g(e){if(e.length===0)return[];const n=e.map(()=>"?").join(",");return(await(await s()).prepareUncached(`SELECT DISTINCT session_id FROM sessions WHERE node_id IN (${n}) AND session_id IS NOT NULL`).all(...e)).map(({session_id:a})=>a)}i(g,"nodeConversationIds");async function D(e){const n=await s(),t=n.prepare("SELECT 1 FROM sessions WHERE session_id = ? LIMIT 1"),a=n.prepare(`SELECT 1 FROM nodes n WHERE n.fork_source_file LIKE '%\\_' || ? || '.jsonl' ESCAPE '\\'
61
- AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.node_id = n.node_id) LIMIT 1`);for(const o of e)if(!(await t.get(o)!==void 0||await a.get(o)!==void 0))try{await re().delete(o)}catch(r){if(!(r instanceof se))throw r}}i(D,"deleteNodeConversations");async function v(e,n){const t=await M(e,n);return t===null||t.deleted_at!==null?!1:(await ve(e,t),!0)}i(v,"deleteNodeObject");async function A(e){return{nodeId:e,app:await N(e)===null?null:await he(e)}}i(A,"nodeFiles");async function Y({nodeId:e,app:n}){n!==null&&W(C(n).nodes,await Te(e,n)),W(ae(H(e)),H(e))}i(Y,"removeNodeAppTrees");function V({nodeId:e}){return[Se(e)]}i(V,"nodeOwnedDirs");function X({nodeId:e,app:n}){if(n!==null)try{ee(U(C(n).conversations,e))}catch(t){if(!["ENOENT","ENOTEMPTY"].includes(t.code??""))throw t}}i(X,"removeNodeConversationDir");async function k(e){await Y(e);for(const n of V(e))ne(n,{recursive:!0,force:!0});X(e)}i(k,"removeNodeFiles");async function Qn(e){if(await R(e))return{deleted:!1};const n=await A(e),t=await g([e]),a=await p(async o=>(await v(o,e),{deleted:!0}));return await D(t),await k(n),a}i(Qn,"deleteNode");async function Kn(e){const n=[...new Set(e)];if(n.length===0)return[];const t=await y(n,R);if(t.length>0)throw new Error(`refusing to delete nodes with unreconciled managed worktrees: ${t.join(", ")}`);const a=await O(n,A),o=await g(n),r=n.map(()=>"?").join(","),d=(await(await s()).prepareUncached(`SELECT node_id FROM nodes WHERE node_id IN (${r}) ORDER BY created`).all(...n)).map(({node_id:l})=>l),u=await y(d,async l=>await p(async _=>await v(_,l)));await D(o);for(const l of u){const _=a[n.indexOf(l)];await x(_,async()=>await k(_))}return u}i(Kn,"deleteNodes");async function Zn(e){const n=e.dryRun??!1,t=e.includeStale??!1,a=Date.now()-e.ttlDays*864e5,o=new Date(a).toISOString(),r=j()??"",d=await s(),u=i(c=>K(c)<a,"quiet"),l=i(c=>({node_id:c.node_id,status:c.status,created:c.created}),"toPruned"),_=(await y((await d.prepare(`SELECT * FROM node_rows
63
+ ORDER BY created DESC`).all(e)).map(f)}i(Xn,"listResumableRoots");export*from"./tree.js";async function Zn(e,n,t){return await p(async a=>{const o=await a.prepare("SELECT status, final_report, frozen_at FROM nodes WHERE node_id = ?").get(e);return o===void 0?{kind:"missing"}:n(o)?{kind:"terminal",status:o.status,final_report:o.final_report}:{kind:"ran",result:await t()}})}i(Zn,"withFreshTerminalGuard");async function R(e){return await fe(e)}i(R,"hasUnreconciledManagedWorktree");async function J(e,n={}){return!["done","dead","canceled"].includes(e.status)||e.pi_pid!==null||e.frozen_at!==null||await R(e.node_id)||e.node_id===U()||b(e)?!1:n.pastTtl===!0||!["crashed","stranded",null].includes(e.terminal_reason??null)}i(J,"isCollectible");async function D(e){if(e.length===0)return[];const n=e.map(()=>"?").join(",");return(await(await s()).prepareUncached(`SELECT DISTINCT session_id FROM sessions WHERE node_id IN (${n}) AND session_id IS NOT NULL`).all(...e)).map(({session_id:a})=>a)}i(D,"nodeConversationIds");async function g(e){const n=await s(),t=n.prepare("SELECT 1 FROM sessions WHERE session_id = ? LIMIT 1"),a=n.prepare(`SELECT 1 FROM nodes n WHERE n.fork_source_file LIKE '%\\_' || ? || '.jsonl' ESCAPE '\\'
64
+ AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.node_id = n.node_id) LIMIT 1`);for(const o of e)if(!(await t.get(o)!==void 0||await a.get(o)!==void 0))try{await re().delete(o)}catch(r){if(!(r instanceof se))throw r}}i(g,"deleteNodeConversations");async function A(e,n){const t=await M(e,n);return t===null||t.deleted_at!==null?!1:(await ve(e,t),!0)}i(A,"deleteNodeObject");async function v(e){return{nodeId:e,app:await N(e)===null?null:await he(e)}}i(v,"nodeFiles");async function Y({nodeId:e,app:n}){n!==null&&W(C(n).nodes,await Le(e,n)),W(ae(H(e)),H(e))}i(Y,"removeNodeAppTrees");function V({nodeId:e}){return[Oe(e)]}i(V,"nodeOwnedDirs");function Q({nodeId:e,app:n}){if(n!==null)try{ee(j(C(n).conversations,e))}catch(t){if(!["ENOENT","ENOTEMPTY"].includes(t.code??""))throw t}}i(Q,"removeNodeConversationDir");async function k(e){await Y(e);for(const n of V(e))ne(n,{recursive:!0,force:!0});Q(e)}i(k,"removeNodeFiles");async function et(e){if(await R(e))return{deleted:!1};const n=await v(e),t=await D([e]),a=await p(async o=>(await A(o,e),{deleted:!0}));return await g(t),await k(n),a}i(et,"deleteNode");async function nt(e){const n=[...new Set(e)];if(n.length===0)return[];const t=await y(n,R);if(t.length>0)throw new Error(`refusing to delete nodes with unreconciled managed worktrees: ${t.join(", ")}`);const a=await h(n,v),o=await D(n),r=n.map(()=>"?").join(","),d=(await(await s()).prepareUncached(`SELECT node_id FROM nodes WHERE node_id IN (${r}) ORDER BY created`).all(...n)).map(({node_id:l})=>l),c=await y(d,async l=>await p(async _=>await A(_,l)));await g(o);for(const l of c){const _=a[n.indexOf(l)];await x(_,async()=>await k(_))}return c}i(nt,"deleteNodes");async function tt(e){const n=e.dryRun??!1,t=e.includeStale??!1,a=Date.now()-e.ttlDays*864e5,o=new Date(a).toISOString(),r=U()??"",d=await s(),c=i(u=>X(u)<a,"quiet"),l=i(u=>({node_id:u.node_id,status:u.status,created:u.created}),"toPruned"),_=(await y((await d.prepare(`SELECT * FROM node_rows
62
65
  WHERE status IN ('dead', 'done', 'canceled') AND created < ?
63
- ORDER BY created`).all(o)).map(f),async c=>await J(c,{pastTtl:!0})&&u(c)&&!await e.held(c.node_id))).map(l),S=t?(await y((await d.prepare(`SELECT * FROM node_rows
66
+ ORDER BY created`).all(o)).map(f),async u=>await J(u,{pastTtl:!0})&&c(u)&&!await e.held(u.node_id))).map(l),S=t?(await y((await d.prepare(`SELECT * FROM node_rows
64
67
  WHERE status IN ('active', 'idle') AND created < ?
65
- ORDER BY created`).all(o)).map(f),async c=>c.node_id!==r&&!ye(c.pi_pid??null)&&(c.frozen_at??null)===null&&(c.respawn_not_before??null)===null&&c.intent!=="idle-release"&&!b(c)&&!await de(c.node_id)&&!await R(c.node_id)&&u(c)&&!await e.held(c.node_id))).map(l):[],m=await G([..._,...S]);return n||m.length===0?{pruned:m,dryRun:n}:(await Q(m,e.removeDirs),{pruned:m,dryRun:n})}i(Zn,"pruneNodes");async function G(e){const t=(await s()).prepare("SELECT node_id FROM nodes WHERE run_id = ? AND node_id != ?"),a=new Set(e.map(o=>o.node_id));return await y(e,async o=>(await t.all(o.node_id,o.node_id)).every(r=>a.has(r.node_id)))}i(G,"retainRunRootsWithMembers");async function Q(e,n){if(e.length===0)return;const t=await O(e,async o=>await A(o.node_id)),a=await g(e.map(o=>o.node_id));for(const o of e)await p(async r=>await v(r,o.node_id));if(await D(a),n!==void 0){for(const o of t)await x(o,async()=>{await Y(o),X(o)});n(t.flatMap(V));return}for(const o of t)await x(o,async()=>await k(o))}i(Q,"deletePrunedNodes");async function x(e,n){try{n()}catch(t){oe({level:"error",event:"canvas.node_files.remove_failed",error:t,fields:{node_id:e.nodeId}})}}i(x,"eachNodeBestEffort");function K(e){let n=0;for(const t of[e.created,e.launched_at,e.last_settled_at,e.finalized_at,e.outcome_at,e.last_activity_at]){if(t==null)continue;const a=Date.parse(t);Number.isFinite(a)&&a>n&&(n=a)}try{const t=te(U(Re(e.node_id),"telemetry.json"),{throwIfNoEntry:!1});t!==void 0&&t.mtimeMs>n&&(n=t.mtimeMs)}catch{}return n}i(K,"lastActivityMs");async function et(e){const n=e.dryRun??!1,t=await je(),a=await y(t,async l=>await J(l)&&!await e.held(l.node_id)),o=t.length-a.length,r=Math.max(0,e.maxNodes-o),d=a.map(l=>({row:l,recency:K(l)})).sort((l,_)=>_.recency-l.recency).slice(r).map(({row:l})=>({node_id:l.node_id,status:l.status,created:l.created})),u=await G(d);return n||u.length===0?{pruned:u,dryRun:n}:(await Q(u),{pruned:u,dryRun:n})}i(et,"pruneToLimit");export{pn as abandonCreateRequest,on as assertRunNotDeleting,bn as browseNodes,fn as canonicalSessionFile,Yn as childrenOf,Bn as claimWarmSpare,Dn as clearFinalReportIfMatches,jn as clearFrozen,_n as completeCreateRequest,rn as createNode,Qn as deleteNode,Kn as deleteNodes,mn as dueNodeDeadlines,sn as findCreateRequest,En as findNodeBySessionFile,gn as getFinalReport,N as getNode,wn as getRow,yn as getRowByPane,Fn as graphNodes,J as isCollectible,zn as isWarmSpare,K as lastActivityMs,Mn as listNodeIdentities,je as listNodes,Wn as listNodesByProfile,Cn as listNodesForSupervision,Xn as listResumableRoots,Hn as listTerminalPlacementResidue,$n as listWarmSpares,A as nodeFiles,We as nodesForSupervisionSql,ln as pruneExpiredCreateRequests,Zn as pruneNodes,et as pruneToLimit,un as recordCreateRequestNode,An as recordLaunch,Un as recordRespawnAttempt,kn as recordSettledTurn,Pn as registerWarmSpare,k as removeNodeFiles,dn as reserveCreateRequest,cn as reserveCreateRequestNode,Sn as rewriteLocalNodeIdentity,Vn as rosterNodes,xn as setFrozen,Tn as setIntent,Nn as setNodeDeadline,vn as setPresence,On as setStatus,Rn as shiftProfileNodeDeadlines,Ue as terminalPlacementResidueSql,Ln as transitionStatusIntent,qn as unregisterWarmSpare,hn as updateNode,In as updateNodeTelemetry,Jn as warmSpareCount,Gn as withFreshTerminalGuard};
68
+ ORDER BY created`).all(o)).map(f),async u=>u.node_id!==r&&!me(u.pi_pid??null)&&(u.frozen_at??null)===null&&(u.respawn_not_before??null)===null&&u.intent!=="idle-release"&&!b(u)&&!await de(u.node_id)&&!await R(u.node_id)&&c(u)&&!await e.held(u.node_id))).map(l):[],m=await K([..._,...S]);return n||m.length===0?{pruned:m,dryRun:n}:(await G(m,e.removeDirs),{pruned:m,dryRun:n})}i(tt,"pruneNodes");async function K(e){const t=(await s()).prepare("SELECT node_id FROM nodes WHERE run_id = ? AND node_id != ?"),a=new Set(e.map(o=>o.node_id));return await y(e,async o=>(await t.all(o.node_id,o.node_id)).every(r=>a.has(r.node_id)))}i(K,"retainRunRootsWithMembers");async function G(e,n){if(e.length===0)return;const t=await h(e,async o=>await v(o.node_id)),a=await D(e.map(o=>o.node_id));for(const o of e)await p(async r=>await A(r,o.node_id));if(await g(a),n!==void 0){for(const o of t)await x(o,async()=>{await Y(o),Q(o)});n(t.flatMap(V));return}for(const o of t)await x(o,async()=>await k(o))}i(G,"deletePrunedNodes");async function x(e,n){try{n()}catch(t){oe({level:"error",event:"canvas.node_files.remove_failed",error:t,fields:{node_id:e.nodeId}})}}i(x,"eachNodeBestEffort");function X(e){let n=0;for(const t of[e.created,e.launched_at,e.last_settled_at,e.finalized_at,e.outcome_at,e.last_activity_at]){if(t==null)continue;const a=Date.parse(t);Number.isFinite(a)&&a>n&&(n=a)}try{const t=te(j(Se(e.node_id),"telemetry.json"),{throwIfNoEntry:!1});t!==void 0&&t.mtimeMs>n&&(n=t.mtimeMs)}catch{}return n}i(X,"lastActivityMs");async function at(e){const n=e.dryRun??!1,t=await je(),a=await y(t,async l=>await J(l)&&!await e.held(l.node_id)),o=t.length-a.length,r=Math.max(0,e.maxNodes-o),d=a.map(l=>({row:l,recency:X(l)})).sort((l,_)=>_.recency-l.recency).slice(r).map(({row:l})=>({node_id:l.node_id,status:l.status,created:l.created})),c=await K(d);return n||c.length===0?{pruned:c,dryRun:n}:(await G(c),{pruned:c,dryRun:n})}i(at,"pruneToLimit");export{Ie as PARKED_RESIDENT_SQL,En as abandonCreateRequest,sn as assertRunNotDeleting,Fn as browseNodes,wn as canonicalSessionFile,Kn as childrenOf,Vn as claimWarmSpare,vn as clearFinalReportIfMatches,Wn as clearFrozen,fn as completeCreateRequest,dn as createNode,et as deleteNode,nt as deleteNodes,Rn as dueNodeDeadlines,ln as findCreateRequest,yn as findNodeBySessionFile,An as getFinalReport,N as getNode,mn as getRow,Nn as getRowByPane,Cn as graphNodes,J as isCollectible,Yn as isWarmSpare,X as lastActivityMs,qn as listNodeIdentities,je as listNodes,In as listNodesByProfile,Pn as listNodesForSupervision,$n as listParkedResidentsWithWakeMail,Xn as listResumableRoots,Mn as listTerminalPlacementResidue,Jn as listWarmSpares,v as nodeFiles,be as nodesForSupervisionSql,un as pruneExpiredCreateRequests,tt as pruneNodes,at as pruneToLimit,_n as recordCreateRequestNode,xn as recordLaunch,bn as recordRespawnAttempt,Un as recordSettledTurn,zn as registerWarmSpare,k as removeNodeFiles,cn as reserveCreateRequest,pn as reserveCreateRequestNode,hn as rewriteLocalNodeIdentity,Gn as rosterNodes,jn as setFrozen,Dn as setIntent,Sn as setNodeDeadline,kn as setPresence,Ln as setStatus,On as shiftProfileNodeDeadlines,We as terminalPlacementResidueSql,gn as transitionStatusIntent,Bn as unregisterWarmSpare,Tn as updateNode,Hn as updateNodeTelemetry,Qn as warmSpareCount,Zn as withFreshTerminalGuard};
@@ -1,4 +1,3 @@
1
- import { type CanvasDb } from './db.js';
2
1
  import { type DeliverySettlement } from './deliveries.js';
3
2
  import { type DeliveryFailure, type DeliverySettlement as ProcessDeliverySettlement } from './delivery-contract.js';
4
3
  export type DaemonActionState = 'pending' | 'handed_off' | 'acknowledged' | 'permanent_failed';
@@ -29,8 +28,6 @@ export interface DaemonActionRecord {
29
28
  createdAt: number;
30
29
  updatedAt: number;
31
30
  }
32
- /** The table DDL. Shared by the migration that creates it; idempotent. */
33
- export declare function createDaemonActionsTable(db: CanvasDb): Promise<void>;
34
31
  /** Insert one frozen daemon action, due now. A duplicate idempotency key returns the original action id. */
35
32
  export declare function enqueueDaemonAction(input: DaemonActionInput): Promise<string>;
36
33
  export declare function readDaemonAction(idempotencyKey: string): Promise<DaemonActionRecord | null>;