toolroll 0.9.48 → 0.9.50

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 (69) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cli-http.js +3 -0
  3. package/dist/desktop-update.d.ts +2 -2
  4. package/dist/flow-triggers.js +7 -0
  5. package/dist/mcp-http.d.ts +1 -0
  6. package/dist/mcp-http.js +12 -15
  7. package/dist/mcp-oauth.d.ts +3 -0
  8. package/dist/mcp-oauth.js +13 -21
  9. package/dist/mcp-person.d.ts +0 -9
  10. package/dist/mcp-person.js +2 -1
  11. package/dist/operate.js +4 -1
  12. package/dist/public-access.d.ts +3 -1
  13. package/dist/public-access.js +5 -1
  14. package/dist/request-budget.d.ts +30 -3
  15. package/dist/request-budget.js +44 -1
  16. package/dist/serve.d.ts +2 -605
  17. package/dist/serve.js +462 -23733
  18. package/dist/server/chat.d.ts +41 -0
  19. package/dist/server/chat.js +1458 -0
  20. package/dist/server/edge-refusal.d.ts +5 -0
  21. package/dist/server/edge-refusal.js +56 -0
  22. package/dist/server/flows.d.ts +12 -0
  23. package/dist/server/flows.js +832 -0
  24. package/dist/server/guards.d.ts +72 -0
  25. package/dist/server/guards.js +357 -0
  26. package/dist/server/handler-context.d.ts +22 -0
  27. package/dist/server/handler-context.js +1 -0
  28. package/dist/server/handler-registry.d.ts +21 -0
  29. package/dist/server/handler-registry.js +34 -0
  30. package/dist/server/pages-assets.d.ts +10 -0
  31. package/dist/server/pages-assets.js +103 -0
  32. package/dist/server/pages.d.ts +11 -0
  33. package/dist/server/pages.js +910 -0
  34. package/dist/server/people-tokens.d.ts +20 -0
  35. package/dist/server/people-tokens.js +694 -0
  36. package/dist/server/remote-hooks.d.ts +29 -0
  37. package/dist/server/remote-hooks.js +130 -0
  38. package/dist/server/remote.d.ts +59 -0
  39. package/dist/server/remote.js +185 -0
  40. package/dist/server/route-policy.d.ts +18 -0
  41. package/dist/server/route-policy.js +30 -0
  42. package/dist/server/route-table.d.ts +74 -0
  43. package/dist/server/route-table.js +350 -0
  44. package/dist/server/runtime.d.ts +280 -0
  45. package/dist/server/runtime.js +25 -0
  46. package/dist/server/settings.d.ts +22 -0
  47. package/dist/server/settings.js +2388 -0
  48. package/dist/server/shared.d.ts +3334 -0
  49. package/dist/server/shared.js +12708 -0
  50. package/dist/server/task-views.d.ts +82 -0
  51. package/dist/server/task-views.js +1099 -0
  52. package/dist/server/tasks.d.ts +87 -0
  53. package/dist/server/tasks.js +3579 -0
  54. package/dist/session-http.d.ts +5 -0
  55. package/dist/session-http.js +16 -0
  56. package/dist/session-server.d.ts +5 -0
  57. package/dist/session-server.js +2 -0
  58. package/dist/team-cli.js +28 -6
  59. package/dist/team-contract.d.ts +7 -0
  60. package/dist/team-contract.js +7 -0
  61. package/dist/team-http.d.ts +10 -1
  62. package/dist/team-http.js +23 -3
  63. package/dist/team-leads.d.ts +5 -1
  64. package/dist/team-leads.js +42 -4
  65. package/dist/team-runtime.d.ts +1 -1
  66. package/dist/team-runtime.js +3 -0
  67. package/dist/teams.d.ts +3 -0
  68. package/dist/teams.js +18 -0
  69. package/package.json +1 -1
package/dist/serve.d.ts CHANGED
@@ -1,606 +1,3 @@
1
- import { type BrowserWorkspace, type BrowserNeedAction, type BrowserSignIn, type BrowserUpdateNotice, type BrowserSettingsGroup } from './browser-workspace.js';
2
- import { CodingWorkspace } from './coding-workspace.js';
3
- import { type FetchLike } from "./flow-share.js";
4
- import { type MailSender } from "./flow-actions.js";
5
- import { type TriggerIo } from "./flow-triggers.js";
6
- import { type CliHttpOptions, type RunOperateAs } from './cli-http.js';
7
- import { type AssignmentSnapshot } from './assignment.js';
8
- import type { PublishExec } from './publish.js';
9
- import { type TaskStatus } from './task-status.js';
10
- import { type VersionRunner } from "./model-catalog.js";
11
- import { type Server } from "node:http";
12
- import { type ProofVerdict, type CriterionMatrixRow } from "./proof.js";
13
- import { type Decision, type Run, type Store, type TaskState } from "./store.js";
14
- import { previewGithubRepo, cloneGithubRepo, listGithubRepos } from "./onboard.js";
15
- import { run as execRun } from "./exec.js";
16
- import { type FirstRunStep } from "./first-run.js";
17
- import { type Gap } from "./gaps.js";
18
- import { type AgentChoice } from "./agentconfig.js";
19
- import { type RouteProjection, type RouteOverride, type RouteStamp, type RiskLevel } from "./phase-routing.js";
20
- import { type Phase } from "./provider.js";
21
- import { type IntegrationIo } from "./integrations.js";
22
- import { launchRuntimeUpdate } from "./toolroll-update.js";
23
- import type { RepairChainRow } from "./store.js";
24
- import type { RevisionLineage } from "./store.js";
25
- import type { SubscriptionMateRunner } from "./subscription-chat.js";
26
- import { type InstallMethod } from "./install-method.js";
27
- export type ServeOptions = {
28
- /** Tests: runs a person's command for the HTTP MCP gateway instead of operate.ts's. */
29
- runOperateAs?: import("./mcp-person.js").RunOperateAs;
30
- /** `toolroll demo`: the scripted lead that answers Chat instead of a model. */
31
- demoLead?: import("./demo.js").DemoLead;
32
- /** Tests: the bin whose real path says how Toolroll was installed (Settings → Updates' command). */
33
- installBin?: string;
34
- /** Native coding workspace injection for isolated integration tests. */
35
- codingWorkspace?: CodingWorkspace;
36
- /** Read-only worker connections for heavy reads (read-executor.ts); 0 reads in-process. Default: off under tests. */
37
- readWorkers?: number;
38
- store: Store;
39
- evidenceRoot: string;
40
- clock?: () => Date;
41
- /**
42
- * The console's canonical https origin, when TLS terminates in front
43
- * (arc 3 finding 2/16): EXACTLY an origin — no path, query, credentials.
44
- * The one trust anchor for secure-context features: it joins the allowed
45
- * hosts, its origin authorizes POSTs, cookies turn Secure, and the
46
- * install/push cards light up. X-Forwarded-* is consulted only from a
47
- * loopback peer, the same-host proxy (public-access.ts).
48
- */
49
- publicUrl?: string;
50
- /** Tests: the shared command boundary `POST /api/cli` runs (default: operate.ts's runOperateAs). */
51
- cliRunner?: RunOperateAs;
52
- /** Tests: remote command metadata until the shared contract declares it. */
53
- cliModeOf?: CliHttpOptions['modeOf'];
54
- /** Tests: the clock request budgets for API tokens count by (request-budget.ts). */
55
- requestBudgetClock?: () => number;
56
- /** Where repos.json lives — every enrollment locks exactly this file. */
57
- registryPath?: string;
58
- /** This console fronts an `up` process: onboarding copy says how to watch. */
59
- upConsole?: boolean;
60
- /**
61
- * The lead on by default (onboarding): with no lead set up, the agent CLI
62
- * signed in on this computer runs it, once. `up` and `serve` turn this on;
63
- * tests opt in.
64
- */
65
- leadByDefault?: boolean;
66
- /** Test seam: the operating system the sign-in command is written for. */
67
- platform?: NodeJS.Platform;
68
- /** Extra Host values this server answers as (a Tailscale name, a LAN ip:port). */
69
- allowedHosts?: readonly string[];
70
- /**
71
- * This computer's names on its tailnet (onboarding): read at start and every
72
- * few minutes; the console answers to each on its own port without an
73
- * --allow-host, and the phone card names the address. Absent = none.
74
- */
75
- tailnetNames?: () => Promise<readonly string[]>;
76
- /**
77
- * The first-account road (setup review): while NO approver exists, the
78
- * login page offers "create the first account", gated by this code —
79
- * printed once by the process that started the server, never stored.
80
- * Five wrong codes close the road until the server restarts. The moment
81
- * an approver exists, the page is the ordinary sign-in.
82
- */
83
- setupCode?: string;
84
- /**
85
- * Where the Telegram bot token lives when set from here. Present = the
86
- * settings card renders; absent = no settings surface at all.
87
- */
88
- telegramTokenFile?: string;
89
- /** Where messaging config files live (beside the database) — enables the
90
- * primary-messenger selector on the settings screen. */
91
- configDir?: string;
92
- /** Test seam for the Slack setup handshake. */
93
- slackFetcher?: typeof fetch;
94
- /** Settings → Updates seams: the latest release, how this Toolroll was
95
- * installed, its version, and how the updater job starts. Tests and
96
- * screenshots inject these; production reads the registry and launchd. */
97
- updates?: {
98
- latest?: () => Promise<{
99
- version: string;
100
- }>;
101
- method?: InstallMethod;
102
- current?: string;
103
- dist?: string;
104
- launch?: typeof launchRuntimeUpdate;
105
- };
106
- discordFetcher?: typeof fetch;
107
- /** Injected by tests: Microsoft sign-in, key metadata and Teams conversation calls. */
108
- teamsFetcher?: typeof fetch;
109
- /** Injected by tests: how "Check now" reaches GitHub (gh) and Linear (fetch). */
110
- flowTriggerIo?: Partial<TriggerIo>;
111
- /**
112
- * The repo this console serves. Scopes run evidence to that repo's tasks
113
- * (and unplaced ones) and turns on the gaps and capabilities views —
114
- * without it those pages say so instead of guessing.
115
- */
116
- repo?: string;
117
- /**
118
- * The full authorization ceiling (v2 review, finding 1): `repos` this
119
- * server may show and operate on, plus `projectRoots` under which any git
120
- * repository qualifies. `repo` above is sugar for one entry in `repos`.
121
- * No configuration at all is the legacy unscoped mode — everything
122
- * visible, and stated as such where the code decides.
123
- */
124
- repos?: readonly string[];
125
- projectRoots?: readonly string[];
126
- /** Repositories the co-located `up` process has proved and is watching.
127
- * Kept as a callback so projects added after startup appear immediately
128
- * without turning the durable registry itself into an authorization source. */
129
- currentRepos?: () => readonly string[];
130
- /** Injected by tests: the fetch direct-API chat turns use, and where chat
131
- * keys are read from (defaults to process.env). */
132
- chatFetcher?: typeof fetch;
133
- /** Subscription-backed mate transport; injected in tests so no real
134
- * Codex or Claude membership turn is consumed. */
135
- subscriptionChatRunner?: SubscriptionMateRunner;
136
- /** Tests: stands in for `codex mcp list --json` in the project (the Tools page's "Found on this computer"). */
137
- codexToolList?: (cwd: string) => Promise<string | null>;
138
- /** Tests: the home whose ~/.toolroll (or older ~/.standing-orders) tool-secrets and ~/.claude.json the Tools page uses. */
139
- toolHome?: string;
140
- /** v87: sends Send email steps' mail and the settings test (tests inject one). */
141
- mailSender?: MailSender;
142
- /** Injected by tests: how Flows → Import fetches a flow file's address. */
143
- flowFetch?: FetchLike;
144
- /** v89: Google's token endpoint (tests inject a scripted one). */
145
- googleFetch?: typeof fetch;
146
- /** Tests: every request a one-click connection makes (discovery, registration, tokens). */
147
- connectFetch?: typeof fetch;
148
- /** Tests: every request sign-in with the identity provider makes (discovery, keys, tokens). */
149
- ssoFetch?: typeof fetch;
150
- chatEnv?: Record<string, string | undefined>;
151
- /**
152
- * The live peek's locality ASSERTION (live-peek v3 §3): the administrator
153
- * who starts serve names the runner this machine owns. This is documented
154
- * as an assertion, not machine-bound credential enforcement — the product
155
- * has none anywhere. Absent = the peek is off, and says so.
156
- */
157
- desktopIdentity?: string;
158
- /** Trusted native admission callback; enrollment rows alone never supply this authority. */
159
- additionalProjectRepos?: () => readonly string[];
160
- /** The co-located `up`'s exact admitted repositories, read on every request: its startup projects plus those
161
- * added since (`repos add`, the lead, the console) and minus those removed. When given it replaces `repos` as
162
- * the exact part of the ceiling, so an addition or removal shows without a restart. */
163
- admittedRepos?: () => readonly string[];
164
- connectionProbe?: typeof execRun;
165
- connectionHome?: string;
166
- /** Test seam for Chat's first tasks: the `gh` and `git grep` reads. */
167
- firstTaskRunner?: typeof execRun;
168
- /** Test seam for Settings → Integrations: how its checks reach services (fetch, gh, mail servers). */
169
- integrationIo?: Partial<IntegrationIo>;
170
- modelCatalogFetcher?: typeof fetch;
171
- /** Test seams for Settings → Models: CLI version probes and the PATH they search. */
172
- modelRunner?: VersionRunner;
173
- modelPath?: string;
174
- localRunner?: string;
175
- /** The checkout pool root the peek confines itself to (realpath-proved). */
176
- poolRoot?: string;
177
- /**
178
- * Editor deep links (arc 6): a DEPLOYMENT capability, not an activation.
179
- * vscode:// links open on the BROWSER's machine, so links render only
180
- * when three statements align: the operator started serve with
181
- * --editor vscode AND --runner (this machine owns the worktrees), the
182
- * run belongs to that runner, and THIS session turned links on for
183
- * this device. "vscode" is the only value; the scheme is never data.
184
- */
185
- editorLinks?: "vscode";
186
- /**
187
- * The attended-mint capability (Phase 2E): present only on a co-located
188
- * `up` console, which alone can hold a session. `headOf` reads the
189
- * repository's CURRENT head — the exact commit the signed terms pin.
190
- */
191
- attended?: {
192
- runner: string;
193
- headOf: (repo: string) => Promise<string | null>;
194
- coordinator?: import("./held.js").HeldSessionCoordinator;
195
- };
196
- /** Injected by tests: the onboarding ceremony's gh-facing halves — the
197
- * ceremony's gating, nonce, and enrollment logic is what the HTTP tests
198
- * prove; gh itself is proved by onboard.test.ts. */
199
- ghPreview?: typeof previewGithubRepo;
200
- ghClone?: typeof cloneGithubRepo;
201
- ghList?: typeof listGithubRepos;
202
- /** Injected by tests: the git and gh calls pull-request setup and Merge make. */
203
- publishExec?: PublishExec;
204
- };
205
- /** Where `up`'s one-time sign-in link points, and how long it works. */
206
- export declare const SIGN_IN_LINK_PATH = "/login/once/";
207
- export declare const SIGN_IN_LINK_MS: number;
208
- /** The console's server, and the one-time sign-in link `up` opens: a path on this server, or null for no such approver.
209
- * closeCoding starts the coding shutdown on its own, ahead of the rest of a stop; close() awaits the same promise. */
210
- export type DecisionServer = Server & {
211
- mintSignInLink(account: string): string | null;
212
- closeCoding(): Promise<void>;
213
- };
214
- /** How long a stop waits for teammates and the lead's follow pass before closing anyway. */
215
- export declare const SHUTDOWN_WAIT_MS = 5000;
1
+ import { type DecisionServer, type ServeOptions } from "./server/shared.js";
216
2
  export declare function createDecisionServer(options: ServeOptions): DecisionServer;
217
- /**
218
- * A vscode://file href, or null (arc 6, finding 2): the link exists only
219
- * when every part is provably tame — an absolute, control-free worktree;
220
- * a relative, single-line path whose segments contain no empty, dot,
221
- * dot-dot, or backslash components (so lexical resolution stays below the
222
- * worktree); a line inside the same 1..1,000,000 range the comment form
223
- * enforces. Encoding failures return null — a file row degrades to plain
224
- * text, never to a 500. The scheme is a constant, never data.
225
- */
226
- export declare function editorFileHref(worktree: string, path: string, line?: number | null): string | null;
227
- /** Earlier versions of a task still in flight, in plain words: queued
228
- * while they only wait, running once one has started; null when none. */
229
- export declare function earlierVersionsWords(active: number, running: number): string | null;
230
- /** The Agents view every console surface renders (v47): the SAME
231
- * projection the CLI prints — who plans, builds, and revises,
232
- * whether each was recommended, overridden, or pinned, its reasons, and
233
- * the readiness the task's runners have reported (ready / unavailable /
234
- * unknown — an unknown is said, never upgraded). Readiness is volatile and
235
- * never part of what an approval signs, so the ceremony shows the agents
236
- * and their reasons only. */
237
- export type RouteView = {
238
- kind: "route" | "legacy" | "unreadable";
239
- source: "approved" | "proposed" | "live" | null;
240
- projection: RouteProjection | null;
241
- /** A proven pre-routing row: its approved agent profile, nothing more. */
242
- legacy: {
243
- provider: string;
244
- model: string;
245
- repairModel: string;
246
- approved: boolean;
247
- } | null;
248
- /** A routed row whose agents cannot be read — fail closed, in words. */
249
- problem: string | null;
250
- riskLevel: RiskLevel;
251
- overrides: RouteOverride[];
252
- /** An approver may edit: a live claim, a tournament, or a viewer session refuses. */
253
- editable: boolean;
254
- editableWhy: string | null;
255
- /** A planner change after a draft landed asks for a real re-plan. */
256
- replanOnPlanChange: boolean;
257
- /** The scope digest the change forms CAS against; null = no scope yet. */
258
- digest: string | null;
259
- /** v48: the configured, role-valid agents an approver may choose from —
260
- * every option an exact pair the operator named once in configuration.
261
- * The form offers these and nothing else. */
262
- choices: Record<Phase, AgentChoice[]>;
263
- };
264
- /** The page CSS this module writes itself (not the imported modules'), for the stylesheet contract tests. */
265
- export declare const PAGE_CSS: string;
266
- /** Everything the sidebar needs to draw itself for one request. */
267
- type Chrome = {
268
- projectScoped?: boolean;
269
- active: "code" | "inbox" | "board" | "queue" | "fleet" | "workbench" | "work" | "done" | "activity" | "review" | "system" | "tasks" | "runs" | "caps" | "routines" | "recipes" | "projects" | "flows" | "settings" | "chat" | "people" | "ledger" | "spend" | "mode" | "menu" | "none";
270
- project: string | null;
271
- /** The surface's scope for the scope bar — which rows this screen can
272
- * show. Derived from the ROUTE, not the session: portfolio and fleet are
273
- * all-project even while a project is open; the board says which of its
274
- * two modes it is in. Absent = the session default (open project, else
275
- * all projects). Display only — switching stays POST + CSRF. */
276
- scope?: "all" | "project" | "board-all";
277
- /** The saturated inbox count — never a sum of unbounded list reads. */
278
- inboxCount: number;
279
- /** The project the Tasks count covers: the request's own project view
280
- * (the open project, or /work's ?project=), null for every admitted project. */
281
- inboxProject?: string | null;
282
- /** The Tasks badge's words, naming what it covers: "3 need you in shop". */
283
- inboxLabel?: string;
284
- inboxSaturated: boolean;
285
- settings: boolean;
286
- /** This database is a demo sandbox: banner every page, spend fenced. */
287
- demo?: boolean;
288
- /** The active operating mode's banner (M1): rides every page scoped to
289
- * a repo with a live mode — a signed posture is never invisible. */
290
- modeBanner?: {
291
- words: string;
292
- name: string;
293
- };
294
- /** Providers whose sign-in stopped working: every page says so, once. */
295
- signIn?: BrowserSignIn[];
296
- /** A newer Toolroll: a quiet notice for an operator until they dismiss this version. */
297
- update?: BrowserUpdateNotice;
298
- /** An update waiting on something, what, and the action that clears it: every page, for an operator. */
299
- updateWaiting?: {
300
- words: string;
301
- };
302
- /** The chat tab renders only where chat could ever be allowed. */
303
- chat?: boolean;
304
- code?: boolean;
305
- /** A rendered list pane makes the page master-detail. */
306
- listPane?: string;
307
- /** A compact pulse for the currently open workspace. Null in the
308
- * cross-workspace view; absent only when the store could not answer. */
309
- projectPeek?: ProjectPeek | null;
310
- /** The switcher (board pass): every enrolled project inside the ceiling,
311
- * most recently opened first — the one-tap switch on any screen. */
312
- projects?: {
313
- path: string;
314
- name: string;
315
- }[];
316
- /** The session's csrf token, for the switcher's forms; "" when the
317
- * request has no cookie session (bearer), which renders the switcher
318
- * inert. */
319
- csrf?: string;
320
- /** Where a switch made on this screen returns to. */
321
- returnTo?: string;
322
- };
323
- /**
324
- * A page described, not yet rendered (arc 4): every chromed HTML route
325
- * returns one of these and ONE helper (sendScreen, inside the server)
326
- * owns the nonce, the palette index, the shortcuts overlay, script
327
- * composition, and the CSP. Renderers stopped calling shell() themselves
328
- * so those five things cannot drift apart per route.
329
- */
330
- type Screen = {
331
- title: string;
332
- body: string;
333
- chrome?: Chrome;
334
- /** The page's own executable behavior (a region poller, the push
335
- * enrollment script). fetches: true when it calls fetch — connect-src
336
- * is granted only then. */
337
- functional?: {
338
- script: string;
339
- fetches?: boolean;
340
- };
341
- refreshSeconds?: number;
342
- /** Render sensitive even when no password field is visible — one-time
343
- * secrets and judgment calls the classifier cannot see. */
344
- forceSensitive?: boolean;
345
- /** Structured conversation; complex guarded forms stay native islands. */
346
- workspace?: Partial<Pick<BrowserWorkspace, 'conversation' | 'team' | 'focus' | 'result' | 'catchUpHtml' | 'controlsHtml' | 'notices' | 'pageHtml' | 'view' | 'firstRun' | 'phone' | 'home'>>;
347
- };
348
- /**
349
- * The sensitivity classifier (arc 4, findings 3/17): a body showing a
350
- * password input renders WITHOUT the chrome additions (palette, overlay,
351
- * global keys) — the page's own functional script still ships. Tolerant
352
- * of quoting, casing, and whitespace; `data-type="password"` and prose
353
- * mentioning passwords do not match. This is defense-in-depth over a
354
- * file whose only HTML producer is its own double-quoted template
355
- * convention — forceSensitive is the escape hatch for what a regex
356
- * cannot judge.
357
- */
358
- export declare const SENSITIVE_INPUT: RegExp;
359
- /**
360
- * v100: for someone signed in with the identity provider, every step-up
361
- * password field (autocomplete="current-password"; a secret like a bot token
362
- * is never one) becomes that sign-in: confirmed, when the provider checked
363
- * them in the last ten minutes, or a link to be checked again, then back here.
364
- */
365
- export declare function ssoStepUps(html: string, sso: {
366
- label: string;
367
- fresh: boolean;
368
- }, returnTo: string): string;
369
- /**
370
- * The page for an address the console doesn't answer to (onboarding): what was opened, where it answers, and the exact
371
- * command that admits this address. It stands alone (styles inline, no script, no font), because every other asset
372
- * would be refused at this address too; and it holds nothing a stranger's page doesn't already know.
373
- */
374
- export declare function wrongHostPage(facts: {
375
- opened: string | null;
376
- served: string;
377
- command: string | null;
378
- }): string;
379
- /**
380
- * The inbox (v3): only things stalling progress without a person, one card
381
- * per underlying stall, each with its verb inline or one step away. No
382
- * auto-refresh — approval links lead to the step-up screen, and a page
383
- * that might hold typed input never re-renders itself.
384
- */
385
- export type InboxTab = "needs-you" | "ready" | "running" | "all";
386
- export declare function parseInboxTab(raw: string | null): InboxTab | undefined;
387
- /** What each tab holds, as a short fingerprint: a tab is unread when its
388
- * fingerprint differs from the one this browser saw there last. */
389
- export declare function inboxFingerprints(data: Pick<Parameters<typeof inboxPage>[1], "decisions" | "approvals" | "requeueables" | "cancelledBlockers" | "gaps" | "needsVerification" | "ready" | "running">): Record<InboxTab, string>;
390
- declare function inboxPage(chrome: Chrome, data: {
391
- csrf: string;
392
- revision: number;
393
- /** No project open in scoped mode: every admitted project at once,
394
- * chips on every row, links only — acting means opening the project. */
395
- rollup: boolean;
396
- /** A project is OPEN: only then do decisions answer on the card. The
397
- * legacy unscoped projectless inbox stays links-only too (commit-1
398
- * review, finding 4) — the partial belongs to a chosen project. */
399
- interactive: boolean;
400
- decisions: (Decision & {
401
- taskId: string;
402
- repo?: string | null;
403
- })[];
404
- approvals: {
405
- taskId: string;
406
- title: string;
407
- goal: string;
408
- proposedAt: string;
409
- repo?: string | null; /** v48 authority repair: the closed consent door's title, or null when a yes could bind. */
410
- closed?: string | null;
411
- }[];
412
- requeueables: {
413
- taskId: string;
414
- title: string;
415
- state: TaskState;
416
- strikes: number;
417
- incidentCount: number;
418
- repo?: string | null;
419
- }[];
420
- cancelledBlockers: {
421
- blockerId: string;
422
- dependentCount: number;
423
- exampleDependent: string;
424
- repo?: string | null;
425
- blockerRepo?: string | null;
426
- }[];
427
- gaps: Gap[];
428
- /** A completed task whose proof is short or refuted and not yet accepted
429
- * (Priority 2) — reads "needs verification" here too, never silently
430
- * "done" just because the inbox does not otherwise look at finished work. */
431
- needsVerification: {
432
- taskId: string;
433
- title: string;
434
- verdict: "short" | "refuted";
435
- repo?: string | null;
436
- matrix?: CriterionMatrixRow[];
437
- repairChain?: RepairChainRow | null;
438
- }[];
439
- /** The first-run steps; null once the installation has had its first Ready result. */
440
- wizard: FirstRunStep[] | null;
441
- /** Whether any worker is answering right now — said at the top when none is. */
442
- worker: {
443
- answering: number;
444
- registered: number;
445
- lastHeard: string | null;
446
- };
447
- now: Date;
448
- /** Console v2: the tab shown, results ready to review, work running now,
449
- * and the tabs holding something this browser hasn't seen (dots on a phone). */
450
- tab?: InboxTab;
451
- ready?: {
452
- taskId: string;
453
- title: string;
454
- detail: string;
455
- repo: string | null;
456
- }[];
457
- running?: {
458
- taskId: string;
459
- title: string;
460
- detail: string;
461
- repo: string | null;
462
- }[];
463
- unread?: readonly InboxTab[];
464
- }): Screen;
465
- /** The task composer's modes (console v2), as the words the lead reads for that one turn. */
466
- export type TaskComposerMode = "build" | "plan" | "answer";
467
- export declare const TASK_COMPOSER_MODES: Record<TaskComposerMode, string>;
468
- /**
469
- * The inline-answer enhancement (portfolio arc §2): submits a reversible
470
- * option's form as the urlencoded POST the forms-only gate expects, follows
471
- * the redirect, and — because an answered decision leaves the open list —
472
- * replaces ONLY that card with the answered receipt parsed from the
473
- * decision page's own rendering, or removes the card. Anything unexpected
474
- * (auth, a page that is not the decision's) navigates instead of inserting.
475
- * Nothing else on the page is touched: typed input elsewhere survives.
476
- */
477
- export declare function decisionAnswerScript(): string;
478
- type ProjectPeek = {
479
- waiting: number;
480
- queued: number;
481
- running: number;
482
- doneRecently: number;
483
- };
484
- /**
485
- * Creating work is the product's first verb, so it gets a whole calm page:
486
- * a title, the goal that becomes the scope draft, and the project it lands
487
- * in — then straight to the approve card, which is the aha the flow serves.
488
- */
489
- /** One queue card. Taken work renders pinned — visible, never draggable. */
490
- /**
491
- * The request's own session facts, readable from anywhere below the
492
- * dispatcher without threading them through forty call sites: the csrf
493
- * token the chrome's switcher forms carry, and the path a switch returns
494
- * to. AsyncLocalStorage follows the request's own async chain, so two
495
- * interleaved requests never read each other's token.
496
- */
497
- /** The person's pinned theme from their own cookie; null follows the device. */
498
- export declare function pinnedTheme(cookieHeader: string | undefined): "light" | "dark" | null;
499
- /** A request path fit for a log: the one-time sign-in link's code is left out. */
500
- export declare function redactedPath(path: string): string;
501
- /** The /queue page's one nonce'd script: delegated pointer-event drag (it
502
- * survives every fragment swap — finding 17) plus a poller that re-checks
503
- * focus, dirty inputs, and an in-flight drag AT SWAP TIME, never only
504
- * before the fetch. Select dirtiness compares against data-initial
505
- * (finding 18); missing that, a select counts clean.
506
- */
507
- export declare function queueScript(): string;
508
- /**
509
- * A revision's lineage and ACTUAL terms, in the same words on the task
510
- * page, the approval card, and chat (contract handoff task 2): which
511
- * source and build it revises, the ancestry to its root, the terms the
512
- * child really carries (read from its own scope — never restated from the
513
- * brief), what is re-resolved for THIS approval, what never inherits, and
514
- * — when the task continues a repair chain — the attempts used against
515
- * the signed cap.
516
- */
517
- export declare function revisionLineageWords(lineage: RevisionLineage): string[];
518
- /** Review priority: a deterministic, LABELED presentation aid over facts
519
- * the done list already carries. Band 0 goes first; the words name why.
520
- * It is never a verdict — the stored proof verdict stays the authority,
521
- * and an operator's acceptance lowers a band without touching it. */
522
- export type ReviewPriority = {
523
- band: 0 | 1 | 2;
524
- label: "needs action" | "review" | "no flags";
525
- reasons: string[];
526
- };
527
- export type ReviewQueueFacts = {
528
- /** Only an exact current task/run match carries the assignment status. */
529
- assignment?: AssignmentSnapshot | null;
530
- proofReasons?: readonly string[];
531
- runId: number | null;
532
- outcome: string | null;
533
- proofVerdict: ProofVerdict | null;
534
- proofAccepted: boolean;
535
- proofMatrix: readonly CriterionMatrixRow[];
536
- ciFailing: boolean;
537
- publicationState: string | null;
538
- };
539
- export declare function reviewPriorityOf(row: ReviewQueueFacts): ReviewPriority;
540
- /** Ranked, stable: band first, then newest completion, then task id — the
541
- * same input always yields the same queue, whoever loads it. */
542
- export declare function rankReviewQueue<T extends ReviewQueueFacts & {
543
- completedAt: string;
544
- taskId: string;
545
- }>(rows: readonly T[]): (T & {
546
- priority: ReviewPriority;
547
- })[];
548
- /** Whether a changed path sits inside the scope's signed "touches" — an
549
- * exact file, a directory prefix (with or without its slash), or a plain
550
- * `*` / `**` glob. Touches are advisory in the scope; here they only
551
- * decide which files wear the "outside the signed touches" flag. */
552
- export declare function withinSignedTouches(path: string, touches: readonly string[]): boolean;
553
- /** A stable, attribute-safe anchor for one file of the sealed patch —
554
- * derived from the path's bytes, never from the path's characters, so a
555
- * hostile file name can neither break the id nor escape the attribute. */
556
- export declare function diffFileAnchor(path: string): string;
557
- export type ReviewFileRow = {
558
- path: string;
559
- additions: number | null;
560
- deletions: number | null;
561
- renamedFrom: string | null;
562
- anchor: string | null;
563
- outsideTouches: boolean;
564
- cited: boolean;
565
- };
566
- /** The changed-file list's own review priority: outside the signed
567
- * touches first, then files a machine cannot diff or a criterion never
568
- * cited, then the rest by churn. Presentation only — the sealed patch
569
- * keeps its own order beneath, byte for byte. */
570
- export declare function reviewFilePriority(file: ReviewFileRow, proofCitesPaths: boolean): ReviewPriority;
571
- export declare function orderChangedFiles(files: readonly ReviewFileRow[], proofCitesPaths: boolean): (ReviewFileRow & {
572
- priority: ReviewPriority;
573
- })[];
574
- /** Older machine-checked results saved a mechanical sentence; say the same
575
- * facts in plain words (the version id stays, shortened). */
576
- export declare function plainConclusionOf(conclusion: string): string;
577
- /** A Needs you result's one action (needs-you.ts): a link to the act that resolves it, or Confirm it
578
- * stopped behind the password. Null under every other headline. */
579
- export declare function needActionOf(assignment: AssignmentSnapshot | null, status: TaskStatus | null, csrf: string, returnTo: string, result?: {
580
- accepted: boolean;
581
- humanReview: boolean;
582
- run: number;
583
- action: string;
584
- rebuildable?: boolean;
585
- refuted?: boolean;
586
- }): BrowserNeedAction | null;
587
- /** The facts region alone, for the open-run poll (A4). A finished run's
588
- * fragment says so instead of quietly growing forms (finding 5), and a run
589
- * that stopped being the task's live claim says so too — both carry the
590
- * stop marker, so an open tab quits refetching a dead build (round-4
591
- * finding 15). */
592
- export declare function runFactsFragment(run: Run, taskId: string, live: boolean, route?: RouteStamp | null): string;
593
- /** Settings destinations under short headings: an icon and a name each, and a chat app's logo and state. */
594
- export declare function settingsTiles(groups: BrowserSettingsGroup[]): string;
595
- /**
596
- * The settings groups, with each chat app's state from what the server already holds: not set up,
597
- * connected, or getting alerts (only when that service was chosen, or is the only one).
598
- * A Telegram bot whose saved delivery state reports a problem says so instead. With no config folder
599
- * the state is unknown, so the tiles carry none.
600
- */
601
- export declare function settingsGroups(messaging: {
602
- channel: string | null;
603
- implicit: boolean;
604
- configured: string[];
605
- } | null, telegramFailing?: boolean): BrowserSettingsGroup[];
606
- export {};
3
+ export { decisionAnswerScript, diffFileAnchor, earlierVersionsWords, editorFileHref, inboxFingerprints, needActionOf, orderChangedFiles, PAGE_CSS, parseInboxTab, pinnedTheme, plainConclusionOf, queueScript, rankReviewQueue, redactedPath, reviewFilePriority, reviewPriorityOf, revisionLineageWords, runFactsFragment, SENSITIVE_INPUT, settingsGroups, settingsTiles, SHUTDOWN_WAIT_MS, SIGN_IN_LINK_MS, SIGN_IN_LINK_PATH, ssoStepUps, TASK_COMPOSER_MODES, withinSignedTouches, wrongHostPage, type DecisionServer, type InboxTab, type ReviewFileRow, type ReviewPriority, type ReviewQueueFacts, type RouteView, type ServeOptions, type TaskComposerMode } from "./server/shared.js";