@north-light/cli 0.3.446 → 0.3.448

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 (71) hide show
  1. package/dist/api/contract.d.ts +1 -1
  2. package/dist/api/contract.js +1 -1
  3. package/dist/api/dto/nodes.d.ts +5 -0
  4. package/dist/api/dto/objects.d.ts +33 -2
  5. package/dist/api/error-codes.d.ts +15 -0
  6. package/dist/api/error-codes.js +1 -1
  7. package/dist/clients/attach/viewer.js +578 -577
  8. package/dist/commands/canvas/list.js +3 -3
  9. package/dist/commands/canvas/read.js +4 -4
  10. package/dist/commands/node/inspect.js +8 -8
  11. package/dist/commands/sys/sync-shared.js +1 -1
  12. package/dist/commands/sys/update.js +1 -1
  13. package/dist/core/canvas/migrations.js +65 -31
  14. package/dist/core/feed/inbox.js +1 -1
  15. package/dist/core/graph/events.js +8 -8
  16. package/dist/core/graph/kinds/node.js +5 -5
  17. package/dist/core/graph/objects.js +8 -8
  18. package/dist/core/graph/reader.js +3 -3
  19. package/dist/core/graph/receivers.d.ts +2 -1
  20. package/dist/core/graph/receivers.js +5 -5
  21. package/dist/core/graph/spaces/app.js +1 -1
  22. package/dist/core/graph/types.d.ts +9 -1
  23. package/dist/core/peer/client.d.ts +2 -0
  24. package/dist/core/peer/client.js +1 -1
  25. package/dist/core/peer/directory.js +1 -1
  26. package/dist/core/peer/home.d.ts +40 -0
  27. package/dist/core/peer/home.js +2 -0
  28. package/dist/core/peer/ingest.d.ts +26 -0
  29. package/dist/core/peer/ingest.js +1 -0
  30. package/dist/core/peer/names.d.ts +3 -0
  31. package/dist/core/peer/names.js +1 -0
  32. package/dist/core/peer/outbox-store.d.ts +70 -0
  33. package/dist/core/peer/outbox-store.js +4 -0
  34. package/dist/core/peer/receiver.d.ts +8 -0
  35. package/dist/core/peer/receiver.js +1 -0
  36. package/dist/core/peer/stubs.d.ts +53 -0
  37. package/dist/core/peer/stubs.js +1 -0
  38. package/dist/core/peer/version.d.ts +2 -2
  39. package/dist/core/peer/version.js +1 -1
  40. package/dist/core/runtime/broker/inbox.js +1 -1
  41. package/dist/core/scoped-state/settings.js +1 -1
  42. package/dist/daemon/api/app-listener.js +9 -9
  43. package/dist/daemon/api/handlers/messages.js +2 -2
  44. package/dist/daemon/api/handlers/nodes.js +1 -1
  45. package/dist/daemon/api/handlers/objects.d.ts +4 -0
  46. package/dist/daemon/api/handlers/objects.js +2 -2
  47. package/dist/daemon/api/principal.d.ts +4 -4
  48. package/dist/daemon/api/principal.js +1 -1
  49. package/dist/daemon/api/sync-notice.d.ts +17 -0
  50. package/dist/daemon/api/sync-notice.js +1 -0
  51. package/dist/daemon/crtrd.js +8 -8
  52. package/dist/daemon/peer/forward.d.ts +69 -0
  53. package/dist/daemon/peer/forward.js +1 -0
  54. package/dist/daemon/peer/handlers.d.ts +6 -1
  55. package/dist/daemon/peer/handlers.js +1 -1
  56. package/dist/daemon/peer/local-ingress.d.ts +8 -0
  57. package/dist/daemon/peer/local-ingress.js +1 -0
  58. package/dist/daemon/peer/outbox.d.ts +38 -0
  59. package/dist/daemon/peer/outbox.js +1 -0
  60. package/dist/daemon/peer/relay-client.d.ts +35 -0
  61. package/dist/daemon/peer/relay-client.js +1 -0
  62. package/dist/daemon/peer/relay-protocol.d.ts +52 -0
  63. package/dist/daemon/peer/relay-protocol.js +1 -0
  64. package/dist/daemon/peer/relay-service.d.ts +26 -0
  65. package/dist/daemon/peer/relay-service.js +1 -0
  66. package/dist/shared/generated-context.d.ts +8 -0
  67. package/dist/shared/generated-context.js +4 -4
  68. package/dist/shared/inbox-entry-body.js +5 -5
  69. package/package.json +2 -2
  70. package/packages/crouter-identity/package.json +1 -1
  71. package/runtime.lock.json +12 -12
@@ -1,3 +1,3 @@
1
- var s=Object.defineProperty;var t=(e,r)=>s(e,"name",{value:r,configurable:!0});import{defineLeaf as a}from"../../core/command.js";import{PRIVACY_LEVELS_DTO as i}from"../../api/dto/objects.js";import{cliClient as c,rethrowAsCliError as d}from"../api-client.js";import{objectRow as l}from"./read.js";function m(e){const r=l(e);if(e.type!=="document")return r;const n=[`privacy=${e.privacy}`,e.rules!==void 0?`rules=${e.rules}`:""].filter(Boolean).join(" ");return`${r}
2
- ${n}${e.summary?` \u2014 ${e.summary}`:""}`}t(m,"listItemRow");const g=a({name:"list",description:"list objects by type, kind, owner, privacy or name prefix",whenToUse:"browsing what exists without reading it \u2014 the documents an owner holds, a node\u2019s reports, every job of a node. Records nothing, so listing does not make you a watcher.",help:{name:"canvas list",summary:"list the objects you can read, filtered; records nothing",params:[{kind:"flag",name:"type",type:"string",required:!1,constraint:"Only objects of this kind: document, node, job, person, app, repo or profile. The daemon rejects a name no kind declares and lists the kinds."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Only objects of this kind: for documents knowledge, preference or report; for nodes the node kind."},{kind:"flag",name:"owner",type:"string",required:!1,constraint:"Only objects this owner owns directly: a node id, a handle, or any name `crtr canvas read` accepts."},{kind:"flag",name:"privacy",type:"enum",choices:[...i],required:!1,constraint:"Only objects at this privacy level."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Only objects whose name starts with this prefix."},{kind:"flag",name:"deleted",type:"bool",required:!1,constraint:"When present, lists deleted objects instead of live ones."},{kind:"flag",name:"limit",type:"int",required:!1,default:50,constraint:"Page size, 1 to 100."},{kind:"flag",name:"cursor",type:"string",required:!1,constraint:"The `next_cursor` of the previous page."}],output:[{name:"items",type:"string[]",required:!0,constraint:"One row per object: id, `[[name]]`, type/kind, owner handle and preview. A document row adds its privacy, its rule count and its summary."},{name:"next_cursor",type:"string",required:!1,constraint:"Pass as `--cursor` for the next page; absent on the last page."}],outputKind:"object",effects:["None. Listing records no watch."]},run:t(async e=>{const r={...e.type?{type:e.type}:{},...e.kind?{kind:e.kind}:{},...e.owner?{owner:e.owner}:{},...e.privacy?{privacy:e.privacy}:{},...e.name?{name:e.name}:{},...e.deleted===!0?{deleted:!0}:{},limit:e.limit??50,...e.cursor?{cursor:e.cursor}:{}};try{return{...await c().objects.list(r)}}catch(n){d(n)}},"run"),render:t(e=>{const{items:r,next_cursor:n}=e;if(r.length===0)return"No objects match.";const o=r.map(m);return n&&o.push("",`More: \`crtr canvas list \u2026 --cursor ${n}\`.`),o.join(`
3
- `)},"render")});export{m as listItemRow,g as listLeaf};
1
+ var m=Object.defineProperty;var s=(e,t)=>m(e,"name",{value:t,configurable:!0});import{defineLeaf as h}from"../../core/command.js";import{PRIVACY_LEVELS_DTO as u}from"../../api/dto/objects.js";import{cliClient as f,rethrowAsCliError as p}from"../api-client.js";import{objectRow as l}from"./read.js";function y(e){const t=e.machine?`${l(e)} machine=${e.machine.name}`:l(e);if(e.type!=="document")return t;const r=[`privacy=${e.privacy}`,e.rules!==void 0?`rules=${e.rules}`:""].filter(Boolean).join(" ");return`${t}
2
+ ${r}${e.summary?` \u2014 ${e.summary}`:""}`}s(y,"listItemRow");const v=h({name:"list",description:"list objects by type, kind, owner, privacy or name prefix",whenToUse:"browsing what exists without reading it \u2014 the documents an owner holds, a node\u2019s reports, every job of a node. Records nothing, so listing does not make you a watcher.",help:{name:"canvas list",summary:"list the objects you can read, filtered; records nothing",params:[{kind:"flag",name:"type",type:"string",required:!1,constraint:"Only objects of this kind: document, node, job, person, app, repo or profile. The daemon rejects a name no kind declares and lists the kinds."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Only objects of this kind: for documents knowledge, preference or report; for nodes the node kind."},{kind:"flag",name:"owner",type:"string",required:!1,constraint:"Only objects this owner owns directly: a node id, a handle, or any name `crtr canvas read` accepts."},{kind:"flag",name:"privacy",type:"enum",choices:[...u],required:!1,constraint:"Only objects at this privacy level."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Only objects whose name starts with this prefix."},{kind:"flag",name:"deleted",type:"bool",required:!1,constraint:"When present, lists deleted objects instead of live ones."},{kind:"flag",name:"machine",type:"string",required:!1,constraint:"List exactly one machine of your account (`runtime:<id>` or its bare id), paging through its own cursor. Without it a joined runtime lists its own objects plus the first page of every other machine, each row labelled `machine=<name>`."},{kind:"flag",name:"limit",type:"int",required:!1,default:50,constraint:"Page size, 1 to 100."},{kind:"flag",name:"cursor",type:"string",required:!1,constraint:"The `next_cursor` of the previous page."}],output:[{name:"items",type:"string[]",required:!0,constraint:"One row per object: id, `[[name]]`, type/kind, owner handle and preview. A document row adds its privacy, its rule count and its summary."},{name:"machines",type:"object[]",required:!1,constraint:"On a joined runtime: one entry per machine, `{machine_id, name, state: ok|unreachable|too_old, more}`. `more` means that machine has further rows: page it with `--machine`."},{name:"next_cursor",type:"string",required:!1,constraint:"Pass as `--cursor` for the next page of THIS machine (or of `--machine`); absent on the last page."}],outputKind:"object",effects:["None. Listing records no watch."]},run:s(async e=>{const t={...e.type?{type:e.type}:{},...e.kind?{kind:e.kind}:{},...e.owner?{owner:e.owner}:{},...e.privacy?{privacy:e.privacy}:{},...e.name?{name:e.name}:{},...e.deleted===!0?{deleted:!0}:{},...e.machine?{machine:e.machine}:{},limit:e.limit??50,...e.cursor?{cursor:e.cursor}:{}};try{return{...await f().objects.list(t)}}catch(r){p(r)}},"run"),render:s(e=>{const{items:t,next_cursor:r,machines:o}=e,i=o?.length===1?o[0].machine_id:null,a=t.length===0?["No objects match."]:t.map(y),c=(o??[]).filter(n=>n.state!=="ok"),d=(o??[]).filter(n=>n.state==="ok"&&n.more&&n.machine_id!==o[0].machine_id&&i===null);(c.length>0||d.length>0)&&a.push("");for(const n of c)a.push(n.state==="too_old"?`Not listed: ${n.name} (${n.machine_id}) runs a crtr too old to take part; update it with \`crtr sys update\` there.`:`Not listed: ${n.name} (${n.machine_id}) is unreachable, so its objects are missing from this list.`);for(const n of d)a.push(`${n.name} has more: \`crtr canvas list --machine ${n.machine_id} \u2026\`.`);return r&&a.push("",`More: \`crtr canvas list \u2026${i===null?"":` --machine ${i}`} --cursor ${r}\`.`),a.join(`
3
+ `)},"render")});export{y as listItemRow,v as listLeaf};
@@ -1,10 +1,10 @@
1
- var l=Object.defineProperty;var o=(t,e)=>l(t,"name",{value:e,configurable:!0});import{defineLeaf as p}from"../../core/command.js";import{attr as i,header as m,section as f}from"../../core/graph/kinds/render.js";import{PREVIEW_RESULT_PATH_ENV as c}from"../../core/preview-result-path.js";import{isJsonOutput as b}from"../../core/io.js";import{cliClient as w,rethrowAsCliError as y}from"../api-client.js";const j="A name (the `[[ ]]` brackets are optional) or a raw object id. A name is `<owner-handle>/<path>`; a node or other owner is also named by its id or handle.";import{attr as q,objectRow as O}from"../../core/graph/kinds/render.js";function h(t){if(t.state==="remote")return`No object named ${t.remote} on this runtime. It may be on another runtime, or the name may be misspelled.`;if(t.state==="deleted"){const e=t.deleted;return[`${m("deleted",e,i("deleted_at",e.deleted_at))}`,`Last preview: ${e.preview}`,"</deleted>"].join(`
1
+ var l=Object.defineProperty;var o=(t,e)=>l(t,"name",{value:e,configurable:!0});import{defineLeaf as p}from"../../core/command.js";import{attr as i,header as u,section as f}from"../../core/graph/kinds/render.js";import{PREVIEW_RESULT_PATH_ENV as c}from"../../core/preview-result-path.js";import{isJsonOutput as b}from"../../core/io.js";import{cliClient as w,rethrowAsCliError as y}from"../api-client.js";const j="A name (the `[[ ]]` brackets are optional) or a raw object id. A name is `<owner-handle>/<path>`; a node or other owner is also named by its id or handle.";import{attr as q,objectRow as I}from"../../core/graph/kinds/render.js";function h(t){if(t.state==="remote")return`No object named ${t.remote} on this runtime. It may be on another runtime, or the name may be misspelled.`;if(t.state==="unknown")return`No machine of yours answers for ${t.ref} (unreachable: ${t.unreachable.join(", ")||"none named"}). It may be on one of them; try again when they are back.`;if(t.state==="deleted"){const e=t.deleted;return[`${u("deleted",e,i("deleted_at",e.deleted_at))}`,`Last preview: ${e.preview}`,"</deleted>"].join(`
2
2
  `)}return`${t.text}
3
- </object>`}o(h,"renderRead");function u(t){if(t.state!=="object"||t.type!=="document")return null;const e=t.data,n=t.object,r=[m("object",n,i("privacy",n.privacy)+i("revision",e.revision)),`Preview: ${n.preview}`];if(e.summary&&r.push(`Summary: ${e.summary}`),e.fields!==void 0&&r.push(`<fields>
3
+ </object>`}o(h,"renderRead");function m(t){if(t.state!=="object"||t.type!=="document")return null;const e=t.data,n=t.object,r=[u("object",n,i("privacy",n.privacy)+i("revision",e.revision)),`Preview: ${n.preview}`];if(e.summary&&r.push(`Summary: ${e.summary}`),e.fields!==void 0&&r.push(`<fields>
4
4
  ${JSON.stringify(e.fields,null,2)}
5
5
  </fields>`),e.needs_merge&&(e.heads.forEach((a,d)=>r.push(`<head${i("rev",a.rev_id)}${i("number",a.number)}${i("author",a.author_id)}>
6
6
  ${e.bodies[d]??""}
7
7
  </head>`)),r.push(`This document has ${e.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)),e.listing?.length){const a=e.listing.some(s=>s.owner?.id===n.owner?.id&&s.name.startsWith(`${n.name}/`)),d=e.listing.some(s=>s.owner?.id!==n.owner?.id||!s.name.startsWith(`${n.name}/`));r.push("",...f(a&&d?`Names under ${n.name}/ and documents it links to`:a?`Names under ${n.name}/`:"Documents it links to",e.listing))}return r.push("</object>"),{body:e.needs_merge?"":e.bodies[0]??"",metadata:r.join(`
8
- `),context:e.attachments??""}}o(u,"documentReadParts");function v(t){const e=u(t);return e===null||t.state!=="object"||b()?t:{state:"object",type:"document",object:t.object,readMetadata:e.metadata,readContext:e.context}}o(v,"previewRead");function g(t){const e=u(t);if(e===null||process.env[c]===void 0&&process.stdout.isTTY)return h(t);const n=`${e.metadata}
8
+ `),context:e.attachments??""}}o(m,"documentReadParts");function v(t){const e=m(t);return e===null||t.state!=="object"||b()?t:{state:"object",type:"document",object:t.object,readMetadata:e.metadata,readContext:e.context}}o(v,"previewRead");function g(t){const e=m(t);if(e===null||process.env[c]===void 0&&process.stdout.isTTY)return h(t);const n=`${e.metadata}
9
9
  ${e.context?`${e.context}
10
- `:""}`;return process.env[c]||process.stderr.write(n),e.body}o(g,"renderReadOutput");const k=p({name:"read",description:"read one object \u2014 a document, node, job or owner \u2014 by name or id",whenToUse:"you need the content or state of an object you can name: a document\u2019s body, a node\u2019s status and what it owns, a job\u2019s result. Reading makes you a watcher of the object. Find the name first with `crtr canvas search` or `crtr canvas list` when you do not know it.",help:{name:"canvas read",summary:"read one object by name or id and become a watcher of it",params:[{kind:"positional",name:"ref",required:!0,constraint:j},{kind:"flag",name:"fields",type:"bool",required:!1,constraint:"When present, a document read also returns its delivery rules, why-it-exists, unlisted, lint-ignore and plugin extension fields."}],output:[{name:"object",type:"string",required:!0,constraint:"A document prints only its exact body to stdout (including when piped or redirected). Its attributed `<object>` header, preview, summary, revision, listing, linked previews, and `<auto-loaded-context>` arrive AFTER command output in a node\u2019s tool result. Several heads print no stdout body; each head with its text appears in metadata, and the next `crtr doc edit` merges them. Outside a node, metadata goes to stderr when stdout is not a TTY; a TTY shows the full rendering as before. `--json` is unchanged. Non-document objects retain their full rendered stdout."},{name:"deleted",type:"string",required:!1,constraint:"`<deleted \u2026>` with the last preview when the object was deleted."},{name:"remote",type:"string",required:!1,constraint:"A line saying no object has that name on this runtime: it may be on another runtime, or the name may be misspelled."}],outputKind:"object",effects:["A live read records a watch on the object for you (every event subject) and publishes a read event to its other watchers. A deleted or remote answer records nothing."]},run:o(async t=>{try{return{...await w().objects.read(t.ref,t.fields===!0?{fields:!0}:void 0)}}catch(e){y(e)}},"run"),render:o(t=>g(t),"render"),preview:o(t=>v(t),"preview"),stdoutExact:o(t=>u(t)!==null&&!(process.env[c]===void 0&&process.stdout.isTTY),"stdoutExact")});export{j as REF_CONSTRAINT,q as attr,u as documentReadParts,O as objectRow,v as previewRead,k as readLeaf,h as renderRead,g as renderReadOutput};
10
+ `:""}`;return process.env[c]||process.stderr.write(n),e.body}o(g,"renderReadOutput");const _=p({name:"read",description:"read one object \u2014 a document, node, job or owner \u2014 by name or id",whenToUse:"you need the content or state of an object you can name: a document\u2019s body, a node\u2019s status and what it owns, a job\u2019s result. Reading makes you a watcher of the object. Find the name first with `crtr canvas search` or `crtr canvas list` when you do not know it.",help:{name:"canvas read",summary:"read one object by name or id and become a watcher of it",params:[{kind:"positional",name:"ref",required:!0,constraint:j},{kind:"flag",name:"fields",type:"bool",required:!1,constraint:"When present, a document read also returns its delivery rules, why-it-exists, unlisted, lint-ignore and plugin extension fields."}],output:[{name:"object",type:"string",required:!0,constraint:"A document prints only its exact body to stdout (including when piped or redirected). Its attributed `<object>` header, preview, summary, revision, listing, linked previews, and `<auto-loaded-context>` arrive AFTER command output in a node\u2019s tool result. Several heads print no stdout body; each head with its text appears in metadata, and the next `crtr doc edit` merges them. Outside a node, metadata goes to stderr when stdout is not a TTY; a TTY shows the full rendering as before. `--json` is unchanged. Non-document objects retain their full rendered stdout."},{name:"deleted",type:"string",required:!1,constraint:"`<deleted \u2026>` with the last preview when the object was deleted."},{name:"remote",type:"string",required:!1,constraint:"A line saying no object has that name on this runtime: it may be on another runtime, or the name may be misspelled."}],outputKind:"object",effects:["A live read records a watch on the object for you (every event subject) and publishes a read event to its other watchers. A deleted or remote answer records nothing."]},run:o(async t=>{try{return{...await w().objects.read(t.ref,t.fields===!0?{fields:!0}:void 0)}}catch(e){y(e)}},"run"),render:o(t=>g(t),"render"),preview:o(t=>v(t),"preview"),stdoutExact:o(t=>m(t)!==null&&!(process.env[c]===void 0&&process.stdout.isTTY),"stdoutExact")});export{j as REF_CONSTRAINT,q as attr,m as documentReadParts,I as objectRow,v as previewRead,_ as readLeaf,h as renderRead,g as renderReadOutput};
@@ -1,12 +1,12 @@
1
- var N=Object.defineProperty;var h=(n,e)=>N(n,"name",{value:e,configurable:!0});import{defineBranch as R,defineLeaf as b}from"../../core/command.js";import{InputError as y}from"../../core/io.js";import{requireScope as P}from"../../core/errors.js";import{isPidAlive as I}from"../../core/canvas/pid.js";import{fullName as k}from"../../core/canvas/labels.js";import{fuzzyMatch as O}from"../../core/tui/fuzzy.js";import{nodeSnapshotLeaf as F}from"../node-snapshot.js";import{nodeTranscriptLeaf as L}from"../node-transcript.js";import{nodeContextLeaf as A}from"../node-context.js";import{cliClient as $,cliCanvasSource as x,rethrowAsCliError as w}from"../api-client.js";import{RemoteCanvasSource as q}from"../../core/canvas/remote-canvas-source.js";import{kindsStateBlock as C,profilesStateBlock as U,resolveProfileViaDaemon as D}from"../profile/daemon-profiles.js";import{focusViewer as z,nodeInPane as E}from"../surface/node/placement.js";const B=b({name:"list",description:"list nodes on the canvas",whenToUse:"you want a flat roster of the nodes on the canvas, sliced by displayed name, status, kind, mode, lifecycle, profile, cwd, and graph scope (--under a node, for that node plus its subscription descendants). The filters AND together. Use `node inspect show` instead to drill into one node and its spine neighbors, `canvas dashboard` for the tree shape, and `canvas attention` to find nodes blocked on the user",help:{name:"node inspect list",summary:"list nodes on the canvas, filtered by any combination of attribute slices and a graph-scope (--under) that AND together",params:[{kind:"flag",name:"status",type:"string",required:!1,constraint:"Filter status (comma-separated for several; accepted values: active, idle, done, dead, canceled). NOTE: `active` means the engine process is live (never closed), NOT that the node is generating right now \u2014 an active node is usually dormant between turns. To tell working-vs-idle, check the pi session-file mtime or CPU, not status."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Filter by persona kind (comma-separated for several). The <kinds> list below names every top-level installable kind; a registered sub-kind filters too by exact path even though it is not listed."},{kind:"flag",name:"mode",type:"string",required:!1,constraint:"Filter by mode (comma-separated for several; accepted values: base, orchestrator)."},{kind:"flag",name:"lifecycle",type:"string",required:!1,constraint:"Filter by lifecycle (comma-separated for several; accepted values: terminal, resident)."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Filter by profile. On the local canvas, accepts a profile id or manifest name from the <profiles> list below, or a close-enough name that resolves to the nearest profile. Against a remote canvas, pass the exact profile id carried by its node rows."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Filter by the displayed node label (handle plus generated description) with the canvas browser\u2019s case-insensitive fuzzy subsequence match."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Filter to nodes pinned to this exact cwd (absolute path). Roster is canvas-wide (all cwds) by default."},{kind:"flag",name:"under",type:"string",required:!1,constraint:'Graph scope: restrict to this node and its subscription descendants (the sub-DAG reachable downward \u2014 its reports, theirs, \u2026). This is "one initiative / my subtree". ANDs with every attribute filter above, narrowing any of them to this subtree.'},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"nodes",type:"object[]",required:!0,constraint:"Rows include {node_id, name, kind, mode, lifecycle, status, cwd, profile_id, parent, created}. `name` is the displayed node label searched by --name and shown in canvas views. `profile_id` is the stable profile-directory id (null only for historical no-profile nodes)."}],outputKind:"object",effects:["Read-only: lists nodes through the daemon API."]},helpState:{leaf:h(async()=>(await Promise.all([C(),U()])).join(`
2
- `),"leaf")},run:h(async n=>{const e=h(r=>{const g=n[r];return g!==void 0&&g!==""?g.split(",").map(v=>v.trim()).filter(v=>v!==""):void 0},"csv"),o=e("status"),s=e("kind"),u=e("mode"),d=e("lifecycle"),f=n.profile,c=n.name,l=n.cwd,i=n.under,p=x({canvasName:n.canvas}),a=p instanceof q?f:f===void 0?void 0:(await D(f)).id;let t;if(i!==void 0&&i!==""){if(await p.getNode(i).catch(w)===null)throw new y({error:"not_found",message:`no node: ${i}`,next:"List nodes with `crtr node inspect list`, then pass a real id to --under."});t=new Set([i,...await p.view(i)])}return{nodes:(await p.listNodes(o!==void 0?{status:o}:void 0).catch(w)).filter(r=>!(t!==void 0&&!t.has(r.node_id)||s!==void 0&&!s.includes(r.kind)||u!==void 0&&!u.includes(r.mode)||d!==void 0&&!d.includes(r.lifecycle)||a!==void 0&&r.profile_id!==a||l!==void 0&&l!==""&&r.cwd!==l)).map(r=>({...r,name:k(r)})).filter(r=>c===void 0||c===""||O(c,r.name))}},"run")}),S=new WeakSet;async function j(n,e){const o=await n.getNode(e.node_id).catch(w);return{node_id:e.node_id,name:o?k(o):"(missing)",kind:o?.kind??"?",status:o?o.intent?`${o.status}/${o.intent}`:o.status:"?",active:e.active}}h(j,"enrichNeighbor");const K=b({name:"show",description:"show a node + its spine neighbors and drill-in pointers",whenToUse:"you want one node in depth \u2014 the debugging entrypoint: a glanceable meta slice, named spine neighbors, a pending-cron count, and exact drill-in paths. Use `node inspect list` for the flat roster or `canvas dashboard` for the whole-tree shape",help:{name:"node inspect show",summary:"show a node in depth \u2014 meta slice, named neighbors, pending-cron count, and drill-in pointers",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id."},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"node",type:"object",required:!0,constraint:"The full node meta (system prompt + every telemetry field). The render surfaces a glanceable slice; `--json` carries the complete dump."},{name:"fault",type:"object",required:!0,constraint:"The active runtime fault projection, or null: {link, kind, retry: {disposition}, since}."},{name:"reports",type:"object[]",required:!0,constraint:"Who this node subscribes to (its reports/down), each enriched with {node_id, name, kind, status, active} \u2014 these are typically its spawned children."},{name:"managers",type:"object[]",required:!0,constraint:"Who subscribes to this node (its managers/up), same enriched shape."},{name:"pending_crons",type:"number",required:!0,constraint:"How many pending crons were created by this node. Inspect with `crtr cron list`."},{name:"paths",type:"object",required:!0,constraint:"Resolved on-disk locations: {context_dir, session_file} \u2014 read these directly to debug. Reports are documents: `crtr canvas read <node>/reports/<name>`."},{name:"follow_up",type:"string",required:!0,constraint:"The concrete next commands to drill deeper."}],outputKind:"object",effects:["Read-only: reads the node, its edges, and pending crons through crtrd."],preview:{suppressOutput:!0}},run:h(async n=>{const e=n.node,o=n.canvas,s=x({canvasName:o});if(s instanceof q){const t=await s.rawShow(e);if(t===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list --canvas <name>`."});const m={...t};return S.add(m),m}const u=await s.getNode(e).catch(t=>w(t,"List nodes with `crtr node inspect list`."));if(u===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list`."});const d=u,f=$(),c=await Promise.all((await s.subscriptionsOf(e)).map(t=>j(s,t))),l=await Promise.all((await s.subscribersOf(e)).map(t=>j(s,t))),i=(await f.listCrons().catch(w)).filter(t=>t.created_by===e).length,p={context_dir:d.paths.context_dir,...d.pi_session_file!==void 0?{session_file:d.pi_session_file}:{}},a=[];return a.push(`List the documents it owns (reports, plans, notes): \`crtr canvas list --owner ${e}\`.`),a.push(`Browse its context dir (and its subscriptions') in nvim: \`crtr node inspect context ${e}\`.`),p.session_file&&a.push(`Read the raw conversation transcript: ${p.session_file}`),a.push(`On-disk context dir (ls/read directly): ${p.context_dir}`),i>0&&a.push(`It created ${i} pending cron(s): \`crtr cron list\`.`),c.length>0&&a.push(`Drill into a child/report: \`crtr node inspect show <node_id>\` (${c.map(t=>t.node_id).join(", ")}).`),a.push(`Full machine dump (system prompt + all telemetry): \`crtr --json node inspect show ${e}\`.`),{node:d,fault:d.fault??null,reports:c,managers:l,pending_crons:i,paths:p,follow_up:a.join(`
3
- `)}},"run"),render:h(n=>{const e=n.node,o=String(e.node_id),s=e.pi_pid,d=S.has(n)?"remote (liveness not checked locally)":I(s)?"alive":"dead",f=e.intent?`/${String(e.intent)}`:"",c=n.fault,l=[];l.push(`# ${k(e)} (${o})`);const i=[`- kind/mode/lifecycle: ${e.kind} / ${e.mode} / ${e.lifecycle}`,`- status: ${e.status}${f}`,...c==null?[]:[`- fault: ${String(c.kind)} / ${String(c.retry?.disposition)} since ${String(c.since)}`],`- broker pid: ${s??"(none)"} \u2014 ${d}`,`- cwd: ${e.cwd}`,`- host: ${e.host_kind}`+(e.profile_id?` \xB7 profile ${e.profile_id}`:""),`- cycles: ${e.cycles} \xB7 created ${e.created}`];e.parent&&i.push(`- parent: ${e.parent}`),i.push(`- creator: ${e.creator??"an external process"}`),e.waiting_for&&i.push(`- waiting for message: ${e.waiting_for}`),l.push(i.join(`
4
- `));const p=h((a,t)=>{if(t.length===0)return`${a}: none`;const m=["node_id","name","kind","status","active"],_=`| ${m.join(" | ")} |`,r=`| ${m.map(()=>"---").join(" | ")} |`,g=t.map(v=>`| ${m.map(T=>String(v[T]??"").replace(/\|/g,"\\|").replace(/\n/g," ")).join(" | ")} |`).join(`
5
- `);return`${t.length} ${a}:
1
+ var R=Object.defineProperty;var h=(n,e)=>R(n,"name",{value:e,configurable:!0});import{defineBranch as P,defineLeaf as k}from"../../core/command.js";import{InputError as y}from"../../core/io.js";import{requireScope as I}from"../../core/errors.js";import{isPidAlive as O}from"../../core/canvas/pid.js";import{fullName as $}from"../../core/canvas/labels.js";import{fuzzyMatch as F}from"../../core/tui/fuzzy.js";import{nodeSnapshotLeaf as L}from"../node-snapshot.js";import{nodeTranscriptLeaf as A}from"../node-transcript.js";import{nodeContextLeaf as C}from"../node-context.js";import{cliClient as _,cliCanvasSource as x,rethrowAsCliError as w}from"../api-client.js";import{RemoteCanvasSource as q}from"../../core/canvas/remote-canvas-source.js";import{kindsStateBlock as U,profilesStateBlock as D,resolveProfileViaDaemon as z}from"../profile/daemon-profiles.js";import{focusViewer as E,nodeInPane as B}from"../surface/node/placement.js";const M=k({name:"list",description:"list nodes on the canvas",whenToUse:"you want a flat roster of the nodes on the canvas, sliced by displayed name, status, kind, mode, lifecycle, profile, cwd, and graph scope (--under a node, for that node plus its subscription descendants). The filters AND together. Use `node inspect show` instead to drill into one node and its spine neighbors, `canvas dashboard` for the tree shape, and `canvas attention` to find nodes blocked on the user",help:{name:"node inspect list",summary:"list nodes on the canvas, filtered by any combination of attribute slices and a graph-scope (--under) that AND together",params:[{kind:"flag",name:"status",type:"string",required:!1,constraint:"Filter status (comma-separated for several; accepted values: active, idle, done, dead, canceled). NOTE: `active` means the engine process is live (never closed), NOT that the node is generating right now \u2014 an active node is usually dormant between turns. To tell working-vs-idle, check the pi session-file mtime or CPU, not status."},{kind:"flag",name:"kind",type:"string",required:!1,constraint:"Filter by persona kind (comma-separated for several). The <kinds> list below names every top-level installable kind; a registered sub-kind filters too by exact path even though it is not listed."},{kind:"flag",name:"mode",type:"string",required:!1,constraint:"Filter by mode (comma-separated for several; accepted values: base, orchestrator)."},{kind:"flag",name:"lifecycle",type:"string",required:!1,constraint:"Filter by lifecycle (comma-separated for several; accepted values: terminal, resident)."},{kind:"flag",name:"profile",type:"string",required:!1,constraint:"Filter by profile. On the local canvas, accepts a profile id or manifest name from the <profiles> list below, or a close-enough name that resolves to the nearest profile. Against a remote canvas, pass the exact profile id carried by its node rows."},{kind:"flag",name:"name",type:"string",required:!1,constraint:"Filter by the displayed node label (handle plus generated description) with the canvas browser\u2019s case-insensitive fuzzy subsequence match."},{kind:"flag",name:"cwd",type:"string",required:!1,constraint:"Filter to nodes pinned to this exact cwd (absolute path). Roster is canvas-wide (all cwds) by default."},{kind:"flag",name:"under",type:"string",required:!1,constraint:'Graph scope: restrict to this node and its subscription descendants (the sub-DAG reachable downward \u2014 its reports, theirs, \u2026). This is "one initiative / my subtree". ANDs with every attribute filter above, narrowing any of them to this subtree.'},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"nodes",type:"object[]",required:!0,constraint:"Rows include {node_id, name, kind, mode, lifecycle, status, cwd, profile_id, parent, created}. `name` is the displayed node label searched by --name and shown in canvas views. `profile_id` is the stable profile-directory id (null only for historical no-profile nodes)."}],outputKind:"object",effects:["Read-only: lists nodes through the daemon API."]},helpState:{leaf:h(async()=>(await Promise.all([U(),D()])).join(`
2
+ `),"leaf")},run:h(async n=>{const e=h(r=>{const g=n[r];return g!==void 0&&g!==""?g.split(",").map(v=>v.trim()).filter(v=>v!==""):void 0},"csv"),o=e("status"),t=e("kind"),u=e("mode"),d=e("lifecycle"),m=n.profile,c=n.name,l=n.cwd,i=n.under,p=x({canvasName:n.canvas}),a=p instanceof q?m:m===void 0?void 0:(await z(m)).id;let s;if(i!==void 0&&i!==""){if(await p.getNode(i).catch(w)===null)throw new y({error:"not_found",message:`no node: ${i}`,next:"List nodes with `crtr node inspect list`, then pass a real id to --under."});s=new Set([i,...await p.view(i)])}return{nodes:(await p.listNodes(o!==void 0?{status:o}:void 0).catch(w)).filter(r=>!(s!==void 0&&!s.has(r.node_id)||t!==void 0&&!t.includes(r.kind)||u!==void 0&&!u.includes(r.mode)||d!==void 0&&!d.includes(r.lifecycle)||a!==void 0&&r.profile_id!==a||l!==void 0&&l!==""&&r.cwd!==l)).map(r=>({...r,name:$(r)})).filter(r=>c===void 0||c===""||F(c,r.name))}},"run")}),S=new WeakSet;async function j(n,e){const o=await n.getNode(e.node_id).catch(w);return{node_id:e.node_id,name:o?$(o):"(missing)",kind:o?.kind??"?",status:o?o.intent?`${o.status}/${o.intent}`:o.status:"?",active:e.active}}h(j,"enrichNeighbor");const K=k({name:"show",description:"show a node + its spine neighbors and drill-in pointers",whenToUse:"you want one node in depth \u2014 the debugging entrypoint: a glanceable meta slice, named spine neighbors, a pending-cron count, and exact drill-in paths. Use `node inspect list` for the flat roster or `canvas dashboard` for the whole-tree shape",help:{name:"node inspect show",summary:"show a node in depth \u2014 meta slice, named neighbors, pending-cron count, and drill-in pointers",params:[{kind:"positional",name:"node",required:!0,constraint:"Node id."},{kind:"flag",name:"canvas",type:"string",required:!1,constraint:"Read from the named remote canvas target (see `crtr canvas config list`) instead of the local canvas. Overrides `crtr canvas use`."}],output:[{name:"node",type:"object",required:!0,constraint:"The full node meta (system prompt + every telemetry field). The render surfaces a glanceable slice; `--json` carries the complete dump."},{name:"fault",type:"object",required:!0,constraint:"The active runtime fault projection, or null: {link, kind, retry: {disposition}, since}."},{name:"reports",type:"object[]",required:!0,constraint:"Who this node subscribes to (its reports/down), each enriched with {node_id, name, kind, status, active} \u2014 these are typically its spawned children."},{name:"managers",type:"object[]",required:!0,constraint:"Who subscribes to this node (its managers/up), same enriched shape."},{name:"pending_crons",type:"number",required:!0,constraint:"How many pending crons were created by this node. Inspect with `crtr cron list`."},{name:"paths",type:"object",required:!0,constraint:"Resolved on-disk locations: {context_dir, session_file} \u2014 read these directly to debug. Reports are documents: `crtr canvas read <node>/reports/<name>`."},{name:"follow_up",type:"string",required:!0,constraint:"The concrete next commands to drill deeper."}],outputKind:"object",effects:["Read-only: reads the node, its edges, and pending crons through crtrd."],preview:{suppressOutput:!0}},run:h(async n=>{const e=n.node,o=n.canvas,t=x({canvasName:o});if(t instanceof q){const s=await t.rawShow(e);if(s===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list --canvas <name>`."});const f={...s};return S.add(f),f}const u=await t.getNode(e).catch(s=>w(s,"List nodes with `crtr node inspect list`."));if(u===null)throw new y({error:"not_found",message:`no node: ${e}`,next:"List nodes with `crtr node inspect list`."});const d=u,m=_(),c=await Promise.all((await t.subscriptionsOf(e)).map(s=>j(t,s))),l=await Promise.all((await t.subscribersOf(e)).map(s=>j(t,s))),i=(await m.listCrons().catch(w)).filter(s=>s.created_by===e).length,p={context_dir:d.paths.context_dir,...d.pi_session_file!==void 0?{session_file:d.pi_session_file}:{}},a=[];return a.push(`List the documents it owns (reports, plans, notes): \`crtr canvas list --owner ${e}\`.`),a.push(`Browse its context dir (and its subscriptions') in nvim: \`crtr node inspect context ${e}\`.`),p.session_file&&a.push(`Read the raw conversation transcript: ${p.session_file}`),a.push(`On-disk context dir (ls/read directly): ${p.context_dir}`),i>0&&a.push(`It created ${i} pending cron(s): \`crtr cron list\`.`),c.length>0&&a.push(`Drill into a child/report: \`crtr node inspect show <node_id>\` (${c.map(s=>s.node_id).join(", ")}).`),a.push(`Full machine dump (system prompt + all telemetry): \`crtr --json node inspect show ${e}\`.`),{node:d,fault:d.fault??null,reports:c,managers:l,pending_crons:i,paths:p,follow_up:a.join(`
3
+ `)}},"run"),render:h(n=>{const e=n.node,o=String(e.node_id),t=e.pi_pid,d=S.has(n)?"remote (liveness not checked locally)":O(t)?"alive":"dead",m=e.intent?`/${String(e.intent)}`:"",c=n.fault,l=[];l.push(`# ${$(e)} (${o})`);const i=[`- kind/mode/lifecycle: ${e.kind} / ${e.mode} / ${e.lifecycle}`,`- status: ${e.status}${m}`,...c==null?[]:[`- fault: ${String(c.kind)} / ${String(c.retry?.disposition)} since ${String(c.since)}`],`- broker pid: ${t??"(none)"} \u2014 ${d}`,`- cwd: ${e.cwd}`,`- host: ${e.host_kind}`+(e.profile_id?` \xB7 profile ${e.profile_id}`:""),`- cycles: ${e.cycles} \xB7 created ${e.created}`],p=e.machine;p&&i.push(`- machine: ${p.name??p.id}`),e.parent&&i.push(`- parent: ${e.parent}`),i.push(`- creator: ${e.creator??"an external process"}`),e.waiting_for&&i.push(`- waiting for message: ${e.waiting_for}`),l.push(i.join(`
4
+ `));const a=h((s,f)=>{if(f.length===0)return`${s}: none`;const b=["node_id","name","kind","status","active"],r=`| ${b.join(" | ")} |`,g=`| ${b.map(()=>"---").join(" | ")} |`,v=f.map(T=>`| ${b.map(N=>String(T[N]??"").replace(/\|/g,"\\|").replace(/\n/g," ")).join(" | ")} |`).join(`
5
+ `);return`${f.length} ${s}:
6
6
 
7
- ${_}
8
7
  ${r}
9
- ${g}`},"table");return l.push(p("reports (down \u2014 subscriptions, usually children)",n.reports)),l.push(p("managers (up \u2014 subscribers)",n.managers)),l.push(`${n.pending_crons} pending cron(s)`),l.push(`Drill deeper:
8
+ ${g}
9
+ ${v}`},"table");return l.push(a("reports (down \u2014 subscriptions, usually children)",n.reports)),l.push(a("managers (up \u2014 subscribers)",n.managers)),l.push(`${n.pending_crons} pending cron(s)`),l.push(`Drill deeper:
10
10
  ${String(n.follow_up)}`),l.join(`
11
11
 
12
- `)},"render")}),oe=b({name:"fork",description:"fork a node into an independent idle root with the same conversation and durable context",whenToUse:"a conversation has already accumulated the context you want, and you want a new user-driven branch beside it without sending a prompt or inheriting any graph-management responsibility. This copies the conversation and durable context, then waits for the fork\u2019s first real user message to supply its mandate. Use `node new --fork-from` instead when spawning a managed worker with an immediate task",help:{name:"node fork",summary:"create an independent resident root from a node\u2019s conversation and durable context, with no kickoff prompt or model turn",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Source node id. Mutually exclusive with --pane; one of them is required."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the source node. Mutually exclusive with --node; one of them is required. The prefix menu passes this for you and the new viewer splits beside this pane."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The new independent root id."},{name:"focused",type:"boolean",required:!0,constraint:"True when a new viewer pane opened beside the caller; false outside tmux."},{name:"session",type:"string",required:!1,constraint:"The tmux session containing the new viewer, when one opened."}],outputKind:"object",effects:["Creates a resident base-mode root with the source node\u2019s copied pi conversation, cwd, profile, kind, model override, and durable context files. Top-level initial-prompt.md, yield-message.md, result.json, and the jobs/ folder of background bash jobs are omitted.","Copies no parent, subscriptions, subscribers, children, crons, worktree, situational context, or lifecycle responsibility. Sends no prompt and consumes no model turn; the first real user message becomes the fork\u2019s mandate.","Inside tmux, opens and focuses a surface-attach viewer as an even-horizontal split in the source pane\u2019s window. Outside tmux, the root is still created but no interactive fallback opens."]},run:h(async n=>{P("crtr:act","crtr node fork");const e=n.pane,o=n.node;if(o!==void 0&&e!==void 0)throw new y({error:"conflicting_target",message:"--node and --pane are mutually exclusive",next:"Pass the source node id or its viewer pane, not both."});let s=o;if(s===void 0&&e!==void 0&&(s=E(e)),s===void 0||s==="")throw new y({error:"no_node",message:"no source node was provided or found in the pane",next:"Pass --node <id>, or --pane <pane-id> for a pane showing a node."});const u=await $().forkNode(s).catch(w),d=await z(u.node_id,{cwd:u.cwd,name:u.name,...e!==void 0?{pane:e}:{},newPane:!0});return{node_id:u.node_id,focused:d.focused,session:d.session}},"run"),render:h(n=>{const e=n.focused===!0?` Viewer opened beside the source${n.session?` in session ${n.session}`:""}.`:" No viewer opened because no tmux pane was available.";return`Forked independent idle root ${n.node_id}.${e} It will make no model call until its first real user message.`},"render")}),ie=R({name:"inspect",description:"read one node \u2014 its graph position, conversation, and context dir",whenToUse:"reading everything about ONE node you can name: enumerate the roster (`list`), inspect a node and its spine neighbors (`show`), or browse its on-disk context dir (`context`). The documents a node owns are `crtr canvas list --owner <id>`. Use `canvas dashboard` instead to render the whole tree SHAPE, or `canvas attention` to find which nodes are blocked on the user",help:{name:"node inspect",summary:"read one node (or the roster) \u2014 topology, conversation, and context dir",model:"Inspection is read-only and never revives a node. The roster is the selection surface; one-node metadata points to progressively heavier views: a parsed broker snapshot, rendered conversation, or context browser."},children:[B,K,F,L,A]});export{oe as nodeFork,ie as nodeInspect};
12
+ `)},"render")}),ie=k({name:"fork",description:"fork a node into an independent idle root with the same conversation and durable context",whenToUse:"a conversation has already accumulated the context you want, and you want a new user-driven branch beside it without sending a prompt or inheriting any graph-management responsibility. This copies the conversation and durable context, then waits for the fork\u2019s first real user message to supply its mandate. Use `node new --fork-from` instead when spawning a managed worker with an immediate task",help:{name:"node fork",summary:"create an independent resident root from a node\u2019s conversation and durable context, with no kickoff prompt or model turn",params:[{kind:"flag",name:"node",type:"string",required:!1,constraint:"Source node id. Mutually exclusive with --pane; one of them is required."},{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane showing the source node. Mutually exclusive with --node; one of them is required. The prefix menu passes this for you and the new viewer splits beside this pane."}],output:[{name:"node_id",type:"string",required:!0,constraint:"The new independent root id."},{name:"focused",type:"boolean",required:!0,constraint:"True when a new viewer pane opened beside the caller; false outside tmux."},{name:"session",type:"string",required:!1,constraint:"The tmux session containing the new viewer, when one opened."}],outputKind:"object",effects:["Creates a resident base-mode root with the source node\u2019s copied pi conversation, cwd, profile, kind, model override, and durable context files. Top-level initial-prompt.md, yield-message.md, result.json, and the jobs/ folder of background bash jobs are omitted.","Copies no parent, subscriptions, subscribers, children, crons, worktree, situational context, or lifecycle responsibility. Sends no prompt and consumes no model turn; the first real user message becomes the fork\u2019s mandate.","Inside tmux, opens and focuses a surface-attach viewer as an even-horizontal split in the source pane\u2019s window. Outside tmux, the root is still created but no interactive fallback opens."]},run:h(async n=>{I("crtr:act","crtr node fork");const e=n.pane,o=n.node;if(o!==void 0&&e!==void 0)throw new y({error:"conflicting_target",message:"--node and --pane are mutually exclusive",next:"Pass the source node id or its viewer pane, not both."});let t=o;if(t===void 0&&e!==void 0&&(t=B(e)),t===void 0||t==="")throw new y({error:"no_node",message:"no source node was provided or found in the pane",next:"Pass --node <id>, or --pane <pane-id> for a pane showing a node."});const u=await _().forkNode(t).catch(w),d=await E(u.node_id,{cwd:u.cwd,name:u.name,...e!==void 0?{pane:e}:{},newPane:!0});return{node_id:u.node_id,focused:d.focused,session:d.session}},"run"),render:h(n=>{const e=n.focused===!0?` Viewer opened beside the source${n.session?` in session ${n.session}`:""}.`:" No viewer opened because no tmux pane was available.";return`Forked independent idle root ${n.node_id}.${e} It will make no model call until its first real user message.`},"render")}),re=P({name:"inspect",description:"read one node \u2014 its graph position, conversation, and context dir",whenToUse:"reading everything about ONE node you can name: enumerate the roster (`list`), inspect a node and its spine neighbors (`show`), or browse its on-disk context dir (`context`). The documents a node owns are `crtr canvas list --owner <id>`. Use `canvas dashboard` instead to render the whole tree SHAPE, or `canvas attention` to find which nodes are blocked on the user",help:{name:"node inspect",summary:"read one node (or the roster) \u2014 topology, conversation, and context dir",model:"Inspection is read-only and never revives a node. The roster is the selection surface; one-node metadata points to progressively heavier views: a parsed broker snapshot, rendered conversation, or context browser."},children:[M,K,L,A,C]});export{ie as nodeFork,re as nodeInspect};
@@ -1 +1 @@
1
- var f=Object.defineProperty;var i=(n,e)=>f(n,"name",{value:e,configurable:!0});import{ApiError as h}from"../../api/index.js";import{identifyCheckout as p}from"../../core/graph/repo-sync/identity.js";import{rulesFromFrontmatter as w}from"../../core/graph/rules.js";import{usage as g}from"../../core/errors.js";function S(n){if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n)}i(S,"scalarString");function m(n){let e=n.replace(/\s+/g," ").trim();return e=e.replace(/^[,;:.\s]+/,"").replace(/[,;:.\s]+$/,""),/^[A-Z][a-z]/.test(e)&&(e=e.charAt(0).toLowerCase()+e.slice(1)),e}i(m,"cleanClause");const y=/\b(?:use\s+this\s+skill\s+when|use\s+this\s+when|this\s+skill\s+should\s+be\s+used\s+when|used\s+when|use\s+when)\b\s*/i;function v(n,e){const t=n.replace(/\s+/g," ").trim();if(t==="")return`When this migrated ${e} applies, this ${e} should be read.`;const r=t.match(y);if(r&&r.index!==void 0){const a=m(t.slice(0,r.index)),o=m(t.slice(r.index+r[0].length));if(o!==""){let s=`When ${o}, this ${e} should be read`;return a!==""&&(s+=` because ${a}`),`${s}.`}}return`When ${m(t)}, this ${e} should be read.`}i(v,"routeFromDescription");function C(n){return n.replace(/\\/g,"/").replace(/\.md$/i,"").split("/").map(t=>t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")).filter(Boolean).join("/")}i(C,"normalizedName");function E(n){return w(n).map(e=>({on:e.on,deliver:e.deliver,...e.match!==void 0?{match:e.match}:{},...e.matchFrontmatter!==void 0?{match_frontmatter:e.matchFrontmatter}:{},...e.if!==void 0?{if:e.if}:{}}))}i(E,"rulesFromLegacyFrontmatter");async function d(n,e,t){let r;do{const a=await n.objects.list({type:e,limit:100,...r?{cursor:r}:{}});for(const o of a.items){const s=await n.objects.read(o.id);if(s.state!=="object"||s.type!==e)continue;const u=s.data;if(u.identity.external_id===t)return u.handle}r=a.next_cursor??void 0}while(r);return null}i(d,"ownerByIdentity");async function l(n,e){const t=new Set;let r;do{const a=await n.objects.list({type:"document",owner:e,limit:100,...r?{cursor:r}:{}});for(const o of a.items)t.add(o.name);r=a.next_cursor??void 0}while(r);return t}i(l,"documentNames");async function W(n,e){const t=p(e);if(!t.ok)throw g(`${e} is not inside a repo: ${t.reason}`);const r=await d(n,"repo",t.externalId);return{owner:"repo",cwd:t.root,handle:r??t.handleHint,existing:r?await l(n,r):new Set}}i(W,"repoOwner");async function k(n){const e=await d(n,"person","user:local");return{owner:"user",cwd:process.cwd(),handle:e??"user",existing:e?await l(n,e):new Set}}i(k,"userOwner");async function z(n,e,t,r){const a={preview:t.preview,...t.summary!==void 0&&t.summary!==""?{summary:t.summary}:{},...t.privacy!==void 0?{privacy:t.privacy}:{},rules:t.rules};if(!e.existing.has(t.name)){const c=await n.docs.write({name:t.name,body:t.body,kind:t.kind,owner:e.owner,cwd:e.cwd,...a});return e.handle=c.name.slice(0,c.name.length-t.name.length-1),e.existing.add(t.name),{name:c.name,changed:!0}}const o=`${e.handle}/${t.name}`,s=await n.objects.read(o),u=s.state==="object"&&s.type==="document"?s.data.bodies:null;return s.state==="object"&&u!==null&&u.length===1&&u[0]===t.body&&s.object.preview===t.preview?{name:o,changed:!1}:{name:(await n.docs.edit(o,{body:t.body,rationale:r,...a})).name,changed:!0}}i(z,"putDoc");function A(n){if(n instanceof h)return n.message;throw n}i(A,"writeFailure");export{C as normalizedName,z as putDoc,W as repoOwner,v as routeFromDescription,E as rulesFromLegacyFrontmatter,S as scalarString,k as userOwner,A as writeFailure};
1
+ var f=Object.defineProperty;var i=(n,e)=>f(n,"name",{value:e,configurable:!0});import{ApiError as h}from"../../api/index.js";import{identifyCheckout as p}from"../../core/graph/repo-sync/identity.js";import{rulesFromFrontmatter as w}from"../../core/graph/rules.js";import{usage as g}from"../../core/errors.js";function S(n){if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n)}i(S,"scalarString");function m(n){let e=n.replace(/\s+/g," ").trim();return e=e.replace(/^[,;:.\s]+/,"").replace(/[,;:.\s]+$/,""),/^[A-Z][a-z]/.test(e)&&(e=e.charAt(0).toLowerCase()+e.slice(1)),e}i(m,"cleanClause");const y=/\b(?:use\s+this\s+skill\s+when|use\s+this\s+when|this\s+skill\s+should\s+be\s+used\s+when|used\s+when|use\s+when)\b\s*/i;function v(n,e){const t=n.replace(/\s+/g," ").trim();if(t==="")return`When this migrated ${e} applies, this ${e} should be read.`;const r=t.match(y);if(r&&r.index!==void 0){const a=m(t.slice(0,r.index)),o=m(t.slice(r.index+r[0].length));if(o!==""){let s=`When ${o}, this ${e} should be read`;return a!==""&&(s+=` because ${a}`),`${s}.`}}return`When ${m(t)}, this ${e} should be read.`}i(v,"routeFromDescription");function C(n){return n.replace(/\\/g,"/").replace(/\.md$/i,"").split("/").map(t=>t.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")).filter(Boolean).join("/")}i(C,"normalizedName");function E(n){return w(n).map(e=>({on:e.on,deliver:e.deliver,...e.match!==void 0?{match:e.match}:{},...e.matchFrontmatter!==void 0?{match_frontmatter:e.matchFrontmatter}:{},...e.if!==void 0?{if:e.if}:{}}))}i(E,"rulesFromLegacyFrontmatter");async function d(n,e,t){let r;do{const a=await n.objects.list({type:e,machine:"self",limit:100,...r?{cursor:r}:{}});for(const o of a.items){const s=await n.objects.read(o.id);if(s.state!=="object"||s.type!==e)continue;const c=s.data;if(c.identity.external_id===t)return c.handle}r=a.next_cursor??void 0}while(r);return null}i(d,"ownerByIdentity");async function l(n,e){const t=new Set;let r;do{const a=await n.objects.list({type:"document",owner:e,machine:"self",limit:100,...r?{cursor:r}:{}});for(const o of a.items)t.add(o.name);r=a.next_cursor??void 0}while(r);return t}i(l,"documentNames");async function W(n,e){const t=p(e);if(!t.ok)throw g(`${e} is not inside a repo: ${t.reason}`);const r=await d(n,"repo",t.externalId);return{owner:"repo",cwd:t.root,handle:r??t.handleHint,existing:r?await l(n,r):new Set}}i(W,"repoOwner");async function k(n){const e=await d(n,"person","user:local");return{owner:"user",cwd:process.cwd(),handle:e??"user",existing:e?await l(n,e):new Set}}i(k,"userOwner");async function z(n,e,t,r){const a={preview:t.preview,...t.summary!==void 0&&t.summary!==""?{summary:t.summary}:{},...t.privacy!==void 0?{privacy:t.privacy}:{},rules:t.rules};if(!e.existing.has(t.name)){const u=await n.docs.write({name:t.name,body:t.body,kind:t.kind,owner:e.owner,cwd:e.cwd,...a});return e.handle=u.name.slice(0,u.name.length-t.name.length-1),e.existing.add(t.name),{name:u.name,changed:!0}}const o=`${e.handle}/${t.name}`,s=await n.objects.read(o),c=s.state==="object"&&s.type==="document"?s.data.bodies:null;return s.state==="object"&&c!==null&&c.length===1&&c[0]===t.body&&s.object.preview===t.preview?{name:o,changed:!1}:{name:(await n.docs.edit(o,{body:t.body,rationale:r,...a})).name,changed:!0}}i(z,"putDoc");function A(n){if(n instanceof h)return n.message;throw n}i(A,"writeFailure");export{C as normalizedName,z as putDoc,W as repoOwner,v as routeFromDescription,E as rulesFromLegacyFrontmatter,S as scalarString,k as userOwner,A as writeFailure};
@@ -1 +1 @@
1
- var u=Object.defineProperty;var c=(o,s)=>u(o,"name",{value:s,configurable:!0});import{defineLeaf as l}from"../../core/command.js";import{updateState as d}from"../../core/config.js";import{projectScopeRoot as p}from"../../core/scope.js";import{selfCheck as f,selfUpdate as m,contentCheck as h}from"../../core/self-update.js";import{marketUpdate as g}from"../pkg/market-manage.js";import{pluginUpdate as y}from"../pkg/plugin-manage.js";import{nowIso as k}from"../../core/fs-utils.js";import{processLocatedGeneration as b,readPackageVersion as _,runtimeManifest as v,selectedGeneration as w}from"./shared.js";const x=l({name:"update",description:"update binary and content",whenToUse:"upgrading crtr or its installed plugins and marketplaces \u2014 pull the latest binary, refresh installed content, or both, or just check what is out of date without applying anything.",help:{name:"sys update",summary:"update the crtr binary and/or installed plugins and marketplaces",params:[{kind:"flag",name:"target",type:"enum",choices:["self","content","all"],required:!1,constraint:"What to update. Default: all."},{kind:"flag",name:"check",type:"bool",required:!1,constraint:"Check for updates without applying them (bounded, blocking)."}],output:[{name:"target",type:"string",required:!1,constraint:"Present when applying updates: self | content | all."},{name:"status",type:"string",required:!1,constraint:"done | failed when applying updates."},{name:"error",type:"string",required:!1,constraint:"Failure message when status is failed."},{name:"updates",type:"object[]",required:!1,constraint:"Present when --check. Each: {name, current, latest, up_to_date, unreachable, kind}."},{name:"up_to_date",type:"boolean",required:!1,constraint:"Present when --check. True when all items are up to date."}],outputKind:"object",effects:["--check \u2014 read-only, bounded network calls.","Default (no --check) \u2014 launches a background job; returns job handle immediately.","Content update replaces each marketplace and source-installed plugin checkout with a freshly staged revision, discarding local modifications in those directories."]},run:c(async o=>{const s=o.target,i=o.check,n=s!==void 0?s:"all";if(i){const t=[];if(n==="self"||n==="all"){const e=f();e!==null?t.push({name:e.package,kind:"self",current:e.current,latest:e.latest,up_to_date:!e.migrating&&e.current===e.latest,unreachable:!1}):t.push({name:"@north-light/cli",kind:"self",current:null,latest:null,up_to_date:!0,unreachable:!0})}if(n==="content"||n==="all"){const e=h();for(const r of e)t.push({name:r.name,kind:r.kind,current:r.current,latest:r.latest,up_to_date:r.up_to_date,unreachable:r.unreachable})}const a=t.every(e=>e.up_to_date||e.unreachable);return{updates:t,up_to_date:a}}try{if(n==="self"||n==="all"){m();const t=["user"];p()&&t.unshift("project");for(const a of t)d(a,e=>{e.last_self_check=k()})}return(n==="content"||n==="all")&&(await g.run({}),await y.run({})),{target:n,status:"done"}}catch(t){const a=t instanceof Error?t.message:String(t);return{target:n,status:"failed",error:a}}},"run")}),G=l({name:"version",description:"print installed version",whenToUse:"you need the installed crtr version \u2014 to report it in a bug or confirm an upgrade landed.",help:{name:"sys version",summary:"report selected and process runtime generations",params:[],output:[{name:"version",type:"string",required:!0,constraint:"Version from this process generation manifest; package.json version in a development checkout."},{name:"selected_generation",type:"object",required:!0,constraint:"Selected runtime generation: {id, version, status}; id/version are null when no selection exists."},{name:"process_generation",type:"object",required:!0,constraint:"Generation containing this loaded module: {id, version, status}; id/version are null in a development checkout."},{name:"drift",type:"boolean",required:!0,constraint:"True when selected and process generation ids differ."}],outputKind:"object",effects:["None. Read-only."]},run:c(async o=>{const s=c(t=>{if(t.generation===null)return{id:null,version:null,status:t.error??"no runtime generation"};const{id:a,manifest:e}=t.generation,r=v.validateManifestShape(e,{id:a,entryName:"cli"});return{id:a,version:typeof e.packageVersion=="string"?e.packageVersion:null,status:r.ok?"valid":r.error}},"describe"),i=s(w()),n=s(b());return{version:n.version??_(),selected_generation:i,process_generation:n,drift:i.id!==null&&n.id!==null&&i.id!==n.id}},"run")});export{x as sysUpdateLeaf,G as sysVersionLeaf};
1
+ var d=Object.defineProperty;var l=(i,a)=>d(i,"name",{value:a,configurable:!0});import{defineLeaf as u}from"../../core/command.js";import{updateState as p}from"../../core/config.js";import{projectScopeRoot as f}from"../../core/scope.js";import{selfCheck as h,selfUpdate as m,contentCheck as g}from"../../core/self-update.js";import{marketUpdate as y}from"../pkg/market-manage.js";import{pluginUpdate as k}from"../pkg/plugin-manage.js";import{nowIso as b}from"../../core/fs-utils.js";import{processLocatedGeneration as w,readPackageVersion as _,runtimeManifest as v,selectedGeneration as j}from"./shared.js";const E=u({name:"update",description:"update binary and content",whenToUse:"upgrading crtr or its installed plugins and marketplaces \u2014 pull the latest binary, refresh installed content, or both, or just check what is out of date without applying anything.",help:{name:"sys update",summary:"update the crtr binary and/or installed plugins and marketplaces",params:[{kind:"flag",name:"target",type:"enum",choices:["self","content","all"],required:!1,constraint:"What to update. Default: all."},{kind:"flag",name:"check",type:"bool",required:!1,constraint:"Check for updates without applying them (bounded, blocking)."}],output:[{name:"target",type:"string",required:!1,constraint:"Present when applying updates: self | content | all."},{name:"status",type:"string",required:!1,constraint:"done | failed when applying updates."},{name:"error",type:"string",required:!1,constraint:"Failure message when status is failed."},{name:"warning",type:"string",required:!1,constraint:"Present when the update was applied but recording the self-check time failed; status stays done."},{name:"updates",type:"object[]",required:!1,constraint:"Present when --check. Each: {name, current, latest, up_to_date, unreachable, kind}."},{name:"up_to_date",type:"boolean",required:!1,constraint:"Present when --check. True when all items are up to date."}],outputKind:"object",effects:["--check \u2014 read-only, bounded network calls.","Default (no --check) \u2014 launches a background job; returns job handle immediately.","Content update replaces each marketplace and source-installed plugin checkout with a freshly staged revision, discarding local modifications in those directories."]},run:l(async i=>{const a=i.target,c=i.check,t=a!==void 0?a:"all";if(c){const n=[];if(t==="self"||t==="all"){const e=h();e!==null?n.push({name:e.package,kind:"self",current:e.current,latest:e.latest,up_to_date:!e.migrating&&e.current===e.latest,unreachable:!1}):n.push({name:"@north-light/cli",kind:"self",current:null,latest:null,up_to_date:!0,unreachable:!0})}if(t==="content"||t==="all"){const e=g();for(const o of e)n.push({name:o.name,kind:o.kind,current:o.current,latest:o.latest,up_to_date:o.up_to_date,unreachable:o.unreachable})}const r=n.every(e=>e.up_to_date||e.unreachable);return{updates:n,up_to_date:r}}const s=[];try{if(t==="self"||t==="all"){m();const n=["user"];f()&&n.unshift("project");for(const r of n)try{p(r,e=>{e.last_self_check=b()})}catch(e){s.push(`recording the ${r}-scope self-check failed: ${e instanceof Error?e.message:String(e)}`)}}return(t==="content"||t==="all")&&(await y.run({}),await k.run({})),s.length===0?{target:t,status:"done"}:{target:t,status:"done",warning:`update installed, but ${s.join("; ")}`}}catch(n){const r=n instanceof Error?n.message:String(n);return{target:t,status:"failed",error:r}}},"run")}),G=u({name:"version",description:"print installed version",whenToUse:"you need the installed crtr version \u2014 to report it in a bug or confirm an upgrade landed.",help:{name:"sys version",summary:"report selected and process runtime generations",params:[],output:[{name:"version",type:"string",required:!0,constraint:"Version from this process generation manifest; package.json version in a development checkout."},{name:"selected_generation",type:"object",required:!0,constraint:"Selected runtime generation: {id, version, status}; id/version are null when no selection exists."},{name:"process_generation",type:"object",required:!0,constraint:"Generation containing this loaded module: {id, version, status}; id/version are null in a development checkout."},{name:"drift",type:"boolean",required:!0,constraint:"True when selected and process generation ids differ."}],outputKind:"object",effects:["None. Read-only."]},run:l(async i=>{const a=l(s=>{if(s.generation===null)return{id:null,version:null,status:s.error??"no runtime generation"};const{id:n,manifest:r}=s.generation,e=v.validateManifestShape(r,{id:n,entryName:"cli"});return{id:n,version:typeof r.packageVersion=="string"?r.packageVersion:null,status:e.ok?"valid":e.error}},"describe"),c=a(j()),t=a(w());return{version:t.version??_(),selected_generation:c,process_generation:t,drift:c.id!==null&&t.id!==null&&c.id!==t.id}},"run")});export{E as sysUpdateLeaf,G as sysVersionLeaf};