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
package/dist/server/console.css
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
--muted: var(--so-raised); --muted-foreground: var(--so-muted); --border: var(--so-line); --input: var(--so-input-line);
|
|
42
42
|
--primary: var(--so-accent); --primary-foreground: var(--so-on-accent); --secondary: var(--so-raised);
|
|
43
43
|
--accent: var(--so-soft); --destructive: var(--so-danger); --destructive-soft: var(--so-danger-soft);
|
|
44
|
-
--success: var(--so-success); --success-soft: var(--so-success-soft); --warning: var(--so-
|
|
44
|
+
--success: var(--so-success); --success-soft: var(--so-success-soft); --warning: var(--so-neutral-ink); --warning-soft: var(--so-neutral-soft);
|
|
45
45
|
--running: var(--so-info); --running-soft: var(--so-info-soft); --ring: var(--so-signal);
|
|
46
46
|
/* The accent means one thing: a person is needed (approve, answer, decide). */
|
|
47
47
|
--brand: var(--so-attention); --brand-foreground: var(--so-on-attention); --brand-soft: var(--so-attention-soft);
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
}
|
|
142
142
|
.badge-note {
|
|
143
143
|
background: color-mix(in srgb, var(--muted) 58%, var(--card));
|
|
144
|
-
color: var(--so-
|
|
144
|
+
color: var(--so-neutral-ink); border-color: var(--border);
|
|
145
145
|
}
|
|
146
146
|
.badge-overdue {
|
|
147
147
|
background: color-mix(in srgb, var(--muted) 58%, var(--card)); color: var(--foreground);
|
|
@@ -173,17 +173,17 @@
|
|
|
173
173
|
}
|
|
174
174
|
.badge-cut { background: var(--muted); }
|
|
175
175
|
/* The status chip (components/ui/badge.tsx `size="chip"`, after ReUI's light badge with a dot): 20px, 6px
|
|
176
|
-
corners, a soft wash, 11.5px words and a 6px dot. Needs you is
|
|
177
|
-
|
|
176
|
+
corners, a soft wash, 11.5px words and a 6px dot. Needs you is solid ink with paper words and
|
|
177
|
+
no dot; elsewhere the dot is decoration and the word carries the meaning. */
|
|
178
178
|
.chip {
|
|
179
179
|
display: inline-flex; align-items: center; gap: .375rem; height: 1.25rem; padding: 0 .375rem; border-radius: var(--so-radius-sm);
|
|
180
180
|
font-family: var(--font-sans); font-size: .71875rem; font-weight: 500; line-height: 1; white-space: nowrap; vertical-align: middle;
|
|
181
181
|
background: var(--so-neutral-soft); color: var(--so-ink);
|
|
182
182
|
}
|
|
183
|
-
/* Ink words, the tone in the dot (the Agents → Live chip); Needs you
|
|
183
|
+
/* Ink words, the tone in the dot (the Agents → Live chip); Needs you is solid ink, no dot. */
|
|
184
184
|
.chip-dot { width: .375rem; height: .375rem; flex-shrink: 0; border-radius: var(--so-radius-full); background: var(--so-neutral-ink); }
|
|
185
|
-
.chip-needs { background: var(--so-
|
|
186
|
-
.chip-needs .chip-dot {
|
|
185
|
+
.chip-needs { background: var(--so-needs); color: var(--so-on-signal); }
|
|
186
|
+
.chip-needs .chip-dot { display: none; }
|
|
187
187
|
.chip-live { background: var(--so-info-soft); }
|
|
188
188
|
.chip-live .chip-dot { background: var(--so-info); }
|
|
189
189
|
.chip-done { background: var(--so-success-soft); }
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
.frame { display: flex; flex-direction: column; gap: .25rem; padding: .25rem; border: 1px solid var(--so-line); border-radius: var(--so-radius-card); background: var(--so-raised); }
|
|
196
196
|
.frame-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; min-height: 2rem; padding: .25rem .625rem; }
|
|
197
197
|
.frame-panel { position: relative; border: 1px solid var(--so-line); border-radius: calc(var(--so-radius-card) - .25rem - 1px); background: var(--so-paper); padding: .75rem .875rem; }
|
|
198
|
-
.frame-panel.waits { border-color: var(--so-
|
|
198
|
+
.frame-panel.waits { border-color: var(--so-needs); }
|
|
199
199
|
|
|
200
200
|
.card {
|
|
201
201
|
border: 1px solid var(--glass-border); border-radius: var(--radius); background: var(--glass);
|
|
@@ -1012,7 +1012,7 @@
|
|
|
1012
1012
|
.dispatch-status[data-dispatch-status="proof-refuted"] .dispatch-copy > strong::before,
|
|
1013
1013
|
.dispatch-status[data-dispatch-status="needs-verification"] .dispatch-copy > strong::before {
|
|
1014
1014
|
content: ""; display: inline-block; width: .45rem; height: .45rem; margin-right: .45rem; border-radius: 50%; vertical-align: .08rem;
|
|
1015
|
-
background: var(--
|
|
1015
|
+
background: var(--warning);
|
|
1016
1016
|
}
|
|
1017
1017
|
.problem.dispatch-status[data-dispatch-status="proof-refuted"] .dispatch-copy > strong::before { background: var(--destructive); }
|
|
1018
1018
|
.dispatch-status[data-dispatch-status="needs-verification"] .dispatch-copy > strong::before { background: var(--muted-foreground); }
|
|
@@ -1110,14 +1110,14 @@
|
|
|
1110
1110
|
.contract-panel { margin-top: .8rem; padding: .7rem .85rem; border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px); background: color-mix(in srgb, var(--muted) 45%, transparent); }
|
|
1111
1111
|
.contract-panel .approval-label { margin: 0 0 .25rem; }
|
|
1112
1112
|
.contract-panel p { margin: .2rem 0; }
|
|
1113
|
-
.contract-amended { border-color: color-mix(in srgb, var(--warning
|
|
1113
|
+
.contract-amended { border-color: color-mix(in srgb, var(--warning) 55%, var(--glass-border)); background: color-mix(in srgb, var(--warning) 9%, transparent); }
|
|
1114
1114
|
.contract-reason { font-size: .9rem; }
|
|
1115
1115
|
.contract-changes { margin: .5rem 0 0; padding-left: 1.1rem; display: grid; gap: .45rem; }
|
|
1116
1116
|
.contract-changes li { overflow-wrap: anywhere; }
|
|
1117
1117
|
.contract-change-kind { display: inline-block; margin-right: .3rem; padding: .05rem .4rem; border-radius: 999px; font: 600 .62rem/1.5 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; background: color-mix(in srgb, var(--muted) 70%, transparent); }
|
|
1118
1118
|
.contract-change-added { background: color-mix(in srgb, var(--success, #2f9e5f) 18%, transparent); }
|
|
1119
1119
|
.contract-change-removed { background: color-mix(in srgb, var(--danger, #c8453d) 18%, transparent); }
|
|
1120
|
-
.contract-change-changed { background: color-mix(in srgb, var(--warning
|
|
1120
|
+
.contract-change-changed { background: color-mix(in srgb, var(--warning) 22%, transparent); }
|
|
1121
1121
|
.contract-before, .contract-after { margin-top: .15rem; font-size: .85rem; }
|
|
1122
1122
|
.contract-before { color: var(--muted-foreground); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--muted-foreground) 55%, transparent); }
|
|
1123
1123
|
.contract-note { margin-top: .5rem; }
|
|
@@ -1251,6 +1251,35 @@
|
|
|
1251
1251
|
.approval-roles dd { margin: 0; }
|
|
1252
1252
|
.approval-roles dd ul { margin: 2px 0 0; color: var(--muted-foreground); }
|
|
1253
1253
|
.chat-plan .approval-sheet { padding: 0; border: 0; background: none; }
|
|
1254
|
+
/* The plan sheet (task page, docs/plans/task-page-steps.md): the same terms read top to bottom — one lead sentence,
|
|
1255
|
+
Steps, Done when, Will change / Won't touch, Worth knowing, the agent — every part open, small muted headings. */
|
|
1256
|
+
.plan-sheet { display: grid; gap: 22px; margin: 0; min-width: 0; color: var(--so-ink); }
|
|
1257
|
+
.plan-sheet > * { margin: 0; }
|
|
1258
|
+
.plan-sheet-lead { max-width: 66ch; font-size: 17px; line-height: 1.5; letter-spacing: -.01em; overflow-wrap: anywhere; }
|
|
1259
|
+
.plan-sheet-lead-long { font-size: 15px; line-height: 1.6; letter-spacing: 0; }
|
|
1260
|
+
.plan-sheet-text { max-width: 66ch; font-size: 14px; line-height: 1.65; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
1261
|
+
.plan-sheet-part { display: grid; align-content: start; gap: var(--so-space-sm); min-width: 0; max-width: 75ch; font-size: 14px; line-height: 1.6; overflow-wrap: anywhere; }
|
|
1262
|
+
.plan-sheet-part > *, .plan-sheet-part p, .plan-sheet-part ul, .plan-sheet-part ol, .plan-sheet-part dl { margin: 0; }
|
|
1263
|
+
.plan-sheet-h { margin: 0; font-size: 12px; font-weight: 500; line-height: 1.5; letter-spacing: 0; text-transform: none; color: var(--so-muted); }
|
|
1264
|
+
.plan-sheet-sub { color: var(--so-muted); font-size: 12.5px; }
|
|
1265
|
+
.plan-sheet-steps { display: grid; gap: var(--so-space-sm); padding: 0; list-style: none; counter-reset: plan-step; }
|
|
1266
|
+
.plan-sheet-steps > li { display: flex; gap: var(--so-space-md); counter-increment: plan-step; }
|
|
1267
|
+
.plan-sheet-steps > li::before { content: counter(plan-step); flex: 0 0 22px; box-sizing: border-box; width: 22px; height: 22px; border: 1px solid var(--so-line); border-radius: 50%; display: grid; place-items: center; font-size: 12px; color: var(--so-muted); font-variant-numeric: tabular-nums; }
|
|
1268
|
+
.plan-sheet-steps > li > span { min-width: 0; padding-top: 1px; }
|
|
1269
|
+
.plan-sheet-done { display: grid; padding: 0; list-style: none; }
|
|
1270
|
+
.plan-sheet-done > li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--so-space-xs) var(--so-space-md); padding: var(--so-space-sm) 0; border-bottom: 1px solid var(--so-line); }
|
|
1271
|
+
.plan-sheet-done > li:last-child { border-bottom: 0; }
|
|
1272
|
+
.plan-sheet-done > li > span:first-child { flex: 1 1 260px; min-width: 0; }
|
|
1273
|
+
.plan-sheet-how { flex: none; font-size: 12.5px; color: var(--so-muted); }
|
|
1274
|
+
.plan-sheet-pair { display: flex; flex-wrap: wrap; gap: var(--so-space-lg) 40px; }
|
|
1275
|
+
.plan-sheet-pair > .plan-sheet-part { flex: 1 1 220px; }
|
|
1276
|
+
.plan-sheet .approval-paths li { color: var(--so-ink); font-size: 13px; line-height: 1.7; }
|
|
1277
|
+
.plan-sheet-list { display: grid; gap: var(--so-space-xs); padding-left: 1.25rem; }
|
|
1278
|
+
.plan-sheet-warn { color: var(--so-ink); }
|
|
1279
|
+
.plan-sheet .approval-amendment { margin: 0; }
|
|
1280
|
+
.plan-sheet .approval-who, .plan-sheet .approval-evidence, .plan-sheet .approval-allowing, .plan-sheet .approval-you-check { margin: 0; }
|
|
1281
|
+
.plan-sheet .approval-roles { margin: 0; }
|
|
1282
|
+
.plan-sheet .revision-card { margin: 0; padding: 0; border: 0; background: none; }
|
|
1254
1283
|
@media (max-width: 760px) {
|
|
1255
1284
|
.approval-sheet { gap: var(--so-space-md); padding: 14px; }
|
|
1256
1285
|
.approval-row { grid-template-columns: 1fr; gap: 2px; }
|
|
@@ -1564,7 +1593,7 @@
|
|
|
1564
1593
|
.status-line { display: inline-flex; align-items: center; gap: .45rem; min-width: 0; font-size: .875rem; font-weight: 600; color: var(--foreground); }
|
|
1565
1594
|
.status-line .status-label { min-width: 0; overflow-wrap: anywhere; }
|
|
1566
1595
|
.status-line .status-dot { flex: none; width: .5rem; height: .5rem; border-radius: 50%; background: var(--muted-foreground); }
|
|
1567
|
-
.status-line[data-tone="attention"] .status-dot { background: var(--
|
|
1596
|
+
.status-line[data-tone="attention"] .status-dot { background: var(--so-needs); }
|
|
1568
1597
|
.status-line[data-tone="problem"] .status-dot { background: var(--destructive); }
|
|
1569
1598
|
.status-line[data-tone="live"] .status-dot { background: var(--running); box-shadow: 0 0 0 3px var(--running-soft); }
|
|
1570
1599
|
.status-line[data-tone="ready"] .status-dot, .status-line[data-tone="done"] .status-dot { background: var(--success); }
|
|
@@ -1577,7 +1606,7 @@
|
|
|
1577
1606
|
.pull-request-head strong { font-size: 1.0625rem; font-weight: 600; color: var(--foreground); display: inline-flex; align-items: center; gap: .5rem; }
|
|
1578
1607
|
.pull-request-head strong::before { content: ""; width: .5rem; height: .5rem; border-radius: 999px; background: var(--muted-foreground); }
|
|
1579
1608
|
.pull-request--ok .pull-request-head strong::before { background: var(--success, #15803d); }
|
|
1580
|
-
.pull-request--problem .pull-request-head strong::before { background: var(--
|
|
1609
|
+
.pull-request--problem .pull-request-head strong::before { background: var(--foreground); }
|
|
1581
1610
|
.pull-request-act { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem .75rem; margin: .25rem 0 0; }
|
|
1582
1611
|
.pull-request-act .meta { flex: 1 1 100%; }
|
|
1583
1612
|
.pull-request-act label { display: grid; gap: .25rem; flex: 1 1 12rem; margin: 0; }
|
|
@@ -1813,7 +1842,7 @@
|
|
|
1813
1842
|
}
|
|
1814
1843
|
/* A lane is a frame (components/ui/frame.tsx, after ReUI's Frame): a raised well with a hairline, its head a
|
|
1815
1844
|
status chip and a mono count on the well's fill, its cards paper panels at concentric corners. Only the lane
|
|
1816
|
-
that waits on a person is
|
|
1845
|
+
that waits on a person is ink: its chip, and each card's thin full outline. No fill, no stripe, no shadow. */
|
|
1817
1846
|
.lane {
|
|
1818
1847
|
background: var(--so-raised); border: 1px solid var(--so-line);
|
|
1819
1848
|
border-radius: var(--so-radius-card); padding: .25rem; min-height: 12rem;
|
|
@@ -1830,7 +1859,7 @@
|
|
|
1830
1859
|
background: var(--so-paper); border: 1px solid var(--so-line);
|
|
1831
1860
|
border-radius: calc(var(--so-radius-card) - .25rem - 1px); padding: .625rem .75rem; margin-top: .25rem;
|
|
1832
1861
|
}
|
|
1833
|
-
.lane-attention .lane-card { border-color: var(--so-
|
|
1862
|
+
.lane-attention .lane-card { border-color: var(--so-needs); }
|
|
1834
1863
|
/* The order view's columns are frames too, with roomier insides (a form, a note) and a quiet dot by the name. */
|
|
1835
1864
|
.lane.queue-column { padding: .5rem; }
|
|
1836
1865
|
.queue-column > h2::before { content: ""; width: .375rem; height: .375rem; border-radius: var(--so-radius-full); flex: none; background: var(--muted-foreground); opacity: .55; }
|
|
@@ -2854,9 +2883,9 @@ html.so-swap::view-transition-old(*):only-child { animation: so-card-out 160ms e
|
|
|
2854
2883
|
.tc-c0 { color: var(--so-ink); stroke: var(--so-ink); }
|
|
2855
2884
|
.tc-c1 { color: var(--so-info); stroke: var(--so-info); }
|
|
2856
2885
|
.tc-c2 { color: var(--so-success); stroke: var(--so-success); }
|
|
2857
|
-
.tc-c3 { color: var(--so-
|
|
2886
|
+
.tc-c3 { color: var(--so-muted); stroke: var(--so-muted); }
|
|
2858
2887
|
.tc-c4 { color: var(--so-danger); stroke: var(--so-danger); }
|
|
2859
|
-
.tc-c5 { color: var(--so-
|
|
2888
|
+
.tc-c5 { color: var(--so-input-line); stroke: var(--so-input-line); }
|
|
2860
2889
|
.tc-line { margin: 0; display: grid; gap: var(--so-space-xs); }
|
|
2861
2890
|
.tc-line svg { width: 100%; height: 90px; }
|
|
2862
2891
|
.tc-line figcaption { font-size: 11.5px; color: var(--so-muted); }
|
package/dist/server/kit.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* as plain HTML without it.
|
|
10
10
|
*/
|
|
11
11
|
import { type AttributeValue, type Html, type HtmlValue, type PostFormOptions } from "../html.js";
|
|
12
|
-
import { type ApprovalFacts, type ApprovalKind, type ChipTone, type KitIcon, type StatusKey, type StepItem, type TimingRow } from "../design/kit.js";
|
|
12
|
+
import { type ApprovalFacts, type ApprovalKind, type ChipTone, type KitIcon, type StatusKey, type StepItem, type StepRowMark, type TimingRow } from "../design/kit.js";
|
|
13
13
|
import type { Headline } from "../task-status.js";
|
|
14
14
|
type Attrs = Readonly<Record<string, AttributeValue>>;
|
|
15
15
|
export declare function icon(name: KitIcon, small?: boolean): Html;
|
|
@@ -140,7 +140,7 @@ export declare function facts(rows: ReadonlyArray<readonly [key: string, value:
|
|
|
140
140
|
export declare const note: (text: HtmlValue) => Html;
|
|
141
141
|
/** A refusal or problem, where it happened (role=alert): what went wrong and what didn't change. */
|
|
142
142
|
export declare const notice: (text: HtmlValue) => Html;
|
|
143
|
-
/** One neutral system line (a builder offline, an update): not a failure, never
|
|
143
|
+
/** One neutral system line (a builder offline, an update): not a failure, never the needs-you mark. */
|
|
144
144
|
export declare const infoLine: (text: HtmlValue) => Html;
|
|
145
145
|
export declare function empty(options: {
|
|
146
146
|
title: string;
|
|
@@ -223,7 +223,7 @@ export declare function approveForm(options: {
|
|
|
223
223
|
}): Html;
|
|
224
224
|
/** The terms line for an act, from the same rules. */
|
|
225
225
|
export declare const approvalTerms: (kind: ApprovalKind, facts: ApprovalFacts) => string;
|
|
226
|
-
/** Waits that aren't tasks, on their own page (a spend limit, a failed backup): one
|
|
226
|
+
/** Waits that aren't tasks, on their own page (a spend limit, a failed backup): one ink outline, a count, items
|
|
227
227
|
* split by hairlines, each with its one action. They never join the global Needs-you count. */
|
|
228
228
|
export declare function needsPanel(items: ReadonlyArray<{
|
|
229
229
|
title: string;
|
|
@@ -359,6 +359,39 @@ export declare function outField(options: {
|
|
|
359
359
|
error?: string | null;
|
|
360
360
|
attrs?: Attrs;
|
|
361
361
|
}): Html;
|
|
362
|
+
/** One step row: its marker, label, one sentence, a time (`at` ISO, `when` the words for it), and its body. `toggle`: a
|
|
363
|
+
* finished row's head is a disclosure button (aria-expanded) for its body; `open` shows the body. */
|
|
364
|
+
export type StepRowItem = {
|
|
365
|
+
key: string;
|
|
366
|
+
label: string;
|
|
367
|
+
mark: StepRowMark;
|
|
368
|
+
sentence: HtmlValue;
|
|
369
|
+
needsYou?: boolean;
|
|
370
|
+
current?: boolean;
|
|
371
|
+
at?: string | null;
|
|
372
|
+
when?: string;
|
|
373
|
+
body?: HtmlValue;
|
|
374
|
+
toggle?: boolean;
|
|
375
|
+
open?: boolean;
|
|
376
|
+
};
|
|
377
|
+
/** The steps of one object as the page itself (a task: Plan · Approval · Build · Checks · Ready): an ordered list, a
|
|
378
|
+
* marker on a rail, the label, one sentence and a time per row, and the row's body under it. The current row is
|
|
379
|
+
* `aria-current="step"`. Same markup as `KStepRows`. */
|
|
380
|
+
export declare function stepRows(items: readonly StepRowItem[], label?: string): Html;
|
|
381
|
+
/** The work's frame (KIT.md "The work"): a header (the title, who is working with a blue dot while it runs, Close), the
|
|
382
|
+
* body that scrolls, and the message box at the foot. The records themselves are followed live by the workspace
|
|
383
|
+
* (`KWork` and `useConversation`); a page without script shows what `body` holds. Same markup as `KWork`. */
|
|
384
|
+
export declare function work(options: {
|
|
385
|
+
id: string;
|
|
386
|
+
title: string;
|
|
387
|
+
who?: HtmlValue;
|
|
388
|
+
live?: boolean;
|
|
389
|
+
close?: string | null;
|
|
390
|
+
hidden?: boolean;
|
|
391
|
+
body?: HtmlValue;
|
|
392
|
+
foot?: HtmlValue;
|
|
393
|
+
attrs?: Attrs;
|
|
394
|
+
}): Html;
|
|
362
395
|
export type CheckStep = {
|
|
363
396
|
key: string;
|
|
364
397
|
title: string;
|
package/dist/server/kit.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* (src/browser/kit/behavior.ts), which wires any kit markup the workspace places; every control here still works
|
|
9
9
|
* as plain HTML without it.
|
|
10
10
|
*/
|
|
11
|
-
import { attributes, html, joinHtml, passwordlessRendering, postForm } from "../html.js";
|
|
12
|
-
import { KIT_ICONS, NOT_FOUND, SETTINGS_GROUPS, STATUS, STEP_WORDS, TIMING_WORDS, approvalAsk, chipOfHeadline, dur, needsWords, stepsFill, termsOf, timingBars, } from "../design/kit.js";
|
|
11
|
+
import { attributes, html, htmlString, joinHtml, passwordlessRendering, postForm } from "../html.js";
|
|
12
|
+
import { KIT_ICONS, NOT_FOUND, SETTINGS_GROUPS, STATUS, STEP_ROW_WORDS, STEP_WORDS, stepRowBodyId, TIMING_WORDS, approvalAsk, chipOfHeadline, dur, needsWords, stepsFill, termsOf, timingBars, } from "../design/kit.js";
|
|
13
13
|
const cls = (...names) => names.filter(Boolean).join(" ");
|
|
14
14
|
// ---- text and icons ---------------------------------------------------------------------------------------------
|
|
15
15
|
export function icon(name, small = false) {
|
|
@@ -106,7 +106,7 @@ export function facts(rows) {
|
|
|
106
106
|
export const note = (text) => html `<p class="k-note">${text}</p>`;
|
|
107
107
|
/** A refusal or problem, where it happened (role=alert): what went wrong and what didn't change. */
|
|
108
108
|
export const notice = (text) => html `<p class="k-notice" role="alert">${icon("alert", true)}<span>${text}</span></p>`;
|
|
109
|
-
/** One neutral system line (a builder offline, an update): not a failure, never
|
|
109
|
+
/** One neutral system line (a builder offline, an update): not a failure, never the needs-you mark. */
|
|
110
110
|
export const infoLine = (text) => html `<p class="k-notice info">${text}</p>`;
|
|
111
111
|
export function empty(options) {
|
|
112
112
|
return html `<div class="k-empty"><p class="k-empty-t">${options.title}</p>${options.text ? html `<p class="k-empty-x">${options.text}</p>` : ""}${options.action ?? ""}</div>`;
|
|
@@ -180,7 +180,7 @@ export function approveForm(options) {
|
|
|
180
180
|
}
|
|
181
181
|
/** The terms line for an act, from the same rules. */
|
|
182
182
|
export const approvalTerms = (kind, facts) => termsOf(kind, facts);
|
|
183
|
-
/** Waits that aren't tasks, on their own page (a spend limit, a failed backup): one
|
|
183
|
+
/** Waits that aren't tasks, on their own page (a spend limit, a failed backup): one ink outline, a count, items
|
|
184
184
|
* split by hairlines, each with its one action. They never join the global Needs-you count. */
|
|
185
185
|
export function needsPanel(items, label = "Needs you") {
|
|
186
186
|
if (items.length === 0)
|
|
@@ -320,6 +320,35 @@ export function outField(options) {
|
|
|
320
320
|
return html `<div class="k-field"><label class="k-label" for="${options.id}">${options.label}</label>${control}\
|
|
321
321
|
${options.hint ? html `<p class="k-hint" id="${options.id}-hint">${options.hint}</p>` : ""}${options.error ? html `<p class="k-err" id="${options.id}-err" role="alert">${options.error}</p>` : ""}</div>`;
|
|
322
322
|
}
|
|
323
|
+
/** The steps of one object as the page itself (a task: Plan · Approval · Build · Checks · Ready): an ordered list, a
|
|
324
|
+
* marker on a rail, the label, one sentence and a time per row, and the row's body under it. The current row is
|
|
325
|
+
* `aria-current="step"`. Same markup as `KStepRows`. */
|
|
326
|
+
export function stepRows(items, label = "Steps") {
|
|
327
|
+
return html `<ol class="k-steprows" aria-label="${label}">${items.map(item => {
|
|
328
|
+
const hasBody = item.body !== undefined && htmlString(html `${item.body}`) !== "";
|
|
329
|
+
const id = stepRowBodyId(item.key);
|
|
330
|
+
const head = html `<span class="k-steprow-label">${item.label}<span class="k-sr">, ${STEP_ROW_WORDS[item.mark]}</span></span>\
|
|
331
|
+
<span class="k-steprow-say">${item.needsYou ? chip("Needs you", "needs") : ""}${item.sentence === "" ? "" : html `<span>${item.sentence}</span>`}</span>\
|
|
332
|
+
${item.at ? html `<time class="k-steprow-time k-num" datetime="${item.at}">${item.when ?? ""}</time>` : ""}`;
|
|
333
|
+
return html `<li class="${cls("k-steprow", item.mark)}" data-step-row="${item.key}"${item.current ? html ` aria-current="step"` : ""}><span class="k-steprow-mark" aria-hidden="true"></span>\
|
|
334
|
+
<div class="k-steprow-main">${item.toggle && hasBody
|
|
335
|
+
? html `<button class="k-steprow-head" type="button" aria-expanded="${item.open ? "true" : "false"}" aria-controls="${id}">${head}</button>`
|
|
336
|
+
: html `<div class="k-steprow-head">${head}</div>`}${hasBody ? html `<div class="k-steprow-body" id="${id}"${item.open ? "" : html ` hidden`}>${item.body}</div>` : ""}</div></li>`;
|
|
337
|
+
})}</ol>`;
|
|
338
|
+
}
|
|
339
|
+
// ---- the work -----------------------------------------------------------------------------------------------------
|
|
340
|
+
/** The work's frame (KIT.md "The work"): a header (the title, who is working with a blue dot while it runs, Close), the
|
|
341
|
+
* body that scrolls, and the message box at the foot. The records themselves are followed live by the workspace
|
|
342
|
+
* (`KWork` and `useConversation`); a page without script shows what `body` holds. Same markup as `KWork`. */
|
|
343
|
+
export function work(options) {
|
|
344
|
+
const who = options.who === undefined || htmlString(html `${options.who}`) === "" ? ""
|
|
345
|
+
: html `<p class="k-work-who">${options.live ? html `<span class="k-work-dot" aria-hidden="true"></span>` : ""}<span>${options.who}</span></p>`;
|
|
346
|
+
const close = options.close === undefined || options.close === null ? "" : btn(options.close, { variant: "ghost", sm: true, iconOnly: "x" });
|
|
347
|
+
const foot = options.foot === undefined || htmlString(html `${options.foot}`) === "" ? "" : html `<div class="k-work-foot">${options.foot}</div>`;
|
|
348
|
+
return html `<aside class="k-work" id="${options.id}" aria-labelledby="${options.id}-h"${options.hidden ? html ` hidden` : ""}${attributes(options.attrs ?? {})}>\
|
|
349
|
+
<header class="k-work-head"><div class="k-work-title"><h2 id="${options.id}-h">${options.title}</h2>${who}</div>${close}</header>\
|
|
350
|
+
<div class="k-work-body" data-agent-scroll="">${options.body ?? ""}</div>${foot}</aside>`;
|
|
351
|
+
}
|
|
323
352
|
/** A short list of steps: a mark, the step and one line, its one action. Done steps read muted with a check; a step
|
|
324
353
|
* being checked shows a static ring (running state never animates). The state is also said in words. */
|
|
325
354
|
export function checklist(steps, label = "Steps") {
|
|
@@ -84,6 +84,8 @@ export type TaskChatFocus = {
|
|
|
84
84
|
origin?: TaskOrigin | null;
|
|
85
85
|
/** The repair chain row when this task is a machine-drafted repair. */
|
|
86
86
|
repairChain: RepairChainRow | null;
|
|
87
|
+
/** A release filed while its pull request's checks still ran: the sheet says nothing deploys until they pass. */
|
|
88
|
+
releaseCiRunning?: boolean;
|
|
87
89
|
} | null;
|
|
88
90
|
decisions: (Decision & {
|
|
89
91
|
taskId: string;
|
|
@@ -93,6 +93,7 @@ export function taskChatApproval(focus, csrf) {
|
|
|
93
93
|
coordinator: approval.coordinator,
|
|
94
94
|
origin: approval.origin ?? null,
|
|
95
95
|
deliverable: approval.deliverable,
|
|
96
|
+
releaseCiRunning: approval.releaseCiRunning === true,
|
|
96
97
|
rebuild: focus.assignment?.need != null && "key" in focus.assignment.need && focus.assignment.need.key === "replan" ? focus.assignment.need.build : null,
|
|
97
98
|
// Edit plan opens the task page's sheet with its fields open for editing.
|
|
98
99
|
editHref: `${taskHref(focus.id)}?edit=plan#plan-editor`,
|
|
@@ -129,7 +129,7 @@ export function boardBody(data, ciRed) {
|
|
|
129
129
|
return `${Math.round(minutes / 60)}h`;
|
|
130
130
|
return `${Math.round(minutes / (24 * 60))}d`;
|
|
131
131
|
};
|
|
132
|
-
// A lane's head is a status chip in its own tone (after ReUI's badge with a dot):
|
|
132
|
+
// A lane's head is a status chip in its own tone (after ReUI's badge with a dot): solid ink only for the lane that
|
|
133
133
|
// waits on a person, blue for building, green for done, neutral otherwise. The word carries the state.
|
|
134
134
|
const LANE_CHIP = { attention: "chip-needs", building: "chip-live", done: "chip-done", queued: "", waiting: "" };
|
|
135
135
|
const laneChip = (key, title) => html `<span class="chip ${LANE_CHIP[key]}"><span class="chip-dot" aria-hidden="true"></span>${title}</span>`;
|
|
@@ -70,7 +70,7 @@ export function editorFileHref(worktree, path, line) {
|
|
|
70
70
|
* chat (v39, extending Priority 2's "one surface, six places" rule from
|
|
71
71
|
* the verdict word to the per-criterion state). */
|
|
72
72
|
export function matrixStateBadge(state) {
|
|
73
|
-
// Red belongs to a Failed headline alone (task-status.ts); an unmet requirement is an
|
|
73
|
+
// Red belongs to a Failed headline alone (task-status.ts); an unmet requirement is an ink note.
|
|
74
74
|
const cls = state === "pass" ? "badge-done" : state === "failed" ? "badge-note" : state === "missing" ? "badge-note" : "badge-manual-review";
|
|
75
75
|
// The same words as the Checks tab and the card's Requirements row (task-status.ts).
|
|
76
76
|
return html `<span class="badge ${cls}" data-matrix-state="${state}">${requirementWordOf({ state })}</span>`;
|
|
@@ -828,7 +828,7 @@ export function pullRequestCardHtml(pr, csrf) {
|
|
|
828
828
|
const view = pr.view;
|
|
829
829
|
const url = safePrUrl(view.prUrl);
|
|
830
830
|
const link = view.prNumber === null ? "" : url === null ? html `<span class="mono">PR #${view.prNumber}</span>` : html `<a href="${url}" class="mono" rel="noreferrer" target="_blank">PR #${view.prNumber}</a>`;
|
|
831
|
-
// A pull request's trouble never undoes the result:
|
|
831
|
+
// A pull request's trouble never undoes the result: an ink note, never red.
|
|
832
832
|
const tone = view.state === "ready" || view.state === "merged" ? "ok" : view.state === "failing" || view.state === "failed" ? "problem" : "waiting";
|
|
833
833
|
const revision = view.revisionTask === null || view.state !== "failing" ? "" : html ` <a href="${taskHref(view.revisionTask)}">Open revision</a>`;
|
|
834
834
|
const merged = view.mergeCommit === null ? "" : html `<p class="meta">Merge commit <span class="mono">${view.mergeCommit.slice(0, 12)}</span></p>`;
|
|
@@ -1507,7 +1507,7 @@ export function completionReceiptCard(view, taskId, place, standing = receiptSta
|
|
|
1507
1507
|
lead,
|
|
1508
1508
|
html `<p class="receipt-summary">${conciseOutcomeOf(view.summary ?? (view.outcome === "no-change" ? "The agent found that no repository change was needed." : "The build finished without a concise handoff."))}</p>`,
|
|
1509
1509
|
headline ? html `<div class="receipt-actions"><a class="button-link" href="${resultHref}" data-open-result data-primary-action>${status.action?.label ?? "Open result"}</a></div>` : "",
|
|
1510
|
-
// A pull request that couldn't open never undoes the result: an
|
|
1510
|
+
// A pull request that couldn't open never undoes the result: an ink note, not red.
|
|
1511
1511
|
view.publication?.state === "failed" ? html `<p class="receipt-note">${statusIconSvg("note")} Pull request couldn't open. The commit is safe locally.</p>` : "",
|
|
1512
1512
|
caveats,
|
|
1513
1513
|
coverage,
|
|
@@ -122,6 +122,8 @@ export type ApprovalSheetInput = {
|
|
|
122
122
|
freshSince?: string | null;
|
|
123
123
|
/** Easy-start C5: a laptop's local owner — eligible (no password field), or why not and where to go. */
|
|
124
124
|
localOwner?: LocalApprovalView | null;
|
|
125
|
+
/** A release filed while its pull request's checks still ran: the plan sheet says nothing deploys until they pass. */
|
|
126
|
+
releaseCiRunning?: boolean;
|
|
125
127
|
};
|
|
126
128
|
export type LocalApprovalView = {
|
|
127
129
|
eligible: true;
|
|
@@ -147,7 +149,15 @@ export declare function approvalSheetParts(input: ApprovalSheetInput): {
|
|
|
147
149
|
after: Html;
|
|
148
150
|
allowing: string[];
|
|
149
151
|
passwordNote: string;
|
|
152
|
+
/** The same terms as `lead`, `rows` and `details`, re-ordered to read top to bottom (`planSheetHtml`), nothing folded. */
|
|
153
|
+
sheet: Html;
|
|
154
|
+
/** The sheet's lead sentence (the approach's first sentence, else the goal), for a one-line summary of the plan. */
|
|
155
|
+
sheetLead: string;
|
|
150
156
|
};
|
|
157
|
+
/** The plan sheet: what an approval signs, read top to bottom (approvalSheetParts' own parts, re-ordered). */
|
|
158
|
+
export declare function planSheetHtml(input: ApprovalSheetInput): Html;
|
|
159
|
+
/** Evidence kinds on the plan sheet: how each requirement is proven, in plain words. */
|
|
160
|
+
export declare const EVIDENCE_SHEET: Record<string, string>;
|
|
151
161
|
/** Earlier versions of a task still in flight, in plain words: queued
|
|
152
162
|
* while they only wait, running once one has started; null when none. */
|
|
153
163
|
export declare function earlierVersionsWords(active: number, running: number): string | null;
|