toolroll 0.9.100 → 0.9.101
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.
- package/CHANGELOG.md +7 -0
- package/dist/accent-colors.js +1 -1
- package/dist/activity-line.d.ts +1 -1
- package/dist/activity-line.js +1 -1
- package/dist/browser/terminal.css +1 -1
- package/dist/browser/terminal.js +42 -42
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +32 -32
- package/dist/browser-workspace.d.ts +31 -2
- package/dist/design/kit.css +94 -2
- package/dist/design/kit.d.ts +12 -4
- package/dist/design/kit.js +8 -2
- package/dist/design/tokens.css +5 -5
- package/dist/first-run.d.ts +10 -6
- package/dist/first-run.js +19 -18
- package/dist/guides.js +1 -1
- package/dist/operate.js +2 -0
- package/dist/scope.d.ts +5 -0
- package/dist/scope.js +8 -1
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +1 -1
- package/dist/server/console.css +46 -17
- package/dist/server/kit.d.ts +36 -3
- package/dist/server/kit.js +33 -4
- package/dist/server/render-chat.d.ts +2 -0
- package/dist/server/render-chat.js +1 -0
- package/dist/server/render-pages.js +1 -1
- package/dist/server/render-results.js +3 -3
- package/dist/server/render-tasks.d.ts +10 -0
- package/dist/server/render-tasks.js +231 -62
- package/dist/server/task-views.js +5 -1
- package/dist/settings-groups-ui.js +1 -1
- package/dist/store.js +14 -3
- package/dist/task-archive.d.ts +3 -0
- package/dist/task-archive.js +5 -0
- package/dist/task-status.d.ts +2 -2
- package/dist/task-status.js +3 -3
- package/dist/tui.js +1 -1
- package/dist/workspace-ui.d.ts +69 -0
- package/dist/workspace-ui.js +103 -0
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import type { AssignmentSnapshot } from './assignment.js';
|
|
|
8
8
|
export { browserCrewFromIndex, browserWorkActionHref } from './browser-crew.js';
|
|
9
9
|
import type { Store } from './store.js';
|
|
10
10
|
import type { WorkSummaryAccess } from './work-summary.js';
|
|
11
|
-
import type { StatusTone } from './workspace-ui.js';
|
|
11
|
+
import type { StatusTone, StepRow } from './workspace-ui.js';
|
|
12
12
|
import type { Ask, AskChip } from './needs-you.js';
|
|
13
13
|
import type { WorkIndexGroup } from './work-index.js';
|
|
14
14
|
import type { AssignmentCard } from './assignment-ui.js';
|
|
@@ -414,6 +414,24 @@ export type BrowserTaskView = {
|
|
|
414
414
|
line: string;
|
|
415
415
|
action: BrowserLink | null;
|
|
416
416
|
} | null;
|
|
417
|
+
/** The plan's steps and where each stands, from the latest checkpoint (all pending before the first). */
|
|
418
|
+
steps?: {
|
|
419
|
+
title: string;
|
|
420
|
+
state: "pending" | "current" | "completed" | "blocked";
|
|
421
|
+
}[];
|
|
422
|
+
} | null;
|
|
423
|
+
/** The Plan row: the plan's lead sentence, who wrote it and when, and its body (the plan sheet and the plan's editor;
|
|
424
|
+
* only the editor while the approval shows the sheet). `planning`: a planner is writing it now. Null: no plan yet.
|
|
425
|
+
* `key` names what the body holds (the editor alone, or the sheet of one exact plan): the page installs the body once
|
|
426
|
+
* and again when the key changes. */
|
|
427
|
+
plan?: {
|
|
428
|
+
lead: string | null;
|
|
429
|
+
by: string | null;
|
|
430
|
+
at: string | null;
|
|
431
|
+
html: string;
|
|
432
|
+
planning: boolean;
|
|
433
|
+
updating?: boolean;
|
|
434
|
+
key: string;
|
|
417
435
|
} | null;
|
|
418
436
|
/** What the agent did last on the live run, and when; the page words it against its own clock (activity-line.ts). */
|
|
419
437
|
activity?: RunActivity | null;
|
|
@@ -422,6 +440,14 @@ export type BrowserTaskView = {
|
|
|
422
440
|
room: string;
|
|
423
441
|
at: string | null;
|
|
424
442
|
} | null;
|
|
443
|
+
/** The work panel's run (docs/plans/task-page-steps.md "Watch the work"): the live build, else the latest one, who ran it,
|
|
444
|
+
* and its records window on the run page (null on a page that asks for a password). Null: no build yet. */
|
|
445
|
+
work?: {
|
|
446
|
+
run: number;
|
|
447
|
+
live: boolean;
|
|
448
|
+
agent: string;
|
|
449
|
+
transcript: string | null;
|
|
450
|
+
} | null;
|
|
425
451
|
/** Stop, on the Building card: the exact live build's stop form (posts its run id). */
|
|
426
452
|
stop?: {
|
|
427
453
|
action: string;
|
|
@@ -478,8 +504,11 @@ export type BrowserTaskView = {
|
|
|
478
504
|
href: string;
|
|
479
505
|
starter: string;
|
|
480
506
|
} | null;
|
|
481
|
-
/**
|
|
507
|
+
/** The task's road, Plan → Approval → Build → Checks → Ready (four for a report), from recorded facts. */
|
|
482
508
|
journey?: JourneyStep[] | null;
|
|
509
|
+
/** The page's step rows (workspace-ui.ts stepRowsOf over this view, after every change the server made to it): the
|
|
510
|
+
* steps are the page. Null: no road (cancelled, or no status), so the page keeps its status block. */
|
|
511
|
+
steps?: StepRow[] | null;
|
|
483
512
|
/** The thread's server-side entries; the conversation's messages join them in time order. */
|
|
484
513
|
thread?: BrowserTaskThreadItem[];
|
|
485
514
|
details?: BrowserTaskDetailGroup[];
|
package/dist/design/kit.css
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* stays here: status words on their soft wash, mixed toward ink so they read at 4.5:1 or better, and the motion
|
|
20
20
|
* vocabulary (three durations, one curve; nothing longer, no bounce). */
|
|
21
21
|
:root {
|
|
22
|
-
--so-needs-ink:
|
|
22
|
+
--so-needs-ink: var(--so-ink);
|
|
23
23
|
--so-live-ink: color-mix(in srgb, var(--so-info) 82%, var(--so-ink));
|
|
24
24
|
--so-done-ink: color-mix(in srgb, var(--so-success) 80%, var(--so-ink));
|
|
25
25
|
--so-fail-ink: color-mix(in srgb, var(--so-danger) 85%, var(--so-ink));
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
/* ---------- Status: five words, one tone each ---------- */
|
|
65
65
|
.k-chip { display: inline-flex; align-items: center; gap: 6px; height: 20px; padding: 0 7px; border-radius: 6px; font: var(--so-typography-badge); background: var(--so-neutral-soft); color: var(--so-neutral-ink); white-space: nowrap; flex: none; }
|
|
66
66
|
.k-chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--dot, var(--so-muted)); flex: none; }
|
|
67
|
-
.k-chip.needs { background: var(--so-needs
|
|
67
|
+
.k-chip.needs { background: var(--so-needs); color: var(--so-on-signal); }
|
|
68
|
+
.k-chip.needs::before { display: none; }
|
|
68
69
|
.k-chip.ask { background: var(--so-neutral-soft); color: var(--so-ink); --dot: var(--so-needs); }
|
|
69
70
|
.k-chip.live { background: var(--so-info-soft); color: var(--so-live-ink); --dot: var(--so-info); }
|
|
70
71
|
.k-chip.done { background: var(--so-success-soft); color: var(--so-done-ink); --dot: var(--so-success); }
|
|
@@ -255,6 +256,82 @@
|
|
|
255
256
|
.k-step-l { line-height: 1.2; white-space: nowrap; }
|
|
256
257
|
.k-step-s { margin-top: -4px; min-height: 1.3em; font-size: 11.5px; font-weight: 400; line-height: 1.3; color: var(--so-muted); white-space: nowrap; }
|
|
257
258
|
|
|
259
|
+
/* ---------- Step rows: the steps are the page ---------- */
|
|
260
|
+
.k-steprows { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
|
|
261
|
+
.k-steprow { position: relative; display: grid; grid-template-columns: 20px minmax(0, 1fr); column-gap: 14px; margin: 0; padding: 0; }
|
|
262
|
+
.k-steprow::before { content: ""; position: absolute; left: 9.5px; top: 24px; bottom: 4px; width: 1px; background: var(--so-line); }
|
|
263
|
+
.k-steprow:last-child::before { content: none; }
|
|
264
|
+
.k-steprow-mark { position: relative; z-index: 1; box-sizing: border-box; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--so-field-line); background: var(--so-paper); }
|
|
265
|
+
.k-steprow.done .k-steprow-mark { border-color: var(--so-ink); background: var(--so-ink); }
|
|
266
|
+
.k-steprow.done .k-steprow-mark::after { content: ""; width: 4px; height: 8px; margin-top: -2px; border: solid var(--so-paper); border-width: 0 1.6px 1.6px 0; transform: rotate(45deg); }
|
|
267
|
+
.k-steprow:is(.needs, .live, .wait, .stuck) .k-steprow-mark { border-width: 2px; }
|
|
268
|
+
.k-steprow:is(.needs, .live, .wait, .stuck) .k-steprow-mark::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
|
|
269
|
+
.k-steprow.needs .k-steprow-mark { border-color: var(--so-needs); color: var(--so-needs); }
|
|
270
|
+
.k-steprow.live .k-steprow-mark { border-color: var(--so-info); color: var(--so-info); }
|
|
271
|
+
.k-steprow.wait .k-steprow-mark { border-color: var(--so-muted); color: var(--so-muted); }
|
|
272
|
+
.k-steprow.stuck .k-steprow-mark { border-color: var(--so-danger); color: var(--so-danger); }
|
|
273
|
+
.k-steprow.skipped .k-steprow-mark { border-style: dashed; }
|
|
274
|
+
.k-steprow-main { min-width: 0; display: grid; align-content: start; gap: 12px; padding-bottom: 22px; }
|
|
275
|
+
.k-steprow:last-child .k-steprow-main { padding-bottom: 0; }
|
|
276
|
+
.k-steprow:is(.needs, .live, .wait, .stuck) .k-steprow-main { padding-bottom: 26px; }
|
|
277
|
+
.k-steprow-head { display: flex; align-items: baseline; gap: 12px; width: 100%; min-width: 0; min-height: 20px; margin: 0; padding: 0; border: 0; border-radius: 6px; background: none; color: inherit; font: 400 13px/20px var(--so-font-sans); text-align: left; }
|
|
278
|
+
button.k-steprow-head { cursor: pointer; transition: color var(--m-quick) var(--m-ease); }
|
|
279
|
+
button.k-steprow-head::after { content: ""; flex: none; align-self: center; width: 6px; height: 6px; margin: 0 4px 0 2px; border: solid var(--so-muted); border-width: 0 1.5px 1.5px 0; transform: rotate(-45deg); transition: transform var(--m-quick) var(--m-ease); }
|
|
280
|
+
button.k-steprow-head[aria-expanded="true"]::after { transform: rotate(45deg); }
|
|
281
|
+
.k-steprow-label { flex: 0 0 84px; min-width: 0; font: 600 14px/20px var(--so-font-sans); color: var(--so-ink); }
|
|
282
|
+
.k-steprow-say { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; color: var(--so-muted); overflow-wrap: anywhere; }
|
|
283
|
+
.k-steprow:is(.needs, .live, .wait, .stuck) .k-steprow-say { color: var(--so-ink); }
|
|
284
|
+
.k-steprow-time { flex: none; color: var(--so-muted); font-size: 12.5px; }
|
|
285
|
+
.k-steprow.todo .k-steprow-label { font-weight: 500; color: var(--so-muted); }
|
|
286
|
+
.k-steprow-body { display: grid; gap: 16px; min-width: 0; }
|
|
287
|
+
.k-steprow-body[hidden] { display: none; }
|
|
288
|
+
/* The one ink outline of a step that waits on the viewer is the row's; a waiting box inside it draws none of its own. */
|
|
289
|
+
.k-steprow.needs > .k-steprow-main > .k-steprow-body { border: 1px solid var(--so-needs); border-radius: var(--so-radius-card); padding: 16px 18px 18px; }
|
|
290
|
+
.k-steprow.needs > .k-steprow-main > .k-steprow-body .k-slots.wait { border: 0; border-radius: 0; padding: 0; }
|
|
291
|
+
.k-steprow-body .k-slot-status h2 { color: var(--so-ink); }
|
|
292
|
+
.k-steprow-body .k-slot-acts:empty { display: none; }
|
|
293
|
+
@media (hover: hover) and (pointer: fine) {
|
|
294
|
+
button.k-steprow-head:hover .k-steprow-say { color: var(--so-ink); }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* ---------- The work: one agent's work as a chat ---------- */
|
|
298
|
+
.k-work { box-sizing: border-box; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--so-paper); color: var(--so-ink); }
|
|
299
|
+
.k-work[hidden] { display: none; }
|
|
300
|
+
.k-work-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 10px 12px 18px; border-bottom: 1px solid var(--so-line); }
|
|
301
|
+
.k-work-title { display: grid; gap: 1px; min-width: 0; }
|
|
302
|
+
.k-work-title h2 { margin: 0; font: 600 14px/1.4 var(--so-font-sans); }
|
|
303
|
+
.k-work-who { display: flex; align-items: center; gap: 6px; min-width: 0; margin: 0; font-size: 12px; line-height: 1.4; color: var(--so-muted); }
|
|
304
|
+
.k-work-who > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
305
|
+
.k-work-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--so-live); }
|
|
306
|
+
.k-work-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: grid; align-content: start; gap: 16px; padding: 18px; }
|
|
307
|
+
.k-work-foot { flex: none; display: grid; gap: 8px; padding: 8px 14px 14px; max-height: min(50%, 420px); overflow-y: auto; overscroll-behavior: contain; }
|
|
308
|
+
.k-work-foot:empty { display: none; }
|
|
309
|
+
.k-work-conv { display: grid; gap: var(--so-space-sm); min-width: 0; }
|
|
310
|
+
.k-work-conv-h { display: flex; justify-content: flex-end; }
|
|
311
|
+
.k-work-conv .k-work-tx { max-height: 60vh; overflow-y: auto; overscroll-behavior: contain; }
|
|
312
|
+
.k-work-tx { min-width: 0; display: grid; gap: 12px; }
|
|
313
|
+
.k-work-empty { margin: 0; padding: var(--so-space-md) 0; font-size: 13px; color: var(--so-muted); }
|
|
314
|
+
.k-work-lines { display: grid; gap: 14px; margin: 0; padding: 0; list-style: none; font-size: 14px; line-height: 1.6; }
|
|
315
|
+
.k-work-say { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
316
|
+
.k-work-mark { font-size: 12px; color: var(--so-muted); }
|
|
317
|
+
.k-work-steps { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; font-size: 13px; line-height: 1.5; color: var(--so-muted); }
|
|
318
|
+
.k-work-step-l { display: flex; align-items: center; gap: 10px; min-height: 26px; min-width: 0; }
|
|
319
|
+
.k-work-step.running .k-work-step-l { color: var(--so-ink); }
|
|
320
|
+
.k-work-step-t { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
|
|
321
|
+
.k-work-step-t .k-mono { font-size: 12px; color: var(--so-ink); }
|
|
322
|
+
.k-work-step-s { flex: none; display: inline-flex; align-items: center; gap: var(--so-space-xs); font-size: 12px; color: var(--so-muted); }
|
|
323
|
+
.k-work-step-s.ok { color: var(--so-done-ink); }
|
|
324
|
+
.k-work-step-s.failed { color: var(--so-fail-ink); }
|
|
325
|
+
.k-work-step-s.running { color: var(--so-live-ink); }
|
|
326
|
+
.k-work-out { max-height: 288px; overflow: auto; margin: 4px 0 6px; padding: var(--so-space-sm) 10px; border-radius: var(--so-radius-md); background: var(--so-code-bg); color: var(--so-ink); font: 12px/1.5 var(--so-font-mono); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
327
|
+
.k-work-note { display: grid; justify-items: end; gap: 2px; }
|
|
328
|
+
.k-work-bubble { max-width: 82%; margin: 0; padding: 8px 14px; border-radius: 18px; background: var(--so-user-bubble); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
329
|
+
.k-work-note-s { margin: 0; font-size: 12px; color: var(--so-muted); }
|
|
330
|
+
.k-work-term { display: grid; gap: 2px; margin: 0; padding: 10px var(--so-space-md); list-style: none; border-radius: var(--so-radius-card); background: var(--so-code-bg); color: var(--so-ink); font: 12px/1.45 var(--so-font-mono); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
331
|
+
.k-work-term-note { color: var(--so-live-ink); }
|
|
332
|
+
.k-work-term-out { display: block; padding-left: var(--so-space-md); }
|
|
333
|
+
.k-work-term-failed { color: var(--so-fail-ink); }
|
|
334
|
+
|
|
258
335
|
/* ---------- Approval: four fixed slots in every state ---------- */
|
|
259
336
|
.k-slots { border: 1px solid var(--so-line); border-radius: var(--so-radius-card); padding: 16px 18px; display: grid; gap: 10px; background: var(--so-paper); transition: border-color var(--m-slow) var(--m-ease); }
|
|
260
337
|
.k-slots.wait { border-color: var(--so-needs); }
|
|
@@ -521,6 +598,21 @@ html:not(.k-js) .k-composer:focus-within, html.k-kbd .k-composer:focus-within {
|
|
|
521
598
|
.k-card { padding: 12px 16px; }
|
|
522
599
|
.k-step { font-size: 11px; }
|
|
523
600
|
.k-step-s { font-size: 10.5px; white-space: normal; }
|
|
601
|
+
.k-steprow-head { flex-wrap: wrap; row-gap: 2px; min-height: 44px; padding: 12px 0; }
|
|
602
|
+
.k-steprow-mark { margin-top: 12px; }
|
|
603
|
+
.k-steprow::before { top: 36px; }
|
|
604
|
+
.k-steprow-main { gap: 8px; padding-bottom: 8px; }
|
|
605
|
+
.k-steprow:is(.needs, .live, .wait, .stuck) .k-steprow-main { padding-bottom: 16px; }
|
|
606
|
+
/* The label and its time on one line, the sentence under them. */
|
|
607
|
+
.k-steprow-label { flex: 1 1 auto; order: 0; }
|
|
608
|
+
.k-steprow-time { order: 1; }
|
|
609
|
+
button.k-steprow-head::after { order: 2; }
|
|
610
|
+
.k-steprow-say { order: 3; flex: 1 1 100%; }
|
|
611
|
+
.k-steprow-say:empty { display: none; }
|
|
612
|
+
.k-steprow.needs > .k-steprow-main > .k-steprow-body { padding: 14px; }
|
|
613
|
+
/* An open body takes the whole width under its head; the rail stops at the head. No z-index: one would trap the body's phone dock under the app's. */
|
|
614
|
+
.k-steprow-body { margin-left: -34px; position: relative; background: var(--so-paper); }
|
|
615
|
+
.k-steprow-body .k-slot-acts > .k-btn, .k-steprow-body .k-slot-acts > form, .k-steprow-body .k-slot-acts > form > .k-btn { flex: 1 1 100%; width: 100%; }
|
|
524
616
|
.k-doc { padding: 14px 16px 40px; gap: 18px; }
|
|
525
617
|
.k-dh h1 { font-size: 20px; }
|
|
526
618
|
.k-backlink { display: none; }
|
package/dist/design/kit.d.ts
CHANGED
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
import { type Headline } from "../task-status.js";
|
|
11
11
|
/** The five status words. */
|
|
12
12
|
export type StatusKey = "needs" | "running" | "queued" | "finished" | "failed";
|
|
13
|
-
/** A chip's tone: "" is neutral; "ask" names a specific ask inside a Needs-you group (ink words,
|
|
13
|
+
/** A chip's tone: "" is neutral; "ask" names a specific ask inside a Needs-you group (ink words, ink dot). */
|
|
14
14
|
export type ChipTone = "" | "needs" | "ask" | "live" | "done" | "failed";
|
|
15
15
|
export declare const STATUS: Readonly<Record<StatusKey, {
|
|
16
16
|
word: string;
|
|
17
17
|
tone: ChipTone;
|
|
18
18
|
}>>;
|
|
19
19
|
/** A task's headline (task-status.ts) as the kit's chip: its own word, in the tone of the status it belongs to. A
|
|
20
|
-
* row that waits on a person never shows a failure tone; something that waits on someone else
|
|
20
|
+
* row that waits on a person never shows a failure tone; something that waits on someone else never carries the needs-you mark. */
|
|
21
21
|
export declare function chipOfHeadline(headline: Headline): {
|
|
22
22
|
word: string;
|
|
23
23
|
tone: ChipTone;
|
|
@@ -25,7 +25,7 @@ export declare function chipOfHeadline(headline: Headline): {
|
|
|
25
25
|
};
|
|
26
26
|
/** Which of the five a headline is. */
|
|
27
27
|
export declare function statusOfHeadline(headline: Headline): StatusKey;
|
|
28
|
-
/** Resource states (a computer that builds, not work): never
|
|
28
|
+
/** Resource states (a computer that builds, not work): never the needs-you mark. */
|
|
29
29
|
export declare const RESOURCE: Readonly<Record<"idle" | "building" | "offline", {
|
|
30
30
|
word: string;
|
|
31
31
|
tone: ChipTone;
|
|
@@ -77,7 +77,15 @@ export declare function timingBars(rows: readonly TimingRow[], scale?: number):
|
|
|
77
77
|
left: number;
|
|
78
78
|
width: number;
|
|
79
79
|
} | null>;
|
|
80
|
-
/**
|
|
80
|
+
/** A step row's marker: done (an ink disc with a check), needs (waits on this person: an ink ring with a dot), live
|
|
81
|
+
* (runs now: blue), wait (current, waiting on nothing this person does), stuck (stopped there: vermilion), skipped (a
|
|
82
|
+
* dashed ring), todo (not reached: a grey ring). */
|
|
83
|
+
export type StepRowMark = "done" | "needs" | "live" | "wait" | "stuck" | "skipped" | "todo";
|
|
84
|
+
/** The words a screen reader hears for a step row's marker. */
|
|
85
|
+
export declare const STEP_ROW_WORDS: Readonly<Record<StepRowMark, string>>;
|
|
86
|
+
/** The id of a step row's body, for its disclosure's aria-controls. */
|
|
87
|
+
export declare const stepRowBodyId: (key: string) => string;
|
|
88
|
+
/** One step on a progress line: done (a check), now (waits on you: ink), live (running: blue), failed, or to do. */
|
|
81
89
|
export type StepState = "done" | "now" | "live" | "failed" | "todo";
|
|
82
90
|
export type StepItem = {
|
|
83
91
|
label: string;
|
package/dist/design/kit.js
CHANGED
|
@@ -16,7 +16,7 @@ export const STATUS = {
|
|
|
16
16
|
failed: { word: "Failed", tone: "failed" },
|
|
17
17
|
};
|
|
18
18
|
/** A task's headline (task-status.ts) as the kit's chip: its own word, in the tone of the status it belongs to. A
|
|
19
|
-
* row that waits on a person never shows a failure tone; something that waits on someone else
|
|
19
|
+
* row that waits on a person never shows a failure tone; something that waits on someone else never carries the needs-you mark. */
|
|
20
20
|
export function chipOfHeadline(headline) {
|
|
21
21
|
const status = statusOfHeadline(headline);
|
|
22
22
|
return { word: headline === "Needs you" ? STATUS.needs.word : headline, tone: STATUS[status].tone, status };
|
|
@@ -32,7 +32,7 @@ export function statusOfHeadline(headline) {
|
|
|
32
32
|
case "neutral": return "queued";
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
/** Resource states (a computer that builds, not work): never
|
|
35
|
+
/** Resource states (a computer that builds, not work): never the needs-you mark. */
|
|
36
36
|
export const RESOURCE = {
|
|
37
37
|
idle: { word: "Idle", tone: "" },
|
|
38
38
|
building: { word: "Building", tone: "live" },
|
|
@@ -100,6 +100,12 @@ export function timingBars(rows, scale) {
|
|
|
100
100
|
const sc = scale ?? Math.max(1, ...rows.map(row => row.start + (row.st === "q" ? 0 : row.dur))) * 1.02;
|
|
101
101
|
return rows.map(row => row.st === "q" ? null : { left: (Math.max(0, row.start) / sc) * 100, width: (Math.max(row.dur, sc / 400) / sc) * 100 });
|
|
102
102
|
}
|
|
103
|
+
/** The words a screen reader hears for a step row's marker. */
|
|
104
|
+
export const STEP_ROW_WORDS = {
|
|
105
|
+
done: "done", needs: "waiting on you", live: "in progress", wait: "waiting", stuck: "stopped here", skipped: "skipped", todo: "not started",
|
|
106
|
+
};
|
|
107
|
+
/** The id of a step row's body, for its disclosure's aria-controls. */
|
|
108
|
+
export const stepRowBodyId = (key) => `steprow-${key}`;
|
|
103
109
|
/** The words a screen reader hears for a step's state. */
|
|
104
110
|
export const STEP_WORDS = { done: "done", now: "waiting on you", live: "in progress", failed: "failed", todo: "not started" };
|
|
105
111
|
/** How far the line is filled, 0–1: up to the current step (the first that isn't done), or all of it. */
|
package/dist/design/tokens.css
CHANGED
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
--so-nav-hover: #e4e4e4;
|
|
42
42
|
/* Nav Ink: idle sidebar rows and their hover fill on the frame. */
|
|
43
43
|
--so-nav-ink: #525252;
|
|
44
|
-
/*
|
|
45
|
-
--so-needs: var(--so-
|
|
46
|
-
/*
|
|
47
|
-
--so-needs-soft: var(--so-
|
|
44
|
+
/* Ink accent: the default accent, used for what waits on a person. */
|
|
45
|
+
--so-needs: var(--so-signal);
|
|
46
|
+
/* Ink wash: the fill behind attention badge text and the 3px focus halo around a focused field or composer — one step stronger than the neutral badge fill, so a waiting badge still reads first. */
|
|
47
|
+
--so-needs-soft: var(--so-signal-soft);
|
|
48
48
|
--so-neutral-ink: #525252;
|
|
49
49
|
/* Neutral Badge: the badge for anything that is a fact and not a claim on the person, such as queued, running or built today in a project peek, or a count in a fold. */
|
|
50
50
|
--so-neutral-soft: #f0f0f0;
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
--so-typography-title-sm-letter-spacing: -0.14px;
|
|
157
157
|
--so-typography-title-sm-line-height: 1.3;
|
|
158
158
|
--so-user-bubble: #f2f2f2;
|
|
159
|
-
/*
|
|
159
|
+
/* The terminal's yellow only. Pages never use it: cautions are neutral ink. */
|
|
160
160
|
--so-warning: #ab6400;
|
|
161
161
|
--so-warning-soft: #fff4d5;
|
|
162
162
|
}
|
package/dist/first-run.d.ts
CHANGED
|
@@ -76,20 +76,24 @@ export declare const TODO_GREP_ARGS: readonly string[];
|
|
|
76
76
|
export declare function findFirstTasks(repo: string, runner?: Runner): Promise<FirstTaskSuggestion[]>;
|
|
77
77
|
/** "First result in 7 min": how long after the installation began its first Ready result arrived. */
|
|
78
78
|
export declare function firstResultWords(since: string, at: string): string | null;
|
|
79
|
-
/**
|
|
80
|
-
|
|
79
|
+
/** A task's five steps, as a person reads them: the one label set the task page's rows, chat's first-task journey and
|
|
80
|
+
* the progress line all read. */
|
|
81
|
+
export declare const JOURNEY_STEPS: readonly [readonly ["plan", "Plan"], readonly ["approve", "Approval"], readonly ["build", "Build"], readonly ["checks", "Checks"], readonly ["ready", "Ready"]];
|
|
81
82
|
export type JourneyKey = (typeof JOURNEY_STEPS)[number][0];
|
|
82
83
|
/** `stuck`: the step it stopped at (Failed, Stopped, or waiting on something other than the approval). */
|
|
83
84
|
/** `skipped`: a stage the task went past without it happening (its checks didn't run or couldn't be read). `needsYou`:
|
|
84
|
-
* the current or stuck step waits on a person, so it is the one step drawn
|
|
85
|
+
* the current or stuck step waits on a person, so it is the one step drawn in the needs-you ink. */
|
|
86
|
+
/** `say`: what the step's state means when its label alone doesn't say it ("Checks failed", "Checks not run"); the
|
|
87
|
+
* label is always the step's own name from JOURNEY_STEPS. */
|
|
85
88
|
export type JourneyStep = {
|
|
86
89
|
key: JourneyKey;
|
|
87
90
|
label: string;
|
|
88
91
|
state: "done" | "current" | "stuck" | "skipped" | "todo";
|
|
89
92
|
needsYou?: true;
|
|
93
|
+
say?: string;
|
|
90
94
|
};
|
|
91
95
|
/**
|
|
92
|
-
* Where the first task stands on Plan →
|
|
96
|
+
* Where the first task stands on Plan → Approval → Build → Checks → Ready, from the one stage every surface reads
|
|
93
97
|
* (task-status.ts). Waiting for a worker before approval is still the plan; after approval it is the build. `built`:
|
|
94
98
|
* the build finished with a result.
|
|
95
99
|
*/
|
|
@@ -101,8 +105,8 @@ export declare function firstTaskJourney(read: {
|
|
|
101
105
|
* nothing says (the step is then shown skipped, never done). The road reads this one answer, never a row's words. */
|
|
102
106
|
export type RoadChecks = "passed" | "running" | "failed" | "not-run" | "off" | "unreadable" | null;
|
|
103
107
|
/**
|
|
104
|
-
* Any task's road (the
|
|
105
|
-
* from recorded facts.
|
|
108
|
+
* Any task's road (the step rows on its page): the first task's five steps, told only
|
|
109
|
+
* from recorded facts. Approval is done only when the plan was approved (a rewritten plan waiting on approval
|
|
106
110
|
* stands there again); a task that never needed one shows it skipped. Checks is done only when the approved check
|
|
107
111
|
* passed; a running, missing or Off check says so, and with no checks fact it is skipped. A failed check, or one that
|
|
108
112
|
* can't be read, stops the road at Checks: Ready isn't done (fail closed), even on a task a person marked complete.
|
package/dist/first-run.js
CHANGED
|
@@ -133,10 +133,11 @@ export function firstResultWords(since, at) {
|
|
|
133
133
|
}
|
|
134
134
|
return `First result in ${Math.round(minutes / (24 * 60))} days`;
|
|
135
135
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
136
|
+
/** A task's five steps, as a person reads them: the one label set the task page's rows, chat's first-task journey and
|
|
137
|
+
* the progress line all read. */
|
|
138
|
+
export const JOURNEY_STEPS = [["plan", "Plan"], ["approve", "Approval"], ["build", "Build"], ["checks", "Checks"], ["ready", "Ready"]];
|
|
138
139
|
/**
|
|
139
|
-
* Where the first task stands on Plan →
|
|
140
|
+
* Where the first task stands on Plan → Approval → Build → Checks → Ready, from the one stage every surface reads
|
|
140
141
|
* (task-status.ts). Waiting for a worker before approval is still the plan; after approval it is the build. `built`:
|
|
141
142
|
* the build finished with a result.
|
|
142
143
|
*/
|
|
@@ -155,8 +156,8 @@ export function firstTaskJourney(read, approved, built = false) {
|
|
|
155
156
|
state: index < at.index ? "done" : index === at.index ? (at.stuck ? "stuck" : "current") : "todo" }));
|
|
156
157
|
}
|
|
157
158
|
/**
|
|
158
|
-
* Any task's road (the
|
|
159
|
-
* from recorded facts.
|
|
159
|
+
* Any task's road (the step rows on its page): the first task's five steps, told only
|
|
160
|
+
* from recorded facts. Approval is done only when the plan was approved (a rewritten plan waiting on approval
|
|
160
161
|
* stands there again); a task that never needed one shows it skipped. Checks is done only when the approved check
|
|
161
162
|
* passed; a running, missing or Off check says so, and with no checks fact it is skipped. A failed check, or one that
|
|
162
163
|
* can't be read, stops the road at Checks: Ready isn't done (fail closed), even on a task a person marked complete.
|
|
@@ -181,13 +182,13 @@ export function taskRoad(read, approved, built, facts) {
|
|
|
181
182
|
return { ...step, state: "done" };
|
|
182
183
|
case "not-run":
|
|
183
184
|
waitsAtReady = true;
|
|
184
|
-
return { ...step, state: "skipped",
|
|
185
|
+
return { ...step, state: "skipped", say: "Checks not run" };
|
|
185
186
|
case "off":
|
|
186
187
|
waitsAtReady = true;
|
|
187
|
-
return { ...step, state: "skipped",
|
|
188
|
-
case "running": return { ...step, state: "current",
|
|
189
|
-
case "failed": return { ...step,
|
|
190
|
-
case "unreadable": return { ...step,
|
|
188
|
+
return { ...step, state: "skipped", say: "Checks at release" };
|
|
189
|
+
case "running": return { ...step, state: "current", say: "Checks running" };
|
|
190
|
+
case "failed": return { ...step, say: "Checks failed" };
|
|
191
|
+
case "unreadable": return { ...step, say: "Checks unreadable" };
|
|
191
192
|
default: return step;
|
|
192
193
|
}
|
|
193
194
|
}
|
|
@@ -195,16 +196,16 @@ export function taskRoad(read, approved, built, facts) {
|
|
|
195
196
|
return step;
|
|
196
197
|
// At Checks now: only a recorded failure, an unreadable check or a running check changes how it reads.
|
|
197
198
|
if (step.state === "current")
|
|
198
|
-
return facts.checks === "failed" ? { ...step, state: "stuck",
|
|
199
|
-
: facts.checks === "unreadable" ? { ...step, state: "stuck",
|
|
200
|
-
: facts.checks === "running" ? { ...step,
|
|
199
|
+
return facts.checks === "failed" ? { ...step, state: "stuck", say: "Checks failed" }
|
|
200
|
+
: facts.checks === "unreadable" ? { ...step, state: "stuck", say: "Checks unreadable" }
|
|
201
|
+
: facts.checks === "running" ? { ...step, say: "Checks running" } : step;
|
|
201
202
|
switch (facts.checks ?? null) {
|
|
202
203
|
case "passed": return step;
|
|
203
|
-
case "running": return { ...step, state: "current",
|
|
204
|
-
case "failed": return { ...step, state: "stuck",
|
|
205
|
-
case "not-run": return { ...step, state: "skipped",
|
|
206
|
-
case "off": return { ...step, state: "skipped",
|
|
207
|
-
case "unreadable": return { ...step, state: "stuck",
|
|
204
|
+
case "running": return { ...step, state: "current", say: "Checks running" };
|
|
205
|
+
case "failed": return { ...step, state: "stuck", say: "Checks failed" };
|
|
206
|
+
case "not-run": return { ...step, state: "skipped", say: "Checks not run" };
|
|
207
|
+
case "off": return { ...step, state: "skipped", say: "Checks at release" };
|
|
208
|
+
case "unreadable": return { ...step, state: "stuck", say: "Checks unreadable", ...(complete ? {} : { needsYou: true }) };
|
|
208
209
|
default: return { ...step, state: "skipped" };
|
|
209
210
|
}
|
|
210
211
|
});
|
package/dist/guides.js
CHANGED
|
@@ -335,7 +335,7 @@ ${AUTHORITY_LINE}
|
|
|
335
335
|
- The rail is four rows — inbox · board · builds · projects — and a
|
|
336
336
|
**more** group: portfolio, task list, fleet, system,
|
|
337
337
|
requirements, people, operating mode, settings. On a phone the same
|
|
338
|
-
five sit in the tab bar and more is \`/menu\`.
|
|
338
|
+
five sit in the tab bar and more is \`/menu\`. The needs-you mark appears only on
|
|
339
339
|
what needs a person: the inbox count and the one act that resolves a
|
|
340
340
|
screen (approve, answer, retry).
|
|
341
341
|
|
package/dist/operate.js
CHANGED
|
@@ -10531,6 +10531,8 @@ function describeApproveFailure(reason, id) {
|
|
|
10531
10531
|
return "only a person can approve this — approve it on the task page or from your paired chat";
|
|
10532
10532
|
if (reason === "archived")
|
|
10533
10533
|
return `${id} is put away — restore it with \`toolroll task restore ${id}\` first`;
|
|
10534
|
+
if (reason === "cancelled")
|
|
10535
|
+
return `${id} was cancelled, so there is nothing to approve`;
|
|
10534
10536
|
if (reason === "second-approver")
|
|
10535
10537
|
return `your approval of ${id} is recorded; it is protected work, so a second person needs to approve it (toolroll task approve ${id} as them)`;
|
|
10536
10538
|
if (reason === "no-approvers") {
|
package/dist/scope.d.ts
CHANGED
|
@@ -605,6 +605,11 @@ export type ApproveResult = {
|
|
|
605
605
|
| {
|
|
606
606
|
ok: false;
|
|
607
607
|
reason: "archived";
|
|
608
|
+
}
|
|
609
|
+
/** The task was cancelled: a cancelled task takes no approval, by any road (a stale page, the CLI). */
|
|
610
|
+
| {
|
|
611
|
+
ok: false;
|
|
612
|
+
reason: "cancelled";
|
|
608
613
|
};
|
|
609
614
|
/**
|
|
610
615
|
* Whether this name-and-token pair is a person the store knows. Shared by
|
package/dist/scope.js
CHANGED
|
@@ -52,7 +52,7 @@ import { z } from "zod";
|
|
|
52
52
|
import {} from "./contracts/acceptance-terms.js";
|
|
53
53
|
import { parseContract } from "./contracts/contract.js";
|
|
54
54
|
import { readAcceptance, readScopeTerms, storedRubricSchema } from "./contracts/scope.js";
|
|
55
|
-
import { taskArchived } from "./task-archive.js";
|
|
55
|
+
import { taskArchived, taskCancelled } from "./task-archive.js";
|
|
56
56
|
import { releaseCiHoldOf, releaseCiHoldWords } from "./release-ci-hold.js";
|
|
57
57
|
import { NO_READINESS, exactModelId, legOf, projectRoute, routeDigestOf, routeFromJson, routeJsonProblem, routeWords, } from "./phase-routing.js";
|
|
58
58
|
/** Same shape as a runner's credential, for the same reasons. */
|
|
@@ -1120,6 +1120,10 @@ chat) {
|
|
|
1120
1120
|
// A put-away task (v145) is restored first; sealScopeApproval refuses it too, on every road.
|
|
1121
1121
|
if (taskArchived(store, taskId))
|
|
1122
1122
|
return { ok: false, reason: "archived" };
|
|
1123
|
+
// A cancelled task takes no yes either — read here, in the seal's transaction, before any vote or proof is
|
|
1124
|
+
// written: an approval page left open while the task was cancelled elsewhere, or the CLI, approves nothing.
|
|
1125
|
+
if (taskCancelled(store, taskId))
|
|
1126
|
+
return { ok: false, reason: "cancelled" };
|
|
1123
1127
|
// The digest is required, not optional. An operator reads a scope, somebody
|
|
1124
1128
|
// rewrites it, and an approval that did not name what it saw would agree to
|
|
1125
1129
|
// the new one in silence — which is the whole failure this guards.
|
|
@@ -1550,6 +1554,9 @@ export function liveReleaseOf(store, taskId, action, now = new Date()) {
|
|
|
1550
1554
|
// A put-away task (v145, task-tidy.md), or a put-away anchor, deploys, merges and carries nothing: restore it first.
|
|
1551
1555
|
if (taskArchived(store, taskId) || taskArchived(store, a.anchorTask))
|
|
1552
1556
|
return refuse("the release task is put away");
|
|
1557
|
+
// A cancelled task, or a cancelled anchor, the same: cancelling ends what its approval allows.
|
|
1558
|
+
if (taskCancelled(store, taskId) || taskCancelled(store, a.anchorTask))
|
|
1559
|
+
return refuse("the release task was cancelled");
|
|
1553
1560
|
const newest = newestReleaseGeneration(store, a.repo, a.version, a.pr);
|
|
1554
1561
|
if (newest === null || newest.id !== a.id)
|
|
1555
1562
|
return refuse("a newer approval of this release replaced this one");
|
package/dist/server/chrome.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export declare const DEMO_BANNER_SHORT = "Demo: sample projects. Nothing calls a
|
|
|
56
56
|
* a person's accent (accentHead) still wins over the generated default. */
|
|
57
57
|
export declare const STYLE: string;
|
|
58
58
|
/** Appearance: a three-way segmented switch, one tap per choice. */
|
|
59
|
-
export declare const THEME_CONTROLS_CSS = ".task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}@media(hover:hover) and (pointer:fine){.result-action .result-feedback-link:hover{background:var(--so-raised)}}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-
|
|
59
|
+
export declare const THEME_CONTROLS_CSS = ".task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}@media(hover:hover) and (pointer:fine){.result-action .result-feedback-link:hover{background:var(--so-raised)}}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-neutral-soft);color:var(--so-ink)}.verdict-chip--info{background:var(--so-info-soft);color:var(--so-info)}.verdict-by{margin:.4rem 0 0}details.result-request-open{margin:.5rem 0}details.result-request-open>summary{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;cursor:pointer;list-style:none}details.result-request-open>summary::-webkit-details-marker{display:none}details.result-request-open[open]>summary{margin-bottom:.75rem}.settings-tiles{display:grid;gap:1.25rem;margin:0 0 2rem}.settings-tiles h2{margin:0 0 .5rem;font-size:.875rem;font-weight:600;color:var(--so-muted)}.settings-tiles section>div{display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.5rem}.settings-tiles a>span{display:grid;gap:.1rem;min-width:0}.settings-tiles .provider-status{font-weight:400;font-size:.8125rem}.settings-tiles a{display:flex;align-items:center;gap:.6rem;min-height:3rem;padding:.65rem .8rem;border:1px solid var(--so-line);border-radius:.625rem;background:var(--so-paper);color:var(--so-ink);text-decoration:none;font-weight:550;font-size:.875rem}@media(hover:hover) and (pointer:fine){.settings-tiles a:hover{border-color:var(--so-input-line);background:var(--so-raised)}}.settings-tiles a>svg{width:1.1rem;height:1.1rem;flex-shrink:0;color:var(--so-accent-text)}details.settings-more{margin:.25rem 0 1.25rem}details.settings-more>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:550}details.settings-more>summary .meta{font-weight:400;margin-left:.35rem}.settings-changed{margin-top:-.25rem}.appearance{margin:0 0 28px}.appearance h2{margin:0 0 10px}.theme-switch{display:inline-flex;flex-wrap:nowrap;max-width:100%;gap:4px;padding:4px;margin:0;border:1px solid var(--so-line);border-radius:10px;background:var(--so-raised)}.theme-switch .theme-choice,.so-native-region .theme-switch .theme-choice{flex:1 1 0;width:auto;white-space:nowrap;min-height:40px;padding:8px 16px;border:0;border-radius:7px;background:transparent;color:var(--so-muted);font:inherit;font-weight:550;box-shadow:none;cursor:pointer}@media(hover:hover) and (pointer:fine){.theme-switch .theme-choice:hover{color:var(--so-ink)}}.theme-switch .theme-choice[aria-pressed=\"true\"]{background:var(--so-paper);color:var(--so-ink);box-shadow:0 1px 2px rgb(0 0 0 / .1)}.appearance .meta{margin:8px 0 0}@media(max-width:600px){.theme-switch .theme-choice{min-height:44px}}.update-notes{white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;max-height:18rem;overflow:auto}";
|
|
60
60
|
/** The page CSS this module writes itself (not the imported modules'), for the stylesheet contract tests. */
|
|
61
61
|
export declare const PAGE_CSS: string;
|
|
62
62
|
/** The Inbox tabs (console v2): a segmented track of real links; the dot marks a tab with something new, on phones only. */
|
package/dist/server/chrome.js
CHANGED
|
@@ -150,7 +150,7 @@ export const STYLE = readFileSync(join(import.meta.dirname, "..", "design", "tok
|
|
|
150
150
|
// server pages (server/kit.ts) and React views (browser/kit/) looks the same everywhere.
|
|
151
151
|
readFileSync(join(import.meta.dirname, "..", "design", "kit.css"), "utf8");
|
|
152
152
|
/** Appearance: a three-way segmented switch, one tap per choice. */
|
|
153
|
-
export const THEME_CONTROLS_CSS = `.task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}@media(hover:hover) and (pointer:fine){.result-action .result-feedback-link:hover{background:var(--so-raised)}}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-
|
|
153
|
+
export const THEME_CONTROLS_CSS = `.task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}@media(hover:hover) and (pointer:fine){.result-action .result-feedback-link:hover{background:var(--so-raised)}}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-neutral-soft);color:var(--so-ink)}.verdict-chip--info{background:var(--so-info-soft);color:var(--so-info)}.verdict-by{margin:.4rem 0 0}details.result-request-open{margin:.5rem 0}details.result-request-open>summary{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;cursor:pointer;list-style:none}details.result-request-open>summary::-webkit-details-marker{display:none}details.result-request-open[open]>summary{margin-bottom:.75rem}.settings-tiles{display:grid;gap:1.25rem;margin:0 0 2rem}.settings-tiles h2{margin:0 0 .5rem;font-size:.875rem;font-weight:600;color:var(--so-muted)}.settings-tiles section>div{display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.5rem}.settings-tiles a>span{display:grid;gap:.1rem;min-width:0}.settings-tiles .provider-status{font-weight:400;font-size:.8125rem}.settings-tiles a{display:flex;align-items:center;gap:.6rem;min-height:3rem;padding:.65rem .8rem;border:1px solid var(--so-line);border-radius:.625rem;background:var(--so-paper);color:var(--so-ink);text-decoration:none;font-weight:550;font-size:.875rem}@media(hover:hover) and (pointer:fine){.settings-tiles a:hover{border-color:var(--so-input-line);background:var(--so-raised)}}.settings-tiles a>svg{width:1.1rem;height:1.1rem;flex-shrink:0;color:var(--so-accent-text)}details.settings-more{margin:.25rem 0 1.25rem}details.settings-more>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:550}details.settings-more>summary .meta{font-weight:400;margin-left:.35rem}.settings-changed{margin-top:-.25rem}.appearance{margin:0 0 28px}.appearance h2{margin:0 0 10px}.theme-switch{display:inline-flex;flex-wrap:nowrap;max-width:100%;gap:4px;padding:4px;margin:0;border:1px solid var(--so-line);border-radius:10px;background:var(--so-raised)}.theme-switch .theme-choice,.so-native-region .theme-switch .theme-choice{flex:1 1 0;width:auto;white-space:nowrap;min-height:40px;padding:8px 16px;border:0;border-radius:7px;background:transparent;color:var(--so-muted);font:inherit;font-weight:550;box-shadow:none;cursor:pointer}@media(hover:hover) and (pointer:fine){.theme-switch .theme-choice:hover{color:var(--so-ink)}}.theme-switch .theme-choice[aria-pressed="true"]{background:var(--so-paper);color:var(--so-ink);box-shadow:0 1px 2px rgb(0 0 0 / .1)}.appearance .meta{margin:8px 0 0}@media(max-width:600px){.theme-switch .theme-choice{min-height:44px}}.update-notes{white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;max-height:18rem;overflow:auto}`;
|
|
154
154
|
/** The page CSS this module writes itself (not the imported modules'), for the stylesheet contract tests. */
|
|
155
155
|
export const PAGE_CSS = STYLE + THEME_CONTROLS_CSS;
|
|
156
156
|
/** The Inbox tabs (console v2): a segmented track of real links; the dot marks a tab with something new, on phones only. */
|