toolroll 0.9.36 → 0.9.38

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 (175) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/dist/assignment-adapters.d.ts +12 -48
  3. package/dist/assignment-adapters.js +33 -43
  4. package/dist/browser/THIRD_PARTY_NOTICES.txt +3 -3
  5. package/dist/browser/workspace.css +1 -1
  6. package/dist/browser/workspace.js +26 -26
  7. package/dist/browser-crew.js +5 -0
  8. package/dist/browser-workspace.d.ts +2 -0
  9. package/dist/build-review.d.ts +1 -1
  10. package/dist/build-review.js +2 -1
  11. package/dist/chat-acceptance.d.ts +1 -1
  12. package/dist/chat-actions.d.ts +18 -12
  13. package/dist/chat-actions.js +15 -65
  14. package/dist/chat-ask.js +5 -5
  15. package/dist/chat-channel.js +20 -9
  16. package/dist/chat-decide.d.ts +18 -4
  17. package/dist/chat-decide.js +31 -11
  18. package/dist/chat-delivery-state.d.ts +12 -70
  19. package/dist/chat-delivery-state.js +17 -135
  20. package/dist/chat-delivery.js +58 -30
  21. package/dist/chat-flow.js +8 -6
  22. package/dist/chat-inbox.js +1 -1
  23. package/dist/coding-context.d.ts +2 -39
  24. package/dist/coding-context.js +2 -1
  25. package/dist/coding-handoff.d.ts +6 -25
  26. package/dist/coding-handoff.js +11 -5
  27. package/dist/coding-types.d.ts +2 -26
  28. package/dist/coding-workspace.d.ts +2 -0
  29. package/dist/coding-workspace.js +50 -14
  30. package/dist/contracts/acceptance-terms.d.ts +14 -0
  31. package/dist/contracts/acceptance-terms.js +16 -0
  32. package/dist/contracts/chat-actions.d.ts +328 -0
  33. package/dist/contracts/chat-actions.js +133 -0
  34. package/dist/contracts/chat-callback-rows.d.ts +59 -0
  35. package/dist/contracts/chat-callback-rows.js +46 -0
  36. package/dist/contracts/chat-content.d.ts +276 -0
  37. package/dist/contracts/chat-content.js +127 -0
  38. package/dist/contracts/chat-tables.d.ts +6 -0
  39. package/dist/contracts/chat-tables.js +136 -0
  40. package/dist/contracts/coding-context.d.ts +97 -0
  41. package/dist/contracts/coding-context.js +60 -0
  42. package/dist/contracts/coding-handoff.d.ts +44 -0
  43. package/dist/contracts/coding-handoff.js +47 -0
  44. package/dist/contracts/coding-workspace.d.ts +165 -0
  45. package/dist/contracts/coding-workspace.js +71 -0
  46. package/dist/contracts/contract.d.ts +7 -2
  47. package/dist/contracts/contract.js +21 -12
  48. package/dist/contracts/decision.d.ts +45 -0
  49. package/dist/contracts/decision.js +45 -0
  50. package/dist/contracts/discord-callback.d.ts +45 -0
  51. package/dist/contracts/discord-callback.js +34 -0
  52. package/dist/contracts/flow-card.d.ts +50 -0
  53. package/dist/contracts/flow-card.js +46 -0
  54. package/dist/contracts/flow-send.d.ts +119 -0
  55. package/dist/contracts/flow-send.js +112 -0
  56. package/dist/contracts/flow.d.ts +5 -0
  57. package/dist/contracts/flow.js +5 -0
  58. package/dist/contracts/gateway-tools.d.ts +374 -0
  59. package/dist/contracts/gateway-tools.js +94 -0
  60. package/dist/contracts/lead-context.d.ts +165 -0
  61. package/dist/contracts/lead-context.js +73 -0
  62. package/dist/contracts/lead-tools.d.ts +1905 -0
  63. package/dist/contracts/lead-tools.js +265 -0
  64. package/dist/contracts/memory-pass.d.ts +158 -0
  65. package/dist/contracts/memory-pass.js +102 -0
  66. package/dist/contracts/project-knowledge.d.ts +126 -0
  67. package/dist/contracts/project-knowledge.js +93 -0
  68. package/dist/contracts/project-memory.d.ts +117 -0
  69. package/dist/contracts/project-memory.js +51 -0
  70. package/dist/contracts/project-skills.d.ts +121 -0
  71. package/dist/contracts/project-skills.js +76 -0
  72. package/dist/contracts/review-findings.d.ts +46 -0
  73. package/dist/contracts/review-findings.js +48 -0
  74. package/dist/contracts/route.d.ts +484 -0
  75. package/dist/contracts/route.js +128 -0
  76. package/dist/contracts/scope.d.ts +105 -0
  77. package/dist/contracts/scope.js +114 -0
  78. package/dist/contracts/scout-report.d.ts +234 -0
  79. package/dist/contracts/scout-report.js +141 -0
  80. package/dist/contracts/slack-callback.d.ts +43 -0
  81. package/dist/contracts/slack-callback.js +35 -0
  82. package/dist/contracts/sort-answer.d.ts +83 -0
  83. package/dist/contracts/sort-answer.js +77 -0
  84. package/dist/contracts/stage-output.d.ts +127 -0
  85. package/dist/contracts/stage-output.js +166 -0
  86. package/dist/contracts/task-sizing.d.ts +24 -0
  87. package/dist/contracts/task-sizing.js +28 -0
  88. package/dist/contracts/teammate-turn.d.ts +43 -0
  89. package/dist/contracts/teammate-turn.js +51 -0
  90. package/dist/contracts/teams-callback.d.ts +14 -0
  91. package/dist/contracts/teams-callback.js +14 -0
  92. package/dist/contracts/telegram-callback.d.ts +120 -0
  93. package/dist/contracts/telegram-callback.js +97 -0
  94. package/dist/decision.d.ts +11 -20
  95. package/dist/decision.js +86 -167
  96. package/dist/desktop-update.d.ts +1 -1
  97. package/dist/discord-chat.js +31 -20
  98. package/dist/flow-engine.js +14 -17
  99. package/dist/flow-items.d.ts +4 -13
  100. package/dist/flow-items.js +1 -15
  101. package/dist/flow-send.d.ts +6 -37
  102. package/dist/flow-send.js +18 -14
  103. package/dist/flow-share.js +7 -1
  104. package/dist/flow-sort.d.ts +7 -26
  105. package/dist/flow-sort.js +25 -20
  106. package/dist/flow-steps.js +3 -2
  107. package/dist/flows.d.ts +2 -4
  108. package/dist/flows.js +9 -5
  109. package/dist/invoke.js +4 -4
  110. package/dist/lead-context.d.ts +4 -2
  111. package/dist/lead-context.js +24 -17
  112. package/dist/mate-progress.d.ts +26 -0
  113. package/dist/mate-progress.js +24 -0
  114. package/dist/mate-tools.d.ts +4 -0
  115. package/dist/mate-tools.js +108 -275
  116. package/dist/mate.js +11 -2
  117. package/dist/mcp-connect.d.ts +24 -4
  118. package/dist/mcp-connect.js +78 -15
  119. package/dist/mcp.js +84 -216
  120. package/dist/memory-pass.d.ts +17 -42
  121. package/dist/memory-pass.js +54 -26
  122. package/dist/phase-routing.d.ts +19 -72
  123. package/dist/phase-routing.js +34 -164
  124. package/dist/project-knowledge.d.ts +16 -35
  125. package/dist/project-knowledge.js +42 -21
  126. package/dist/project-memory.d.ts +2 -28
  127. package/dist/project-memory.js +28 -13
  128. package/dist/project-skills.d.ts +16 -38
  129. package/dist/project-skills.js +41 -32
  130. package/dist/project-tools.d.ts +1 -0
  131. package/dist/project-tools.js +4 -4
  132. package/dist/provider.d.ts +2 -0
  133. package/dist/provider.js +4 -16
  134. package/dist/result-shots.d.ts +1 -1
  135. package/dist/result-shots.js +2 -1
  136. package/dist/review-switch.d.ts +3 -8
  137. package/dist/reviewer.d.ts +8 -12
  138. package/dist/reviewer.js +11 -35
  139. package/dist/scope.d.ts +21 -43
  140. package/dist/scope.js +42 -128
  141. package/dist/scout-report.d.ts +9 -194
  142. package/dist/scout-report.js +113 -264
  143. package/dist/scout.js +15 -11
  144. package/dist/serve.js +23 -5
  145. package/dist/setup-guide.d.ts +2 -2
  146. package/dist/slack-chat.js +26 -20
  147. package/dist/slack-state.js +2 -1
  148. package/dist/store.d.ts +9 -32
  149. package/dist/store.js +18 -15
  150. package/dist/structured-output.js +2 -1
  151. package/dist/subscription-chat.d.ts +4 -0
  152. package/dist/subscription-chat.js +4 -1
  153. package/dist/task-review-brief.d.ts +1 -7
  154. package/dist/task-review-brief.js +6 -6
  155. package/dist/task-sizing.d.ts +3 -27
  156. package/dist/task-sizing.js +11 -26
  157. package/dist/task-text.d.ts +0 -5
  158. package/dist/task-text.js +1 -3
  159. package/dist/teammate-question.js +7 -5
  160. package/dist/teammate-work.js +9 -5
  161. package/dist/teammates.d.ts +13 -64
  162. package/dist/teammates.js +32 -33
  163. package/dist/teams-chat.js +20 -11
  164. package/dist/telegram-flow.d.ts +9 -0
  165. package/dist/telegram-flow.js +44 -8
  166. package/dist/telegram-mate.d.ts +4 -14
  167. package/dist/telegram-mate.js +9 -8
  168. package/dist/telegram-team.d.ts +2 -19
  169. package/dist/telegram.d.ts +1 -1
  170. package/dist/telegram.js +94 -68
  171. package/dist/text-limits.d.ts +142 -1
  172. package/dist/text-limits.js +144 -1
  173. package/dist/tools-ui.d.ts +2 -1
  174. package/dist/tools-ui.js +7 -4
  175. package/package.json +17 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,82 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.38 — 2026-10-06
4
+
5
+ - **The release check is faster.** Its app journeys run in about 8 minutes
6
+ instead of about 12, with no journey or coverage dropped.
7
+ - **Lead chat tool steps tell the truth.** A step shows done only when it
8
+ succeeded. A failed step says why in plain words.
9
+ - **Telegram decision cards lead with the action.** Decisions, plans, lead
10
+ proposals, flow approvals and flow choices say what to do and what it does
11
+ first. "Nothing changes until you confirm." stays on every proposal, and
12
+ buttons on cards already sent still work.
13
+ - **Crew rows say why.** A task that is waiting, failed or needs you shows the
14
+ reason in one line; tap it to read the rest. The whole row still opens the
15
+ task.
16
+ - **Dependency updates.** @slack/socket-mode 3.1.0, imapflow 2.2.5,
17
+ nodemailer 10.0.15, mailparser 3.9.36, lucide-react 1.52.0, @xyflow/react
18
+ 12.12.0, happy-dom 20.14.5 and tsx 4.23.15. Vitest takes the 4.1.11 security
19
+ patch and stays on 4; version 5 waits for its own migration. `npm audit`
20
+ reports no vulnerabilities.
21
+
22
+ ## 0.9.37 — 2026-10-06
23
+
24
+ - **Zod revamp, waves 1 and 2 finished.** Every handoff between a model and
25
+ Toolroll, and the context passed between steps, is now one schema each in
26
+ `src/contracts/`: the lead's 51 tools and the 25 MCP gateway tools, the
27
+ scout report, task sizing, reviewer findings, decisions, teammate turns and
28
+ sort answers, the lead's context bundle, project knowledge, memory and
29
+ skills, chat actions and channel callbacks, and the desktop coding handoff,
30
+ context and session record. A model gets the schema as `--json-schema`
31
+ where its harness takes one; a refusal names the field
32
+ (`steps[0].routes[0].goesTo: required`). Everything that was accepted before
33
+ is still accepted: tool calls with extra or loose arguments, model answers
34
+ with nulls or overlong text (clipped as before), saved reports, rows,
35
+ sessions, chat buttons and proposals. Replayed against real saved data
36
+ (scout reports, findings, decisions, 410 scopes and 796 routes, 279 chat
37
+ buttons, every saved flow and card), all of it reads the same.
38
+ - **Research can read PostHog.** A research run gets a connected service's
39
+ query tool (PostHog's `exec`) only when the access the service actually
40
+ granted is read-only. Otherwise it skips it and says why on the run and the
41
+ integration, with a **Reconnect read-only** action. Connecting PostHog as
42
+ usual is unchanged, and builds keep every tool. Connections made before this
43
+ release didn't record what was granted, so research skips them until you
44
+ reconnect read-only.
45
+ - **A question's recommendation can carry its reason.** `connect: because…`
46
+ now counts as recommending `connect`, instead of failing the question.
47
+ - **A Telegram update Toolroll can't read** is logged and answered OK, so
48
+ Telegram doesn't keep resending it. A Slack, Discord or Teams message part
49
+ that can't be read is dropped with its reason instead of retried forever.
50
+ - **Rolling back:** flow cards written by 0.9.37 read as empty in 0.9.36, so a
51
+ rollback loses the step outputs of cards still in progress.
52
+ - **Scopes, acceptance criteria and sealed routes have one contract.** A task's
53
+ scope (goal, exclusions, touch paths, rubric) and an acceptance criterion are
54
+ described once from the plan contract's own fields (`src/contracts/scope.ts`);
55
+ a sealed agent route, in both versions it has been saved in, with its
56
+ overrides and task size, is one schema (`src/contracts/route.ts`). The shared
57
+ rubric input schema is ready for the lead-tool migration. Every saved scope,
58
+ standing order and sealed route reads and digests exactly as before, so no
59
+ approval changes.
60
+ Nothing new is refused: a scope still names up to 50 paths and a criterion
61
+ still ignores keys it doesn't use. Rubric and route refusals are now
62
+ field-named lines (`acceptance[0].statement over 1,000 bytes`), and a route
63
+ made by a newer Toolroll says so.
64
+ - **What a flow's steps hand on has one contract.** A finished zone's
65
+ `{{stage.…}}` words, a card's saved outputs, and what Send to me and Person
66
+ chooses send are each described once (`src/contracts/stage-output.ts`,
67
+ `flow-send.ts`, `flow-card.ts`). Saved cards and sends read exactly as
68
+ before. A build or research task filed after a step whose output was too
69
+ long to pass on now gets that output whole, not just a link to it.
70
+ - **Tightened, on purpose.** Saving a flow with a new `{{stage.…}}` that its
71
+ zone doesn't hand on is refused, naming where:
72
+ `stages[2].instructions: stage.research.unknown is not available (Research
73
+ hands on {{stage.research}}, {{stage.research.items}} and
74
+ {{stage.research.report}})`. This covers the canvas, `toolroll flows
75
+ create/edit/import`, the lead and templates. A reference a flow already had
76
+ is never refused, and nothing changes for flows that are only read or run.
77
+ Card outputs and kept sends are saved with a version; ones a newer Toolroll
78
+ wrote are refused rather than misread or overwritten.
79
+
3
80
  ## 0.9.36 — 2026-10-06
4
81
 
5
82
  - **Flows have one contract.** Every kind of zone, step, route, answer,
@@ -1,87 +1,52 @@
1
1
  import { type AssignmentSnapshot } from "./assignment.js";
2
2
  import type { Store } from "./store.js";
3
- export declare const ASSIGNMENT_ACTIONS: readonly ["show", "updates", "claim", "check", "brief", "inbox", "ack"];
4
- export type AssignmentOperation = typeof ASSIGNMENT_ACTIONS[number];
3
+ import { type AssignmentInput, type AssignmentOperation } from "./contracts/gateway-tools.js";
4
+ export declare const ASSIGNMENT_ACTIONS: AssignmentOperation[];
5
+ export type { AssignmentOperation };
5
6
  type Args = Record<string, unknown>;
6
7
  type Failure = {
7
8
  ok: false;
8
9
  reason: string;
9
10
  message: string;
10
11
  };
12
+ /** The gateway's assignment tools: names and words. Each one's input is ASSIGNMENT_INPUTS[operation]
13
+ * (src/contracts/gateway-tools.ts), which `toolroll assignment` reads its flags with too. */
11
14
  export declare const ASSIGNMENT_TOOLS: readonly [{
12
15
  readonly name: "get_assignment";
13
16
  readonly operation: "show";
14
17
  readonly description: "Read one assignment's root, current execution, owner, exact result and handoff receipt. Approval, proof and deployment remain separate facts.";
15
- readonly inputSchema: {
16
- type: string;
17
- properties: Record<string, unknown>;
18
- required: string[];
19
- additionalProperties: boolean;
20
- };
21
18
  }, {
22
19
  readonly name: "list_assignment_updates";
23
20
  readonly operation: "updates";
24
21
  readonly description: "Read durable assignment updates in your projects after a cursor. Save nextCursor after processing; repeated reads do not acknowledge or deliver anything.";
25
- readonly inputSchema: {
26
- type: string;
27
- properties: Record<string, unknown>;
28
- required: string[];
29
- additionalProperties: boolean;
30
- };
31
22
  }, {
32
23
  readonly name: "claim_assignment";
33
24
  readonly operation: "claim";
34
25
  readonly description: "Record yourself as this assignment's lead. Repeating your claim is safe; another active owner cannot be replaced. This grants no approval or execution authority.";
35
- readonly inputSchema: {
36
- type: string;
37
- properties: Record<string, unknown>;
38
- required: string[];
39
- additionalProperties: boolean;
40
- };
41
26
  }, {
42
27
  readonly name: "acknowledge_assignment";
43
28
  readonly operation: "check";
44
29
  readonly description: "Acknowledge the exact ready-to-check receipt as its lead, using the current receipt digest. This does not accept failed proof, answer decisions, approve work, publish or deploy.";
45
- readonly inputSchema: {
46
- type: string;
47
- properties: Record<string, unknown>;
48
- required: string[];
49
- additionalProperties: boolean;
50
- };
51
30
  }, {
52
31
  readonly name: "get_assignment_brief";
53
32
  readonly operation: "brief";
54
33
  readonly description: "Catch up from the local database: current work, decisions, saved results and project knowledge. Bounded read only; no model call or task mutation.";
55
- readonly inputSchema: {
56
- type: string;
57
- properties: Record<string, unknown>;
58
- required: string[];
59
- additionalProperties: boolean;
60
- };
61
34
  }, {
62
35
  readonly name: "get_assignment_inbox";
63
36
  readonly operation: "inbox";
64
37
  readonly description: "Receive a durable batch of your assignments' status changes. Use a stable consumer name. Until acknowledged, the same batch survives reconnects and restarts. Receiving never completes or reruns work.";
65
- readonly inputSchema: {
66
- type: string;
67
- properties: Record<string, unknown>;
68
- required: string[];
69
- additionalProperties: boolean;
70
- };
71
38
  }, {
72
39
  readonly name: "acknowledge_assignment_delivery";
73
40
  readonly operation: "ack";
74
41
  readonly description: "Acknowledge receipt of an inbox batch after handling its updates. This advances only your delivery cursor; it never marks work complete, answers a decision or starts a revision.";
75
- readonly inputSchema: {
76
- type: string;
77
- properties: Record<string, unknown>;
78
- required: string[];
79
- additionalProperties: boolean;
80
- };
81
42
  }];
82
- /** The CLI and MCP use the same bounded input contract. MCP also validates its
83
- * descriptor before dispatch; this check protects direct adapter callers. */
84
- export declare function assignmentArgumentProblem(operation: AssignmentOperation, args: Args): string | null;
43
+ /** The CLI and MCP read an assignment call with the same schema; MCP reads it before dispatch too, and this protects
44
+ * direct adapter callers. A refusal is its path-named lines; a ref or project path with control characters, which
45
+ * JSON Schema can't say, is refused after parsing. */
46
+ export declare function readAssignmentArgs<O extends AssignmentOperation>(operation: O, args: Args): {
47
+ ok: true;
48
+ value: AssignmentInput<O>;
49
+ } | Failure;
85
50
  /** Every read and mutation authenticates inside the same transaction as its
86
51
  * projection. A cached name/allowlist cannot keep a revoked identity alive. */
87
52
  export declare function assignmentForCoordinator(store: Store, token: string, operation: AssignmentOperation, args: Args, now: Date, evidenceRoot?: string): Failure | {
@@ -179,4 +144,3 @@ export declare function coordinatorToken(flags: Map<string, string | true>, env:
179
144
  token: string | null;
180
145
  } | Failure;
181
146
  export declare function runAssignmentCommand(positional: readonly string[], flags: Map<string, string | true>, context: AssignmentCliContext): number;
182
- export {};
@@ -8,47 +8,36 @@ import { assignmentCatchUp } from "./assignment-brief.js";
8
8
  import { assignmentInbox, acknowledgeAssignmentDelivery } from "./assignment-delivery.js";
9
9
  import { syncAssignmentStatuses } from "./assignment-status.js";
10
10
  import { envelopeJson } from "./envelope.js";
11
- export const ASSIGNMENT_ACTIONS = ["show", "updates", "claim", "check", "brief", "inbox", "ack"];
11
+ import { parseContract } from "./contracts/contract.js";
12
+ import { ASSIGNMENT_INPUTS } from "./contracts/gateway-tools.js";
13
+ export const ASSIGNMENT_ACTIONS = Object.keys(ASSIGNMENT_INPUTS);
12
14
  const failure = (reason, message) => ({ ok: false, reason, message });
13
- const reference = { type: "string", minLength: 1, maxLength: 64 };
14
- const digest = { type: "string", minLength: 64, maxLength: 64, pattern: "^[a-f0-9]{64}$" };
15
- const batchId = { type: "string", minLength: 32, maxLength: 32, pattern: "^[a-f0-9]{32}$" };
16
- const consumer = { type: "string", minLength: 1, maxLength: 64, pattern: "^[a-z0-9][a-z0-9-]{0,63}$" };
17
- const object = (properties, required = []) => ({ type: "object", properties, required, additionalProperties: false });
15
+ /** The gateway's assignment tools: names and words. Each one's input is ASSIGNMENT_INPUTS[operation]
16
+ * (src/contracts/gateway-tools.ts), which `toolroll assignment` reads its flags with too. */
18
17
  export const ASSIGNMENT_TOOLS = [
19
- { name: "get_assignment", operation: "show", description: "Read one assignment's root, current execution, owner, exact result and handoff receipt. Approval, proof and deployment remain separate facts.", inputSchema: object({ ref: reference }, ["ref"]) },
20
- { name: "list_assignment_updates", operation: "updates", description: "Read durable assignment updates in your projects after a cursor. Save nextCursor after processing; repeated reads do not acknowledge or deliver anything.", inputSchema: object({ after: { type: "integer", minimum: 0, maximum: Number.MAX_SAFE_INTEGER }, limit: { type: "integer", minimum: 1, maximum: 100 } }) },
21
- { name: "claim_assignment", operation: "claim", description: "Record yourself as this assignment's lead. Repeating your claim is safe; another active owner cannot be replaced. This grants no approval or execution authority.", inputSchema: object({ ref: reference }, ["ref"]) },
22
- { name: "acknowledge_assignment", operation: "check", description: "Acknowledge the exact ready-to-check receipt as its lead, using the current receipt digest. This does not accept failed proof, answer decisions, approve work, publish or deploy.", inputSchema: object({ ref: reference, digest }, ["ref", "digest"]) },
23
- { name: "get_assignment_brief", operation: "brief", description: "Catch up from the local database: current work, decisions, saved results and project knowledge. Bounded read only; no model call or task mutation.", inputSchema: object({ repo: { type: "string", minLength: 1, maxLength: 4096 }, limit: { type: "integer", minimum: 1, maximum: 25 } }) },
24
- { name: "get_assignment_inbox", operation: "inbox", description: "Receive a durable batch of your assignments' status changes. Use a stable consumer name. Until acknowledged, the same batch survives reconnects and restarts. Receiving never completes or reruns work.", inputSchema: object({ consumer, limit: { type: "integer", minimum: 1, maximum: 100 } }, ["consumer"]) },
25
- { name: "acknowledge_assignment_delivery", operation: "ack", description: "Acknowledge receipt of an inbox batch after handling its updates. This advances only your delivery cursor; it never marks work complete, answers a decision or starts a revision.", inputSchema: object({ consumer, batchId }, ["consumer", "batchId"]) },
18
+ { name: "get_assignment", operation: "show", description: "Read one assignment's root, current execution, owner, exact result and handoff receipt. Approval, proof and deployment remain separate facts." },
19
+ { name: "list_assignment_updates", operation: "updates", description: "Read durable assignment updates in your projects after a cursor. Save nextCursor after processing; repeated reads do not acknowledge or deliver anything." },
20
+ { name: "claim_assignment", operation: "claim", description: "Record yourself as this assignment's lead. Repeating your claim is safe; another active owner cannot be replaced. This grants no approval or execution authority." },
21
+ { name: "acknowledge_assignment", operation: "check", description: "Acknowledge the exact ready-to-check receipt as its lead, using the current receipt digest. This does not accept failed proof, answer decisions, approve work, publish or deploy." },
22
+ { name: "get_assignment_brief", operation: "brief", description: "Catch up from the local database: current work, decisions, saved results and project knowledge. Bounded read only; no model call or task mutation." },
23
+ { name: "get_assignment_inbox", operation: "inbox", description: "Receive a durable batch of your assignments' status changes. Use a stable consumer name. Until acknowledged, the same batch survives reconnects and restarts. Receiving never completes or reruns work." },
24
+ { name: "acknowledge_assignment_delivery", operation: "ack", description: "Acknowledge receipt of an inbox batch after handling its updates. This advances only your delivery cursor; it never marks work complete, answers a decision or starts a revision." },
26
25
  ];
27
- /** The CLI and MCP use the same bounded input contract. MCP also validates its
28
- * descriptor before dispatch; this check protects direct adapter callers. */
29
- export function assignmentArgumentProblem(operation, args) {
26
+ /** The CLI and MCP read an assignment call with the same schema; MCP reads it before dispatch too, and this protects
27
+ * direct adapter callers. A refusal is its path-named lines; a ref or project path with control characters, which
28
+ * JSON Schema can't say, is refused after parsing. */
29
+ export function readAssignmentArgs(operation, args) {
30
30
  if (!ASSIGNMENT_ACTIONS.includes(operation))
31
- return "Choose show, updates, claim, check, brief, inbox, or ack.";
32
- const allowed = operation === "brief" ? ["repo", "limit"] : operation === "inbox" ? ["consumer", "limit"] : operation === "ack" ? ["consumer", "batchId"] : operation === "updates" ? ["after", "limit"] : operation === "check" ? ["ref", "digest"] : ["ref"];
33
- for (const key of Object.keys(args))
34
- if (!allowed.includes(key))
35
- return `Unknown argument: ${key}.`;
36
- if (["show", "claim", "check"].includes(operation) && (typeof args["ref"] !== "string" || args["ref"].length < 1 || args["ref"].length > 64 || /[\u0000-\u001f\u007f]/.test(args["ref"])))
37
- return "Choose a task id, 1–64 characters without control characters.";
38
- if (operation === "check" && (typeof args["digest"] !== "string" || !/^[a-f0-9]{64}$/.test(args["digest"])))
39
- return "Use the exact 64-character receipt digest from assignment show.";
40
- if ((operation === "inbox" || operation === "ack") && (typeof args["consumer"] !== "string" || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(args["consumer"])))
41
- return "Use a stable consumer name with 1–64 lowercase letters, digits or hyphens.";
42
- if (operation === "ack" && (typeof args["batchId"] !== "string" || !/^[a-f0-9]{32}$/.test(args["batchId"])))
43
- return "Use the exact batchId from assignment inbox.";
44
- if (args["repo"] !== undefined && (typeof args["repo"] !== "string" || args["repo"].length < 1 || args["repo"].length > 4096 || /[\u0000-\u001f\u007f]/.test(args["repo"])))
45
- return "Choose a project path without control characters.";
46
- for (const [name, min, max] of [["after", 0, Number.MAX_SAFE_INTEGER], ["limit", 1, operation === "brief" ? 25 : 100]]) {
47
- const value = args[name];
48
- if (value !== undefined && (typeof value !== "number" || !Number.isSafeInteger(value) || value < min || value > max))
49
- return `${name} must be an integer from ${min} to ${max}.`;
31
+ return failure("usage", "Choose show, updates, claim, check, brief, inbox, or ack.");
32
+ const read = parseContract(ASSIGNMENT_INPUTS[operation], args);
33
+ if (!read.ok)
34
+ return failure("usage", read.issues.map(one => one.line).join("; "));
35
+ const value = read.value;
36
+ for (const field of ["ref", "repo"]) {
37
+ if (typeof value[field] === "string" && /[\u0000-\u001f\u007f]/.test(value[field]))
38
+ return failure("usage", `${field}: must not contain control characters`);
50
39
  }
51
- return null;
40
+ return { ok: true, value };
52
41
  }
53
42
  function readAssignment(store, operation, args, now, access, root) {
54
43
  if (operation === "brief")
@@ -61,9 +50,10 @@ function readAssignment(store, operation, args, now, access, root) {
61
50
  /** Every read and mutation authenticates inside the same transaction as its
62
51
  * projection. A cached name/allowlist cannot keep a revoked identity alive. */
63
52
  export function assignmentForCoordinator(store, token, operation, args, now, evidenceRoot) {
64
- const problem = assignmentArgumentProblem(operation, args);
65
- if (problem !== null)
66
- return failure("usage", problem);
53
+ const read = readAssignmentArgs(operation, args);
54
+ if (!read.ok)
55
+ return read;
56
+ args = read.value;
67
57
  // Authenticate before maintenance, then authenticate again inside delivery.
68
58
  // Reconciliation owns one short transaction per family and cannot sit under
69
59
  // the delivery transaction's writer reservation.
@@ -225,11 +215,11 @@ export function runAssignmentCommand(positional, flags, context) {
225
215
  for (const flag of operationFlags) {
226
216
  const value = flags.get(flag);
227
217
  if (value !== undefined)
228
- args[flag === "batch" ? "batchId" : flag] = ["after", "limit"].includes(flag) ? typeof value === "string" && /^\d+$/.test(value) ? Number(value) : NaN : value;
218
+ args[flag === "batch" ? "batchId" : flag] = ["after", "limit"].includes(flag) && typeof value === "string" && /^\d+$/.test(value) ? Number(value) : value;
229
219
  }
230
- const problem = assignmentArgumentProblem(operation, args);
231
- if (problem !== null)
232
- return emit(failure("usage", problem));
220
+ const read = readAssignmentArgs(operation, args);
221
+ if (!read.ok)
222
+ return emit(read);
233
223
  const credential = coordinatorToken(flags, context.env ?? process.env);
234
224
  if ("ok" in credential)
235
225
  return emit(credential);
@@ -1460,7 +1460,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1460
1460
  SOFTWARE.
1461
1461
 
1462
1462
 
1463
- ## Bundled dependency: @xyflow/react 12.11.6
1463
+ ## Bundled dependency: @xyflow/react 12.12.0
1464
1464
 
1465
1465
  MIT License
1466
1466
 
@@ -1485,7 +1485,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1485
1485
  SOFTWARE.
1486
1486
 
1487
1487
 
1488
- ## Bundled dependency: @xyflow/system 0.0.82
1488
+ ## Bundled dependency: @xyflow/system 0.0.83
1489
1489
 
1490
1490
  MIT License
1491
1491
 
@@ -1971,7 +1971,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1971
1971
  SOFTWARE.
1972
1972
 
1973
1973
 
1974
- ## Bundled dependency: lucide-react 1.47.0
1974
+ ## Bundled dependency: lucide-react 1.52.0
1975
1975
 
1976
1976
  ISC License
1977
1977