toolroll 0.9.85 → 0.9.87
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 +83 -0
- package/dist/agent-fence.d.ts +6 -2
- package/dist/agent-fence.js +3 -2
- 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/assignment.js +4 -3
- 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 -68
- package/dist/browser-crew.js +1 -1
- package/dist/browser-workspace.d.ts +363 -177
- package/dist/browser-workspace.js +10 -9
- package/dist/chat-actions.d.ts +11 -1
- package/dist/chat-actions.js +53 -1
- package/dist/chat-channel.js +1 -0
- package/dist/chat-controls.d.ts +1 -1
- package/dist/chat-controls.js +1 -1
- package/dist/chat-quiet.js +3 -2
- 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/claim.d.ts +3 -0
- package/dist/claim.js +4 -1
- package/dist/contracts/chat-actions.d.ts +9 -0
- package/dist/contracts/chat-actions.js +3 -0
- package/dist/contracts/cli.d.ts +43 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +4 -1
- package/dist/contracts/console-api.js +4 -1
- package/dist/contracts/flow-propose.d.ts +4 -1
- package/dist/contracts/flow-propose.js +1 -1
- package/dist/contracts/flow.d.ts +41 -0
- package/dist/contracts/flow.js +4 -2
- package/dist/contracts/lead-tools.d.ts +21 -0
- package/dist/contracts/lead-tools.js +2 -0
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/contracts/trigger-payloads.d.ts +20 -0
- package/dist/contracts/trigger-payloads.js +4 -0
- package/dist/coordinator.js +1 -0
- package/dist/credentials-ui.d.ts +5 -3
- package/dist/credentials-ui.js +58 -31
- package/dist/deploy-gate.js +4 -0
- package/dist/design/kit.css +685 -0
- package/dist/design/kit.d.ts +208 -0
- package/dist/design/kit.js +177 -0
- package/dist/design/tokens.css +19 -1
- package/dist/discord-settings.js +8 -4
- package/dist/dispatch.d.ts +3 -0
- package/dist/dispatch.js +4 -1
- package/dist/export-ui.d.ts +6 -4
- package/dist/export-ui.js +18 -8
- package/dist/flow-browser.d.ts +103 -0
- package/dist/flow-browser.js +204 -0
- package/dist/flow-changed.d.ts +14 -0
- package/dist/flow-changed.js +53 -0
- package/dist/flow-code.d.ts +5 -1
- package/dist/flow-code.js +4 -1
- package/dist/flow-engine.js +16 -0
- package/dist/flow-gallery-ui.d.ts +41 -4
- package/dist/flow-gallery-ui.js +95 -63
- package/dist/flow-live.js +9 -1
- package/dist/flow-pull-request.js +15 -7
- package/dist/flow-share.js +3 -1
- package/dist/flow-starters-ui.d.ts +3 -9
- package/dist/flow-starters-ui.js +12 -23
- package/dist/flow-steps.d.ts +9 -1
- package/dist/flow-steps.js +55 -5
- package/dist/flow-triggers.js +55 -0
- 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.d.ts +19 -0
- package/dist/flows-cli.js +54 -5
- package/dist/flows-ui.d.ts +12 -6
- package/dist/flows-ui.js +152 -32
- package/dist/flows.js +5 -2
- 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/lead-tools.js +35 -6
- package/dist/lead-voice.js +16 -5
- 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 +249 -6
- 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-delete.js +7 -3
- 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-flow.js +35 -4
- 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 +21 -0
- package/dist/release.js +40 -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/result-follow-ups.js +4 -0
- package/dist/retention-ui.d.ts +4 -3
- package/dist/retention-ui.js +15 -12
- package/dist/scope.d.ts +8 -0
- package/dist/scope.js +13 -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 +20 -18
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +19 -9
- package/dist/server/console.css +31 -2
- package/dist/server/flows.js +79 -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 +69 -0
- package/dist/server/kit.d.ts +405 -0
- package/dist/server/kit.js +361 -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 +35 -190
- package/dist/server/render-pages.js +154 -563
- 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 +43 -5
- package/dist/server/render-tasks.js +131 -91
- package/dist/server/route-table.js +31 -5
- package/dist/server/settings.js +276 -255
- package/dist/server/task-views.d.ts +8 -0
- package/dist/server/task-views.js +90 -2
- package/dist/server/tasks.d.ts +18 -0
- package/dist/server/tasks.js +148 -41
- 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/settings-proofs.js +1 -0
- 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 +182 -5
- package/dist/store.js +512 -38
- package/dist/surface.js +23 -3
- package/dist/task-archive.d.ts +10 -0
- package/dist/task-archive.js +16 -0
- package/dist/task-control.d.ts +1 -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/tidy.d.ts +130 -0
- package/dist/tidy.js +503 -0
- 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.d.ts +24 -0
- package/dist/work-index.js +56 -30
- package/dist/workspace-ui.d.ts +1 -1
- package/dist/workspace-ui.js +8 -4
- package/package.json +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New task (Wave E, src/design/KIT.md): one describe box, the project it lands in and "Read code before planning" in
|
|
3
|
+
* the box's bottom row, the round send; every other choice behind More options; ideas under it. The form posts the
|
|
4
|
+
* same fields /tasks/add has always read (title, repo, plan-first with planning-policy=choice, quality-mode, after,
|
|
5
|
+
* goal, acceptance, not, touches, scout, id, permission-mode, projectRevision), so every server check is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import { html, joinHtml, postForm } from "../html.js";
|
|
8
|
+
import { projectName } from "../project.js";
|
|
9
|
+
import { screen } from "./chrome.js";
|
|
10
|
+
import { btn, composer, disclose, doc, docHeader, dock, field, ideas, input, note, phoneHeader, radios, select, sendButton, switchInput, textarea } from "./kit.js";
|
|
11
|
+
const FORM_ID = "nt-form";
|
|
12
|
+
const PLAN_ON = "The agent reads the code and asks you anything unclear, then writes the plan.";
|
|
13
|
+
const PLAN_OFF = "The agent writes the plan straight from your words. Faster for small, obvious changes.";
|
|
14
|
+
/** The projects as the select offers them: names, with the parent folder when two share a name; the open one first
|
|
15
|
+
* picked. Values are the paths the server proves. */
|
|
16
|
+
function projectItems(projects, open) {
|
|
17
|
+
const all = open !== null && !projects.some(one => one.path === open) ? [{ path: open, name: projectName(open) }, ...projects] : [...projects];
|
|
18
|
+
const counts = new Map();
|
|
19
|
+
for (const one of all)
|
|
20
|
+
counts.set(one.name, (counts.get(one.name) ?? 0) + 1);
|
|
21
|
+
return all.map(one => {
|
|
22
|
+
if ((counts.get(one.name) ?? 0) < 2)
|
|
23
|
+
return [one.path, one.name];
|
|
24
|
+
const parent = one.path.split(/[\\/]/).filter(Boolean).slice(-2, -1)[0] ?? one.path;
|
|
25
|
+
return [one.path, `${one.name} (${parent})`];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export function newTaskPage(chrome, project,
|
|
29
|
+
/** undefined: keep the revision the refused form posted (its draft), so a project switch since still refuses. */
|
|
30
|
+
projectRevision, problem, candidates = [], permissionDefault = "auto", qualityDefault = "default", projects = [],
|
|
31
|
+
/** A shipped template's fields, or a refused filing's own words, back in the form. */
|
|
32
|
+
prefill = null,
|
|
33
|
+
/** Words an idea's link put in the box (GET ?text=). */
|
|
34
|
+
draft = null,
|
|
35
|
+
/** Ideas for the chosen project: one tap drafts the words into the box. */
|
|
36
|
+
suggestions = []) {
|
|
37
|
+
const head = html `${phoneHeader("New task", { back: "/work" })}`;
|
|
38
|
+
const header = docHeader({ title: "New task", back: ["/work", "Tasks"], meta: "Nothing is built until you approve its plan.", same: true });
|
|
39
|
+
const items = projectItems(projects, project);
|
|
40
|
+
const values = prefill?.values;
|
|
41
|
+
// No project to choose from: the task names its folder (the server proves it), and adding a project is one link away.
|
|
42
|
+
const typed = items.length === 0;
|
|
43
|
+
const chosen = values?.get("repo") ?? project ?? items[0]?.[0] ?? "";
|
|
44
|
+
const planOn = values === undefined || values.get("plan-first") === "1";
|
|
45
|
+
const quality = values?.get("quality-mode") ?? qualityDefault;
|
|
46
|
+
const after = values?.get("after") ?? "";
|
|
47
|
+
const permission = values?.get("permission-mode") === "bypassPermissions" ? "bypassPermissions" : values?.get("permission-mode") === "auto" ? "auto" : permissionDefault;
|
|
48
|
+
const text = prefill?.title ?? draft ?? "";
|
|
49
|
+
// More options opens on a template, or when a refused filing had used any of them.
|
|
50
|
+
const optionsUsed = prefill !== null && (values === undefined || ["goal", "acceptance", "not", "touches", "id", "after"].some(name => (values.get(name) ?? "") !== "") || values.get("scout") === "1");
|
|
51
|
+
const folder = !typed ? "" : field({ id: "nt-repo", label: "Project folder", hint: "No projects yet: name the folder of a git repository.",
|
|
52
|
+
control: input({ id: "nt-repo", name: "repo", value: chosen, hint: true, attrs: { required: true, placeholder: "/path/to/repository", autocapitalize: "none", spellcheck: "false" } }) });
|
|
53
|
+
const bar = joinHtml([
|
|
54
|
+
typed ? "" : select({ id: "nt-project", name: "repo", label: "Project", items, current: chosen, sm: true }),
|
|
55
|
+
switchInput({ id: "nt-plan", name: "plan-first", label: "Read code before planning", on: planOn, attrs: { value: "1" } }),
|
|
56
|
+
]);
|
|
57
|
+
const box = composer({
|
|
58
|
+
id: "nt", name: "title", label: "What should change?", placeholder: "What should change? One or two sentences is enough.",
|
|
59
|
+
value: text, rows: 4, maxRows: 10, before: bar, error: problem,
|
|
60
|
+
send: sendButton({ label: "File task" }),
|
|
61
|
+
note: html `<span class="k-on-note">${PLAN_ON}</span><span class="k-off-note">${PLAN_OFF}</span>`,
|
|
62
|
+
textAttrs: { maxlength: 200, autofocus: true },
|
|
63
|
+
});
|
|
64
|
+
const options = html `<div class="k-form">\
|
|
65
|
+
${field({ id: "nt-quality", label: "Checks", control: select({ id: "nt-quality", name: "quality-mode", items: [["default", "Default checks"], ["strict", "Strict (release)"]], current: quality, wide: true }) })}\
|
|
66
|
+
${candidates.length === 0 ? "" : field({ id: "nt-after", label: "Starts", control: select({ id: "nt-after", name: "after", wide: true, current: after,
|
|
67
|
+
items: [["", "Right away"], ...candidates.map(one => [one.id, `After ${one.id}: ${one.title}`])] }) })}\
|
|
68
|
+
${field({ id: "nt-goal", label: "Goal (optional)", hint: "With acceptance below, automatic approval can sign an unchanged plan.", control: textarea({ id: "nt-goal", name: "goal", rows: 2, value: prefill?.goal ?? "", attrs: { placeholder: "What success looks like" } }) })}\
|
|
69
|
+
${field({ id: "nt-acceptance", label: "Acceptance", hint: "Needed with a goal. One per line: statement | evidence,kinds | how", control: textarea({ id: "nt-acceptance", name: "acceptance", rows: 2, value: prefill?.acceptance ?? "", attrs: { placeholder: "Requests over the limit return 429 | check" } }) })}\
|
|
70
|
+
${field({ id: "nt-not", label: "Not this (optional)", control: input({ id: "nt-not", name: "not", value: prefill?.not ?? "" }) })}\
|
|
71
|
+
${field({ id: "nt-touches", label: "Likely touches (optional)", hint: "Paths, separated by commas.", control: input({ id: "nt-touches", name: "touches", value: prefill?.touches ?? "", hint: true }) })}\
|
|
72
|
+
<div class="k-checks"><label><input type="checkbox" name="scout" value="1"${values?.get("scout") === "1" ? html ` checked` : ""}>Research only: a read-only report, no code changes</label></div>\
|
|
73
|
+
${field({ id: "nt-id", label: "Task id (optional)", control: input({ id: "nt-id", name: "id", value: values?.get("id") ?? "", attrs: { placeholder: "Made from the request" } }) })}\
|
|
74
|
+
<div class="k-field"><span class="k-label">Agent permissions</span>${radios({ name: "permission-mode", legend: "Agent permissions", current: permission, items: [
|
|
75
|
+
{ value: "auto", label: "Auto", text: "Asks before risky actions." },
|
|
76
|
+
{ value: "bypassPermissions", label: "Full access", text: "Never asks and can change files anywhere on this computer. Trusted repositories only." },
|
|
77
|
+
] })}<p class="k-hint">From Settings. You can still change it on the plan before you approve.</p></div></div>`;
|
|
78
|
+
const form = postForm("/tasks/add", joinHtml([
|
|
79
|
+
prefill !== null && values === undefined ? note("Filled in from a template. Change anything; it still waits for your approval.") : "",
|
|
80
|
+
folder,
|
|
81
|
+
typed ? note(html `<a class="k-link" href="/projects?return=%2Ftasks%2Fnew">Add a project</a> to choose it here next time.`) : "",
|
|
82
|
+
box,
|
|
83
|
+
disclose("More options", options, optionsUsed),
|
|
84
|
+
]), {
|
|
85
|
+
attrs: { class: "k-form k-dock-send", id: FORM_ID },
|
|
86
|
+
projectRevision: projectRevision === undefined && values?.get("projectRevision") == null ? null : String(projectRevision ?? values?.get("projectRevision") ?? ""),
|
|
87
|
+
hidden: { "planning-policy": "choice" },
|
|
88
|
+
});
|
|
89
|
+
const chosenName = items.find(([path]) => path === chosen)?.[1] ?? (chosen === "" ? "your project" : projectName(chosen));
|
|
90
|
+
const ideaList = ideas({
|
|
91
|
+
label: `Ideas for ${chosenName}`, into: "nt",
|
|
92
|
+
items: suggestions.map(one => ({ label: one.label, draft: one.draft, href: `/tasks/new?text=${encodeURIComponent(one.draft)}` })),
|
|
93
|
+
});
|
|
94
|
+
const recipes = note(html `Work you do often? <a class="k-link" href="/recipes">Use a saved recipe</a>.`);
|
|
95
|
+
return screen("New task", html `${head}${doc(header, form, ideaList, recipes)}${dock(btn("File task", { variant: "primary", type: "submit", attrs: { form: FORM_ID } }))}`, { chrome });
|
|
96
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /next (Wave E, src/design/KIT.md): everything waiting on a person, one at a time, each in the approval slots with
|
|
3
|
+
* its one act, every act landing back here. The forms post exactly what they always have (the approve form's nonce,
|
|
4
|
+
* digest and password; a decision's choice, confirm and note; a requeue), so every server check is unchanged. The
|
|
5
|
+
* approval shows the password only when the rules ask (approveForm, standard): none with Passwordless or a remembered
|
|
6
|
+
* password the task page's own preview says may approve these exact terms; otherwise the password, required.
|
|
7
|
+
*/
|
|
8
|
+
import { type TaskOrigin } from "../task-source.js";
|
|
9
|
+
import type { Gap } from "../gaps.js";
|
|
10
|
+
import type { Scope } from "../scope.js";
|
|
11
|
+
import type { Decision } from "../store.js";
|
|
12
|
+
import { type Chrome, type Screen } from "./chrome.js";
|
|
13
|
+
import { type PlanContractView, type RouteView } from "./render-tasks.js";
|
|
14
|
+
export type NextItem = {
|
|
15
|
+
key: string;
|
|
16
|
+
kind: "decision";
|
|
17
|
+
decision: Decision & {
|
|
18
|
+
taskId: string;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
key: string;
|
|
22
|
+
kind: "approval";
|
|
23
|
+
approval: {
|
|
24
|
+
taskId: string;
|
|
25
|
+
title: string;
|
|
26
|
+
goal: string;
|
|
27
|
+
digest: string;
|
|
28
|
+
proposedAt: string;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
key: string;
|
|
32
|
+
kind: "requeue";
|
|
33
|
+
stalled: {
|
|
34
|
+
taskId: string;
|
|
35
|
+
title: string;
|
|
36
|
+
strikes: number;
|
|
37
|
+
incidentCount: number;
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
key: string;
|
|
41
|
+
kind: "gap";
|
|
42
|
+
gap: Gap;
|
|
43
|
+
} | null;
|
|
44
|
+
export declare function nextPage(chrome: Chrome, data: {
|
|
45
|
+
item: NextItem;
|
|
46
|
+
scope: Scope | null;
|
|
47
|
+
planDocument: string | null;
|
|
48
|
+
planContract?: PlanContractView | null;
|
|
49
|
+
approvalDigest: string | null;
|
|
50
|
+
/** v34: said inside the ceremony when the yes buys a report, not a branch. */
|
|
51
|
+
deliverable?: "branch" | "report";
|
|
52
|
+
/** v48: the agents the yes freezes — the one block every ceremony shows. */
|
|
53
|
+
route: RouteView | null;
|
|
54
|
+
/** v126: where the work came from (an outside event's line of context, never a term agreed to). */
|
|
55
|
+
origin?: TaskOrigin | null;
|
|
56
|
+
/** A remembered password stands in for these exact terms (the task page's preview): one click, no field. */
|
|
57
|
+
remembered?: boolean;
|
|
58
|
+
csrf: string;
|
|
59
|
+
nonce: string;
|
|
60
|
+
remaining: number;
|
|
61
|
+
skipped: string[];
|
|
62
|
+
now: Date;
|
|
63
|
+
}): Screen;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /next (Wave E, src/design/KIT.md): everything waiting on a person, one at a time, each in the approval slots with
|
|
3
|
+
* its one act, every act landing back here. The forms post exactly what they always have (the approve form's nonce,
|
|
4
|
+
* digest and password; a decision's choice, confirm and note; a requeue), so every server check is unchanged. The
|
|
5
|
+
* approval shows the password only when the rules ask (approveForm, standard): none with Passwordless or a remembered
|
|
6
|
+
* password the task page's own preview says may approve these exact terms; otherwise the password, required.
|
|
7
|
+
*/
|
|
8
|
+
import { originNote } from "../task-source.js";
|
|
9
|
+
import { html, joinHtml, postForm } from "../html.js";
|
|
10
|
+
import { screen, when } from "./chrome.js";
|
|
11
|
+
import { taskHref } from "./http.js";
|
|
12
|
+
import { acceptanceCeremonyHtml, agentsCeremonyHtml, consentClosedHtml, consentDoorOf, executionPlanHtml, planContractHtml, profileWords, runtimeDetailsHtml, } from "./render-tasks.js";
|
|
13
|
+
import { approvalFactsNow, approvalTerms, approveForm, btn, chip, disclose, doc, docHeader, empty, facts, note, phoneHeader, slots } from "./kit.js";
|
|
14
|
+
/** One decision option: a one-click answer (an irreversible one behind its own disclosure, with the confirm the server
|
|
15
|
+
* requires) and its consequence. A note travels from the task's own page. */
|
|
16
|
+
function optionForm(decision, option) {
|
|
17
|
+
const recommended = option.id === decision.recommendation;
|
|
18
|
+
const form = postForm(`/d/${decision.id}/answer`, html `<div class="k-acts">${btn(option.label, { variant: option.reversible ? (recommended ? "primary" : "outline") : "danger", type: "submit" })}</div>\
|
|
19
|
+
<p class="k-note">${recommended ? html `${chip("Recommended", "", { dot: false })} ` : ""}${option.consequence}</p>`, { attrs: { class: "k-form" }, returnTo: "next", hidden: { choice: option.id, confirm: option.reversible ? null : "yes" } });
|
|
20
|
+
return option.reversible ? form : disclose(`${option.label} (can't be undone)`, form);
|
|
21
|
+
}
|
|
22
|
+
export function nextPage(chrome, data) {
|
|
23
|
+
const { item } = data;
|
|
24
|
+
const title = "Needs you";
|
|
25
|
+
if (item === null) {
|
|
26
|
+
const held = data.skipped.length;
|
|
27
|
+
return screen(title, html `${phoneHeader(title)}${doc(docHeader({ title, same: true }), held > 0
|
|
28
|
+
? empty({ title: `Only the ${held} you set aside ${held === 1 ? "is" : "are"} left.`, text: "Look at them again now, or come back later.", action: btn("Look at them again", { sm: true, href: "/next" }) })
|
|
29
|
+
: empty({ title: "Nothing needs you.", text: "Everything is either working or waiting on its own clock.", action: btn("Open Tasks", { sm: true, href: "/work" }) }))}`, { chrome });
|
|
30
|
+
}
|
|
31
|
+
const skipHref = `/next?skip=${encodeURIComponent([...data.skipped, item.key].join(","))}`;
|
|
32
|
+
const header = docHeader({
|
|
33
|
+
title, same: true,
|
|
34
|
+
meta: data.remaining === 1 ? "The last thing waiting on you" : `1 of ${data.remaining} waiting on you`,
|
|
35
|
+
right: btn("Not now", { variant: "ghost", sm: true, href: skipHref }),
|
|
36
|
+
});
|
|
37
|
+
const openTask = (taskId, words = "Open the task") => html `<a class="k-link" href="${taskHref(taskId)}">${words}</a>`;
|
|
38
|
+
let card;
|
|
39
|
+
if (item.kind === "decision") {
|
|
40
|
+
const { decision } = item;
|
|
41
|
+
card = slots({
|
|
42
|
+
wait: true, attrs: { "data-decision": String(decision.id) },
|
|
43
|
+
status: html `${chip("Question", "ask")}<h2>${decision.question}</h2>`,
|
|
44
|
+
text: decision.recap,
|
|
45
|
+
acts: joinHtml(decision.options.map(option => optionForm(decision, option))),
|
|
46
|
+
terms: html `${decision.taskId} · asked ${when(decision.createdAt)} · ${openTask(decision.taskId, "Answer with a note on the task")}`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else if (item.kind === "approval" && !consentDoorOf(data.scope, data.route).open) {
|
|
50
|
+
const door = consentDoorOf(data.scope, data.route);
|
|
51
|
+
card = slots({
|
|
52
|
+
wait: true,
|
|
53
|
+
status: html `${chip("Plan", "ask")}<h2>${item.approval.title}</h2>`,
|
|
54
|
+
text: item.approval.taskId,
|
|
55
|
+
acts: consentClosedHtml(item.approval.taskId, door, "next"),
|
|
56
|
+
terms: openTask(item.approval.taskId),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
else if (item.kind === "approval") {
|
|
60
|
+
const scope = data.scope;
|
|
61
|
+
const facts_ = approvalFactsNow({ remembered: data.remembered === true });
|
|
62
|
+
const terms = joinHtml([
|
|
63
|
+
data.deliverable === "report" ? note("Research only: a read-only session investigates this goal and delivers a report. No branch; nothing in the repository changes.") : "",
|
|
64
|
+
scope === null || scope.profileState !== "unresolved" ? "" : profileWords(scope),
|
|
65
|
+
originNote(data.origin) === null ? "" : html `<p class="k-note" data-approval-origin>${originNote(data.origin)}</p>`,
|
|
66
|
+
facts([
|
|
67
|
+
["Goal", scope?.goal ?? item.approval.goal],
|
|
68
|
+
["Not this", scope?.outOfScope == null ? "No exclusions" : scope.outOfScope],
|
|
69
|
+
["Touches", scope === null || scope.touches.length === 0 ? "Anything" : scope.touches.join(", ")],
|
|
70
|
+
]),
|
|
71
|
+
scope === null ? "" : acceptanceCeremonyHtml(scope.acceptance),
|
|
72
|
+
// The agents the yes freezes (v48): the same block the task page and chat sign under, before the password.
|
|
73
|
+
agentsCeremonyHtml(data.route),
|
|
74
|
+
scope === null ? "" : runtimeDetailsHtml(scope),
|
|
75
|
+
]);
|
|
76
|
+
const plan = data.planDocument === null ? "" : html `<section class="k-sec"><h3>The plan</h3>${executionPlanHtml(data.planDocument, true)}${planContractHtml(data.planContract ?? null, "ceremony")}</section>`;
|
|
77
|
+
const digest = data.approvalDigest ?? item.approval.digest;
|
|
78
|
+
// The terms ride inside the form, before the password: what the yes covers is on the form that says it.
|
|
79
|
+
card = html `${plan}${slots({
|
|
80
|
+
wait: true, attrs: { "data-approval": digest },
|
|
81
|
+
status: html `${chip("Plan", "ask")}<h2>${item.approval.title}</h2>`,
|
|
82
|
+
text: html `${item.approval.taskId} · ${openTask(item.approval.taskId, "Open the task to change the scope first")}`,
|
|
83
|
+
acts: approveForm({ action: `${taskHref(item.approval.taskId)}/approve`, kind: "standard", facts: facts_, label: "Approve and start", primary: true,
|
|
84
|
+
before: html `<section class="k-sec"><h3>Approve exactly this</h3>${terms}</section>`,
|
|
85
|
+
form: { returnTo: "next", hidden: { nonce: data.nonce, digest }, attrs: { class: "k-form" } } }),
|
|
86
|
+
terms: approvalTerms("standard", facts_),
|
|
87
|
+
})}`;
|
|
88
|
+
}
|
|
89
|
+
else if (item.kind === "requeue") {
|
|
90
|
+
card = slots({
|
|
91
|
+
wait: true,
|
|
92
|
+
status: html `${chip("Stopped", "ask")}<h2>${item.stalled.title}</h2>`,
|
|
93
|
+
text: `Stopped with ${item.stalled.incidentCount} incident${item.stalled.incidentCount === 1 ? "" : "s"}${item.stalled.strikes > 0 ? ` after ${item.stalled.strikes} attempt${item.stalled.strikes === 1 ? "" : "s"}` : ""}. Retrying resolves the incidents, clears the failed attempts and puts it back in line.`,
|
|
94
|
+
acts: postForm(`${taskHref(item.stalled.taskId)}/requeue`, btn("Retry this work", { variant: "primary", type: "submit" }), { returnTo: "next" }),
|
|
95
|
+
terms: html `${item.stalled.taskId} · ${openTask(item.stalled.taskId, "Read the attempts first")}`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const { gap } = item;
|
|
100
|
+
card = slots({
|
|
101
|
+
wait: true,
|
|
102
|
+
status: html `${chip("Missing", "ask")}<h2>Supply ${gap.key}</h2>`,
|
|
103
|
+
text: html `${gap.state}. Filling it starts ${gap.unblocks.length} task${gap.unblocks.length === 1 ? "" : "s"}: ${joinHtml(gap.unblocks.map(one => html `<span class="k-mono">${one}</span>`), ", ")}.`,
|
|
104
|
+
acts: "",
|
|
105
|
+
terms: html `Prove it is filled from a terminal: <code class="k-mono">${gap.verify}</code>`,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return screen(title, html `${phoneHeader(title)}${doc(header, card)}`, { chrome });
|
|
109
|
+
}
|
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
/** Everyday console pages: home, inbox, board, work, projects, fleet and the queue. */
|
|
2
|
-
import { type
|
|
2
|
+
import { type TidyItem } from "../tidy.js";
|
|
3
3
|
import { type Html } from "../html.js";
|
|
4
4
|
import { type AssignmentSnapshot } from "../assignment.js";
|
|
5
5
|
import { type BoardCard } from "../board.js";
|
|
6
|
-
import { type BrowserLimits
|
|
7
|
-
import { type CheckLevel } from "../check-levels.js";
|
|
6
|
+
import { type BrowserLimits } from "../browser-workspace.js";
|
|
8
7
|
import { type DispatchDiagnosis } from "../dispatch.js";
|
|
9
8
|
import { type FirstRunStep } from "../first-run.js";
|
|
10
9
|
import { type Gap } from "../gaps.js";
|
|
11
|
-
import { type ListOutcome } from "../onboard.js";
|
|
12
10
|
import { type parseBaseTreeSnapshot } from "../peek.js";
|
|
13
11
|
import { type CriterionMatrixRow } from "../proof.js";
|
|
14
|
-
import { type QualityMode } from "../quality.js";
|
|
15
12
|
import { type Runner } from "../runner.js";
|
|
16
|
-
import { type Scope, type UnattendedPermissionMode } from "../scope.js";
|
|
17
13
|
import { type Decision, type Incident, type RepairChainRow, type Run, type Store, type TaskState, type WorktreeRow } from "../store.js";
|
|
18
14
|
import { tally } from "../summary.js";
|
|
19
|
-
import { type WorkIndexGroup, type WorkIndexPage } from "../work-index.js";
|
|
15
|
+
import { type WorkIndexGroup, type WorkIndexItem, type WorkIndexPage } from "../work-index.js";
|
|
16
|
+
import { type ChipTone } from "../design/kit.js";
|
|
20
17
|
import { type WorkFacts, type WorkStatus, type WorkView } from "../workspace-ui.js";
|
|
21
18
|
import { type Chrome, type Screen } from "./chrome.js";
|
|
22
|
-
import { type PlanContractView, type RouteView } from "./render-tasks.js";
|
|
23
19
|
export declare const TASK_STATES: readonly TaskState[];
|
|
24
20
|
/**
|
|
25
21
|
* The inbox (v3): only things stalling progress without a person, one card
|
|
@@ -111,9 +107,8 @@ export declare function inboxPage(chrome: Chrome, data: {
|
|
|
111
107
|
}[];
|
|
112
108
|
unread?: readonly InboxTab[];
|
|
113
109
|
}): Screen;
|
|
114
|
-
/** System: the machinery — workers, background service, workspaces. */
|
|
115
110
|
/** Start a builder: the one command, as text to select (/start-builder, where every "Connect a builder" leads, and
|
|
116
|
-
*
|
|
111
|
+
* the Agents page). `project`: the open project's name, when the viewer may see it; `connected`: whether a builder
|
|
117
112
|
* that may build there is checking in (null: say nothing); `managed`: whether this person can start one themselves
|
|
118
113
|
* (registering a builder takes an instance operator), else who to ask. */
|
|
119
114
|
export declare function startBuilderHtml(data: {
|
|
@@ -122,40 +117,6 @@ export declare function startBuilderHtml(data: {
|
|
|
122
117
|
connected: boolean | null;
|
|
123
118
|
managed: boolean;
|
|
124
119
|
}): Html;
|
|
125
|
-
export declare function systemPage(chrome: Chrome, data: {
|
|
126
|
-
agents: {
|
|
127
|
-
phase: "plan" | "build" | "repair" | "review";
|
|
128
|
-
provider?: string;
|
|
129
|
-
model?: string | null;
|
|
130
|
-
source?: "pinned" | "flag" | "project" | "installation" | "default";
|
|
131
|
-
problem?: string;
|
|
132
|
-
setBy: string | null;
|
|
133
|
-
}[];
|
|
134
|
-
building: {
|
|
135
|
-
taskId: string;
|
|
136
|
-
runner: string;
|
|
137
|
-
claimedAt: string;
|
|
138
|
-
expiresAt: string;
|
|
139
|
-
model: string | null;
|
|
140
|
-
}[];
|
|
141
|
-
runners: Runner[];
|
|
142
|
-
worktrees: WorktreeRow[];
|
|
143
|
-
episode: {
|
|
144
|
-
id: number;
|
|
145
|
-
startedAt: string;
|
|
146
|
-
endedAt: string | null;
|
|
147
|
-
ticks: number;
|
|
148
|
-
built: number;
|
|
149
|
-
broke: number;
|
|
150
|
-
} | null;
|
|
151
|
-
outboxPending: number;
|
|
152
|
-
externalWork?: {
|
|
153
|
-
remoteRepo: string;
|
|
154
|
-
blocked: string | null;
|
|
155
|
-
openEpisode: string | null;
|
|
156
|
-
}[];
|
|
157
|
-
now: Date;
|
|
158
|
-
}): Screen;
|
|
159
120
|
/**
|
|
160
121
|
* A build's stage as one of three steps — set up, writing, checking and
|
|
161
122
|
* committing — read from the machine's own phase, never a percent. The
|
|
@@ -202,8 +163,6 @@ export declare function boardBody(data: {
|
|
|
202
163
|
questions: number;
|
|
203
164
|
} | null;
|
|
204
165
|
}, ciRed: (pr: number) => boolean): Html;
|
|
205
|
-
/** Completed work: one row per done task, its final run and PR attached. */
|
|
206
|
-
export declare function donePage(chrome: Chrome, rows: ReturnType<Store["listCompletedWorkScoped"]>, ciRed: (pr: number) => boolean): Screen;
|
|
207
166
|
export declare function homePage(chrome: Chrome, data: {
|
|
208
167
|
csrf: string;
|
|
209
168
|
taskCount: number;
|
|
@@ -243,40 +202,6 @@ export declare function homePage(chrome: Chrome, data: {
|
|
|
243
202
|
settings: boolean;
|
|
244
203
|
now: Date;
|
|
245
204
|
}): Screen;
|
|
246
|
-
export type TaskComposerPrefill = {
|
|
247
|
-
title: string;
|
|
248
|
-
goal: string;
|
|
249
|
-
not: string;
|
|
250
|
-
touches: string;
|
|
251
|
-
acceptance: string;
|
|
252
|
-
values?: URLSearchParams;
|
|
253
|
-
};
|
|
254
|
-
/** The one front door for new work. The common path is one prompt and one
|
|
255
|
-
* button; the detailed contract remains available in-place for templates,
|
|
256
|
-
* experts, and the rare task that should skip repository-aware planning. */
|
|
257
|
-
/** Where new work goes when no project is open: a choice from the projects
|
|
258
|
-
* this person already has, never a typed path; a new project is one link
|
|
259
|
-
* away. Same-named checkouts show their parent folder to tell them apart. */
|
|
260
|
-
export declare function projectPickerHtml(projects: {
|
|
261
|
-
path: string;
|
|
262
|
-
name: string;
|
|
263
|
-
}[], chosen: string): Html;
|
|
264
|
-
export declare function taskComposerHtml(data: {
|
|
265
|
-
project: string | null;
|
|
266
|
-
projectRevision?: number;
|
|
267
|
-
prefill?: TaskComposerPrefill | null;
|
|
268
|
-
candidates?: {
|
|
269
|
-
id: string;
|
|
270
|
-
title: string;
|
|
271
|
-
}[];
|
|
272
|
-
permissionDefault: UnattendedPermissionMode;
|
|
273
|
-
qualityDefault: QualityMode;
|
|
274
|
-
/** Projects this person may place work in, most recently opened first. */
|
|
275
|
-
projects?: {
|
|
276
|
-
path: string;
|
|
277
|
-
name: string;
|
|
278
|
-
}[];
|
|
279
|
-
}): Html;
|
|
280
205
|
export type WorkRow = WorkFacts & {
|
|
281
206
|
assignment?: AssignmentSnapshot | null;
|
|
282
207
|
assignmentProblem?: boolean;
|
|
@@ -286,6 +211,19 @@ export type WorkRow = WorkFacts & {
|
|
|
286
211
|
resultRunId: number | null;
|
|
287
212
|
};
|
|
288
213
|
export declare const TASK_GROUP_LABEL: Readonly<Record<WorkIndexGroup, string>>;
|
|
214
|
+
/** A list row's chip (src/design/KIT.md): a waiting row names its ask ("Plan", "Result") in the ask tone, or says
|
|
215
|
+
* Needs you; every other row wears its headline in the tone of the status it belongs to. */
|
|
216
|
+
export declare function workRowChip(row: Pick<WorkIndexItem, 'ask' | 'chip' | 'status' | 'archived'>): {
|
|
217
|
+
word: string;
|
|
218
|
+
tone: ChipTone;
|
|
219
|
+
};
|
|
220
|
+
/** The board's four columns: what needs you, what will start on its own, what runs, what finished. */
|
|
221
|
+
export type WorkBoard = {
|
|
222
|
+
needs: WorkIndexPage;
|
|
223
|
+
queued: WorkIndexPage;
|
|
224
|
+
running: WorkIndexPage;
|
|
225
|
+
finished: WorkIndexPage;
|
|
226
|
+
};
|
|
289
227
|
export declare function workPage(chrome: Chrome, data: {
|
|
290
228
|
view: WorkView;
|
|
291
229
|
projectFilter?: string;
|
|
@@ -295,19 +233,13 @@ export declare function workPage(chrome: Chrome, data: {
|
|
|
295
233
|
now: Date;
|
|
296
234
|
limits?: BrowserLimits | null;
|
|
297
235
|
state?: TaskState | null;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
name: string;
|
|
306
|
-
path: string;
|
|
307
|
-
git: boolean;
|
|
308
|
-
}[];
|
|
309
|
-
/** Unused: postForm adds the request's CSRF field. Kept for callers. */
|
|
310
|
-
csrf: string;
|
|
236
|
+
/** An approver in a browser session: rows offer Put away (or Restore, archived), and the page offers Put away old tasks. */
|
|
237
|
+
canPutAway?: boolean;
|
|
238
|
+
/** The project this list shows (null: every project in view) and whether All was asked for by name (`all=1`). */
|
|
239
|
+
lens?: string | null;
|
|
240
|
+
all?: boolean;
|
|
241
|
+
/** The Board view's columns, read from the same index as the list; absent for the List view. */
|
|
242
|
+
board?: WorkBoard | null;
|
|
311
243
|
}): Screen;
|
|
312
244
|
/** The compact completed row shared by both halves of the control room. */
|
|
313
245
|
export type WorkbenchDone = {
|
|
@@ -432,26 +364,6 @@ export type ProjectPeek = {
|
|
|
432
364
|
* GitHub identity. Everything else is null.
|
|
433
365
|
*/
|
|
434
366
|
export declare function githubIdentityOf(remoteUrl: string): string | null;
|
|
435
|
-
/** The GitHub listing page: the account's repositories with ONE honest
|
|
436
|
-
* action each. Names, descriptions, and paths are gh/filesystem DATA —
|
|
437
|
-
* escaped at the sink like everything else. */
|
|
438
|
-
export declare function githubReposPage(chrome: Chrome, data: {
|
|
439
|
-
/** The last listing; null until someone lists (a POST: listing asks GitHub, so a page visit never does). */
|
|
440
|
-
listed: ListOutcome | null;
|
|
441
|
-
local: Map<string, string>;
|
|
442
|
-
registered: Set<string>;
|
|
443
|
-
/** Unused: postForm adds the request's CSRF field. Kept for callers. */
|
|
444
|
-
csrf: string;
|
|
445
|
-
cloneReady: boolean;
|
|
446
|
-
openProject: string | null;
|
|
447
|
-
/** A projects folder didn't answer in time: local copies weren't matched this time. */
|
|
448
|
-
localUnanswered?: boolean;
|
|
449
|
-
}): Screen;
|
|
450
|
-
export declare function projectsPage(chrome: Chrome, recent: {
|
|
451
|
-
path: string;
|
|
452
|
-
name: string;
|
|
453
|
-
lastOpenedAt: string;
|
|
454
|
-
}[], candidates: string[], open: string | null, problem: string | null, _unscopedMode: boolean, browsable?: boolean, onboard?: OnboardCardState | null, peeks?: Record<string, ProjectPeek | null>, returnTo?: string, pullRequestsOn?: (path: string) => boolean, checkLevelOf?: (path: string) => CheckLevel, activity?: BrowserProjectsView["activity"]): Screen;
|
|
455
367
|
/** The no-script "move to the front" sentinel: the form cannot name the
|
|
456
368
|
* front of a partition, so the handler resolves it (slice 1b, fix 1). */
|
|
457
369
|
export declare const QUEUE_FRONT = "__TOP__";
|
|
@@ -470,18 +382,6 @@ export declare function queueBody(tasks: QueueCardTask[], workers: {
|
|
|
470
382
|
capacity: number;
|
|
471
383
|
building: number;
|
|
472
384
|
}[], revision: number, queueRevision: number): Html;
|
|
473
|
-
/**
|
|
474
|
-
* The fleet screen — one lane per runner, and the work in front of it.
|
|
475
|
-
* Building claims pin to the top of their worker's lane (live — never
|
|
476
|
-
* draggable); queued reservations sit below it (draggable to another
|
|
477
|
-
* worker, re-reserving them). Every card wears its project chip, which is
|
|
478
|
-
* the whole point: which agent is on which project is the page's answer.
|
|
479
|
-
* Form-free like the board, except the per-worker note, so the lane stack
|
|
480
|
-
* can re-render itself while somebody watches.
|
|
481
|
-
*/
|
|
482
|
-
export declare function fleetBody(queued: ReturnType<Store["fleetQueue"]>, building: ReturnType<Store["liveClaims"]>, runners: Runner[], queueRevision: number, visibleRepo: (repo: string | null) => boolean): Html;
|
|
483
|
-
/** Identical drag mechanics to the queue — the pointer events land on the worker's column. */
|
|
484
|
-
export declare function fleetScript(): string;
|
|
485
385
|
/** The /queue page's one nonce'd script: delegated pointer-event drag (it
|
|
486
386
|
* survives every fragment swap — finding 17) plus a poller that re-checks
|
|
487
387
|
* focus, dirty inputs, and an in-flight drag AT SWAP TIME, never only
|
|
@@ -489,71 +389,6 @@ export declare function fleetScript(): string;
|
|
|
489
389
|
* (finding 18); missing that, a select counts clean.
|
|
490
390
|
*/
|
|
491
391
|
export declare function queueScript(): string;
|
|
492
|
-
export declare function newTaskPage(chrome: Chrome, project: string | null,
|
|
493
|
-
/** undefined: keep the revision the refused form posted (its draft), so a project switch since still refuses. */
|
|
494
|
-
projectRevision: number | undefined, problem: string | null, candidates?: {
|
|
495
|
-
id: string;
|
|
496
|
-
title: string;
|
|
497
|
-
}[], permissionDefault?: UnattendedPermissionMode, qualityDefault?: QualityMode, projects?: {
|
|
498
|
-
path: string;
|
|
499
|
-
name: string;
|
|
500
|
-
}[],
|
|
501
|
-
/** A shipped template's fields, or a refused filing's own words, back in the form. */
|
|
502
|
-
prefill?: TaskComposerPrefill | null): Screen;
|
|
503
|
-
/**
|
|
504
|
-
* The triage flow: everything waiting on a person, one card at a time.
|
|
505
|
-
* Full context ON the card, the act inline, and every act lands back here
|
|
506
|
-
* — clearing the queue is taps, not navigation. Read state travels in the
|
|
507
|
-
* URL (the bounded skip cursor), never in the session: two tabs cannot
|
|
508
|
-
* fight, and a shared link shows the same queue.
|
|
509
|
-
*/
|
|
510
|
-
export declare function nextPage(chrome: Chrome, data: {
|
|
511
|
-
item: {
|
|
512
|
-
key: string;
|
|
513
|
-
kind: "decision";
|
|
514
|
-
decision: Decision & {
|
|
515
|
-
taskId: string;
|
|
516
|
-
};
|
|
517
|
-
} | {
|
|
518
|
-
key: string;
|
|
519
|
-
kind: "approval";
|
|
520
|
-
approval: {
|
|
521
|
-
taskId: string;
|
|
522
|
-
title: string;
|
|
523
|
-
goal: string;
|
|
524
|
-
digest: string;
|
|
525
|
-
proposedAt: string;
|
|
526
|
-
};
|
|
527
|
-
} | {
|
|
528
|
-
key: string;
|
|
529
|
-
kind: "requeue";
|
|
530
|
-
stalled: {
|
|
531
|
-
taskId: string;
|
|
532
|
-
title: string;
|
|
533
|
-
strikes: number;
|
|
534
|
-
incidentCount: number;
|
|
535
|
-
};
|
|
536
|
-
} | {
|
|
537
|
-
key: string;
|
|
538
|
-
kind: "gap";
|
|
539
|
-
gap: Gap;
|
|
540
|
-
} | null;
|
|
541
|
-
scope: Scope | null;
|
|
542
|
-
planDocument: string | null;
|
|
543
|
-
planContract?: PlanContractView | null;
|
|
544
|
-
approvalDigest: string | null;
|
|
545
|
-
/** v34: said inside the ceremony when the yes buys a report, not a branch. */
|
|
546
|
-
deliverable?: "branch" | "report";
|
|
547
|
-
/** v48: the agents the yes freezes — the one block every ceremony shows. */
|
|
548
|
-
route: RouteView | null;
|
|
549
|
-
/** v126: where the work came from (an outside event's line of context, never a term agreed to). */
|
|
550
|
-
origin?: TaskOrigin | null;
|
|
551
|
-
csrf: string;
|
|
552
|
-
nonce: string;
|
|
553
|
-
remaining: number;
|
|
554
|
-
skipped: string[];
|
|
555
|
-
now: Date;
|
|
556
|
-
}): Screen;
|
|
557
392
|
export type PeekAdmission = {
|
|
558
393
|
run: Run;
|
|
559
394
|
/** The run's checkout, PROVEN non-null by the guards: a reviewer run
|
|
@@ -562,3 +397,13 @@ export type PeekAdmission = {
|
|
|
562
397
|
epoch: string;
|
|
563
398
|
entries: ReturnType<typeof parseBaseTreeSnapshot>;
|
|
564
399
|
};
|
|
400
|
+
/** Put away old tasks (docs/plans/task-tidy.md): exactly what would be put away, grouped, each with why, every one
|
|
401
|
+
* ticked; one step-up puts away the ticked ones, bound to this preview's digest. The CLI twin is named beside it. */
|
|
402
|
+
export declare function putAwayPage(chrome: Chrome, data: {
|
|
403
|
+
items: readonly TidyItem[];
|
|
404
|
+
days: number;
|
|
405
|
+
digest: string;
|
|
406
|
+
now: Date;
|
|
407
|
+
problem: string | null;
|
|
408
|
+
releasesSkipped: string | null;
|
|
409
|
+
}): Screen;
|