@north-light/crouter 0.3.221 → 0.3.222

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 (155) hide show
  1. package/dist/api/client.d.ts +21 -1
  2. package/dist/api/client.js +34 -0
  3. package/dist/api/dto/chat-inventory.d.ts +13 -0
  4. package/dist/api/dto/human-requests.d.ts +88 -0
  5. package/dist/api/dto/human-requests.js +4 -0
  6. package/dist/api/dto/human.d.ts +3 -0
  7. package/dist/api/dto/reviews.d.ts +2 -0
  8. package/dist/api/index.d.ts +1 -0
  9. package/dist/api/index.js +1 -0
  10. package/dist/api/routes.d.ts +7 -0
  11. package/dist/api/routes.js +10 -0
  12. package/dist/builtin-memory/00-runtime-base/00-authoring.md +31 -0
  13. package/dist/builtin-memory/00-runtime-base/01-escalation.md +14 -0
  14. package/dist/builtin-memory/{insights/listen.md → 00-runtime-base/02-insight-capture.md} +1 -0
  15. package/dist/builtin-memory/02-turn-lifecycle/00-ending-a-turn.md +27 -0
  16. package/dist/builtin-memory/{02-lifecycle/01-resident.md → 02-turn-lifecycle/02-resident.md} +5 -0
  17. package/dist/builtin-memory/04-base-worker.md +4 -8
  18. package/dist/builtin-memory/04-orchestration-kernel.md +1 -1
  19. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -0
  20. package/dist/builtin-memory/05-kinds/advisor/advice-contract.md +1 -0
  21. package/dist/builtin-memory/05-kinds/design/00-base.md +2 -1
  22. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +2 -1
  23. package/dist/builtin-memory/05-kinds/design/design-contract.md +19 -0
  24. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -0
  25. package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +1 -0
  26. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -0
  27. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -0
  28. package/dist/builtin-memory/05-kinds/general/00-base.md +1 -0
  29. package/dist/builtin-memory/05-kinds/plan/00-base.md +2 -1
  30. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +2 -1
  31. package/dist/builtin-memory/05-kinds/plan/plan-contract.md +28 -0
  32. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -0
  33. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -0
  34. package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +1 -0
  35. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -0
  36. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -0
  37. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -0
  38. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -0
  39. package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -0
  40. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +1 -0
  41. package/dist/builtin-memory/05-kinds/review/security-findings.md +1 -0
  42. package/dist/builtin-memory/05-kinds/spec/00-base.md +4 -3
  43. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -0
  44. package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -0
  45. package/dist/builtin-memory/design/guide.md +35 -0
  46. package/dist/builtin-memory/design/roadmap.md +21 -0
  47. package/dist/builtin-memory/insights/capture.md +1 -1
  48. package/dist/builtin-memory/internal/plugins.md +10 -1
  49. package/dist/builtin-memory/internal/storage-tiers.md +1 -1
  50. package/dist/builtin-memory/plan/roadmap.md +6 -28
  51. package/dist/builtin-memory/spec/guide.md +19 -8
  52. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +28 -15
  53. package/dist/clients/attach/render/markdown-source.js +106 -1
  54. package/dist/clients/attach/session/file-links.d.ts +13 -4
  55. package/dist/clients/attach/session/file-links.js +54 -58
  56. package/dist/clients/attach/viewer.js +525 -523
  57. package/dist/clients/inbox/controller.js +1 -1
  58. package/dist/clients/inbox/resolve.d.ts +1 -0
  59. package/dist/clients/inbox/review/review-client.js +3 -1
  60. package/dist/commands/__tests__/human.test.js +2 -2
  61. package/dist/commands/human/request.d.ts +2 -0
  62. package/dist/commands/human/request.js +281 -0
  63. package/dist/commands/human.js +5 -2
  64. package/dist/commands/sys/config.js +2 -2
  65. package/dist/commands/sys/doctor.js +54 -2
  66. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +7 -4
  67. package/dist/core/__tests__/fixtures/memory-slash-live-probe.d.ts +1 -0
  68. package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +71 -0
  69. package/dist/core/__tests__/human-action-delivery.test.d.ts +1 -0
  70. package/dist/core/__tests__/human-action-delivery.test.js +140 -0
  71. package/dist/core/__tests__/human-actions.test.d.ts +1 -0
  72. package/dist/core/__tests__/human-actions.test.js +116 -0
  73. package/dist/core/__tests__/inline-memory-refs.test.js +1 -1
  74. package/dist/core/__tests__/profile-project-memory-delivery.test.js +1 -1
  75. package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +1 -0
  76. package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +91 -0
  77. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +1 -0
  78. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +127 -0
  79. package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +1 -0
  80. package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +31 -0
  81. package/dist/core/canvas/db.js +23 -0
  82. package/dist/core/canvas/human-deliveries.d.ts +53 -0
  83. package/dist/core/canvas/human-deliveries.js +75 -0
  84. package/dist/core/config.d.ts +13 -1
  85. package/dist/core/config.js +51 -1
  86. package/dist/core/feed/inbox.d.ts +6 -0
  87. package/dist/core/feed/inbox.js +9 -1
  88. package/dist/core/human/action-binding.d.ts +21 -0
  89. package/dist/core/human/action-binding.js +40 -0
  90. package/dist/core/human/completion.d.ts +38 -0
  91. package/dist/core/human/completion.js +27 -0
  92. package/dist/core/human/convention.d.ts +2 -0
  93. package/dist/core/human/convention.js +2 -0
  94. package/dist/core/human/tickets.d.ts +25 -6
  95. package/dist/core/human/tickets.js +19 -13
  96. package/dist/core/human/types.d.ts +5 -0
  97. package/dist/core/human-actions.d.ts +25 -0
  98. package/dist/core/human-actions.js +101 -0
  99. package/dist/core/memory-resolver.js +1 -1
  100. package/dist/core/profiles/select.d.ts +2 -0
  101. package/dist/core/profiles/select.js +21 -4
  102. package/dist/core/runtime/broker/frame-dispatch.js +2 -5
  103. package/dist/core/runtime/broker-inventory.d.ts +1 -2
  104. package/dist/core/runtime/broker-inventory.js +2 -77
  105. package/dist/core/runtime/broker-persona-guidance.js +1 -1
  106. package/dist/core/runtime/broker.js +4 -4
  107. package/dist/core/runtime/chat-inventory-rows.d.ts +8 -0
  108. package/dist/core/runtime/chat-inventory-rows.js +105 -0
  109. package/dist/core/runtime/command-surface.d.ts +8 -3
  110. package/dist/core/runtime/command-surface.js +42 -6
  111. package/dist/core/runtime/launch-target.d.ts +25 -0
  112. package/dist/core/runtime/launch-target.js +54 -0
  113. package/dist/core/runtime/persona.js +3 -3
  114. package/dist/core/runtime/prospective-inventory-cli.d.ts +1 -0
  115. package/dist/core/runtime/prospective-inventory-cli.js +61 -0
  116. package/dist/core/runtime/prospective-inventory.d.ts +10 -0
  117. package/dist/core/runtime/prospective-inventory.js +88 -0
  118. package/dist/core/runtime/spawn.d.ts +3 -1
  119. package/dist/core/runtime/spawn.js +5 -3
  120. package/dist/core/substrate/on-read.js +17 -28
  121. package/dist/core/substrate/render-node.d.ts +3 -2
  122. package/dist/core/substrate/render-node.js +3 -2
  123. package/dist/core/substrate/render.js +51 -19
  124. package/dist/core/substrate/schema.d.ts +5 -1
  125. package/dist/core/substrate/schema.js +4 -4
  126. package/dist/core/user-settings.d.ts +4 -0
  127. package/dist/core/user-settings.js +1 -0
  128. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +52 -3
  129. package/dist/daemon/api/handlers/human-requests.d.ts +2 -0
  130. package/dist/daemon/api/handlers/human-requests.js +409 -0
  131. package/dist/daemon/api/handlers/human.js +3 -0
  132. package/dist/daemon/api/handlers/inbox.js +3 -0
  133. package/dist/daemon/api/handlers/nodes.d.ts +1 -3
  134. package/dist/daemon/api/handlers/nodes.js +11 -46
  135. package/dist/daemon/api/handlers/prospective-chat-inventory.d.ts +2 -0
  136. package/dist/daemon/api/handlers/prospective-chat-inventory.js +59 -0
  137. package/dist/daemon/api/handlers/reviews.js +10 -2
  138. package/dist/daemon/api/server.js +4 -0
  139. package/dist/daemon/crtrd.js +6 -0
  140. package/dist/daemon/human/deliver-action.d.ts +16 -0
  141. package/dist/daemon/human/deliver-action.js +168 -0
  142. package/dist/daemon/human/finish.d.ts +8 -5
  143. package/dist/daemon/human/finish.js +45 -6
  144. package/dist/daemon/human/sweep.js +4 -1
  145. package/dist/daemon/reconcilers/human-delivery-lane.d.ts +10 -0
  146. package/dist/daemon/reconcilers/human-delivery-lane.js +41 -0
  147. package/dist/daemon/review/finish.d.ts +8 -3
  148. package/dist/daemon/review/finish.js +19 -1
  149. package/dist/types.d.ts +8 -0
  150. package/dist/types.js +1 -0
  151. package/package.json +1 -1
  152. package/runtime.lock.json +2 -2
  153. package/dist/builtin-memory/00-runtime-base.md +0 -55
  154. package/dist/builtin-memory/design.md +0 -55
  155. /package/dist/builtin-memory/{02-lifecycle/00-terminal.md → 02-turn-lifecycle/01-terminal.md} +0 -0
@@ -12,12 +12,13 @@ import type { AttachEnsureRequest, AttachEnsureResultDTO } from './dto/attach.js
12
12
  import type { DeleteProfileRequest, DeleteProfileResultDTO, EnsureProfileRequest, ProfileDTO } from './dto/profiles.js';
13
13
  import type { FilePeekDTO } from './dto/files.js';
14
14
  import type { MemoryDocRefDTO } from './dto/memory.js';
15
- import type { ChatInventoryDTO } from './dto/chat-inventory.js';
15
+ import type { ChatInventoryDTO, ProspectiveChatInventoryDTO, ProspectiveChatInventoryQuery } from './dto/chat-inventory.js';
16
16
  import type { CredentialRemovalResultDTO, CredentialResultDTO, InstallCredentialRequest, ModelAuthListDTO } from './dto/modelauth.js';
17
17
  import type { CreateHumanBridgeRequest, HumanBridgeResultDTO, HumanCancelRequest, HumanCancelResultDTO, HumanResolveRequest, HumanResolveResultDTO } from './dto/human.js';
18
18
  import type { CancelReviewRequest, CreateReviewRequest, ListReviewsQuery, ReviewCancelResultDTO, ReviewDocumentBaseDTO, ReviewDTO, ReviewListDTO, ReviewSubmitResultDTO } from './dto/reviews.js';
19
19
  import type { CreateReviewCommentRequest, EditReviewCommentRequest, ListReviewCommentsQuery, ReadReviewCommentEventsQuery, ReviewCommentActionRequest, ReviewCommentDetailDTO, ReviewCommentEventsDTO, ReviewCommentListDTO, ReviewCommentMutationDTO, ReviewCommentRangeBatchRequest, ReviewCommentRangeBatchResultDTO } from './dto/review-comments.js';
20
20
  import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, InboxPageDTO, InboxPageHistoryDTO, InboxPageResponseDTO, InboxTicketIdDTO, PageFeedbackResolutionDTO, PageResponsesDTO, PageTicketResultDTO, RespondInboxPageRequest } from './dto/inbox.js';
21
+ import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js';
21
22
  import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, PruneRequest, PruneResultDTO, RebuildIndexResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js';
22
23
  import type { CloseWorktreeResultDTO } from './dto/worktree.js';
23
24
  import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
@@ -157,6 +158,7 @@ export declare class CrtrClient {
157
158
  * inline `/name` token resolves to. Never revives — a node whose broker is
158
159
  * not live answers `broker_live: false` with empty arrays. */
159
160
  getChatInventory(id: string): Promise<ChatInventoryDTO>;
161
+ getProspectiveChatInventory(q?: ProspectiveChatInventoryQuery): Promise<ProspectiveChatInventoryDTO>;
160
162
  getArtifacts(id: string, q?: ArtifactsQuery): Promise<ArtifactListDTO>;
161
163
  getContext(id: string): Promise<ContextListDTO>;
162
164
  /** Read an absolute host path as UTF-8 (capped, `truncated` when clipped) for
@@ -220,6 +222,24 @@ export declare class CrtrClient {
220
222
  getInboxResponse(ticketId: InboxTicketIdDTO): Promise<InboxPageResponseDTO>;
221
223
  /** Cancel a ticket (terminal response, never deletion). */
222
224
  cancelHumanInboxTicket(ticketId: InboxTicketIdDTO, request?: CancelInboxTicketRequest): Promise<CanceledTicketResultDTO>;
225
+ /** Create one durable human request. Its `request_id` is the same opaque id
226
+ * the inbox routes address, so the request and the inbox ticket are one
227
+ * record. An unresolvable `action.name` is rejected before the page is
228
+ * published, leaving no inbox row behind. */
229
+ createHumanRequest(request: CreateHumanRequestRequest): Promise<CreateHumanRequestDTO>;
230
+ /** Read one request: its current state, its answer when answered, and the
231
+ * delivery state of its completion action when it bound one. */
232
+ getHumanRequest(requestId: HumanRequestIdDTO): Promise<HumanRequestDTO>;
233
+ /** Revise a pending request's page in place. Identity, provenance, and the
234
+ * frozen action binding are preserved; a settled request refuses. */
235
+ replaceHumanRequest(requestId: HumanRequestIdDTO, request: ReplaceHumanRequestRequest): Promise<HumanRequestDTO>;
236
+ /** Settle a request `answered` programmatically. Races a human answer to the
237
+ * same first-writer-wins result. */
238
+ respondHumanRequest(requestId: HumanRequestIdDTO, request: RespondHumanRequestRequest): Promise<HumanRequestDTO>;
239
+ /** The recipient surface closing a request without answering. */
240
+ dismissHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise<HumanRequestDTO>;
241
+ /** The requester withdrawing its own request. */
242
+ cancelHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise<HumanRequestDTO>;
223
243
  /** Resolve one page feedback comment — the bound companion's report that it
224
244
  * has been dealt with. `nodeId` names the caller; the daemon refuses any
225
245
  * node but the ticket's companion. Terminal for the comment; appends no
@@ -274,6 +274,9 @@ export class CrtrClient {
274
274
  getChatInventory(id) {
275
275
  return this.request('GET', routes.nodeChatInventory(this.nodePath(id)));
276
276
  }
277
+ getProspectiveChatInventory(q) {
278
+ return this.request('GET', withQuery(routes.prospectiveChatInventory(), q));
279
+ }
277
280
  getArtifacts(id, q) {
278
281
  return this.request('GET', withQuery(routes.nodeArtifacts(this.nodePath(id)), q));
279
282
  }
@@ -426,6 +429,37 @@ export class CrtrClient {
426
429
  cancelHumanInboxTicket(ticketId, request) {
427
430
  return this.request('POST', routes.humanInboxCancel(this.ticketId(ticketId)), request ?? {});
428
431
  }
432
+ // ---- Durable programmatic human requests -------------------------------
433
+ /** Create one durable human request. Its `request_id` is the same opaque id
434
+ * the inbox routes address, so the request and the inbox ticket are one
435
+ * record. An unresolvable `action.name` is rejected before the page is
436
+ * published, leaving no inbox row behind. */
437
+ createHumanRequest(request) {
438
+ return this.request('POST', routes.humanRequests(), request);
439
+ }
440
+ /** Read one request: its current state, its answer when answered, and the
441
+ * delivery state of its completion action when it bound one. */
442
+ getHumanRequest(requestId) {
443
+ return this.request('GET', routes.humanRequest(this.ticketId(requestId)));
444
+ }
445
+ /** Revise a pending request's page in place. Identity, provenance, and the
446
+ * frozen action binding are preserved; a settled request refuses. */
447
+ replaceHumanRequest(requestId, request) {
448
+ return this.request('POST', routes.humanRequestReplace(this.ticketId(requestId)), request);
449
+ }
450
+ /** Settle a request `answered` programmatically. Races a human answer to the
451
+ * same first-writer-wins result. */
452
+ respondHumanRequest(requestId, request) {
453
+ return this.request('POST', routes.humanRequestRespond(this.ticketId(requestId)), request);
454
+ }
455
+ /** The recipient surface closing a request without answering. */
456
+ dismissHumanRequest(requestId, request = {}) {
457
+ return this.request('POST', routes.humanRequestDismiss(this.ticketId(requestId)), request);
458
+ }
459
+ /** The requester withdrawing its own request. */
460
+ cancelHumanRequest(requestId, request = {}) {
461
+ return this.request('POST', routes.humanRequestCancel(this.ticketId(requestId)), request);
462
+ }
429
463
  /** Resolve one page feedback comment — the bound companion's report that it
430
464
  * has been dealt with. `nodeId` names the caller; the daemon refuses any
431
465
  * node but the ticket's companion. Terminal for the comment; appends no
@@ -41,3 +41,16 @@ export interface ChatInventoryDTO {
41
41
  commands: ChatInventoryCommandDTO[];
42
42
  memory_refs: ChatInventoryMemoryRefDTO[];
43
43
  }
44
+ /** Session-less inventory for the launch target a create would resolve. */
45
+ export interface ProspectiveChatInventoryDTO {
46
+ profile_id: string | null;
47
+ cwd: string;
48
+ commands: ChatInventoryCommandDTO[];
49
+ memory_refs: ChatInventoryMemoryRefDTO[];
50
+ }
51
+ export interface ProspectiveChatInventoryQuery {
52
+ profile?: string;
53
+ cwd?: string;
54
+ /** Same optional kind operand as POST /v1/nodes. */
55
+ kind?: string;
56
+ }
@@ -0,0 +1,88 @@
1
+ import type { IsoTime } from './common.js';
2
+ import type { InboxTicketIdDTO, PageResponsesDTO, TicketSourceDTO } from './inbox.js';
3
+ /** A request id IS an opaque inbox ticket id: lowercase 64-hex. */
4
+ export type HumanRequestIdDTO = InboxTicketIdDTO;
5
+ /** The complete authored page text, inline — never a path. */
6
+ export interface HumanRequestPageDTO {
7
+ dialect: 'jsx' | 'html';
8
+ source: string;
9
+ }
10
+ export interface HumanRequestDeliveryDTO {
11
+ placement: 'inline' | 'panel';
12
+ inbox: boolean;
13
+ reply: boolean;
14
+ }
15
+ /** Frozen at creation: the action name and its opaque payload. An omitted
16
+ * `payload` is frozen as JSON null, so the completion document always carries it. */
17
+ export interface HumanRequestActionDTO {
18
+ name: string;
19
+ payload?: unknown;
20
+ }
21
+ export interface CreateHumanRequestRequest {
22
+ page: HumanRequestPageDTO;
23
+ delivery?: HumanRequestDeliveryDTO;
24
+ source?: TicketSourceDTO;
25
+ creator_cwd: string;
26
+ action?: HumanRequestActionDTO;
27
+ }
28
+ export type HumanRequestState = 'pending' | 'answered' | 'dismissed' | 'canceled';
29
+ export type HumanRequestDeliveryState = 'none' | 'pending' | 'running' | 'accepted' | 'permanent_failed';
30
+ export interface CreateHumanRequestDTO {
31
+ request_id: HumanRequestIdDTO;
32
+ state: 'pending';
33
+ /** Omitted entirely when the request carries no action binding. */
34
+ action?: {
35
+ name: string;
36
+ };
37
+ delivery_state: HumanRequestDeliveryState;
38
+ }
39
+ export interface HumanRequestDeliveryFailureDTO {
40
+ kind: 'exit' | 'signal' | 'timeout' | 'spawn_error';
41
+ exit_code?: number;
42
+ signal?: string;
43
+ message?: string;
44
+ /** A bounded tail, not full output. */
45
+ stderr?: string;
46
+ }
47
+ export interface HumanRequestDeliveryDetailDTO {
48
+ state: HumanRequestDeliveryState;
49
+ /** Attempts started. */
50
+ attempt: number;
51
+ /** Present only while pending after a retryable failure. */
52
+ next_attempt_at?: IsoTime;
53
+ accepted_at?: IsoTime;
54
+ permanent_failed_at?: IsoTime;
55
+ last_failure?: HumanRequestDeliveryFailureDTO;
56
+ }
57
+ export interface HumanRequestDTO {
58
+ request_id: HumanRequestIdDTO;
59
+ state: HumanRequestState;
60
+ title: string;
61
+ subtitle?: string;
62
+ source: TicketSourceDTO;
63
+ emitted_at: IsoTime;
64
+ /** Present unless pending. */
65
+ settled_at?: IsoTime;
66
+ /** Present only when `state` is `answered`. */
67
+ responses?: PageResponsesDTO;
68
+ reason?: string;
69
+ actor?: string;
70
+ /** `action` and `delivery` are both omitted when no action is bound. */
71
+ action?: {
72
+ name: string;
73
+ payload: unknown;
74
+ };
75
+ delivery?: HumanRequestDeliveryDetailDTO;
76
+ }
77
+ export interface ReplaceHumanRequestRequest {
78
+ page: HumanRequestPageDTO;
79
+ delivery?: HumanRequestDeliveryDTO;
80
+ }
81
+ export interface RespondHumanRequestRequest {
82
+ responses: PageResponsesDTO;
83
+ actor?: string;
84
+ }
85
+ export interface SettleHumanRequestRequest {
86
+ reason?: string;
87
+ actor?: string;
88
+ }
@@ -0,0 +1,4 @@
1
+ // Durable programmatic human-request DTOs — crtrd `/v1/human/requests`. The
2
+ // envelope is snake_case; nested page-protocol objects keep their canonical
3
+ // camelCase names, matching the inbox DTOs.
4
+ export {};
@@ -44,6 +44,9 @@ export interface HumanResolveRequest {
44
44
  export interface HumanCancelRequest {
45
45
  reason?: string;
46
46
  actor?: string;
47
+ /** The recipient surface closing it sends `dismissed`; a requester retracting
48
+ * it sends `canceled` or omits the field. */
49
+ disposition?: 'canceled' | 'dismissed';
47
50
  }
48
51
  /** `POST /v1/human/tickets/{ticket_id}/resolve` result. */
49
52
  export interface HumanResolveResultDTO {
@@ -93,6 +93,8 @@ export interface ReviewCancelResultDTO {
93
93
  export interface CancelReviewRequest {
94
94
  reason?: string;
95
95
  actor?: string;
96
+ /** Recipient surfaces send `dismissed`; a requester withdrawal defaults to `canceled`. */
97
+ disposition?: 'canceled' | 'dismissed';
96
98
  }
97
99
  /** Daemon-derived coordinate base for the terminal review surface. */
98
100
  export interface ReviewDocumentBaseDTO {
@@ -25,6 +25,7 @@ export * from './dto/human.js';
25
25
  export * from './dto/files.js';
26
26
  export * from './dto/memory.js';
27
27
  export * from './dto/inbox.js';
28
+ export * from './dto/human-requests.js';
28
29
  export * from './dto/reviews.js';
29
30
  export * from './dto/review-comments.js';
30
31
  export * from './dto/chat-inventory.js';
package/dist/api/index.js CHANGED
@@ -26,6 +26,7 @@ export * from './dto/human.js';
26
26
  export * from './dto/files.js';
27
27
  export * from './dto/memory.js';
28
28
  export * from './dto/inbox.js';
29
+ export * from './dto/human-requests.js';
29
30
  export * from './dto/reviews.js';
30
31
  export * from './dto/review-comments.js';
31
32
  export * from './dto/chat-inventory.js';
@@ -12,6 +12,7 @@ export declare const routes: {
12
12
  readonly nodeSubject: (id: string) => string;
13
13
  readonly nodeSession: (id: string) => string;
14
14
  readonly nodeChatInventory: (id: string) => string;
15
+ readonly prospectiveChatInventory: () => string;
15
16
  readonly nodeTranscript: (id: string) => string;
16
17
  readonly nodeContext: (id: string) => string;
17
18
  readonly nodeArtifacts: (id: string) => string;
@@ -84,6 +85,12 @@ export declare const routes: {
84
85
  readonly humanInboxResponse: (ticketId: string) => string;
85
86
  readonly humanInboxCancel: (ticketId: string) => string;
86
87
  readonly humanInboxFeedbackResolve: (ticketId: string, commentId: string) => string;
88
+ readonly humanRequests: () => string;
89
+ readonly humanRequest: (requestId: string) => string;
90
+ readonly humanRequestReplace: (requestId: string) => string;
91
+ readonly humanRequestRespond: (requestId: string) => string;
92
+ readonly humanRequestDismiss: (requestId: string) => string;
93
+ readonly humanRequestCancel: (requestId: string) => string;
87
94
  readonly profiles: () => string;
88
95
  readonly profile: (name: string) => string;
89
96
  readonly modelAuths: () => string;
@@ -28,6 +28,7 @@ export const routes = {
28
28
  nodeSubject: (id) => `${V}/nodes/${id}/subject`,
29
29
  nodeSession: (id) => `${V}/nodes/${id}/session`,
30
30
  nodeChatInventory: (id) => `${V}/nodes/${id}/chat-inventory`,
31
+ prospectiveChatInventory: () => `${V}/prospective-chat-inventory`,
31
32
  nodeTranscript: (id) => `${V}/nodes/${id}/transcript`,
32
33
  nodeContext: (id) => `${V}/nodes/${id}/context`,
33
34
  nodeArtifacts: (id) => `${V}/nodes/${id}/artifacts`,
@@ -111,6 +112,15 @@ export const routes = {
111
112
  humanInboxResponse: (ticketId) => `${V}/human/inbox/${ticketId}/response`,
112
113
  humanInboxCancel: (ticketId) => `${V}/human/inbox/${ticketId}/cancel`,
113
114
  humanInboxFeedbackResolve: (ticketId, commentId) => `${V}/human/inbox/${ticketId}/feedback-comments/${commentId}/resolve`,
115
+ // Durable programmatic human requests. `request_id` is the same opaque
116
+ // inbox ticket id the `/v1/human/inbox` routes address, so one request is one
117
+ // record across both surfaces.
118
+ humanRequests: () => `${V}/human/requests`,
119
+ humanRequest: (requestId) => `${V}/human/requests/${requestId}`,
120
+ humanRequestReplace: (requestId) => `${V}/human/requests/${requestId}/replace`,
121
+ humanRequestRespond: (requestId) => `${V}/human/requests/${requestId}/respond`,
122
+ humanRequestDismiss: (requestId) => `${V}/human/requests/${requestId}/dismiss`,
123
+ humanRequestCancel: (requestId) => `${V}/human/requests/${requestId}/cancel`,
114
124
  // Profiles (deletion is daemon-owned because it crosses canvas state)
115
125
  profiles: () => `${V}/profiles`,
116
126
  profile: (name) => `${V}/profiles/${name}`,
@@ -0,0 +1,31 @@
1
+ ---
2
+ kind: preference
3
+ when-and-why-to-read: When a node writes an artifact, report, or decision for another reader, this preference should be read because current, concrete records let the next action proceed without reconstructing stale context or invented terminology.
4
+ rationale: >-
5
+ The living-document paragraph ("Living documents") exists because agents default to appending — plans kept old+new versions side by side, answered Q&A sections stayed behind after the answer was folded in, findings docs grew contradicted layers (observed by Silas, 2026-07-08). The stale trail isn't neutral history; it keeps steering the next reader (the pink-elephant effect), measurably dulling the agent that consumes the doc. Orchestrators already had this discipline in the kernel; base workers, who author most artifacts, had nothing.
6
+
7
+ "Say what actually happens" exists because an approval request called a root a person had created an "attended root" — an invented category with no referent in the product, which forced Silas to halt the decision and ask what the term meant (2026-07-28). Agents coin taxonomies to compress a distinction; the reader pays by decoding a word that names nothing real.
8
+
9
+ The Mermaid line exists because the viewer's inline diagram affordance is otherwise invisible to an agent working from ordinary Markdown defaults.
10
+
11
+ An "Identity" section is deliberately absent, and the artifacts section carries no paths. The bearings message already states the node id, the context dir's absolute path, the `$CRTR_CONTEXT_DIR` env var, the address-by-absolute-path rule, the bare-`context/` trap, and the cwd — so a layer copy was pure duplication. It was also the only per-node text in the whole system-prompt block: the preference render interpolates `$CRTR_NODE_ID`/`$CRTR_CONTEXT_DIR`, which made every node's cached prompt prefix globally unique. Keep node-specific values out of this layer; bearings is where they belong.
12
+ lint-ignore: length
13
+ surfaces:
14
+ - on: boot
15
+ at: content
16
+ ---
17
+
18
+ ## Working in the canvas
19
+ You are a **node** in a live agent graph (the crtr canvas). This section is your operating protocol — it is true for every node regardless of role.
20
+
21
+ ## Artifacts
22
+ An artifact you write to your context dir is shared by pointer: whatever carries it — a report, a reply, an ask — names its absolute path, never the full substance pasted in.
23
+
24
+ ## Living documents
25
+ Every doc you keep — artifact, plan, findings, memory — is a living statement of what is true *now*, never a log of how it got that way. When something changes, rewrite the doc in place as if writing it fresh: fold an answer into the section it settles and delete the question, replace superseded findings, and never leave an old version beside the new one. Superseded text keeps steering whoever reads it — an audit trail in a working doc costs the next reader the very attention the doc exists to save.
26
+
27
+ ## Say what actually happens
28
+ 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.
29
+
30
+ ## Mermaid diagrams
31
+ When visual structure would land faster than prose, use a Mermaid fence; the user's terminal viewer renders it inline.
@@ -0,0 +1,14 @@
1
+ ---
2
+ kind: preference
3
+ when-and-why-to-read: When progress depends on a person deciding, reviewing, or responding, or when a crtr command fails unexpectedly, this preference should be read because the runtime can deliver the needed signal to its actual recipient instead of leaving work stranded in conversation prose.
4
+ rationale: The human inbox and system-feedback commands are delivery paths whose effects are otherwise invisible in ordinary conversation.
5
+ surfaces:
6
+ - on: boot
7
+ at: content
8
+ ---
9
+
10
+ ## When blocked, want feedback, or need the user
11
+ Don't guess at a decision a person should make. Run `crtr human send -h` and put the question to the user through the crouter human inbox, because a question posed as prose in a reply or report pings nobody while an ask lands on their screen and pushes the answer back to your inbox. An ask blocks on a person, so spend them well: resolve what the code, a tool, or a delegate can settle, and engage when intent is genuinely ambiguous, when approaches carry real tradeoffs, when scope or direction changes, when an action is irreversible or high-risk, or when finished work needs sign-off — a whole goal costs a handful of asks, not a stream.
12
+
13
+ ## When crtr itself misbehaves
14
+ A `crtr` command that errors unexpectedly, hangs, churns, double-spawns, or contradicts its own `-h` is a harness bug — don't silently work around it. Run `crtr sys feedback` to report it (`-h` for how), then continue.
@@ -7,4 +7,5 @@ surfaces:
7
7
  at: content
8
8
  ---
9
9
 
10
+ ## When user knowledge should persist
10
11
  When directly received user-supplied or user-validated material may contain a coherent reusable principle, follow [[insights/capture]]. Use an active domain listener's boundary when one matches; otherwise use the higher bar: the episode must justify a permanent reusable principle future agents should be routed to, and a new domain needs that principle as its first approved truth. Do not treat approval of an insight review as a fresh candidate, because user knowledge unavailable from model weights should not disappear with the episode.
@@ -0,0 +1,27 @@
1
+ ---
2
+ kind: preference
3
+ when-and-why-to-read: When a node has no immediate action because it awaits an event, a person, or a fresh context window, this preference should be read because ending the turn through the matching runtime path preserves wakeability without wasting a live window or losing an unanswered decision.
4
+ rationale: >-
5
+ "Waiting is a way to end a turn" lived in its own ungated all-node doc until 2026-07-28. Same gate, same audience, never independently readable — so the split bought no routing and cost a stub cross-reference in runtime-base pointing at a section spliced a few hundred tokens later. It now has its own sort position as the turn-lifecycle preamble; split it again only when a section needs its own sort position, incident rationale, or independent deletion/re-gate decision.
6
+
7
+ Yield applies to every node regardless of mode; promotion does not, because only the mode layers own that boundary — 04-base-worker for when a base node should promote, the kernel for how an orchestrator uses promotion — so restating it in the universal layer duplicated the base-worker text for an audience that includes nodes it does not apply to.
8
+ lint-ignore: length
9
+ surfaces:
10
+ - on: boot
11
+ at: content
12
+ ---
13
+
14
+ ## Waiting is a way to end a turn
15
+
16
+ When your goal is sound but your next step is blocked on something that has not happened yet — a child's report, the user, a CI run, tomorrow morning — you are **waiting**. Waiting is free: you end your turn, hold no window, and burn no compute, and the runtime brings you back the instant the thing you wait on happens.
17
+
18
+ - **Never busy-wait.** Do not hold your window open to re-poll a URL or watch a clock. A wait that costs a live window is a defect — just stop: end your turn and go dormant.
19
+ - **For waits the runtime already knows — a child's report or the reply to your own human page — just stop.** Go dormant; the runtime wakes you when it lands. There is nothing to poll or verify, and a deadline set to "check in" on a delegate is unnecessary — children auto-wake you when they push.
20
+ - **Schedule a wake yourself only when nothing can push to you** — recurring or scheduled standing work, or polling an external the spine can't deliver (CI, a deploy, a clock). Run `crtr cron -h` to schedule the matching bash action, or `crtr node wait deadline -h` when the desired contract is an inbox-versus-deadline race.
21
+
22
+ ## Yield for a fresh window
23
+ When your context is filling but the mandate isn't done, yield: you revive fresh as the same node with the same mandate, carrying a note to your future self.
24
+
25
+ crtr node yield # `crtr node yield -h` — refresh into a clean window, carrying a note forward
26
+
27
+ Never yield carrying an unasked question: put anything you're still wondering for the user through `crtr human send` BEFORE you yield — an in-flight ask survives the refresh, and its answer wakes your fresh window like any child's report.
@@ -7,5 +7,10 @@ surfaces:
7
7
  at: content
8
8
  ---
9
9
 
10
+ ## Communicating with the user
11
+ - Respond to what was actually said—don’t invent questions, concerns, or agreement.
12
+ - Lead with substance—skip praise, validation, and conversational throat-clearing.
13
+ - Use plain, proportionate language—cut clichés, metaphors, faux urgency, and repetition.
14
+
10
15
  ## How you end
11
16
  You are **resident** and interactable: you are never forced to submit a final result. Stopping is legitimate — the runtime keeps live waits wakeable and completes an unattended conversation after nothing remains to wake it. Do **not** `crtr push final` to "finish" (it would close you mid-conversation); you end by yielding or by being closed. End your turn whenever you have nothing in hand — the runtime owns what happens next.
@@ -11,12 +11,8 @@ surfaces:
11
11
  at: content
12
12
  ---
13
13
 
14
- ## You are a hands-on worker
14
+ ## Execution vs promotion
15
+ You are a base-node, which means you primarily handle tasks yourself. If you would benefit from parallelism or are executing a task that requires or would benefit from many large phases, promote yourself (`crtr node promote -h`). Promoting grants you better delegation management tools and guidelines.
15
16
 
16
- Own the task you were given and complete it yourself in this window. Your scarce resource is task completion, not preserving your context for steering.
17
-
18
- Delegate only a genuinely independent subtask that can run in parallel while you continue owning the parent task. Each child gets a bounded outcome distinct from your whole assignment; passing the same task to another base node creates recursion instead of progress.
19
-
20
- One delegation fits that rule before the work even starts: when the task sits in code you cannot yet map — you don't know which files it touches or which constraints hold — spawn an `explore` scout to chart it. A current-state map is a bounded outcome distinct from your assignment, and explore runs on a light model tier, so the `file:line` map it wakes you with spends the scout's cheap window instead of the context you need for the work itself. Skip the scout when you already know the surface or it is small enough to read directly — waiting on one for a two-file change costs more than it saves.
21
-
22
- When the goal will not fit one window but is still yours to build, `crtr node yield` and continue hands-on in a fresh window. Become an orchestrator only when enough independent work can run in parallel that coordinating and integrating children should replace hands-on execution as your primary job; use `crtr node yield --promote` to refresh too, or `crtr node promote` to switch without refreshing.
17
+ ## Exploring
18
+ When the task sits in code you cannot yet map — you don't know which files it touches or which constraints hold — spawn 1–3 `explore` scout nodes to chart it (`crtr node -h`). A current-state map is a bounded outcome distinct from your assignment. Skip the scout when you already know the surface or it is small enough to read directly — waiting on one for a two-file change costs more than it saves.
@@ -5,7 +5,7 @@ gate: {mode: orchestrator}
5
5
  rationale: >-
6
6
  Two observed orchestration failures set this kernel's stopping rules. A sole-writer feature lane produced a 5-deep 1:1 developer/orchestrator chain by repeatedly delegating the whole assignment; separately, the kernel's “idle capacity,” “maximum agents,” and “when in doubt, more rigor” objective helped produce review-only subtrees as large as 87 nodes and five levels deep. Coordination must optimize new evidence toward the goal rather than node count or process length.
7
7
 
8
- Waiting guidance is deliberately absent: 00-runtime-base owns waiting for every node, including the auto-wake on a child's report, so a kernel copy only duplicated it. Likewise the roadmap-curation paragraph leans on runtime-base's "Living documents" for the fold-in/rewrite discipline and keeps only what is roadmap-specific, and memory guidance is absent because the substrate's always-present boot rendering already carries read-before-act, capture, and staleness rules for every node. Promotion guidance is absent because the promote boundary is a base-node decision 04-base-worker owns; here only the sub-orchestrator-child threshold matters, and "Delegating" carries it. User-engagement calibration is absent because runtime-base's "When blocked" section owns it for every node, and the yield-with-unasked-question rule already lives in runtime-base's yield section; the kernel keeps only the stakeholder framing and the roadmap note about pending answers.
8
+ Waiting guidance is deliberately absent: 02-turn-lifecycle/00-ending-a-turn owns waiting for every node, including the auto-wake on a child's report, so a kernel copy only duplicated it. Likewise the roadmap-curation paragraph leans on 00-runtime-base/00-authoring's "Living documents" for the fold-in/rewrite discipline and keeps only what is roadmap-specific, and memory guidance is absent because the substrate's always-present boot rendering already carries read-before-act, capture, and staleness rules for every node. Promotion guidance is absent because the promote boundary is a base-node decision 04-base-worker owns; here only the sub-orchestrator-child threshold matters, and "Delegating" carries it. User-engagement calibration is absent because 00-runtime-base/01-escalation's "When blocked" section owns it for every node, and the yield-with-unasked-question rule already lives in 02-turn-lifecycle/00-ending-a-turn; the kernel keeps only the stakeholder framing and the roadmap note about pending answers.
9
9
  lint-ignore: length
10
10
  surfaces:
11
11
  - on: boot
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When deliberation is warranted
12
13
  Use a council only when the cost of a wrong consequential judgment warrants deliberation; an ordinary second opinion needs one advisor or a few un-orchestrated advisors.
13
14
 
14
15
  Keep first-round opinions blind and independent, then synthesize on evidence quality rather than consensus. Preserve a well-supported minority and name a residual crux instead of manufacturing agreement.
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When advising from evidence
12
13
  Ground advice in evidence. Inspect the code, logs, repro steps, prior reports, or runtime state needed to understand the situation; do not answer from vibes when the facts are available. For debugging, drive toward the smallest credible root cause: reproduce or trace the failure, separate symptoms from causes, and name the file, command, invariant, or design assumption that explains it.
13
14
 
14
15
  Your deliverable is the advice: conclusion first, then the evidence and the recommended next move. If the right next move is an implementation, say exactly what should change or hand it to a developer; do not turn advisory work into a broad refactor unless the task explicitly asks you to apply the fix.
@@ -9,8 +9,9 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When designing a bounded system
12
13
  You are a design agent. Given a bounded design task — a component, subsystem, or interaction surface — you produce one design document an implementer can build from without re-deciding anything you left open. That, not emitting a document, is the bar for done. When a decision turns on judgment the user should own — a performance tradeoff, a data-model shape, which pattern to adopt — work it out with them via `crtr human send` rather than picking the obvious option alone, because the obvious option is usually not the right one.
13
14
 
14
- Read your task for the scope, the constraints, and the interface contracts you must honor. Write the design to `design-<subject>.md` in your context dir, in the standard shape: Context & constraints, Architecture (lead with a diagram, then prose), Components & responsibilities, Interfaces & contracts, Data model, Key flows, Decisions, Open risks. Three things make it a design rather than a description: every decision that closes a real option is captured in Decisions with the alternatives you rejected and why — resolve the choice, never hand the implementer a branch to pick; every interface is concrete enough that both sides can build to it without negotiating; and it stays above implementation — no function bodies, library calls, algorithm walkthroughs, or implementation ordering. If something could be pasted into source, cut it.
15
+ Read your task for the scope, the constraints, and the interface contracts you must honor. Write the design to `design-<subject>.md` in your context dir, in the standard shape: Context & constraints, Architecture (lead with a diagram, then prose), Components & responsibilities, Interfaces & contracts, Data model, Key flows, Decisions, Open risks. Two things make it a design rather than a description: every decision that closes a real option is captured in Decisions with the alternatives you rejected and why — resolve the choice, never hand the implementer a branch to pick; and every interface is concrete enough that both sides can build to it without negotiating.
15
16
 
16
17
  Deliver the design file path plus a tight summary — one sentence per decision, what was chosen and what it closed off. Promote into a design orchestrator only when settled boundaries expose independent design surfaces; tightly coupled architecture stays base across yields so one mind owns its coherence.
@@ -7,8 +7,9 @@ surfaces:
7
7
  at: content
8
8
  ---
9
9
 
10
+ ## Coordinating a design effort
10
11
  You are a **design orchestrator** — you own a design effort whose independent surfaces make parallel design worthwhile, and you deliver one coherent result by delegating each bounded sub-design to a `design` child and integrating what returns into a unified artifact.
11
12
 
12
- Before you shape the roadmap, read `crtr memory read design` for the artifact shape, the top-down vs. bottom-up call, and the decomposition discipline. Your first act after reading it is to define the shared interface contracts between the sub-designs and write them to `design-contracts.md` in your context dir before any child starts — those contracts are the seams that let parallel sub-designs compose instead of collide. Each child gets the overall architecture framing, the contracts doc, and the explicit scope of its piece.
13
+ Before you shape the roadmap, read `crtr memory read design/roadmap` for the decomposition discipline. Your first act after reading it is to define the shared interface contracts between the sub-designs and write them to `design-contracts.md` in your context dir before any child starts — those contracts are the seams that let parallel sub-designs compose instead of collide. Each child gets the overall architecture framing, the contracts doc, and the explicit scope of its piece.
13
14
 
14
15
  Integration is the work, not a formality: read every sub-design, verify each contract is honored on *both* sides, reconcile the inconsistencies that only surface with the whole picture loaded, and synthesize a single document that reads as one voice — not a concatenation of pieces with the decision rationale lost between them. The design is done only when an implementer could build any piece from it without discovering that two pieces disagree.
@@ -0,0 +1,19 @@
1
+ ---
2
+ kind: preference
3
+ when-and-why-to-read: When a node is spawned as kind design, this preference should be read so the design closes the expensive decisions at the right altitude instead of drifting into implementation or over-specifying what the implementer could safely decide.
4
+ gate: {kind: design}
5
+ rationale: >-
6
+ The design personas described how to write the artifact but routed to no design guidance, so a base design node booted with no altitude rule and no bound on over-specification. Gates on the kind with no mode so design orchestrators load it too. Carries the contract only — the artifact shape and the decomposition decision stay in the docs it points at.
7
+ surfaces:
8
+ - on: boot
9
+ at: content
10
+ ---
11
+
12
+ ## What a design must settle
13
+ A design fixes the load-bearing structure before anyone writes code: component boundaries and responsibilities, interface contracts and data models, key flows, and the decisions that close real options with their rationale and rejected alternatives.
14
+
15
+ It is not requirements — those state the behavior the system must satisfy, while the design states how it is structured to produce that behavior. It is not a plan — plans order implementation work against the design. The altitude ceiling: a planner reading the design has no design questions left, and a coder reading it still has implementation choices to make. No function bodies, no algorithm walkthroughs, no library calls, no ordering of implementation steps; anything that could be pasted into source belongs downstream.
16
+
17
+ Design enough to unblock parallelism and close the decisions that are expensive to reverse, and no further. Over-specification is as harmful as under-specification — it creates brittleness and deferred rework when reality does not match the paper — so leave the implementer what they can decide without risk. Name a genuinely unclear sub-section that is off the critical path as open rather than filling it with a plausible guess.
18
+
19
+ Read `crtr memory read design/guide` for what each section of the artifact must contain and the top-down versus bottom-up call.
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When implementing
12
13
  Work directly. Read the relevant files before editing, match the existing code style and module conventions, and keep your delegation shallow — a focused exploration or a review pass is worth handing off, but most of the work is yours. Throw errors early; no silent fallbacks. Break things correctly rather than patching them badly. Compatibility is governed by the approved spec or migration decision.
13
14
 
14
15
  Done means **provably correct against the spec's acceptance criteria** — not "it builds," not "the tests pass." Green output proves the code ran, not that it does what was asked; check the result against each acceptance criterion yourself. On a load-bearing change, get it critiqued by something other than you before calling it done — spawn a reviewer on the diff and fold in what it finds. Every Critical, Major, or acceptance-violating finding is fixed, always — keep the fix net-neutral-or-simpler, never bolt on complexity to patch it. A Minor or cosmetic finding that doesn't affect acceptance is fixed when the fix is net-neutral-or-simpler, or else closed with a one-line reason — closing is a resolution, not a deferral. But validate judiciously: a delegate's green report is settled evidence — don't re-run a suite or re-read a diff that already cleared its gate; check only what changed since. Promote into a developer orchestrator only when the change splits into genuinely independent implementation lanes; a long or tightly coupled build stays base across yields.
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When shaping a software roadmap
12
13
  Before you shape a software roadmap, read `crtr memory read development` for development styles, roadmap shapes, and exit criteria that fit the goal's risk.
13
14
 
14
15
  Treat implementation as complete only when it is **provably correct against the spec's acceptance criteria**, not merely when it compiles.
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## Mapping the factual surface
12
13
  Your work is **read-only evidence gathering** — map what exists, where it lives, how it behaves, and which constraints, gaps, or feasibility limits the source proves.
13
14
 
14
15
  Keep the result descriptive. Root cause and recommendations belong to `advisor`, target architecture to `design`, required behavior and acceptance criteria to `spec`, and implementation decomposition to `plan`. A task cannot expand your role: even when it explicitly asks, **never** produce those decisions. Complete the factual map and identify the matching handoff; read-only does not make decision work exploration.
@@ -9,6 +9,7 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## Coordinating exploration
12
13
  Decompose the factual surface — by subsystem, directory, layer, or sub-question — into areas small enough for one base `explore` scout to map well, and delegate each a sharp, self-contained evidence question. A task cannot expand your role: even when it explicitly asks for diagnosis or a target-state decision, gather only the facts that decision needs and return the unperformed handoff to the matching specialist. Do not assign decision work to a scout or make it during synthesis. Do not create more explore orchestrators beneath you; split an oversized slice yourself. Keep fan-out proportional: start with the few scouts needed to cover the real seams and add follow-ups only for concrete gaps or contradictions.
13
14
 
14
15
  Integrate what they return into one coherent current-state map: the existing architecture, call paths, constraints, gaps, and `file:line` evidence. The map is complete only when every factual sub-question is answered — fill a gap with another scout rather than a guess, and reconcile contradictory evidence with a focused follow-up. Your deliverable is the factual synthesis, not a pile of transcripts or a proposed solution.
@@ -11,4 +11,5 @@ surfaces:
11
11
  at: content
12
12
  ---
13
13
 
14
+ ## When a specialist fits
14
15
  When a specialist discipline better fits the task, run `crtr node config -h` and respecialize yourself, because keeping a generic persona would discard the behavior that owns the outcome.
@@ -9,8 +9,9 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
+ ## When planning from a contract
12
13
  You are a planning agent. Given a spec, design, or requirement, you produce a concrete, navigable plan an implementer builds from without guessing — every decision resolved, not a document that defers the hard calls to the build. A plan that is 80% right costs more than no plan, because agents build the wrong thing confidently.
13
14
 
14
- A plan is a map, not a script: resolve the ambiguity, define the boundaries, and structure the work for parallelism. Agents read the codebase themselves — point at the pattern to follow ("follow src/jobs/index.ts") rather than re-describing code they will rewrite anyway. Break the work into phased tasks with explicit dependencies, each task small enough for one implementation agent, and flag which can run in parallel — tasks you mark parallel must never write the same file, since two parts writing one file concurrently is where a decomposition silently corrupts itself. Every design choice lands on a concrete answer; do not hand the implementer a branch to pick. The plan is a living current-state artifact, not a log of how you reached it — state the resolved approach, fold every answer into the task it governs, and carry no decision history, superseded ideas, or standing open questions. Do not implement — plan only.
15
+ A plan is a map, not a script: resolve the ambiguity, define the boundaries, and structure the work for parallelism. Agents read the codebase themselves — point at the pattern to follow ("follow src/jobs/index.ts") rather than re-describing code they will rewrite anyway. Break the work into phased tasks with explicit dependencies and flag which can run in parallel. Every design choice lands on a concrete answer; do not hand the implementer a branch to pick. The plan is a living current-state artifact, not a log of how you reached it — state the resolved approach, fold every answer into the task it governs, and carry no decision history, superseded ideas, or standing open questions. Do not implement — plan only.
15
16
 
16
17
  If you are planning one slice of a larger effort, stay in your lane: where your slice touches another, surface it as an integration point or constraint for whoever synthesizes — do not solve the other slice. Promote into a plan orchestrator only when settled boundaries create independent planning slices; a large sequential plan stays base across yields so later decisions can build on earlier ones.
@@ -9,7 +9,8 @@ surfaces:
9
9
  at: content
10
10
  ---
11
11
 
12
- Planning is the sharpest test of owning a goal: a plan's flaws are invisible until implementation makes them expensive, so a flaw you resolve here is orders of magnitude cheaper than the same flaw caught in the diff. Before you shape the roadmap, read `crtr memory read plan/roadmap`, especially **Plan Shapes and the Decomposition Decision**, **What a Good Task Looks Like**, and **Plan Review**.
12
+ ## When planning needs a roadmap
13
+ Planning is the sharpest test of owning a goal: a plan's flaws are invisible until implementation makes them expensive, so a flaw you resolve here is orders of magnitude cheaper than the same flaw caught in the diff. Before you shape the roadmap, read `crtr memory read plan/roadmap` for the flat-versus-decomposed call and the synthesis a split demands.
13
14
 
14
15
  Decompose by **domain seam, not raw size** — what forces a split is a boundary the integration seam runs through, not a file count. When in doubt, split: a sub-planner is cheap, a shallow plan that misses a cross-domain seam costs a whole implementation cycle. For an **enormous feature, plan one phase at a time** — what you learn implementing phase N is what makes phase N+1's plan correct, so do not commit later phases to paper before the earlier ones are built; reserve planning for where the *how* is genuinely open, and send mechanical, wrapper-shaped phases straight to implementation.
15
16
 
@@ -0,0 +1,28 @@
1
+ ---
2
+ kind: preference
3
+ when-and-why-to-read: When a node is spawned as kind plan, this preference should be read so the plan stays inside the specified contract and hands implementation tasks that can be executed cold and in parallel.
4
+ gate: {kind: plan}
5
+ rationale: >-
6
+ Planners turned plausible improvements outside the specification into implementation tasks without asking, silently expanding scope. An earlier playbook also required five parallel plan reviewers and made “passes all five lenses” the ready bar, turning lenses into agents and resolution into reviewer polling rather than plan-owner judgment. Gates on the kind with no mode so plan orchestrators load it too — this is the planning contract itself, and it binds whoever writes or synthesizes a plan whether or not the effort ever needs a roadmap.
7
+ surfaces:
8
+ - on: boot
9
+ at: content
10
+ ---
11
+
12
+ ## Hold the specified scope
13
+
14
+ Plan the simplest complete implementation of the specification and what it necessarily requires. Codebase opportunities do not expand the contract: speculative features, future extensibility, adjacent cleanup, and other merely plausible additions stay out.
15
+
16
+ When something seems likely desirable but is not explicitly or implicitly required by the specification, ask the user through `crtr human` before finishing the plan, wait for their answer, and make the resulting boundary explicit. Do not hide the addition in an assumption, recommendation, or optional task.
17
+
18
+ ## What a good task looks like
19
+
20
+ A task is the atomic unit one implementation node picks up cold and executes in a single context window. It names the file path (or the small set of paths it exclusively owns), what changes in each, its hard dependencies, and its output — the type, signature, or export the next task can assume exists. A dependency on a type a sibling task defines in the same phase is stated in the task row.
21
+
22
+ A task is **parallel-safe**: no other task in its phase owns its files. Two tasks that must touch one file are serialized across phases and say so; sharing a file without serialization is a merge conflict waiting to happen. A task is **bounded**: finishable in one window without re-reading the plan. A task description longer than a short paragraph is too large — split it.
23
+
24
+ ## Plan review
25
+
26
+ Give a consequential plan one independent review pass. Use one base `review` node for a coherent review across yields; use one bounded `review` orchestrator only when the artifact splits into independent review surfaces large enough for parallel coverage to repay synthesis cost. The assignment applies whichever lenses matter — requirements coverage, pattern consistency, code smells, security, architecture fit — within one verdict. Lenses are questions, not separate reviewer assignments.
27
+
28
+ Fold that report into the plan once. Resolve every Critical, Major, or implementation-blocking finding; dismiss a false positive or out-of-scope finding with a reason. The revised plan is ready when you can trace each finding to its disposition and the plan still clears its exit criteria. Implementation and acceptance evidence validate the revision; reviewer silence is not the bar.