toolroll 0.9.55 → 0.9.57

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 (223) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +24 -8
  3. package/dist/action-ledger.d.ts +2 -4
  4. package/dist/action-ledger.js +2 -10
  5. package/dist/approval-policy.d.ts +5 -5
  6. package/dist/approval-policy.js +4 -4
  7. package/dist/approval-rules-ui.js +2 -2
  8. package/dist/assignment-adapters.d.ts +5 -0
  9. package/dist/assignment.d.ts +24 -3
  10. package/dist/assignment.js +36 -10
  11. package/dist/browser/workspace.js +5 -5
  12. package/dist/browser-workspace.d.ts +12 -12
  13. package/dist/browser-workspace.js +1 -1
  14. package/dist/budget-alerts.js +3 -3
  15. package/dist/chat-actions.d.ts +23 -18
  16. package/dist/chat-actions.js +110 -88
  17. package/dist/chat-ask.d.ts +2 -2
  18. package/dist/chat-ask.js +5 -5
  19. package/dist/chat-channel.d.ts +15 -15
  20. package/dist/chat-channel.js +20 -20
  21. package/dist/chat-controls.d.ts +0 -4
  22. package/dist/chat-controls.js +0 -1
  23. package/dist/chat-core.js +1 -1
  24. package/dist/chat-delivery-state.js +2 -2
  25. package/dist/chat-delivery.d.ts +2 -2
  26. package/dist/chat-delivery.js +30 -37
  27. package/dist/chat-flow.js +3 -3
  28. package/dist/chat-messages.d.ts +1 -1
  29. package/dist/chat-messages.js +4 -4
  30. package/dist/chat-migration.d.ts +1 -1
  31. package/dist/chat-migration.js +11 -11
  32. package/dist/chat-rooms.js +3 -3
  33. package/dist/chat-voice.js +1 -1
  34. package/dist/chat-warmth.d.ts +2 -2
  35. package/dist/check-levels.d.ts +3 -0
  36. package/dist/check-levels.js +5 -0
  37. package/dist/cli.d.ts +1 -1
  38. package/dist/cli.js +6 -7
  39. package/dist/contracts/chat-actions.d.ts +32 -27
  40. package/dist/contracts/chat-actions.js +29 -11
  41. package/dist/contracts/chat-content.d.ts +1 -1
  42. package/dist/contracts/chat-content.js +1 -1
  43. package/dist/contracts/chat-tables.js +4 -4
  44. package/dist/contracts/console-api.d.ts +6 -6
  45. package/dist/contracts/console-api.js +7 -7
  46. package/dist/contracts/flow-propose.d.ts +3 -3
  47. package/dist/contracts/flow.d.ts +132 -125
  48. package/dist/contracts/flow.js +27 -12
  49. package/dist/contracts/lead-context.d.ts +1 -1
  50. package/dist/contracts/lead-context.js +2 -2
  51. package/dist/contracts/lead-tools.d.ts +20 -18
  52. package/dist/contracts/lead-tools.js +15 -15
  53. package/dist/contracts/stage-output.d.ts +1 -1
  54. package/dist/contracts/stage-output.js +1 -1
  55. package/dist/contracts/store-json.d.ts +23 -22
  56. package/dist/contracts/store-json.js +17 -17
  57. package/dist/contracts/{teammate-turn.d.ts → subagent-turn.d.ts} +5 -5
  58. package/dist/contracts/{teammate-turn.js → subagent-turn.js} +7 -7
  59. package/dist/converse.d.ts +23 -23
  60. package/dist/converse.js +28 -28
  61. package/dist/coordinator-proposals.d.ts +2 -2
  62. package/dist/coordinator-proposals.js +1 -1
  63. package/dist/coordinator.js +1 -1
  64. package/dist/deprecations.d.ts +12 -0
  65. package/dist/deprecations.js +20 -0
  66. package/dist/desktop-update-gate.js +8 -4
  67. package/dist/desktop-update.js +6 -1
  68. package/dist/discord-chat.js +6 -6
  69. package/dist/dispatch.d.ts +1 -1
  70. package/dist/dispatch.js +1 -1
  71. package/dist/dispose.js +0 -5
  72. package/dist/envelope.js +0 -1
  73. package/dist/export-ui.js +1 -1
  74. package/dist/export.js +7 -7
  75. package/dist/flow-engine.d.ts +2 -2
  76. package/dist/flow-engine.js +21 -21
  77. package/dist/flow-insights.d.ts +1 -1
  78. package/dist/flow-share.js +13 -8
  79. package/dist/flow-steps.d.ts +5 -5
  80. package/dist/flow-steps.js +19 -19
  81. package/dist/flow-triggers.d.ts +1 -1
  82. package/dist/flow-triggers.js +1 -1
  83. package/dist/flows-cli.js +1 -1
  84. package/dist/flows-ui.js +20 -20
  85. package/dist/flows.js +19 -19
  86. package/dist/guides.js +4 -3
  87. package/dist/invoke.js +1 -1
  88. package/dist/kits-ui.js +5 -5
  89. package/dist/kits.d.ts +12 -12
  90. package/dist/kits.js +31 -31
  91. package/dist/{mate-cli.d.ts → lead-cli.d.ts} +11 -11
  92. package/dist/{mate-cli.js → lead-cli.js} +38 -38
  93. package/dist/lead-commitments.js +4 -4
  94. package/dist/lead-context.d.ts +2 -2
  95. package/dist/lead-context.js +9 -9
  96. package/dist/{mate-contract.d.ts → lead-contract.d.ts} +3 -3
  97. package/dist/{mate-contract.js → lead-contract.js} +7 -6
  98. package/dist/{mate-doors.d.ts → lead-doors.d.ts} +6 -6
  99. package/dist/{mate-doors.js → lead-doors.js} +24 -24
  100. package/dist/lead-follow.d.ts +5 -5
  101. package/dist/lead-follow.js +9 -9
  102. package/dist/lead-people.d.ts +5 -5
  103. package/dist/lead-people.js +14 -14
  104. package/dist/{mate-progress.d.ts → lead-progress.d.ts} +9 -9
  105. package/dist/{mate-progress.js → lead-progress.js} +3 -3
  106. package/dist/lead-status.d.ts +1 -1
  107. package/dist/lead-status.js +2 -2
  108. package/dist/{mate-tools.d.ts → lead-tools.d.ts} +19 -19
  109. package/dist/{mate-tools.js → lead-tools.js} +109 -101
  110. package/dist/{mate.d.ts → lead.d.ts} +27 -27
  111. package/dist/{mate.js → lead.js} +102 -102
  112. package/dist/limits-ui.d.ts +1 -1
  113. package/dist/limits-ui.js +1 -1
  114. package/dist/mcp-connect.d.ts +1 -1
  115. package/dist/mcp-connect.js +3 -3
  116. package/dist/mcp-core.js +1 -1
  117. package/dist/memory-pass.d.ts +2 -2
  118. package/dist/memory-pass.js +7 -7
  119. package/dist/notification-rows.d.ts +2 -2
  120. package/dist/operate.d.ts +3 -3
  121. package/dist/operate.js +52 -42
  122. package/dist/policy.d.ts +1 -1
  123. package/dist/principal.d.ts +1 -1
  124. package/dist/principal.js +2 -2
  125. package/dist/project-delete-ui.js +1 -1
  126. package/dist/project-delete.d.ts +1 -1
  127. package/dist/project-delete.js +26 -26
  128. package/dist/project-memory.js +1 -1
  129. package/dist/project-tools.d.ts +1 -1
  130. package/dist/project-tools.js +1 -1
  131. package/dist/proof.d.ts +9 -0
  132. package/dist/proof.js +12 -0
  133. package/dist/recipe-ui.js +1 -1
  134. package/dist/release-coverage.d.ts +16 -0
  135. package/dist/release-coverage.js +92 -0
  136. package/dist/retention.js +4 -4
  137. package/dist/scope.d.ts +2 -2
  138. package/dist/scout-report.d.ts +1 -1
  139. package/dist/scout-report.js +1 -1
  140. package/dist/serve.js +40 -45
  141. package/dist/server/chat.d.ts +4 -4
  142. package/dist/server/chat.js +105 -103
  143. package/dist/server/chrome.js +3 -3
  144. package/dist/server/flows.js +69 -62
  145. package/dist/server/guards.js +3 -3
  146. package/dist/server/http.d.ts +3 -3
  147. package/dist/server/http.js +1 -1
  148. package/dist/server/live.js +6 -6
  149. package/dist/server/people-tokens.js +1 -1
  150. package/dist/server/remote.js +12 -10
  151. package/dist/server/render-chat.d.ts +30 -30
  152. package/dist/server/render-chat.js +33 -33
  153. package/dist/server/render-pages.js +2 -2
  154. package/dist/server/render-results.d.ts +4 -1
  155. package/dist/server/render-results.js +23 -9
  156. package/dist/server/render-settings.d.ts +7 -0
  157. package/dist/server/render-settings.js +3 -0
  158. package/dist/server/route-table.js +9 -7
  159. package/dist/server/runtime.d.ts +13 -13
  160. package/dist/server/settings.js +14 -13
  161. package/dist/server/tasks.js +34 -30
  162. package/dist/setup-guide.d.ts +2 -2
  163. package/dist/slack-chat.d.ts +2 -2
  164. package/dist/slack-chat.js +6 -6
  165. package/dist/spend-ui.d.ts +3 -3
  166. package/dist/spend-ui.js +9 -9
  167. package/dist/spend.d.ts +14 -14
  168. package/dist/spend.js +31 -31
  169. package/dist/store-baseline.d.ts +19 -0
  170. package/dist/store-baseline.js +2873 -0
  171. package/dist/store.d.ts +200 -254
  172. package/dist/store.js +830 -3152
  173. package/dist/subagent-admin.d.ts +53 -0
  174. package/dist/{teammate-admin.js → subagent-admin.js} +37 -37
  175. package/dist/{teammate-desk.d.ts → subagent-desk.d.ts} +22 -23
  176. package/dist/{teammate-desk.js → subagent-desk.js} +26 -35
  177. package/dist/{teammate-memory.d.ts → subagent-memory.d.ts} +17 -17
  178. package/dist/{teammate-memory.js → subagent-memory.js} +41 -41
  179. package/dist/{teammate-question.d.ts → subagent-question.d.ts} +6 -6
  180. package/dist/{teammate-question.js → subagent-question.js} +17 -17
  181. package/dist/{teammate-tools.d.ts → subagent-tools.d.ts} +18 -18
  182. package/dist/{teammate-tools.js → subagent-tools.js} +36 -36
  183. package/dist/{teammate-week.d.ts → subagent-week.d.ts} +10 -10
  184. package/dist/{teammate-week.js → subagent-week.js} +23 -23
  185. package/dist/{teammate-work.d.ts → subagent-work.d.ts} +21 -21
  186. package/dist/{teammate-work.js → subagent-work.js} +50 -50
  187. package/dist/subagents-ui.d.ts +22 -0
  188. package/dist/{teammates-ui.js → subagents-ui.js} +45 -45
  189. package/dist/{teammates.d.ts → subagents.d.ts} +11 -11
  190. package/dist/{teammates.js → subagents.js} +21 -21
  191. package/dist/subscription-chat.d.ts +13 -13
  192. package/dist/subscription-chat.js +19 -19
  193. package/dist/surface.d.ts +19 -2
  194. package/dist/surface.js +7 -31
  195. package/dist/task-outcome-cli.js +3 -1
  196. package/dist/task-status.d.ts +59 -7
  197. package/dist/task-status.js +132 -16
  198. package/dist/team-cli.d.ts +1 -0
  199. package/dist/team-cli.js +14 -2
  200. package/dist/team-leads.js +13 -13
  201. package/dist/team-runtime.d.ts +2 -2
  202. package/dist/team-runtime.js +9 -9
  203. package/dist/teams-chat.js +6 -6
  204. package/dist/telegram-flow.d.ts +3 -3
  205. package/dist/telegram-flow.js +3 -3
  206. package/dist/{telegram-mate.d.ts → telegram-lead.d.ts} +5 -5
  207. package/dist/{telegram-mate.js → telegram-lead.js} +27 -27
  208. package/dist/telegram-status.d.ts +11 -4
  209. package/dist/telegram-status.js +18 -11
  210. package/dist/telegram-team.d.ts +1 -1
  211. package/dist/telegram-team.js +5 -5
  212. package/dist/telegram.d.ts +1 -1
  213. package/dist/telegram.js +13 -34
  214. package/dist/text-limits.d.ts +18 -18
  215. package/dist/text-limits.js +18 -18
  216. package/dist/toolroll-update.d.ts +8 -0
  217. package/dist/toolroll-update.js +45 -8
  218. package/dist/work-index.d.ts +6 -1
  219. package/dist/work-index.js +50 -8
  220. package/dist/workspace-ui.js +2 -1
  221. package/package.json +1 -2
  222. package/dist/teammate-admin.d.ts +0 -53
  223. package/dist/teammates-ui.d.ts +0 -21
package/dist/guides.js CHANGED
@@ -318,7 +318,7 @@ ${AUTHORITY_LINE}
318
318
  transcripts following.
319
319
  - **projects** (\`/projects\`): enrol, open, or switch repositories; the
320
320
  project name in the header is the one-tap switcher on every screen.
321
- - **chat** (\`/chat\`): the mate — a conversation across every project
321
+ - **chat** (\`/chat\`): the lead — a conversation across every project
322
322
  that only PROPOSES (file, reorder, reserve, hold, rewrite a scope,
323
323
  cancel, answer a decision); each proposal is a card the person
324
324
  confirms. Coordinators over the MCP gateway propose the same way, and
@@ -340,7 +340,7 @@ ${AUTHORITY_LINE}
340
340
  - \`toolroll peek\`: one pane per live agent (digits focus, \`q\`
341
341
  leaves); \`peek <run>\` follows one; \`peek --tmux\` opens a tmux window
342
342
  per run.
343
- - \`toolroll chat\`: the mate in the terminal (\`--say "…"\` for one
343
+ - \`toolroll chat\`: the lead in the terminal (\`--say "…"\` for one
344
344
  turn); \`toolroll proposals\` lists and confirms coordinator
345
345
  proposals.
346
346
  - \`toolroll task add "<title>" --report\`: a SCOUT task — a
@@ -359,7 +359,8 @@ needs you · queued · waiting · building · done · failed; a *scope* is the
359
359
  contract a person approves; a *decision* is a typed question an agent
360
360
  parked; a *hold* pauses the next attempt; a *stale approval* means the
361
361
  approval no longer matches how builds are routed — approving again fixes
362
- it; a *scout* delivers a report; the *mate* proposes and never acts.
362
+ it; a *scout* delivers a report; the *lead* proposes and never acts, and
363
+ its *subagents* work within the rules you write for them.
363
364
  `,
364
365
  };
365
366
  const knowledge = {
package/dist/invoke.js CHANGED
@@ -353,7 +353,7 @@ export async function invokeAgent(store, runId, spec, invocation, options) {
353
353
  const evidence = spec.provider === "claude" ? claudeBillingFrom(billingSeen)
354
354
  // Codex signed in with ChatGPT is its plan, unless its plan is itself billed by use (seen by the console's probe).
355
355
  : codexLogin === "subscription" ? seenBilling(store.handle, "codex") ?? "subscription" : codexLogin;
356
- // What this computer's Claude does with no key from us (teammates and drafts bill the same way): learnt only from a
356
+ // What this computer's Claude does with no key from us (subagents and drafts bill the same way): learnt only from a
357
357
  // run we gave no key that got as far as an answer.
358
358
  if (spec.provider === "claude" && managedKey === null && authMode === "subscription" && billingSeen.answered && evidence !== null) {
359
359
  store.recordProviderBilling("claude", evidence, new Date());
package/dist/kits-ui.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { kitChecklist, kitInstalled, KITS } from "./kits.js";
2
- import { TEAMMATE_TEMPLATES } from "./teammates.js";
2
+ import { SUBAGENT_TEMPLATES } from "./subagents.js";
3
3
  import { html, postForm } from "./html.js";
4
4
  const CHECK = html `<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`;
5
5
  const RING = html `<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg>`;
@@ -12,21 +12,21 @@ export const KITS_CSS = `.kits{max-width:960px;min-width:0}.kits-lede{color:var(
12
12
  `.kit-steps .kit-step-said{flex:1;min-width:0}.kit-steps li[data-done="true"] .kit-step-said{color:var(--so-muted)}.kit-steps form{margin:0}.kit-steps button,.kit-steps .kit-step-go{min-height:40px;white-space:nowrap}` +
13
13
  `.kit-steps .kit-step-go{display:inline-flex;align-items:center;padding:0 12px;border:1px solid var(--so-line);border-radius:8px;text-decoration:none;font-size:.9rem}` +
14
14
  `@media(max-width:600px){.kit-steps li{flex-wrap:wrap}.kit-steps .kit-step-said{flex-basis:calc(100% - 40px)}.kit form select{font-size:16px}}`;
15
- const teammateWords = (kit) => { const template = TEAMMATE_TEMPLATES.find(one => one.id === kit.teammate.template); return template === undefined ? kit.teammate.handle : template.label.toLowerCase(); };
15
+ const subagentWords = (kit) => { const template = SUBAGENT_TEMPLATES.find(one => one.id === kit.subagent.template); return template === undefined ? kit.subagent.handle : template.label.toLowerCase(); };
16
16
  /** The gallery: every kit, set up in a project with one button (or opened, when it's already there). */
17
17
  export function kitsGalleryHtml(store, projects, projectName, canSetUp, notice) {
18
18
  const cards = KITS.map(kit => {
19
19
  const here = projects.filter(repo => kitInstalled(store, kit, repo) !== null);
20
20
  const open = projects.length === 1 && here.length === 1;
21
- const name = kit.teammate.handle.charAt(0).toUpperCase() + kit.teammate.handle.slice(1);
22
- const gets = `${name} (${teammateWords(kit)}) · the ${kit.flowName} flow${kit.tools.length === 0 ? "" : ` · works with ${kit.tools.map(one => one.label).join(" and ")}`}`;
21
+ const name = kit.subagent.handle.charAt(0).toUpperCase() + kit.subagent.handle.slice(1);
22
+ const gets = `${name} (${subagentWords(kit)}) · the ${kit.flowName} flow${kit.tools.length === 0 ? "" : ` · works with ${kit.tools.map(one => one.label).join(" and ")}`}`;
23
23
  const action = open ? html `<a class="kit-open" href="/kits/${kit.id}?repo=${encodeURIComponent(projects[0])}">Open ${kit.name} →</a>`
24
24
  : !canSetUp || projects.length === 0 ? ""
25
25
  : postForm(`/kits/${kit.id}/setup`, html `${projects.length === 1 ? ""
26
26
  : html `<label>Project<select name="repo">${projects.map(repo => html `<option value="${repo}">${projectName(repo)}${here.includes(repo) ? " (set up)" : ""}</option>`)}</select></label>`}<button>Set it up</button>`, { hidden: { repo: projects.length === 1 ? projects[0] : null } });
27
27
  return html `<article class="kit" data-kit="${kit.id}"><h2>${kit.name}</h2><p class="kit-promise">${kit.promise}</p><p class="kit-gets">${gets}</p>${action}</article>`;
28
28
  });
29
- return html `<section class="kits">${notice.problem ? html `<p class="problem" role="alert">${notice.problem}</p>` : ""}<p class="kits-lede">A working setup in one click: an AI teammate, the flow it works, and what to connect next. Nothing goes out without you approving it.</p><div class="kit-grid">${cards}</div></section>`;
29
+ return html `<section class="kits">${notice.problem ? html `<p class="problem" role="alert">${notice.problem}</p>` : ""}<p class="kits-lede">A working setup in one click: a subagent, the flow it works, and what to connect next. Nothing goes out without you approving it.</p><div class="kit-grid">${cards}</div></section>`;
30
30
  }
31
31
  /** A kit's own page: what's set up, and the next step on each line. */
32
32
  export function kitPageHtml(store, kit, repo, dir, canSetUp, notice) {
package/dist/kits.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type FlowStepInput } from "./flows.js";
2
- import type { FlowRow, Store, TeammateRow } from "./store.js";
3
- import { type ToolIo } from "./teammate-tools.js";
4
- /** A tool a kit's teammate works better with: the catalog entry that connects it, and why. */
2
+ import type { FlowRow, Store, SubagentRow } from "./store.js";
3
+ import { type ToolIo } from "./subagent-tools.js";
4
+ /** A tool a kit's subagent works better with: the catalog entry that connects it, and why. */
5
5
  export type KitTool = {
6
6
  tool: string;
7
7
  label: string;
@@ -11,8 +11,8 @@ export type Kit = {
11
11
  id: string;
12
12
  name: string;
13
13
  promise: string;
14
- /** The teammate it hires: a template, and the name it starts with. */
15
- teammate: {
14
+ /** The subagent it hires: a template, and the name it starts with. */
15
+ subagent: {
16
16
  template: string;
17
17
  handle: string;
18
18
  };
@@ -38,23 +38,23 @@ type Done = {
38
38
  ok: true;
39
39
  said: string;
40
40
  flow: number;
41
- teammate: number;
41
+ subagent: number;
42
42
  } | {
43
43
  ok: false;
44
44
  said: string;
45
45
  };
46
- /** A kit set up in a project: its flow (by name) and its teammate, when both are there. */
46
+ /** A kit set up in a project: its flow (by name) and its subagent, when both are there. */
47
47
  export declare function kitInstalled(store: Store, kit: Kit, repo: string): {
48
48
  flow: FlowRow;
49
- mate: TeammateRow;
49
+ mate: SubagentRow;
50
50
  } | null;
51
51
  /**
52
- * Set a kit up: its teammate (kept if one of that name is already there), its
53
- * flow, and its button triggers; then its teammate may use whichever of the
52
+ * Set a kit up: its subagent (kept if one of that name is already there), its
53
+ * flow, and its button triggers; then its subagent may use whichever of the
54
54
  * kit's tools the project already has (reading free, writing asking first).
55
55
  */
56
56
  export declare function setUpKit(store: Store, kit: Kit, repo: string, by: string, now: Date, dir: string | null, io?: ToolIo): Promise<Done>;
57
- /** The same, all at once (a chat confirmation can't wait on a tool): its teammate is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
57
+ /** The same, all at once (a chat confirmation can't wait on a tool): its subagent is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
58
58
  export declare function setUpKitNow(store: Store, kit: Kit, repo: string, by: string, now: Date, dir: string | null, grantByName?: boolean): Done;
59
59
  /** One line of a kit's checklist: done, or the next step with where to take it. */
60
60
  export type KitStep = {
@@ -67,7 +67,7 @@ export type KitStep = {
67
67
  };
68
68
  /** What's set up and what's left, read fresh each time. */
69
69
  export declare function kitChecklist(store: Store, kit: Kit, repo: string, dir: string | null): KitStep[];
70
- /** A sample card in the kit's first zone, so its teammate starts on it at once. */
70
+ /** A sample card in the kit's first zone, so its subagent starts on it at once. */
71
71
  export declare function addKitSample(store: Store, kit: Kit, repo: string, by: string, now: Date): {
72
72
  ok: true;
73
73
  href: string;
package/dist/kits.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Starter kits: a working setup in one click — an AI teammate, the flow
2
+ * Starter kits: a working setup in one click — a subagent, the flow
3
3
  * it works, and the triggers that are safe to add straight away — plus a
4
4
  * checklist of what's left (connect email, connect a tool) and a sample card
5
- * that shows the teammate at work within seconds.
5
+ * that shows the subagent at work within seconds.
6
6
  *
7
7
  * A kit adds nothing a person couldn't add by hand, and nothing that acts
8
8
  * outside: replies go out only after you approve them, a code change is filed
@@ -16,17 +16,17 @@ import { googleConnected } from "./google-mail.js";
16
16
  import { readEmailSettings } from "./email-settings.js";
17
17
  import { mailboxReady } from "./mailbox.js";
18
18
  import { projectToolsOf } from "./project-tools.js";
19
- import { createTeammateFrom, nameOf } from "./teammate-admin.js";
20
- import { grantListed, grantTool } from "./teammate-tools.js";
21
- import { TEAMMATE_TEMPLATES } from "./teammates.js";
19
+ import { createSubagentFrom, nameOf } from "./subagent-admin.js";
20
+ import { grantListed, grantTool } from "./subagent-tools.js";
21
+ import { SUBAGENT_TEMPLATES } from "./subagents.js";
22
22
  export const KITS = [
23
23
  {
24
24
  id: "support-desk", name: "Support desk",
25
25
  promise: "Maya answers customer emails, looks orders up and refunds within limits you set. You approve each reply before it goes out.",
26
- teammate: { template: "support", handle: "maya" },
26
+ subagent: { template: "support", handle: "maya" },
27
27
  flowName: "Support desk",
28
28
  steps: [
29
- { id: "answer", title: "Maya answers", kind: "teammate", teammate: "maya",
29
+ { id: "answer", title: "Maya answers", kind: "subagent", subagent: "maya",
30
30
  instructions: "Read the customer's message. Look things up (and refund, within your rules) with your tools when it helps. Write the reply we'd send in \"text\". Pick Reply when it's ready for the customer, or Needs a person when your rules say to ask first or you can't help.",
31
31
  routes: [{ answer: "Reply", goesTo: "You check the reply" }, { answer: "Needs a person", goesTo: "For you" }], ifFails: "For you" },
32
32
  { id: "check", title: "You check the reply", kind: "approval", decider: "owner", next: "Send it", ifFails: "Maya answers" },
@@ -44,10 +44,10 @@ export const KITS = [
44
44
  {
45
45
  id: "bug-triage", name: "Bug triage",
46
46
  promise: "Theo reads every new issue, says what it is and how urgent, answers questions, and turns real bugs into fixes you approve.",
47
- teammate: { template: "triage", handle: "theo" },
47
+ subagent: { template: "triage", handle: "theo" },
48
48
  flowName: "Bug triage",
49
49
  steps: [
50
- { id: "sort", title: "Theo sorts it", kind: "teammate", teammate: "theo",
50
+ { id: "sort", title: "Theo sorts it", kind: "subagent", subagent: "theo",
51
51
  instructions: "Read the report. In \"text\", say in one or two sentences what it is and how urgent (for a bug, add what you'd check first; for a question, write the answer). Pick Bug for something broken in this project's code, Question for someone asking how something works, or Duplicate or noise for anything else, saying why.",
52
52
  routes: [{ answer: "Bug", goesTo: "Fix it" }, { answer: "Question", goesTo: "Answered" }, { answer: "Duplicate or noise", goesTo: "Closed" }], ifFails: "For you" },
53
53
  { id: "fix", title: "Fix it", kind: "task", planning: "auto", instructions: "Fix the bug this card reports. Theo's notes on it: {{stage.sort}}", next: "You review the fix" },
@@ -67,10 +67,10 @@ export const KITS = [
67
67
  {
68
68
  id: "sales-follow-up", name: "Sales follow-up",
69
69
  promise: "Leo writes back to every new lead within minutes, you approve the email, and it waits for their answer, so no lead goes cold.",
70
- teammate: { template: "sales", handle: "leo" },
70
+ subagent: { template: "sales", handle: "leo" },
71
71
  flowName: "Sales follow-up",
72
72
  steps: [
73
- { id: "write", title: "Leo writes back", kind: "teammate", teammate: "leo",
73
+ { id: "write", title: "Leo writes back", kind: "subagent", subagent: "leo",
74
74
  instructions: "Read the lead. In \"text\", write a short, friendly first reply that answers what they asked and suggests one clear next step. Pick Write back, or Not a fit (say why).",
75
75
  routes: [{ answer: "Write back", goesTo: "You check it" }, { answer: "Not a fit", goesTo: "Not a fit" }], ifFails: "Not a fit" },
76
76
  { id: "check", title: "You check it", kind: "approval", decider: "owner", next: "Send it", ifFails: "Leo writes back" },
@@ -87,10 +87,10 @@ export const KITS = [
87
87
  {
88
88
  id: "ops-requests", name: "Ops requests",
89
89
  promise: "Ada approves routine requests under $200 without you and brings you everything else, so the team gets answers the same day.",
90
- teammate: { template: "ops", handle: "ada" },
90
+ subagent: { template: "ops", handle: "ada" },
91
91
  flowName: "Ops requests",
92
92
  steps: [
93
- { id: "decide", title: "Ada decides", kind: "approval", teammate: "ada", decider: "owner", next: "Tell the team", ifFails: "Needs more" },
93
+ { id: "decide", title: "Ada decides", kind: "approval", subagent: "ada", decider: "owner", next: "Tell the team", ifFails: "Needs more" },
94
94
  { id: "tell", title: "Tell the team", kind: "notify", message: "Approved: {{card.title}}", next: "Done" },
95
95
  { id: "more", title: "Needs more", kind: "inbox" },
96
96
  { id: "done", title: "Done", kind: "done" },
@@ -104,22 +104,22 @@ export const KITS = [
104
104
  },
105
105
  ];
106
106
  export const kitOf = (id) => KITS.find(one => one.id === id) ?? null;
107
- /** A kit set up in a project: its flow (by name) and its teammate, when both are there. */
107
+ /** A kit set up in a project: its flow (by name) and its subagent, when both are there. */
108
108
  export function kitInstalled(store, kit, repo) {
109
- const mate = store.teammateByHandle(repo, kit.teammate.handle);
109
+ const mate = store.subagentByHandle(repo, kit.subagent.handle);
110
110
  const flow = store.listFlows([repo]).find(one => one.name === kit.flowName && one.state === "active") ?? null;
111
111
  return mate === null || flow === null ? null : { flow, mate };
112
112
  }
113
113
  /**
114
- * Set a kit up: its teammate (kept if one of that name is already there), its
115
- * flow, and its button triggers; then its teammate may use whichever of the
114
+ * Set a kit up: its subagent (kept if one of that name is already there), its
115
+ * flow, and its button triggers; then its subagent may use whichever of the
116
116
  * kit's tools the project already has (reading free, writing asking first).
117
117
  */
118
118
  export async function setUpKit(store, kit, repo, by, now, dir, io = {}) {
119
119
  const made = setUpKitNow(store, kit, repo, by, now, dir);
120
120
  if (!made.ok || made.said.endsWith("already set up here."))
121
121
  return made;
122
- const mate = store.getTeammate(made.teammate);
122
+ const mate = store.getSubagent(made.subagent);
123
123
  const present = new Set(projectToolsOf(store, repo).map(one => one.name));
124
124
  for (const tool of kit.tools.filter(one => present.has(one.tool))) {
125
125
  try {
@@ -129,20 +129,20 @@ export async function setUpKit(store, kit, repo, by, now, dir, io = {}) {
129
129
  }
130
130
  return made;
131
131
  }
132
- /** The same, all at once (a chat confirmation can't wait on a tool): its teammate is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
132
+ /** The same, all at once (a chat confirmation can't wait on a tool): its subagent is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
133
133
  export function setUpKitNow(store, kit, repo, by, now, dir, grantByName = false) {
134
134
  const had = kitInstalled(store, kit, repo);
135
135
  if (had !== null)
136
- return { ok: true, said: `${kit.name} is already set up here.`, flow: had.flow.id, teammate: had.mate.id };
137
- let mate = store.teammateByHandle(repo, kit.teammate.handle);
136
+ return { ok: true, said: `${kit.name} is already set up here.`, flow: had.flow.id, subagent: had.mate.id };
137
+ let mate = store.subagentByHandle(repo, kit.subagent.handle);
138
138
  if (mate === null) {
139
- const template = TEAMMATE_TEMPLATES.find(one => one.id === kit.teammate.template);
139
+ const template = SUBAGENT_TEMPLATES.find(one => one.id === kit.subagent.template);
140
140
  if (template === undefined)
141
- return { ok: false, said: "That kit's teammate template is missing." };
142
- const made = createTeammateFrom(store, { repo, template: template.id, by }, now);
141
+ return { ok: false, said: "That kit's subagent template is missing." };
142
+ const made = createSubagentFrom(store, { repo, template: template.id, by }, now);
143
143
  if (!made.ok)
144
144
  return { ok: false, said: made.said };
145
- mate = store.getTeammate(made.id);
145
+ mate = store.getSubagent(made.id);
146
146
  }
147
147
  let definition;
148
148
  try {
@@ -158,7 +158,7 @@ export function setUpKitNow(store, kit, repo, by, now, dir, grantByName = false)
158
158
  if (grantByName)
159
159
  for (const tool of projectToolsOf(store, repo).filter(one => kit.tools.some(each => each.tool === one.name)))
160
160
  grantListed(store, mate, tool, null, by, now);
161
- return { ok: true, said: `${kit.name} is ready: ${nameOf(mate)} works its ${kit.flowName} flow.`, flow: flowId, teammate: mate.id };
161
+ return { ok: true, said: `${kit.name} is ready: ${nameOf(mate)} works its ${kit.flowName} flow.`, flow: flowId, subagent: mate.id };
162
162
  }
163
163
  /** What's set up and what's left, read fresh each time. */
164
164
  export function kitChecklist(store, kit, repo, dir) {
@@ -167,7 +167,7 @@ export function kitChecklist(store, kit, repo, dir) {
167
167
  return [];
168
168
  const name = nameOf(set.mate);
169
169
  const steps = [
170
- { id: "teammate", done: true, said: `${name} joined the team`, href: `/teammates/${set.mate.id}` },
170
+ { id: "subagent", done: true, said: `${name} joined the team`, href: `/settings/lead/subagents/${set.mate.id}` },
171
171
  { id: "flow", done: true, said: `The ${kit.flowName} flow is ready`, href: `/flows/${set.flow.id}` },
172
172
  ];
173
173
  if (kit.email === true) {
@@ -184,18 +184,18 @@ export function kitChecklist(store, kit, repo, dir) {
184
184
  const tools = projectToolsOf(store, repo);
185
185
  for (const tool of kit.tools) {
186
186
  const connected = tools.some(one => one.name === tool.tool);
187
- const granted = store.teammateGrant(set.mate.id, tool.tool) !== null;
187
+ const granted = store.subagentGrant(set.mate.id, tool.tool) !== null;
188
188
  steps.push(connected && granted
189
- ? { id: `tool-${tool.tool}`, done: true, said: `${name} can use ${tool.label}`, href: `/teammates/${set.mate.id}#tools` }
189
+ ? { id: `tool-${tool.tool}`, done: true, said: `${name} can use ${tool.label}`, href: `/settings/lead/subagents/${set.mate.id}#tools` }
190
190
  : connected
191
- ? { id: `tool-${tool.tool}`, done: false, said: `Let ${name} use ${tool.label}, ${tool.why}`, href: `/teammates/${set.mate.id}#tools` }
191
+ ? { id: `tool-${tool.tool}`, done: false, said: `Let ${name} use ${tool.label}, ${tool.why}`, href: `/settings/lead/subagents/${set.mate.id}#tools` }
192
192
  : { id: `tool-${tool.tool}`, done: false, said: `Connect ${tool.label}, ${tool.why}`, href: `/settings/tools?repo=${encodeURIComponent(repo)}&kit=${kit.id}&connect=${tool.tool}#connect`, action: "connect", tool: tool.tool });
193
193
  }
194
194
  const tried = store.flowCards(set.flow.id, true).length > 0;
195
195
  steps.push({ id: "sample", done: tried, said: tried ? `${name} has worked a card` : `See ${name} work a sample card`, href: tried ? `/flows/${set.flow.id}` : null, ...(tried ? {} : { action: "sample" }) });
196
196
  return steps;
197
197
  }
198
- /** A sample card in the kit's first zone, so its teammate starts on it at once. */
198
+ /** A sample card in the kit's first zone, so its subagent starts on it at once. */
199
199
  export function addKitSample(store, kit, repo, by, now) {
200
200
  const set = kitInstalled(store, kit, repo);
201
201
  if (set === null)
@@ -1,16 +1,16 @@
1
- import { type MateProposal, type Store } from "./store.js";
1
+ import { type LeadProposal, type Store } from "./store.js";
2
2
  import { type ShapeOptions } from "./reply-shape.js";
3
- import type { SubscriptionMateRunner } from "./subscription-chat.js";
4
- export type MateCliSeams = {
3
+ import type { SubscriptionLeadRunner } from "./subscription-chat.js";
4
+ export type LeadCliSeams = {
5
5
  fetcher?: typeof fetch;
6
6
  env?: Record<string, string | undefined>;
7
7
  /** Lines the REPL reads instead of stdin (tests). */
8
8
  lines?: AsyncIterable<string> | Iterable<string>;
9
9
  clock?: () => Date;
10
10
  /** Subscription harness seam; tests never consume a real membership turn. */
11
- subscriptionRunner?: SubscriptionMateRunner;
11
+ subscriptionRunner?: SubscriptionLeadRunner;
12
12
  };
13
- export type MateCliInput = {
13
+ export type LeadCliInput = {
14
14
  store: Store;
15
15
  databaseFile: string;
16
16
  write: (line: string) => void;
@@ -25,18 +25,18 @@ export type MateCliInput = {
25
25
  end: boolean;
26
26
  follow?: boolean;
27
27
  ceilingUsd: number | undefined;
28
- seams?: MateCliSeams;
28
+ seams?: LeadCliSeams;
29
29
  /** Where evidence lives — a scout's report reads from here. */
30
30
  evidenceRoot?: string;
31
31
  /** The console's address(es): a reply's links there are named as its pages ("the task"), not by host. */
32
32
  appOrigin?: ShapeOptions["appOrigin"];
33
33
  };
34
- export type MateCliResult = {
34
+ export type LeadCliResult = {
35
35
  code: number;
36
36
  reason?: string;
37
37
  message?: string;
38
38
  };
39
- export declare const MATE_CLI_EXIT: {
39
+ export declare const LEAD_CLI_EXIT: {
40
40
  readonly ok: 0;
41
41
  readonly failed: 1;
42
42
  readonly usage: 2;
@@ -49,7 +49,7 @@ export declare const MATE_CLI_EXIT: {
49
49
  */
50
50
  export declare function answerContextLines(store: Store, payload: Record<string, unknown>): string[];
51
51
  /** One line per proposal, numbered in thread order, for the operator to name. */
52
- export declare function proposalLines(proposals: readonly MateProposal[], repos: readonly string[], ordinal?: (proposal: MateProposal) => number): string[];
52
+ export declare function proposalLines(proposals: readonly LeadProposal[], repos: readonly string[], ordinal?: (proposal: LeadProposal) => number): string[];
53
53
  /** The lines for one proposal, its answer context included when it is an answer. */
54
- export declare function proposalBlock(store: Store, proposal: MateProposal, repos: readonly string[], number: number): string[];
55
- export declare function runMateCli(input: MateCliInput): Promise<MateCliResult>;
54
+ export declare function proposalBlock(store: Store, proposal: LeadProposal, repos: readonly string[], number: number): string[];
55
+ export declare function runLeadCli(input: LeadCliInput): Promise<LeadCliResult>;
@@ -1,7 +1,7 @@
1
1
  import { configureLeadFollow, leadFollowStatus } from './lead-follow.js';
2
2
  /**
3
3
  * `toolroll chat` (mate arc §6): the same thread the console shows,
4
- * driven from a terminal. The password is typed once — it mints the mate
4
+ * driven from a terminal. The password is typed once — it mints the lead
5
5
  * session, the one ceremony a conversation gets — and every later turn
6
6
  * debits that session without asking again. Confirming a card runs the
7
7
  * same doors the console runs; password-class acts (approving a scope,
@@ -10,16 +10,16 @@ import { configureLeadFollow, leadFollowStatus } from './lead-follow.js';
10
10
  import { createHash } from "node:crypto";
11
11
  import { readFileSync } from "node:fs";
12
12
  import { dirname, join } from "node:path";
13
- import { MATE_ASK_OTHER } from "./store.js";
13
+ import { LEAD_ASK_OTHER } from "./store.js";
14
14
  import { CHAT_KEY_ENV, credentialKeyOf, isDirectChatProvider, priceForConfig, subscriptionCredentialKey } from "./converse.js";
15
15
  import { verifyApproverByPassword } from "./principal.js";
16
- import { runMateTurn } from "./mate.js";
16
+ import { runLeadTurn } from "./lead.js";
17
17
  import { voiceReply } from "./reply-shape.js";
18
- import { confirmMateProposal, dismissMateProposal } from "./mate-doors.js";
18
+ import { confirmLeadProposal, dismissLeadProposal } from "./lead-doors.js";
19
19
  import { projectName } from "./project.js";
20
20
  import { CHAT_CONTROLS, chatControlHref, isChatControl } from "./chat-controls.js";
21
21
  import { CHAT_TASK_ACTIONS, isChatTaskAction } from "./chat-task-actions.js";
22
- export const MATE_CLI_EXIT = { ok: 0, failed: 1, usage: 2, refused: 3 };
22
+ export const LEAD_CLI_EXIT = { ok: 0, failed: 1, usage: 2, refused: 3 };
23
23
  function money(microusd) {
24
24
  return `$${(microusd / 1_000_000).toFixed(2)}`;
25
25
  }
@@ -119,7 +119,7 @@ async function* linesOf(seams) {
119
119
  reader.close();
120
120
  }
121
121
  }
122
- export async function runMateCli(input) {
122
+ export async function runLeadCli(input) {
123
123
  const { store, write, json } = input;
124
124
  const seams = input.seams ?? {};
125
125
  const clock = seams.clock ?? (() => new Date());
@@ -132,7 +132,7 @@ export async function runMateCli(input) {
132
132
  if (json)
133
133
  write(JSON.stringify({ command: "chat", ...envelope }));
134
134
  };
135
- const refuse = (reason, message, code = MATE_CLI_EXIT.refused) => {
135
+ const refuse = (reason, message, code = LEAD_CLI_EXIT.refused) => {
136
136
  if (json)
137
137
  write(JSON.stringify({ ok: false, command: "chat", reason, message }));
138
138
  else
@@ -154,22 +154,22 @@ export async function runMateCli(input) {
154
154
  return refuse("no-key", `no ${directProvider} key — export ${CHAT_KEY_ENV[directProvider]}, or paste one on the console's chat page`);
155
155
  const repos = [...input.repos];
156
156
  if (repos.length === 0)
157
- return refuse("empty-ceiling", "The lead has no projects to look at. Name some with --repo, or add projects in the console.", MATE_CLI_EXIT.usage);
157
+ return refuse("empty-ceiling", "The lead has no projects to look at. Name some with --repo, or add projects in the console.", LEAD_CLI_EXIT.usage);
158
158
  const verified = verifyApproverByPassword(store, input.credentials.name, input.credentials.token, repos);
159
159
  if (!verified.ok)
160
160
  return refuse("unauthenticated", "that is not an approver, or the password does not match");
161
161
  const who = verified.who;
162
162
  let now = clock();
163
163
  if (input.end) {
164
- const turns = store.failLiveMateTurnsFor(who.name, "ended", now);
165
- const sessions = store.endMateSessionsFor(who.name, who.name, now);
166
- const threads = store.closeMateThreadsFor(who.name, now);
164
+ const turns = store.failLiveLeadTurnsFor(who.name, "ended", now);
165
+ const sessions = store.endLeadSessionsFor(who.name, who.name, now);
166
+ const threads = store.closeLeadThreadsFor(who.name, now);
167
167
  emit({ ok: true, ended: { sessions, threads, turns } });
168
168
  say(sessions === 0 ? "No conversation was open, so there was nothing to end." : "The conversation has ended and its history is forgotten.");
169
- return { code: MATE_CLI_EXIT.ok };
169
+ return { code: LEAD_CLI_EXIT.ok };
170
170
  }
171
- store.sweepStaleMateTurns(now);
172
- let session = store.activeMateSession(who.name);
171
+ store.sweepStaleLeadTurns(now);
172
+ let session = store.activeLeadSession(who.name);
173
173
  const credentialKey = direct ? credentialKeyOf(directProvider, key) : subscriptionCredentialKey(subscriptionProvider);
174
174
  if (session !== null && session.credentialKey !== credentialKey) {
175
175
  // A session minted under another provider key cannot be spent by this
@@ -177,38 +177,38 @@ export async function runMateCli(input) {
177
177
  return refuse("key-mismatch", "The open conversation was started with a different provider key. Use that key, or end it with --end and start a new one.");
178
178
  }
179
179
  if (session !== null && session.ceilingDigest !== who.ceilingDigest) {
180
- store.endMateSession(session.id, who.name, now);
181
- store.closeMateThreadsFor(who.name, now);
180
+ store.endLeadSession(session.id, who.name, now);
181
+ store.closeLeadThreadsFor(who.name, now);
182
182
  say("The projects you named differ from the open conversation's, so it ended. Starting a new one.");
183
183
  session = null;
184
184
  }
185
185
  if (session === null) {
186
186
  const ceilingUsd = direct ? (input.ceilingUsd ?? 5) : 0;
187
187
  if (direct && (!Number.isFinite(ceilingUsd) || ceilingUsd <= 0 || ceilingUsd > 1_000))
188
- return refuse("usage", "--ceiling-usd is a dollar amount between 0 and 1000", MATE_CLI_EXIT.usage);
188
+ return refuse("usage", "--ceiling-usd is a dollar amount between 0 and 1000", LEAD_CLI_EXIT.usage);
189
189
  const ceilingMicrousd = Math.round(ceilingUsd * 1_000_000);
190
190
  const termsDigest = createHash("sha256").update(`${ceilingMicrousd}\n${who.ceilingDigest}`).digest("hex");
191
- const id = store.mintMateSession({ approver: who.name, approverGeneration: who.generation, credentialKey, ceilingMicrousd, ceilingDigest: who.ceilingDigest, termsDigest }, now);
192
- session = store.getMateSession(id);
191
+ const id = store.mintLeadSession({ approver: who.name, approverGeneration: who.generation, credentialKey, ceilingMicrousd, ceilingDigest: who.ceilingDigest, termsDigest }, now);
192
+ session = store.getLeadSession(id);
193
193
  if (session === null)
194
- return refuse("failed", "A new conversation couldn't be started. Try again.", MATE_CLI_EXIT.failed);
194
+ return refuse("failed", "A new conversation couldn't be started. Try again.", LEAD_CLI_EXIT.failed);
195
195
  if (!direct && input.ceilingUsd !== undefined)
196
196
  say("the supplied --ceiling-usd value is ignored for membership usage");
197
- say(`mate conversation started: ${direct ? `up to ${money(ceilingMicrousd)}` : "subscription usage (no dollar limit)"} over ${repos.map(one => projectName(one)).join(", ")} — live until you end it`);
197
+ say(`lead conversation started: ${direct ? `up to ${money(ceilingMicrousd)}` : "subscription usage (no dollar limit)"} over ${repos.map(one => projectName(one)).join(", ")} — live until you end it`);
198
198
  if (direct)
199
199
  say(`(the weekly chat limit, ${money(config.weeklyCeilingMicrousd)}, still applies)`);
200
200
  }
201
201
  else {
202
- say(`mate conversation live: ${direct ? `${money(session.spentMicrousd)} of ${money(session.ceilingMicrousd)} spent` : "subscription usage (no dollar limit)"} — live until you end it`);
202
+ say(`lead conversation live: ${direct ? `${money(session.spentMicrousd)} of ${money(session.ceilingMicrousd)} spent` : "subscription usage (no dollar limit)"} — live until you end it`);
203
203
  }
204
- const thread = store.openMateThread(who.name, who.ceilingDigest, now).thread;
204
+ const thread = store.openLeadThread(who.name, who.ceilingDigest, now).thread;
205
205
  if (input.follow !== undefined) {
206
206
  if (!configureLeadFollow(store, who, session, thread, input.follow, now))
207
207
  return refuse("standing", "Conversation access changed.");
208
208
  say(leadFollowStatus(store, who.name).detail);
209
209
  emit({ ok: true, follow: leadFollowStatus(store, who.name) });
210
210
  }
211
- const pendingProposals = () => store.listMateProposals(thread.id, ["pending"]);
211
+ const pendingProposals = () => store.listLeadProposals(thread.id, ["pending"]);
212
212
  // Ordinals are assigned once per proposal and never reused within this
213
213
  // run (slice-2 review, finding 4): `confirm 2` means the card printed as
214
214
  // 2, whatever the console did to its neighbours meanwhile.
@@ -224,7 +224,7 @@ export async function runMateCli(input) {
224
224
  const byOrdinal = (ordinal) => {
225
225
  for (const [id, n] of ordinals)
226
226
  if (n === ordinal)
227
- return store.getMateProposal(id);
227
+ return store.getLeadProposal(id);
228
228
  return null;
229
229
  };
230
230
  const printProposals = () => {
@@ -239,12 +239,12 @@ export async function runMateCli(input) {
239
239
  say(line);
240
240
  };
241
241
  const turn = async (message) => {
242
- const live = store.activeMateSession(who.name);
242
+ const live = store.activeLeadSession(who.name);
243
243
  if (live === null) {
244
244
  const outcome = { ok: false, refused: "session-ended", message: "This conversation has ended. Run chat again to start a new one." };
245
245
  return outcome;
246
246
  }
247
- return runMateTurn({ store, who, session: live, thread, config, key, message, channel: "terminal", ...(seams.fetcher === undefined ? {} : { fetcher: seams.fetcher }), ...(seams.subscriptionRunner === undefined ? {} : { subscriptionRunner: seams.subscriptionRunner }), ...(input.evidenceRoot === undefined ? {} : { evidenceRoot: input.evidenceRoot }), clock });
247
+ return runLeadTurn({ store, who, session: live, thread, config, key, message, channel: "terminal", ...(seams.fetcher === undefined ? {} : { fetcher: seams.fetcher }), ...(seams.subscriptionRunner === undefined ? {} : { subscriptionRunner: seams.subscriptionRunner }), ...(input.evidenceRoot === undefined ? {} : { evidenceRoot: input.evidenceRoot }), clock });
248
248
  };
249
249
  const report = (outcome, message) => {
250
250
  if (outcome.ok && outcome.replayed) {
@@ -253,14 +253,14 @@ export async function runMateCli(input) {
253
253
  return;
254
254
  }
255
255
  if (outcome.ok) {
256
- const ask = store.mateAsk(outcome.turn);
256
+ const ask = store.leadAsk(outcome.turn);
257
257
  emit({ ok: true, turn: outcome.turn, reply: outcome.reply, activity: outcome.activity, steps: outcome.steps, settledMicrousd: outcome.settledMicrousd, proposals: pendingProposals().map(one => ({ id: one.id, ordinal: ordinalOf(one), kind: one.kind, payload: one.payload })),
258
- ...(ask === null ? {} : { ask: { question: ask.question, options: [...ask.options, MATE_ASK_OTHER] } }) });
258
+ ...(ask === null ? {} : { ask: { question: ask.question, options: [...ask.options, LEAD_ASK_OTHER] } }) });
259
259
  say(` ${outcome.activity}`);
260
260
  say(voiceReply(outcome.reply, "terminal", { appOrigin: input.appOrigin ?? null, ...(message === undefined ? {} : { asked: message }) }));
261
261
  // The lead's question: the terminal has no buttons, so the options are listed to type back.
262
262
  if (ask !== null)
263
- say(`${ask.question}\n${ask.options.map(one => ` · ${one}`).join("\n")}\n · ${MATE_ASK_OTHER} (type your answer)`);
263
+ say(`${ask.question}\n${ask.options.map(one => ` · ${one}`).join("\n")}\n · ${LEAD_ASK_OTHER} (type your answer)`);
264
264
  printProposals();
265
265
  return;
266
266
  }
@@ -270,7 +270,7 @@ export async function runMateCli(input) {
270
270
  if (input.say !== undefined) {
271
271
  const outcome = await turn(input.say);
272
272
  report(outcome, input.say);
273
- return { code: outcome.ok ? MATE_CLI_EXIT.ok : MATE_CLI_EXIT.refused };
273
+ return { code: outcome.ok ? LEAD_CLI_EXIT.ok : LEAD_CLI_EXIT.refused };
274
274
  }
275
275
  // The REPL. Text is a turn; a few words are acts on the cards.
276
276
  say("say something, or: proposals · confirm N · dismiss N · open N · end · quit");
@@ -311,12 +311,12 @@ export async function runMateCli(input) {
311
311
  openTask(proposal);
312
312
  }
313
313
  else if (verb === "dismiss") {
314
- const done = dismissMateProposal(store, who, proposal.id, now);
314
+ const done = dismissLeadProposal(store, who, proposal.id, now);
315
315
  emit({ ok: done, act: "dismiss", proposal: proposal.id });
316
316
  say(done ? `dismissed ${act[2]}` : "that proposal was already acted on");
317
317
  }
318
318
  else {
319
- const outcome = confirmMateProposal(store, who, proposal.id, now, { confirm: act[3] !== undefined, via: "cli", chatProvider: () => {
319
+ const outcome = confirmLeadProposal(store, who, proposal.id, now, { confirm: act[3] !== undefined, via: "cli", chatProvider: () => {
320
320
  const current = store.getChatConfig();
321
321
  return current === null ? null : { config: current, key: isDirectChatProvider(current.provider) ? keyFor(current, input.databaseFile, env) : null };
322
322
  }, ...(input.evidenceRoot === undefined ? {} : { evidenceRoot: input.evidenceRoot }) });
@@ -338,12 +338,12 @@ export async function runMateCli(input) {
338
338
  if (word === "quit" || word === "exit")
339
339
  break;
340
340
  if (word === "end") {
341
- store.failLiveMateTurnsFor(who.name, "ended", now);
342
- store.endMateSessionsFor(who.name, who.name, now);
343
- store.closeMateThreadsFor(who.name, now);
341
+ store.failLiveLeadTurnsFor(who.name, "ended", now);
342
+ store.endLeadSessionsFor(who.name, who.name, now);
343
+ store.closeLeadThreadsFor(who.name, now);
344
344
  say("The conversation has ended and its history is forgotten.");
345
345
  emit({ ok: true, ended: true });
346
- return { code: MATE_CLI_EXIT.ok };
346
+ return { code: LEAD_CLI_EXIT.ok };
347
347
  }
348
348
  if (word === "help" || word === "?") {
349
349
  say("say something, or: proposals · confirm N · dismiss N · open N · end · quit");
@@ -351,5 +351,5 @@ export async function runMateCli(input) {
351
351
  }
352
352
  report(await turn(line), line);
353
353
  }
354
- return { code: MATE_CLI_EXIT.ok };
354
+ return { code: LEAD_CLI_EXIT.ok };
355
355
  }
@@ -90,7 +90,7 @@ export function getCommitment(store, id) {
90
90
  /** The reply that made a promise was shown: its turn is over, and it was answered or its text reached the conversation
91
91
  * before it failed. A turn still running has shown nothing yet, whatever it has written so far. */
92
92
  const SHOWN = (turn) => `EXISTS (SELECT 1 FROM mate_turn t WHERE t.id = ${turn} AND (t.state = 'answered'
93
- OR t.state = 'failed' AND EXISTS (SELECT 1 FROM mate_message m WHERE m.turn = t.id AND m.role = 'assistant')))`;
93
+ OR t.state = 'failed' AND EXISTS (SELECT 1 FROM lead_message m WHERE m.turn = t.id AND m.role = 'assistant')))`;
94
94
  /** A promise only counts once the reply that made it was shown: one from a reply still being written, or one that
95
95
  * failed without reaching the owner, was never heard. */
96
96
  const HEARD = `(c.turn IS NULL OR ${SHOWN('c.turn')})`;
@@ -173,7 +173,7 @@ export function checkLeadCommitments(store, now, root) {
173
173
  continue;
174
174
  }
175
175
  // A reply still being written may yet be delivered; one that was not is dropped above.
176
- const turn = one.turn === null ? null : store.getMateTurn(one.turn);
176
+ const turn = one.turn === null ? null : store.getLeadTurn(one.turn);
177
177
  if (turn !== null && (turn.state === 'queued' || turn.state === 'running'))
178
178
  continue;
179
179
  const account = store.accountOf(one.owner);
@@ -181,7 +181,7 @@ export function checkLeadCommitments(store, now, root) {
181
181
  close('cancelled', 'Access to this project ended.');
182
182
  continue;
183
183
  }
184
- const thread = store.getMateThread(one.thread);
184
+ const thread = store.getLeadThread(one.thread);
185
185
  if (thread === null || thread.approver !== one.owner || thread.closedAt !== null) {
186
186
  close('cancelled', 'The conversation it was promised in was closed.');
187
187
  continue;
@@ -203,7 +203,7 @@ export function checkLeadCommitments(store, now, root) {
203
203
  return;
204
204
  // The shared conversation always keeps the line; a promise made on a phone or team chat is also said there, as
205
205
  // the lead's own message to its owner, on that chat alone (the usual delivery receipts apply).
206
- store.appendMateMessage({ thread: one.thread, turn: null, role: 'assistant', text: line }, now);
206
+ store.appendLeadMessage({ thread: one.thread, turn: null, role: 'assistant', text: line }, now);
207
207
  if (one.channel !== 'chat')
208
208
  store.enqueueNotification({ dedupeKey: `${PROMISE_KEY}${one.channel}:${one.id}`, kind: LEAD_SAY_KIND, subject: leadNameOf(store, one.owner),
209
209
  body: line.slice(0, 300), recipient: one.owner, source: { installation: true } }, now);