@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
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Placeholder translation for the Postgres engine. Call sites keep SQLite's `?` / `?N` spelling; this turns it into
3
+ * `$n`. Slot semantics follow SQLite: `?N` is always slot N (so one value can be bound to several `?1`), and a bare
4
+ * `?` takes the slot after the highest one used so far. `?` inside single-quoted literals, double-quoted identifiers,
5
+ * dollar-quoted bodies and comments is left alone. Identifiers are never rewritten.
6
+ */
7
+ export interface TranslatedStatement {
8
+ /** SQL with `$n` placeholders. */
9
+ text: string;
10
+ /** Number of parameter slots (the highest slot used). */
11
+ slots: number;
12
+ /** Prepared-statement name on the connection: a hash of the original SQL. */
13
+ name: string;
14
+ }
15
+ export declare function translatePlaceholders(sql: string): TranslatedStatement;
16
+ /** Translation without caching, for generated SQL that is run once. */
17
+ export declare function translateOnce(sql: string): Omit<TranslatedStatement, 'name'>;
@@ -0,0 +1,2 @@
1
+ var s=Object.defineProperty;var f=(t,i)=>s(t,"name",{value:i,configurable:!0});import{createHash as u}from"node:crypto";const h=new Map;function $(t){const i=h.get(t);if(i!==void 0)return i;const r=l(t);return h.set(t,r),r}f($,"translatePlaceholders");function g(t){const{text:i,slots:r}=l(t);return{text:i,slots:r}}f(g,"translateOnce");function l(t){let i="",r=0,n=0;const a=t.length;for(;n<a;){const o=t[n];if(o==="'"||o==='"'){let e=n+1;for(;e<a;e++)if(t[e]===o){if(t[e+1]===o){e++;continue}break}i+=t.slice(n,e+1),n=e+1}else if(o==="-"&&t[n+1]==="-"){let e=t.indexOf(`
2
+ `,n);e===-1&&(e=a),i+=t.slice(n,e),n=e}else if(o==="/"&&t[n+1]==="*"){let e=t.indexOf("*/",n+2);e=e===-1?a:e+2,i+=t.slice(n,e),n=e}else if(o==="$"&&/[A-Za-z_$]/.test(t[n+1]??"")){const e=/^\$[A-Za-z_]*\$/.exec(t.slice(n))?.[0];if(e===void 0){i+=o,n++;continue}let c=t.indexOf(e,n+e.length);c=c===-1?a:c+e.length,i+=t.slice(n,c),n=c}else if(o==="?"){let e=n+1;for(;e<a&&t[e]>="0"&&t[e]<="9";)e++;const c=e>n+1?Number(t.slice(n+1,e)):r+1;if(c<1)throw new Error(`invalid placeholder ?${c} in: ${t}`);c>r&&(r=c),i+=`$${c}`,n=e}else i+=o,n++}return{text:i,slots:r,name:`s${u("sha1").update(t).digest("hex")}`}}f(l,"translate");export{g as translateOnce,$ as translatePlaceholders};
@@ -1,3 +1,3 @@
1
- var $=Object.defineProperty;var r=(n,e)=>$(n,"name",{value:e,configurable:!0});import{canRead as D}from"../../graph/access.js";import{bodyOf as k}from"../../graph/bodies.js";import{resolveName as M,viewOf as m}from"../../graph/names.js";import{rulesForOwners as S,rulesOf as R}from"../../graph/rules.js";import{loadExactProfileManifest as L}from"../../profiles/manifest.js";import{assembleNodeSubject as C}from"../subject.js";import{filterAsync as N,mapAsync as _}from"../../async-array.js";function y(n){return n.type==="node"?n.id:n.name}r(y,"ownerHandle");function H(n){return`${n.type}:${y(n)}`}r(H,"typedLimitKey");function b(n,e,t){if(t?.class==="node"&&t.profile!==null&&t.profile.rowid===e.rowid)return"content";const o=n?.delivery_limits;return o?o[H(e)]??o[y(e)]??"content":"content"}r(b,"deliveryLimitFor");async function h(n,e){if(e.class!=="node"||e.profile===null)return null;const t=await n.prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'profile'").get(e.profile.rowid);if(!t)throw new Error(`profile object ${e.profile.id} has no profile identity`);return L(t.external_id).manifest}r(h,"readerManifest");async function f(n,e,t){return await n.prepareUncached(`SELECT o.*, d.heads_key, d.unlisted, d.source_path FROM objects o JOIN documents d ON d.object = o.rowid
2
- WHERE o.type = 'document' AND o.deleted_at IS NULL AND ${e} ORDER BY o.rowid`).all(...t)}r(f,"documentRows");async function A(n,e){const t=e.heads_key.split(","),o=await n.prepareUncached(`SELECT body_hash FROM revisions WHERE document = ? AND rev_id IN (${t.map(()=>"?").join(",")})
3
- ORDER BY number DESC LIMIT 1`).get(e.rowid,...t);if(!o)throw new Error(`document ${e.id} has no head revision ${e.heads_key}`);return o.body_hash}r(A,"headBodyHash");function E(n,e,t){const o=new Map;return{view:t,readable:r(async i=>{let s=o.get(i.rowid);return s===void 0&&o.set(i.rowid,s=await D(n,e,i)),s},"readable")}}r(E,"resolveContext");async function j(n,e,t,o,i,s){const{view:w}=t,u=w.findIndex(O=>O.rowid===i.owner),l=u>=0?w[u]:await n.prepare("SELECT * FROM objects WHERE rowid = ?").get(i.owner),p=y(l),d=await M(n,e,i.name,t),a=await A(n,i),{heads_key:c,unlisted:g,source_path:v,...x}=i;return{object:x,owner:l,ownerHandle:p,viewRank:u>=0?u:w.length,ownNode:e.class==="node"&&i.owner===e.node.rowid,shipped:v!==null,kind:i.kind==="preference"?"preference":"knowledge",name:i.name,displayName:"object"in d&&d.object.rowid===i.rowid?i.name:`${p}/${i.name}`,preview:i.preview,unlisted:g!==0,headsKey:c,bodyHash:a,body:r(()=>k(a,v),"body"),rules:s,limit:b(o,l,e)}}r(j,"toDeliveryDoc");async function J(n,e,t){const o=await m(n,e),i=E(n,e,o),s=await h(n,e),w=new Map;for(const a of await S(n,t,o.map(c=>c.rowid)))w.set(a.object,[...w.get(a.object)??[],a]);const u=e.class==="node"&&t.includes("boot")?await f(n,"o.owner = ?",[e.node.rowid]):[],l=[...new Set([...w.keys(),...u.map(a=>a.rowid)])],p=l.length===0?[]:await f(n,`o.rowid IN (${l.map(()=>"?").join(",")})`,l),d=new Map(o.map((a,c)=>[a.rowid,c]));return await _((await N(p,i.readable)).sort((a,c)=>d.get(a.owner)-d.get(c.owner)||a.rowid-c.rowid),async a=>await j(n,e,i,s,a,w.get(a.rowid)??[]))}r(J,"loadCorpus");async function P(n,e,t){const o=(await f(n,"o.rowid = ?",[t.rowid]))[0];if(!o)throw new Error(`document ${t.id} has no documents row`);return await j(n,e,E(n,e,await m(n,e)),await h(n,e),o,await R(n,o))}r(P,"deliveryDocOf");async function q(n,e,t){const o=E(n,e,await m(n,e)),i=await h(n,e);return await _(await N(await f(n,"o.owner = ? AND d.unlisted = 0",[t.rowid]),o.readable),async s=>await j(n,e,o,i,s,await R(n,s)))}r(q,"listingCorpus");async function z(n,e){if(e.class!=="node")throw new Error(`nodeSubject needs a node reader, got ${e.class}`);const t=await C(e.node.id,[...e.repos,...e.projectRepos]);if(t===null)throw new Error(`no node ${e.node.id}`);return t}r(z,"nodeSubject");export{P as deliveryDocOf,b as deliveryLimitFor,q as listingCorpus,J as loadCorpus,z as nodeSubject,y as ownerHandle,H as typedLimitKey};
1
+ var $=Object.defineProperty;var s=(n,e)=>$(n,"name",{value:e,configurable:!0});import{canRead as D}from"../../graph/access.js";import{bodyOf as k}from"../../graph/bodies.js";import{resolveName as M,viewOf as m}from"../../graph/names.js";import{rulesForOwners as S,rulesOf as R}from"../../graph/rules.js";import{loadExactProfileManifest as L}from"../../profiles/manifest.js";import{assembleNodeSubject as C}from"../subject.js";import{filterAsync as N,mapAsync as _}from"../../async-array.js";function y(n){return n.type==="node"?n.id:n.name}s(y,"ownerHandle");function H(n){return`${n.type}:${y(n)}`}s(H,"typedLimitKey");function b(n,e,t){if(t?.class==="node"&&t.profile!==null&&t.profile.id===e.id)return"content";const o=n?.delivery_limits;return o?o[H(e)]??o[y(e)]??"content":"content"}s(b,"deliveryLimitFor");async function h(n,e){if(e.class!=="node"||e.profile===null)return null;const t=await n.prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'profile'").get(e.profile.id);if(!t)throw new Error(`profile object ${e.profile.id} has no profile identity`);return L(t.external_id).manifest}s(h,"readerManifest");async function f(n,e,t){return await n.prepareUncached(`SELECT o.*, d.heads_key, d.unlisted, d.source_path FROM objects o JOIN documents d ON d.object = o.id
2
+ WHERE o.type = 'document' AND o.deleted_at IS NULL AND ${e} ORDER BY o.seq`).all(...t)}s(f,"documentRows");async function A(n,e){const t=e.heads_key.split(","),o=await n.prepareUncached(`SELECT body_hash FROM revisions WHERE document = ? AND rev_id IN (${t.map(()=>"?").join(",")})
3
+ ORDER BY number DESC LIMIT 1`).get(e.id,...t);if(!o)throw new Error(`document ${e.id} has no head revision ${e.heads_key}`);return o.body_hash}s(A,"headBodyHash");function E(n,e,t){const o=new Map;return{view:t,readable:s(async i=>{let r=o.get(i.id);return r===void 0&&o.set(i.id,r=await D(n,e,i)),r},"readable")}}s(E,"resolveContext");async function j(n,e,t,o,i,r){const{view:c}=t,u=c.findIndex(O=>O.id===i.owner),w=u>=0?c[u]:await n.prepare("SELECT * FROM objects WHERE id = ?").get(i.owner),d=y(w),p=await M(n,e,i.name,t),a=await A(n,i),{heads_key:l,unlisted:g,source_path:v,...x}=i;return{object:x,owner:w,ownerHandle:d,viewRank:u>=0?u:c.length,ownNode:e.class==="node"&&i.owner===e.node.id,shipped:v!==null,kind:i.kind==="preference"?"preference":"knowledge",name:i.name,displayName:"object"in p&&p.object.id===i.id?i.name:`${d}/${i.name}`,preview:i.preview,unlisted:g!==0,headsKey:l,bodyHash:a,body:s(()=>k(a,v),"body"),rules:r,limit:b(o,w,e)}}s(j,"toDeliveryDoc");async function Y(n,e,t){const o=await m(n,e),i=E(n,e,o),r=await h(n,e),c=new Map;for(const a of await S(n,t,o.map(l=>l.id)))c.set(a.object,[...c.get(a.object)??[],a]);const u=e.class==="node"&&t.includes("boot")?await f(n,"o.owner = ?",[e.node.id]):[],w=[...new Set([...c.keys(),...u.map(a=>a.id)])],d=w.length===0?[]:await f(n,`o.id IN (${w.map(()=>"?").join(",")})`,w),p=new Map(o.map((a,l)=>[a.id,l]));return await _((await N(d,i.readable)).sort((a,l)=>p.get(a.owner)-p.get(l.owner)||a.seq-l.seq),async a=>await j(n,e,i,r,a,c.get(a.id)??[]))}s(Y,"loadCorpus");async function J(n,e,t){const o=(await f(n,"o.id = ?",[t.id]))[0];if(!o)throw new Error(`document ${t.id} has no documents row`);return await j(n,e,E(n,e,await m(n,e)),await h(n,e),o,await R(n,o))}s(J,"deliveryDocOf");async function P(n,e,t){const o=E(n,e,await m(n,e)),i=await h(n,e);return await _(await N(await f(n,"o.owner = ? AND d.unlisted = 0",[t.id]),o.readable),async r=>await j(n,e,o,i,r,await R(n,r)))}s(P,"listingCorpus");async function z(n,e){if(e.class!=="node")throw new Error(`nodeSubject needs a node reader, got ${e.class}`);const t=await C(e.node.id,[...e.repos,...e.projectRepos]);if(t===null)throw new Error(`no node ${e.node.id}`);return t}s(z,"nodeSubject");export{J as deliveryDocOf,b as deliveryLimitFor,P as listingCorpus,Y as loadCorpus,z as nodeSubject,y as ownerHandle,H as typedLimitKey};
@@ -1,6 +1,6 @@
1
- var I=Object.defineProperty;var d=(t,e)=>I(t,"name",{value:e,configurable:!0});import{dirname as L}from"node:path";import{clearLedger as F,demoteTranscript as $,freezePreferences as b,loadLedger as M,saveLedger as P}from"../../graph/exposures.js";import{recordWatch as T}from"../../graph/watches.js";import{publish as H}from"../../graph/events.js";import{viewOf as x}from"../../graph/names.js";import{checkoutsForCwd as y}from"../../graph/repo-sync/repos.js";import{liveLookups as W,profileObject as Y,viewRepos as U}from"../../graph/reader.js";import{ownerForGrantee as B}from"../../graph/objects.js";import{resolveName as G}from"../../graph/names.js";import{SCOPE_VOCABULARY as J}from"../../scopes.js";import{getNode as K}from"../../canvas/index.js";import{recordMemoryReadsIn as V}from"../../canvas/memory-reads.js";import{lookupProfile as X}from"../../profiles/manifest.js";import{getDefaultProfileId as z}from"../../profiles/default-binding.js";import{effectiveScopes as Q,profileNameFor as Z,scopeForCwd as q}from"../subject-fields.js";import{spineDepth as ee}from"../subject.js";import{appForNode as te}from"../../canvas/node-agent-paths.js";import{interpolateNodePaths as oe}from"../../canvas/paths.js";import{readableProjectForScopes as ne}from"../../spaces/permissions.js";import{ApiError as u}from"../../../api/errors.js";import{buildContextBearings as re}from"../../runtime/bearings.js";import{deliveryDocOf as g,listingCorpus as ie,loadCorpus as w,nodeSubject as j}from"./corpus.js";import{listingPrefixes as ae}from"./listings.js";import{planDelivery as se}from"./plan.js";import{renderEvent as N,renderExplicitRead as O}from"./render-event.js";import{renderConfigDelta as ce,renderKnowledge as de,renderPreferences as k,renderWorkspaceOpen as _}from"./render-boot.js";import{mapAsync as le}from"../../async-array.js";function f(t){if(t.class!=="node")throw new Error(`delivery needs a node reader, got ${t.class}`);return t}d(f,"nodeOf");const R=-1;function v(t){return t.node.rowid===R}d(v,"isHypothetical");async function S(t,e){if(!v(e))return await te(e.node.id);const o=await t.prepare("SELECT external_id FROM identities WHERE object = ?").get(e.app.rowid);if(!o)throw new Error(`app object ${e.app.id} has no identity`);return o.external_id}d(S,"granteeOf");async function pe(t,e,o,r=async i=>await y(t,i)){const i=f(e).node,c=new Set,n=new Date().toISOString(),a=[];for(const{doc:s,level:l}of o)l!=="content"||c.has(s.object.rowid)||(c.add(s.object.rowid),await T(t,i,s.object,"deliver",{readHeadsKey:s.headsKey}),await H(t,{event:"read",object:s.object,actor:i,attrs:{}},r),a.push({name:s.name,scope:s.ownerHandle,at:n,type:"loaded"}));v(f(e))||await V(t,i.id,a)}d(pe,"recordContentDelivery");async function E(t,e,o){const r=(await y(t,L(o))).filter(i=>!e.repos.some(c=>c.rowid===i.repo.rowid));return r.length===0?e:{...e,repos:[...e.repos,...r.map(i=>i.repo)],checkouts:[...e.checkouts,...r]}}d(E,"fileReadReader");async function ue(t,e,o){const r=await S(t,e);if(!(o.startsWith("/")&&(process.platform!=="linux"&&r==="app:terminal"||ne(o,r,e.scopes??[],null))))throw new u(403,"scope_missing","read file is outside the run mounts")}d(ue,"assertReadableFile");async function me(t){const e=f(t.reader),o=e.node,r=await S(t.db,e),i=await w(t.db,t.reader,["slash-command"]),c=i.map(n=>{const a=n.body();return{name:n.displayName,command_name:n.displayName,description:n.preview,canonical_body:a,execution_body:oe(a,o.id,r)}});return{docs:i,commands:c}}d(me,"slashCommands");function fe(t){if(t.shipped)return"builtin";switch(t.owner.type){case"node":return"node";case"repo":return"project";case"profile":return"profile";default:return"user"}}d(fe,"scopeOf");async function we(t,e){const o=[],r=new Set;for(const i of await x(t,e)){const c=await ie(t,e,i);for(const n of c){o.push({name:n.displayName,kind:n.kind,scope:fe(n),shortForm:n.preview,gatewayVisible:!n.shipped}),r.add(n.displayName);const a=n.displayName===n.name?"":`${n.ownerHandle}/`;for(const s of ae(c,n.name))r.add(`${a}${s}`)}}return{refs:o,names:[...r]}}d(we,"composerNames");async function C(t,e){const o=f(t.reader),{db:r,ledger:i}=t,c=d(()=>{if(typeof e.subject!="string"||e.subject==="")throw new u(400,"usage",`delivery activity ${e.activity} requires a subject`);return e.subject},"requireSubject");switch(e.activity){case"boot":{if(e.inherited===!0){for(const[s,l]of i.objects)if(l.transcript===void 0)i.objects.delete(s);else{const{system:p,...m}=l;i.objects.set(s,m)}for(const[s,l]of i.listed)l.transcript===void 0?i.listed.delete(s):i.listed.set(s,{transcript:l.transcript});return i.preferenceSnapshot=null,{result:{content:"",inherited:!0},delivered:[]}}const n=v(o)?await ye(t):await re(o.node.id,t),a=await k({...t,channel:"system"});return b(i,a.content),{result:{content:n.content},delivered:[...n.delivered,...a.delivered]}}case"system-prompt":{if(i.preferenceSnapshot!==null)return{result:{content:i.preferenceSnapshot},delivered:[]};const n=await k({...t,channel:"system"});return{result:{content:b(i,n.content)},delivered:n.delivered}}case"compact":{for(const n of await w(r,o,["pre-command"]))$(i,n.object.rowid);return{result:{content:""},delivered:[]}}case"persona":{const n=await ce(t);return{result:{content:n.content},delivered:n.delivered}}case"file-read":{const n=c();await ue(r,o,n);const a=await E(r,o,n),s={...t,reader:a},l=await N(s,"file-read",{absoluteFile:n},await w(r,a,["file-read"]));return{result:{content:l.content},delivered:l.delivered}}case"command":case"pre-command":{const n=await N(t,e.activity,{command:c()});return{result:{content:n.content},delivered:n.delivered}}case"slash-command":{const{docs:n,commands:a}=await me(t);if(e.subject===void 0||e.subject==="")return{result:{content:"",commands:a},delivered:[]};const s=n.findIndex(m=>m.displayName===e.subject||m.name===e.subject);if(s<0)throw new u(404,"not_found",`no slash command named ${e.subject}`);const l=n[s],p=await O(t,l,!0);return{result:{content:"",execution_body:a[s].execution_body,blocks:p.attachments===""?[]:[p.attachments]},delivered:[{doc:l,level:"content"},...p.delivered]}}case"workspace-open":{const n=await _(t);return{result:{content:n.content},delivered:n.delivered}}case"document-read":{const n=await D(r,o,c()),a=await O(t,await g(r,o,n),!0);return{result:{content:a.attachments},delivered:a.delivered}}case"names":return{result:{content:"",...await we(r,o)},delivered:[]};default:throw new u(400,"usage",`unknown delivery activity ${String(e.activity)}`)}}d(C,"render");async function ye(t){const e=await de(t),o=await _(t);return{content:[e.content,o.content].filter(r=>r!=="").join(`
2
- `),delivered:[...e.delivered,...o.delivered]}}d(ye,"hypotheticalBearings");async function D(t,e,o){const r=await G(t,e,o);if("object"in r&&r.object.type==="document")return r.object;throw"ambiguous"in r?new u(409,"ambiguous",`${o} names ${r.ambiguous.length} documents; name one as <type>:<owner>/<name>`):new u(404,"not_found",`no document ${o} the reader can read`)}d(D,"readDocument");const ve=["workspace-open","document-read"];async function Ve(t,e,o){if(ve.includes(o.activity))throw new u(400,"usage",`delivery activity ${o.activity} is available to a dry run only`);const r=f(e).node;o.activity==="boot"&&o.inherited!==!0&&await F(t,r.rowid);const i=await M(t,r.rowid),c={db:t,reader:e,subject:await j(t,e),ledger:i,channel:"transcript"},{result:n,delivered:a}=await C(c,o);return await pe(t,e,a),await P(t,i),n}d(Ve,"deliver");const he={boot:"boot","workspace-open":"workspace-open","file-read":"file-read","document-read":"document-read",command:"command","pre-command":"pre-command","slash-command":"slash-command"};async function Xe(t,e){const o=await K(t);if(o===null)throw new u(404,"not_found",`no node ${t}`);return{cwd:e.cwd??o.cwd,profile:e.profile!==void 0?e.profile:o.profile_id,grantee:e.grantee??o.grantee,kind:e.kind??o.kind,mode:e.mode??o.mode,lifecycle:e.lifecycle??o.lifecycle,hasManager:e.hasManager??(o.parent??null)!==null,depth:e.depth??await ee(t)}}d(Xe,"hypotheticalFrom");function be(t,e){if(t===null)return null;if(t===void 0||t==="")return z(e);const o=X(t);if(o.kind!=="resolved"){const r=`no profile ${t}`;throw new u(404,"not_found",r,{error:"not_found",message:r,next:"List profile ids and names with `crtr profile list`."})}return o.entry.profileId}d(be,"resolveProfileId");async function ze(t,e){const o=await B(t,e.grantee??"app:terminal"),r=be(e.profile,e.cwd),i=await U(e.cwd,r,async p=>await y(t,p),W(t)),{repos:c}=i,n=e.mode??"base",s={class:"node",node:{rowid:R,id:"hypothetical",type:"node",kind:e.kind??"general",owner:o.rowid,privacy:"private",name:"hypothetical",preview:"",created_at:new Date(0).toISOString(),deleted_at:null},app:o,scopes:[...J],cwd:e.cwd,...i,profile:r===null?null:await Y(t,r,o)},l={kind:e.kind??"general",mode:n,lifecycle:e.lifecycle??(n==="orchestrator"?"resident":"terminal"),hasManager:e.hasManager??!0,cwd:e.cwd,scope:q(e.cwd),orchestration:{depth:e.depth??0},profile:Z(r),scopes:Q(null),repo:[...c,...i.projectRepos].map(p=>p.name)};return{reader:s,subject:l}}d(ze,"hypotheticalReader");async function Qe(t,e,o,r,i){const n={node:f(e).node.rowid,preferenceSnapshot:null,objects:new Map,listed:new Map},a={...i??await j(t,e),...r},s={db:t,reader:e,subject:a,ledger:n,channel:"transcript"},{result:l}=await C(s,o),p=he[o.activity];let m=null;if(p!==void 0){const A=o.activity==="file-read"?{absoluteFile:o.subject}:o.activity==="command"||o.activity==="pre-command"?{command:o.subject}:o.activity==="document-read"&&o.subject!==void 0?{doc:await g(t,e,await D(t,e,o.subject))}:{},h=o.activity==="file-read"&&o.subject!==void 0?await E(t,f(e),o.subject):e;m=await se(t,a,h,await w(t,h,[p]),p,A)}return{result:l,plan:m}}d(Qe,"inspect");async function Ze(t,e,o){const r=await t.prepare(`SELECT o.*, MAX(r.number) AS to_seq, GROUP_CONCAT(DISTINCT a.id) AS authors
3
- FROM watches w JOIN objects o ON o.rowid = w.object AND o.type = 'document' AND o.deleted_at IS NULL
4
- JOIN revisions r ON r.document = o.rowid LEFT JOIN objects a ON a.rowid = r.author
1
+ var A=Object.defineProperty;var d=(t,e)=>A(t,"name",{value:e,configurable:!0});import{dirname as L}from"node:path";import{clearLedger as F,demoteTranscript as $,freezePreferences as b,loadLedger as M,saveLedger as P}from"../../graph/exposures.js";import{recordWatch as T}from"../../graph/watches.js";import{publish as H}from"../../graph/events.js";import{viewOf as x}from"../../graph/names.js";import{checkoutsForCwd as y}from"../../graph/repo-sync/repos.js";import{liveLookups as W,profileObject as Y,viewRepos as B}from"../../graph/reader.js";import{ownerForGrantee as U}from"../../graph/objects.js";import{resolveName as J}from"../../graph/names.js";import{SCOPE_VOCABULARY as K}from"../../scopes.js";import{getNode as V}from"../../canvas/index.js";import{recordMemoryReadsIn as G}from"../../canvas/memory-reads.js";import{lookupProfile as X}from"../../profiles/manifest.js";import{getDefaultProfileId as z}from"../../profiles/default-binding.js";import{effectiveScopes as Q,profileNameFor as Z,scopeForCwd as q}from"../subject-fields.js";import{spineDepth as ee}from"../subject.js";import{appForNode as te}from"../../canvas/node-agent-paths.js";import{interpolateNodePaths as ne}from"../../canvas/paths.js";import{readableProjectForScopes as oe}from"../../spaces/permissions.js";import{ApiError as u}from"../../../api/errors.js";import{buildContextBearings as re}from"../../runtime/bearings.js";import{deliveryDocOf as g,listingCorpus as ae,loadCorpus as w,nodeSubject as j}from"./corpus.js";import{listingPrefixes as ie}from"./listings.js";import{planDelivery as se}from"./plan.js";import{renderEvent as N,renderExplicitRead as k}from"./render-event.js";import{renderConfigDelta as ce,renderKnowledge as de,renderPreferences as O,renderWorkspaceOpen as _}from"./render-boot.js";import{mapAsync as le}from"../../async-array.js";function f(t){if(t.class!=="node")throw new Error(`delivery needs a node reader, got ${t.class}`);return t}d(f,"nodeOf");const S="hypothetical";function v(t){return t.node.id===S}d(v,"isHypothetical");async function R(t,e){if(!v(e))return await te(e.node.id);const n=await t.prepare("SELECT external_id FROM identities WHERE object = ?").get(e.app.id);if(!n)throw new Error(`app object ${e.app.id} has no identity`);return n.external_id}d(R,"granteeOf");async function pe(t,e,n,r=async a=>await y(t,a)){const a=f(e).node,c=new Set,o=new Date().toISOString(),i=[];for(const{doc:s,level:l}of n)l!=="content"||c.has(s.object.id)||(c.add(s.object.id),await T(t,a,s.object,"deliver",{readHeadsKey:s.headsKey}),await H(t,{event:"read",object:s.object,actor:a,attrs:{}},r),i.push({name:s.name,scope:s.ownerHandle,at:o,type:"loaded"}));v(f(e))||await G(t,a.id,i)}d(pe,"recordContentDelivery");async function E(t,e,n){const r=(await y(t,L(n))).filter(a=>!e.repos.some(c=>c.id===a.repo.id));return r.length===0?e:{...e,repos:[...e.repos,...r.map(a=>a.repo)],checkouts:[...e.checkouts,...r]}}d(E,"fileReadReader");async function ue(t,e,n){const r=await R(t,e);if(!(n.startsWith("/")&&(process.platform!=="linux"&&r==="app:terminal"||oe(n,r,e.scopes??[],null))))throw new u(403,"scope_missing","read file is outside the run mounts")}d(ue,"assertReadableFile");async function me(t){const e=f(t.reader),n=e.node,r=await R(t.db,e),a=await w(t.db,t.reader,["slash-command"]),c=a.map(o=>{const i=o.body();return{name:o.displayName,command_name:o.displayName,description:o.preview,canonical_body:i,execution_body:ne(i,n.id,r)}});return{docs:a,commands:c}}d(me,"slashCommands");function fe(t){if(t.shipped)return"builtin";switch(t.owner.type){case"node":return"node";case"repo":return"project";case"profile":return"profile";default:return"user"}}d(fe,"scopeOf");async function we(t,e){const n=[],r=new Set;for(const a of await x(t,e)){const c=await ae(t,e,a);for(const o of c){n.push({name:o.displayName,kind:o.kind,scope:fe(o),shortForm:o.preview,gatewayVisible:!o.shipped}),r.add(o.displayName);const i=o.displayName===o.name?"":`${o.ownerHandle}/`;for(const s of ie(c,o.name))r.add(`${i}${s}`)}}return{refs:n,names:[...r]}}d(we,"composerNames");async function D(t,e){const n=f(t.reader),{db:r,ledger:a}=t,c=d(()=>{if(typeof e.subject!="string"||e.subject==="")throw new u(400,"usage",`delivery activity ${e.activity} requires a subject`);return e.subject},"requireSubject");switch(e.activity){case"boot":{if(e.inherited===!0){for(const[s,l]of a.objects)if(l.transcript===void 0)a.objects.delete(s);else{const{system:p,...m}=l;a.objects.set(s,m)}for(const[s,l]of a.listed)l.transcript===void 0?a.listed.delete(s):a.listed.set(s,{transcript:l.transcript});return a.preferenceSnapshot=null,{result:{content:"",inherited:!0},delivered:[]}}const o=v(n)?await ye(t):await re(n.node.id,t),i=await O({...t,channel:"system"});return b(a,i.content),{result:{content:o.content},delivered:[...o.delivered,...i.delivered]}}case"system-prompt":{if(a.preferenceSnapshot!==null)return{result:{content:a.preferenceSnapshot},delivered:[]};const o=await O({...t,channel:"system"});return{result:{content:b(a,o.content)},delivered:o.delivered}}case"compact":{for(const o of await w(r,n,["pre-command"]))$(a,o.object.id);return{result:{content:""},delivered:[]}}case"persona":{const o=await ce(t);return{result:{content:o.content},delivered:o.delivered}}case"file-read":{const o=c();await ue(r,n,o);const i=await E(r,n,o),s={...t,reader:i},l=await N(s,"file-read",{absoluteFile:o},await w(r,i,["file-read"]));return{result:{content:l.content},delivered:l.delivered}}case"command":case"pre-command":{const o=await N(t,e.activity,{command:c()});return{result:{content:o.content},delivered:o.delivered}}case"slash-command":{const{docs:o,commands:i}=await me(t);if(e.subject===void 0||e.subject==="")return{result:{content:"",commands:i},delivered:[]};const s=o.findIndex(m=>m.displayName===e.subject||m.name===e.subject);if(s<0)throw new u(404,"not_found",`no slash command named ${e.subject}`);const l=o[s],p=await k(t,l,!0);return{result:{content:"",execution_body:i[s].execution_body,blocks:p.attachments===""?[]:[p.attachments]},delivered:[{doc:l,level:"content"},...p.delivered]}}case"workspace-open":{const o=await _(t);return{result:{content:o.content},delivered:o.delivered}}case"document-read":{const o=await C(r,n,c()),i=await k(t,await g(r,n,o),!0);return{result:{content:i.attachments},delivered:i.delivered}}case"names":return{result:{content:"",...await we(r,n)},delivered:[]};default:throw new u(400,"usage",`unknown delivery activity ${String(e.activity)}`)}}d(D,"render");async function ye(t){const e=await de(t),n=await _(t);return{content:[e.content,n.content].filter(r=>r!=="").join(`
2
+ `),delivered:[...e.delivered,...n.delivered]}}d(ye,"hypotheticalBearings");async function C(t,e,n){const r=await J(t,e,n);if("object"in r&&r.object.type==="document")return r.object;throw"ambiguous"in r?new u(409,"ambiguous",`${n} names ${r.ambiguous.length} documents; name one as <type>:<owner>/<name>`):new u(404,"not_found",`no document ${n} the reader can read`)}d(C,"readDocument");const ve=["workspace-open","document-read"];async function Ge(t,e,n){if(ve.includes(n.activity))throw new u(400,"usage",`delivery activity ${n.activity} is available to a dry run only`);const r=f(e).node;n.activity==="boot"&&n.inherited!==!0&&await F(t,r.id);const a=await M(t,r.id),c={db:t,reader:e,subject:await j(t,e),ledger:a,channel:"transcript"},{result:o,delivered:i}=await D(c,n);return await pe(t,e,i),await P(t,a),o}d(Ge,"deliver");const he={boot:"boot","workspace-open":"workspace-open","file-read":"file-read","document-read":"document-read",command:"command","pre-command":"pre-command","slash-command":"slash-command"};async function Xe(t,e){const n=await V(t);if(n===null)throw new u(404,"not_found",`no node ${t}`);return{cwd:e.cwd??n.cwd,profile:e.profile!==void 0?e.profile:n.profile_id,grantee:e.grantee??n.grantee,kind:e.kind??n.kind,mode:e.mode??n.mode,lifecycle:e.lifecycle??n.lifecycle,hasManager:e.hasManager??(n.parent??null)!==null,depth:e.depth??await ee(t)}}d(Xe,"hypotheticalFrom");function be(t,e){if(t===null)return null;if(t===void 0||t==="")return z(e);const n=X(t);if(n.kind!=="resolved"){const r=`no profile ${t}`;throw new u(404,"not_found",r,{error:"not_found",message:r,next:"List profile ids and names with `crtr profile list`."})}return n.entry.profileId}d(be,"resolveProfileId");async function ze(t,e){const n=await U(t,e.grantee??"app:terminal"),r=be(e.profile,e.cwd),a=await B(e.cwd,r,async p=>await y(t,p),W(t)),{repos:c}=a,o=e.mode??"base",s={class:"node",node:{id:S,seq:0,type:"node",kind:e.kind??"general",owner:n.id,privacy:"private",name:"hypothetical",preview:"",created_at:new Date(0).toISOString(),deleted_at:null},app:n,scopes:[...K],cwd:e.cwd,...a,profile:r===null?null:await Y(t,r,n)},l={kind:e.kind??"general",mode:o,lifecycle:e.lifecycle??(o==="orchestrator"?"resident":"terminal"),hasManager:e.hasManager??!0,cwd:e.cwd,scope:q(e.cwd),orchestration:{depth:e.depth??0},profile:Z(r),scopes:Q(null),repo:[...c,...a.projectRepos].map(p=>p.name)};return{reader:s,subject:l}}d(ze,"hypotheticalReader");async function Qe(t,e,n,r,a){const o={node:f(e).node.id,preferenceSnapshot:null,objects:new Map,listed:new Map},i={...a??await j(t,e),...r},s={db:t,reader:e,subject:i,ledger:o,channel:"transcript"},{result:l}=await D(s,n),p=he[n.activity];let m=null;if(p!==void 0){const I=n.activity==="file-read"?{absoluteFile:n.subject}:n.activity==="command"||n.activity==="pre-command"?{command:n.subject}:n.activity==="document-read"&&n.subject!==void 0?{doc:await g(t,e,await C(t,e,n.subject))}:{},h=n.activity==="file-read"&&n.subject!==void 0?await E(t,f(e),n.subject):e;m=await se(t,i,h,await w(t,h,[p]),p,I)}return{result:l,plan:m}}d(Qe,"inspect");async function Ze(t,e,n){const r=await t.prepare(`SELECT o.*, MAX(r.number) AS to_seq, string_agg(DISTINCT a.id, ',') AS authors
3
+ FROM watches w JOIN objects o ON o.id = w.object AND o.type = 'document' AND o.deleted_at IS NULL
4
+ JOIN revisions r ON r.document = o.id LEFT JOIN objects a ON a.id = r.author
5
5
  WHERE w.watcher = ? AND r.created_at > ? AND (r.author IS NULL OR r.author != ?)
6
- GROUP BY o.rowid ORDER BY o.rowid`).all(e.rowid,o,e.rowid);return await le(r,async({to_seq:i,authors:c,...n})=>{const a=await t.prepare("SELECT MAX(number) AS seq FROM revisions WHERE document = ? AND created_at <= ?").get(n.rowid,o);return{doc:n,from:a.seq,to:i,authors:c===null?[]:c.split(",")}})}d(Ze,"changedWhileDone");export{ve as DRY_RUN_ONLY,Ze as changedWhileDone,Ve as deliver,Xe as hypotheticalFrom,ze as hypotheticalReader,Qe as inspect,pe as recordContentDelivery};
6
+ GROUP BY o.id ORDER BY o.seq`).all(e.id,n,e.id);return await le(r,async({to_seq:a,authors:c,...o})=>{const i=await t.prepare("SELECT MAX(number) AS seq FROM revisions WHERE document = ? AND created_at <= ?").get(o.id,n);return{doc:o,from:i.seq,to:a,authors:c===null?[]:c.split(",")}})}d(Ze,"changedWhileDone");export{ve as DRY_RUN_ONLY,Ze as changedWhileDone,Ge as deliver,Xe as hypotheticalFrom,ze as hypotheticalReader,Qe as inspect,pe as recordContentDelivery};
@@ -1,4 +1,4 @@
1
- var x=Object.defineProperty;var o=(n,e)=>x(n,"name",{value:e,configurable:!0});import{heldAtOrAbove as v,hold as j}from"../../graph/exposures.js";function p(n){return n.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}o(p,"attr");function k(n,e){return`${n.owner.id}/${e}`}o(k,"listingKey");function f(n,e){return e!==""&&n.some(r=>r.name.startsWith(`${e}/`))}o(f,"isPrefix");function A(n,e){const r=e.split("/");return r.map((s,l)=>r.slice(0,r.length-l).join("/")).filter(s=>f(n,s))}o(A,"listingPrefixes");function N(n,e){return n.displayName===n.name?e:`${n.ownerHandle}/${e}`}o(N,"listingLabel");function B(n,e,r,u,s){const l=new Map(n.map(t=>[t.name,t])),g=[...new Set(n.filter(t=>t.name.startsWith(`${e}/`)).map(t=>`${e}/${t.name.slice(e.length+1).split("/")[0]}`))].sort(),m=g.filter(t=>!f(n,t)),y=g.filter(t=>f(n,t)),a=[],d=[],h=o(t=>{if(t===void 0||t.unlisted)return null;const i={object:t.object.rowid,headsKey:t.headsKey,contentHash:t.bodyHash};return s&&v(r,i,"preview")?null:(j(r,u,i,"preview"),d.push(t),t.preview.trim())},"suffix"),$=o((t,i)=>i===null||i===""?`[[${t}]]`:`[[${t}]]: ${i}`,"line");for(const t of m){const i=l.get(t),c=h(i);c!==null&&a.push($(i.displayName,c))}for(const t of y){const i=l.get(t),c=i??n.find(w=>w.name.startsWith(`${t}/`));a.push($(i?.displayName??N(c,t),h(i)))}return{lines:a,previewed:d}}o(B,"renderListing");function H(n,e){return`<memory-listing dir="${p(n)}">
1
+ var x=Object.defineProperty;var o=(n,e)=>x(n,"name",{value:e,configurable:!0});import{heldAtOrAbove as v,hold as j}from"../../graph/exposures.js";function p(n){return n.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}o(p,"attr");function k(n,e){return`${n.owner.id}/${e}`}o(k,"listingKey");function f(n,e){return e!==""&&n.some(r=>r.name.startsWith(`${e}/`))}o(f,"isPrefix");function A(n,e){const r=e.split("/");return r.map((s,l)=>r.slice(0,r.length-l).join("/")).filter(s=>f(n,s))}o(A,"listingPrefixes");function N(n,e){return n.displayName===n.name?e:`${n.ownerHandle}/${e}`}o(N,"listingLabel");function B(n,e,r,u,s){const l=new Map(n.map(t=>[t.name,t])),g=[...new Set(n.filter(t=>t.name.startsWith(`${e}/`)).map(t=>`${e}/${t.name.slice(e.length+1).split("/")[0]}`))].sort(),m=g.filter(t=>!f(n,t)),y=g.filter(t=>f(n,t)),a=[],d=[],h=o(t=>{if(t===void 0||t.unlisted)return null;const i={object:t.object.id,headsKey:t.headsKey,contentHash:t.bodyHash};return s&&v(r,i,"preview")?null:(j(r,u,i,"preview"),d.push(t),t.preview.trim())},"suffix"),$=o((t,i)=>i===null||i===""?`[[${t}]]`:`[[${t}]]: ${i}`,"line");for(const t of m){const i=l.get(t),c=h(i);c!==null&&a.push($(i.displayName,c))}for(const t of y){const i=l.get(t),c=i??n.find(w=>w.name.startsWith(`${t}/`));a.push($(i?.displayName??N(c,t),h(i)))}return{lines:a,previewed:d}}o(B,"renderListing");function H(n,e){return`<memory-listing dir="${p(n)}">
2
2
  ${e.join(`
3
3
  `)}
4
4
  </memory-listing>`}o(H,"listingBlock");function P(n,e,r){return r.length===0?H(n,e):`<memory-listing ${e.length>0?`dir="${p(n)}" `:""}linked-from="${p(n)}">
@@ -8,8 +8,8 @@ export interface MatchPayload {
8
8
  absoluteFile?: string;
9
9
  /** `file-read`: the read file's own frontmatter (empty for a non-markdown file). */
10
10
  readFrontmatter?: Record<string, unknown>;
11
- /** `file-read`: checkout root of each repo object (by rowid) that encloses the read file. */
12
- repoRoots?: ReadonlyMap<number, string>;
11
+ /** `file-read`: checkout root of each repo object (by id) that encloses the read file. */
12
+ repoRoots?: ReadonlyMap<string, string>;
13
13
  /** `document-read`: the document that was delivered or read. */
14
14
  doc?: DeliveryDoc;
15
15
  /** `command` / `pre-command`: the command string. */
@@ -1 +1 @@
1
- var d=Object.defineProperty;var o=(t,s)=>d(t,"name",{value:s,configurable:!0});import{basename as h,isAbsolute as p,matchesGlob as g,relative as w}from"node:path";import{evalCondition as l}from"../../predicate.js";import{commandSegments as $,stripHeredocs as G}from"../../shell-segments.js";function R(t,s){if(t.if===void 0)return{pass:!0};if(s===null)return{pass:!1,reason:"rule `if` with no node config to match"};try{return l(t.if,s)?{pass:!0}:{pass:!1,reason:"rule `if` does not match this node config"}}catch(i){return{pass:!1,reason:`rule \`if\` failed to evaluate: ${String(i)}`}}}o(R,"ruleGate");function a(t,s){try{return g(t,s)}catch{return!1}}o(a,"safeGlob");function M(t){const s=t.trim().split(/\s+/);if(s.length===1&&s[0]==="")return null;const i=[];for(const n of s){const e=n.split("*");for(let r=0;r<e.length;r+=1)e[r]!==""&&i.push({kind:"literal",text:e[r]}),r<e.length-1&&i.push({kind:"any"})}return i}o(M,"commandGlobPattern");function y(t,s){const i=t.split("").map(n=>n==="?"?"[\\s\\S]":n.replace(/[.+^${}()|[\]\\]/g,"\\$&")).join("");return new RegExp(`^${i}$`).test(s)}o(y,"tokenMatches");function F(t,s){const i=new Map,n=o((e,r)=>{const f=`${e}:${r}`,m=i.get(f);if(m!==void 0)return m;let c;if(e===t.length)c=r===s.length;else if(t[e].kind==="any")c=n(e+1,r)||r<s.length&&n(e,r+1);else{const u=s[r];c=u!==void 0&&!u.opaque&&y(t[e].text,u.text)&&n(e+1,r+1)}return i.set(f,c),c},"match");return n(0,0)}o(F,"segmentMatches");function W(t,s){const i=M(t);return i===null?!1:$(s).filter(({tokens:n})=>n.length>0).some(({tokens:n})=>F(i,n))}o(W,"commandGlobMatches");function b(t,s,i,n){if(t.startsWith("./")){const e=s.owner.type==="repo"?i.repoRoots?.get(s.owner.rowid):void 0;if(e===void 0)return!1;const r=w(e,n);return r===""||r.startsWith("..")||p(r)?!1:a(r,t.slice(2))}return a(n,t)||a(h(n),t)}o(b,"fileGlobMatches");function v(t,s,i){const n=`${i.ownerHandle}/${i.name}`;if(t.startsWith("./")){const e=`${s.ownerHandle}/`;return n.startsWith(e)&&a(n.slice(e.length),t.slice(2))}return a(i.displayName,t)||a(n,t)}o(v,"documentGlobMatches");function j(t,s,i,n){if(t.on!==i)return!1;switch(i){case"boot":case"workspace-open":case"slash-command":return!0;case"file-read":{const e=n.absoluteFile;if(e===void 0||t.match!==void 0&&!t.match.some(r=>b(r,s,n,e)))return!1;if(t.matchFrontmatter!==void 0){const r=n.readFrontmatter??{};if(Object.keys(r).length===0||!l(t.matchFrontmatter,r))return!1}return t.match!==void 0||t.matchFrontmatter!==void 0}case"document-read":{const e=n.doc;return e!==void 0&&t.match!==void 0&&t.match.some(r=>v(r,s,e))}case"command":case"pre-command":{const e=n.command;if(e===void 0||t.match===void 0)return!1;const r=i==="pre-command"?G(e):e;return t.match.some(f=>W(f,r))}}}o(j,"ruleConstraintsFit");export{j as ruleConstraintsFit,R as ruleGate};
1
+ var d=Object.defineProperty;var o=(t,s)=>d(t,"name",{value:s,configurable:!0});import{basename as h,isAbsolute as p,matchesGlob as g,relative as w}from"node:path";import{evalCondition as l}from"../../predicate.js";import{commandSegments as $,stripHeredocs as G}from"../../shell-segments.js";function R(t,s){if(t.if===void 0)return{pass:!0};if(s===null)return{pass:!1,reason:"rule `if` with no node config to match"};try{return l(t.if,s)?{pass:!0}:{pass:!1,reason:"rule `if` does not match this node config"}}catch(i){return{pass:!1,reason:`rule \`if\` failed to evaluate: ${String(i)}`}}}o(R,"ruleGate");function a(t,s){try{return g(t,s)}catch{return!1}}o(a,"safeGlob");function M(t){const s=t.trim().split(/\s+/);if(s.length===1&&s[0]==="")return null;const i=[];for(const n of s){const e=n.split("*");for(let r=0;r<e.length;r+=1)e[r]!==""&&i.push({kind:"literal",text:e[r]}),r<e.length-1&&i.push({kind:"any"})}return i}o(M,"commandGlobPattern");function y(t,s){const i=t.split("").map(n=>n==="?"?"[\\s\\S]":n.replace(/[.+^${}()|[\]\\]/g,"\\$&")).join("");return new RegExp(`^${i}$`).test(s)}o(y,"tokenMatches");function F(t,s){const i=new Map,n=o((e,r)=>{const f=`${e}:${r}`,m=i.get(f);if(m!==void 0)return m;let c;if(e===t.length)c=r===s.length;else if(t[e].kind==="any")c=n(e+1,r)||r<s.length&&n(e,r+1);else{const u=s[r];c=u!==void 0&&!u.opaque&&y(t[e].text,u.text)&&n(e+1,r+1)}return i.set(f,c),c},"match");return n(0,0)}o(F,"segmentMatches");function W(t,s){const i=M(t);return i===null?!1:$(s).filter(({tokens:n})=>n.length>0).some(({tokens:n})=>F(i,n))}o(W,"commandGlobMatches");function b(t,s,i,n){if(t.startsWith("./")){const e=s.owner.type==="repo"?i.repoRoots?.get(s.owner.id):void 0;if(e===void 0)return!1;const r=w(e,n);return r===""||r.startsWith("..")||p(r)?!1:a(r,t.slice(2))}return a(n,t)||a(h(n),t)}o(b,"fileGlobMatches");function v(t,s,i){const n=`${i.ownerHandle}/${i.name}`;if(t.startsWith("./")){const e=`${s.ownerHandle}/`;return n.startsWith(e)&&a(n.slice(e.length),t.slice(2))}return a(i.displayName,t)||a(n,t)}o(v,"documentGlobMatches");function j(t,s,i,n){if(t.on!==i)return!1;switch(i){case"boot":case"workspace-open":case"slash-command":return!0;case"file-read":{const e=n.absoluteFile;if(e===void 0||t.match!==void 0&&!t.match.some(r=>b(r,s,n,e)))return!1;if(t.matchFrontmatter!==void 0){const r=n.readFrontmatter??{};if(Object.keys(r).length===0||!l(t.matchFrontmatter,r))return!1}return t.match!==void 0||t.matchFrontmatter!==void 0}case"document-read":{const e=n.doc;return e!==void 0&&t.match!==void 0&&t.match.some(r=>v(r,s,e))}case"command":case"pre-command":{const e=n.command;if(e===void 0||t.match===void 0)return!1;const r=i==="pre-command"?G(e):e;return t.match.some(f=>W(f,r))}}}o(j,"ruleConstraintsFit");export{j as ruleConstraintsFit,R as ruleGate};
@@ -1,3 +1,3 @@
1
- var p=Object.defineProperty;var d=(e,i)=>p(e,"name",{value:i,configurable:!0});import{dirname as h}from"node:path";import{parseFrontmatterGeneric as w}from"../../frontmatter.js";import{readText as g,realpathOrSelf as R}from"../../fs-utils.js";import{checkoutChain as b}from"../../graph/repo-sync/identity.js";import{minRung as k,rungAtLeast as N,rungRank as m}from"../schema.js";import{ruleConstraintsFit as O,ruleGate as F}from"./match.js";function E(e){return e.doc.ownNode?"knowledge":e.doc.kind}d(E,"bootPartitionOf");async function L(e,i,t,a,o,n={}){const r=await v(e,o,n),c=(o==="document-read"&&n.doc!==void 0?a.filter(u=>u.object.rowid!==n.doc.object.rowid):a).map(u=>j(u,i,o,r));return W(o,c),{on:o,subject:i,reader:t,docs:c}}d(L,"planDelivery");async function v(e,i,t){if(i!=="file-read"||t.absoluteFile===void 0)return t;const a=R(t.absoluteFile);return{...t,absoluteFile:a,readFrontmatter:t.readFrontmatter??x(a),repoRoots:await y(e,a)}}d(v,"resolvePayload");function x(e){if(!/\.(md|mdx|markdown)$/i.test(e))return{};try{return w(g(e)).data??{}}catch{return{}}}d(x,"readFileFrontmatter");async function y(e,i){const t=new Map,a=e.prepare(`SELECT o.rowid FROM identities i JOIN objects o ON o.rowid = i.object
2
- WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`);for(const n of b(h(i))){if(!n.ok)break;const r=await a.get(n.scheme,n.externalId);r!==void 0&&!t.has(r.rowid)&&t.set(r.rowid,n.root)}const o=await e.prepare(`SELECT o.rowid, i.external_id AS path FROM identities i JOIN objects o ON o.rowid = i.object
3
- WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{rowid:n,path:r}of o)!t.has(n)&&i.startsWith(r.endsWith("/")?r:`${r}/`)&&t.set(n,r);return t}d(y,"repoRootsOf");function j(e,i,t,a){const o=e.rules.filter(s=>s.on===t).map(s=>{const f=F(s,i);return{rule:s,gate:f,matched:f.pass&&O(s,e,t,a)}});let n=null;for(const{rule:s,matched:f}of o)f&&(n===null||m(s.deliver)>m(n.deliver))&&(n=s);const r=n?.deliver??"none",l=(t==="boot"||t==="workspace-open")&&!e.ownNode?e.limit:null,c=l===null?r:k(r,l),u=t==="boot"&&e.ownNode&&o.length===0?"name":c;return{doc:e,authoredRules:o,matchedRule:n,authoredRung:r,limit:l,cappedRung:c,ruleGate:o.length===0?null:n!==null?{pass:!0}:o.find(s=>!s.gate.pass)?.gate??{pass:!0},finalRung:u,winner:!1,shadowedBy:null}}d(j,"decide");function A(e,i){if(i==="boot"){const t=e.authoredRules.length>0&&e.authoredRules.every(a=>!a.gate.pass);return e.limit!=="none"&&!t}return N(e.finalRung,"name")}d(A,"holdsName");function W(e,i){const t=e==="boot"||e==="workspace-open",a=new Map;for(const o of i){if(!A(o,e))continue;if(!t){o.winner=!0;continue}const n=e==="boot"?`${E(o)}:${o.doc.name}`:o.doc.name,r=a.get(n);r===void 0?(a.set(n,o),o.winner=!0):o.shadowedBy=r.doc}}d(W,"resolveWinners");export{E as bootPartitionOf,L as planDelivery};
1
+ var p=Object.defineProperty;var d=(e,i)=>p(e,"name",{value:i,configurable:!0});import{dirname as h}from"node:path";import{parseFrontmatterGeneric as w}from"../../frontmatter.js";import{readText as g,realpathOrSelf as R}from"../../fs-utils.js";import{checkoutChain as b}from"../../graph/repo-sync/identity.js";import{minRung as k,rungAtLeast as N,rungRank as m}from"../schema.js";import{ruleConstraintsFit as O,ruleGate as F}from"./match.js";function E(e){return e.doc.ownNode?"knowledge":e.doc.kind}d(E,"bootPartitionOf");async function L(e,i,t,a,n,o={}){const r=await v(e,n,o),c=(n==="document-read"&&o.doc!==void 0?a.filter(u=>u.object.id!==o.doc.object.id):a).map(u=>j(u,i,n,r));return W(n,c),{on:n,subject:i,reader:t,docs:c}}d(L,"planDelivery");async function v(e,i,t){if(i!=="file-read"||t.absoluteFile===void 0)return t;const a=R(t.absoluteFile);return{...t,absoluteFile:a,readFrontmatter:t.readFrontmatter??x(a),repoRoots:await y(e,a)}}d(v,"resolvePayload");function x(e){if(!/\.(md|mdx|markdown)$/i.test(e))return{};try{return w(g(e)).data??{}}catch{return{}}}d(x,"readFileFrontmatter");async function y(e,i){const t=new Map,a=e.prepare(`SELECT o.id FROM identities i JOIN objects o ON o.id = i.object
2
+ WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`);for(const o of b(h(i))){if(!o.ok)break;const r=await a.get(o.scheme,o.externalId);r!==void 0&&!t.has(r.id)&&t.set(r.id,o.root)}const n=await e.prepare(`SELECT o.id, i.external_id AS path FROM identities i JOIN objects o ON o.id = i.object
3
+ WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{id:o,path:r}of n)!t.has(o)&&i.startsWith(r.endsWith("/")?r:`${r}/`)&&t.set(o,r);return t}d(y,"repoRootsOf");function j(e,i,t,a){const n=e.rules.filter(s=>s.on===t).map(s=>{const f=F(s,i);return{rule:s,gate:f,matched:f.pass&&O(s,e,t,a)}});let o=null;for(const{rule:s,matched:f}of n)f&&(o===null||m(s.deliver)>m(o.deliver))&&(o=s);const r=o?.deliver??"none",l=(t==="boot"||t==="workspace-open")&&!e.ownNode?e.limit:null,c=l===null?r:k(r,l),u=t==="boot"&&e.ownNode&&n.length===0?"name":c;return{doc:e,authoredRules:n,matchedRule:o,authoredRung:r,limit:l,cappedRung:c,ruleGate:n.length===0?null:o!==null?{pass:!0}:n.find(s=>!s.gate.pass)?.gate??{pass:!0},finalRung:u,winner:!1,shadowedBy:null}}d(j,"decide");function A(e,i){if(i==="boot"){const t=e.authoredRules.length>0&&e.authoredRules.every(a=>!a.gate.pass);return e.limit!=="none"&&!t}return N(e.finalRung,"name")}d(A,"holdsName");function W(e,i){const t=e==="boot"||e==="workspace-open",a=new Map;for(const n of i){if(!A(n,e))continue;if(!t){n.winner=!0;continue}const o=e==="boot"?`${E(n)}:${n.doc.name}`:n.doc.name,r=a.get(o);r===void 0?(a.set(o,n),n.winner=!0):n.shadowedBy=r.doc}}d(W,"resolveWinners");export{E as bootPartitionOf,L as planDelivery};
@@ -1,7 +1,7 @@
1
- var Y=Object.defineProperty;var l=(e,s)=>Y(e,"name",{value:s,configurable:!0});import{heldAtOrAbove as $,hold as _,freezePreferences as F}from"../../graph/exposures.js";import{interpolateNodePaths as z}from"../../canvas/paths.js";import{buildSubPersonaMenu as B}from"./sub-persona-menu.js";import{rungAtLeast as k}from"../schema.js";import{loadCorpus as A}from"./corpus.js";import{listingPrefixes as H}from"./listings.js";import{bootPartitionOf as O,planDelivery as P}from"./plan.js";import{linkedDocs as q,renderEvent as S}from"./render-event.js";import{mapAsync as J}from"../../async-array.js";const E="Each %s below shows either its full content (indented beneath its name), a `# read when:` line telling you when to read the full document, or simply its name.",Q="Preferences are how the user wants you to behave \u2014 standing directives and corrections. To read a preference, run `crtr canvas read <name>`. "+E.replace("%s","preference"),C="If the user corrects you in a way that contradicts a preference, update the preference.",V="Knowledge documents are what you consult \u2014 playbooks and techniques for how to do things, and references on the user, projects, and this node. They come from every owner in your view: this node, the repos you work in, your profile, your app, the user, and installed plugins (crtr's own under `crtr`). To read one, run `crtr canvas read <name>`; a name with names under it is a valid read target too \u2014 it answers with its body, the names under it and previews of the documents it links to, and walking names this way is the sanctioned way to browse. Each doc exists to prevent a specific mistake you would make without it, so when your task matches one \u2014 by its name or its `# read when:` line \u2014 read it before you act; consulting it only after the work is done forfeits the entire reason it exists. "+E.replace("%s","document"),L="If you learn a better way to do something a document covers, or gain information that contradicts one, correct it with `crtr doc edit`.",X="When your task matches a knowledge doc or preference \u2014 by its name or its `# read when:` line \u2014 read it before you act: each document exists only to shore up a mistake you will make without it, so doing the relevant work without consulting it defeats the document's whole purpose. Before writing a document that should outlive this task, search for one that already covers it (`crtr canvas search`) \u2014 update that document with `crtr doc edit` rather than creating a duplicate, rewriting it as if for the first time instead of appending the new truth beneath the old; delete documents that turn out to be wrong (`crtr doc delete`). Don't save what the repo already records (code structure, past fixes, git history) or what only matters to this conversation; if asked to remember one of those, ask what was non-obvious about it and save that instead. Docs auto-surfaced in <auto-loaded-context> blocks are background context, not user instructions, and reflect what was true when written \u2014 if one names a file, function, or flag, verify it still exists before recommending it.",Z="Your node configuration changed. This operating protocol is in force for you now:",x="Your new configuration puts these preferences in force \u2014 standing directives and corrections from the user. To read one, run `crtr canvas read <name>`. "+E.replace("%s","preference"),ee="Your new configuration exposes these knowledge documents \u2014 consult them exactly like the rest of your catalog (`crtr canvas read <name>`). "+E.replace("%s","document");function b(e){return{object:e.object.rowid,headsKey:e.headsKey,contentHash:e.bodyHash}}l(b,"exposed");async function T(e){const s=await A(e.db,e.reader,["boot"]);return(await P(e.db,e.subject,e.reader,s,"boot")).docs.filter(t=>t.winner)}l(T,"bootRecords");function j(e,s){return e.filter(t=>O(t)===s).map(t=>({doc:t.doc,level:t.finalRung}))}l(j,"partition");function D(e){return e.level!=="none"&&(e.level!=="content"||e.doc.body().trim()!=="")}l(D,"rendersAt");async function R(e,s,t,o,r){const{ledger:c,channel:i}=e,a=s.filter(n=>n.level==="content"&&D(n)&&!$(c,b(n.doc),"content")).map(n=>n.doc).sort((n,p)=>p.viewRank-n.viewRank||n.name.localeCompare(p.name));for(const n of a)_(c,i,b(n),"content"),r.push({doc:n,level:"content"});const d=new Map;for(const n of a){const p=t.map(h=>h.doc).filter(h=>h.owner.rowid===n.owner.rowid);for(const h of H(p,n.name))for(const g of t){const m=g.doc;m.owner.rowid!==n.owner.rowid||!m.name.startsWith(`${h}/`)||m.name.slice(h.length+1).includes("/")||g.level==="content"||k(g.level,"preview")||m.unlisted||!m.ownNode&&!k(m.limit,"preview")||$(c,b(m),"preview")||d.set(m.object.rowid,{doc:m,level:"preview",cause:"directory listing attached to content delivery"})}}const u=new Map(t.map(n=>[n.doc.object.rowid,n])),v=new Set(a.map(n=>n.object.rowid));for(const n of a)for(const p of await q(e.db,e.reader,n)){const h=p.object.rowid,g=u.get(h);d.has(h)||v.has(h)||g!==void 0&&k(g.level,"preview")||O({doc:p})===O({doc:n})&&(!p.ownNode&&!k(p.limit,"preview")||$(c,b(p),"preview")||d.set(h,{doc:g?.doc??p,level:"preview",cause:"link preview attached to content delivery"}))}const y=(await J(a,async n=>await S(e,"document-read",{doc:n}))).flatMap(({content:n,delivered:p})=>(r.push(...p),n===""?[]:[n])),w=s.filter(n=>n.level!=="content").map(n=>d.get(n.doc.object.rowid)??n),f=new Set(w.map(n=>n.doc.object.rowid));w.push(...[...d.values()].filter(n=>!f.has(n.doc.object.rowid)));for(const n of w)D(n)&&(_(c,i,b(n.doc),n.level),r.push({doc:n.doc,level:n.level,...n.cause===void 0?{}:{cause:n.cause}}));return{content:a,attachments:y,tree:te(w,o)}}l(R,"renderGrouped");function I(e){return{segment:e,own:null,dirs:new Map,leaves:new Map,hidden:0,renders:!1,count:0}}l(I,"newDir");const ne=l(e=>k(e,"name"),"visible");function M(e,s){let t=e.hidden;for(const o of e.dirs.values())t+=M(o,e.segment==="");return e.renders=e.own!==null||e.leaves.size>0||[...e.dirs.values()].some(o=>o.renders)||s||e.segment==="",e.count=e.renders?t:0,e.renders?0:t}l(M,"resolveDir");function G(e,s,t){const o=e.level==="preview"?e.doc.preview.trim():"";return o===""?`${t}${s}`:`${t}${s} # read when: ${o}`}l(G,"entryLine");function K(e,s,t){const o=[...[...e.dirs.values()].filter(r=>r.renders).map(r=>({name:r.segment,dir:r})),...[...e.leaves].map(([r,c])=>({name:r,leaf:c}))].sort((r,c)=>r.name.localeCompare(c.name));e.count>0&&o.push({name:"",more:e.count}),o.forEach((r,c)=>{const i=c===o.length-1,a=s+(i?"\u2514\u2500 ":"\u251C\u2500 ");if("more"in r)t.push(`${a}[+${r.more} more]`);else if(r.dir!==void 0){const d=`${r.dir.segment}/`;t.push(r.dir.own===null?`${a}${d}`:G(r.dir.own,d,a)),K(r.dir,s+(i?" ":"\u2502 "),t)}else t.push(G(r.leaf,r.name,a))})}l(K,"renderChildren");function te(e,s){if(e.length===0)return"";const t=I(""),o=l(i=>{let a=t;for(const d of i){let u=a.dirs.get(d);u===void 0&&a.dirs.set(d,u=I(d)),a=u}return a},"dirAt"),r=new Set(e.map(i=>i.doc.displayName));for(const i of e){const a=i.doc.displayName.split("/"),d=[...r].some(u=>u.startsWith(`${i.doc.displayName}/`));ne(i.level)?d?o(a).own=i:o(a.slice(0,-1)).leaves.set(a[a.length-1],i):o(d?a:a.slice(0,-1)).hidden+=1}M(t,!1);const c=[s];return K(t,"",c),c.join(`
2
- `)}l(te,"buildTree");function N(e,s){const{reader:t}=e;return t.class==="node"?z(s,t.node.id,t.app.name):s}l(N,"interpolate");function W(e){return e.shipped}l(W,"isShipped");function U(e){const s=e.content.filter(W).map(o=>o.body().trim()).filter(o=>o!==""),t=e.content.filter(o=>!W(o)).map(o=>o.body().trim()===""?"":`<preference name="${o.displayName}">
1
+ var Y=Object.defineProperty;var l=(e,s)=>Y(e,"name",{value:s,configurable:!0});import{heldAtOrAbove as $,hold as _,freezePreferences as q}from"../../graph/exposures.js";import{interpolateNodePaths as F}from"../../canvas/paths.js";import{buildSubPersonaMenu as z}from"./sub-persona-menu.js";import{rungAtLeast as k}from"../schema.js";import{loadCorpus as A}from"./corpus.js";import{listingPrefixes as B}from"./listings.js";import{bootPartitionOf as O,planDelivery as P}from"./plan.js";import{linkedDocs as H,renderEvent as S}from"./render-event.js";import{mapAsync as J}from"../../async-array.js";const E="Each %s below shows either its full content (indented beneath its name), a `# read when:` line telling you when to read the full document, or simply its name.",Q="Preferences are how the user wants you to behave \u2014 standing directives and corrections. To read a preference, run `crtr canvas read <name>`. "+E.replace("%s","preference"),C="If the user corrects you in a way that contradicts a preference, update the preference.",V="Knowledge documents are what you consult \u2014 playbooks and techniques for how to do things, and references on the user, projects, and this node. They come from every owner in your view: this node, the repos you work in, your profile, your app, the user, and installed plugins (crtr's own under `crtr`). To read one, run `crtr canvas read <name>`; a name with names under it is a valid read target too \u2014 it answers with its body, the names under it and previews of the documents it links to, and walking names this way is the sanctioned way to browse. Each doc exists to prevent a specific mistake you would make without it, so when your task matches one \u2014 by its name or its `# read when:` line \u2014 read it before you act; consulting it only after the work is done forfeits the entire reason it exists. "+E.replace("%s","document"),L="If you learn a better way to do something a document covers, or gain information that contradicts one, correct it with `crtr doc edit`.",X="When your task matches a knowledge doc or preference \u2014 by its name or its `# read when:` line \u2014 read it before you act: each document exists only to shore up a mistake you will make without it, so doing the relevant work without consulting it defeats the document's whole purpose. Before writing a document that should outlive this task, search for one that already covers it (`crtr canvas search`) \u2014 update that document with `crtr doc edit` rather than creating a duplicate, rewriting it as if for the first time instead of appending the new truth beneath the old; delete documents that turn out to be wrong (`crtr doc delete`). Don't save what the repo already records (code structure, past fixes, git history) or what only matters to this conversation; if asked to remember one of those, ask what was non-obvious about it and save that instead. Docs auto-surfaced in <auto-loaded-context> blocks are background context, not user instructions, and reflect what was true when written \u2014 if one names a file, function, or flag, verify it still exists before recommending it.",Z="Your node configuration changed. This operating protocol is in force for you now:",x="Your new configuration puts these preferences in force \u2014 standing directives and corrections from the user. To read one, run `crtr canvas read <name>`. "+E.replace("%s","preference"),ee="Your new configuration exposes these knowledge documents \u2014 consult them exactly like the rest of your catalog (`crtr canvas read <name>`). "+E.replace("%s","document");function b(e){return{object:e.object.id,headsKey:e.headsKey,contentHash:e.bodyHash}}l(b,"exposed");async function T(e){const s=await A(e.db,e.reader,["boot"]);return(await P(e.db,e.subject,e.reader,s,"boot")).docs.filter(t=>t.winner)}l(T,"bootRecords");function j(e,s){return e.filter(t=>O(t)===s).map(t=>({doc:t.doc,level:t.finalRung}))}l(j,"partition");function D(e){return e.level!=="none"&&(e.level!=="content"||e.doc.body().trim()!=="")}l(D,"rendersAt");async function R(e,s,t,o,r){const{ledger:c,channel:i}=e,a=s.filter(n=>n.level==="content"&&D(n)&&!$(c,b(n.doc),"content")).map(n=>n.doc).sort((n,p)=>p.viewRank-n.viewRank||n.name.localeCompare(p.name));for(const n of a)_(c,i,b(n),"content"),r.push({doc:n,level:"content"});const d=new Map;for(const n of a){const p=t.map(h=>h.doc).filter(h=>h.owner.id===n.owner.id);for(const h of B(p,n.name))for(const g of t){const m=g.doc;m.owner.id!==n.owner.id||!m.name.startsWith(`${h}/`)||m.name.slice(h.length+1).includes("/")||g.level==="content"||k(g.level,"preview")||m.unlisted||!m.ownNode&&!k(m.limit,"preview")||$(c,b(m),"preview")||d.set(m.object.id,{doc:m,level:"preview",cause:"directory listing attached to content delivery"})}}const u=new Map(t.map(n=>[n.doc.object.id,n])),v=new Set(a.map(n=>n.object.id));for(const n of a)for(const p of await H(e.db,e.reader,n)){const h=p.object.id,g=u.get(h);d.has(h)||v.has(h)||g!==void 0&&k(g.level,"preview")||O({doc:p})===O({doc:n})&&(!p.ownNode&&!k(p.limit,"preview")||$(c,b(p),"preview")||d.set(h,{doc:g?.doc??p,level:"preview",cause:"link preview attached to content delivery"}))}const y=(await J(a,async n=>await S(e,"document-read",{doc:n}))).flatMap(({content:n,delivered:p})=>(r.push(...p),n===""?[]:[n])),w=s.filter(n=>n.level!=="content").map(n=>d.get(n.doc.object.id)??n),f=new Set(w.map(n=>n.doc.object.id));w.push(...[...d.values()].filter(n=>!f.has(n.doc.object.id)));for(const n of w)D(n)&&(_(c,i,b(n.doc),n.level),r.push({doc:n.doc,level:n.level,...n.cause===void 0?{}:{cause:n.cause}}));return{content:a,attachments:y,tree:te(w,o)}}l(R,"renderGrouped");function I(e){return{segment:e,own:null,dirs:new Map,leaves:new Map,hidden:0,renders:!1,count:0}}l(I,"newDir");const ne=l(e=>k(e,"name"),"visible");function M(e,s){let t=e.hidden;for(const o of e.dirs.values())t+=M(o,e.segment==="");return e.renders=e.own!==null||e.leaves.size>0||[...e.dirs.values()].some(o=>o.renders)||s||e.segment==="",e.count=e.renders?t:0,e.renders?0:t}l(M,"resolveDir");function G(e,s,t){const o=e.level==="preview"?e.doc.preview.trim():"";return o===""?`${t}${s}`:`${t}${s} # read when: ${o}`}l(G,"entryLine");function K(e,s,t){const o=[...[...e.dirs.values()].filter(r=>r.renders).map(r=>({name:r.segment,dir:r})),...[...e.leaves].map(([r,c])=>({name:r,leaf:c}))].sort((r,c)=>r.name.localeCompare(c.name));e.count>0&&o.push({name:"",more:e.count}),o.forEach((r,c)=>{const i=c===o.length-1,a=s+(i?"\u2514\u2500 ":"\u251C\u2500 ");if("more"in r)t.push(`${a}[+${r.more} more]`);else if(r.dir!==void 0){const d=`${r.dir.segment}/`;t.push(r.dir.own===null?`${a}${d}`:G(r.dir.own,d,a)),K(r.dir,s+(i?" ":"\u2502 "),t)}else t.push(G(r.leaf,r.name,a))})}l(K,"renderChildren");function te(e,s){if(e.length===0)return"";const t=I(""),o=l(i=>{let a=t;for(const d of i){let u=a.dirs.get(d);u===void 0&&a.dirs.set(d,u=I(d)),a=u}return a},"dirAt"),r=new Set(e.map(i=>i.doc.displayName));for(const i of e){const a=i.doc.displayName.split("/"),d=[...r].some(u=>u.startsWith(`${i.doc.displayName}/`));ne(i.level)?d?o(a).own=i:o(a.slice(0,-1)).leaves.set(a[a.length-1],i):o(d?a:a.slice(0,-1)).hidden+=1}M(t,!1);const c=[s];return K(t,"",c),c.join(`
2
+ `)}l(te,"buildTree");function N(e,s){const{reader:t}=e;return t.class==="node"?F(s,t.node.id,t.app.name):s}l(N,"interpolate");function W(e){return e.shipped}l(W,"isShipped");function U(e){const s=e.content.filter(W).map(o=>o.body().trim()).filter(o=>o!==""),t=e.content.filter(o=>!W(o)).map(o=>o.body().trim()===""?"":`<preference name="${o.displayName}">
3
3
  ${o.body().trim()}
4
- </preference>`).filter(o=>o!=="");return{shipped:s,editable:t}}l(U,"preferenceParts");async function pe(e){if(e.ledger.preferenceSnapshot!==null)return{content:e.ledger.preferenceSnapshot,delivered:[]};const s={...e,channel:"system"},t=[];let o=[],r=X;if(e.subject!==null){const i=j(await T(s),"preference"),a=await R(s,i,i,"preferences",t),{shipped:d,editable:u}=U(a),v=B(e.subject.kind);o=[...d,...a.attachments,...v===""?[]:[v]],(u.length>0||a.tree!=="")&&(r+=`
4
+ </preference>`).filter(o=>o!=="");return{shipped:s,editable:t}}l(U,"preferenceParts");async function pe(e){if(e.ledger.preferenceSnapshot!==null)return{content:e.ledger.preferenceSnapshot,delivered:[]};const s={...e,channel:"system"},t=[];let o=[],r=X;if(e.subject!==null){const i=j(await T(s),"preference"),a=await R(s,i,i,"preferences",t),{shipped:d,editable:u}=U(a),v=z(e.subject.kind);o=[...d,...a.attachments,...v===""?[]:[v]],(u.length>0||a.tree!=="")&&(r+=`
5
5
 
6
6
  ${Q}`,u.length>0&&(r+=`
7
7
 
@@ -15,7 +15,7 @@ ${C}`)}const c=[...o,`<memory kind="preference">
15
15
  ${r}
16
16
  </memory>`].join(`
17
17
 
18
- `);return{content:F(e.ledger,N(e,c)),delivered:t}}l(pe,"renderPreferences");async function he(e){const s=[],t=j(await T(e),"knowledge"),o=await R(e,t,t,"knowledge",s),r=[...o.content.map(i=>i.body().trim()),...o.attachments].filter(i=>i!=="");if(r.length===0&&o.tree==="")return{content:"",delivered:s};let c=V;return r.length>0&&(c+=`
18
+ `);return{content:q(e.ledger,N(e,c)),delivered:t}}l(pe,"renderPreferences");async function he(e){const s=[],t=j(await T(e),"knowledge"),o=await R(e,t,t,"knowledge",s),r=[...o.content.map(i=>i.body().trim()),...o.attachments].filter(i=>i!=="");if(r.length===0&&o.tree==="")return{content:"",delivered:s};let c=V;return r.length>0&&(c+=`
19
19
 
20
20
  ${r.join(`
21
21
 
@@ -25,7 +25,7 @@ ${o.tree}`),c+=`
25
25
 
26
26
  ${L}`,{content:N(e,`<memory kind="knowledge">
27
27
  ${c}
28
- </memory>`),delivered:s}}l(he,"renderKnowledge");async function me(e){const s=await A(e.db,e.reader,["workspace-open"]),t=(await P(e.db,e.subject,e.reader,s,"workspace-open")).docs.filter(c=>c.winner).map(c=>c.doc).sort((c,i)=>i.viewRank-c.viewRank||c.object.rowid-i.object.rowid),{content:o,delivered:r}=await S(e,"workspace-open",{},t);return{content:N(e,o),delivered:r}}l(me,"renderWorkspaceOpen");async function we(e){const{ledger:s}=e,t=[],o=await T(e),r=l(f=>f.filter(n=>D(n)&&!$(s,b(n.doc),n.level)),"fresh"),c=j(o,"preference"),i=await R(e,r(c),c,"preferences",t),{shipped:a,editable:d}=U(i),u=[];if((a.length>0||i.attachments.length>0)&&u.push(`${Z}
28
+ </memory>`),delivered:s}}l(he,"renderKnowledge");async function me(e){const s=await A(e.db,e.reader,["workspace-open"]),t=(await P(e.db,e.subject,e.reader,s,"workspace-open")).docs.filter(c=>c.winner).map(c=>c.doc).sort((c,i)=>i.viewRank-c.viewRank||c.object.seq-i.object.seq),{content:o,delivered:r}=await S(e,"workspace-open",{},t);return{content:N(e,o),delivered:r}}l(me,"renderWorkspaceOpen");async function we(e){const{ledger:s}=e,t=[],o=await T(e),r=l(f=>f.filter(n=>D(n)&&!$(s,b(n.doc),n.level)),"fresh"),c=j(o,"preference"),i=await R(e,r(c),c,"preferences",t),{shipped:a,editable:d}=U(i),u=[];if((a.length>0||i.attachments.length>0)&&u.push(`${Z}
29
29
 
30
30
  ${[...a,...i.attachments].join(`
31
31
 
@@ -1,8 +1,8 @@
1
- var N=Object.defineProperty;var s=(e,n)=>N(e,"name",{value:n,configurable:!0});import{canRead as D}from"../../graph/access.js";import{heldAtOrAbove as b,hold as y,holdListing as E,listedAtOrAbove as O}from"../../graph/exposures.js";import{deliveryDocOf as H,listingCorpus as K,loadCorpus as g}from"./corpus.js";import{listingBlock as L,ownSetBlock as R,listingKey as C,listingLabel as x,listingPrefixes as P,renderListing as k}from"./listings.js";import{planDelivery as B}from"./plan.js";import{filterAsync as M,mapAsync as S}from"../../async-array.js";function v(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}s(v,"attr");function W(e,n){let t=`kind="${v(e.kind)}" name="${v(e.displayName)}"`;if(n==="content"){const i=e.body().trim();if(i!=="")return`<memory ${t}>
2
- ${i}
3
- </memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${v(e.preview.trim())}"`);return`<memory ${t} />`}s(W,"renderEnvelope");function j(e){return e.length===0?"":`<auto-loaded-context>
1
+ var N=Object.defineProperty;var s=(e,n)=>N(e,"name",{value:n,configurable:!0});import{canRead as D}from"../../graph/access.js";import{heldAtOrAbove as g,hold as v,holdListing as E,listedAtOrAbove as O}from"../../graph/exposures.js";import{deliveryDocOf as H,listingCorpus as K,loadCorpus as w}from"./corpus.js";import{listingBlock as L,ownSetBlock as R,listingKey as C,listingLabel as x,listingPrefixes as P,renderListing as k}from"./listings.js";import{planDelivery as B}from"./plan.js";import{filterAsync as M,mapAsync as S}from"../../async-array.js";function b(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}s(b,"attr");function W(e,n){let t=`kind="${b(e.kind)}" name="${b(e.displayName)}"`;if(n==="content"){const r=e.body().trim();if(r!=="")return`<memory ${t}>
2
+ ${r}
3
+ </memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${b(e.preview.trim())}"`);return`<memory ${t} />`}s(W,"renderEnvelope");function j(e){return e.length===0?"":`<auto-loaded-context>
4
4
  ${e.join(`
5
5
  `)}
6
- </auto-loaded-context>`}s(j,"wrapAutoLoaded");async function I(e,n){let t=e.members.get(n.owner.rowid);return t===void 0&&(t=await K(e.ctx.db,e.ctx.reader,n.owner),e.members.set(n.owner.rowid,t)),t}s(I,"membersOf");async function _(e,n,t){const i=await e.prepare(`SELECT o.* FROM edges e JOIN objects o ON o.rowid = e.dst
7
- WHERE e.type = 'links-to' AND e.src = ? AND o.type = 'document' AND o.deleted_at IS NULL AND o.rowid <> ?
8
- ORDER BY e.written_as`).all(t.object.rowid,t.object.rowid);return await S(await M(i,async o=>await D(e,n,o)),async o=>await H(e,n,o))}s(_,"linkedDocs");function q(e,n){return n.owner.rowid===e.owner.rowid&&n.name.startsWith(`${e.name}/`)&&!n.name.slice(e.name.length+1).includes("/")}s(q,"underOwnPrefix");async function F(e,n){const{ledger:t,channel:i}=e.ctx,o=[],c=[];for(const r of await _(e.ctx.db,e.ctx.reader,n)){if(q(n,r)&&!r.unlisted)continue;const l={object:r.object.rowid,headsKey:r.headsKey,contentHash:r.bodyHash};if(b(t,l,"preview"))continue;y(t,i,l,"preview"),e.delivered.push({doc:r,level:"preview",cause:"link preview attached to content delivery"}),c.push(r);const a=r.preview.trim();o.push(a===""?`[[${r.displayName}]]`:`[[${r.displayName}]]: ${a}`)}return{lines:o,linked:c}}s(F,"linkPreviews");async function A(e,n,t){const{ledger:i,channel:o}=e.ctx,c=await I(e,n),r=[];let l,a=[];for(const m of P(c,n.name)){const p=m===n.name,f=C(n,m);if(!(p&&t)&&O(i,f,"preview"))continue;const{lines:d,previewed:u}=k(c,m,i,o,!(p&&t));for(const w of u)e.delivered.push({doc:w,level:"preview",cause:"directory listing attached to content delivery"});d.length!==0&&(E(i,o,f,"preview"),p?a=d:r.push(L(x(n,m),d)))}const h=await F(e,n);return t?a.length>0&&(l=a):a.length+h.lines.length>0&&r.unshift(R(x(n,n.name),a,h.lines)),e.chainCorpus??=await g(e.ctx.db,e.ctx.reader,["document-read"]),r.push(...await $(e,e.chainCorpus,"document-read",{doc:n},"memory-read companion of content delivery")),{blocks:r,...l===void 0?{}:{listing:l},linked:h.linked}}s(A,"attachments");async function $(e,n,t,i,o){const{db:c,reader:r,subject:l,ledger:a,channel:h}=e.ctx,m=await B(c,l,r,n,t,i),p=[];for(const f of m.docs){const d=f.finalRung;if(!f.winner||d==="none")continue;const{doc:u}=f,w={object:u.object.rowid,headsKey:u.headsKey,contentHash:u.bodyHash};b(a,w,d)||(y(a,h,w,d),e.delivered.push({doc:u,level:d,...o===void 0?{}:{cause:o}}),d==="content"&&p.push(...(await A(e,u,!1)).blocks),p.push(W(u,d)))}return p}s($,"renderPlan");async function V(e,n,t,i){i??=await g(e.db,e.reader,[n]);const o={ctx:e,delivered:[],members:new Map};return{content:j(await $(o,i,n,t)),delivered:o.delivered}}s(V,"renderEvent");async function X(e,n,t=!1){const i={ctx:e,delivered:[],members:new Map};y(e.ledger,e.channel,{object:n.object.rowid,headsKey:n.headsKey,contentHash:n.bodyHash},"content");const{blocks:o,listing:c,linked:r}=await A(i,n,!t);return{attachments:j(o),...c===void 0?{}:{listing:c},linked:r,delivered:i.delivered}}s(X,"renderExplicitRead");export{_ as linkedDocs,W as renderEnvelope,V as renderEvent,X as renderExplicitRead,j as wrapAutoLoaded};
6
+ </auto-loaded-context>`}s(j,"wrapAutoLoaded");async function I(e,n){let t=e.members.get(n.owner.id);return t===void 0&&(t=await K(e.ctx.db,e.ctx.reader,n.owner),e.members.set(n.owner.id,t)),t}s(I,"membersOf");async function _(e,n,t){const r=await e.prepare(`SELECT o.* FROM edges e JOIN objects o ON o.id = e.dst
7
+ WHERE e.type = 'links-to' AND e.src = ? AND o.type = 'document' AND o.deleted_at IS NULL AND o.id <> ?
8
+ ORDER BY e.written_as`).all(t.object.id,t.object.id);return await S(await M(r,async o=>await D(e,n,o)),async o=>await H(e,n,o))}s(_,"linkedDocs");function q(e,n){return n.owner.id===e.owner.id&&n.name.startsWith(`${e.name}/`)&&!n.name.slice(e.name.length+1).includes("/")}s(q,"underOwnPrefix");async function F(e,n){const{ledger:t,channel:r}=e.ctx,o=[],c=[];for(const i of await _(e.ctx.db,e.ctx.reader,n)){if(q(n,i)&&!i.unlisted)continue;const l={object:i.object.id,headsKey:i.headsKey,contentHash:i.bodyHash};if(g(t,l,"preview"))continue;v(t,r,l,"preview"),e.delivered.push({doc:i,level:"preview",cause:"link preview attached to content delivery"}),c.push(i);const a=i.preview.trim();o.push(a===""?`[[${i.displayName}]]`:`[[${i.displayName}]]: ${a}`)}return{lines:o,linked:c}}s(F,"linkPreviews");async function A(e,n,t){const{ledger:r,channel:o}=e.ctx,c=await I(e,n),i=[];let l,a=[];for(const m of P(c,n.name)){const p=m===n.name,f=C(n,m);if(!(p&&t)&&O(r,f,"preview"))continue;const{lines:d,previewed:u}=k(c,m,r,o,!(p&&t));for(const y of u)e.delivered.push({doc:y,level:"preview",cause:"directory listing attached to content delivery"});d.length!==0&&(E(r,o,f,"preview"),p?a=d:i.push(L(x(n,m),d)))}const h=await F(e,n);return t?a.length>0&&(l=a):a.length+h.lines.length>0&&i.unshift(R(x(n,n.name),a,h.lines)),e.chainCorpus??=await w(e.ctx.db,e.ctx.reader,["document-read"]),i.push(...await $(e,e.chainCorpus,"document-read",{doc:n},"memory-read companion of content delivery")),{blocks:i,...l===void 0?{}:{listing:l},linked:h.linked}}s(A,"attachments");async function $(e,n,t,r,o){const{db:c,reader:i,subject:l,ledger:a,channel:h}=e.ctx,m=await B(c,l,i,n,t,r),p=[];for(const f of m.docs){const d=f.finalRung;if(!f.winner||d==="none")continue;const{doc:u}=f,y={object:u.object.id,headsKey:u.headsKey,contentHash:u.bodyHash};g(a,y,d)||(v(a,h,y,d),e.delivered.push({doc:u,level:d,...o===void 0?{}:{cause:o}}),d==="content"&&p.push(...(await A(e,u,!1)).blocks),p.push(W(u,d)))}return p}s($,"renderPlan");async function V(e,n,t,r){r??=await w(e.db,e.reader,[n]);const o={ctx:e,delivered:[],members:new Map};return{content:j(await $(o,r,n,t)),delivered:o.delivered}}s(V,"renderEvent");async function X(e,n,t=!1){const r={ctx:e,delivered:[],members:new Map};v(e.ledger,e.channel,{object:n.object.id,headsKey:n.headsKey,contentHash:n.bodyHash},"content");const{blocks:o,listing:c,linked:i}=await A(r,n,!t);return{attachments:j(o),...c===void 0?{}:{listing:c},linked:i,delivered:r.delivered}}s(X,"renderExplicitRead");export{_ as linkedDocs,W as renderEnvelope,V as renderEvent,X as renderExplicitRead,j as wrapAutoLoaded};
@@ -1,10 +1,10 @@
1
- var h=Object.defineProperty;var a=(e,t)=>h(e,"name",{value:t,configurable:!0});import{withCanvasWrite as q,openDb as d}from"../canvas/db.js";import{RunError as _}from"../runs/operations.js";const w="app:terminal";function r(e=new Date){return e.toISOString().slice(0,7)}a(r,"usageMonth");function l(e){const[t,n]=e.split("-").map(Number);return new Date(Date.UTC(t,n,1)).toISOString()}a(l,"resetAt");async function k(e,t,n=new Date){const u=r(n);await e.prepare(`INSERT INTO usage (grantee, month, payer, source, served_model, input_tokens, output_tokens, cached_tokens, usd_equivalent)
1
+ var f=Object.defineProperty;var a=(e,t)=>f(e,"name",{value:t,configurable:!0});import{withCanvasWrite as h,openDb as d}from"../canvas/db.js";import{RunError as _}from"../runs/operations.js";const q="app:terminal";function r(e=new Date){return e.toISOString().slice(0,7)}a(r,"usageMonth");function l(e){const[t,n]=e.split("-").map(Number);return new Date(Date.UTC(t,n,1)).toISOString()}a(l,"resetAt");async function w(e,t,n=new Date){const u=r(n);await e.prepare(`INSERT INTO usage (grantee, month, payer, source, served_model, input_tokens, output_tokens, cached_tokens, usd_equivalent)
2
2
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
3
3
  ON CONFLICT(grantee, month, payer, source, served_model) DO UPDATE SET
4
- input_tokens = input_tokens + excluded.input_tokens,
5
- output_tokens = output_tokens + excluded.output_tokens,
6
- cached_tokens = cached_tokens + excluded.cached_tokens,
7
- usd_equivalent = CASE WHEN usd_equivalent IS NULL AND excluded.usd_equivalent IS NULL THEN NULL
8
- ELSE COALESCE(usd_equivalent, 0) + COALESCE(excluded.usd_equivalent, 0) END`).run(t.grantee,u,t.payer,t.source,t.served_model,t.input_tokens,t.output_tokens,t.cached_tokens,t.usd_equivalent),t.payer==="user"&&t.source==="model"&&t.usd_equivalent!==null&&t.usd_equivalent>0&&await e.prepare(`INSERT INTO grantee_usage (grantee, month, usd_equivalent) VALUES (?, ?, ?)
9
- ON CONFLICT(grantee, month) DO UPDATE SET usd_equivalent = usd_equivalent + excluded.usd_equivalent`).run(t.grantee,u,t.usd_equivalent)}a(k,"addUsage");async function g(e,t,n,u,s){await q(async p=>await k(p,{grantee:e,payer:t,source:"model",served_model:n,input_tokens:u.input,output_tokens:u.output,cached_tokens:u.cacheRead,usd_equivalent:s}))}a(g,"recordModelUsage");async function c(e,t=r()){return(await(await d()).prepare("SELECT usd_equivalent FROM grantee_usage WHERE grantee = ? AND month = ?").get(e,t))?.usd_equivalent??0}a(c,"monthSpend");function m(e){return e.grantee===w?null:e.spend_cap}a(m,"effectiveCap");async function x(e,t=new Date){if(!e)return;const n=m(e);if(n===null)return;const u=r(t),s=await c(e.grantee,u);if(!(s<n))throw new _(402,"cap_exhausted",`${e.grantee} reached its monthly usage limit`,void 0,{spend_cap:n,usd_equivalent:s,reset_at:l(u)})}a(x,"assertUnderCap");async function C(e,t,n=r()){const u=await(await d()).prepare(`SELECT payer, source, served_model, input_tokens, output_tokens, usd_equivalent
10
- FROM usage WHERE grantee = ? AND month = ? ORDER BY served_model`).all(e,n),s=a(i=>u.filter(o=>o.payer===i&&o.source==="model").map(({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:f})=>({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:f})),"byModel"),p=u.filter(i=>i.payer==="app").reduce((i,o)=>i+(o.usd_equivalent??0),0);return{grantee:e,month:n,usd_equivalent:await c(e,n),by_model:s("user"),app_paid:{usd_equivalent:p,by_model:s("app")},spend_cap:m({grantee:e,spend_cap:t}),reset_at:l(n)}}a(C,"usageFor");function D(e){if(e===null)return r();if(!/^[1-9]\d{3}-(0[1-9]|1[0-2])$/.test(e))throw new _(400,"invalid_request","month must be YYYY-MM","month");return e}a(D,"parseUsageMonth");export{w as UNCAPPED_GRANTEE,k as addUsage,x as assertUnderCap,m as effectiveCap,c as monthSpend,D as parseUsageMonth,g as recordModelUsage,l as resetAt,C as usageFor,r as usageMonth};
4
+ input_tokens = usage.input_tokens + excluded.input_tokens,
5
+ output_tokens = usage.output_tokens + excluded.output_tokens,
6
+ cached_tokens = usage.cached_tokens + excluded.cached_tokens,
7
+ usd_equivalent = CASE WHEN usage.usd_equivalent IS NULL AND excluded.usd_equivalent IS NULL THEN NULL
8
+ ELSE COALESCE(usage.usd_equivalent, 0) + COALESCE(excluded.usd_equivalent, 0) END`).run(t.grantee,u,t.payer,t.source,t.served_model,t.input_tokens,t.output_tokens,t.cached_tokens,t.usd_equivalent),t.payer==="user"&&t.source==="model"&&t.usd_equivalent!==null&&t.usd_equivalent>0&&await e.prepare(`INSERT INTO grantee_usage (grantee, month, usd_equivalent) VALUES (?, ?, ?)
9
+ ON CONFLICT(grantee, month) DO UPDATE SET usd_equivalent = grantee_usage.usd_equivalent + excluded.usd_equivalent`).run(t.grantee,u,t.usd_equivalent)}a(w,"addUsage");async function y(e,t,n,u,s){await h(async p=>await w(p,{grantee:e,payer:t,source:"model",served_model:n,input_tokens:u.input,output_tokens:u.output,cached_tokens:u.cacheRead,usd_equivalent:s}))}a(y,"recordModelUsage");async function c(e,t=r()){return(await(await d()).prepare("SELECT usd_equivalent FROM grantee_usage WHERE grantee = ? AND month = ?").get(e,t))?.usd_equivalent??0}a(c,"monthSpend");function m(e){return e.grantee===q?null:e.spend_cap}a(m,"effectiveCap");async function x(e,t=new Date){if(!e)return;const n=m(e);if(n===null)return;const u=r(t),s=await c(e.grantee,u);if(!(s<n))throw new _(402,"cap_exhausted",`${e.grantee} reached its monthly usage limit`,void 0,{spend_cap:n,usd_equivalent:s,reset_at:l(u)})}a(x,"assertUnderCap");async function C(e,t,n=r()){const u=await(await d()).prepare(`SELECT payer, source, served_model, input_tokens, output_tokens, usd_equivalent
10
+ FROM usage WHERE grantee = ? AND month = ? ORDER BY served_model`).all(e,n),s=a(i=>u.filter(o=>o.payer===i&&o.source==="model").map(({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:g})=>({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:g})),"byModel"),p=u.filter(i=>i.payer==="app").reduce((i,o)=>i+(o.usd_equivalent??0),0);return{grantee:e,month:n,usd_equivalent:await c(e,n),by_model:s("user"),app_paid:{usd_equivalent:p,by_model:s("app")},spend_cap:m({grantee:e,spend_cap:t}),reset_at:l(n)}}a(C,"usageFor");function D(e){if(e===null)return r();if(!/^[1-9]\d{3}-(0[1-9]|1[0-2])$/.test(e))throw new _(400,"invalid_request","month must be YYYY-MM","month");return e}a(D,"parseUsageMonth");export{q as UNCAPPED_GRANTEE,w as addUsage,x as assertUnderCap,m as effectiveCap,c as monthSpend,D as parseUsageMonth,y as recordModelUsage,l as resetAt,C as usageFor,r as usageMonth};
@@ -1,18 +1,18 @@
1
- var Z=Object.defineProperty;var o=(e,r)=>Z(e,"name",{value:r,configurable:!0});import{existsSync as k,mkdirSync as P,readFileSync as ee,realpathSync as H,rmSync as te,writeFileSync as re}from"node:fs";import{createHash as ne}from"node:crypto";import{dirname as oe,isAbsolute as ae,join as se,relative as ie,resolve as N,sep as ce}from"node:path";import{gitAsync as he,gitSync as i}from"./git.js";import{crtrHome as C}from"./canvas/paths.js";import{closeWorktreeAndRepoint as ue,getNode as v,recordLandIntent as le}from"./canvas/index.js";import{CONFIG_FILE as de,CRTR_DIR_NAME as O,STATE_FILE as fe}from"../types.js";import{withExclusiveDirectoryLock as pe,withExclusiveDirectoryLockAsync as me}from"./exclusive-lock.js";import{parseStatusPorcelain as be,planLandIntoCheckout as ke,refDeleteTransactionStdin as _e}from"./worktree-landing.js";import{shellQuote as w}from"../shared/shell-quote.js";class f extends Error{static{o(this,"WorktreeError")}code;next;detail;constructor(r,t,n,a){super(t),this.name="WorktreeError",this.code=r,this.next=n,this.detail=a}}function _(e,r,t,n){const a=i(r,e);if(a.status!==0){const s=(a.stderr.trim()||a.stdout.trim()).trim();throw new f(t,`git ${r.join(" ")} failed`,n,s)}return a.stdout.trim()}o(_,"runGit");function F(){return`${C()}/worktrees`}o(F,"managedWorktreesRoot");function ge(e){return`${F()}/${e}`}o(ge,"managedWorktreePath");function Xe(e){return e?.managed_worktree?.state==="open"}o(Xe,"hasOpenManagedWorktree");async function x(e){const t=(await v(e))?.managed_worktree;return t?.state==="open"?t:null}o(x,"openManagedWorktreeForNode");function we(e){const r=i(["rev-parse","--show-toplevel"],e);if(r.status!==0){const t=(r.stderr.trim()||r.stdout.trim()).trim();throw new f("not_git_repo",`cwd ${e} is not a git repository`,"Pass --cwd <real repo> pointing inside a git repository.",t)}return r.stdout.trim()}o(we,"repoRootFor");function ye(e){const r=ie(E(F()),E(e));return r!==""&&r!==".."&&!r.startsWith(`..${ce}`)&&!ae(r)}o(ye,"isManagedWorktreeBase");function $e(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===0)return!0;if(n.status===1&&n.executionFailed!==!0)return!1;const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
1
+ var Z=Object.defineProperty;var o=(e,r)=>Z(e,"name",{value:r,configurable:!0});import{existsSync as k,mkdirSync as H,readFileSync as ee,realpathSync as N,rmSync as te,writeFileSync as re}from"node:fs";import{createHash as ne}from"node:crypto";import{dirname as oe,isAbsolute as ae,join as se,relative as ie,resolve as C,sep as ce}from"node:path";import{gitAsync as he,gitSync as i}from"./git.js";import{crtrHome as O}from"./canvas/paths.js";import{closeWorktreeAndRepoint as ue,getNode as v,recordLandIntent as le}from"./canvas/index.js";import{CONFIG_FILE as de,CRTR_DIR_NAME as A,STATE_FILE as fe}from"../types.js";import{withExclusiveDirectoryLock as pe,withExclusiveDirectoryLockAsync as me}from"./exclusive-lock.js";import{parseStatusPorcelain as be,planLandIntoCheckout as ke,refDeleteTransactionStdin as _e}from"./worktree-landing.js";import{shellQuote as w}from"../shared/shell-quote.js";class f extends Error{static{o(this,"WorktreeError")}code;next;detail;constructor(r,t,n,a){super(t),this.name="WorktreeError",this.code=r,this.next=n,this.detail=a}}function _(e,r,t,n){const a=i(r,e);if(a.status!==0){const s=(a.stderr.trim()||a.stdout.trim()).trim();throw new f(t,`git ${r.join(" ")} failed`,n,s)}return a.stdout.trim()}o(_,"runGit");function F(){return`${O()}/worktrees`}o(F,"managedWorktreesRoot");function ge(e){return`${F()}/${e}`}o(ge,"managedWorktreePath");function Xe(e){return e?.managed_worktree?.state==="open"}o(Xe,"hasOpenManagedWorktree");async function x(e){const t=(await v(e))?.managed_worktree;return t?.state==="open"?t:null}o(x,"openManagedWorktreeForNode");function we(e){const r=i(["rev-parse","--show-toplevel"],e);if(r.status!==0){const t=(r.stderr.trim()||r.stdout.trim()).trim();throw new f("not_git_repo",`cwd ${e} is not a git repository`,"Pass --cwd <real repo> pointing inside a git repository.",t)}return r.stdout.trim()}o(we,"repoRootFor");function ye(e){const r=ie(E(F()),E(e));return r!==""&&r!==".."&&!r.startsWith(`..${ce}`)&&!ae(r)}o(ye,"isManagedWorktreeBase");function $e(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===0)return!0;if(n.status===1&&n.executionFailed!==!0)return!1;const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
2
2
  process error: ${n.processError}`;throw new f("recorded_branch_inspection_failed",`could not inspect recorded branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
3
- stderr: ${a}${s}`)}o($e,"recordedBranchExists");function A(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===1&&n.executionFailed!==!0)throw new f("missing_base_branch",`managed worktree base '${r}' does not name an existing local branch`,"The base must be a local branch that landing can fast-forward \u2014 freshen your local branch from origin first (rebase-not-merge), then base on it.");if(n.status!==0){const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
3
+ stderr: ${a}${s}`)}o($e,"recordedBranchExists");function R(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===1&&n.executionFailed!==!0)throw new f("missing_base_branch",`managed worktree base '${r}' does not name an existing local branch`,"The base must be a local branch that landing can fast-forward \u2014 freshen your local branch from origin first (rebase-not-merge), then base on it.");if(n.status!==0){const a=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
4
4
  process error: ${n.processError}`;throw new f("base_branch_inspection_failed",`could not inspect local base branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
5
- stderr: ${a}${s}`)}return _(e,["rev-parse","--verify",t],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}o(A,"resolveLandableBase");function ve(e,r){const t=_(e,["worktree","list","--porcelain"],"worktree_list_failed","Inspect the repository worktrees manually, then retry.");return I(t,r)}o(ve,"checkoutPathForBranch");function I(e,r){let t=null;for(const n of e.split(`
6
- `))if(n.startsWith("worktree "))t=n.slice(9).trim();else if(n===`branch refs/heads/${r}`)return t;return null}o(I,"checkoutPathForBranchInList");function xe(e,r){return e===r||E(e)===E(r)}o(xe,"samePath");function E(e){try{return H.native(e)}catch{return N(e)}}o(E,"canonicalPath");const q=3e4;function G(e){const r=`${C()}/worktree-locks`;return P(r,{recursive:!0}),`${r}/${ne("sha256").update(e).digest("hex")}`}o(G,"worktreeLockPathForCommonDir");function S(e){const r=_(e,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.");return H(N(e,r))}o(S,"commonGitDir");function B(e,r){const t=S(e);return pe(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(B,"withRepositoryWorktreeLock");async function j(e,r){const t=S(e);return me(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(j,"withRepositoryWorktreeLockAsync");function D(e,r,t){const n=i(["worktree","list","--porcelain"],e);if(n.status!==0)return null;let a=null;for(const s of n.stdout.split(`
5
+ stderr: ${a}${s}`)}return _(e,["rev-parse","--verify",t],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}o(R,"resolveLandableBase");function ve(e,r){const t=_(e,["worktree","list","--porcelain"],"worktree_list_failed","Inspect the repository worktrees manually, then retry.");return I(t,r)}o(ve,"checkoutPathForBranch");function I(e,r){let t=null;for(const n of e.split(`
6
+ `))if(n.startsWith("worktree "))t=n.slice(9).trim();else if(n===`branch refs/heads/${r}`)return t;return null}o(I,"checkoutPathForBranchInList");function xe(e,r){return e===r||E(e)===E(r)}o(xe,"samePath");function E(e){try{return N.native(e)}catch{return C(e)}}o(E,"canonicalPath");const q=3e4;function G(e){const r=`${O()}/worktree-locks`;return H(r,{recursive:!0}),`${r}/${ne("sha256").update(e).digest("hex")}`}o(G,"worktreeLockPathForCommonDir");function S(e){const r=_(e,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.");return N(C(e,r))}o(S,"commonGitDir");function B(e,r){const t=S(e);return pe(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(B,"withRepositoryWorktreeLock");async function j(e,r){const t=S(e);return me(G(t),r,{timeoutMs:q,timeoutError:o(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(j,"withRepositoryWorktreeLockAsync");function D(e,r,t){const n=i(["worktree","list","--porcelain"],e);if(n.status!==0)return null;let a=null;for(const s of n.stdout.split(`
7
7
  `))if(s.startsWith("worktree "))a=s.slice(9).trim();else if(a!==null&&xe(a,r)&&s===`branch refs/heads/${t}`)return!0;return!1}o(D,"registeredWorktree");function Ee(e,r,t){const n=[],a=`refs/heads/${r}`,s=i(["rev-parse","--verify","--quiet",a],e);s.status===0&&n.push({ref:a,sha:s.stdout.trim()});const u=i(["rev-parse","--symbolic-full-name","--verify",`${r}@{upstream}`],e),h=u.status===0&&u.stdout.trim().startsWith("refs/")?u.stdout.trim():`refs/remotes/origin/${r}`,m=i(["rev-parse","--verify","--quiet",h],e);if(m.status===0&&n.push({ref:h,sha:m.stdout.trim()}),n.length===0)return null;for(const d of n)if(i(["merge-base","--is-ancestor",t,d.sha],e).status===0)return{containingRef:d.ref,containingSha:d.sha};for(const d of n){const l=i(["cherry",d.sha,t],e);if(l.status!==0)continue;if(l.stdout.split(`
8
8
  `).map(c=>c.trim()).filter(c=>c!=="").every(c=>c.startsWith("-")))return{containingRef:d.ref,containingSha:d.sha}}for(const d of n){const l=i(["rev-parse","--verify",`${d.sha}^{tree}`],e);if(l.status!==0)continue;const b=i(["merge-tree","--write-tree",d.sha,t],e);if(b.status===0&&b.stdout.split(`
9
- `)[0]?.trim()===l.stdout.trim())return{containingRef:d.ref,containingSha:d.sha}}return null}o(Ee,"proveBranchContained");function K(e,r){const t=i(["rev-parse","--verify",`refs/heads/${e.branch}`],e.repo_root);if(t.status!==0||t.stdout.trim()!==e.base_sha)return;const n=D(e.repo_root,e.path,e.branch);if(n!==null){if(n){if(i(["worktree","remove","--force",e.path],e.repo_root).status!==0||D(e.repo_root,e.path,e.branch)!==!1)return}else if(r&&k(e.path))try{te(e.path,{recursive:!0,force:!0})}catch{return}try{i(["update-ref","-d",`refs/heads/${e.branch}`,e.base_sha],e.repo_root)}catch{}}}o(K,"rollbackManagedWorktreeLocked");function ze(e){B(e.repo_root,()=>K(e,!1))}o(ze,"rollbackManagedWorktree");const Se="# crtr: exclude crtr's own untracked project-scope bookkeeping (auto-added at managed-worktree creation)",De=[`/${O}/${de}`,`/${O}/${fe}`];function We(e){try{const r=se(S(e),"info","exclude");P(oe(r),{recursive:!0});let t="";try{t=ee(r,"utf8")}catch{}const n=new Set(t.split(`
9
+ `)[0]?.trim()===l.stdout.trim())return{containingRef:d.ref,containingSha:d.sha}}return null}o(Ee,"proveBranchContained");function K(e,r){const t=i(["rev-parse","--verify",`refs/heads/${e.branch}`],e.repo_root);if(t.status!==0||t.stdout.trim()!==e.base_sha)return;const n=D(e.repo_root,e.path,e.branch);if(n!==null){if(n){if(i(["worktree","remove","--force",e.path],e.repo_root).status!==0||D(e.repo_root,e.path,e.branch)!==!1)return}else if(r&&k(e.path))try{te(e.path,{recursive:!0,force:!0})}catch{return}try{i(["update-ref","-d",`refs/heads/${e.branch}`,e.base_sha],e.repo_root)}catch{}}}o(K,"rollbackManagedWorktreeLocked");function ze(e){B(e.repo_root,()=>K(e,!1))}o(ze,"rollbackManagedWorktree");const Se="# crtr: exclude crtr's own untracked project-scope bookkeeping (auto-added at managed-worktree creation)",De=[`/${A}/${de}`,`/${A}/${fe}`,`/${A}/operations.db*`];function We(e){try{const r=se(S(e),"info","exclude");H(oe(r),{recursive:!0});let t="";try{t=ee(r,"utf8")}catch{}const n=new Set(t.split(`
10
10
  `).map(h=>h.trim())),a=De.filter(h=>!n.has(h));if(a.length===0)return;const u=(t.length>0&&!t.endsWith(`
11
11
  `)?`
12
12
  `:"")+Se+`
13
13
  `+a.join(`
14
14
  `)+`
15
- `;re(r,t+u)}catch{}}o(We,"seedManagedWorktreeExclude");function Qe(e,r,t="main"){const n=we(e);if(ye(n))throw new f("managed_worktree_base",`cwd ${n} is a managed worktree and cannot be used as a managed worktree base`,"Pass `--cwd` pointing at the repository\u2019s primary checkout and keep `--worktree` set to the desired existing local base branch, including the parent branch.");return B(n,()=>{const a=A(n,t),s=ge(r),u=`crtr/${r}`;if(k(s))throw new f("worktree_path_exists",`managed worktree path already exists: ${s}`,"Remove the stale path or choose a fresh node id.");if(i(["show-ref","--verify","--quiet",`refs/heads/${u}`],n).status===0)throw new f("worktree_branch_exists",`managed worktree branch already exists: ${u}`,"Remove the stale branch or choose a fresh node id.");const h={state:"open",path:s,branch:u,repo_root:n,base_ref:t,base_sha:a,created:new Date().toISOString()};_(n,["branch",u,a],"worktree_branch_create_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.");try{return _(n,["worktree","add",s,u],"worktree_add_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree."),We(n),h}catch(m){throw K(h,!0),m}})}o(Qe,"createManagedWorktree");function Ae(e){return _(e,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")}o(Ae,"statusPorcelain");function U(e){return _(e,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")}o(U,"currentBranch");function X(e,r){return _(e,["rev-parse","--git-path",r],"git_path_failed","Inspect the worktree manually, then retry.")}o(X,"gitPath");function R(e){return k(X(e,"rebase-merge"))||k(X(e,"rebase-apply"))}o(R,"isRebaseInProgress");async function $(e,r,t="pending"){const n=await v(e);await ue(e,{cwd:r.repo_root,cleanup:t,closedAt:new Date().toISOString(),unbindSession:n?.pi_session_id!=null||n?.pi_session_file!=null})}o($,"persistClosedWorktreeState");async function Re(e,r){const t=(await v(e))?.managed_worktree;t==null||t.state!=="open"||await le(e,{at:new Date().toISOString(),blocked:r})}o(Re,"recordBlockedLandIntent");function Me(e,r,t,n){const a=i(["status","--porcelain"],e);if(a.status!==0)return{ok:!1,detail:(a.stderr.trim()||a.stdout.trim()).trim()};const s=i(["diff","--name-only",t,n],e);if(s.status!==0)return{ok:!1,detail:(s.stderr.trim()||s.stdout.trim()).trim()};const u=s.stdout.split(`
15
+ `;re(r,t+u)}catch{}}o(We,"seedManagedWorktreeExclude");function Qe(e,r,t="main"){const n=we(e);if(ye(n))throw new f("managed_worktree_base",`cwd ${n} is a managed worktree and cannot be used as a managed worktree base`,"Pass `--cwd` pointing at the repository\u2019s primary checkout and keep `--worktree` set to the desired existing local base branch, including the parent branch.");return B(n,()=>{const a=R(n,t),s=ge(r),u=`crtr/${r}`;if(k(s))throw new f("worktree_path_exists",`managed worktree path already exists: ${s}`,"Remove the stale path or choose a fresh node id.");if(i(["show-ref","--verify","--quiet",`refs/heads/${u}`],n).status===0)throw new f("worktree_branch_exists",`managed worktree branch already exists: ${u}`,"Remove the stale branch or choose a fresh node id.");const h={state:"open",path:s,branch:u,repo_root:n,base_ref:t,base_sha:a,created:new Date().toISOString()};_(n,["branch",u,a],"worktree_branch_create_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.");try{return _(n,["worktree","add",s,u],"worktree_add_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree."),We(n),h}catch(m){throw K(h,!0),m}})}o(Qe,"createManagedWorktree");function Ae(e){return _(e,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")}o(Ae,"statusPorcelain");function U(e){return _(e,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")}o(U,"currentBranch");function X(e,r){return _(e,["rev-parse","--git-path",r],"git_path_failed","Inspect the worktree manually, then retry.")}o(X,"gitPath");function M(e){return k(X(e,"rebase-merge"))||k(X(e,"rebase-apply"))}o(M,"isRebaseInProgress");async function $(e,r,t="pending"){const n=await v(e);await ue(e,{cwd:r.repo_root,cleanup:t,closedAt:new Date().toISOString(),unbindSession:n?.pi_session_id!=null||n?.pi_session_file!=null})}o($,"persistClosedWorktreeState");async function Re(e,r){const t=(await v(e))?.managed_worktree;t==null||t.state!=="open"||await le(e,{at:new Date().toISOString(),blocked:r})}o(Re,"recordBlockedLandIntent");function Me(e,r,t,n){const a=i(["status","--porcelain"],e);if(a.status!==0)return{ok:!1,detail:(a.stderr.trim()||a.stdout.trim()).trim()};const s=i(["diff","--name-only",t,n],e);if(s.status!==0)return{ok:!1,detail:(s.stderr.trim()||s.stdout.trim()).trim()};const u=s.stdout.split(`
16
16
  `).map(g=>g.trim()).filter(g=>g!==""),h=ke(be(a.stdout),u);if(h.kind==="refuse")return{ok:!1,detail:`untracked files in ${e} would be overwritten by the incoming commits: ${h.collisions.join(", ")}`};const m=o(()=>{const g=i(["merge","--ff-only",n],e);return g.status===0?{ok:!0}:{ok:!1,detail:(g.stderr.trim()||g.stdout.trim()).trim()}},"merge");if(h.kind==="direct")return m();const d=i(["rev-parse","--verify","--quiet","refs/stash"],e),l=d.status===0?d.stdout.trim():null,b=i(["stash","push","--message",`crtr landing ${r}`],e);if(b.status!==0)return{ok:!1,detail:(b.stderr.trim()||b.stdout.trim()).trim()};const c=i(["rev-parse","--verify","--quiet","refs/stash"],e),p=c.status===0?c.stdout.trim():null;if(p===null||p===l)return m();const y=`local changes from ${e} are retained in stash ${p}; recover them with \`git -C ${w(e)} stash apply ${p}\` and resolve any conflict.`,W=m();return W.ok?i(["stash","apply",p],e).status===0?(z(e,p),{ok:!0}):(i(["reset","--hard",n],e),{ok:!0,stash:`the shared base checkout was reset to landed commit ${n} because local changes conflicted with it. ${y}`}):i(["stash","apply",p],e).status===0?(z(e,p),W):{ok:!1,detail:`${W.detail}
17
- ${y}`}}o(Me,"landIntoBaseCheckout");function z(e,r){const t=i(["rev-parse","--verify","--quiet","refs/stash"],e);t.status===0&&t.stdout.trim()===r&&i(["stash","drop"],e)}o(z,"dropStashIfStillTip");function M(e){const r=`git -C ${w(e.repo_root)} worktree remove ${w(e.path)}`;return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact. After its node exits, run \`${r}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}; delete it only after that checkout is removed and its landed commit is still contained in ${e.base_ref}.`}}o(M,"deferredCleanupResult");async function Le(e,r,t){if(D(r.repo_root,r.path,t)!==!0)throw new f("wrong_branch",`managed worktree's recorded branch ${r.branch} no longer exists, and its checkout at ${r.path} is not registered to ${t} either`,`Inspect ${r.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);const n=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.");if(Ee(r.path,r.base_ref,n)===null)throw new f("branch_moved_unlanded",`managed worktree's recorded branch ${r.branch} no longer exists; its checkout is now on ${t} at ${n}, which carries content local base branch '${r.base_ref}' does not yet contain`,`Land or push ${t} through its own workflow (merge its PR, or fast-forward '${r.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${t} should be delivered.`);const s=S(r.repo_root),u=D(r.repo_root,r.path,t)===!0,h=U(r.path)===t,m=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")===n;if(!u||!h||!m)throw new f("wrong_branch",`managed worktree at ${r.path} changed while closing`,`Inspect ${r.path}, then rerun \`crtr node worktree close\`.`);const d={observed_branch:t,observed_sha:n,common_dir:s,authorized:new Date().toISOString()};await $(e,{...r,disposal:d},"pending");const l=`git -C ${w(r.repo_root)} worktree remove ${w(r.path)}`;return{node_id:e,branch:t,worktree_path:r.path,landed_sha:n,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${r.path} remains intact. After its node exits, run \`${l}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`${t} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}o(Le,"closeBranchMovedWorktree");async function Te(e,r){const t=(await v(e))?.managed_worktree;if(t==null)return{message:`node ${e} has no managed worktree`,next:`Nothing to ${r} for this node.`};if(t.state==="abandoned"){const n=t.abandoned?.branch??t.branch;return{message:`node ${e}'s managed worktree was already abandoned`,next:`Nothing to ${r} for this node; its work was retained on branch ${n}.`}}return t.state==="closed"?t.cleanup==="complete"?{message:`node ${e}'s managed worktree is already closed and its cleanup is complete`,next:`Nothing to ${r} for this node.`}:{message:`node ${e}'s managed worktree is already closed; this is not lost ownership \u2014 its checkout at ${t.path} is scheduled for automatic cleanup once that is safe`,next:`Nothing to ${r} for this node. The daemon sweep finishes removing ${t.path} on its own; inspect it directly only if it still needs manual attention.`}:{message:`node ${e} has no open managed worktree`,next:`Nothing to ${r} for this node.`}}o(Te,"noManagedWorktreeMessage");async function Q(e){if(await v(e)===null)throw new f("unknown_node",`unknown node: ${e}`,"Run this from a live node, or pass a real node id once that command supports it.");const t=await x(e);if(t===null){const{message:c,next:p}=await Te(e,"close");throw new f("no_managed_worktree",c,p)}if(!k(t.path)){const c=L(t);if(c===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));if(await V(e,t,c)===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));return{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:c.branchSha??t.base_sha,worktree_removed:!0,branch_deleted:!0}}if(R(t.path))throw new f("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(Ae(t.path)!=="")throw new f("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${t.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);const a=U(t.path);if(a!==t.branch){const c=a==="HEAD"?"detached HEAD":a,p=$e(t.path,t.branch);if(p||a==="HEAD")throw new f("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${c})`,p?`Check out ${t.branch} in ${t.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`:`The recorded branch ${t.branch} no longer exists, and ${t.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);return await Le(e,t,a)}let s;try{s=A(t.path,t.base_ref)}catch(c){const p=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(!(c instanceof f)||c.code!=="missing_base_branch"||p!==t.base_sha)throw c;return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:t.base_sha,...M(t)}}const u=i(["rebase",s],t.path);if(u.status!==0){const c=(u.stderr.trim()||u.stdout.trim()).trim();throw new f("rebase_failed",`rebase onto local base branch '${t.base_ref}' did not complete`,`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`,c)}const h=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),m=o(async(c,p,y)=>(await Re(e,c),new f("land_base_failed",c,p,y)),"blocked"),d=i(["merge-base","--is-ancestor",s,h],t.path);if(d.status!==0)throw await m(`rebased worktree is not a fast-forward of local base branch '${t.base_ref}'`,"Ask the user with `crtr human send` how to land this managed worktree.",(d.stderr.trim()||d.stdout.trim()).trim());const l=ve(t.path,t.base_ref);if(l!==null){const c=i(["rev-parse","HEAD"],l),p=c.stdout.trim();if(c.status!==0||p!==s){const y=c.status!==0?(c.stderr.trim()||p).trim():`expected ${s}, found ${p}`;throw await m(`local base branch '${t.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${l}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,y)}}let b;if(l!==null){const c=Me(l,t.branch,s,h);if(!c.ok)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,`Local base branch '${t.base_ref}' is checked out at ${l} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,c.detail);b=c.stash}else{const c=i(["update-ref",`refs/heads/${t.base_ref}`,h,s],t.path);if(c.status!==0)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,"Ask the user with `crtr human send` how to land this managed worktree.",(c.stderr.trim()||c.stdout.trim()).trim())}return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:h,...M(t),...b===void 0?{}:{base_checkout_stash:b}}}o(Q,"closeManagedWorktreeLocked");async function Je(e){const r=await x(e);return r===null?await Q(e):await j(k(r.path)?r.path:r.repo_root,async()=>await Q(e))}o(Je,"closeManagedWorktree");function Pe(e,r,t,n){const a=_e(e.branch,r,t,n),s=i(["update-ref","--stdin"],e.repo_root,a),u=s.status===0;if(u)return{branchDeleted:u};const h=(s.stderr.trim()||s.stdout.trim()).trim();return{branchDeleted:u,branchDeleteError:`local branch ${e.branch} could not be deleted automatically (${h}); run \`git -C ${w(e.repo_root)} branch -D ${w(e.branch)}\` after confirming it is merged.`}}o(Pe,"bestEffortDeleteBranchWithContainmentProof");function L(e){if(e.state!=="open"||k(e.path))return null;const r=`refs/heads/${e.branch}`,t=i(["show-ref","--verify","--quiet",r],e.repo_root);if(t.status===1)return{branchSha:null};if(t.status!==0)return null;const n=i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const a=n.stdout.trim(),s=i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||I(s.stdout,e.branch)!==null)return null;const u=[],h=`refs/heads/${e.base_ref}`,m=i(["show-ref","--verify","--quiet",h],e.repo_root);if(m.status===0){const l=i(["rev-parse","--verify",h],e.repo_root);if(l.status!==0)return null;u.push({ref:h,sha:l.stdout.trim()})}else if(m.status!==1)return null;const d=i(["rev-parse","--symbolic-full-name","--verify",`${e.base_ref}@{upstream}`],e.repo_root);if(d.status===0){const l=d.stdout.trim(),b=i(["rev-parse","--verify",l],e.repo_root);l.startsWith("refs/")&&b.status===0&&u.push({ref:l,sha:b.stdout.trim()})}else{const l=`refs/remotes/origin/${e.base_ref}`,b=i(["show-ref","--verify","--quiet",l],e.repo_root);if(b.status===0){const c=i(["rev-parse","--verify",l],e.repo_root);c.status===0&&u.push({ref:l,sha:c.stdout.trim()})}else if(b.status!==1)return null}for(const l of u)if(i(["merge-base","--is-ancestor",a,l.sha],e.repo_root).status===0)return{branchSha:a,containingRef:l.ref,containingSha:l.sha};return null}o(L,"proveAbsentPathManagedWorktree");function J(e){return`The recorded checkout path is gone, but crtr cannot prove ${e.branch} is already delivered. Push or land ${e.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`}o(J,"missingWorktreeRecoveryHint");function T(e){if(e.state!=="open"||!k(e.path)||R(e.path))return null;const r=i(["rev-parse","--abbrev-ref","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch)return null;const t=i(["status","--porcelain"],e.path);if(t.status!==0||t.stdout.trim()!=="")return null;const n=i(["rev-parse","HEAD"],e.path);if(n.status!==0)return null;const a=n.stdout.trim();let s;try{s=A(e.path,e.base_ref)}catch(h){if(h instanceof f&&h.code==="missing_base_branch"&&a===e.base_sha)return{branchSha:a,baseSha:e.base_sha};throw h}return i(["merge-base","--is-ancestor",a,s],e.path).status!==0?null:{branchSha:a,baseSha:s}}o(T,"proveCleanEmptyManagedWorktree");async function V(e,r,t){if(k(r.path))return null;if(t.branchSha===null)return await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0};if(t.containingRef===void 0||t.containingSha===void 0)return null;const{branchDeleted:n}=Pe(r,t.branchSha,t.containingRef,t.containingSha);return n?(await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):null}o(V,"autoDropAbsentPathManagedWorktreeLocked");async function He(e,r,t){const n=T(r);return n===null||n.branchSha!==t.branchSha?null:(await $(e,r,"pending"),{node_id:e,branch:r.branch,worktree_path:r.path,...M(r)})}o(He,"autoDropCleanManagedWorktreeLocked");function Y(e){if(e.state!=="open"||!k(e.path)||R(e.path))return null;const r=i(["status","--porcelain"],e.path);if(r.status!==0||r.stdout.trim()!=="")return null;const t=i(["rev-parse","HEAD"],e.path);return t.status===0?t.stdout.trim():null}o(Y,"cleanCurrentCheckoutTip");async function Ve(e){const r=Y(e);if(r===null)return!1;const t=process.env.GIT_SSH_COMMAND??process.env.GIT_SSH??"ssh",n=await he(["ls-remote","--exit-code","--heads","origin"],e.path,void 0,{timeoutMs:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:`${t} -o BatchMode=yes`}});return n.status!==0||!n.stdout.split(`
18
- `).some(s=>{const[u,h]=s.split(" ",2);return u===r&&h?.startsWith("refs/heads/")===!0})?!1:Y(e)===r}o(Ve,"branchIsPushedAtCurrentTip");async function Ye(e){const r=await x(e);if(r===null)return null;const t=!k(r.path);return(t?L(r)===null:T(r)===null)?null:await j(t?r.repo_root:r.path,async()=>{const n=await x(e);if(n===null)return null;if(!k(n.path)){const s=L(n);return s===null?null:await V(e,n,s)}const a=T(n);return a===null?null:await He(e,n,a)})}o(Ye,"autoDropCleanManagedWorktree");export{q as WORKTREE_LOCK_WAIT_MS,f as WorktreeError,Ye as autoDropCleanManagedWorktree,He as autoDropCleanManagedWorktreeLocked,Ve as branchIsPushedAtCurrentTip,I as checkoutPathForBranchInList,Je as closeManagedWorktree,Qe as createManagedWorktree,Xe as hasOpenManagedWorktree,ye as isManagedWorktreeBase,R as isRebaseInProgress,ge as managedWorktreePath,F as managedWorktreesRoot,J as missingWorktreeRecoveryHint,x as openManagedWorktreeForNode,$ as persistClosedWorktreeState,T as proveCleanEmptyManagedWorktree,ze as rollbackManagedWorktree,xe as samePath,G as worktreeLockPathForCommonDir};
17
+ ${y}`}}o(Me,"landIntoBaseCheckout");function z(e,r){const t=i(["rev-parse","--verify","--quiet","refs/stash"],e);t.status===0&&t.stdout.trim()===r&&i(["stash","drop"],e)}o(z,"dropStashIfStillTip");function L(e){const r=`git -C ${w(e.repo_root)} worktree remove ${w(e.path)}`;return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact. After its node exits, run \`${r}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}; delete it only after that checkout is removed and its landed commit is still contained in ${e.base_ref}.`}}o(L,"deferredCleanupResult");async function Le(e,r,t){if(D(r.repo_root,r.path,t)!==!0)throw new f("wrong_branch",`managed worktree's recorded branch ${r.branch} no longer exists, and its checkout at ${r.path} is not registered to ${t} either`,`Inspect ${r.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);const n=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.");if(Ee(r.path,r.base_ref,n)===null)throw new f("branch_moved_unlanded",`managed worktree's recorded branch ${r.branch} no longer exists; its checkout is now on ${t} at ${n}, which carries content local base branch '${r.base_ref}' does not yet contain`,`Land or push ${t} through its own workflow (merge its PR, or fast-forward '${r.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${t} should be delivered.`);const s=S(r.repo_root),u=D(r.repo_root,r.path,t)===!0,h=U(r.path)===t,m=_(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")===n;if(!u||!h||!m)throw new f("wrong_branch",`managed worktree at ${r.path} changed while closing`,`Inspect ${r.path}, then rerun \`crtr node worktree close\`.`);const d={observed_branch:t,observed_sha:n,common_dir:s,authorized:new Date().toISOString()};await $(e,{...r,disposal:d},"pending");const l=`git -C ${w(r.repo_root)} worktree remove ${w(r.path)}`;return{node_id:e,branch:t,worktree_path:r.path,landed_sha:n,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${r.path} remains intact. After its node exits, run \`${l}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`${t} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}o(Le,"closeBranchMovedWorktree");async function Te(e,r){const t=(await v(e))?.managed_worktree;if(t==null)return{message:`node ${e} has no managed worktree`,next:`Nothing to ${r} for this node.`};if(t.state==="abandoned"){const n=t.abandoned?.branch??t.branch;return{message:`node ${e}'s managed worktree was already abandoned`,next:`Nothing to ${r} for this node; its work was retained on branch ${n}.`}}return t.state==="closed"?t.cleanup==="complete"?{message:`node ${e}'s managed worktree is already closed and its cleanup is complete`,next:`Nothing to ${r} for this node.`}:{message:`node ${e}'s managed worktree is already closed; this is not lost ownership \u2014 its checkout at ${t.path} is scheduled for automatic cleanup once that is safe`,next:`Nothing to ${r} for this node. The daemon sweep finishes removing ${t.path} on its own; inspect it directly only if it still needs manual attention.`}:{message:`node ${e} has no open managed worktree`,next:`Nothing to ${r} for this node.`}}o(Te,"noManagedWorktreeMessage");async function Q(e){if(await v(e)===null)throw new f("unknown_node",`unknown node: ${e}`,"Run this from a live node, or pass a real node id once that command supports it.");const t=await x(e);if(t===null){const{message:c,next:p}=await Te(e,"close");throw new f("no_managed_worktree",c,p)}if(!k(t.path)){const c=T(t);if(c===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));if(await V(e,t,c)===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,J(t));return{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:c.branchSha??t.base_sha,worktree_removed:!0,branch_deleted:!0}}if(M(t.path))throw new f("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(Ae(t.path)!=="")throw new f("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${t.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);const a=U(t.path);if(a!==t.branch){const c=a==="HEAD"?"detached HEAD":a,p=$e(t.path,t.branch);if(p||a==="HEAD")throw new f("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${c})`,p?`Check out ${t.branch} in ${t.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`:`The recorded branch ${t.branch} no longer exists, and ${t.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);return await Le(e,t,a)}let s;try{s=R(t.path,t.base_ref)}catch(c){const p=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(!(c instanceof f)||c.code!=="missing_base_branch"||p!==t.base_sha)throw c;return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:t.base_sha,...L(t)}}const u=i(["rebase",s],t.path);if(u.status!==0){const c=(u.stderr.trim()||u.stdout.trim()).trim();throw new f("rebase_failed",`rebase onto local base branch '${t.base_ref}' did not complete`,`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`,c)}const h=_(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),m=o(async(c,p,y)=>(await Re(e,c),new f("land_base_failed",c,p,y)),"blocked"),d=i(["merge-base","--is-ancestor",s,h],t.path);if(d.status!==0)throw await m(`rebased worktree is not a fast-forward of local base branch '${t.base_ref}'`,"Ask the user with `crtr human send` how to land this managed worktree.",(d.stderr.trim()||d.stdout.trim()).trim());const l=ve(t.path,t.base_ref);if(l!==null){const c=i(["rev-parse","HEAD"],l),p=c.stdout.trim();if(c.status!==0||p!==s){const y=c.status!==0?(c.stderr.trim()||p).trim():`expected ${s}, found ${p}`;throw await m(`local base branch '${t.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${l}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,y)}}let b;if(l!==null){const c=Me(l,t.branch,s,h);if(!c.ok)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,`Local base branch '${t.base_ref}' is checked out at ${l} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,c.detail);b=c.stash}else{const c=i(["update-ref",`refs/heads/${t.base_ref}`,h,s],t.path);if(c.status!==0)throw await m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,"Ask the user with `crtr human send` how to land this managed worktree.",(c.stderr.trim()||c.stdout.trim()).trim())}return await $(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:h,...L(t),...b===void 0?{}:{base_checkout_stash:b}}}o(Q,"closeManagedWorktreeLocked");async function Je(e){const r=await x(e);return r===null?await Q(e):await j(k(r.path)?r.path:r.repo_root,async()=>await Q(e))}o(Je,"closeManagedWorktree");function Pe(e,r,t,n){const a=_e(e.branch,r,t,n),s=i(["update-ref","--stdin"],e.repo_root,a),u=s.status===0;if(u)return{branchDeleted:u};const h=(s.stderr.trim()||s.stdout.trim()).trim();return{branchDeleted:u,branchDeleteError:`local branch ${e.branch} could not be deleted automatically (${h}); run \`git -C ${w(e.repo_root)} branch -D ${w(e.branch)}\` after confirming it is merged.`}}o(Pe,"bestEffortDeleteBranchWithContainmentProof");function T(e){if(e.state!=="open"||k(e.path))return null;const r=`refs/heads/${e.branch}`,t=i(["show-ref","--verify","--quiet",r],e.repo_root);if(t.status===1)return{branchSha:null};if(t.status!==0)return null;const n=i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const a=n.stdout.trim(),s=i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||I(s.stdout,e.branch)!==null)return null;const u=[],h=`refs/heads/${e.base_ref}`,m=i(["show-ref","--verify","--quiet",h],e.repo_root);if(m.status===0){const l=i(["rev-parse","--verify",h],e.repo_root);if(l.status!==0)return null;u.push({ref:h,sha:l.stdout.trim()})}else if(m.status!==1)return null;const d=i(["rev-parse","--symbolic-full-name","--verify",`${e.base_ref}@{upstream}`],e.repo_root);if(d.status===0){const l=d.stdout.trim(),b=i(["rev-parse","--verify",l],e.repo_root);l.startsWith("refs/")&&b.status===0&&u.push({ref:l,sha:b.stdout.trim()})}else{const l=`refs/remotes/origin/${e.base_ref}`,b=i(["show-ref","--verify","--quiet",l],e.repo_root);if(b.status===0){const c=i(["rev-parse","--verify",l],e.repo_root);c.status===0&&u.push({ref:l,sha:c.stdout.trim()})}else if(b.status!==1)return null}for(const l of u)if(i(["merge-base","--is-ancestor",a,l.sha],e.repo_root).status===0)return{branchSha:a,containingRef:l.ref,containingSha:l.sha};return null}o(T,"proveAbsentPathManagedWorktree");function J(e){return`The recorded checkout path is gone, but crtr cannot prove ${e.branch} is already delivered. Push or land ${e.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`}o(J,"missingWorktreeRecoveryHint");function P(e){if(e.state!=="open"||!k(e.path)||M(e.path))return null;const r=i(["rev-parse","--abbrev-ref","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch)return null;const t=i(["status","--porcelain"],e.path);if(t.status!==0||t.stdout.trim()!=="")return null;const n=i(["rev-parse","HEAD"],e.path);if(n.status!==0)return null;const a=n.stdout.trim();let s;try{s=R(e.path,e.base_ref)}catch(h){if(h instanceof f&&h.code==="missing_base_branch"&&a===e.base_sha)return{branchSha:a,baseSha:e.base_sha};throw h}return i(["merge-base","--is-ancestor",a,s],e.path).status!==0?null:{branchSha:a,baseSha:s}}o(P,"proveCleanEmptyManagedWorktree");async function V(e,r,t){if(k(r.path))return null;if(t.branchSha===null)return await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0};if(t.containingRef===void 0||t.containingSha===void 0)return null;const{branchDeleted:n}=Pe(r,t.branchSha,t.containingRef,t.containingSha);return n?(await $(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):null}o(V,"autoDropAbsentPathManagedWorktreeLocked");async function He(e,r,t){const n=P(r);return n===null||n.branchSha!==t.branchSha?null:(await $(e,r,"pending"),{node_id:e,branch:r.branch,worktree_path:r.path,...L(r)})}o(He,"autoDropCleanManagedWorktreeLocked");function Y(e){if(e.state!=="open"||!k(e.path)||M(e.path))return null;const r=i(["status","--porcelain"],e.path);if(r.status!==0||r.stdout.trim()!=="")return null;const t=i(["rev-parse","HEAD"],e.path);return t.status===0?t.stdout.trim():null}o(Y,"cleanCurrentCheckoutTip");async function Ve(e){const r=Y(e);if(r===null)return!1;const t=process.env.GIT_SSH_COMMAND??process.env.GIT_SSH??"ssh",n=await he(["ls-remote","--exit-code","--heads","origin"],e.path,void 0,{timeoutMs:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:`${t} -o BatchMode=yes`}});return n.status!==0||!n.stdout.split(`
18
+ `).some(s=>{const[u,h]=s.split(" ",2);return u===r&&h?.startsWith("refs/heads/")===!0})?!1:Y(e)===r}o(Ve,"branchIsPushedAtCurrentTip");async function Ye(e){const r=await x(e);if(r===null)return null;const t=!k(r.path);return(t?T(r)===null:P(r)===null)?null:await j(t?r.repo_root:r.path,async()=>{const n=await x(e);if(n===null)return null;if(!k(n.path)){const s=T(n);return s===null?null:await V(e,n,s)}const a=P(n);return a===null?null:await He(e,n,a)})}o(Ye,"autoDropCleanManagedWorktree");export{q as WORKTREE_LOCK_WAIT_MS,f as WorktreeError,Ye as autoDropCleanManagedWorktree,He as autoDropCleanManagedWorktreeLocked,Ve as branchIsPushedAtCurrentTip,I as checkoutPathForBranchInList,Je as closeManagedWorktree,Qe as createManagedWorktree,Xe as hasOpenManagedWorktree,ye as isManagedWorktreeBase,M as isRebaseInProgress,ge as managedWorktreePath,F as managedWorktreesRoot,J as missingWorktreeRecoveryHint,x as openManagedWorktreeForNode,$ as persistClosedWorktreeState,P as proveCleanEmptyManagedWorktree,ze as rollbackManagedWorktree,xe as samePath,G as worktreeLockPathForCommonDir};
@@ -1,8 +1,8 @@
1
- var N=Object.defineProperty;var c=(t,e)=>N(t,"name",{value:e,configurable:!0});import{WebSocketServer as O}from"ws";import{isSafeNodeId as E}from"../../core/canvas/paths.js";import{getNode as S}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as P,CLIENT_READ_CAPS as D,FrameDecoder as F,FrameOverflowError as U}from"../../core/runtime/broker-protocol.js";import{emitEvent as V}from"../../core/events/emit.js";import{classify as k}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as L,recordFault as w}from"../../core/canvas/recovery.js";import{decideAttachRevive as H}from"../../core/runtime/revive.js";import{connectViewSocket as M,probeViewSocket as W,waitForBrokerViewSocket as J}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as j}from"../../core/spaces/open-beneath.js";import{attachViewer as A,detachViewer as q,presentViewer as z}from"./viewer-presence.js";const K=new O({noServer:!0,maxPayload:P.maxLineBytes}),Q=25e3,G=6e4;function X(t,e=Q,n=G){let a=!0,o=!1,i=Date.now();const f=c(()=>{a=!0},"acknowledge"),y=c(()=>{o||(o=!0,clearInterval(d),t.off("pong",f))},"stop");t.on("pong",f);const d=setInterval(()=>{if(Date.now()-i>n){a=!0;return}if(!a){y(),t.terminate();return}a=!1;try{t.ping()}catch{y(),t.terminate()}},e);return d.unref(),{stop:y,noteActivity:c(()=>{i=Date.now()},"noteActivity")}}c(X,"startRemoteAttachHeartbeat");function b(t){const e=Buffer.from(t,"utf8");return e.byteLength<=123?t:e.subarray(0,123).toString("utf8")}c(b,"clampReason");function u(t,e,n,a,o){const i=JSON.stringify({error:{code:a,message:o,origin:"runtime"}}),f=`HTTP/1.1 ${e} ${n}\r
1
+ var P=Object.defineProperty;var n=(t,e)=>P(t,"name",{value:e,configurable:!0});import{WebSocketServer as D}from"ws";import{isSafeNodeId as A}from"../../core/canvas/paths.js";import{getNode as R}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as F,CLIENT_READ_CAPS as U,FrameDecoder as V,FrameOverflowError as L}from"../../core/runtime/broker-protocol.js";import{emitEvent as H}from"../../core/events/emit.js";import{classify as k}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as M,recordFault as w}from"../../core/canvas/recovery.js";import{decideAttachRevive as W}from"../../core/runtime/revive.js";import{connectViewSocket as J,probeViewSocket as j,waitForBrokerViewSocket as q}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as z}from"../../core/spaces/open-beneath.js";import{attachViewer as $,detachViewer as K,presentViewer as Q}from"./viewer-presence.js";const G=new D({noServer:!0,maxPayload:F.maxLineBytes}),X=25e3,Y=6e4;function Z(t,e=X,s=Y){let a=!0,o=!1,i=Date.now();const f=n(()=>{a=!0},"acknowledge"),u=n(()=>{o||(o=!0,clearInterval(y),t.off("pong",f))},"stop");t.on("pong",f);const y=setInterval(()=>{if(Date.now()-i>s){a=!0;return}if(!a){u(),t.terminate();return}a=!1;try{t.ping()}catch{u(),t.terminate()}},e);return y.unref(),{stop:u,noteActivity:n(()=>{i=Date.now()},"noteActivity")}}n(Z,"startRemoteAttachHeartbeat");function b(t){const e=Buffer.from(t,"utf8");return e.byteLength<=123?t:e.subarray(0,123).toString("utf8")}n(b,"clampReason");function m(t,e,s,a,o){const i=JSON.stringify({error:{code:a,message:o,origin:"runtime"}}),f=`HTTP/1.1 ${e} ${s}\r
2
2
  content-type: application/json; charset=utf-8\r
3
3
  content-length: ${Buffer.byteLength(i)}\r
4
4
  connection: close\r
5
5
  \r
6
- `+i;try{t.end(f)}catch{try{t.destroy()}catch{}}}c(u,"refuseUpgrade");function Y(t){if(new URL(t.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const n=t.headers["x-crtr-attach-revive"];return(Array.isArray(n)?n[0]:n)==="0"}c(Y,"reviveOptedOut");function Z(t){return new URL(t.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}c(Z,"wakeParkedRequested");function R(t){return t===1e3||t===1001||t===1005}c(R,"isCleanViewerClose");function m(t,e,n){n.catch(a=>V({level:"error",event:e,node_id:t,error:a}))}c(m,"detach");async function I(t,e){if(!E(e)){try{t.close(1008,b(`invalid node id: ${e}`))}catch{}return}if(await S(e)===null){try{t.close(1011,b(`no node ${e}`))}catch{}return}await v(e,{link:"viewer\u2194crtrd"});const n=M(e),a=new F(D);let o=!1,i=!1,f,y=!1,d=!1,g=!1;n.on("connect",()=>{y=!0,!o&&g&&A(e,t),m(e,"daemon.bridge.connect_failed",v(e,{link:"relay\u2194broker"}))});const h=c((r,l)=>{if(!o){if(o=!0,q(e,t),f?.stop(),!n.destroyed)try{n.destroy()}catch{}try{t.close(r,b(l))}catch{}}},"teardown");f=X(t);const $=c(async r=>{f?.noteActivity();let l;try{l=a.push(r)}catch(s){const p=s instanceof U?`broker sent an oversized frame (${s.message})`:`failed to decode a broker frame for ${e}`;h(1009,p);return}for(const s of l)if(t.readyState===t.OPEN&&(t.send(JSON.stringify(s)),g&&s?.type==="welcome"&&z(e,t)))try{await L(e)}catch{}},"onData");n.on("data",r=>m(e,"daemon.bridge.data_failed",$(r)));const C=c(async r=>{const l=k("relay\u2194broker",r);await w(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:r.message});const s=r.code==="ECONNREFUSED"||r.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${r.message}`;h(1011,s)},"onSocketError");n.on("error",r=>m(e,"daemon.bridge.socket_error_failed",C(r)));const T=c(async r=>{o||r||(await v(e,{link:"relay\u2194broker"}),h(1e3,"broker socket closed"))},"onSocketClose");n.on("close",r=>m(e,"daemon.bridge.socket_close_failed",T(r)));const x=c(async(r,l)=>{const s=l.toString("utf8");if(o){R(r)&&await v(e,{link:"viewer\u2194crtrd"});return}if(R(r))await v(e,{link:"viewer\u2194crtrd"});else if(!i){i=!0;const p=k("viewer\u2194crtrd",{code:r,reason:s});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:p.kind,retry:{disposition:"auto"},message:s||`remote attach closed (${r})`})}h(r,s||`remote attach closed (${r})`)},"onWsClose");t.on("close",(r,l)=>m(e,"daemon.bridge.ws_close_failed",x(r,l)));const B=c(async()=>{if(!i){i=!0;const r=k("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:r.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}h(1011,"remote attach websocket error")},"onWsError");t.on("error",()=>m(e,"daemon.bridge.ws_error_failed",B())),t.on("message",r=>{if(o||n.destroyed)return;f?.noteActivity();const s=(Array.isArray(r)?Buffer.concat(r):Buffer.isBuffer(r)?r:Buffer.from(new Uint8Array(r))).toString("utf8");if(!d)try{const _=JSON.parse(s);_?.type==="hello"&&(d=!0,g=_.attends!==!1,g&&y&&A(e,t))}catch{}const p=s.endsWith(`
7
- `)?s:s+`
8
- `;try{n.write(p)}catch{}})}c(I,"bridgeConnection");async function me(t,e,n,a){e.on("error",()=>{});try{if(!E(a)){u(e,400,"Bad Request","invalid_node_id",`invalid node id: ${a}`);return}if(await S(a)===null){u(e,404,"Not Found","node_not_found",`no node ${a}`);return}if(Y(t)){if(!await W(a,250)){u(e,409,"Conflict","node_dormant",`node ${a} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const i=await H(a,{resume:!0,capacity:"refuse"},Z(t));if(i.parked){u(e,409,"Conflict","node_dormant",`node ${a} is parked; attach with ?wakeParked=1 to wake it`);return}o=i.result.launch?.exited}catch(i){const f=i instanceof Error?i.message:String(i);u(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await J(a,o)){u(e,409,"Conflict","broker_not_ready",`broker view socket for ${a} did not become listenable after revive`);return}}if(e.destroyed)return;K.handleUpgrade(t,e,n,o=>m(a,"daemon.bridge.connection_failed",I(o,a)))}catch(o){const i=o instanceof Error?o.message:String(o);if(j(o)){u(e,400,"Bad Request","invalid_request",i);return}u(e,500,"Internal Server Error","internal",`attach upgrade failed: ${i}`)}}c(me,"handleAttachUpgrade");export{Q as REMOTE_ATTACH_HEARTBEAT_MS,G as REMOTE_ATTACH_QUIET_MS,me as handleAttachUpgrade,R as isCleanViewerClose,u as refuseUpgrade,X as startRemoteAttachHeartbeat};
6
+ `+i;try{t.end(f)}catch{try{t.destroy()}catch{}}}n(m,"refuseUpgrade");function I(t){if(new URL(t.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const s=t.headers["x-crtr-attach-revive"];return(Array.isArray(s)?s[0]:s)==="0"}n(I,"reviveOptedOut");function ee(t){return new URL(t.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}n(ee,"wakeParkedRequested");function C(t){return t===1e3||t===1001||t===1005}n(C,"isCleanViewerClose");function d(t,e,s){s.catch(a=>H({level:"error",event:e,node_id:t,error:a}))}n(d,"detach");async function te(t,e){const s=[];let a=n(r=>{s.push(r)},"relayMessage");if(t.on("message",r=>a(r)),!A(e)){try{t.close(1008,b(`invalid node id: ${e}`))}catch{}return}if(await R(e)===null){try{t.close(1011,b(`no node ${e}`))}catch{}return}await v(e,{link:"viewer\u2194crtrd"});const o=J(e),i=new V(U);let f=!1,u=!1,y,_=!1,E=!1,g=!1;o.on("connect",()=>{_=!0,!f&&g&&$(e,t),d(e,"daemon.bridge.connect_failed",v(e,{link:"relay\u2194broker"}))});const h=n((r,l)=>{if(!f){if(f=!0,K(e,t),y?.stop(),!o.destroyed)try{o.destroy()}catch{}try{t.close(r,b(l))}catch{}}},"teardown");y=Z(t);const T=n(async r=>{y?.noteActivity();let l;try{l=i.push(r)}catch(c){const p=c instanceof L?`broker sent an oversized frame (${c.message})`:`failed to decode a broker frame for ${e}`;h(1009,p);return}for(const c of l)if(t.readyState===t.OPEN&&(t.send(JSON.stringify(c)),g&&c?.type==="welcome"&&Q(e,t)))try{await M(e)}catch{}},"onData");o.on("data",r=>d(e,"daemon.bridge.data_failed",T(r)));const x=n(async r=>{const l=k("relay\u2194broker",r);await w(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:r.message});const c=r.code==="ECONNREFUSED"||r.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${r.message}`;h(1011,c)},"onSocketError");o.on("error",r=>d(e,"daemon.bridge.socket_error_failed",x(r)));const B=n(async r=>{f||r||(await v(e,{link:"relay\u2194broker"}),h(1e3,"broker socket closed"))},"onSocketClose");o.on("close",r=>d(e,"daemon.bridge.socket_close_failed",B(r)));const N=n(async(r,l)=>{const c=l.toString("utf8");if(f){C(r)&&await v(e,{link:"viewer\u2194crtrd"});return}if(C(r))await v(e,{link:"viewer\u2194crtrd"});else if(!u){u=!0;const p=k("viewer\u2194crtrd",{code:r,reason:c});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:p.kind,retry:{disposition:"auto"},message:c||`remote attach closed (${r})`})}h(r,c||`remote attach closed (${r})`)},"onWsClose");t.on("close",(r,l)=>d(e,"daemon.bridge.ws_close_failed",N(r,l)));const O=n(async()=>{if(!u){u=!0;const r=k("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await w(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:r.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}h(1011,"remote attach websocket error")},"onWsError");t.on("error",()=>d(e,"daemon.bridge.ws_error_failed",O())),a=n(r=>{if(f||o.destroyed)return;y?.noteActivity();const c=(Array.isArray(r)?Buffer.concat(r):Buffer.isBuffer(r)?r:Buffer.from(new Uint8Array(r))).toString("utf8");if(!E)try{const S=JSON.parse(c);S?.type==="hello"&&(E=!0,g=S.attends!==!1,g&&_&&$(e,t))}catch{}const p=c.endsWith(`
7
+ `)?c:c+`
8
+ `;try{o.write(p)}catch{}},"relayMessage");for(const r of s.splice(0))a(r)}n(te,"bridgeConnection");async function de(t,e,s,a){e.on("error",()=>{});try{if(!A(a)){m(e,400,"Bad Request","invalid_node_id",`invalid node id: ${a}`);return}if(await R(a)===null){m(e,404,"Not Found","node_not_found",`no node ${a}`);return}if(I(t)){if(!await j(a,250)){m(e,409,"Conflict","node_dormant",`node ${a} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const i=await W(a,{resume:!0,capacity:"refuse"},ee(t));if(i.parked){m(e,409,"Conflict","node_dormant",`node ${a} is parked; attach with ?wakeParked=1 to wake it`);return}o=i.result.launch?.exited}catch(i){const f=i instanceof Error?i.message:String(i);m(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await q(a,o)){m(e,409,"Conflict","broker_not_ready",`broker view socket for ${a} did not become listenable after revive`);return}}if(e.destroyed)return;G.handleUpgrade(t,e,s,o=>d(a,"daemon.bridge.connection_failed",te(o,a)))}catch(o){const i=o instanceof Error?o.message:String(o);if(z(o)){m(e,400,"Bad Request","invalid_request",i);return}m(e,500,"Internal Server Error","internal",`attach upgrade failed: ${i}`)}}n(de,"handleAttachUpgrade");export{X as REMOTE_ATTACH_HEARTBEAT_MS,Y as REMOTE_ATTACH_QUIET_MS,de as handleAttachUpgrade,C as isCleanViewerClose,m as refuseUpgrade,Z as startRemoteAttachHeartbeat};