toolroll 0.9.67 → 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 (236) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/acp-client.js +1 -3
  3. package/dist/agent-board.d.ts +0 -1
  4. package/dist/agent-board.js +0 -1
  5. package/dist/agent-fence.js +3 -0
  6. package/dist/browser/workspace.css +1 -1
  7. package/dist/browser/workspace.js +31 -29
  8. package/dist/builder.js +3 -26
  9. package/dist/canonical-json.d.ts +14 -0
  10. package/dist/canonical-json.js +36 -0
  11. package/dist/chat-actions.js +1 -2
  12. package/dist/chat-admission.d.ts +19 -0
  13. package/dist/chat-admission.js +22 -0
  14. package/dist/chat-channel.js +1 -1
  15. package/dist/chat-delivery.js +0 -1
  16. package/dist/chat-follow.d.ts +17 -0
  17. package/dist/chat-follow.js +32 -0
  18. package/dist/chat-messages.js +0 -1
  19. package/dist/chat-settings-page.d.ts +23 -0
  20. package/dist/chat-settings-page.js +41 -0
  21. package/dist/claim.js +3 -6
  22. package/dist/claude-print.d.ts +12 -0
  23. package/dist/claude-print.js +34 -0
  24. package/dist/cli-http.d.ts +0 -7
  25. package/dist/cli-http.js +0 -21
  26. package/dist/cli.d.ts +3 -10
  27. package/dist/cli.js +15 -24
  28. package/dist/coding-provider.js +2 -1
  29. package/dist/coding-workspace.js +1 -1
  30. package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
  31. package/dist/connect-cli.js +331 -0
  32. package/dist/containment.d.ts +0 -2
  33. package/dist/containment.js +2 -6
  34. package/dist/contracts/chat-actions.d.ts +0 -1
  35. package/dist/contracts/chat-content.d.ts +0 -4
  36. package/dist/contracts/chat-content.js +0 -2
  37. package/dist/contracts/chat-tables.d.ts +0 -1
  38. package/dist/contracts/cli.d.ts +0 -62
  39. package/dist/contracts/cli.js +0 -4
  40. package/dist/contracts/coding-workspace.js +1 -1
  41. package/dist/contracts/contract.js +1 -1
  42. package/dist/contracts/flow-card.d.ts +0 -1
  43. package/dist/contracts/flow-propose.d.ts +0 -1
  44. package/dist/contracts/flow-send.js +1 -1
  45. package/dist/contracts/gateway-tools.d.ts +0 -1
  46. package/dist/contracts/integration-metadata.js +1 -1
  47. package/dist/contracts/lead-tools.d.ts +0 -1
  48. package/dist/contracts/memory-pass.d.ts +0 -1
  49. package/dist/contracts/memory-pass.js +1 -1
  50. package/dist/contracts/plan.js +1 -1
  51. package/dist/contracts/project-knowledge.js +1 -1
  52. package/dist/contracts/project-skills.d.ts +0 -1
  53. package/dist/contracts/proof.js +1 -1
  54. package/dist/contracts/recipes.js +1 -1
  55. package/dist/contracts/scope.js +1 -1
  56. package/dist/contracts/scout-report.js +1 -1
  57. package/dist/contracts/teams-callback.d.ts +0 -1
  58. package/dist/converse.d.ts +0 -6
  59. package/dist/converse.js +0 -19
  60. package/dist/daemon.js +3 -2
  61. package/dist/decision.d.ts +1 -3
  62. package/dist/deprecations.d.ts +12 -4
  63. package/dist/deprecations.js +27 -4
  64. package/dist/desktop-update-recovery.js +1 -1
  65. package/dist/desktop-update.js +3 -2
  66. package/dist/discord-chat.js +4 -15
  67. package/dist/discord-settings.d.ts +2 -6
  68. package/dist/discord-settings.js +10 -38
  69. package/dist/discord.js +12 -23
  70. package/dist/evidence.d.ts +0 -1
  71. package/dist/evidence.js +0 -3
  72. package/dist/exec.d.ts +0 -9
  73. package/dist/exec.js +3 -81
  74. package/dist/flow-actions.js +0 -3
  75. package/dist/flow-draft.d.ts +1 -3
  76. package/dist/flow-draft.js +15 -28
  77. package/dist/flow-scripts.d.ts +1 -8
  78. package/dist/flow-scripts.js +0 -13
  79. package/dist/flow-send.js +1 -1
  80. package/dist/flow-share.d.ts +0 -2
  81. package/dist/flow-share.js +1 -6
  82. package/dist/flow-steps.js +1 -1
  83. package/dist/flow-triggers.d.ts +0 -1
  84. package/dist/flow-triggers.js +1 -2
  85. package/dist/flow-unattended.js +1 -12
  86. package/dist/flows.js +1 -1
  87. package/dist/health-cli.d.ts +2 -2
  88. package/dist/health-cli.js +1 -1
  89. package/dist/invoke.d.ts +0 -3
  90. package/dist/invoke.js +5 -3
  91. package/dist/is-record.d.ts +2 -0
  92. package/dist/is-record.js +2 -0
  93. package/dist/lead-doors.d.ts +1 -5
  94. package/dist/lead-doors.js +0 -4
  95. package/dist/lead-tools.js +3 -6
  96. package/dist/live-detail.d.ts +0 -1
  97. package/dist/live-detail.js +0 -6
  98. package/dist/live-terminal.js +2 -1
  99. package/dist/live.d.ts +0 -1
  100. package/dist/live.js +1 -2
  101. package/dist/mcp-core.js +0 -2
  102. package/dist/memory-pass.js +1 -1
  103. package/dist/model-catalog.js +1 -1
  104. package/dist/modes.js +1 -12
  105. package/dist/operate.js +383 -750
  106. package/dist/password-bearer.d.ts +0 -2
  107. package/dist/password-bearer.js +0 -4
  108. package/dist/peek-cli.js +2 -1
  109. package/dist/peek.d.ts +2 -26
  110. package/dist/peek.js +2 -168
  111. package/dist/phase-routing.d.ts +0 -4
  112. package/dist/phase-routing.js +2 -21
  113. package/dist/planner-source.d.ts +2 -1
  114. package/dist/planner-source.js +2 -12
  115. package/dist/planner.js +2 -14
  116. package/dist/process-tree.d.ts +0 -2
  117. package/dist/process-tree.js +0 -10
  118. package/dist/project-delete.d.ts +0 -2
  119. package/dist/project-delete.js +1 -3
  120. package/dist/project-learning.d.ts +0 -14
  121. package/dist/project-skills.d.ts +0 -1
  122. package/dist/project-skills.js +0 -14
  123. package/dist/project-tools.js +2 -10
  124. package/dist/provider.d.ts +0 -17
  125. package/dist/provider.js +0 -26
  126. package/dist/pulls.d.ts +0 -2
  127. package/dist/pulls.js +0 -9
  128. package/dist/release-adapters.d.ts +3 -0
  129. package/dist/release-adapters.js +15 -5
  130. package/dist/remote-exec.d.ts +3 -2
  131. package/dist/remote-exec.js +3 -2
  132. package/dist/repos.d.ts +0 -5
  133. package/dist/repos.js +2 -10
  134. package/dist/repository-context.d.ts +0 -2
  135. package/dist/repository-context.js +0 -4
  136. package/dist/restart-certification.d.ts +0 -2
  137. package/dist/restart-certification.js +1 -5
  138. package/dist/result-follow-ups.d.ts +1 -4
  139. package/dist/result-follow-ups.js +1 -6
  140. package/dist/result-review.d.ts +0 -2
  141. package/dist/result-review.js +0 -2
  142. package/dist/retention.d.ts +0 -1
  143. package/dist/retention.js +0 -1
  144. package/dist/review-context.d.ts +0 -1
  145. package/dist/review-context.js +1 -12
  146. package/dist/reviewer.d.ts +0 -16
  147. package/dist/reviewer.js +0 -18
  148. package/dist/run-closeout.js +2 -1
  149. package/dist/scope.js +1 -13
  150. package/dist/scout-browser.js +2 -1
  151. package/dist/serve.js +2 -2
  152. package/dist/server/console.css +5 -133
  153. package/dist/server/flows.js +2 -2
  154. package/dist/server/http.d.ts +2 -0
  155. package/dist/server/http.js +5 -0
  156. package/dist/server/pages.js +2 -2
  157. package/dist/server/people-tokens.js +3 -4
  158. package/dist/server/remote.js +1 -6
  159. package/dist/server/render-chat.d.ts +9 -2
  160. package/dist/server/render-chat.js +53 -7
  161. package/dist/server/render-results.d.ts +0 -6
  162. package/dist/server/render-results.js +3 -9
  163. package/dist/server/render-tasks.js +4 -5
  164. package/dist/server/route-table.d.ts +0 -4
  165. package/dist/server/route-table.js +0 -6
  166. package/dist/server/settings.js +23 -23
  167. package/dist/server/task-views.js +1 -1
  168. package/dist/server/tasks.js +3 -3
  169. package/dist/setup-guide.d.ts +2 -2
  170. package/dist/skills.d.ts +0 -6
  171. package/dist/skills.js +0 -8
  172. package/dist/slack-chat.d.ts +1 -7
  173. package/dist/slack-chat.js +5 -18
  174. package/dist/slack-settings.d.ts +2 -6
  175. package/dist/slack-settings.js +10 -38
  176. package/dist/slack.js +12 -23
  177. package/dist/sleep.d.ts +2 -0
  178. package/dist/sleep.js +2 -0
  179. package/dist/store.d.ts +0 -73
  180. package/dist/store.js +3 -177
  181. package/dist/structured-output.d.ts +0 -1
  182. package/dist/structured-output.js +0 -1
  183. package/dist/subagent-work.d.ts +0 -2
  184. package/dist/subagent-work.js +0 -2
  185. package/dist/subagents.d.ts +1 -3
  186. package/dist/subagents.js +20 -33
  187. package/dist/subscription-chat.d.ts +1 -3
  188. package/dist/subscription-chat.js +2 -3
  189. package/dist/task-sizing.d.ts +1 -4
  190. package/dist/task-sizing.js +3 -10
  191. package/dist/teams-chat.js +4 -11
  192. package/dist/teams.js +12 -19
  193. package/dist/telegram-lead.js +2 -2
  194. package/dist/telegram.js +1 -1
  195. package/dist/token-notices.d.ts +0 -11
  196. package/dist/token-notices.js +1 -5
  197. package/dist/tool-secret-store.d.ts +0 -3
  198. package/dist/tool-secret-store.js +2 -11
  199. package/dist/toolroll-update.d.ts +0 -2
  200. package/dist/toolroll-update.js +2 -2
  201. package/dist/verification-evidence.d.ts +0 -1
  202. package/dist/verification-evidence.js +0 -1
  203. package/dist/webhooks.d.ts +0 -1
  204. package/dist/webhooks.js +0 -1
  205. package/dist/workspace-ui.d.ts +0 -8
  206. package/dist/workspace-ui.js +1 -6
  207. package/package.json +1 -1
  208. package/dist/contracts/native-census.d.ts +0 -42
  209. package/dist/contracts/native-census.js +0 -36
  210. package/dist/process-recovery-anchor.d.ts +0 -75
  211. package/dist/process-recovery-anchor.js +0 -188
  212. package/dist/process-recovery-coalition.d.ts +0 -25
  213. package/dist/process-recovery-coalition.js +0 -105
  214. package/dist/process-recovery-eligibility.d.ts +0 -179
  215. package/dist/process-recovery-eligibility.js +0 -174
  216. package/dist/process-recovery-native.d.ts +0 -161
  217. package/dist/process-recovery-native.js +0 -595
  218. package/dist/process-recovery-provenance.d.ts +0 -163
  219. package/dist/process-recovery-provenance.js +0 -292
  220. package/dist/process-recovery-services.d.ts +0 -56
  221. package/dist/process-recovery-services.js +0 -191
  222. package/dist/process-recovery-settlement.d.ts +0 -32
  223. package/dist/process-recovery-settlement.js +0 -133
  224. package/dist/process-recovery.d.ts +0 -41
  225. package/dist/process-recovery.js +0 -91
  226. package/dist/session-brief.d.ts +0 -8
  227. package/dist/session-brief.js +0 -24
  228. package/dist/session-cli.d.ts +0 -42
  229. package/dist/session-cli.js +0 -271
  230. package/dist/session-contract.d.ts +0 -183
  231. package/dist/session-contract.js +0 -122
  232. package/dist/session-remote.d.ts +0 -19
  233. package/dist/session-remote.js +0 -86
  234. package/dist/session-service.d.ts +0 -22
  235. package/dist/session-service.js +0 -157
  236. package/dist/team-cli.js +0 -692
@@ -0,0 +1,2 @@
1
+ /** Wait `ms` milliseconds on the global timer (so fake timers in tests still drive it). */
2
+ export declare const sleep: (ms: number) => Promise<void>;
package/dist/sleep.js ADDED
@@ -0,0 +1,2 @@
1
+ /** Wait `ms` milliseconds on the global timer (so fake timers in tests still drive it). */
2
+ export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
package/dist/store.d.ts CHANGED
@@ -415,8 +415,6 @@ type CancellationTransition = {
415
415
  changed: false;
416
416
  reason: CancellationRefusal;
417
417
  };
418
- /** States from which no further work is dispatched. */
419
- export declare const TERMINAL_STATES: readonly TaskState[];
420
418
  export type Task = {
421
419
  id: string;
422
420
  title: string;
@@ -486,18 +484,6 @@ export type TaskRef = {
486
484
  /** Recorded, not asserted: what the grant's selector is checked against. */
487
485
  origin: TaskOrigin;
488
486
  };
489
- /** A standing order: a pre-approved template whose instances build unattended. */
490
- export type ExecutionSlot = {
491
- id: number;
492
- runner: string;
493
- state: "reserved" | "running" | "released";
494
- run: number | null;
495
- incarnation: string | null;
496
- processGroup: number | null;
497
- reservedAt: string;
498
- runningAt: string | null;
499
- releasedAt: string | null;
500
- };
501
487
  /** Chat providers are direct API adapters — a DISJOINT type from the build
502
488
  * harness providers, by design (Codex v3 review, change 1). */
503
489
  export type DirectChatProviderId = "anthropic-api" | "openrouter-api";
@@ -999,8 +985,6 @@ export type Capability = {
999
985
  lastResult: string | null;
1000
986
  expiresAt: string | null;
1001
987
  };
1002
- /** `kind:name`, the unambiguous way a requirement names a capability. */
1003
- export declare function capabilityKey(capability: Pick<Capability, "kind" | "name">): string;
1004
988
  /** Parse `kind:name`; a bare name is refused rather than guessed at. */
1005
989
  export declare function parseCapabilityKey(key: string): {
1006
990
  kind: Capability["kind"];
@@ -2297,7 +2281,6 @@ export declare class Store {
2297
2281
  mirrorAllowsCompletion(taskId: string): boolean;
2298
2282
  /** Whether a stored acquire mutation exists — the replay marker's fact. */
2299
2283
  hasMutationRecord(mutation: Mutation): boolean;
2300
- enqueueExternalIntent(mirror: string, kind: "comment" | "transition" | "close", body: string | null, now: Date): void;
2301
2284
  pendingExternalIntents(limit?: number): {
2302
2285
  id: number;
2303
2286
  mirror: string;
@@ -4053,24 +4036,6 @@ export declare class Store {
4053
4036
  liveClaimByLease(leaseId: string, now: Date): {
4054
4037
  leaseId: string;
4055
4038
  } | null;
4056
- reserveExecutionSlots(runner: string, count: number, now: Date): number[];
4057
- /** reserved → running happens in the stamp-before-spawn moment, carrying
4058
- * the process group so recovery can ask the OS before freeing capacity. */
4059
- markSlotRunning(id: number, facts: {
4060
- run: number;
4061
- incarnation?: string | null;
4062
- processGroup?: number | null;
4063
- }, now: Date): boolean;
4064
- /** A correction process replaces the exited provider in the same open
4065
- * root attempt. It may refresh only that attempt's exact occupied slot. */
4066
- refreshSlotProcess(id: number, facts: {
4067
- run: number;
4068
- incarnation?: string | null;
4069
- processGroup: number;
4070
- }): boolean;
4071
- releaseExecutionSlot(id: number, now: Date): boolean;
4072
- liveSlotCount(runner: string): number;
4073
- getExecutionSlot(id: number): ExecutionSlot | null;
4074
4039
  /** Minted from a POST, never a GET. Bounded per approver; expired rows
4075
4040
  * are swept rather than accumulating. */
4076
4041
  mintCeremonyNonce(spec: {
@@ -4868,22 +4833,6 @@ export declare class Store {
4868
4833
  listTasksScoped(repo: string | null, state: TaskState | undefined, limit: number, selectedId: string | null): (Task & {
4869
4834
  repo: string | null;
4870
4835
  })[];
4871
- /**
4872
- * The Work destination's one bounded page (workspace package 1 query):
4873
- * the newest tasks the viewer may see, with the viewer's already-proved
4874
- * admission bound BEFORE the ordering and the limit — never a wider
4875
- * read post-filtered in the caller. `admitted` is the resolved
4876
- * permitted repo set: `null` means unrestricted (every placed row),
4877
- * `[]` means no placed project is permitted (no placed row at all).
4878
- * `includeUnplaced` says whether NULL-repo rows belong to this viewer;
4879
- * an account restricted to projects never sees them, so they must not
4880
- * spend its page. Every predicate is a bound parameter; the limit is
4881
- * clamped here, not trusted from the caller. Read-only; the legacy
4882
- * `listTasksScoped` is untouched.
4883
- */
4884
- listWorkTasksAdmitted(admitted: readonly string[] | null, includeUnplaced: boolean, limit: number): (Task & {
4885
- repo: string | null;
4886
- })[];
4887
4836
  /** Newest first, because the question is almost always "what just happened". */
4888
4837
  runsFor(taskRef: number): Run[];
4889
4838
  /**
@@ -5309,7 +5258,6 @@ export declare class Store {
5309
5258
  run: number;
5310
5259
  kind: Incident["kind"];
5311
5260
  }, now: Date): number;
5312
- incidentForRun(run: number): Incident | null;
5313
5261
  /** Unresolved, task attached, oldest first. No time window: these do not age out. */
5314
5262
  openIncidents(repo?: string | null): (Incident & {
5315
5263
  taskId: string;
@@ -5516,9 +5464,6 @@ export declare class Store {
5516
5464
  claimMergeIntent(id: number, by: string, leaseMs: number, now: Date): {
5517
5465
  generation: number;
5518
5466
  } | null;
5519
- /** Renew the lease AND re-prove the generation in one CAS — the last
5520
- * gate before the external call; a failed re-proof aborts the attempt. */
5521
- renewMergeClaim(id: number, generation: number, leaseMs: number, now: Date): boolean;
5522
5467
  /** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
5523
5468
  * state it believes it owns, and a terminal row is never overwritten —
5524
5469
  * a stale claim owner cannot un-merge what the observer already settled,
@@ -5583,12 +5528,6 @@ export declare class Store {
5583
5528
  lastError: string | null;
5584
5529
  firingDeadline: string | null;
5585
5530
  } | null;
5586
- latestObservation(githubRepo: string, prNumber: number): {
5587
- headSha: string;
5588
- state: string;
5589
- observedAt: string;
5590
- generation: number;
5591
- } | null;
5592
5531
  /** Revocation is immediate: intents not yet pushed die with the grant. */
5593
5532
  revokePublicationGrant(repo: string, by: string, now: Date): boolean;
5594
5533
  publicationGrantFor(repo: string): PublicationGrant | null;
@@ -6408,7 +6347,6 @@ export declare class Store {
6408
6347
  recentLeadTurns(approver: string, limit?: number): LeadTurn[];
6409
6348
  getLeadTurn(id: number): LeadTurn | null;
6410
6349
  liveLeadTurnFor(approver: string): LeadTurn | null;
6411
- leadStepsOf(leadTurn: number): ChatTurn[];
6412
6350
  /** Remember a project was opened. Upsert keeps added_at; recency always moves.
6413
6351
  * A project added for the first time starts on Quick checks. */
6414
6352
  upsertProject(path: string, name: string, now: Date, admission?: {
@@ -6469,17 +6407,6 @@ export declare class Store {
6469
6407
  repo: string | null;
6470
6408
  blockerRepo: string | null;
6471
6409
  }[];
6472
- /**
6473
- * Active work only, running first — the Work tab's page. Terminal history
6474
- * belongs to Done and the build ledger, never to this list.
6475
- */
6476
- listActiveWorkScoped(repo: string | null, now: Date, limit?: number): (Task & {
6477
- repo: string | null;
6478
- approved: boolean;
6479
- held: boolean;
6480
- buildingBy: string | null;
6481
- strikes: number;
6482
- })[];
6483
6410
  /**
6484
6411
  * Completed work, one row per done task with its final accepted run and
6485
6412
  * any publication attached — never composed from separate task and PR
package/dist/store.js CHANGED
@@ -68,13 +68,13 @@ import { containerEmptiness } from "./container-state.js";
68
68
  import { hasDisguisedText, hasForbiddenControls, validateNote } from "./decision.js";
69
69
  import { parseReviewContext, reviewContextCustodyProblem } from "./review-context.js";
70
70
  import { foldReview, manualReviewOnly } from "./proof.js";
71
- 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";
72
72
  import { resolveScopeProfile, resolveRouteCandidates, exactPinOf, routeOfTask, agentChoicesFor } from "./agentconfig.js";
73
- 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";
74
74
  import { readAuthModeStrict } from "./keys.js";
75
75
  import { modeDigestOf, modeTermsFromJson } from "./modes.js";
76
76
  import { readVerifiedArtifact } from "./evidence.js";
77
- import { isProviderId } from "./provider.js";
77
+ import {} from "./provider.js";
78
78
  import { authenticate as runnerAuthenticate } from "./runner.js";
79
79
  import { stampNewProjectLevel } from "./check-levels.js";
80
80
  import { parseCheckProgressSnapshot } from "./check-progress.js";
@@ -1177,8 +1177,6 @@ CREATE INDEX IF NOT EXISTS sso_identity_account ON sso_identity (account);
1177
1177
  */
1178
1178
  /** The backend name the built-in store registers itself under. */
1179
1179
  export const BUILT_IN = "built-in";
1180
- /** States from which no further work is dispatched. */
1181
- export const TERMINAL_STATES = ["done", "failed", "cancelled"];
1182
1180
  export const LEAD_THREAD = { kind: "lead" };
1183
1181
  /** A lead_message row as a LeadMessage. */
1184
1182
  function readLeadMessageRow(row) {
@@ -1298,10 +1296,6 @@ function readFlowReceipt(row) {
1298
1296
  const optional = (key) => row[key] === null || row[key] === undefined ? null : String(row[key]);
1299
1297
  return { state, card, note: optional("note"), at: String(row["at"]), acceptedAt: optional("accepted_at"), itemJson: optional("item_json") };
1300
1298
  }
1301
- /** `kind:name`, the unambiguous way a requirement names a capability. */
1302
- export function capabilityKey(capability) {
1303
- return `${capability.kind}:${capability.name}`;
1304
- }
1305
1299
  /** Parse `kind:name`; a bare name is refused rather than guessed at. */
1306
1300
  export function parseCapabilityKey(key) {
1307
1301
  const split = key.indexOf(":");
@@ -6413,11 +6407,6 @@ export class Store {
6413
6407
  .get(mutation.idempotencyKey);
6414
6408
  return row !== undefined;
6415
6409
  }
6416
- enqueueExternalIntent(mirror, kind, body, now) {
6417
- this.db
6418
- .prepare("INSERT INTO external_intent (mirror, kind, body, created_at) VALUES (?, ?, ?, ?)")
6419
- .run(mirror, kind, body, now.toISOString());
6420
- }
6421
6410
  pendingExternalIntents(limit = 50) {
6422
6411
  return this.db
6423
6412
  .prepare("SELECT id, mirror, kind, body, attempts FROM external_intent WHERE state = 'pending' ORDER BY id LIMIT ?")
@@ -11423,54 +11412,6 @@ export class Store {
11423
11412
  return row === undefined ? null : { leaseId: String(row["lease_id"]) };
11424
11413
  }
11425
11414
  // ---- worker-process slots (v14, finding 26) ----------------------------
11426
- reserveExecutionSlots(runner, count, now) {
11427
- return this.transact(() => {
11428
- const ids = [];
11429
- for (let index = 0; index < count; index++) {
11430
- const inserted = this.db
11431
- .prepare("INSERT INTO execution_slot (runner, reserved_at) VALUES (?, ?)")
11432
- .run(runner, now.toISOString());
11433
- ids.push(Number(inserted.lastInsertRowid));
11434
- }
11435
- return ids;
11436
- });
11437
- }
11438
- /** reserved → running happens in the stamp-before-spawn moment, carrying
11439
- * the process group so recovery can ask the OS before freeing capacity. */
11440
- markSlotRunning(id, facts, now) {
11441
- const changed = this.db
11442
- .prepare(`UPDATE execution_slot SET state = 'running', run = ?, incarnation = ?, process_group = ?, running_at = ?
11443
- WHERE id = ? AND state = 'reserved'`)
11444
- .run(facts.run, facts.incarnation ?? null, facts.processGroup ?? null, now.toISOString(), id);
11445
- return Number(changed.changes) === 1;
11446
- }
11447
- /** A correction process replaces the exited provider in the same open
11448
- * root attempt. It may refresh only that attempt's exact occupied slot. */
11449
- refreshSlotProcess(id, facts) {
11450
- if (!Number.isInteger(facts.processGroup) || facts.processGroup <= 0)
11451
- return false;
11452
- const changed = this.db.prepare(`UPDATE execution_slot SET process_group = ?
11453
- WHERE id = ? AND state = 'running' AND run = ? AND incarnation IS ?
11454
- AND EXISTS (SELECT 1 FROM run WHERE id = ? AND outcome IS NULL)`)
11455
- .run(facts.processGroup, id, facts.run, facts.incarnation ?? null, facts.run);
11456
- return Number(changed.changes) === 1;
11457
- }
11458
- releaseExecutionSlot(id, now) {
11459
- const changed = this.db
11460
- .prepare("UPDATE execution_slot SET state = 'released', released_at = ? WHERE id = ? AND state IN ('reserved','running')")
11461
- .run(now.toISOString(), id);
11462
- return Number(changed.changes) === 1;
11463
- }
11464
- liveSlotCount(runner) {
11465
- const row = this.db
11466
- .prepare("SELECT COUNT(*) AS n FROM execution_slot WHERE runner = ? AND state IN ('reserved','running')")
11467
- .get(runner);
11468
- return Number(row?.["n"] ?? 0);
11469
- }
11470
- getExecutionSlot(id) {
11471
- const row = this.db.prepare("SELECT * FROM execution_slot WHERE id = ?").get(id);
11472
- return row === undefined ? null : readExecutionSlot(row);
11473
- }
11474
11415
  // ---- durable ceremony nonces (v14, findings 21/30) ---------------------
11475
11416
  /** Minted from a POST, never a GET. Bounded per approver; expired rows
11476
11417
  * are swept rather than accumulating. */
@@ -13528,40 +13469,6 @@ export class Store {
13528
13469
  repo: row["task_repo"] === null ? null : String(row["task_repo"]),
13529
13470
  }));
13530
13471
  }
13531
- /**
13532
- * The Work destination's one bounded page (workspace package 1 query):
13533
- * the newest tasks the viewer may see, with the viewer's already-proved
13534
- * admission bound BEFORE the ordering and the limit — never a wider
13535
- * read post-filtered in the caller. `admitted` is the resolved
13536
- * permitted repo set: `null` means unrestricted (every placed row),
13537
- * `[]` means no placed project is permitted (no placed row at all).
13538
- * `includeUnplaced` says whether NULL-repo rows belong to this viewer;
13539
- * an account restricted to projects never sees them, so they must not
13540
- * spend its page. Every predicate is a bound parameter; the limit is
13541
- * clamped here, not trusted from the caller. Read-only; the legacy
13542
- * `listTasksScoped` is untouched.
13543
- */
13544
- listWorkTasksAdmitted(admitted, includeUnplaced, limit) {
13545
- const page = Math.max(1, Math.min(Math.floor(limit), 500));
13546
- // SQLite accepts an empty IN list, so an empty admission binds as
13547
- // "no placed row" without any special SQL shape.
13548
- const rows = this.db
13549
- .prepare(`SELECT task.*, task_ref.repo AS task_repo FROM task
13550
- JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
13551
- WHERE ((task_ref.repo IS NULL AND ? = 1)
13552
- OR (task_ref.repo IS NOT NULL AND (? = 1 OR task_ref.repo IN (${(admitted ?? []).map(() => "?").join(",")}))))
13553
- ORDER BY task.created_at DESC, task.id DESC LIMIT ?`)
13554
- .all(BUILT_IN, includeUnplaced ? 1 : 0, admitted === null ? 1 : 0, ...(admitted ?? []), page);
13555
- return rows.map(row => ({
13556
- id: String(row["id"]),
13557
- title: String(row["title"]),
13558
- state: String(row["state"]),
13559
- createdAt: String(row["created_at"]),
13560
- updatedAt: String(row["updated_at"]),
13561
- priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
13562
- repo: row["task_repo"] === null ? null : String(row["task_repo"]),
13563
- }));
13564
- }
13565
13472
  /** Newest first, because the question is almost always "what just happened". */
13566
13473
  runsFor(taskRef) {
13567
13474
  return this.db
@@ -14507,10 +14414,6 @@ export class Store {
14507
14414
  .run(incident.run, incident.kind, now.toISOString());
14508
14415
  return Number(inserted.lastInsertRowid);
14509
14416
  }
14510
- incidentForRun(run) {
14511
- const row = this.db.prepare("SELECT * FROM incident WHERE run = ?").get(run);
14512
- return row === undefined ? null : readIncident(row);
14513
- }
14514
14417
  /** Unresolved, task attached, oldest first. No time window: these do not age out. */
14515
14418
  openIncidents(repo = null) {
14516
14419
  return this.db
@@ -14872,14 +14775,6 @@ export class Store {
14872
14775
  return Number(changes) === 1 ? { generation } : null;
14873
14776
  });
14874
14777
  }
14875
- /** Renew the lease AND re-prove the generation in one CAS — the last
14876
- * gate before the external call; a failed re-proof aborts the attempt. */
14877
- renewMergeClaim(id, generation, leaseMs, now) {
14878
- const { changes } = this.db
14879
- .prepare("UPDATE merge_intent SET claimed_until = ? WHERE id = ? AND state = 'claimed' AND generation = ?")
14880
- .run(new Date(now.getTime() + leaseMs).toISOString(), id, generation);
14881
- return Number(changes) === 1;
14882
- }
14883
14778
  /** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
14884
14779
  * state it believes it owns, and a terminal row is never overwritten —
14885
14780
  * a stale claim owner cannot un-merge what the observer already settled,
@@ -15029,14 +14924,6 @@ export class Store {
15029
14924
  firingDeadline: row["firing_deadline"] === null ? null : String(row["firing_deadline"]),
15030
14925
  };
15031
14926
  }
15032
- latestObservation(githubRepo, prNumber) {
15033
- const row = this.db
15034
- .prepare("SELECT head_sha, state, observed_at, generation FROM ci_observation WHERE github_repo = ? AND pr_number = ?")
15035
- .get(githubRepo, prNumber);
15036
- return row === undefined || String(row["observed_at"]) === ""
15037
- ? null
15038
- : { headSha: String(row["head_sha"]), state: String(row["state"]), observedAt: String(row["observed_at"]), generation: Number(row["generation"]) };
15039
- }
15040
14927
  /** Revocation is immediate: intents not yet pushed die with the grant. */
15041
14928
  revokePublicationGrant(repo, by, now) {
15042
14929
  const { changes } = this.db
@@ -16635,9 +16522,6 @@ export class Store {
16635
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);
16636
16523
  return row === undefined ? null : readLeadTurn(row);
16637
16524
  }
16638
- leadStepsOf(leadTurn) {
16639
- return this.db.prepare("SELECT * FROM chat_turn WHERE mate_turn = ? ORDER BY id ASC").all(leadTurn).map(readChatTurn);
16640
- }
16641
16525
  // ---- projects ------------------------------------------------------------
16642
16526
  /** Remember a project was opened. Upsert keeps added_at; recency always moves.
16643
16527
  * A project added for the first time starts on Quick checks. */
@@ -16808,50 +16692,6 @@ export class Store {
16808
16692
  blockerRepo: row["blocker_repo"] === null || row["blocker_repo"] === undefined ? null : String(row["blocker_repo"]),
16809
16693
  }));
16810
16694
  }
16811
- /**
16812
- * Active work only, running first — the Work tab's page. Terminal history
16813
- * belongs to Done and the build ledger, never to this list.
16814
- */
16815
- listActiveWorkScoped(repo, now, limit = 50) {
16816
- const page = Math.max(1, Math.min(Math.floor(limit), 100));
16817
- return this.db
16818
- .prepare(`SELECT task.*, task_ref.repo AS task_repo, task_ref.strikes AS ref_strikes,
16819
- EXISTS (
16820
- SELECT 1 FROM task_scope
16821
- WHERE task_scope.task_id = task.id AND task_scope.approved_digest = task_scope.digest
16822
- AND task_scope.approved_at IS NOT NULL
16823
- ) AS approved,
16824
- EXISTS (
16825
- SELECT 1 FROM hold
16826
- WHERE hold.task_ref = task_ref.id AND (hold.until IS NULL OR hold.until > ?)
16827
- ) AS held,
16828
- (SELECT claim.runner FROM claim
16829
- WHERE claim.task_ref = task_ref.id AND claim.released_at IS NULL AND claim.expires_at > ?
16830
- AND claim.lease_generation = (
16831
- SELECT MAX(newest.lease_generation) FROM claim AS newest
16832
- WHERE newest.task_ref = claim.task_ref)
16833
- LIMIT 1) AS building_by
16834
- FROM task
16835
- JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
16836
- WHERE task.state IN ('running','queued')
16837
- AND (? IS NULL OR task_ref.repo IS NULL OR task_ref.repo = ?)
16838
- ORDER BY CASE task.state WHEN 'running' THEN 0 ELSE 1 END, task.updated_at DESC, task.id DESC
16839
- LIMIT ?`)
16840
- .all(now.toISOString(), now.toISOString(), BUILT_IN, repo, repo, page)
16841
- .map(row => ({
16842
- id: String(row["id"]),
16843
- title: String(row["title"]),
16844
- state: String(row["state"]),
16845
- createdAt: String(row["created_at"]),
16846
- updatedAt: String(row["updated_at"]),
16847
- priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
16848
- repo: row["task_repo"] === null ? null : String(row["task_repo"]),
16849
- approved: Number(row["approved"]) === 1,
16850
- held: Number(row["held"]) === 1,
16851
- buildingBy: row["building_by"] === null ? null : String(row["building_by"]),
16852
- strikes: Number(row["ref_strikes"]),
16853
- }));
16854
- }
16855
16695
  /**
16856
16696
  * Completed work, one row per done task with its final accepted run and
16857
16697
  * any publication attached — never composed from separate task and PR
@@ -19544,20 +19384,6 @@ function readTaskRef(row) {
19544
19384
  origin: String(row["origin"]) === "ours" ? "ours" : "theirs",
19545
19385
  };
19546
19386
  }
19547
- function readExecutionSlot(row) {
19548
- const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
19549
- return {
19550
- id: Number(row["id"]),
19551
- runner: String(row["runner"]),
19552
- state: String(row["state"]),
19553
- run: row["run"] === null ? null : Number(row["run"]),
19554
- incarnation: maybe("incarnation"),
19555
- processGroup: row["process_group"] === null ? null : Number(row["process_group"]),
19556
- reservedAt: String(row["reserved_at"]),
19557
- runningAt: maybe("running_at"),
19558
- releasedAt: maybe("released_at"),
19559
- };
19560
- }
19561
19387
  function readChatTurn(row) {
19562
19388
  const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
19563
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". */
package/dist/subagents.js CHANGED
@@ -17,21 +17,17 @@
17
17
  * spending — those stay with people (or a signed hands-off mode).
18
18
  */
19
19
  import { Buffer } from "node:buffer";
20
- import { mkdtempSync, rmSync } from "node:fs";
21
- import { tmpdir } from "node:os";
22
- import { join } from "node:path";
23
20
  import { strictJsonParse } from "./converse.js";
24
21
  import { scanForSecrets } from "./evidence.js";
25
22
  import { run } from "./exec.js";
23
+ import { CLAUDE_NO_TOOLS_ARGS, CLAUDE_SIGNED_OUT, claudeJsonBody, claudeModelArgs, inScratchDir } from "./claude-print.js";
26
24
  import { ALL_CREDENTIAL_ENV } from "./provider.js";
27
25
  import { readTurnAnswer, TURN_MODEL_SCHEMA } from "./contracts/subagent-turn.js";
28
26
  import { LIMITS } from "./decision.js";
29
27
  import { overruns, TEXT_LIMITS } from "./text-limits.js";
30
28
  export const SOUL_CHARS = 12_000;
31
- const HANDLE = /^[a-z0-9][a-z0-9-]{0,31}$/;
32
29
  /** A handle from a name: "Maya" → "maya". */
33
30
  export const handleOf = (name) => name.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "subagent";
34
- export const isHandle = (value) => typeof value === "string" && HANDLE.test(value);
35
31
  /** A soul file read: its name and role (front matter) and its sections. */
36
32
  export function parseSoul(text) {
37
33
  const normal = text.replace(/\r\n?/g, "\n").trim();
@@ -220,36 +216,27 @@ export function readTurn(value, context) {
220
216
  export const TURN_TIMEOUT_MS = 180_000;
221
217
  /** 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. */
222
218
  export function claudeTurnRunner(runner = run) {
223
- return async (request) => {
224
- const dir = mkdtempSync(join(tmpdir(), "standing-orders-subagent-"));
219
+ return request => inScratchDir("standing-orders-subagent-", async (dir) => {
225
220
  const started = Date.now();
226
- try {
227
- const result = await runner("claude", [
228
- "-p", "--output-format", "json", "--json-schema", JSON.stringify(TURN_MODEL_SCHEMA), "--safe-mode", "--no-session-persistence", "--tools", "", "--permission-mode", "dontAsk",
229
- "--permission-prompts", "none", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}',
230
- ...(request.model === "default" ? [] : ["--model", request.model]),
231
- ], { cwd: dir, stdin: request.prompt, timeoutMs: request.timeoutMs, maxBuffer: 512 * 1024, omitEnv: ALL_CREDENTIAL_ENV, processGroup: true });
232
- if (result.notFound)
233
- return { ok: false, said: "Claude isn't installed on this computer." };
234
- if (result.timedOut)
235
- return { ok: false, said: "Claude took too long to decide." };
236
- const parsed = strictJsonParse(Buffer.from(result.stdout, "utf8"), 512 * 1024, 12);
237
- const body = parsed.ok && typeof parsed.value === "object" && parsed.value !== null && !Array.isArray(parsed.value) ? parsed.value : null;
238
- if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success") {
239
- const why = typeof body?.["subtype"] === "string" && body["subtype"] !== "success" ? ` (${String(body["subtype"]).replace(/_/g, " ").slice(0, 60)})` : result.code !== 0 ? ` (exit ${result.code})` : "";
240
- return { ok: false, said: /not logged in|login|authenticat/i.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : `Claude couldn't decide${why}.` };
241
- }
242
- const cost = costOf(body);
243
- if (body["structured_output"] !== undefined && body["structured_output"] !== null)
244
- return { ok: true, value: body["structured_output"], ms: Date.now() - started, ...cost };
245
- const text = typeof body["result"] === "string" ? body["result"].trim().replace(/^```(?:json)?\n?|\n?```$/g, "") : "";
246
- const inner = strictJsonParse(Buffer.from(text, "utf8"), 64 * 1024, 8);
247
- return inner.ok ? { ok: true, value: inner.value, ms: Date.now() - started, ...cost } : { ok: false, said: "Claude's answer wasn't a decision.", ...cost };
221
+ const result = await runner("claude", [
222
+ "-p", "--output-format", "json", "--json-schema", JSON.stringify(TURN_MODEL_SCHEMA), ...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
223
+ ], { cwd: dir, stdin: request.prompt, timeoutMs: request.timeoutMs, maxBuffer: 512 * 1024, omitEnv: ALL_CREDENTIAL_ENV, processGroup: true });
224
+ if (result.notFound)
225
+ return { ok: false, said: "Claude isn't installed on this computer." };
226
+ if (result.timedOut)
227
+ return { ok: false, said: "Claude took too long to decide." };
228
+ const body = claudeJsonBody(result.stdout, 512 * 1024);
229
+ if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success") {
230
+ const why = typeof body?.["subtype"] === "string" && body["subtype"] !== "success" ? ` (${String(body["subtype"]).replace(/_/g, " ").slice(0, 60)})` : result.code !== 0 ? ` (exit ${result.code})` : "";
231
+ return { ok: false, said: CLAUDE_SIGNED_OUT.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : `Claude couldn't decide${why}.` };
248
232
  }
249
- finally {
250
- rmSync(dir, { recursive: true, force: true });
251
- }
252
- };
233
+ const cost = costOf(body);
234
+ if (body["structured_output"] !== undefined && body["structured_output"] !== null)
235
+ return { ok: true, value: body["structured_output"], ms: Date.now() - started, ...cost };
236
+ const text = typeof body["result"] === "string" ? body["result"].trim().replace(/^```(?:json)?\n?|\n?```$/g, "") : "";
237
+ const inner = strictJsonParse(Buffer.from(text, "utf8"), 64 * 1024, 8);
238
+ return inner.ok ? { ok: true, value: inner.value, ms: Date.now() - started, ...cost } : { ok: false, said: "Claude's answer wasn't a decision.", ...cost };
239
+ });
253
240
  }
254
241
  /** What the CLI says a turn cost, and its tokens (cache reads and writes count as input). */
255
242
  function costOf(body) {
@@ -1,5 +1,5 @@
1
1
  import { type LeadHistoryMessage, type LeadProviderAnswer, type LeadToolSchema } from "./converse.js";
2
- import { run, type ExecResult } from "./exec.js";
2
+ import { type CommandRunner } from "./claude-print.js";
3
3
  import type { SubscriptionChatProviderId } from "./store.js";
4
4
  export type SubscriptionLeadRequest = {
5
5
  provider: SubscriptionChatProviderId;
@@ -27,7 +27,6 @@ export type SubscriptionLeadRunner = (request: SubscriptionLeadRequest) => Promi
27
27
  ok: false;
28
28
  problem: string;
29
29
  }>;
30
- type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
31
30
  /** The model-visible request. Tool results are already redacted by leadView. */
32
31
  export declare function composeSubscriptionLeadPrompt(request: Omit<SubscriptionLeadRequest, "provider" | "model" | "timeoutMs" | "signal">): string;
33
32
  /** Strictly turn the harness's structured output into the provider-neutral answer. */
@@ -49,4 +48,3 @@ export declare function performSubscriptionLeadRequest(request: SubscriptionLead
49
48
  ok: false;
50
49
  problem: string;
51
50
  }>;
52
- export {};
@@ -16,6 +16,7 @@ import { tmpdir } from "node:os";
16
16
  import { join } from "node:path";
17
17
  import { LEAD_MAX_CALLS_PER_STEP, LEAD_STEP_TEXT_CAP_BYTES, LEAD_TOOL_CALL_CAP_BYTES, LEAD_TOOL_CALL_ID_CAP_BYTES, strictJsonParse, tokenCount, } from "./converse.js";
18
18
  import { run } from "./exec.js";
19
+ import { CLAUDE_NO_TOOLS_ARGS, claudeModelArgs } from "./claude-print.js";
19
20
  import { claudeStreamReader } from "./lead-progress.js";
20
21
  import { ALL_CREDENTIAL_ENV } from "./provider.js";
21
22
  import { claudeLimitsOf, noteLimits } from "./provider-limits.js";
@@ -215,9 +216,7 @@ export async function performSubscriptionLeadRequest(request, runner = run) {
215
216
  // Streaming (someone is watching): the same answer, delivered as
216
217
  // events whose final `result` line is the whole structured reply.
217
218
  "-p", ...(streaming ? ["--output-format", "stream-json", "--verbose", "--include-partial-messages"] : ["--output-format", "json"]), "--json-schema", JSON.stringify(schema),
218
- "--safe-mode", "--no-session-persistence", "--tools", "", "--permission-mode", "dontAsk",
219
- "--permission-prompts", "none", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}',
220
- ...(request.model === "default" ? [] : ["--model", request.model]),
219
+ ...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
221
220
  ];
222
221
  }
223
222
  const result = await runner(command, args, {
@@ -1,5 +1,5 @@
1
1
  import { type SizeAnswer } from "./contracts/task-sizing.js";
2
- import { run, type ExecResult } from "./exec.js";
2
+ import { type CommandRunner } from "./claude-print.js";
3
3
  import { type TaskSizing } from "./phase-routing.js";
4
4
  import type { Store } from "./store.js";
5
5
  /** The classifier's whole budget, from asking to answer. */
@@ -24,7 +24,6 @@ export declare function planningSignals(input: SizingInput): boolean;
24
24
  export declare function heuristicSizing(input: SizingInput, why?: string | null): TaskSizing;
25
25
  /** What the classifier reads: the task as data, bounded, keys blanked. */
26
26
  export declare function sizingText(input: SizingInput): string;
27
- type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
28
27
  /** A small Claude model on this computer's sign-in: no tools, no MCP servers, no repository, credential keys stripped.
29
28
  * The abort ends it: a late answer never keeps a command (or its process) waiting. */
30
29
  export declare function claudeSizer(runner?: CommandRunner, model?: string, budgetMs?: number): Sizer;
@@ -41,8 +40,6 @@ export declare function classifyTask(input: SizingInput, sizer: Sizer | null, bu
41
40
  /** Install the process's classifier for filings (the CLI, the console, the worker); returns how to remove it. Unset,
42
41
  * filings keep the description's size — tests never spend a turn. */
43
42
  export declare function installFilingSizer(sizer: Sizer, budgetMs?: number): () => void;
44
- /** Whether filings in this process are classified. */
45
- export declare function filingSizerInstalled(): boolean;
46
43
  /**
47
44
  * After a filing: ask the classifier (within the budget) and apply its size
48
45
  * to the still-unapproved task. Runs in the background; the filing already