@north-light/crouter 0.3.236 → 0.3.238

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 (177) hide show
  1. package/dist/api/client.d.ts +2 -1
  2. package/dist/api/client.js +3 -0
  3. package/dist/api/dto/broker-ops.d.ts +1 -1
  4. package/dist/api/dto/common.d.ts +2 -0
  5. package/dist/api/dto/lifecycle.d.ts +9 -2
  6. package/dist/api/dto/messages.d.ts +5 -0
  7. package/dist/api/dto/nodes.d.ts +10 -2
  8. package/dist/api/dto/worktree.d.ts +10 -0
  9. package/dist/api/routes.d.ts +1 -0
  10. package/dist/api/routes.js +1 -0
  11. package/dist/builtin-memory/00-runtime-base/00-authoring.md +1 -1
  12. package/dist/builtin-memory/internal/agent-shaping.md +1 -1
  13. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +1 -1
  14. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +1 -1
  15. package/dist/clients/attach/render/tool-calls.js +18 -3
  16. package/dist/clients/attach/viewer.js +442 -442
  17. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +6 -0
  18. package/dist/clients/inbox/review/roundtrip.js +1 -1
  19. package/dist/commands/memory/lint.js +22 -13
  20. package/dist/commands/memory/shared.js +1 -1
  21. package/dist/commands/node/create.d.ts +1 -1
  22. package/dist/commands/node/create.js +1 -1
  23. package/dist/commands/node/lifecycle.js +1 -1
  24. package/dist/commands/node-worktree.js +39 -8
  25. package/dist/commands/revive.js +11 -2
  26. package/dist/commands/sys/context/admin/actions.d.ts +48 -0
  27. package/dist/commands/sys/context/admin/actions.js +246 -0
  28. package/dist/commands/sys/context/admin/axes-panel.d.ts +21 -0
  29. package/dist/commands/sys/context/admin/axes-panel.js +117 -0
  30. package/dist/commands/sys/context/admin/detail-panel.d.ts +53 -0
  31. package/dist/commands/sys/context/admin/detail-panel.js +178 -0
  32. package/dist/commands/sys/context/admin/docs-panel.d.ts +45 -0
  33. package/dist/commands/sys/context/admin/docs-panel.js +186 -0
  34. package/dist/commands/sys/context/admin/model.d.ts +75 -0
  35. package/dist/commands/sys/context/admin/model.js +209 -0
  36. package/dist/commands/sys/context/admin/shell.d.ts +82 -0
  37. package/dist/commands/sys/context/admin/shell.js +669 -0
  38. package/dist/commands/sys/context/admin.d.ts +1 -0
  39. package/dist/commands/sys/context/admin.js +124 -0
  40. package/dist/commands/sys/context/doc.d.ts +1 -0
  41. package/dist/commands/sys/context/doc.js +196 -0
  42. package/dist/commands/sys/context/prompt-review.d.ts +1 -0
  43. package/dist/commands/sys/{prompt-review.js → context/prompt-review.js} +10 -10
  44. package/dist/commands/sys/context/resolve.d.ts +55 -0
  45. package/dist/commands/sys/context/resolve.js +428 -0
  46. package/dist/commands/sys/context/sysprompt.d.ts +1 -0
  47. package/dist/commands/sys/{sysprompt.js → context/sysprompt.js} +11 -11
  48. package/dist/commands/sys/context.d.ts +2 -0
  49. package/dist/commands/sys/context.js +20 -0
  50. package/dist/commands/sys.js +3 -4
  51. package/dist/core/__tests__/child-death-wake.test.js +38 -22
  52. package/dist/core/__tests__/cron-self-cancel-delivery.test.js +72 -0
  53. package/dist/core/__tests__/daemon-boot.test.js +40 -28
  54. package/dist/core/__tests__/human-deliver.test.js +1 -1
  55. package/dist/core/__tests__/human-node-not-supervised.test.js +10 -15
  56. package/dist/core/__tests__/integration/revive.test.js +12 -12
  57. package/dist/core/__tests__/integration/spawn-root.test.js +6 -0
  58. package/dist/core/__tests__/integration/worktree-reap.test.js +32 -0
  59. package/dist/core/__tests__/lifecycle-terminal-reasons.test.d.ts +1 -0
  60. package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +61 -0
  61. package/dist/core/__tests__/migration.test.js +38 -1
  62. package/dist/core/__tests__/push-final-guard.test.js +1 -1
  63. package/dist/core/__tests__/revive-capacity.test.d.ts +1 -0
  64. package/dist/core/__tests__/revive-capacity.test.js +127 -0
  65. package/dist/core/__tests__/revive-parked-fresh.test.js +7 -7
  66. package/dist/core/__tests__/seam/broker-cap-freeze.test.d.ts +1 -0
  67. package/dist/core/__tests__/seam/broker-cap-freeze.test.js +81 -0
  68. package/dist/core/__tests__/seam/dormancy-release.test.js +7 -7
  69. package/dist/core/__tests__/seam/yield-refresh-transaction.test.js +1 -1
  70. package/dist/core/canvas/browse/render.js +11 -3
  71. package/dist/core/canvas/canvas.d.ts +15 -3
  72. package/dist/core/canvas/canvas.js +52 -16
  73. package/dist/core/canvas/migrations.js +21 -0
  74. package/dist/core/canvas/nav-render.js +3 -1
  75. package/dist/core/canvas/remote-canvas-source.js +2 -0
  76. package/dist/core/canvas/render-source.d.ts +3 -1
  77. package/dist/core/canvas/render-source.js +7 -3
  78. package/dist/core/canvas/status-glyph.d.ts +10 -1
  79. package/dist/core/canvas/status-glyph.js +19 -3
  80. package/dist/core/canvas/types.d.ts +20 -1
  81. package/dist/core/feed/feed.js +1 -1
  82. package/dist/core/human/feedback-companion.js +5 -2
  83. package/dist/core/keybindings/catalog.d.ts +1 -1
  84. package/dist/core/keybindings/catalog.js +6 -2
  85. package/dist/core/memory/lint.d.ts +19 -0
  86. package/dist/core/memory/lint.js +97 -0
  87. package/dist/core/memory-resolver.d.ts +4 -0
  88. package/dist/core/memory-resolver.js +7 -7
  89. package/dist/core/preview-registry.js +4 -4
  90. package/dist/core/review/realize.js +4 -2
  91. package/dist/core/runtime/close.js +1 -1
  92. package/dist/core/runtime/fleet.d.ts +29 -1
  93. package/dist/core/runtime/fleet.js +23 -0
  94. package/dist/core/runtime/host.js +32 -11
  95. package/dist/core/runtime/launch-prompt.d.ts +1 -1
  96. package/dist/core/runtime/launch-prompt.js +2 -2
  97. package/dist/core/runtime/lifecycle.d.ts +4 -2
  98. package/dist/core/runtime/lifecycle.js +12 -1
  99. package/dist/core/runtime/memory.js +1 -1
  100. package/dist/core/runtime/reopen.js +10 -1
  101. package/dist/core/runtime/reset.js +1 -1
  102. package/dist/core/runtime/revive-all.d.ts +3 -0
  103. package/dist/core/runtime/revive-all.js +10 -4
  104. package/dist/core/runtime/revive.d.ts +12 -0
  105. package/dist/core/runtime/revive.js +62 -3
  106. package/dist/core/runtime/spawn.d.ts +4 -0
  107. package/dist/core/runtime/spawn.js +36 -7
  108. package/dist/core/runtime/tmux-bindings.js +4 -0
  109. package/dist/core/substrate/frontmatter-validation.js +1 -1
  110. package/dist/core/substrate/index.d.ts +6 -3
  111. package/dist/core/substrate/index.js +4 -3
  112. package/dist/core/substrate/on-read.d.ts +0 -8
  113. package/dist/core/substrate/on-read.js +45 -124
  114. package/dist/core/substrate/plan.d.ts +94 -0
  115. package/dist/core/substrate/plan.js +266 -0
  116. package/dist/core/substrate/render.d.ts +5 -6
  117. package/dist/core/substrate/render.js +76 -129
  118. package/dist/core/substrate/schema.d.ts +1 -6
  119. package/dist/core/substrate/schema.js +1 -15
  120. package/dist/core/substrate/session-cache.d.ts +2 -10
  121. package/dist/core/substrate/session-cache.js +9 -47
  122. package/dist/core/substrate/subject-fields.d.ts +1 -4
  123. package/dist/core/substrate/subject-fields.js +2 -5
  124. package/dist/core/substrate/surface-match.d.ts +37 -17
  125. package/dist/core/substrate/surface-match.js +44 -53
  126. package/dist/core/tui/page-host.d.ts +6 -0
  127. package/dist/core/tui/page-host.js +12 -3
  128. package/dist/core/worktree.d.ts +8 -0
  129. package/dist/core/worktree.js +65 -0
  130. package/dist/daemon/__tests__/reconciler-signature.test.js +3 -2
  131. package/dist/daemon/__tests__/thaw-order.test.d.ts +1 -0
  132. package/dist/daemon/__tests__/thaw-order.test.js +55 -0
  133. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +6 -0
  134. package/dist/daemon/api/__tests__/node-create-description.test.js +6 -0
  135. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +1 -1
  136. package/dist/daemon/api/bridge.js +5 -1
  137. package/dist/daemon/api/handlers/attach.js +5 -1
  138. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  139. package/dist/daemon/api/handlers/messages.js +10 -2
  140. package/dist/daemon/api/handlers/nodes.js +8 -1
  141. package/dist/daemon/api/handlers/worktree.js +10 -1
  142. package/dist/daemon/api/map.js +7 -0
  143. package/dist/daemon/companion-retire.js +1 -1
  144. package/dist/daemon/cron/passes.d.ts +0 -5
  145. package/dist/daemon/cron/passes.js +0 -20
  146. package/dist/daemon/cron/sinks.js +1 -1
  147. package/dist/daemon/cron-run.d.ts +5 -6
  148. package/dist/daemon/cron-run.js +7 -16
  149. package/dist/daemon/crtrd.d.ts +0 -10
  150. package/dist/daemon/crtrd.js +23 -61
  151. package/dist/daemon/fleet.d.ts +10 -7
  152. package/dist/daemon/fleet.js +71 -12
  153. package/dist/daemon/messaging/node-message.js +3 -1
  154. package/dist/daemon/profile-delete.js +1 -1
  155. package/dist/daemon/reconcilers/broker-supervision.d.ts +26 -9
  156. package/dist/daemon/reconcilers/broker-supervision.js +39 -52
  157. package/dist/daemon/reconcilers/controller-death.d.ts +7 -0
  158. package/dist/daemon/reconcilers/controller-death.js +26 -0
  159. package/dist/daemon/reconcilers/cron-lane.d.ts +0 -3
  160. package/dist/daemon/reconcilers/cron-lane.js +0 -3
  161. package/dist/daemon/reconcilers/live-obligation.js +3 -1
  162. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +53 -0
  163. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +170 -0
  164. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +5 -0
  165. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +16 -0
  166. package/dist/daemon/reconcilers/node-lifecycle/terminating.d.ts +4 -0
  167. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +13 -0
  168. package/dist/daemon/reconcilers/node-lifecycle/tick.d.ts +26 -0
  169. package/dist/daemon/reconcilers/node-lifecycle/tick.js +140 -0
  170. package/package.json +1 -1
  171. package/runtime.lock.json +2 -2
  172. package/dist/commands/sys/prompt-review.d.ts +0 -1
  173. package/dist/commands/sys/sysprompt.d.ts +0 -1
  174. package/dist/core/__tests__/cron-broker-capacity.test.js +0 -119
  175. package/dist/daemon/reconcilers/dormant-inbox.d.ts +0 -18
  176. package/dist/daemon/reconcilers/dormant-inbox.js +0 -157
  177. /package/dist/core/__tests__/{cron-broker-capacity.test.d.ts → cron-self-cancel-delivery.test.d.ts} +0 -0
@@ -20,7 +20,7 @@ import type { CreateReviewCommentRequest, EditReviewCommentRequest, ListReviewCo
20
20
  import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, InboxPageDTO, InboxPageHistoryDTO, InboxPageResponseDTO, InboxTicketIdDTO, PageFeedbackResolutionDTO, PageResponsesDTO, PageTicketResultDTO, RespondInboxPageRequest } from './dto/inbox.js';
21
21
  import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js';
22
22
  import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, PruneRequest, PruneResultDTO, RebuildIndexResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js';
23
- import type { CloseWorktreeResultDTO } from './dto/worktree.js';
23
+ import type { AbandonWorktreeRequest, AbandonWorktreeResultDTO, CloseWorktreeResultDTO } from './dto/worktree.js';
24
24
  import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
25
25
  export interface CrtrClientOptions {
26
26
  /** Unix socket path (default local transport). Exactly one of socketPath|baseUrl. */
@@ -113,6 +113,7 @@ export declare class CrtrClient {
113
113
  * because it interleaves a canvas WRITE with a git land transaction and
114
114
  * crtrd is the repo host (same principle as spawnChild's creation git). */
115
115
  closeWorktree(id: string): Promise<CloseWorktreeResultDTO>;
116
+ abandonWorktree(id: string, req: AbandonWorktreeRequest): Promise<AbandonWorktreeResultDTO>;
116
117
  subscribe(id: string, req: SubscribeRequest): Promise<SubscriptionDTO>;
117
118
  listFocuses(): Promise<FocusDTO[]>;
118
119
  focusOf(nodeId: string): Promise<FocusDTO | null>;
@@ -176,6 +176,9 @@ export class CrtrClient {
176
176
  closeWorktree(id) {
177
177
  return this.request('POST', routes.nodeWorktreeClose(this.nodePath(id)), {});
178
178
  }
179
+ abandonWorktree(id, req) {
180
+ return this.request('POST', routes.nodeWorktreeAbandon(this.nodePath(id)), req);
181
+ }
179
182
  subscribe(id, req) {
180
183
  return this.request('POST', routes.nodeSubscriptions(this.nodePath(id)), req);
181
184
  }
@@ -75,7 +75,7 @@ export interface BrokerExtensionNodeDTO {
75
75
  fork_from: string | null;
76
76
  profile_id: string | null;
77
77
  managed_worktree?: {
78
- state: 'open' | 'closed';
78
+ state: 'open' | 'closed' | 'abandoned';
79
79
  cleanup?: 'pending' | 'complete';
80
80
  path: string;
81
81
  branch: string;
@@ -19,6 +19,8 @@ export type LifecycleDTO = 'terminal' | 'resident';
19
19
  export type ModeDTO = 'base' | 'orchestrator';
20
20
  /** Why a node last stopped (mirrors the runtime `ExitIntent` union). */
21
21
  export type ExitIntentDTO = 'done' | 'refresh' | 'idle-release' | 'parked' | null;
22
+ /** Why a terminal node ended (mirrors the runtime `TerminalReason` union). */
23
+ export type TerminalReasonDTO = 'finalized' | 'finished' | 'parked' | 'closed' | 'retired' | 'crashed' | 'stranded';
22
24
  /** Inbox urgency tier for a delivered message (mirrors feed/inbox `InboxTier`). */
23
25
  export type InboxTierDTO = 'critical' | 'urgent' | 'normal' | 'deferred';
24
26
  /** Whether a node id is a safe single filesystem path segment. Re-declared here
@@ -21,20 +21,27 @@ export interface ReviveResultDTO {
21
21
  revived: boolean;
22
22
  resumed: boolean;
23
23
  status: NodeStatusDTO;
24
+ /** What the call did: `launched` started a broker, `already-live` found one
25
+ * already running, `frozen` found no free broker slot and left the row
26
+ * waiting for one. */
27
+ outcome: 'launched' | 'already-live' | 'frozen';
24
28
  }
25
29
  /** `POST /v1/nodes/{id}/relaunch-root` result. A null id means the target
26
30
  * was not a relaunchable live root, or its replacement failed to launch. */
27
31
  export interface RelaunchRootResultDTO {
28
32
  newNodeId: NodeIdDTO | null;
29
33
  }
30
- /** `POST /v1/nodes/revive-all` result. Node ids relaunched, plus any that
31
- * failed to revive with the reason (the reader reports both). */
34
+ /** `POST /v1/nodes/revive-all` result. Node ids relaunched, any that failed to
35
+ * revive with the reason, and any the broker cap turned away (the reader
36
+ * reports all three). */
32
37
  export interface ReviveAllResultDTO {
33
38
  revived: NodeIdDTO[];
34
39
  failed: {
35
40
  node_id: NodeIdDTO;
36
41
  error: string;
37
42
  }[];
43
+ /** Frozen for capacity, not failed: the daemon relaunches these as slots free. */
44
+ frozen: NodeIdDTO[];
38
45
  }
39
46
  /** `POST /v1/nodes/{id}/close` body. The cascade set is computed server-side
40
47
  * from edges; the flag only opts out of cascading descendants. */
@@ -57,6 +57,11 @@ export interface MessageResultDTO {
57
57
  delivered: boolean;
58
58
  /** Whether a dormant target was revived to receive the message. */
59
59
  revived: boolean;
60
+ /** Present only when a wake was attempted and did not happen:
61
+ * `capacity_frozen` means no broker slot was free, so the target's row is
62
+ * frozen and the daemon relaunches it when one frees. The entry is durably
63
+ * appended either way, and delivery follows that relaunch. */
64
+ not_revived_reason?: 'capacity_frozen';
60
65
  delivered_at?: IsoTime;
61
66
  /** Which channel a `delivery:'interactive'` send actually used: `'engine'`
62
67
  * (live broker frame loop, no inbox entry) or `'inbox'` (durable fallback).
@@ -1,4 +1,4 @@
1
- import type { Cursor, ExitIntentDTO, IsoTime, LifecycleDTO, ModeDTO, NodeIdDTO, NodeStatusDTO } from './common.js';
1
+ import type { Cursor, ExitIntentDTO, IsoTime, LifecycleDTO, ModeDTO, NodeIdDTO, NodeStatusDTO, TerminalReasonDTO } from './common.js';
2
2
  import type { ReportDTO } from './reports.js';
3
3
  /** `GET /v1/nodes/{id}/subject` — the node-config subject substrate gate
4
4
  * predicates evaluate against. Mirrors `NodeConfigSubject`; this narrow
@@ -76,6 +76,8 @@ export interface NodeSummaryDTO {
76
76
  created: IsoTime;
77
77
  intent: ExitIntentDTO;
78
78
  waiting_for: NodeIdDTO | null;
79
+ frozen_at: IsoTime | null;
80
+ terminal_reason: TerminalReasonDTO | null;
79
81
  pi_pid: number | null;
80
82
  /** Launch-time process identity paired with `pi_pid`, or null when absent. */
81
83
  pi_pid_identity: string | null;
@@ -122,7 +124,7 @@ export interface NodePathsDTO {
122
124
  }
123
125
  /** A node's managed git worktree, if any. */
124
126
  export interface NodeWorktreeDTO {
125
- state: 'open' | 'closed';
127
+ state: 'open' | 'closed' | 'abandoned';
126
128
  /** Pending cleanup must be run manually after the owner exits. */
127
129
  cleanup?: 'pending' | 'complete';
128
130
  path: string;
@@ -132,6 +134,12 @@ export interface NodeWorktreeDTO {
132
134
  base_sha: string;
133
135
  created: IsoTime;
134
136
  closed?: IsoTime;
137
+ abandoned?: {
138
+ branch: string;
139
+ tip_sha: string;
140
+ at: IsoTime;
141
+ by: string;
142
+ };
135
143
  }
136
144
  /** Immutable companion provenance and fork coordinates. Present only on a
137
145
  * daemon-spawned companion node: a `review/companion` node for a human review
@@ -15,3 +15,13 @@ export interface CloseWorktreeResultDTO {
15
15
  branch_deleted: boolean;
16
16
  branch_delete_error?: string;
17
17
  }
18
+ export interface AbandonWorktreeRequest {
19
+ by: string;
20
+ }
21
+ export interface AbandonWorktreeResultDTO {
22
+ node_id: NodeIdDTO;
23
+ branch: string;
24
+ tip_sha: string;
25
+ worktree_path: string;
26
+ branch_deleted: boolean;
27
+ }
@@ -39,6 +39,7 @@ export declare const routes: {
39
39
  readonly nodeWait: (id: string) => string;
40
40
  readonly nodeConfig: (id: string) => string;
41
41
  readonly nodeWorktreeClose: (id: string) => string;
42
+ readonly nodeWorktreeAbandon: (id: string) => string;
42
43
  readonly nodeAttach: (id: string) => string;
43
44
  readonly focuses: () => string;
44
45
  readonly focusByNode: () => string;
@@ -57,6 +57,7 @@ export const routes = {
57
57
  nodeWait: (id) => `${V}/nodes/${id}/wait`,
58
58
  nodeConfig: (id) => `${V}/nodes/${id}/config`,
59
59
  nodeWorktreeClose: (id) => `${V}/nodes/${id}/worktree/close`,
60
+ nodeWorktreeAbandon: (id) => `${V}/nodes/${id}/worktree/abandon`,
60
61
  nodeAttach: (id) => `${V}/nodes/${id}/attach`,
61
62
  // Focuses (viewer registry — the canvas.db `focuses` table)
62
63
  focuses: () => `${V}/focuses`,
@@ -36,4 +36,4 @@ When you have enough information to act, act — do not re-derive facts already
36
36
  Everything you write — replies, reports, approval requests, artifacts, memory docs, comments — describes systems in concrete, existing product terms: the real command, the real event, the actual cause. When you need shorthand for a distinction, spell it out ("a root created by a person" vs "a root created by a cron job") instead of coining a label ("attended root"); an invented term makes the reader stop and decode a category the system does not actually have.
37
37
 
38
38
  ## Mermaid diagrams
39
- When visual structure would land faster than prose, use a Mermaid fence; the user's terminal viewer renders it inline.
39
+ When visual structure would land faster than prose, use a Mermaid fence; it renders inline.
@@ -44,7 +44,7 @@ The discriminators that get missed are **explore vs advisor** (mapping vs judgme
44
44
 
45
45
  ### Sub-kinds
46
46
 
47
- Specialist sub-personas hang off a parent kind. They are not in the top-level `--kind` list but are valid by exact registered path. Use one for a narrowly targeted assignment, not as a mandatory roster; discover the roles available from a kind with `crtr sys prompt-review --list --kind <kind>`. Core and plugins register sub-kinds through the same launch registry.
47
+ Specialist sub-personas hang off a parent kind. They are not in the top-level `--kind` list but are valid by exact registered path. Use one for a narrowly targeted assignment, not as a mandatory roster; discover the roles available from a kind with `crtr sys context prompt-review --list --kind <kind>`. Core and plugins register sub-kinds through the same launch registry.
48
48
 
49
49
  ### Custom personas
50
50
 
@@ -35,7 +35,7 @@ directory's `node_modules/`.
35
35
  | `memory-slash-commands.ts` | Registers every builtin or scope-owned memory marked `slash: true`, including `/spec` and `/plan`. |
36
36
  | `provider-rotation.ts` | Subscription credential rotation across Anthropic / OpenAI-Codex: does its own OAuth login/refresh, rotates on rate-limits, falls back across the model ladder. Registers `/provider-sub <provider> <list\|add\|select\|rm>`. |
37
37
  | `crtr-commands/` | Auto-generates a slash command per `crtr` CLI node. The tree is derived in-process from crtr's own `buildRoot()` (no subprocesses, no cache on disk); `filters.json` controls which nodes are exposed. |
38
- | `sysprompt-window.ts` | Registers `/sysprompt`, which runs `crtr sys sysprompt --window` without injecting the prompt into context. |
38
+ | `sysprompt-window.ts` | Registers `/sysprompt`, which runs `crtr sys context sysprompt --window` without injecting the prompt into context. |
39
39
  | `frontmatter-rules/` | Injects `.pi/rules/*.md` whose `when:` frontmatter matches a read markdown file. `.claude/rules` are migrated into substrate docs with read-glob `surfaces` entries via `crtr sys sync project-guidance`. Needs the `yaml` dep. See the `pi-frontmatter-rules` skill. |
40
40
  | `statusline.ts` | Custom status line. |
41
41
 
@@ -10,7 +10,7 @@ export default function (pi: ExtensionAPI) {
10
10
  description: "Open the calling node's system prompt in a tmux window",
11
11
  handler: async (_args, ctx) => {
12
12
  try {
13
- await exec(CRTR, ["sys", "sysprompt", "--window"]);
13
+ await exec(CRTR, ["sys", "context", "sysprompt", "--window"]);
14
14
  } catch (err: any) {
15
15
  ctx.ui.notify(err instanceof Error ? err.message : String(err), "error");
16
16
  }
@@ -178,6 +178,18 @@ export function createCrtrWriteToolDefinition(cwd, fold = new FoldedToolCallCont
178
178
  // bash (non-crtr commands; `crtr ...` invocations get the command card in
179
179
  // render/crtr-output.ts)
180
180
  const OPERATOR_RE = /^(&&|\|\||\||;|>>|>|<|2>&1|&)$/;
181
+ /** Drop a leading `cd <dir> &&` (or `; `) prefix from a command line. Agents
182
+ * constantly anchor a call to a directory before the command that matters;
183
+ * folded, that prefix is pure noise, so we show only what the line actually
184
+ * does. Applied repeatedly for the rare `cd a && cd b && cmd` chain, and never
185
+ * when the whole line is a bare `cd` (no trailing operator to strip past). */
186
+ const CD_PREFIX_RE = /^cd\s+(?:"[^"]*"|'[^']*'|\S+)\s*(?:&&|;)\s*/;
187
+ function stripCdPrefix(line) {
188
+ let out = line;
189
+ while (CD_PREFIX_RE.test(out))
190
+ out = out.replace(CD_PREFIX_RE, '');
191
+ return out;
192
+ }
181
193
  /** Split a command into shell-ish tokens, keeping quoted spans whole. */
182
194
  function tokenize(line) {
183
195
  return line.match(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+/g) ?? [];
@@ -221,16 +233,18 @@ class BashCallComponent {
221
233
  command = '';
222
234
  purpose;
223
235
  expanded = false;
236
+ folded = false;
224
237
  timeout;
225
238
  theme;
226
239
  /** Nothing is cached across paints (render recomputes from the fields), so
227
240
  * pi's cache-drop hook has nothing to do here. */
228
241
  invalidate() { }
229
- update(theme, command, purpose, expanded, timeout) {
242
+ update(theme, command, purpose, expanded, folded, timeout) {
230
243
  this.theme = theme;
231
244
  this.command = command;
232
245
  this.purpose = purpose;
233
246
  this.expanded = expanded;
247
+ this.folded = folded;
234
248
  this.timeout = timeout;
235
249
  }
236
250
  render(width) {
@@ -241,7 +255,8 @@ class BashCallComponent {
241
255
  if (this.purpose !== undefined) {
242
256
  return [truncateToWidth(`${icon} ${theme.fg('toolOutput', this.purpose)}`, width, '…')];
243
257
  }
244
- const lines = this.command.split('\n').map((line) => line.trim()).filter((line) => line.length > 0);
258
+ const trimmed = this.command.split('\n').map((line) => line.trim()).filter((line) => line.length > 0);
259
+ const lines = this.folded ? trimmed.map(stripCdPrefix) : trimmed;
245
260
  const suffix = this.timeout ? theme.fg('muted', ` (timeout ${this.timeout}s)`) : '';
246
261
  if (lines.length === 0)
247
262
  return [`${icon} ${theme.fg('toolOutput', '...')}`];
@@ -295,7 +310,7 @@ export function createCrtrPlainBashToolDefinition(cwd, fold = new FoldedToolCall
295
310
  // here because it is model-supplied text painted straight into the frame.
296
311
  fold.folded ? normalizeBashJobPurpose(a?.purpose) ?? undefined : undefined,
297
312
  // Folded wins over ctrl+o expansion: a folded bash is always its one-line form.
298
- Boolean(context.expanded) && !fold.folded, typeof a?.timeout === 'number' ? a.timeout : undefined);
313
+ Boolean(context.expanded) && !fold.folded, fold.folded, typeof a?.timeout === 'number' ? a.timeout : undefined);
299
314
  return fold.capture(component);
300
315
  },
301
316
  renderResult(result, options, theme, context) {