toolroll 0.9.65 → 0.9.68

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 (264) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +20 -2
  3. package/dist/acp-client.js +1 -3
  4. package/dist/agent-board.d.ts +0 -1
  5. package/dist/agent-board.js +0 -1
  6. package/dist/agent-fence.d.ts +69 -2
  7. package/dist/agent-fence.js +294 -11
  8. package/dist/agentconfig.js +4 -1
  9. package/dist/batch-checks.js +3 -2
  10. package/dist/browser/THIRD_PARTY_NOTICES.txt +46 -0
  11. package/dist/browser/terminal.js +134 -23
  12. package/dist/browser/workspace.css +2 -2
  13. package/dist/browser/workspace.js +31 -29
  14. package/dist/builder.d.ts +4 -0
  15. package/dist/builder.js +56 -37
  16. package/dist/canonical-json.d.ts +14 -0
  17. package/dist/canonical-json.js +36 -0
  18. package/dist/chat-actions.js +1 -2
  19. package/dist/chat-admission.d.ts +19 -0
  20. package/dist/chat-admission.js +22 -0
  21. package/dist/chat-channel.js +1 -1
  22. package/dist/chat-delivery.js +0 -1
  23. package/dist/chat-follow.d.ts +17 -0
  24. package/dist/chat-follow.js +32 -0
  25. package/dist/chat-messages.js +0 -1
  26. package/dist/chat-settings-page.d.ts +23 -0
  27. package/dist/chat-settings-page.js +41 -0
  28. package/dist/claim.js +3 -6
  29. package/dist/claude-print.d.ts +12 -0
  30. package/dist/claude-print.js +34 -0
  31. package/dist/cli-http.d.ts +0 -7
  32. package/dist/cli-http.js +0 -21
  33. package/dist/cli.d.ts +3 -10
  34. package/dist/cli.js +15 -24
  35. package/dist/coding-provider.js +2 -1
  36. package/dist/coding-workspace.js +1 -1
  37. package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
  38. package/dist/connect-cli.js +331 -0
  39. package/dist/containment.d.ts +0 -2
  40. package/dist/containment.js +2 -6
  41. package/dist/contracts/chat-actions.d.ts +0 -1
  42. package/dist/contracts/chat-content.d.ts +0 -4
  43. package/dist/contracts/chat-content.js +0 -2
  44. package/dist/contracts/chat-tables.d.ts +0 -1
  45. package/dist/contracts/cli.d.ts +0 -62
  46. package/dist/contracts/cli.js +0 -4
  47. package/dist/contracts/coding-workspace.js +1 -1
  48. package/dist/contracts/console-api.d.ts +1 -0
  49. package/dist/contracts/console-api.js +1 -0
  50. package/dist/contracts/contract.js +1 -1
  51. package/dist/contracts/flow-card.d.ts +0 -1
  52. package/dist/contracts/flow-propose.d.ts +0 -1
  53. package/dist/contracts/flow-send.js +1 -1
  54. package/dist/contracts/gateway-tools.d.ts +0 -1
  55. package/dist/contracts/integration-metadata.js +1 -1
  56. package/dist/contracts/lead-tools.d.ts +0 -1
  57. package/dist/contracts/memory-pass.d.ts +0 -1
  58. package/dist/contracts/memory-pass.js +1 -1
  59. package/dist/contracts/plan.js +1 -1
  60. package/dist/contracts/project-knowledge.js +1 -1
  61. package/dist/contracts/project-skills.d.ts +0 -1
  62. package/dist/contracts/proof.js +1 -1
  63. package/dist/contracts/recipes.js +1 -1
  64. package/dist/contracts/scope.js +1 -1
  65. package/dist/contracts/scout-report.js +1 -1
  66. package/dist/contracts/teams-callback.d.ts +0 -1
  67. package/dist/converse.d.ts +0 -6
  68. package/dist/converse.js +0 -19
  69. package/dist/daemon.js +3 -2
  70. package/dist/decision.d.ts +1 -3
  71. package/dist/deprecations.d.ts +12 -4
  72. package/dist/deprecations.js +27 -4
  73. package/dist/desktop-update-recovery.js +1 -1
  74. package/dist/desktop-update.js +3 -2
  75. package/dist/discord-chat.js +4 -15
  76. package/dist/discord-settings.d.ts +2 -6
  77. package/dist/discord-settings.js +10 -38
  78. package/dist/discord.js +12 -23
  79. package/dist/evidence.d.ts +0 -1
  80. package/dist/evidence.js +0 -3
  81. package/dist/exec.d.ts +0 -9
  82. package/dist/exec.js +3 -81
  83. package/dist/flow-actions.js +0 -3
  84. package/dist/flow-draft.d.ts +1 -3
  85. package/dist/flow-draft.js +15 -28
  86. package/dist/flow-scripts.d.ts +1 -8
  87. package/dist/flow-scripts.js +0 -13
  88. package/dist/flow-send.js +1 -1
  89. package/dist/flow-share.d.ts +0 -2
  90. package/dist/flow-share.js +1 -6
  91. package/dist/flow-steps.js +1 -1
  92. package/dist/flow-triggers.d.ts +0 -1
  93. package/dist/flow-triggers.js +1 -2
  94. package/dist/flow-unattended.js +1 -12
  95. package/dist/flows.js +1 -1
  96. package/dist/health-cli.d.ts +2 -2
  97. package/dist/health-cli.js +1 -1
  98. package/dist/invoke.d.ts +18 -3
  99. package/dist/invoke.js +142 -17
  100. package/dist/is-record.d.ts +2 -0
  101. package/dist/is-record.js +2 -0
  102. package/dist/lead-doors.d.ts +1 -5
  103. package/dist/lead-doors.js +0 -4
  104. package/dist/lead-tools.js +3 -6
  105. package/dist/live-detail.d.ts +0 -1
  106. package/dist/live-detail.js +0 -6
  107. package/dist/live-terminal.d.ts +24 -13
  108. package/dist/live-terminal.js +81 -43
  109. package/dist/live.d.ts +0 -1
  110. package/dist/live.js +1 -2
  111. package/dist/mcp-core.js +0 -2
  112. package/dist/memory-pass.js +1 -1
  113. package/dist/model-catalog.js +1 -1
  114. package/dist/modes.js +1 -12
  115. package/dist/operate.d.ts +2 -0
  116. package/dist/operate.js +436 -745
  117. package/dist/password-bearer.d.ts +0 -2
  118. package/dist/password-bearer.js +0 -4
  119. package/dist/peek-cli.js +2 -1
  120. package/dist/peek.d.ts +2 -26
  121. package/dist/peek.js +2 -168
  122. package/dist/phase-routing.d.ts +0 -4
  123. package/dist/phase-routing.js +2 -21
  124. package/dist/planner-source.d.ts +2 -1
  125. package/dist/planner-source.js +2 -12
  126. package/dist/planner.js +2 -14
  127. package/dist/process-tree.d.ts +0 -2
  128. package/dist/process-tree.js +0 -10
  129. package/dist/project-delete-ui.d.ts +6 -0
  130. package/dist/project-delete-ui.js +20 -1
  131. package/dist/project-delete.d.ts +0 -2
  132. package/dist/project-delete.js +1 -3
  133. package/dist/project-learning.d.ts +0 -14
  134. package/dist/project-skills.d.ts +0 -1
  135. package/dist/project-skills.js +0 -14
  136. package/dist/project-tools.js +2 -10
  137. package/dist/provider.d.ts +0 -17
  138. package/dist/provider.js +0 -26
  139. package/dist/pulls.d.ts +0 -2
  140. package/dist/pulls.js +0 -9
  141. package/dist/release-adapters.d.ts +9 -0
  142. package/dist/release-adapters.js +81 -4
  143. package/dist/release.d.ts +7 -1
  144. package/dist/release.js +20 -7
  145. package/dist/remote-exec.d.ts +3 -2
  146. package/dist/remote-exec.js +3 -2
  147. package/dist/repos.d.ts +0 -5
  148. package/dist/repos.js +2 -10
  149. package/dist/repository-context.d.ts +0 -2
  150. package/dist/repository-context.js +0 -4
  151. package/dist/restart-certification.d.ts +0 -2
  152. package/dist/restart-certification.js +1 -5
  153. package/dist/result-follow-ups.d.ts +1 -4
  154. package/dist/result-follow-ups.js +4 -8
  155. package/dist/result-review.d.ts +0 -2
  156. package/dist/result-review.js +0 -2
  157. package/dist/retention.d.ts +0 -1
  158. package/dist/retention.js +0 -1
  159. package/dist/review-context.d.ts +0 -1
  160. package/dist/review-context.js +1 -12
  161. package/dist/reviewer.d.ts +0 -16
  162. package/dist/reviewer.js +0 -18
  163. package/dist/run-closeout.js +2 -1
  164. package/dist/scope.d.ts +13 -0
  165. package/dist/scope.js +11 -18
  166. package/dist/scout-browser.js +2 -1
  167. package/dist/serve.js +3 -2
  168. package/dist/server/chrome.d.ts +10 -1
  169. package/dist/server/chrome.js +45 -4
  170. package/dist/server/console.css +60 -137
  171. package/dist/server/flows.js +2 -2
  172. package/dist/server/http.d.ts +2 -0
  173. package/dist/server/http.js +5 -0
  174. package/dist/server/pages.js +2 -2
  175. package/dist/server/people-tokens.js +3 -4
  176. package/dist/server/remote.js +1 -6
  177. package/dist/server/render-chat.d.ts +9 -2
  178. package/dist/server/render-chat.js +53 -7
  179. package/dist/server/render-pages.d.ts +28 -3
  180. package/dist/server/render-pages.js +78 -9
  181. package/dist/server/render-results.d.ts +0 -6
  182. package/dist/server/render-results.js +3 -9
  183. package/dist/server/render-tasks.js +6 -6
  184. package/dist/server/route-table.d.ts +0 -4
  185. package/dist/server/route-table.js +1 -6
  186. package/dist/server/settings.js +43 -22
  187. package/dist/server/task-views.js +1 -1
  188. package/dist/server/tasks.js +10 -7
  189. package/dist/setup-guide.d.ts +2 -2
  190. package/dist/skills.d.ts +0 -6
  191. package/dist/skills.js +0 -8
  192. package/dist/slack-chat.d.ts +1 -7
  193. package/dist/slack-chat.js +5 -18
  194. package/dist/slack-settings.d.ts +2 -6
  195. package/dist/slack-settings.js +10 -38
  196. package/dist/slack.js +12 -23
  197. package/dist/sleep.d.ts +2 -0
  198. package/dist/sleep.js +2 -0
  199. package/dist/store.d.ts +11 -74
  200. package/dist/store.js +36 -179
  201. package/dist/structured-output.d.ts +0 -1
  202. package/dist/structured-output.js +0 -1
  203. package/dist/subagent-work.d.ts +0 -2
  204. package/dist/subagent-work.js +0 -2
  205. package/dist/subagents.d.ts +1 -3
  206. package/dist/subagents.js +20 -33
  207. package/dist/subscription-chat.d.ts +1 -3
  208. package/dist/subscription-chat.js +2 -3
  209. package/dist/task-sizing.d.ts +1 -4
  210. package/dist/task-sizing.js +3 -10
  211. package/dist/teams-chat.js +4 -11
  212. package/dist/teams.js +12 -19
  213. package/dist/teardown-git.d.ts +22 -0
  214. package/dist/teardown-git.js +136 -2
  215. package/dist/telegram-lead.js +2 -2
  216. package/dist/telegram.js +1 -1
  217. package/dist/token-notices.d.ts +0 -11
  218. package/dist/token-notices.js +1 -5
  219. package/dist/tool-broker.d.ts +12 -0
  220. package/dist/tool-broker.js +66 -2
  221. package/dist/tool-secret-store.d.ts +0 -3
  222. package/dist/tool-secret-store.js +2 -11
  223. package/dist/toolroll-update.d.ts +0 -2
  224. package/dist/toolroll-update.js +2 -2
  225. package/dist/unfenced-test-support.d.ts +2 -0
  226. package/dist/unfenced-test-support.js +11 -0
  227. package/dist/verification-evidence.d.ts +0 -1
  228. package/dist/verification-evidence.js +0 -1
  229. package/dist/webhooks.d.ts +0 -1
  230. package/dist/webhooks.js +0 -1
  231. package/dist/workspace-ui.d.ts +0 -8
  232. package/dist/workspace-ui.js +1 -6
  233. package/dist/writes-mode.d.ts +9 -0
  234. package/dist/writes-mode.js +8 -0
  235. package/package.json +5 -1
  236. package/dist/contracts/native-census.d.ts +0 -42
  237. package/dist/contracts/native-census.js +0 -36
  238. package/dist/process-recovery-anchor.d.ts +0 -75
  239. package/dist/process-recovery-anchor.js +0 -188
  240. package/dist/process-recovery-coalition.d.ts +0 -25
  241. package/dist/process-recovery-coalition.js +0 -105
  242. package/dist/process-recovery-eligibility.d.ts +0 -179
  243. package/dist/process-recovery-eligibility.js +0 -174
  244. package/dist/process-recovery-native.d.ts +0 -161
  245. package/dist/process-recovery-native.js +0 -595
  246. package/dist/process-recovery-provenance.d.ts +0 -163
  247. package/dist/process-recovery-provenance.js +0 -292
  248. package/dist/process-recovery-services.d.ts +0 -56
  249. package/dist/process-recovery-services.js +0 -191
  250. package/dist/process-recovery-settlement.d.ts +0 -32
  251. package/dist/process-recovery-settlement.js +0 -133
  252. package/dist/process-recovery.d.ts +0 -41
  253. package/dist/process-recovery.js +0 -91
  254. package/dist/session-brief.d.ts +0 -8
  255. package/dist/session-brief.js +0 -24
  256. package/dist/session-cli.d.ts +0 -42
  257. package/dist/session-cli.js +0 -271
  258. package/dist/session-contract.d.ts +0 -183
  259. package/dist/session-contract.js +0 -122
  260. package/dist/session-remote.d.ts +0 -19
  261. package/dist/session-remote.js +0 -86
  262. package/dist/session-service.d.ts +0 -22
  263. package/dist/session-service.js +0 -157
  264. package/dist/team-cli.js +0 -692
package/dist/store.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type WritesMode } from "./writes-mode.js";
1
2
  import { type ProjectNetwork, type RunNetworkRecord } from "./egress.js";
2
3
  import { type AcpLaunch } from "./acp-attest.js";
3
4
  import { type ChatBinding } from "./chat-core.js";
@@ -178,7 +179,7 @@ export type SealedLedgerEntry = LedgerEntry & {
178
179
  hash: string;
179
180
  } | null;
180
181
  };
181
- export declare const SCHEMA_VERSION = 130;
182
+ export declare const SCHEMA_VERSION = 131;
182
183
  /** v118: the tables merged into `credential`, in the order they move (a person's API tokens keep their ids first). */
183
184
  export declare const V118_MERGED_TABLES: Readonly<Record<string, CredentialKind>>;
184
185
  /**
@@ -315,6 +316,8 @@ export declare const V129_ADDED_COLUMNS: Readonly<Record<string, Readonly<Record
315
316
  /** v130: a project's network (an approver's setting, egress.ts ProjectNetwork as JSON) and the installation's choice
316
317
  * whether an agent may run where no OS confinement exists (one row; 0 until an instance operator turns it on). */
317
318
  export declare const CONFINEMENT_SCHEMA = "\nCREATE TABLE IF NOT EXISTS project_network (\n repo TEXT PRIMARY KEY,\n network_json TEXT NOT NULL CHECK (length(network_json) <= 16384),\n updated_at TEXT NOT NULL,\n updated_by TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS confinement_setting (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n unfenced_allowed INTEGER NOT NULL DEFAULT 0 CHECK (unfenced_allowed IN (0, 1)),\n updated_at TEXT,\n updated_by TEXT\n);\nINSERT OR IGNORE INTO confinement_setting (id, unfenced_allowed) VALUES (1, 0);\n";
319
+ /** v131: where a project's builds may write (an approver's setting, agent-fence.ts WritesMode). */
320
+ export declare const PROJECT_WRITES_SCHEMA = "\nCREATE TABLE IF NOT EXISTS project_writes (\n repo TEXT PRIMARY KEY,\n mode TEXT NOT NULL CHECK (mode IN ('workspace', 'anywhere')),\n updated_at TEXT NOT NULL,\n updated_by TEXT NOT NULL\n);\n";
318
321
  /** v129: a finished run's How it ran, derived from its own records on first view (display only: never a verdict). Its
319
322
  * parser version says when to derive again; `steps` says how complete the step detail was, and why not. */
320
323
  export declare const RUN_EFFICIENCY_SCHEMA = "\nCREATE TABLE IF NOT EXISTS run_efficiency (\n run INTEGER PRIMARY KEY REFERENCES run(id) ON DELETE CASCADE,\n parser_version INTEGER NOT NULL,\n steps TEXT NOT NULL CHECK (steps IN ('complete','truncated','expired','absent')),\n steps_reason TEXT,\n payload_json TEXT NOT NULL CHECK (length(payload_json) <= 16384),\n derived_at TEXT NOT NULL\n);\n";
@@ -412,8 +415,6 @@ type CancellationTransition = {
412
415
  changed: false;
413
416
  reason: CancellationRefusal;
414
417
  };
415
- /** States from which no further work is dispatched. */
416
- export declare const TERMINAL_STATES: readonly TaskState[];
417
418
  export type Task = {
418
419
  id: string;
419
420
  title: string;
@@ -483,18 +484,6 @@ export type TaskRef = {
483
484
  /** Recorded, not asserted: what the grant's selector is checked against. */
484
485
  origin: TaskOrigin;
485
486
  };
486
- /** A standing order: a pre-approved template whose instances build unattended. */
487
- export type ExecutionSlot = {
488
- id: number;
489
- runner: string;
490
- state: "reserved" | "running" | "released";
491
- run: number | null;
492
- incarnation: string | null;
493
- processGroup: number | null;
494
- reservedAt: string;
495
- runningAt: string | null;
496
- releasedAt: string | null;
497
- };
498
487
  /** Chat providers are direct API adapters — a DISJOINT type from the build
499
488
  * harness providers, by design (Codex v3 review, change 1). */
500
489
  export type DirectChatProviderId = "anthropic-api" | "openrouter-api";
@@ -996,8 +985,6 @@ export type Capability = {
996
985
  lastResult: string | null;
997
986
  expiresAt: string | null;
998
987
  };
999
- /** `kind:name`, the unambiguous way a requirement names a capability. */
1000
- export declare function capabilityKey(capability: Pick<Capability, "kind" | "name">): string;
1001
988
  /** Parse `kind:name`; a bare name is refused rather than guessed at. */
1002
989
  export declare function parseCapabilityKey(key: string): {
1003
990
  kind: Capability["kind"];
@@ -2294,7 +2281,6 @@ export declare class Store {
2294
2281
  mirrorAllowsCompletion(taskId: string): boolean;
2295
2282
  /** Whether a stored acquire mutation exists — the replay marker's fact. */
2296
2283
  hasMutationRecord(mutation: Mutation): boolean;
2297
- enqueueExternalIntent(mirror: string, kind: "comment" | "transition" | "close", body: string | null, now: Date): void;
2298
2284
  pendingExternalIntents(limit?: number): {
2299
2285
  id: number;
2300
2286
  mirror: string;
@@ -4050,24 +4036,6 @@ export declare class Store {
4050
4036
  liveClaimByLease(leaseId: string, now: Date): {
4051
4037
  leaseId: string;
4052
4038
  } | null;
4053
- reserveExecutionSlots(runner: string, count: number, now: Date): number[];
4054
- /** reserved → running happens in the stamp-before-spawn moment, carrying
4055
- * the process group so recovery can ask the OS before freeing capacity. */
4056
- markSlotRunning(id: number, facts: {
4057
- run: number;
4058
- incarnation?: string | null;
4059
- processGroup?: number | null;
4060
- }, now: Date): boolean;
4061
- /** A correction process replaces the exited provider in the same open
4062
- * root attempt. It may refresh only that attempt's exact occupied slot. */
4063
- refreshSlotProcess(id: number, facts: {
4064
- run: number;
4065
- incarnation?: string | null;
4066
- processGroup: number;
4067
- }): boolean;
4068
- releaseExecutionSlot(id: number, now: Date): boolean;
4069
- liveSlotCount(runner: string): number;
4070
- getExecutionSlot(id: number): ExecutionSlot | null;
4071
4039
  /** Minted from a POST, never a GET. Bounded per approver; expired rows
4072
4040
  * are swept rather than accumulating. */
4073
4041
  mintCeremonyNonce(spec: {
@@ -4865,22 +4833,6 @@ export declare class Store {
4865
4833
  listTasksScoped(repo: string | null, state: TaskState | undefined, limit: number, selectedId: string | null): (Task & {
4866
4834
  repo: string | null;
4867
4835
  })[];
4868
- /**
4869
- * The Work destination's one bounded page (workspace package 1 query):
4870
- * the newest tasks the viewer may see, with the viewer's already-proved
4871
- * admission bound BEFORE the ordering and the limit — never a wider
4872
- * read post-filtered in the caller. `admitted` is the resolved
4873
- * permitted repo set: `null` means unrestricted (every placed row),
4874
- * `[]` means no placed project is permitted (no placed row at all).
4875
- * `includeUnplaced` says whether NULL-repo rows belong to this viewer;
4876
- * an account restricted to projects never sees them, so they must not
4877
- * spend its page. Every predicate is a bound parameter; the limit is
4878
- * clamped here, not trusted from the caller. Read-only; the legacy
4879
- * `listTasksScoped` is untouched.
4880
- */
4881
- listWorkTasksAdmitted(admitted: readonly string[] | null, includeUnplaced: boolean, limit: number): (Task & {
4882
- repo: string | null;
4883
- })[];
4884
4836
  /** Newest first, because the question is almost always "what just happened". */
4885
4837
  runsFor(taskRef: number): Run[];
4886
4838
  /**
@@ -5306,7 +5258,6 @@ export declare class Store {
5306
5258
  run: number;
5307
5259
  kind: Incident["kind"];
5308
5260
  }, now: Date): number;
5309
- incidentForRun(run: number): Incident | null;
5310
5261
  /** Unresolved, task attached, oldest first. No time window: these do not age out. */
5311
5262
  openIncidents(repo?: string | null): (Incident & {
5312
5263
  taskId: string;
@@ -5513,9 +5464,6 @@ export declare class Store {
5513
5464
  claimMergeIntent(id: number, by: string, leaseMs: number, now: Date): {
5514
5465
  generation: number;
5515
5466
  } | null;
5516
- /** Renew the lease AND re-prove the generation in one CAS — the last
5517
- * gate before the external call; a failed re-proof aborts the attempt. */
5518
- renewMergeClaim(id: number, generation: number, leaseMs: number, now: Date): boolean;
5519
5467
  /** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
5520
5468
  * state it believes it owns, and a terminal row is never overwritten —
5521
5469
  * a stale claim owner cannot un-merge what the observer already settled,
@@ -5580,12 +5528,6 @@ export declare class Store {
5580
5528
  lastError: string | null;
5581
5529
  firingDeadline: string | null;
5582
5530
  } | null;
5583
- latestObservation(githubRepo: string, prNumber: number): {
5584
- headSha: string;
5585
- state: string;
5586
- observedAt: string;
5587
- generation: number;
5588
- } | null;
5589
5531
  /** Revocation is immediate: intents not yet pushed die with the grant. */
5590
5532
  revokePublicationGrant(repo: string, by: string, now: Date): boolean;
5591
5533
  publicationGrantFor(repo: string): PublicationGrant | null;
@@ -6405,7 +6347,6 @@ export declare class Store {
6405
6347
  recentLeadTurns(approver: string, limit?: number): LeadTurn[];
6406
6348
  getLeadTurn(id: number): LeadTurn | null;
6407
6349
  liveLeadTurnFor(approver: string): LeadTurn | null;
6408
- leadStepsOf(leadTurn: number): ChatTurn[];
6409
6350
  /** Remember a project was opened. Upsert keeps added_at; recency always moves.
6410
6351
  * A project added for the first time starts on Quick checks. */
6411
6352
  upsertProject(path: string, name: string, now: Date, admission?: {
@@ -6466,17 +6407,6 @@ export declare class Store {
6466
6407
  repo: string | null;
6467
6408
  blockerRepo: string | null;
6468
6409
  }[];
6469
- /**
6470
- * Active work only, running first — the Work tab's page. Terminal history
6471
- * belongs to Done and the build ledger, never to this list.
6472
- */
6473
- listActiveWorkScoped(repo: string | null, now: Date, limit?: number): (Task & {
6474
- repo: string | null;
6475
- approved: boolean;
6476
- held: boolean;
6477
- buildingBy: string | null;
6478
- strikes: number;
6479
- })[];
6480
6410
  /**
6481
6411
  * Completed work, one row per done task with its final accepted run and
6482
6412
  * any publication attached — never composed from separate task and PR
@@ -6884,6 +6814,13 @@ export declare class Store {
6884
6814
  before: ProjectNetwork;
6885
6815
  after: ProjectNetwork;
6886
6816
  };
6817
+ /** Where a project's builds may write (agent-fence.ts): its saved setting, or only their workspace. */
6818
+ projectWrites(repo: string): WritesMode;
6819
+ /** An approver changed where a project's builds may write: saved, and in the ledger as before → after. */
6820
+ setProjectWrites(repo: string, mode: WritesMode, by: string, now: Date): {
6821
+ before: WritesMode;
6822
+ after: WritesMode;
6823
+ };
6887
6824
  /** Whether this installation lets an agent run where no OS confinement exists (off unless an operator said so). */
6888
6825
  unfencedAgentsAllowed(): boolean;
6889
6826
  setUnfencedAgentsAllowed(allowed: boolean, by: string, now: Date): void;
package/dist/store.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { WRITES_DEFAULT } from "./writes-mode.js";
1
2
  import { PROJECT_NETWORK_DEFAULT, projectNetworkFromValue, runNetworkFromValue } from "./egress.js";
2
3
  import { isAcpProfile, isAcpProvider } from "./acp-agents.js";
3
4
  import { ACP_CONFORMANCE_VERSION, launchFromJson } from "./acp-attest.js";
@@ -67,13 +68,13 @@ import { containerEmptiness } from "./container-state.js";
67
68
  import { hasDisguisedText, hasForbiddenControls, validateNote } from "./decision.js";
68
69
  import { parseReviewContext, reviewContextCustodyProblem } from "./review-context.js";
69
70
  import { foldReview, manualReviewOnly } from "./proof.js";
70
- import { approvalOf, digestOf, canonicalProfileJson, chainFromJson, profileDigestOf, profileFromJson, scopeAuthorityOf, routeParityProblem, parseAcceptanceCriteria, exactAcceptance, exactStringList, exactSafeIntegerOrNull, exactKeys, GEMINI_LIMITS } from "./scope.js";
71
+ import { approvalOf, digestOf, canonicalProfileJson, chainFromJson, profileDigestOf, profileFromJson, scopeAuthorityOf, routeParityProblem, parseAcceptanceCriteria, exactAcceptance, exactStringList, exactSafeIntegerOrNull } from "./scope.js";
71
72
  import { resolveScopeProfile, resolveRouteCandidates, exactPinOf, routeOfTask, agentChoicesFor } from "./agentconfig.js";
72
- import { canonicalOverridesJson, canonicalRouteJson, exactModelId, isRiskLevel, isTaskSize, headroomFrom, makesNoPlan, legOf, overridesFromJson, phaseOfRole, recommendRoute, routeDigestOf, routeFromJson, routeProblems, routeStampProblem, ROUTE_ERA, PROVIDER_ID_LIST, } from "./phase-routing.js";
73
+ import { canonicalOverridesJson, canonicalRouteJson, isRiskLevel, isTaskSize, headroomFrom, makesNoPlan, legOf, overridesFromJson, phaseOfRole, recommendRoute, routeDigestOf, routeFromJson, routeProblems, routeStampProblem, ROUTE_ERA, PROVIDER_ID_LIST, } from "./phase-routing.js";
73
74
  import { readAuthModeStrict } from "./keys.js";
74
75
  import { modeDigestOf, modeTermsFromJson } from "./modes.js";
75
76
  import { readVerifiedArtifact } from "./evidence.js";
76
- import { isProviderId } from "./provider.js";
77
+ import {} from "./provider.js";
77
78
  import { authenticate as runnerAuthenticate } from "./runner.js";
78
79
  import { stampNewProjectLevel } from "./check-levels.js";
79
80
  import { parseCheckProgressSnapshot } from "./check-progress.js";
@@ -715,7 +716,9 @@ const REGISTERED_AT_FILING = "again, as it was filed";
715
716
  // v130 adds, and changes no saved row: what a project's builds may reach on the network (project_network; egress.ts,
716
717
  // docs/plans/agent-baseline-hardening.md arc 1) and whether this installation lets an agent run with no OS confinement
717
718
  // (confinement_setting, one row; off unless an instance operator turns it on).
718
- export const SCHEMA_VERSION = 130;
719
+ // v131 adds, and changes no saved row: where a project's builds may write (project_writes; agent-fence.ts, docs/plans/
720
+ // agent-baseline-hardening.md arc 2) — only their workspace unless an approver chose anywhere.
721
+ export const SCHEMA_VERSION = 131;
719
722
  /** v118: the tables merged into `credential`, in the order they move (a person's API tokens keep their ids first). */
720
723
  export const V118_MERGED_TABLES = Object.freeze({ api_token: "person", coordinator_credential: "coordinator", lead_credential: "lead" });
721
724
  /** The foreign keys that named a merged table, exactly as their DDL wrote them; each names `credential(id)` instead. */
@@ -848,7 +851,7 @@ const V115_DROPPED_REFERENCES = /\s+REFERENCES (?:contestant|contest|tournament_
848
851
  * unchanged), and adds the nullable column in V125_ADDED_COLUMNS, checked the same way. v126 only adds a new table
849
852
  * (task_source) and the columns in V126_ADDED_COLUMNS (null or 0), checked the same way.
850
853
  */
851
- export const UPDATE_SAFE_MIGRATIONS = Object.freeze([108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130]);
854
+ export const UPDATE_SAFE_MIGRATIONS = Object.freeze([108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131]);
852
855
  /** v119: the columns it adds, by table, with the value every row saved before it reads (toolroll-update's HISTORY_RULES). */
853
856
  export const V119_ADDED_COLUMNS = Object.freeze({
854
857
  task_ref: { planning_generation: { definition: "INTEGER NOT NULL DEFAULT 0", saved: "0" } },
@@ -976,6 +979,15 @@ CREATE TABLE IF NOT EXISTS confinement_setting (
976
979
  );
977
980
  INSERT OR IGNORE INTO confinement_setting (id, unfenced_allowed) VALUES (1, 0);
978
981
  `;
982
+ /** v131: where a project's builds may write (an approver's setting, agent-fence.ts WritesMode). */
983
+ export const PROJECT_WRITES_SCHEMA = `
984
+ CREATE TABLE IF NOT EXISTS project_writes (
985
+ repo TEXT PRIMARY KEY,
986
+ mode TEXT NOT NULL CHECK (mode IN ('workspace', 'anywhere')),
987
+ updated_at TEXT NOT NULL,
988
+ updated_by TEXT NOT NULL
989
+ );
990
+ `;
979
991
  /** v129: a finished run's How it ran, derived from its own records on first view (display only: never a verdict). Its
980
992
  * parser version says when to derive again; `steps` says how complete the step detail was, and why not. */
981
993
  export const RUN_EFFICIENCY_SCHEMA = `
@@ -1165,8 +1177,6 @@ CREATE INDEX IF NOT EXISTS sso_identity_account ON sso_identity (account);
1165
1177
  */
1166
1178
  /** The backend name the built-in store registers itself under. */
1167
1179
  export const BUILT_IN = "built-in";
1168
- /** States from which no further work is dispatched. */
1169
- export const TERMINAL_STATES = ["done", "failed", "cancelled"];
1170
1180
  export const LEAD_THREAD = { kind: "lead" };
1171
1181
  /** A lead_message row as a LeadMessage. */
1172
1182
  function readLeadMessageRow(row) {
@@ -1286,10 +1296,6 @@ function readFlowReceipt(row) {
1286
1296
  const optional = (key) => row[key] === null || row[key] === undefined ? null : String(row[key]);
1287
1297
  return { state, card, note: optional("note"), at: String(row["at"]), acceptedAt: optional("accepted_at"), itemJson: optional("item_json") };
1288
1298
  }
1289
- /** `kind:name`, the unambiguous way a requirement names a capability. */
1290
- export function capabilityKey(capability) {
1291
- return `${capability.kind}:${capability.name}`;
1292
- }
1293
1299
  /** Parse `kind:name`; a bare name is refused rather than guessed at. */
1294
1300
  export function parseCapabilityKey(key) {
1295
1301
  const split = key.indexOf(":");
@@ -3915,6 +3921,8 @@ function initializeStore(db, file) {
3915
3921
  db.exec(RUN_EFFICIENCY_SCHEMA);
3916
3922
  // v130: a project's network and whether an agent may run unconfined (new tables only).
3917
3923
  db.exec(CONFINEMENT_SCHEMA);
3924
+ // v131: where a project's builds may write (a new table only).
3925
+ db.exec(PROJECT_WRITES_SCHEMA);
3918
3926
  // v123: a flow that runs on its own (flow-unattended.ts): its grants and daily runs (new tables), and which authority
3919
3927
  // armed a plan's unchanged-plan approval (plan_authorization.basis, V123_ADDED_COLUMNS: saved rows read the mode).
3920
3928
  db.exec(FLOW_UNATTENDED_SCHEMA);
@@ -6399,11 +6407,6 @@ export class Store {
6399
6407
  .get(mutation.idempotencyKey);
6400
6408
  return row !== undefined;
6401
6409
  }
6402
- enqueueExternalIntent(mirror, kind, body, now) {
6403
- this.db
6404
- .prepare("INSERT INTO external_intent (mirror, kind, body, created_at) VALUES (?, ?, ?, ?)")
6405
- .run(mirror, kind, body, now.toISOString());
6406
- }
6407
6410
  pendingExternalIntents(limit = 50) {
6408
6411
  return this.db
6409
6412
  .prepare("SELECT id, mirror, kind, body, attempts FROM external_intent WHERE state = 'pending' ORDER BY id LIMIT ?")
@@ -11409,54 +11412,6 @@ export class Store {
11409
11412
  return row === undefined ? null : { leaseId: String(row["lease_id"]) };
11410
11413
  }
11411
11414
  // ---- worker-process slots (v14, finding 26) ----------------------------
11412
- reserveExecutionSlots(runner, count, now) {
11413
- return this.transact(() => {
11414
- const ids = [];
11415
- for (let index = 0; index < count; index++) {
11416
- const inserted = this.db
11417
- .prepare("INSERT INTO execution_slot (runner, reserved_at) VALUES (?, ?)")
11418
- .run(runner, now.toISOString());
11419
- ids.push(Number(inserted.lastInsertRowid));
11420
- }
11421
- return ids;
11422
- });
11423
- }
11424
- /** reserved → running happens in the stamp-before-spawn moment, carrying
11425
- * the process group so recovery can ask the OS before freeing capacity. */
11426
- markSlotRunning(id, facts, now) {
11427
- const changed = this.db
11428
- .prepare(`UPDATE execution_slot SET state = 'running', run = ?, incarnation = ?, process_group = ?, running_at = ?
11429
- WHERE id = ? AND state = 'reserved'`)
11430
- .run(facts.run, facts.incarnation ?? null, facts.processGroup ?? null, now.toISOString(), id);
11431
- return Number(changed.changes) === 1;
11432
- }
11433
- /** A correction process replaces the exited provider in the same open
11434
- * root attempt. It may refresh only that attempt's exact occupied slot. */
11435
- refreshSlotProcess(id, facts) {
11436
- if (!Number.isInteger(facts.processGroup) || facts.processGroup <= 0)
11437
- return false;
11438
- const changed = this.db.prepare(`UPDATE execution_slot SET process_group = ?
11439
- WHERE id = ? AND state = 'running' AND run = ? AND incarnation IS ?
11440
- AND EXISTS (SELECT 1 FROM run WHERE id = ? AND outcome IS NULL)`)
11441
- .run(facts.processGroup, id, facts.run, facts.incarnation ?? null, facts.run);
11442
- return Number(changed.changes) === 1;
11443
- }
11444
- releaseExecutionSlot(id, now) {
11445
- const changed = this.db
11446
- .prepare("UPDATE execution_slot SET state = 'released', released_at = ? WHERE id = ? AND state IN ('reserved','running')")
11447
- .run(now.toISOString(), id);
11448
- return Number(changed.changes) === 1;
11449
- }
11450
- liveSlotCount(runner) {
11451
- const row = this.db
11452
- .prepare("SELECT COUNT(*) AS n FROM execution_slot WHERE runner = ? AND state IN ('reserved','running')")
11453
- .get(runner);
11454
- return Number(row?.["n"] ?? 0);
11455
- }
11456
- getExecutionSlot(id) {
11457
- const row = this.db.prepare("SELECT * FROM execution_slot WHERE id = ?").get(id);
11458
- return row === undefined ? null : readExecutionSlot(row);
11459
- }
11460
11415
  // ---- durable ceremony nonces (v14, findings 21/30) ---------------------
11461
11416
  /** Minted from a POST, never a GET. Bounded per approver; expired rows
11462
11417
  * are swept rather than accumulating. */
@@ -13514,40 +13469,6 @@ export class Store {
13514
13469
  repo: row["task_repo"] === null ? null : String(row["task_repo"]),
13515
13470
  }));
13516
13471
  }
13517
- /**
13518
- * The Work destination's one bounded page (workspace package 1 query):
13519
- * the newest tasks the viewer may see, with the viewer's already-proved
13520
- * admission bound BEFORE the ordering and the limit — never a wider
13521
- * read post-filtered in the caller. `admitted` is the resolved
13522
- * permitted repo set: `null` means unrestricted (every placed row),
13523
- * `[]` means no placed project is permitted (no placed row at all).
13524
- * `includeUnplaced` says whether NULL-repo rows belong to this viewer;
13525
- * an account restricted to projects never sees them, so they must not
13526
- * spend its page. Every predicate is a bound parameter; the limit is
13527
- * clamped here, not trusted from the caller. Read-only; the legacy
13528
- * `listTasksScoped` is untouched.
13529
- */
13530
- listWorkTasksAdmitted(admitted, includeUnplaced, limit) {
13531
- const page = Math.max(1, Math.min(Math.floor(limit), 500));
13532
- // SQLite accepts an empty IN list, so an empty admission binds as
13533
- // "no placed row" without any special SQL shape.
13534
- const rows = this.db
13535
- .prepare(`SELECT task.*, task_ref.repo AS task_repo FROM task
13536
- JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
13537
- WHERE ((task_ref.repo IS NULL AND ? = 1)
13538
- OR (task_ref.repo IS NOT NULL AND (? = 1 OR task_ref.repo IN (${(admitted ?? []).map(() => "?").join(",")}))))
13539
- ORDER BY task.created_at DESC, task.id DESC LIMIT ?`)
13540
- .all(BUILT_IN, includeUnplaced ? 1 : 0, admitted === null ? 1 : 0, ...(admitted ?? []), page);
13541
- return rows.map(row => ({
13542
- id: String(row["id"]),
13543
- title: String(row["title"]),
13544
- state: String(row["state"]),
13545
- createdAt: String(row["created_at"]),
13546
- updatedAt: String(row["updated_at"]),
13547
- priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
13548
- repo: row["task_repo"] === null ? null : String(row["task_repo"]),
13549
- }));
13550
- }
13551
13472
  /** Newest first, because the question is almost always "what just happened". */
13552
13473
  runsFor(taskRef) {
13553
13474
  return this.db
@@ -14493,10 +14414,6 @@ export class Store {
14493
14414
  .run(incident.run, incident.kind, now.toISOString());
14494
14415
  return Number(inserted.lastInsertRowid);
14495
14416
  }
14496
- incidentForRun(run) {
14497
- const row = this.db.prepare("SELECT * FROM incident WHERE run = ?").get(run);
14498
- return row === undefined ? null : readIncident(row);
14499
- }
14500
14417
  /** Unresolved, task attached, oldest first. No time window: these do not age out. */
14501
14418
  openIncidents(repo = null) {
14502
14419
  return this.db
@@ -14858,14 +14775,6 @@ export class Store {
14858
14775
  return Number(changes) === 1 ? { generation } : null;
14859
14776
  });
14860
14777
  }
14861
- /** Renew the lease AND re-prove the generation in one CAS — the last
14862
- * gate before the external call; a failed re-proof aborts the attempt. */
14863
- renewMergeClaim(id, generation, leaseMs, now) {
14864
- const { changes } = this.db
14865
- .prepare("UPDATE merge_intent SET claimed_until = ? WHERE id = ? AND state = 'claimed' AND generation = ?")
14866
- .run(new Date(now.getTime() + leaseMs).toISOString(), id, generation);
14867
- return Number(changes) === 1;
14868
- }
14869
14778
  /** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
14870
14779
  * state it believes it owns, and a terminal row is never overwritten —
14871
14780
  * a stale claim owner cannot un-merge what the observer already settled,
@@ -15015,14 +14924,6 @@ export class Store {
15015
14924
  firingDeadline: row["firing_deadline"] === null ? null : String(row["firing_deadline"]),
15016
14925
  };
15017
14926
  }
15018
- latestObservation(githubRepo, prNumber) {
15019
- const row = this.db
15020
- .prepare("SELECT head_sha, state, observed_at, generation FROM ci_observation WHERE github_repo = ? AND pr_number = ?")
15021
- .get(githubRepo, prNumber);
15022
- return row === undefined || String(row["observed_at"]) === ""
15023
- ? null
15024
- : { headSha: String(row["head_sha"]), state: String(row["state"]), observedAt: String(row["observed_at"]), generation: Number(row["generation"]) };
15025
- }
15026
14927
  /** Revocation is immediate: intents not yet pushed die with the grant. */
15027
14928
  revokePublicationGrant(repo, by, now) {
15028
14929
  const { changes } = this.db
@@ -16621,9 +16522,6 @@ export class Store {
16621
16522
  const row = this.db.prepare("SELECT * FROM mate_turn WHERE approver = ? AND state IN ('queued','running') ORDER BY id DESC LIMIT 1").get(approver);
16622
16523
  return row === undefined ? null : readLeadTurn(row);
16623
16524
  }
16624
- leadStepsOf(leadTurn) {
16625
- return this.db.prepare("SELECT * FROM chat_turn WHERE mate_turn = ? ORDER BY id ASC").all(leadTurn).map(readChatTurn);
16626
- }
16627
16525
  // ---- projects ------------------------------------------------------------
16628
16526
  /** Remember a project was opened. Upsert keeps added_at; recency always moves.
16629
16527
  * A project added for the first time starts on Quick checks. */
@@ -16794,50 +16692,6 @@ export class Store {
16794
16692
  blockerRepo: row["blocker_repo"] === null || row["blocker_repo"] === undefined ? null : String(row["blocker_repo"]),
16795
16693
  }));
16796
16694
  }
16797
- /**
16798
- * Active work only, running first — the Work tab's page. Terminal history
16799
- * belongs to Done and the build ledger, never to this list.
16800
- */
16801
- listActiveWorkScoped(repo, now, limit = 50) {
16802
- const page = Math.max(1, Math.min(Math.floor(limit), 100));
16803
- return this.db
16804
- .prepare(`SELECT task.*, task_ref.repo AS task_repo, task_ref.strikes AS ref_strikes,
16805
- EXISTS (
16806
- SELECT 1 FROM task_scope
16807
- WHERE task_scope.task_id = task.id AND task_scope.approved_digest = task_scope.digest
16808
- AND task_scope.approved_at IS NOT NULL
16809
- ) AS approved,
16810
- EXISTS (
16811
- SELECT 1 FROM hold
16812
- WHERE hold.task_ref = task_ref.id AND (hold.until IS NULL OR hold.until > ?)
16813
- ) AS held,
16814
- (SELECT claim.runner FROM claim
16815
- WHERE claim.task_ref = task_ref.id AND claim.released_at IS NULL AND claim.expires_at > ?
16816
- AND claim.lease_generation = (
16817
- SELECT MAX(newest.lease_generation) FROM claim AS newest
16818
- WHERE newest.task_ref = claim.task_ref)
16819
- LIMIT 1) AS building_by
16820
- FROM task
16821
- JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
16822
- WHERE task.state IN ('running','queued')
16823
- AND (? IS NULL OR task_ref.repo IS NULL OR task_ref.repo = ?)
16824
- ORDER BY CASE task.state WHEN 'running' THEN 0 ELSE 1 END, task.updated_at DESC, task.id DESC
16825
- LIMIT ?`)
16826
- .all(now.toISOString(), now.toISOString(), BUILT_IN, repo, repo, page)
16827
- .map(row => ({
16828
- id: String(row["id"]),
16829
- title: String(row["title"]),
16830
- state: String(row["state"]),
16831
- createdAt: String(row["created_at"]),
16832
- updatedAt: String(row["updated_at"]),
16833
- priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
16834
- repo: row["task_repo"] === null ? null : String(row["task_repo"]),
16835
- approved: Number(row["approved"]) === 1,
16836
- held: Number(row["held"]) === 1,
16837
- buildingBy: row["building_by"] === null ? null : String(row["building_by"]),
16838
- strikes: Number(row["ref_strikes"]),
16839
- }));
16840
- }
16841
16695
  /**
16842
16696
  * Completed work, one row per done task with its final accepted run and
16843
16697
  * any publication attached — never composed from separate task and PR
@@ -18246,6 +18100,23 @@ export class Store {
18246
18100
  return { before, after };
18247
18101
  });
18248
18102
  }
18103
+ /** Where a project's builds may write (agent-fence.ts): its saved setting, or only their workspace. */
18104
+ projectWrites(repo) {
18105
+ const mode = this.db.prepare("SELECT mode FROM project_writes WHERE repo = ?").get(repo)?.["mode"];
18106
+ // A damaged row reads as the narrower setting, never the wider one.
18107
+ return mode === "anywhere" ? "anywhere" : WRITES_DEFAULT;
18108
+ }
18109
+ /** An approver changed where a project's builds may write: saved, and in the ledger as before → after. */
18110
+ setProjectWrites(repo, mode, by, now) {
18111
+ return this.transact(() => {
18112
+ const before = this.projectWrites(repo);
18113
+ this.db.prepare(`INSERT INTO project_writes (repo, mode, updated_at, updated_by) VALUES (?, ?, ?, ?)
18114
+ ON CONFLICT (repo) DO UPDATE SET mode = excluded.mode, updated_at = excluded.updated_at, updated_by = excluded.updated_by`).run(repo, mode, now.toISOString(), by);
18115
+ const after = this.projectWrites(repo);
18116
+ this.recordPolicy(by, repo, "build writes", before, after, now);
18117
+ return { before, after };
18118
+ });
18119
+ }
18249
18120
  /** Whether this installation lets an agent run where no OS confinement exists (off unless an operator said so). */
18250
18121
  unfencedAgentsAllowed() {
18251
18122
  return Number(this.db.prepare("SELECT unfenced_allowed FROM confinement_setting WHERE id = 1").get()?.["unfenced_allowed"] ?? 0) === 1;
@@ -19513,20 +19384,6 @@ function readTaskRef(row) {
19513
19384
  origin: String(row["origin"]) === "ours" ? "ours" : "theirs",
19514
19385
  };
19515
19386
  }
19516
- function readExecutionSlot(row) {
19517
- const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
19518
- return {
19519
- id: Number(row["id"]),
19520
- runner: String(row["runner"]),
19521
- state: String(row["state"]),
19522
- run: row["run"] === null ? null : Number(row["run"]),
19523
- incarnation: maybe("incarnation"),
19524
- processGroup: row["process_group"] === null ? null : Number(row["process_group"]),
19525
- reservedAt: String(row["reserved_at"]),
19526
- runningAt: maybe("running_at"),
19527
- releasedAt: maybe("released_at"),
19528
- };
19529
- }
19530
19387
  function readChatTurn(row) {
19531
19388
  const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
19532
19389
  const maybeN = (key) => (row[key] === null || row[key] === undefined ? null : Number(row[key]));
@@ -20,7 +20,6 @@ export declare const REVIEW_OUTPUT_LIMITS: {
20
20
  readonly path: 300;
21
21
  };
22
22
  export declare const REVIEW_NOTE_CODE_POINTS: number;
23
- export declare const REVIEW_NOTE_GUIDANCE: string;
24
23
  export type StructuredNormalization = {
25
24
  text: string;
26
25
  changed: boolean;
@@ -16,7 +16,6 @@ export const STRUCTURED_REPAIR_TIMEOUT_MS = 5 * 60_000;
16
16
  * notes concise without imposing a second, stricter transport contract. */
17
17
  export const REVIEW_OUTPUT_LIMITS = { comments: 40, criteria: 12, note: TEXT_LIMITS.reviewNote, path: TEXT_LIMITS.reviewPath };
18
18
  export const REVIEW_NOTE_CODE_POINTS = Math.floor(REVIEW_OUTPUT_LIMITS.note / 2);
19
- export const REVIEW_NOTE_GUIDANCE = `Keep each comment and criterion note to one concise finding and its evidence. Aim for ${REVIEW_NOTE_CODE_POINTS} characters or fewer; the hard limit is ${REVIEW_OUTPUT_LIMITS.note} UTF-16 units. Preserve the conclusion and any needed provenance; omit repeated rubric text.`;
20
19
  /** Strip only unambiguous, whole-payload wrappers. */
21
20
  export function normalizeStructuredJson(raw) {
22
21
  let text = raw;
@@ -72,5 +72,3 @@ export declare function answerSubagentQuestion(store: Store, id: number, answer:
72
72
  ok: false;
73
73
  said: string;
74
74
  };
75
- /** A card's link, for messages about it. */
76
- export declare const subagentCardHref: (flow: number, card: number) => string;
@@ -304,5 +304,3 @@ export function answerSubagentQuestion(store, id, answer, now) {
304
304
  return { ok: true, said: question.toolCall === null ? "Answered. It picks the card up again now." : choice?.id === APPROVE ? "Approved. The call is made now, exactly as shown." : "It won't make that call. It picks the card up again now." };
305
305
  });
306
306
  }
307
- /** A card's link, for messages about it. */
308
- export const subagentCardHref = (flow, card) => flowCardHref(flow, card);
@@ -1,4 +1,4 @@
1
- import { run, type ExecResult } from "./exec.js";
1
+ import { type CommandRunner } from "./claude-print.js";
2
2
  import type { ContractResult } from "./contracts/contract.js";
3
3
  import { type TurnAnswer } from "./contracts/subagent-turn.js";
4
4
  import { type Overrun } from "./text-limits.js";
@@ -13,7 +13,6 @@ export type Soul = {
13
13
  };
14
14
  /** A handle from a name: "Maya" → "maya". */
15
15
  export declare const handleOf: (name: string) => string;
16
- export declare const isHandle: (value: unknown) => value is string;
17
16
  /** A soul file read: its name and role (front matter) and its sections. */
18
17
  export declare function parseSoul(text: string): {
19
18
  ok: true;
@@ -139,7 +138,6 @@ export type TurnReply = ({
139
138
  /** Runs one turn; injectable so tests never spend a subscription turn. */
140
139
  export type TurnRunner = (request: TurnRequest) => Promise<TurnReply>;
141
140
  export declare const TURN_TIMEOUT_MS = 180000;
142
- type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
143
141
  /** The production runner: Claude through this computer's sign-in, answering in the turn schema (TURN_MODEL_SCHEMA), with no tools, no MCP servers and no repository. */
144
142
  export declare function claudeTurnRunner(runner?: CommandRunner): TurnRunner;
145
143
  /** How a subagent is named to people: "Maya · Support". */