toolroll 0.9.57 → 0.9.59

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 (73) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/action-ledger.js +10 -5
  3. package/dist/actor.d.ts +0 -10
  4. package/dist/actor.js +1 -18
  5. package/dist/api-tokens.d.ts +33 -2
  6. package/dist/api-tokens.js +39 -11
  7. package/dist/assignment-delivery.js +1 -1
  8. package/dist/assignment-status.js +1 -1
  9. package/dist/assignment.js +3 -2
  10. package/dist/browser/workspace.js +1 -1
  11. package/dist/builder.js +4 -2
  12. package/dist/chat-channel.d.ts +1 -0
  13. package/dist/chat-channel.js +3 -0
  14. package/dist/chat-delivery.js +2 -0
  15. package/dist/cli-http.d.ts +7 -0
  16. package/dist/cli-http.js +30 -4
  17. package/dist/cli.js +2 -1
  18. package/dist/contract-changes.d.ts +52 -0
  19. package/dist/contract-changes.js +61 -0
  20. package/dist/coordinator.d.ts +2 -1
  21. package/dist/coordinator.js +22 -31
  22. package/dist/decision.d.ts +4 -0
  23. package/dist/decision.js +8 -0
  24. package/dist/deploy-lock.d.ts +8 -0
  25. package/dist/deploy-lock.js +45 -0
  26. package/dist/desktop-update.d.ts +1 -1
  27. package/dist/dispatch.js +1 -1
  28. package/dist/export.js +2 -2
  29. package/dist/lead-cli.js +3 -0
  30. package/dist/lead-doors.js +3 -0
  31. package/dist/lead-tools.js +2 -1
  32. package/dist/mcp-http.js +5 -5
  33. package/dist/needs-you.js +3 -1
  34. package/dist/operate.js +23 -11
  35. package/dist/password-bearer.d.ts +27 -0
  36. package/dist/password-bearer.js +59 -0
  37. package/dist/planner-source.d.ts +23 -53
  38. package/dist/planner-source.js +43 -68
  39. package/dist/release-gate.d.ts +2 -3
  40. package/dist/release-gate.js +44 -16
  41. package/dist/remote-command.js +0 -2
  42. package/dist/remote-exec.d.ts +19 -0
  43. package/dist/remote-exec.js +9 -8
  44. package/dist/request-budget.d.ts +1 -1
  45. package/dist/scope.js +16 -1
  46. package/dist/serve.js +15 -0
  47. package/dist/server/edge-refusal.d.ts +2 -0
  48. package/dist/server/edge-refusal.js +8 -6
  49. package/dist/server/guards.js +5 -4
  50. package/dist/server/http.d.ts +2 -0
  51. package/dist/server/remote.js +6 -13
  52. package/dist/server/render-chat.js +10 -0
  53. package/dist/server/render-tasks.js +19 -9
  54. package/dist/server/route-table.js +0 -3
  55. package/dist/server/tasks.js +3 -1
  56. package/dist/session-cli.d.ts +38 -9
  57. package/dist/session-cli.js +141 -154
  58. package/dist/session-contract.js +2 -2
  59. package/dist/session-remote.d.ts +19 -0
  60. package/dist/session-remote.js +86 -0
  61. package/dist/store.d.ts +72 -12
  62. package/dist/store.js +367 -105
  63. package/dist/task-status.js +3 -1
  64. package/dist/team-cli.d.ts +3 -0
  65. package/dist/team-cli.js +23 -3
  66. package/dist/telegram-lead.js +6 -0
  67. package/dist/telegram.js +9 -7
  68. package/dist/toolroll-update.js +10 -1
  69. package/package.json +1 -1
  70. package/dist/session-http.d.ts +0 -24
  71. package/dist/session-http.js +0 -170
  72. package/dist/session-server.d.ts +0 -17
  73. package/dist/session-server.js +0 -39
package/dist/store.d.ts CHANGED
@@ -7,7 +7,7 @@ import { type SavedToolAction, type SavedToolRule } from "./contracts/store-json
7
7
  import type { FlowCardChange, FlowCardFields } from "./contracts/flow-card.js";
8
8
  import { type Actor } from "./actor.js";
9
9
  import { type LiveActivityKind } from "./live.js";
10
- import { type TokenPurpose } from "./api-tokens.js";
10
+ import { type CredentialKind, type TokenPurpose } from "./api-tokens.js";
11
11
  import { type CriterionMatrixRow, type CriterionJudgementWord } from "./proof.js";
12
12
  import { type ExecutionProfile, type UnattendedPermissionMode, type AcceptanceCriterion } from "./scope.js";
13
13
  import { type ProviderRoom, type CandidateTier, type TaskSize, type TaskSizing, type PhaseRoute, type PublicationAuthority, type RouteStamp, type ReadinessLookup, type ReadinessObservation, type RouteOverride } from "./phase-routing.js";
@@ -152,13 +152,24 @@ export type SealedLedgerEntry = LedgerEntry & {
152
152
  hash: string;
153
153
  } | null;
154
154
  };
155
- export declare const SCHEMA_VERSION = 117;
155
+ export declare const SCHEMA_VERSION = 119;
156
+ /** v118: the tables merged into `credential`, in the order they move (a person's API tokens keep their ids first). */
157
+ export declare const V118_MERGED_TABLES: Readonly<Record<string, CredentialKind>>;
158
+ /**
159
+ * v118 (D7): one credential table for every machine credential. `id` is the canonical identity every reference holds;
160
+ * `public_id` is the id the secret presents (so_<id>_…, lt_<id>_…) or a coordinator's cid, unique per kind. They are
161
+ * equal unless the merge found two kinds sharing an id. `account` is the person a token acts as (a lead's owner; for
162
+ * a coordinator, who minted it); `projects_json` the project limit (a coordinator's projects); `generation` which
163
+ * issue it is (1, then one more per rotation, per lead token for the same owner, per coordinator of the same name).
164
+ * Lead tokens never expire; a coordinator made before v101 has no expiry.
165
+ */
166
+ export declare const CREDENTIAL_TABLE = "\nCREATE TABLE IF NOT EXISTS credential (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL CHECK (kind IN ('person','lead','coordinator')),\n public_id TEXT NOT NULL,\n account TEXT NOT NULL,\n name TEXT NOT NULL,\n secret_hash TEXT NOT NULL,\n access TEXT NOT NULL CHECK (access IN ('read','act')),\n projects_json TEXT,\n per_hour INTEGER,\n purpose TEXT NOT NULL DEFAULT 'api' CHECK (purpose IN ('api','mcp')),\n generation INTEGER NOT NULL DEFAULT 1 CHECK (generation >= 1),\n created_at TEXT NOT NULL,\n created_by TEXT NOT NULL,\n expires_at TEXT,\n last_used_at TEXT,\n revoked_at TEXT,\n revoked_by TEXT,\n replaces TEXT,\n replaced_by TEXT,\n overlap_until TEXT,\n UNIQUE (kind, public_id)\n);\n";
156
167
  /** v117: each table renamed, by its old name. Rows, ids, foreign keys and indexes go with it (renameForV117). */
157
168
  export declare const V117_RENAMED_TABLES: Readonly<Record<string, string>>;
158
169
  /** v117: the columns renamed with them (by the table's new name): a subagent's rows name it `subagent`. */
159
170
  export declare const V117_RENAMED_COLUMNS: readonly (readonly [table: string, from: string, to: string])[];
160
- /** A row `PRAGMA foreign_key_check` reports, by today's table names: a row already pointing nowhere before v117 is the
161
- * same row after it, though RENAME now reports it (and what it points at) under the new names. */
171
+ /** A row `PRAGMA foreign_key_check` reports, by today's table names: a row already pointing nowhere before v117 (or
172
+ * v118) is the same row after it, though RENAME (or the credential merge) now reports what it points at by the new names. */
162
173
  export declare function orphanKey(row: Record<string, unknown>): string;
163
174
  /** v115: the tables migrateToV115 drops. */
164
175
  export declare const V115_DROPPED_TABLES: readonly string[];
@@ -194,9 +205,18 @@ export declare const V115_DROPPED_TABLES: readonly string[];
194
205
  * transaction that checks each count before the old tables are dropped; the
195
206
  * rehearsal checks each moved table's rows arrived (HISTORY_RULES). v117 renames the mate's tables to the lead's and the
196
207
  * teammates' to its subagents' (SQLite's RENAME, every row, id and link carried), renames their teammate column, and rewrites four internal kinds from 'teammate' to 'subagent' in place; the rehearsal checks
197
- * each renamed table's rows arrived under its new name.
208
+ * each renamed table's rows arrived under its new name. v118 (D7) is checked the same way: every row of api_token,
209
+ * coordinator_credential and lead_credential moves into credential under its kind in one transaction that counts them
210
+ * before the old tables drop, and the references that named them name credential in place, their rows untouched. v119 only adds four columns
211
+ * (planning_generation on task_ref, run and plan_revision, defaulting to 0, and decision.superseded_reason, null);
212
+ * the rehearsal checks every saved row reads the declared default (HISTORY_RULES' added columns).
198
213
  */
199
214
  export declare const UPDATE_SAFE_MIGRATIONS: readonly number[];
215
+ /** v119: the columns it adds, by table, with the value every row saved before it reads (toolroll-update's HISTORY_RULES). */
216
+ export declare const V119_ADDED_COLUMNS: Readonly<Record<string, Readonly<Record<string, {
217
+ definition: string;
218
+ saved: string;
219
+ }>>>>;
200
220
  /** Whether a database settled at `version` reaches this build's schema through update-safe migrations alone. */
201
221
  export declare function updateSafeSchema(version: number | null): boolean;
202
222
  export type OAuthClientRow = {
@@ -317,6 +337,9 @@ export type TaskRef = {
317
337
  plan: "requested" | "drafted" | null;
318
338
  /** Planning failures, counted apart from build strikes by design. */
319
339
  planStrikes: number;
340
+ /** v119: which planning context is active. A rewritten scope advances it; plans, revisions and answers from an
341
+ * earlier generation stay as history, never as the next planner's context. */
342
+ planningGeneration: number;
320
343
  /** What comes back (v34): a branch to publish, or a report to read.
321
344
  * Set at filing and never rewritten — a scout's strikes are the task's. */
322
345
  deliverable: "branch" | "report";
@@ -1037,6 +1060,8 @@ export type Run = {
1037
1060
  taskRef: number;
1038
1061
  leaseId: string;
1039
1062
  runner: string;
1063
+ /** v119: the task's planning generation when this run opened (0 for every run before it). */
1064
+ planningGeneration: number;
1040
1065
  /** Explicit watch ownership for claimless review runs; null on cron/legacy reviews. */
1041
1066
  watchIncarnation?: string | null;
1042
1067
  /** v50: a ROOT reviewer's attempt ordinal for its source run (1..3);
@@ -1181,7 +1206,12 @@ export type Decision = {
1181
1206
  answeredVia: "cli" | "web" | "telegram" | "slack" | "discord" | "teams" | null;
1182
1207
  choice: string | null;
1183
1208
  note: string | null;
1209
+ /** v119: closed without an answer (state 'answered', no choice) because its task's scope changed or the task was
1210
+ * cancelled. null is every real answer and every question still waiting. */
1211
+ supersededReason: DecisionClosure | null;
1184
1212
  };
1213
+ /** Why a question closed without an answer (v119). */
1214
+ export type DecisionClosure = "scope-changed" | "cancelled";
1185
1215
  /** Evidence, by reference. `key` is relative to the evidence root, never absolute. */
1186
1216
  export type Artifact = {
1187
1217
  id: number;
@@ -2358,7 +2388,16 @@ export declare class Store {
2358
2388
  };
2359
2389
  /** v111: record the end of each replaced token whose overlap has passed (it already signs no one in). */
2360
2390
  endRotatedApiTokens(now: Date): number;
2361
- /** A token by id with its kept hash (for the check), or null. */
2391
+ /**
2392
+ * D7: the one check every machine credential takes. The credential a presented secret is (its kind and id), when
2393
+ * its kept hash matches in constant time; null otherwise. Whether it is live, and what its kind may do, stays with
2394
+ * each caller's own policy (a person's API token, a lead token, a coordinator).
2395
+ */
2396
+ presentedCredential(presented: string): {
2397
+ kind: CredentialKind;
2398
+ id: string;
2399
+ } | null;
2400
+ /** A person's API token by id with its kept hash (for the check), or null. */
2362
2401
  apiTokenSecret(id: string): {
2363
2402
  row: ApiTokenRow;
2364
2403
  secretHash: string;
@@ -3424,6 +3463,24 @@ export declare class Store {
3424
3463
  ok: false;
3425
3464
  reason: "live-claim";
3426
3465
  };
3466
+ /**
3467
+ * A rewritten scope starts planning again (v119), in one transaction: the task's planning generation advances, a
3468
+ * requested or drafted plan becomes requested with no strikes, and what the old goal produced leaves the active
3469
+ * planning context — its open questions close (typed 'scope-changed', never a fake answer, their holds and pages
3470
+ * with them) and a revision still waiting for a person is rejected with its hold. The old runs, plans, revisions,
3471
+ * answers and ledger rows all stay: generation-bound reads simply stop offering them to the next planner. Only a
3472
+ * task already planning restarts; false (nothing changed) for any other.
3473
+ */
3474
+ restartPlanning(taskRef: number, now: Date): boolean;
3475
+ /**
3476
+ * Close a task's open and expired questions without answering them (v119): typed with why, no choice, their
3477
+ * holds lifted and their pages resolved, so they leave every decision queue. Answered questions are never touched.
3478
+ * `belowGeneration` limits it to questions asked in earlier planning generations. Caller holds the transaction.
3479
+ */
3480
+ private closeQuestionsLocked;
3481
+ /** The number the next plan revision of a task takes: one past every revision it ever had, in any planning
3482
+ * generation, so a restarted plan's revisions never collide with the history they follow. */
3483
+ nextPlanRevisionNumber(taskRef: number): number;
3427
3484
  /** Move the planning state; null clears it. Caller owns the transaction story. */
3428
3485
  setPlanState(taskRef: number, state: "requested" | "drafted" | null): void;
3429
3486
  addPlanStrike(taskRef: number): number;
@@ -4453,7 +4510,8 @@ export declare class Store {
4453
4510
  * reads in the order the questions arrived. "unanswered" is open + expired:
4454
4511
  * expiry makes a decision louder, never gone.
4455
4512
  */
4456
- /** The newest planner run's plan document for a task, when one exists. */
4513
+ /** The newest planner run's plan document for a task, when one exists in its current planning generation (v119:
4514
+ * a plan drafted for a scope since rewritten is history, read by its artifact id). */
4457
4515
  latestPlanArtifact(taskRef: number): Artifact | null;
4458
4516
  /** The newest plan-contract INGESTION record on one of this task's
4459
4517
  * planner runs (contract handoff, task 1): what the draft proposed
@@ -4486,8 +4544,9 @@ export declare class Store {
4486
4544
  changedFields: readonly string[];
4487
4545
  status: PlanRevisionStatus;
4488
4546
  }, now: Date): number;
4489
- /** Every revision for a task, newest first — the immutable history a
4490
- * reader can show without a second table. */
4547
+ /** Every revision for a task in its current planning generation, newest
4548
+ * first — the immutable history a reader can show without a second table
4549
+ * (v119: an earlier generation's rows stay, read by id). */
4491
4550
  listPlanRevisions(taskRef: number): PlanRevision[];
4492
4551
  /** The current plan revision: the newest row an operator (or an
4493
4552
  * auto-applied plan-only proposal) has actually put in force. Null for
@@ -4544,7 +4603,8 @@ export declare class Store {
4544
4603
  checkpointHistory(run: number): RunCheckpoint[];
4545
4604
  /** The newest scout run's report for a task (v34), when one exists. */
4546
4605
  latestReportArtifact(taskRef: number): Artifact | null;
4547
- /** Answered questions for one task, newest first — the planner's memory. */
4606
+ /** Answered questions for one task, newest first — the planner's memory. Only real answers from its current
4607
+ * planning generation (v119): a question closed unanswered, or asked about a scope since rewritten, is history. */
4548
4608
  answeredDecisionsFor(taskId: string, limit?: number): {
4549
4609
  question: string;
4550
4610
  choice: string | null;
@@ -4646,7 +4706,7 @@ export declare class Store {
4646
4706
  duplicate?: boolean;
4647
4707
  } | {
4648
4708
  ok: false;
4649
- reason: "unknown-decision" | "bad-option" | "already-answered" | "bad-note";
4709
+ reason: "unknown-decision" | "bad-option" | "already-answered" | "closed" | "bad-note";
4650
4710
  };
4651
4711
  /**
4652
4712
  * The answer's body, for callers already holding the transaction — the
@@ -4667,7 +4727,7 @@ export declare class Store {
4667
4727
  duplicate?: boolean;
4668
4728
  } | {
4669
4729
  ok: false;
4670
- reason: "unknown-decision" | "bad-option" | "already-answered" | "bad-note";
4730
+ reason: "unknown-decision" | "bad-option" | "already-answered" | "closed" | "bad-note";
4671
4731
  };
4672
4732
  saveArtifact(artifact: {
4673
4733
  run: number;