toolroll 0.9.86 → 0.9.88
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 +86 -0
- package/dist/acp-check.d.ts +9 -0
- package/dist/acp-check.js +40 -28
- package/dist/agents-board.d.ts +12 -0
- package/dist/agents-board.js +26 -0
- package/dist/approval-rules-ui.d.ts +4 -1
- package/dist/approval-rules-ui.js +31 -15
- package/dist/assignment-ui.js +1 -1
- package/dist/backup-ui.d.ts +5 -4
- package/dist/backup-ui.js +65 -32
- package/dist/browser/terminal.css +1 -1
- package/dist/browser/terminal.js +57 -54
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +35 -70
- package/dist/browser-crew.js +1 -1
- package/dist/browser-workspace.d.ts +329 -183
- package/dist/browser-workspace.js +10 -9
- package/dist/chat-controls.d.ts +1 -1
- package/dist/chat-controls.js +1 -1
- package/dist/chat-settings-page.d.ts +29 -9
- package/dist/chat-settings-page.js +59 -28
- package/dist/check-levels-ui.d.ts +2 -1
- package/dist/check-levels-ui.js +67 -58
- package/dist/contracts/cli.d.ts +43 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +1 -1
- package/dist/contracts/console-api.js +1 -1
- package/dist/credentials-ui.d.ts +5 -3
- package/dist/credentials-ui.js +58 -31
- package/dist/design/kit.css +722 -0
- package/dist/design/kit.d.ts +208 -0
- package/dist/design/kit.js +177 -0
- package/dist/design/tokens.css +31 -1
- package/dist/discord-settings.js +8 -4
- package/dist/export-ui.d.ts +6 -4
- package/dist/export-ui.js +18 -8
- package/dist/flow-changed.d.ts +14 -0
- package/dist/flow-changed.js +53 -0
- package/dist/flow-gallery-ui.d.ts +41 -4
- package/dist/flow-gallery-ui.js +95 -63
- package/dist/flow-starters-ui.d.ts +3 -9
- package/dist/flow-starters-ui.js +12 -23
- package/dist/flow-unattended-words.d.ts +20 -0
- package/dist/flow-unattended-words.js +24 -0
- package/dist/flow-unattended.d.ts +9 -5
- package/dist/flow-unattended.js +45 -23
- package/dist/flows-cli.js +7 -3
- package/dist/flows-ui.d.ts +12 -6
- package/dist/flows-ui.js +141 -30
- package/dist/integrations-ui.d.ts +6 -4
- package/dist/integrations-ui.js +34 -40
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.js +4 -4
- package/dist/kits-ui.d.ts +8 -10
- package/dist/kits-ui.js +29 -33
- package/dist/kits.js +1 -1
- package/dist/knowledge-ui.js +76 -19
- package/dist/ledger-view.d.ts +2 -0
- package/dist/ledger-view.js +41 -38
- package/dist/models-ui.d.ts +8 -3
- package/dist/models-ui.js +82 -59
- package/dist/monitoring-ui.d.ts +4 -2
- package/dist/monitoring-ui.js +44 -13
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +8 -0
- package/dist/operate-remote-arguments.js +1 -0
- package/dist/operate-remote.js +1 -1
- package/dist/operate.d.ts +1 -1
- package/dist/operate.js +38 -4
- package/dist/passwordless.d.ts +1 -1
- package/dist/passwordless.js +1 -1
- package/dist/people-audit-ui.d.ts +2 -1
- package/dist/people-audit-ui.js +25 -23
- package/dist/policy-ui.d.ts +3 -2
- package/dist/policy-ui.js +27 -21
- package/dist/policy.d.ts +3 -0
- package/dist/policy.js +14 -1
- package/dist/project-delete-ui.d.ts +4 -2
- package/dist/project-delete-ui.js +135 -126
- package/dist/project-knowledge.d.ts +10 -10
- package/dist/publish.d.ts +11 -0
- package/dist/publish.js +16 -3
- package/dist/pull-request-ui.d.ts +2 -1
- package/dist/pull-request-ui.js +39 -28
- package/dist/recipe-ui.d.ts +4 -2
- package/dist/recipe-ui.js +14 -4
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +22 -2
- package/dist/release-cli.js +81 -9
- package/dist/release.d.ts +23 -0
- package/dist/release.js +46 -4
- package/dist/releases.js +1 -1
- package/dist/request-budget-ui.d.ts +4 -2
- package/dist/request-budget-ui.js +30 -19
- package/dist/retention-ui.d.ts +4 -3
- package/dist/retention-ui.js +15 -12
- package/dist/scope.d.ts +3 -0
- package/dist/scope.js +6 -0
- package/dist/serve.d.ts +0 -1
- package/dist/serve.js +51 -7
- package/dist/server/agents-computers.d.ts +9 -0
- package/dist/server/agents-computers.js +67 -0
- package/dist/server/chat.js +16 -16
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +19 -9
- package/dist/server/console.css +24 -12
- package/dist/server/flows.js +64 -36
- package/dist/server/home.d.ts +35 -0
- package/dist/server/home.js +104 -0
- package/dist/server/http.d.ts +3 -0
- package/dist/server/http.js +5 -0
- package/dist/server/kit-standalone.d.ts +22 -0
- package/dist/server/kit-standalone.js +70 -0
- package/dist/server/kit.d.ts +419 -0
- package/dist/server/kit.js +369 -0
- package/dist/server/pages.d.ts +2 -1
- package/dist/server/pages.js +213 -174
- package/dist/server/people-tokens.js +26 -85
- package/dist/server/render-history.d.ts +51 -0
- package/dist/server/render-history.js +228 -0
- package/dist/server/render-new-task.d.ts +29 -0
- package/dist/server/render-new-task.js +96 -0
- package/dist/server/render-next.d.ts +63 -0
- package/dist/server/render-next.js +109 -0
- package/dist/server/render-pages.d.ts +22 -190
- package/dist/server/render-pages.js +123 -575
- package/dist/server/render-people.d.ts +24 -3
- package/dist/server/render-people.js +93 -72
- package/dist/server/render-projects.d.ts +103 -0
- package/dist/server/render-projects.js +247 -0
- package/dist/server/render-results.d.ts +5 -24
- package/dist/server/render-results.js +48 -185
- package/dist/server/render-settings.d.ts +5 -74
- package/dist/server/render-settings.js +102 -493
- package/dist/server/render-tasks.d.ts +35 -5
- package/dist/server/render-tasks.js +114 -85
- package/dist/server/route-table.js +20 -5
- package/dist/server/settings.js +276 -255
- package/dist/server/task-views.d.ts +8 -0
- package/dist/server/task-views.js +85 -2
- package/dist/server/tasks.d.ts +8 -0
- package/dist/server/tasks.js +95 -40
- package/dist/server/terminals.js +1 -1
- package/dist/server/welcome.d.ts +22 -0
- package/dist/server/welcome.js +69 -0
- package/dist/settings-groups-ui.d.ts +279 -0
- package/dist/settings-groups-ui.js +615 -0
- package/dist/settings-kit.d.ts +42 -6
- package/dist/settings-kit.js +69 -7
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills-ui.js +59 -7
- package/dist/slack-settings.js +12 -5
- package/dist/spend-ui.d.ts +45 -26
- package/dist/spend-ui.js +124 -56
- package/dist/sso-ui.d.ts +5 -2
- package/dist/sso-ui.js +63 -31
- package/dist/storage-ui.d.ts +3 -2
- package/dist/storage-ui.js +56 -50
- package/dist/store.d.ts +112 -3
- package/dist/store.js +292 -20
- package/dist/surface.js +5 -1
- package/dist/teams-settings.d.ts +2 -1
- package/dist/teams-settings.js +24 -41
- package/dist/telegram-settings.d.ts +0 -4
- package/dist/telegram-settings.js +52 -25
- package/dist/toolroll-update-ui.d.ts +8 -4
- package/dist/toolroll-update-ui.js +55 -45
- package/dist/tools-ui.d.ts +5 -3
- package/dist/tools-ui.js +107 -42
- package/dist/work-index.js +11 -7
- package/dist/workspace-ui.d.ts +1 -1
- package/dist/workspace-ui.js +7 -4
- package/package.json +1 -1
package/dist/storage-ui.js
CHANGED
|
@@ -1,42 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Settings → Storage: how much space task checkouts use, what a clean-up would free now,
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* one-time command for older work), and when a finished task's clean checkout goes by itself. An
|
|
2
|
+
* Settings → Storage: how much space task checkouts use, what a clean-up would free now, the clean-up's preview (what
|
|
3
|
+
* goes, what stays and why, with paths) and its Remove behind the password, what the last storage sweep removed and
|
|
4
|
+
* when (its paths in a disclosure) and why the next one waits, what landed work's teardown did and still waits on (in a
|
|
5
|
+
* disclosure, with the one-time command for older work), and when a finished task's clean checkout goes by itself. An
|
|
6
|
+
* instance operator's page, built from the revamp kit; the Settings frame adds the title.
|
|
6
7
|
*/
|
|
7
8
|
import { homedir } from "node:os";
|
|
8
9
|
import { basename } from "node:path";
|
|
9
|
-
import { html,
|
|
10
|
+
import { html, joinHtml } from "./html.js";
|
|
10
11
|
import { previewDigest, whyWords } from "./checkout-cleanup.js";
|
|
11
12
|
import { CLEANUP_CHOICES, bytesWords } from "./storage.js";
|
|
12
13
|
import { sweepDetails, sweepWords } from "./storage-sweep.js";
|
|
13
14
|
import { sweepScheduleWords } from "./storage-sweep-schedule.js";
|
|
15
|
+
import { codeLine, disclose, formRow, icon, infoLine, note, notice, select, settingsRecord, settingsSection } from "./server/kit.js";
|
|
16
|
+
import { kitSectionForm } from "./settings-kit.js";
|
|
14
17
|
const plural = (count, one, many = `${one}s`) => `${count} ${count === 1 ? one : many}`;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`.storage ul.checkouts li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 12px;padding:8px 0;border-top:1px solid var(--border);font-size:.8125rem}` +
|
|
24
|
-
`.storage ul.checkouts .name{font-weight:500;min-width:0}.storage ul.checkouts .size{font-variant-numeric:tabular-nums;white-space:nowrap}` +
|
|
25
|
-
`.storage ul.checkouts .path{grid-column:1/-1;font-family:var(--font-mono, ui-monospace, monospace);font-size:.6875rem;color:var(--muted-foreground);word-break:break-all}` +
|
|
26
|
-
`.storage ul.checkouts .why{grid-column:1/-1}` +
|
|
27
|
-
`.storage details.discard{grid-column:1/-1}.storage details.discard>summary{cursor:pointer;color:var(--destructive);min-height:2.25rem;display:inline-flex;align-items:center}` +
|
|
28
|
-
`.storage form{display:grid;gap:10px;margin:0}.storage label{display:grid;gap:4px;font-size:.8125rem;font-weight:500;max-width:20rem}` +
|
|
29
|
-
`.storage select,.storage input[type=password]{width:100%;box-sizing:border-box;min-height:2.125rem}.storage form button{justify-self:start;white-space:nowrap}` +
|
|
30
|
-
`.storage form.setting button[type=submit],.storage .preview form.remove button[type=submit]{background:var(--primary);color:var(--primary-foreground);border-color:var(--primary);font-weight:600}` +
|
|
31
|
-
`.storage .sweep{display:grid;gap:4px}.storage .sweep p{margin:0}.storage .sweep .problem{color:var(--destructive)}` +
|
|
32
|
-
`.storage details.sweep-details>summary{cursor:pointer;min-height:2.25rem;display:inline-flex;align-items:center;font-size:.8125rem;color:var(--muted-foreground)}` +
|
|
33
|
-
`.storage details.landed>summary{cursor:pointer;min-height:2.25rem;display:inline-flex;align-items:center;font-size:.8125rem;color:var(--muted-foreground)}` +
|
|
34
|
-
`.storage details.landed .landed-body{display:grid;gap:6px;margin-top:4px;font-size:.8125rem}.storage details.landed p{margin:0}` +
|
|
35
|
-
`.storage details.landed ul{margin:0;padding-left:18px;overflow-wrap:anywhere}.storage details.landed .target{font-family:var(--font-mono, ui-monospace, monospace);font-size:.6875rem}` +
|
|
36
|
-
`.storage details.landed code{font-family:var(--font-mono, ui-monospace, monospace);font-size:.75rem;overflow-wrap:anywhere}` +
|
|
37
|
-
`.storage details.sweep-details ul{margin:4px 0 0;padding-left:18px;font-family:var(--font-mono, ui-monospace, monospace);font-size:.6875rem;color:var(--muted-foreground);overflow-wrap:anywhere}` +
|
|
38
|
-
`@media (max-width:900px){.storage details.sweep-details>summary,.storage details.landed>summary{min-height:44px}.storage details.clean-up>summary,.storage form button{min-height:44px}.storage label{max-width:none}.storage select,.storage input[type=password]{min-height:44px;font-size:16px}.storage .preview form.remove button{width:100%}}`;
|
|
39
|
-
/** Paths under the home folder as ~/…, as the checkout list shows them. */
|
|
18
|
+
/** The page is kit pieces now; nothing of the old look is left. Kept as an export for the shared stylesheet. */
|
|
19
|
+
export const STORAGE_CSS = "";
|
|
20
|
+
/** A path under the home folder as ~/…. */
|
|
21
|
+
function tilde(path) {
|
|
22
|
+
const home = homedir();
|
|
23
|
+
return home !== "" && home !== "/" && path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;
|
|
24
|
+
}
|
|
25
|
+
/** Paths under the home folder as ~/… anywhere in a line, as the checkout list shows them. */
|
|
40
26
|
function homeAsTilde(line) {
|
|
41
27
|
const home = homedir();
|
|
42
28
|
return home === "" || home === "/" ? line : line.split(`${home}/`).join("~/");
|
|
@@ -49,41 +35,61 @@ function whenWords(at) {
|
|
|
49
35
|
/** When the last sweep ran and what it did, then why the next one waits or when it is due; paths and problems behind Details. */
|
|
50
36
|
function sweepHtml(sweep) {
|
|
51
37
|
const last = sweep.last;
|
|
52
|
-
const schedule = sweep.schedule === undefined ? (sweep.off ? html `<p class="
|
|
53
|
-
: html `<p class="
|
|
38
|
+
const schedule = sweep.schedule === undefined ? (sweep.off ? html `<p class="k-note" data-sweep-state="off">Automatic sweep: off.</p>` : "")
|
|
39
|
+
: html `<p class="k-note" data-sweep-state="${sweep.schedule.state}">Automatic sweep: ${sweepScheduleWords(sweep.schedule, whenWords)}</p>`;
|
|
54
40
|
if (last === null)
|
|
55
|
-
return html `<div
|
|
41
|
+
return html `<div data-last-sweep="">${note("Not swept yet.")}${schedule}</div>`;
|
|
56
42
|
const who = last.source === "manual" ? `Cleaned up by ${last.actor}` : "Swept";
|
|
57
43
|
const details = sweepDetails(last.parts);
|
|
58
44
|
const problem = last.parts.some(one => one.failed > 0 || one.problem !== undefined);
|
|
59
|
-
|
|
45
|
+
const said = html `${who} <time datetime="${last.at}">${whenWords(last.at)}</time>. ${sweepWords(last.parts)}`;
|
|
46
|
+
return html `<div data-last-sweep="${last.at}">${problem ? html `<p class="k-notice" role="alert">${icon("alert", true)}<span>${said}</span></p>` : note(said)}${schedule}${details.length === 0 ? "" : disclose("Details", joinHtml(details.map(line => codeLine(homeAsTilde(line)))))}</div>`;
|
|
60
47
|
}
|
|
61
48
|
/** Landed work, on demand: what its teardown did, what it waits on and why, and the one-time command for older work. */
|
|
62
49
|
function landedHtml(landed) {
|
|
63
|
-
const home = homedir();
|
|
64
50
|
const done = landed.completed + landed.checkouts + landed.branches === 0 ? "No landed work cleaned up yet."
|
|
65
51
|
: `${plural(landed.completed, "task")} marked complete; ${plural(landed.checkouts, "checkout")} and ${plural(landed.branches, "local branch", "local branches")} removed.`;
|
|
66
|
-
const waiting = landed.waiting.length === 0 ? "" : html `<
|
|
67
|
-
return html `<
|
|
52
|
+
const waiting = landed.waiting.length === 0 ? "" : html `<div data-landed-waiting>${note(`Waiting (${landed.waiting.length}):`)}${landed.waiting.map(one => settingsRecord({ title: html `<span class="k-mono">${tilde(one.target)}</span>`, sub: one.why ?? "" }))}</div>`;
|
|
53
|
+
return html `<div data-landed>${disclose("Landed work", joinHtml([note(done), waiting,
|
|
54
|
+
note(html `For work that landed before this: <code class="k-mono">toolroll storage clean --landed</code> shows what would go; add <code class="k-mono">--yes</code> to do it.`)]))}</div>`;
|
|
68
55
|
}
|
|
56
|
+
/** One checkout: the task it was for, its size, where it is (the home folder as ~), why it stays, and Discard when it has changes. */
|
|
69
57
|
function item(one) {
|
|
58
|
+
const why = one.why === null ? "" : `${whyWords(one)[0].toUpperCase()}${whyWords(one).slice(1)}`;
|
|
70
59
|
const discard = one.why === "has changes"
|
|
71
|
-
?
|
|
60
|
+
? disclose("Discard", kitSectionForm({ proof: "storage-discard", action: "/settings/storage/discard", id: `discard-${previewId(one.path)}`, hidden: { path: one.path },
|
|
61
|
+
save: { label: "Discard changes", variant: "danger" }, body: note("Throws away this checkout and its uncommitted changes. Its branch stays.") }))
|
|
72
62
|
: "";
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const where = home !== "" && one.path.startsWith(`${home}/`) ? `~${one.path.slice(home.length)}` : one.path;
|
|
76
|
-
return html `<li data-checkout="${one.path}"><span class="name">${one.taskId ?? basename(one.path)}</span><span class="size">${bytesWords(one.bytes)}</span><span class="path">${where}</span>${one.why === null ? "" : html `<span class="why">${whyWords(one)[0].toUpperCase() + whyWords(one).slice(1)}</span>`}${discard}</li>`;
|
|
63
|
+
return settingsRecord({ title: one.taskId ?? basename(one.path), attrs: { "data-checkout": one.path }, when: bytesWords(one.bytes),
|
|
64
|
+
sub: html `<span class="k-mono">${tilde(one.path)}</span>${why === "" ? "" : ` · ${why}`}`, more: discard });
|
|
77
65
|
}
|
|
78
|
-
|
|
66
|
+
/** A short id for a checkout's form, from its path. */
|
|
67
|
+
const previewId = (path) => path.replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "").slice(-48) || "checkout";
|
|
68
|
+
export function storageHtml(view, said) {
|
|
79
69
|
const { plan } = view;
|
|
80
|
-
const note = notice.problem ? html `<p class="problem" role="alert">${notice.problem}</p>` : notice.said ? html `<p role="status">${notice.said}</p>` : "";
|
|
81
70
|
const facts = [plural(plan.count, "checkout"), `${plan.waitingReview} waiting for review`, `${plan.withChanges} kept for their changes`].join(" · ");
|
|
82
71
|
const frees = plan.go.length === 0 ? "Nothing to clean up now." : `Cleaning up now frees about ${bytesWords(plan.freeBytes)}.`;
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
const checkouts = settingsSection({ id: "checkouts", title: `Checkouts use ${bytesWords(plan.totalBytes)}`,
|
|
73
|
+
body: joinHtml([
|
|
74
|
+
said.problem ? notice(said.problem) : said.said ? infoLine(said.said) : "",
|
|
75
|
+
html `<p class="k-note" data-checkout-bytes="${plan.totalBytes}">${facts}</p>`,
|
|
76
|
+
view.measured ?? "",
|
|
77
|
+
html `<p class="k-note" data-clean-bytes="${plan.freeBytes}">${frees}</p>`,
|
|
78
|
+
view.sweep === undefined ? "" : sweepHtml(view.sweep),
|
|
79
|
+
view.landed === undefined ? "" : landedHtml(view.landed),
|
|
80
|
+
]) });
|
|
81
|
+
const remove = plan.go.length === 0 ? "" : kitSectionForm({ proof: "storage-clean", action: "/settings/storage/clean", id: "clean-form", hidden: { preview: previewDigest(plan) },
|
|
82
|
+
save: { label: `Remove ${plural(plan.go.length, "checkout")}`, variant: "danger" }, body: html `` });
|
|
83
|
+
const goes = plan.go.length === 0 ? note("Nothing to remove now.")
|
|
84
|
+
: html `<div data-goes>${plan.go.map(one => item(one))}</div>`;
|
|
85
|
+
const stays = plan.stay.length === 0 ? "" : disclose(`Stays (${plan.stay.length})`, html `<div data-stays>${plan.stay.map(one => item(one))}</div>`);
|
|
86
|
+
const cleanUp = settingsSection({ id: "clean-up", title: "Clean up now",
|
|
87
|
+
lead: plan.go.length === 0 ? "Nothing to remove now." : `Removes ${plural(plan.go.length, "checkout")}, about ${bytesWords(plan.freeBytes)}. Their branches stay, so nothing committed is lost.`,
|
|
88
|
+
body: html `<div data-clean-up>${joinHtml([plan.go.length === 0 ? "" : goes, remove, stays])}</div>` });
|
|
89
|
+
const automatic = settingsSection({ id: "automatic-cleanup", title: "Automatic cleanup",
|
|
90
|
+
lead: "Its branch stays. Checkouts with changes, commits on no branch, in use, or waiting for review are kept. When a task's work is already in main, Toolroll marks it complete and removes its checkout and local branches.",
|
|
91
|
+
body: kitSectionForm({ proof: "storage-cleanup", action: "/settings/storage", id: "cleanup-form", gate: true,
|
|
92
|
+
body: formRow("Remove a finished task's clean checkout", null, select({ id: "storage-cleanup", name: "cleanup", label: "Remove a finished task's clean checkout", current: plan.cleanup,
|
|
93
|
+
items: CLEANUP_CHOICES.map(one => [one.value, one.label]) }), "inline") }) });
|
|
94
|
+
return joinHtml([checkouts, cleanUp, automatic]);
|
|
89
95
|
}
|
package/dist/store.d.ts
CHANGED
|
@@ -233,7 +233,7 @@ export type SealedLedgerEntry = LedgerEntry & {
|
|
|
233
233
|
hash: string;
|
|
234
234
|
} | null;
|
|
235
235
|
};
|
|
236
|
-
export declare const SCHEMA_VERSION =
|
|
236
|
+
export declare const SCHEMA_VERSION = 146;
|
|
237
237
|
/** v118: the tables merged into `credential`, in the order they move (a person's API tokens keep their ids first). */
|
|
238
238
|
export declare const V118_MERGED_TABLES: Readonly<Record<string, CredentialKind>>;
|
|
239
239
|
/**
|
|
@@ -405,6 +405,12 @@ export declare const V143_ADDED_COLUMNS: Readonly<Record<string, Readonly<Record
|
|
|
405
405
|
* the watched branch of the watched repository) the "checks failed" trigger saw, green or red, so tidy can tell a
|
|
406
406
|
* failure notice was fixed by a later commit. */
|
|
407
407
|
export declare const V145_SCHEMA = "\nCREATE TABLE IF NOT EXISTS task_archive (\n task_ref INTEGER PRIMARY KEY REFERENCES task_ref(id),\n by TEXT NOT NULL,\n by_kind TEXT NOT NULL CHECK (by_kind IN ('person','tidy')),\n rule TEXT,\n reason TEXT NOT NULL,\n at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS branch_check_run (\n repo TEXT NOT NULL,\n run_id INTEGER NOT NULL,\n branch TEXT NOT NULL,\n workflow TEXT NOT NULL,\n head_sha TEXT NOT NULL,\n conclusion TEXT NOT NULL CHECK (conclusion IN ('success','failure')),\n run_created_at TEXT NOT NULL,\n observed_at TEXT NOT NULL,\n PRIMARY KEY (repo, run_id)\n);\nCREATE INDEX IF NOT EXISTS branch_check_run_by_workflow ON branch_check_run (repo, branch, workflow, run_created_at);\nCREATE TABLE IF NOT EXISTS merge_in_flight (\n publication INTEGER PRIMARY KEY REFERENCES publication(id),\n task_ref INTEGER NOT NULL REFERENCES task_ref(id),\n token TEXT NOT NULL,\n by TEXT NOT NULL,\n at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS deploy_in_flight (\n task_ref INTEGER PRIMARY KEY REFERENCES task_ref(id),\n run INTEGER NOT NULL,\n at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS flow_step_task (\n card INTEGER NOT NULL,\n entry INTEGER NOT NULL,\n task_id TEXT NOT NULL,\n PRIMARY KEY (card, entry, task_id)\n);\n";
|
|
408
|
+
/** v146: `ci_check` is one pull request check (a GitHub check run or commit status) as the plane's winning observation of
|
|
409
|
+
* that head read it: written only with the observation that won its generation, replacing that head's rows wholesale.
|
|
410
|
+
* `release_step` is one step of a release (release.ts RELEASE_STEPS) as `toolroll release` moved through it: when it
|
|
411
|
+
* started, when it ended and how; recording it never changes the release. Both are read-only history for the Ship and
|
|
412
|
+
* Release views and their CLI twins. */
|
|
413
|
+
export declare const V146_SCHEMA = "\nCREATE TABLE IF NOT EXISTS ci_check (\n github_repo TEXT NOT NULL,\n pr_number INTEGER NOT NULL,\n head_sha TEXT NOT NULL,\n -- A check's identity: its kind (check run or commit status), its workflow and its name, so two workflows' checks\n -- with the same name stay two rows (a failing one never hides behind a passing namesake).\n ident TEXT NOT NULL,\n name TEXT NOT NULL,\n workflow TEXT,\n state TEXT NOT NULL CHECK (state IN ('queued','running','passed','failed','skipped','cancelled','neutral')),\n started_at TEXT,\n completed_at TEXT,\n url TEXT,\n observed_at TEXT NOT NULL,\n PRIMARY KEY (github_repo, pr_number, head_sha, ident)\n);\nCREATE TABLE IF NOT EXISTS release_step (\n task_id TEXT NOT NULL,\n tag TEXT NOT NULL,\n version TEXT NOT NULL,\n pr INTEGER,\n step TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('running','done','failed','waiting')),\n started_at TEXT NOT NULL,\n ended_at TEXT,\n detail TEXT,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (task_id, tag, step)\n);\nCREATE INDEX IF NOT EXISTS release_step_by_task ON release_step (task_id, updated_at);\n";
|
|
408
414
|
/**
|
|
409
415
|
* v135: one approval per release (docs/plans/release-once.md). `release_authority` is the single source of truth for a
|
|
410
416
|
* release a person approved: one row per generation, changed only by compare-and-swap on `rev`, with a lease whose
|
|
@@ -6083,8 +6089,13 @@ export declare class Store {
|
|
|
6083
6089
|
file?: string | null;
|
|
6084
6090
|
held?: string | null;
|
|
6085
6091
|
}, now: Date): number;
|
|
6086
|
-
/** A person approves a held script (one an imported flow brought): from now on it runs.
|
|
6087
|
-
|
|
6092
|
+
/** A person approves a held script (one an imported flow brought): from now on it runs. The approval covers exactly
|
|
6093
|
+
* the version and content the person read (`seen`): the check and the release of the hold are one statement in one
|
|
6094
|
+
* transaction, so a script removed and brought back under the same name is never approved unseen. */
|
|
6095
|
+
approveFlowScript(repo: string, name: string, seen: {
|
|
6096
|
+
version: number;
|
|
6097
|
+
digest: string;
|
|
6098
|
+
}): "approved" | "changed" | "not-held";
|
|
6088
6099
|
removeFlowScript(repo: string, name: string, by?: string, now?: Date): boolean;
|
|
6089
6100
|
/** Claim a card's visit to a step zone. False when another pass holds it or it already finished. */
|
|
6090
6101
|
claimFlowStep(step: {
|
|
@@ -8132,3 +8143,101 @@ export declare function restoreTaskFamily(store: Store, taskId: string, by: stri
|
|
|
8132
8143
|
reason: ArchiveRefusal;
|
|
8133
8144
|
message: string;
|
|
8134
8145
|
};
|
|
8146
|
+
/**
|
|
8147
|
+
* What a LIVE invite grants, for its own join page (Wave E, "Your access"): the role, who invited, the projects and
|
|
8148
|
+
* when it expires. Read without spending an attempt and under exactly inviteIsLive's predicate, so every dead shape
|
|
8149
|
+
* reads as null and still gets the one indistinguishable page (D6). Only a holder of the live token sees it.
|
|
8150
|
+
*/
|
|
8151
|
+
export declare function liveInviteTerms(store: Store, tokenValue: string, now: Date): {
|
|
8152
|
+
role: "approver" | "viewer";
|
|
8153
|
+
mintedBy: string;
|
|
8154
|
+
expiresAt: string;
|
|
8155
|
+
projects: ProjectAccess;
|
|
8156
|
+
} | null;
|
|
8157
|
+
/** One pull request check as GitHub last reported it for the observed head (v146 ci_check). */
|
|
8158
|
+
/** `kind`: a check run or a commit status (part of the check's identity); a row built without it reads as a run when it
|
|
8159
|
+
* names a workflow, else as a status. */
|
|
8160
|
+
export type CiCheckRow = {
|
|
8161
|
+
name: string;
|
|
8162
|
+
workflow: string | null;
|
|
8163
|
+
state: "queued" | "running" | "passed" | "failed" | "skipped" | "cancelled" | "neutral";
|
|
8164
|
+
startedAt: string | null;
|
|
8165
|
+
completedAt: string | null;
|
|
8166
|
+
url: string | null;
|
|
8167
|
+
kind?: "run" | "status";
|
|
8168
|
+
};
|
|
8169
|
+
/** `observed`: the authoritative state of the same winning observation (ci_observation), which the overall status
|
|
8170
|
+
* always comes from; the rows only show each check's own timing. */
|
|
8171
|
+
export type ShipChecks = {
|
|
8172
|
+
githubRepo: string;
|
|
8173
|
+
prNumber: number;
|
|
8174
|
+
headSha: string;
|
|
8175
|
+
observedAt: string;
|
|
8176
|
+
observed: "passing" | "failing" | "running" | "none";
|
|
8177
|
+
checks: CiCheckRow[];
|
|
8178
|
+
};
|
|
8179
|
+
/** At most this many checks are kept for one head; GitHub's rollup is far smaller in practice. */
|
|
8180
|
+
export declare const CI_CHECKS_MAX = 200;
|
|
8181
|
+
/**
|
|
8182
|
+
* GitHub's statusCheckRollup (gh pr view --json statusCheckRollup) as check rows: CheckRun items (name, workflowName,
|
|
8183
|
+
* status, conclusion, startedAt, completedAt, detailsUrl) and StatusContext items (context, state, startedAt, targetUrl).
|
|
8184
|
+
* Strict: an item that is not one of those shapes, has no usable name, or names a state it doesn't know is dropped; one
|
|
8185
|
+
* row per identity (kind, workflow and name), and when one identity appears twice (a re-run) the worse state stands;
|
|
8186
|
+
* at most CI_CHECKS_MAX.
|
|
8187
|
+
*/
|
|
8188
|
+
export declare function parseCiRollup(rollup: unknown): CiCheckRow[];
|
|
8189
|
+
/**
|
|
8190
|
+
* Replace one head's checks wholesale (v146). Call ONLY with an observation that won its generation (publish.ts settles
|
|
8191
|
+
* and records in one transaction): a losing, stale answer never writes here.
|
|
8192
|
+
*/
|
|
8193
|
+
export declare function recordCiChecks(store: Store, githubRepo: string, prNumber: number, headSha: string, rows: readonly CiCheckRow[], now: Date): void;
|
|
8194
|
+
/** A pull request's checks for the head the plane's last winning observation recorded, or null when none was. */
|
|
8195
|
+
export declare function ciChecksFor(store: Store, githubRepo: string, prNumber: number): ShipChecks | null;
|
|
8196
|
+
/** A task's pull request checks: its family's newest publication that has a pull request number, and that pull
|
|
8197
|
+
* request's checks (ciChecksFor). Null: no pull request, or none observed yet. */
|
|
8198
|
+
export declare function shipChecksForTask(store: Store, taskId: string): ShipChecks | null;
|
|
8199
|
+
/** One release step as `toolroll release` moved through it (v146 release_step). */
|
|
8200
|
+
export type ReleaseStepRow = {
|
|
8201
|
+
step: string;
|
|
8202
|
+
state: "running" | "done" | "failed" | "waiting";
|
|
8203
|
+
startedAt: string;
|
|
8204
|
+
endedAt: string | null;
|
|
8205
|
+
detail: string | null;
|
|
8206
|
+
};
|
|
8207
|
+
export type ReleaseProgress = {
|
|
8208
|
+
tag: string;
|
|
8209
|
+
version: string;
|
|
8210
|
+
pr: number | null;
|
|
8211
|
+
startedAt: string;
|
|
8212
|
+
updatedAt: string;
|
|
8213
|
+
steps: ReleaseStepRow[];
|
|
8214
|
+
stopped: {
|
|
8215
|
+
step: string;
|
|
8216
|
+
message: string;
|
|
8217
|
+
at: string;
|
|
8218
|
+
} | null;
|
|
8219
|
+
};
|
|
8220
|
+
/** What a release coordinator says about one step. */
|
|
8221
|
+
export type ReleaseStepEntry = {
|
|
8222
|
+
taskId: string;
|
|
8223
|
+
tag: string;
|
|
8224
|
+
version: string;
|
|
8225
|
+
pr: number | null;
|
|
8226
|
+
step: string;
|
|
8227
|
+
state: ReleaseStepRow["state"];
|
|
8228
|
+
at: Date;
|
|
8229
|
+
detail?: string | null;
|
|
8230
|
+
};
|
|
8231
|
+
/**
|
|
8232
|
+
* Record a release step (v146): `running` or `waiting` opens it (its first start is kept), `done` or `failed` ends it.
|
|
8233
|
+
* A step that runs again after a stop starts its row again. A failed write throws here; the release's adapter swallows
|
|
8234
|
+
* it, so recording never changes a release.
|
|
8235
|
+
*/
|
|
8236
|
+
export declare function recordReleaseStep(store: Store, entry: ReleaseStepEntry): void;
|
|
8237
|
+
/** A release's steps, for the release task: the newest tag recorded for it, its steps in the order they ran, and the
|
|
8238
|
+
* step it stopped at when the last thing recorded was a failure. Null: no step recorded. */
|
|
8239
|
+
export declare function releaseProgressFor(store: Store, taskId: string): ReleaseProgress | null;
|
|
8240
|
+
/** The release task whose steps were recorded most recently (v146), or null when none was. */
|
|
8241
|
+
export declare function latestReleaseStepTask(store: Store): string | null;
|
|
8242
|
+
/** Seconds a step or check took (to its end, or to `now` while it runs); null without a start. */
|
|
8243
|
+
export declare function elapsedSeconds(startedAt: string | null, endedAt: string | null, now: Date): number | null;
|