toolroll 0.9.92 → 0.9.94
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 +87 -0
- package/dist/activity-line.d.ts +7 -4
- package/dist/activity-line.js +9 -7
- package/dist/agent-fence.d.ts +4 -0
- package/dist/agent-fence.js +4 -1
- package/dist/approval-authority.d.ts +7 -1
- package/dist/approval-authority.js +11 -2
- package/dist/approval-password.d.ts +31 -0
- package/dist/approval-password.js +26 -0
- package/dist/assignment-status.d.ts +1 -1
- package/dist/assignment-ui.js +3 -3
- package/dist/assignment.js +16 -3
- package/dist/boot-identity.d.ts +2 -1
- package/dist/boot-identity.js +6 -4
- package/dist/bounded-spawn.d.ts +57 -0
- package/dist/bounded-spawn.js +220 -0
- package/dist/browser/terminal.js +42 -42
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +26 -26
- package/dist/browser-crew.js +2 -2
- package/dist/browser-shell.d.ts +1 -1
- package/dist/browser-shell.js +2 -2
- package/dist/browser-workspace.d.ts +48 -7
- package/dist/browser-workspace.js +3 -3
- package/dist/builder-restart.d.ts +21 -0
- package/dist/builder-restart.js +50 -0
- package/dist/builder.d.ts +4 -0
- package/dist/builder.js +73 -25
- package/dist/chat-acceptance.js +1 -1
- package/dist/chat-actions.d.ts +12 -2
- package/dist/chat-actions.js +25 -2
- package/dist/chat-channel.js +11 -0
- package/dist/chat-decide.d.ts +7 -2
- package/dist/chat-decide.js +37 -9
- package/dist/chat-quiet.js +3 -3
- package/dist/chat-voice.d.ts +1 -1
- package/dist/chat-voice.js +2 -2
- package/dist/check-facts.d.ts +126 -0
- package/dist/check-facts.js +318 -0
- package/dist/check-failure.d.ts +22 -3
- package/dist/check-failure.js +57 -13
- package/dist/check-levels-ui.d.ts +4 -0
- package/dist/check-levels-ui.js +10 -1
- package/dist/check-load.d.ts +85 -0
- package/dist/check-load.js +147 -0
- package/dist/check-only-standing.d.ts +36 -0
- package/dist/check-only-standing.js +39 -0
- package/dist/check-only.d.ts +15 -0
- package/dist/check-only.js +99 -0
- package/dist/check-report.d.ts +7 -0
- package/dist/check-report.js +4 -3
- package/dist/check-stamp.d.ts +46 -0
- package/dist/check-stamp.js +93 -0
- package/dist/checkout-cleanup.d.ts +36 -5
- package/dist/checkout-cleanup.js +166 -14
- package/dist/cli-help.d.ts +4 -1
- package/dist/cli-help.js +47 -30
- package/dist/cli.js +16 -1
- package/dist/code-extract.d.ts +44 -0
- package/dist/code-extract.js +88 -0
- package/dist/code-map-acts.d.ts +24 -0
- package/dist/code-map-acts.js +53 -0
- package/dist/code-map-admission.d.ts +52 -0
- package/dist/code-map-admission.js +295 -0
- package/dist/code-map-build.d.ts +63 -0
- package/dist/code-map-build.js +415 -0
- package/dist/code-map-cli.d.ts +153 -0
- package/dist/code-map-cli.js +103 -0
- package/dist/code-map-main.d.ts +1 -0
- package/dist/code-map-main.js +48 -0
- package/dist/code-map-read.d.ts +106 -0
- package/dist/code-map-read.js +171 -0
- package/dist/code-map-report.d.ts +37 -0
- package/dist/code-map-report.js +95 -0
- package/dist/code-map-shape.d.ts +172 -0
- package/dist/code-map-shape.js +327 -0
- package/dist/code-map-store.d.ts +136 -0
- package/dist/code-map-store.js +233 -0
- package/dist/coding-provider.d.ts +2 -0
- package/dist/coding-provider.js +3 -2
- package/dist/coding-update.js +3 -2
- package/dist/coding-workspace.js +4 -4
- package/dist/console-chrome.js +2 -2
- package/dist/containment.d.ts +5 -0
- package/dist/containment.js +14 -1
- package/dist/contracts/chat-actions.d.ts +9 -0
- package/dist/contracts/chat-actions.js +2 -0
- package/dist/contracts/cli.d.ts +52 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +12 -5
- package/dist/contracts/console-api.js +12 -5
- package/dist/contracts/gateway-tools.d.ts +17 -0
- package/dist/contracts/gateway-tools.js +3 -1
- package/dist/contracts/lead-tools.d.ts +61 -0
- package/dist/contracts/lead-tools.js +10 -1
- package/dist/contracts/project-knowledge.d.ts +38 -5
- package/dist/contracts/project-knowledge.js +11 -5
- package/dist/contracts/project-memory.d.ts +3 -1
- package/dist/contracts/project-memory.js +3 -2
- package/dist/contracts/release-check.d.ts +25 -1
- package/dist/contracts/release-check.js +19 -0
- package/dist/contracts/storage.d.ts +14 -0
- package/dist/contracts/storage.js +3 -1
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/contracts/youiyoux-request.d.ts +1 -1
- package/dist/contracts/youiyoux-request.js +1 -1
- package/dist/desktop-access.js +6 -2
- package/dist/desktop-update.d.ts +2 -2
- package/dist/desktop-update.js +13 -9
- package/dist/dispatch.js +18 -15
- package/dist/dispose.js +8 -2
- package/dist/easy-start.js +2 -3
- package/dist/eval-hooks.d.ts +55 -0
- package/dist/eval-hooks.js +227 -4
- package/dist/evals.js +2 -1
- package/dist/fast-start.d.ts +136 -0
- package/dist/fast-start.js +431 -0
- package/dist/fast-terms.d.ts +9 -0
- package/dist/fast-terms.js +23 -0
- package/dist/fenced-check-coverage.d.ts +62 -0
- package/dist/fenced-check-coverage.js +54 -0
- package/dist/first-run.js +1 -1
- package/dist/flaky-ci.d.ts +31 -0
- package/dist/flaky-ci.js +149 -0
- package/dist/flaky-cli.d.ts +60 -0
- package/dist/flaky-cli.js +60 -0
- package/dist/flaky.d.ts +83 -0
- package/dist/flaky.js +264 -0
- package/dist/flow-card-task.js +3 -0
- package/dist/flow-triggers.d.ts +1 -1
- package/dist/flow-triggers.js +1 -1
- package/dist/github-import.d.ts +62 -0
- package/dist/github-import.js +146 -0
- package/dist/guides.js +15 -10
- package/dist/invoke.d.ts +5 -1
- package/dist/invoke.js +49 -14
- package/dist/job-object-helper.ps1 +10 -3
- package/dist/keymap.d.ts +41 -0
- package/dist/keymap.js +51 -0
- package/dist/knowledge-cli.js +1 -1
- package/dist/knowledge-ui.d.ts +21 -4
- package/dist/knowledge-ui.js +75 -7
- package/dist/laptop-background.d.ts +16 -0
- package/dist/laptop-background.js +108 -2
- package/dist/lead-context.js +1 -1
- package/dist/lead-contract.d.ts +1 -1
- package/dist/lead-contract.js +2 -2
- package/dist/lead-progress.js +3 -0
- package/dist/lead-status.d.ts +2 -0
- package/dist/lead-status.js +6 -2
- package/dist/lead-tools.js +51 -2
- package/dist/lead.js +1 -1
- package/dist/lesson-notes.d.ts +81 -0
- package/dist/lesson-notes.js +336 -0
- package/dist/limits-ui.js +1 -1
- package/dist/local-owner.d.ts +1 -1
- package/dist/local-owner.js +11 -0
- package/dist/machine-check.d.ts +16 -0
- package/dist/machine-check.js +26 -0
- package/dist/machine-identity.d.ts +75 -0
- package/dist/machine-identity.js +170 -0
- package/dist/mcp-core.js +11 -1
- package/dist/memory-cli.d.ts +300 -1
- package/dist/memory-cli.js +62 -9
- package/dist/memory-pass.d.ts +16 -0
- package/dist/memory-pass.js +67 -3
- package/dist/memory-tidy.d.ts +181 -0
- package/dist/memory-tidy.js +523 -0
- package/dist/memory-use.d.ts +35 -0
- package/dist/memory-use.js +109 -0
- package/dist/merge-checklist.d.ts +55 -0
- package/dist/merge-checklist.js +182 -0
- package/dist/needs-you.d.ts +32 -13
- package/dist/needs-you.js +108 -49
- package/dist/nightly-github.d.ts +2 -0
- package/dist/nightly-github.js +4 -4
- package/dist/operate-remote-arguments.js +6 -1
- package/dist/operate-remote.js +3 -1
- package/dist/operate.d.ts +6 -1
- package/dist/operate.js +540 -70
- package/dist/phase-routing.js +2 -2
- package/dist/plain-schema.d.ts +23 -0
- package/dist/plain-schema.js +94 -0
- package/dist/plain-words.d.ts +20 -0
- package/dist/plain-words.js +66 -0
- package/dist/planner.js +2 -1
- package/dist/process-liveness.d.ts +2 -0
- package/dist/process-liveness.js +61 -17
- package/dist/project-delete-ui.d.ts +7 -2
- package/dist/project-delete-ui.js +12 -1
- package/dist/project-delete.js +13 -2
- package/dist/project-knowledge.d.ts +18 -11
- package/dist/project-knowledge.js +39 -9
- package/dist/project-learning.d.ts +2 -1
- package/dist/project-learning.js +15 -45
- package/dist/project-memory.d.ts +5 -0
- package/dist/project-memory.js +22 -2
- package/dist/proof.js +30 -5
- package/dist/provider-auth.js +1 -1
- package/dist/publish.js +9 -1
- package/dist/pull-request-flow.js +5 -0
- package/dist/push.d.ts +26 -3
- package/dist/push.js +55 -15
- package/dist/release-adapters.d.ts +9 -0
- package/dist/release-adapters.js +87 -1
- package/dist/release-approval.d.ts +191 -0
- package/dist/release-approval.js +382 -0
- package/dist/release-auto.js +26 -17
- package/dist/release-card.d.ts +74 -6
- package/dist/release-card.js +179 -23
- package/dist/release-carry.d.ts +7 -2
- package/dist/release-carry.js +39 -9
- package/dist/release-cli.d.ts +4 -0
- package/dist/release-cli.js +38 -23
- package/dist/release-coverage.js +1 -1
- package/dist/release-next.d.ts +48 -0
- package/dist/release-next.js +161 -0
- package/dist/release.d.ts +50 -1
- package/dist/release.js +118 -11
- package/dist/remote-destination.d.ts +36 -0
- package/dist/remote-destination.js +217 -0
- package/dist/remote-main.d.ts +48 -0
- package/dist/remote-main.js +84 -5
- package/dist/repository-context.d.ts +3 -2
- package/dist/repository-context.js +112 -70
- package/dist/restart-certification.d.ts +1 -0
- package/dist/restart-certification.js +8 -6
- package/dist/result-acts.d.ts +29 -21
- package/dist/result-acts.js +36 -25
- package/dist/result-follow-ups.d.ts +2 -2
- package/dist/result-follow-ups.js +18 -4
- package/dist/result-review.d.ts +1 -1
- package/dist/route-change-check.d.ts +4 -0
- package/dist/route-change-check.js +13 -0
- package/dist/route-change.d.ts +22 -0
- package/dist/route-change.js +89 -0
- package/dist/route-hooks.js +3 -2
- package/dist/route-results.d.ts +6 -1
- package/dist/route-results.js +14 -5
- package/dist/run-closeout.d.ts +1 -1
- package/dist/run-closeout.js +7 -5
- package/dist/runner-process.js +3 -2
- package/dist/runner.js +2 -1
- package/dist/scope.d.ts +6 -1
- package/dist/scope.js +22 -9
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +24 -18
- package/dist/server/chat.js +14 -12
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +26 -35
- package/dist/server/console.css +23 -0
- package/dist/server/guards.js +4 -0
- package/dist/server/home.d.ts +6 -0
- package/dist/server/home.js +21 -13
- package/dist/server/http.js +1 -1
- package/dist/server/kit.js +1 -1
- package/dist/server/merge-ready-view.d.ts +10 -0
- package/dist/server/merge-ready-view.js +30 -0
- package/dist/server/pages-assets.d.ts +1 -0
- package/dist/server/pages-assets.js +8 -5
- package/dist/server/pages.js +103 -82
- package/dist/server/render-chat.js +2 -2
- package/dist/server/render-code-map.d.ts +30 -0
- package/dist/server/render-code-map.js +137 -0
- package/dist/server/render-flaky.d.ts +20 -0
- package/dist/server/render-flaky.js +59 -0
- package/dist/server/render-history.js +1 -1
- package/dist/server/render-new-task.d.ts +26 -1
- package/dist/server/render-new-task.js +30 -5
- package/dist/server/render-pages.d.ts +1 -175
- package/dist/server/render-pages.js +38 -313
- package/dist/server/render-projects.d.ts +2 -1
- package/dist/server/render-projects.js +9 -7
- package/dist/server/render-release.d.ts +19 -0
- package/dist/server/render-release.js +84 -0
- package/dist/server/render-results.d.ts +2 -2
- package/dist/server/render-results.js +71 -73
- package/dist/server/render-tasks.d.ts +13 -2
- package/dist/server/render-tasks.js +156 -139
- package/dist/server/retired-routes.d.ts +17 -0
- package/dist/server/retired-routes.js +53 -0
- package/dist/server/route-table.d.ts +4 -1
- package/dist/server/route-table.js +52 -13
- package/dist/server/settings.js +129 -22
- package/dist/server/task-views.js +61 -26
- package/dist/server/tasks.d.ts +17 -6
- package/dist/server/tasks.js +273 -338
- package/dist/server/welcome.js +1 -1
- package/dist/settings-groups-ui.js +1 -1
- package/dist/setup-guide.d.ts +2 -2
- package/dist/stop-proof.d.ts +67 -0
- package/dist/stop-proof.js +295 -0
- package/dist/storage-sweep-process.js +1 -1
- package/dist/storage-sweep.d.ts +5 -3
- package/dist/storage-sweep.js +30 -9
- package/dist/storage-ui.js +28 -17
- package/dist/storage.d.ts +27 -2
- package/dist/storage.js +39 -2
- package/dist/store.d.ts +148 -34
- package/dist/store.js +626 -177
- package/dist/surface.js +46 -5
- package/dist/sweep-quarantine.d.ts +1 -0
- package/dist/sweep-quarantine.js +6 -4
- package/dist/tamper-scan.d.ts +4 -0
- package/dist/tamper-scan.js +90 -0
- package/dist/task-aliases.d.ts +5 -0
- package/dist/task-aliases.js +9 -0
- package/dist/task-control.js +4 -1
- package/dist/task-outcome-cli.d.ts +2 -0
- package/dist/task-outcome-cli.js +36 -17
- package/dist/task-sizing.d.ts +5 -0
- package/dist/task-sizing.js +2 -0
- package/dist/task-source.d.ts +7 -0
- package/dist/task-source.js +14 -0
- package/dist/task-status.d.ts +9 -0
- package/dist/task-status.js +40 -49
- package/dist/teardown-git.d.ts +16 -0
- package/dist/teardown-git.js +63 -5
- package/dist/telegram-progress.js +5 -3
- package/dist/telegram-status.js +6 -4
- package/dist/test-infra.d.ts +8 -0
- package/dist/test-infra.js +18 -0
- package/dist/tidy.js +1 -1
- package/dist/toolroll-update-ui.js +2 -2
- package/dist/toolroll-update.js +18 -5
- package/dist/tui-contract.d.ts +24 -0
- package/dist/tui-source.js +67 -8
- package/dist/tui.js +51 -51
- package/dist/vanished-retry.d.ts +30 -0
- package/dist/vanished-retry.js +174 -0
- package/dist/work-index.d.ts +2 -0
- package/dist/work-index.js +82 -70
- package/dist/work-summary.d.ts +2 -2
- package/dist/work-summary.js +2 -0
- package/dist/workspace-ui.d.ts +4 -2
- package/dist/workspace-ui.js +28 -22
- package/dist/worktree.d.ts +12 -3
- package/dist/worktree.js +68 -13
- package/package.json +1 -1
- package/dist/server/render-next.d.ts +0 -63
- package/dist/server/render-next.js +0 -109
|
@@ -12,7 +12,7 @@ import { projectName } from "../project.js";
|
|
|
12
12
|
import { coverageStateWords, coverageWords, dispatchStatusToken, GOAL_ASSESSMENT_PENDING, manualReviewCriterionOf, manualReviewOnly, passFraction, personCheckWords, plainReasonWords, reviewConflict, semanticCoverage } from "../proof.js";
|
|
13
13
|
import {} from "../pull-request-flow.js";
|
|
14
14
|
import { qualityModeTitle } from "../quality.js";
|
|
15
|
-
import { acceptWithChecksOf, resultActsOf } from "../result-acts.js";
|
|
15
|
+
import { acceptWithChecksOf, resultActsOf, SEND_BACK_PUBLISHED, SEND_BACK_UNPUBLISHED } from "../result-acts.js";
|
|
16
16
|
import { SCREENSHOT_CAPTURE, structuredHandoffView, terminalDiffView } from "../result-evidence-readers.js";
|
|
17
17
|
import { ADD_TESTS_ACTION, followUpChecksOf } from "../result-follow-ups.js";
|
|
18
18
|
import { evidenceHealthOf, evidenceProblemDetailsOf, evidenceResultStatusOf, isRevisionFeedback, RESULT_REVIEW_SCRIPT, RESULT_TABS, resultFactsAttributeMap, resultLeadOf, revisionBatchOf, revisionSourceOf } from "../result-review.js";
|
|
@@ -89,7 +89,7 @@ export function repairChainHtml(chain) {
|
|
|
89
89
|
? `Stopped after ${chain.attempt} attempt${chain.attempt === 1 ? "" : "s"}`
|
|
90
90
|
: chain.outcome === "no-progress"
|
|
91
91
|
? "Stopped because two attempts made no progress"
|
|
92
|
-
: "Stopped because the
|
|
92
|
+
: "Stopped because what the build reported may not match the approved work";
|
|
93
93
|
const link = chain.draftTask === null ? "" : html ` <a href="${taskHref(chain.draftTask)}">${chain.draftTask}</a>`;
|
|
94
94
|
const details = chain.unresolved.length === 0
|
|
95
95
|
? ""
|
|
@@ -202,9 +202,9 @@ export function criterionMatrixHtml(matrix, options = {}) {
|
|
|
202
202
|
html `<p class="requirement-statement">${row.statement}</p>`,
|
|
203
203
|
review?.judgement === "upholds" && !confirmed ? html `<p class="requirement-review" data-review-judgement="upholds">Reviewer confirmed</p>` : "",
|
|
204
204
|
warnings,
|
|
205
|
-
html `<details class="requirement-evidence"><summary>
|
|
206
|
-
html `<p class="meta">Required: ${row.requiredEvidence.map(kind => kinds[kind]).join(", ") || "
|
|
207
|
-
answered.length === 0 ? html `<p class="meta">
|
|
205
|
+
html `<details class="requirement-evidence"><summary>How it was shown</summary><div class="requirement-evidence-body">`,
|
|
206
|
+
html `<p class="meta">Required: ${row.requiredEvidence.map(kind => kinds[kind]).join(", ") || "Nothing named"}</p>`,
|
|
207
|
+
answered.length === 0 ? html `<p class="meta">Nothing was saved to show this requirement.</p>` : groups,
|
|
208
208
|
state !== "pass" || detail.length === 0 ? "" : html `<div class="requirement-evidence-group"><strong>Verification notes</strong><ul>${detail.map(line => html `<li>${line}</li>`)}</ul></div>`,
|
|
209
209
|
reviewDetails,
|
|
210
210
|
coverage === undefined ? "" : html `<p class="meta"${coverage.state === "gap" ? "" : html ` data-context-coverage="${coverage.state}"`}>Review context: ${coverageStateWords(coverage)}</p>`,
|
|
@@ -264,18 +264,18 @@ export function reviewPriorityOf(row) {
|
|
|
264
264
|
const manual = ids(one => one.state === "manual-review");
|
|
265
265
|
const humanReview = manualReviewOnly({ verdict: row.proofVerdict ?? "", reasons: row.proofReasons ?? [], matrix: row.proofMatrix });
|
|
266
266
|
if (row.proofVerdict === "refuted") {
|
|
267
|
-
raise(row.proofAccepted ? 1 : 0, row.proofAccepted ? "
|
|
267
|
+
raise(row.proofAccepted ? 1 : 0, row.proofAccepted ? "the report doesn't match the changes — accepted with a reason" : "the report doesn't match the changes");
|
|
268
268
|
}
|
|
269
269
|
else if (humanReview) {
|
|
270
270
|
raise(1, row.proofAccepted ? "accepted after human review" : "human review needed");
|
|
271
271
|
}
|
|
272
272
|
else if (row.proofVerdict === "short") {
|
|
273
|
-
raise(row.proofAccepted ? 1 : 0, row.proofAccepted ? "
|
|
273
|
+
raise(row.proofAccepted ? 1 : 0, row.proofAccepted ? "not all requirements shown — accepted with a reason" : "not all requirements shown");
|
|
274
274
|
}
|
|
275
275
|
if (contradicted !== "")
|
|
276
276
|
raise(row.proofAccepted ? 1 : 0, `reviewer raised a concern with ${contradicted}`);
|
|
277
277
|
if (broken !== "")
|
|
278
|
-
raise(row.proofAccepted ? 1 : 0, `
|
|
278
|
+
raise(row.proofAccepted ? 1 : 0, `not shown, or shown failing, for ${broken}`);
|
|
279
279
|
if (row.ciFailing)
|
|
280
280
|
raise(0, "CI failing on its pull request — observed, not inferred");
|
|
281
281
|
if (row.publicationState === "failed")
|
|
@@ -458,7 +458,7 @@ export function verificationExplanation(verdict, reasons) {
|
|
|
458
458
|
return "Automatic recovery ran the approved setup, but Toolroll still couldn't start the project check.";
|
|
459
459
|
}
|
|
460
460
|
if (reason === "automatic recovery stopped because this worker no longer owned the build") {
|
|
461
|
-
return "Automatic recovery stopped because this
|
|
461
|
+
return "Automatic recovery stopped because this builder no longer had the build. Another builder can retry it safely.";
|
|
462
462
|
}
|
|
463
463
|
if (reason === "the approved verification command could not be run") {
|
|
464
464
|
return "Toolroll couldn't run the project check.";
|
|
@@ -488,11 +488,11 @@ export function verificationExplanation(verdict, reasons) {
|
|
|
488
488
|
if (verdict === "verified")
|
|
489
489
|
return "Toolroll independently verified this result.";
|
|
490
490
|
if (verdict === "attested")
|
|
491
|
-
return "The agent
|
|
491
|
+
return "The agent reported its own checks, but no project check could run to confirm them.";
|
|
492
492
|
if (verdict === "short")
|
|
493
|
-
return "Some approved requirements
|
|
493
|
+
return "Some approved requirements aren't shown yet.";
|
|
494
494
|
if (verdict === "refuted")
|
|
495
|
-
return "
|
|
495
|
+
return "What the build reported doesn't match its changes.";
|
|
496
496
|
return "No verification result is available for this build.";
|
|
497
497
|
}
|
|
498
498
|
export function verificationRecovered(reasons) {
|
|
@@ -592,30 +592,30 @@ export function reviewCockpitDetailParts(view, csrf, noted, canRetryReview, tab,
|
|
|
592
592
|
const intent = view.intent;
|
|
593
593
|
let intentView = null;
|
|
594
594
|
if (intent === null) {
|
|
595
|
-
parts.push(html `<section class="card cockpit-section" data-cockpit-section="intent"><h3>Approved
|
|
595
|
+
parts.push(html `<section class="card cockpit-section" data-cockpit-section="intent"><h3>Approved plan</h3><p class="meta">No plan was filed for this task, so there is no approved goal or boundary to review.</p></section>`);
|
|
596
596
|
}
|
|
597
597
|
else {
|
|
598
598
|
// The time itself goes to the page as a stamp: the one formatter words it in the viewer's zone.
|
|
599
599
|
const approvalWords = intent.approval.approved
|
|
600
|
-
? `Approved by ${intent.approvedBy ?? "an
|
|
600
|
+
? `Approved by ${intent.approvedBy ?? "an approver"}`
|
|
601
601
|
: intent.approval.reason === "changed"
|
|
602
|
-
? "
|
|
603
|
-
: "Never approved. The result was built without
|
|
602
|
+
? "Edited after approval. The words below are the current plan, not the approved one."
|
|
603
|
+
: "Never approved. The result was built without an approved plan.";
|
|
604
604
|
const approval = intent.approval.approved
|
|
605
|
-
? html `Approved by ${intent.approvedBy ?? "an
|
|
605
|
+
? html `Approved by ${intent.approvedBy ?? "an approver"} · ${whenTime(intent.approval.at)}`
|
|
606
606
|
: approvalWords;
|
|
607
607
|
const body = joinHtml([
|
|
608
608
|
html `<p class="recap" style="margin-top:.25rem"><strong>Goal</strong> ${intent.goal}</p>`,
|
|
609
609
|
intent.outOfScope === null ? html `<p class="meta">No boundary was stated</p>` : html `<p class="recap"><strong>Not this</strong> ${intent.outOfScope}</p>`,
|
|
610
610
|
intent.touches.length === 0
|
|
611
|
-
? html `<p class="meta">No
|
|
611
|
+
? html `<p class="meta">No files were named in the plan, so every changed file is in bounds</p>`
|
|
612
612
|
: html `<p class="row"><span class="meta">Expected to touch</span> ${joinHtml(intent.touches.map(one => html `<span class="mono">${one}</span>`), " ")}</p>`,
|
|
613
613
|
view.plan === null
|
|
614
614
|
? ""
|
|
615
|
-
: html `<p class="meta">Plan revision ${view.plan.revision} · <span class="mono"
|
|
615
|
+
: html `<p class="meta">Plan revision ${view.plan.revision} · <span class="mono">${view.plan.sha256.slice(0, 7)}</span>${view.plan.approach === null ? "" : ` — ${view.plan.approach}`}</p>`,
|
|
616
616
|
]);
|
|
617
617
|
intentView = { approval: approvalWords, approvedAt: intent.approval.approved ? intent.approval.at ?? null : null, html: htmlString(body) };
|
|
618
|
-
parts.push(html `<details class="card cockpit-section cockpit-disclosure" data-cockpit-section="intent"><summary><h3>Approved
|
|
618
|
+
parts.push(html `<details class="card cockpit-section cockpit-disclosure" data-cockpit-section="intent"><summary><h3>Approved plan<small>What this build was asked to do · ${approval}</small></h3><span class="cockpit-disclosure-action">View</span></summary><div class="cockpit-disclosure-body">${body}</div></details>`);
|
|
619
619
|
}
|
|
620
620
|
const selected = {
|
|
621
621
|
taskId: view.taskId, title: view.title, project: view.repo === null ? null : projectName(view.repo), build: run === null ? null : run.id,
|
|
@@ -631,8 +631,8 @@ export function reviewCockpitDetailParts(view, csrf, noted, canRetryReview, tab,
|
|
|
631
631
|
// The raw run record lives under Details now (2026-10-02): /r/<id> for this result redirects here.
|
|
632
632
|
record: run === null ? null : { build: run.id, href: `/r/${run.id}?record=1`, facts: [
|
|
633
633
|
{ label: "Agent", value: [run.provider, run.model].filter(Boolean).join(" · ") },
|
|
634
|
-
{ label: "
|
|
635
|
-
...(view.
|
|
634
|
+
{ label: "Builder", value: run.runner },
|
|
635
|
+
...(view.checkRan === undefined || view.checkRan === null ? [] : [{ label: "Checks", value: view.checkRan }]),
|
|
636
636
|
...(run.branch === null ? [] : [{ label: "Branch", value: run.branch }]),
|
|
637
637
|
...(run.finishedAt === null ? [] : [{ label: "Finished", value: when(run.finishedAt) }]),
|
|
638
638
|
...(run.ranMinutes === null ? [] : [{ label: "Ran", value: `${run.ranMinutes} min` }]),
|
|
@@ -660,7 +660,7 @@ export function reviewCockpitDetailParts(view, csrf, noted, canRetryReview, tab,
|
|
|
660
660
|
if (checks !== undefined)
|
|
661
661
|
parts.push(html `<p class="${checks.status === "failed" || checks.status === "unavailable" ? "problem" : "meta"}" data-actual-checks="${checks.status}">${checks.status === "unavailable" && saved.cause === "command-changed" ? CHECK_COMMAND_CHANGED : html `${checks.status === "unavailable" && saved.status !== "unavailable" ? `${CHECK_UNREADABLE} ` : ""}${checks.detail}`}${checks.logArtifactId === null ? "" : html ` <a href="/r/${run.id}/evidence/${checks.logArtifactId}">Open check output</a>`}</p>`);
|
|
662
662
|
if (assignment?.completion != null)
|
|
663
|
-
parts.push(html `<p class="meta" data-result-completed>
|
|
663
|
+
parts.push(html `<p class="meta" data-result-completed>Accepted by ${assignment.completion.actor.replace(/^operator:/, "")}.</p>`);
|
|
664
664
|
const panel = resultPanelParts(view.detail, {
|
|
665
665
|
place: "review",
|
|
666
666
|
tab,
|
|
@@ -706,7 +706,7 @@ export function reviewCockpitDetailParts(view, csrf, noted, canRetryReview, tab,
|
|
|
706
706
|
proof: proof !== null && proof.proof !== null && proof.proofProblem === null,
|
|
707
707
|
});
|
|
708
708
|
// Refuted: plain Accept and finish stays as allowed, in outline, and the one line before the acts (acts.line) says why.
|
|
709
|
-
const settled = base === null || blocked === null ? base : { ...base, label: "Accept
|
|
709
|
+
const settled = base === null || blocked === null ? base : { ...base, label: "Accept", ready: false };
|
|
710
710
|
const decision = settled === null ? null : { sentence: RESULT_DECISION_SENTENCE, ...settled, ...acceptWithChecksOf(settled, { unanswered, notRight: [] }),
|
|
711
711
|
base: { label: settled.label, ready: settled.ready, why: settled.why } };
|
|
712
712
|
// Run checks: no check ran on this result (or its saved one can't be read), the project has one, and an approver may run it.
|
|
@@ -731,7 +731,7 @@ export function reviewCockpitDetailParts(view, csrf, noted, canRetryReview, tab,
|
|
|
731
731
|
checksRunning,
|
|
732
732
|
blocked,
|
|
733
733
|
canRequest: panel.panel.canRequest && panel.panel.request !== null,
|
|
734
|
-
need: need === null || need.accept != null ? null : need.rebuild != null ? "rebuild" : need.confirm !== null ? "
|
|
734
|
+
need: need === null || need.accept != null ? null : need.rebuild != null ? "rebuild" : need.confirm !== null ? "recheck-stopped" : null,
|
|
735
735
|
next: nextKind === "revise" || nextKind === "draft-repair" ? nextKind : null,
|
|
736
736
|
unanswered: settled === null ? 0 : unanswered.length,
|
|
737
737
|
notRight: 0,
|
|
@@ -812,9 +812,9 @@ export function completionForm(taskId, runId, digest, pullRequestTo = null, acce
|
|
|
812
812
|
const options = { attrs: { class: "card result-complete" }, hidden: { receipt: digest, run: runId, accept: accept === null ? null : "1" } };
|
|
813
813
|
if (pullRequestTo !== null) {
|
|
814
814
|
// With pull requests set up: the PR is the primary road, a bare finish the quiet one beside it.
|
|
815
|
-
return postForm(`${taskHref(taskId)}/complete`, html `${reason}<p class="meta">Finishes the task. A pull request opens on ${pullRequestTo} from this exact commit when you ask for one.</p><div class="result-complete-actions"><button type="submit" name="publish" value="1" style="min-height:44px">
|
|
815
|
+
return postForm(`${taskHref(taskId)}/complete`, html `${reason}<p class="meta">Finishes the task. A pull request opens on ${pullRequestTo} from this exact commit when you ask for one.</p><div class="result-complete-actions"><button type="submit" name="publish" value="1" style="min-height:44px">Accept and open a pull request</button><button type="submit" class="secondary" style="min-height:44px">Accept</button></div>`, options);
|
|
816
816
|
}
|
|
817
|
-
return postForm(`${taskHref(taskId)}/complete`, html `${reason}<p class="meta">Finishes the task. Checks stay unchanged; nothing is published or deployed.</p><button type="submit" style="min-height:44px">Accept
|
|
817
|
+
return postForm(`${taskHref(taskId)}/complete`, html `${reason}<p class="meta">Finishes the task. Checks stay unchanged; nothing is published or deployed.</p><button type="submit" style="min-height:44px">Accept</button>`, options);
|
|
818
818
|
}
|
|
819
819
|
/** The pull request, in one card: its state and link, one line of detail, and the one action it needs — Merge
|
|
820
820
|
* behind the password when checks passed, or Open a pull request for a result completed without one. */
|
|
@@ -854,13 +854,13 @@ function reviewNextActionParts(view, csrf, back) {
|
|
|
854
854
|
const detail = view.detail;
|
|
855
855
|
const card = (kind, title, detailWords, control) => ({ kind, title, detail: detailWords, control });
|
|
856
856
|
if (run === null || detail === null) {
|
|
857
|
-
return card("inspect-task", "No build to review", "This task was
|
|
857
|
+
return card("inspect-task", "No build to review", "This task was accepted without a build record.", html `<a class="button-link" href="${taskHref(view.taskId)}">Open the task</a>`);
|
|
858
858
|
}
|
|
859
859
|
if (detail.ciFailing && csrf !== "") {
|
|
860
|
-
return card("draft-repair", "CI is failing on its pull request",
|
|
860
|
+
return card("draft-repair", "CI is failing on its pull request", `Toolroll confirmed the failure. ${SEND_BACK_PUBLISHED}`, postForm(`/r/${run.id}/draft-repair`, html `<button type="submit">Send back</button>`));
|
|
861
861
|
}
|
|
862
862
|
if (detail.comments.length > 0 && csrf !== "") {
|
|
863
|
-
return card("revise", `${detail.comments.length} note${detail.comments.length === 1 ? "" : "s"} ready`,
|
|
863
|
+
return card("revise", `${detail.comments.length} note${detail.comments.length === 1 ? "" : "s"} ready`, SEND_BACK_UNPUBLISHED, postForm(`/r/${run.id}/revise`, html `${revisionSealFields(detail.comments, detail.sourceDigest)}<button type="submit">Send back</button>`, { returnTo: back ?? reviewHref(view.taskId) }));
|
|
864
864
|
}
|
|
865
865
|
return null;
|
|
866
866
|
}
|
|
@@ -872,8 +872,8 @@ function reviewNextActionParts(view, csrf, back) {
|
|
|
872
872
|
export const PHASE_WORDS = {
|
|
873
873
|
"agent-running": "agent working",
|
|
874
874
|
"validating-handoff": "checking the handoff",
|
|
875
|
-
"correcting-proof": "correcting
|
|
876
|
-
"capturing-evidence": "
|
|
875
|
+
"correcting-proof": "correcting its report",
|
|
876
|
+
"capturing-evidence": "saving its files",
|
|
877
877
|
committing: "committing",
|
|
878
878
|
};
|
|
879
879
|
/** An agent's phase on the home card, from the machine's own vocabulary. */
|
|
@@ -884,8 +884,8 @@ export function homePhaseWords(run) {
|
|
|
884
884
|
return "Reviewing";
|
|
885
885
|
if (run.role === "scout")
|
|
886
886
|
return "Investigating";
|
|
887
|
-
const words = { "agent-running": "Writing the change", "validating-handoff": "Checking its handoff", "capturing-evidence": "Saving its
|
|
888
|
-
committing: "Committing", "verifying-proof": "Running the checks", "correcting-proof": "Correcting its
|
|
887
|
+
const words = { "agent-running": "Writing the change", "validating-handoff": "Checking its handoff", "capturing-evidence": "Saving its files",
|
|
888
|
+
committing: "Committing", "verifying-proof": "Running the checks", "correcting-proof": "Correcting its report" };
|
|
889
889
|
return run.phase === null ? "Starting" : words[run.phase] ?? "Working";
|
|
890
890
|
}
|
|
891
891
|
export function phaseWords(phase) {
|
|
@@ -901,7 +901,7 @@ export const INCIDENT_WORDS = {
|
|
|
901
901
|
"commit-failure": "the commit failed",
|
|
902
902
|
"malformed-plan": "the plan was malformed",
|
|
903
903
|
"plan-attempts-exhausted": "planning failed too many times",
|
|
904
|
-
"malformed-report": "the
|
|
904
|
+
"malformed-report": "the research report was malformed",
|
|
905
905
|
};
|
|
906
906
|
export function incidentWords(kind) {
|
|
907
907
|
return INCIDENT_WORDS[kind] ?? "something went wrong — the run records have the detail";
|
|
@@ -917,11 +917,11 @@ export const EVIDENCE_WORDS = {
|
|
|
917
917
|
handoff: "Agent handoff",
|
|
918
918
|
"revision-brief": "Revision brief",
|
|
919
919
|
report: "Report",
|
|
920
|
-
proof: "Agent
|
|
920
|
+
proof: "Agent report",
|
|
921
921
|
"check-log": "Check log",
|
|
922
922
|
screenshot: "Screenshot",
|
|
923
923
|
"structured-output": "Agent response",
|
|
924
|
-
"plan-contract": "
|
|
924
|
+
"plan-contract": "Your request",
|
|
925
925
|
"review-context": "Review context",
|
|
926
926
|
};
|
|
927
927
|
/** Byte counts as people read them. */
|
|
@@ -1012,7 +1012,7 @@ export function sharedResultFactsOf(run, proof, terminal, handoff, report, publi
|
|
|
1012
1012
|
runId: run.id,
|
|
1013
1013
|
base: statOk ? stat.base : run.baseRevision,
|
|
1014
1014
|
head: statOk ? stat.head : run.headRevision,
|
|
1015
|
-
headSource: statOk ? "
|
|
1015
|
+
headSource: statOk ? "saved diff" : run.headRevision === null ? null : "build record",
|
|
1016
1016
|
checks: passed === null ? null : { passed: passed.passed, total: passed.total },
|
|
1017
1017
|
caveats: proof?.proof?.caveats ?? [],
|
|
1018
1018
|
evidenceProblems: evidenceProblems.map(one => one.words),
|
|
@@ -1285,8 +1285,8 @@ export function reviewDiffHtml(patch, stat, runId, commentable, anchors = new Ma
|
|
|
1285
1285
|
return html `<div class="diff-review" data-review-diff>${commentable
|
|
1286
1286
|
? html `<div class="diff-review-bar"><span class="meta">${parsed.files.length} changed file${parsed.files.length === 1 ? "" : "s"}</span><div class="diff-modes" role="group" aria-label="diff mode"><button type="button" data-diff-mode="view" aria-pressed="true">View</button><button type="button" data-diff-mode="annotate" aria-pressed="false">Annotate</button></div></div><p class="diff-review-help">Select a line, then describe what should change. Nothing is revised until you create the revision below.</p>`
|
|
1287
1287
|
: ""}${files}${patch.truncated
|
|
1288
|
-
? html `<p class="diff-cut">The
|
|
1289
|
-
: parsed.linesTruncated ? html `<p class="diff-cut">This visual diff is shortened. Review the
|
|
1288
|
+
? html `<p class="diff-cut">The saved diff was shortened when it was stored: the rest of the change was never captured, here or in the download.</p>`
|
|
1289
|
+
: parsed.linesTruncated ? html `<p class="diff-cut">This visual diff is shortened. Review the saved patch before approving.</p>` : ""}</div>${storedDownloadLink(runId, patch.artifactId, "diff", patch.truncated)}`;
|
|
1290
1290
|
}
|
|
1291
1291
|
/** The check log as stored (repair 2026-09-14): its output behind a
|
|
1292
1292
|
* disclosure when the bytes verify — a shortened log says so in the
|
|
@@ -1366,7 +1366,7 @@ export function evidenceBundleCard(view, run, publication = null, review = null)
|
|
|
1366
1366
|
if (view === null)
|
|
1367
1367
|
return html ``;
|
|
1368
1368
|
const runId = run.id;
|
|
1369
|
-
const parts = [html `<h2>
|
|
1369
|
+
const parts = [html `<h2>Checks and saved files</h2>`];
|
|
1370
1370
|
if (view.verdict !== null) {
|
|
1371
1371
|
// The same status line every other surface renders for this run
|
|
1372
1372
|
// (workspace package 1), beside the verdict's own explanation.
|
|
@@ -1380,7 +1380,7 @@ export function evidenceBundleCard(view, run, publication = null, review = null)
|
|
|
1380
1380
|
parts.push(criterionMatrixHtml(view.matrix, { runId, links: view.matrixLinks, verdict: view.verdict }));
|
|
1381
1381
|
parts.push(semanticCoverageHtml(view.matrix, view.qualityMode));
|
|
1382
1382
|
if (reviewConflict(view.matrix, view.machineVerdict, view.verdict)) {
|
|
1383
|
-
parts.push(html `<p class="meta">An independent review found
|
|
1383
|
+
parts.push(html `<p class="meta">An independent review found the report doesn't match the changes.</p>`);
|
|
1384
1384
|
}
|
|
1385
1385
|
parts.push(repairChainHtml(view.repairChain));
|
|
1386
1386
|
if (view.proofProblem !== null) {
|
|
@@ -1395,7 +1395,7 @@ export function evidenceBundleCard(view, run, publication = null, review = null)
|
|
|
1395
1395
|
parts.push(html `<div class="result-section"><strong>Checks reported by the agent</strong><ul>${view.proof.checks.map(one => html `<li><span class="mono">${one.command}</span> <span class="meta">(exit ${one.exitCode}) — ${one.summary}</span></li>`)}</ul></div>`);
|
|
1396
1396
|
}
|
|
1397
1397
|
if (view.proof.caveats.length > 0) {
|
|
1398
|
-
parts.push(html `<div class="result-section"><strong>
|
|
1398
|
+
parts.push(html `<div class="result-section"><strong>Limitations the agent noted</strong><ul>${view.proof.caveats.map(one => html `<li>${one}</li>`)}</ul></div>`);
|
|
1399
1399
|
}
|
|
1400
1400
|
}
|
|
1401
1401
|
if (view.checkLog !== null)
|
|
@@ -1422,7 +1422,7 @@ export function followUpsFor(store, evidenceRoot, run, now) {
|
|
|
1422
1422
|
return { repo, checks: followUpChecksOf(store, run.id, now, evidenceRoot), testsTask: tests === undefined ? null : String(tests["outcome"]),
|
|
1423
1423
|
quick: repo !== null && liveQuickCommand(store, repo) !== null, full: repo !== null && store.liveVerifyCommand(repo) !== null };
|
|
1424
1424
|
}
|
|
1425
|
-
export const FOLLOW_UP_WORDS = { waiting: "waiting for a
|
|
1425
|
+
export const FOLLOW_UP_WORDS = { waiting: "waiting for a builder", running: "running", passed: "passed", failed: "failed", "not-run": "didn't run" };
|
|
1426
1426
|
/** Run checks and Add tests, under the result's Checks: what ran since, then the two acts. */
|
|
1427
1427
|
export function followUpsHtml(followUps, runId, o) {
|
|
1428
1428
|
// A batch check names every result it ran with and the exact commit it tested (batch-checks.ts).
|
|
@@ -1520,9 +1520,9 @@ export function completionReceiptCard(view, taskId, place, standing = receiptSta
|
|
|
1520
1520
|
inReview ? html `<details class="receipt-history"><summary>Review history</summary><p class="receipt-review meta" data-receipt-review="${status.token}">${status.detail}</p></details>` : "",
|
|
1521
1521
|
// The matrix count is the proof's own citation; it reads as verified
|
|
1522
1522
|
// only when the machine verified the result (workspace package 1).
|
|
1523
|
-
html `<div class="receipt-facts"><span><strong>${criteria}</strong><small>${stored.tone === "problem" ? html `the agent's own
|
|
1524
|
-
html `<span><strong>${diff}</strong><small>${facts.head === null ? "no commit recorded" : `head ${facts.head.slice(0,
|
|
1525
|
-
html `<span><strong>${view.screenshots.length} screenshot${view.screenshots.length === 1 ? "" : "s"}</strong><small>${view.screenshots.length === 0 ? "none required or captured" : unavailable === 0 ? "
|
|
1523
|
+
html `<div class="receipt-facts"><span><strong>${criteria}</strong><small>${stored.tone === "problem" ? html `the agent's own word — not checked` : stored.token === "agent-attested" ? html `the agent's own word, no project check` : "against the approved plan"}</small></span>`,
|
|
1524
|
+
html `<span><strong>${diff}</strong><small>${facts.head === null ? "no commit recorded" : `head ${facts.head.slice(0, 7)} · ${facts.headSource ?? ""}`}</small></span>`,
|
|
1525
|
+
html `<span><strong>${view.screenshots.length} screenshot${view.screenshots.length === 1 ? "" : "s"}</strong><small>${view.screenshots.length === 0 ? "none required or captured" : unavailable === 0 ? "checked screenshots" : `${unavailable} unavailable — not validated`}</small></span></div>`,
|
|
1526
1526
|
html `<div class="receipt-actions">`,
|
|
1527
1527
|
place === "task"
|
|
1528
1528
|
? html `<a href="${taskChatHref(taskId)}">Discuss in chat →</a>`
|
|
@@ -1684,7 +1684,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1684
1684
|
summaryParts.push(html `<p class="result-files-lead">${detail.files.length === 0 ? "" : html `${joinHtml(detail.files.slice(0, 6).map(one => html `<span class="mono">${one.path}</span>`), ", ")}${detail.files.length > 6 ? ` and ${detail.files.length - 6} more` : ""} — `}<a href="${tabHref("changes")}" data-result-goto="changes">see the diff</a></p>`);
|
|
1685
1685
|
}
|
|
1686
1686
|
if (lead === "summary" && run.outcome === "no-change")
|
|
1687
|
-
summaryParts.push(html `<p class="meta">The agent found that no repository change was needed${statOk && stat.fileCount === 0 ? "; the
|
|
1687
|
+
summaryParts.push(html `<p class="meta">The agent found that no repository change was needed${statOk && stat.fileCount === 0 ? "; the saved diff is empty" : ""}.</p>`);
|
|
1688
1688
|
// The agent's own account — its full conclusion (when the outcome line
|
|
1689
1689
|
// shortened it), what it says it changed, and how it checked — on demand.
|
|
1690
1690
|
const agentAccount = [
|
|
@@ -1702,8 +1702,8 @@ export function resultPanelParts(detail, o) {
|
|
|
1702
1702
|
}
|
|
1703
1703
|
const evidenceSources = [
|
|
1704
1704
|
...(report !== null ? [report.ok ? `verified report${report.truncated ? " (shortened)" : ""}` : "report (unverifiable)"] : []),
|
|
1705
|
-
...(patch !== null ? [patchOk ? `
|
|
1706
|
-
...(proof === null ? [] : proof.proofProblem !== null ? ["
|
|
1705
|
+
...(patch !== null ? [patchOk ? `saved diff${patch.truncated ? " (shortened)" : ""}` : "diff (can't be checked)"] : []),
|
|
1706
|
+
...(proof === null ? [] : proof.proofProblem !== null ? ["agent report (unreadable)"] : proof.proof !== null ? ["agent report"] : []),
|
|
1707
1707
|
...(proof?.checkLog !== null && proof?.checkLog !== undefined ? [proof.checkLog.problem !== null ? "check log (unverifiable)" : `check log${proof.checkLog.truncated ? " (shortened)" : ""}`] : []),
|
|
1708
1708
|
...(shots.length > 0 ? [`${shown.length} validated screenshot${shown.length === 1 ? "" : "s"}${unavailableShots.length > 0 ? `, ${unavailableShots.length} unavailable` : ""}`] : []),
|
|
1709
1709
|
];
|
|
@@ -1728,9 +1728,9 @@ export function resultPanelParts(detail, o) {
|
|
|
1728
1728
|
html `<div><dt>Build</dt><dd>#${runId} · ${run.runner}${agent === null ? ` · ${run.provider}` : ""}${run.finishedAt === null ? "" : html ` · ${whenTime(run.finishedAt)}`}</dd></div>`,
|
|
1729
1729
|
agent === null ? "" : html `<div><dt>Agent</dt><dd>${agent}</dd></div>`,
|
|
1730
1730
|
html `<div><dt>Commits</dt><dd>${facts.head === null
|
|
1731
|
-
? facts.base === null ? "no commit recorded" : html `<span class="mono">${facts.base.slice(0,
|
|
1732
|
-
: html `<span class="mono">${facts.base === null ? "" : `${facts.base.slice(0,
|
|
1733
|
-
html `<div><dt>
|
|
1731
|
+
? facts.base === null ? "no commit recorded" : html `<span class="mono">${facts.base.slice(0, 7)}</span> <span class="meta">base · no head recorded</span>`
|
|
1732
|
+
: html `<span class="mono">${facts.base === null ? "" : `${facts.base.slice(0, 7)} → `}${facts.head.slice(0, 7)}</span> <span class="meta">from the ${facts.headSource ?? "record"}</span>`}</dd></div>`,
|
|
1733
|
+
html `<div><dt>Saved files</dt><dd>${evidenceSources.length === 0 ? "nothing was captured" : evidenceSources.join(" · ")}</dd></div>`,
|
|
1734
1734
|
html `<div><dt>Publication</dt><dd>${publicationHtml}</dd></div>`,
|
|
1735
1735
|
html `</dl>`,
|
|
1736
1736
|
html `<p class="result-links meta">${links}</p>`,
|
|
@@ -1747,7 +1747,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1747
1747
|
else if (!statOk)
|
|
1748
1748
|
changeParts.push(html `<p class="problem">Change summary unavailable: ${stat.problem}.</p>`);
|
|
1749
1749
|
else {
|
|
1750
|
-
changeParts.push(html `<p class="row result-stat"><span class="mono">${stat.base.slice(0,
|
|
1750
|
+
changeParts.push(html `<p class="row result-stat"><span class="mono">${stat.base.slice(0, 7)} → ${stat.head.slice(0, 7)}</span> — ${stat.fileCount === 0
|
|
1751
1751
|
? "no changes, verified"
|
|
1752
1752
|
: `${stat.fileCount} file${stat.fileCount === 1 ? "" : "s"} · +${stat.additions} −${stat.deletions}${stat.binaryCount > 0 ? ` · ${stat.binaryCount} binary` : ""}${stat.filesTruncated ? " · file list cut, counts complete" : ""}`}</p>`);
|
|
1753
1753
|
}
|
|
@@ -1784,10 +1784,10 @@ export function resultPanelParts(detail, o) {
|
|
|
1784
1784
|
if (proof === null && reviewerNotes.length > 0)
|
|
1785
1785
|
checkParts.push(html `<div class="result-section" data-cockpit-source="reviewer"><strong>Previous assessment</strong><ul>${reviewerNotes}</ul></div>`);
|
|
1786
1786
|
if (run.outcome === "no-change" && !directAssessment)
|
|
1787
|
-
checkParts.push(html `<p class="meta">The build concluded that no repository change was needed.
|
|
1787
|
+
checkParts.push(html `<p class="meta">The build concluded that no repository change was needed. With no change, its handoff and the saved diff are the record.</p>`);
|
|
1788
1788
|
if (proof === null) {
|
|
1789
1789
|
if (run.outcome !== "no-change")
|
|
1790
|
-
checkParts.push(html `<p class="meta" data-proof-verdict="none">This build has no
|
|
1790
|
+
checkParts.push(html `<p class="meta" data-proof-verdict="none">This build has no check result or saved files. Review its changes yourself.</p>`);
|
|
1791
1791
|
}
|
|
1792
1792
|
else {
|
|
1793
1793
|
if (proof.verdict !== null && !directAssessment) {
|
|
@@ -1806,7 +1806,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1806
1806
|
if (proof.accepted !== null)
|
|
1807
1807
|
checkParts.push(html `<p class="meta">${humanReview ? "Accepted after human review" : "Accepted with an exception"} by <span class="mono">${proof.accepted.by}</span> · ${whenTime(proof.accepted.at)}${proof.accepted.note === null ? "" : ` — ${proof.accepted.note}`}</p>`);
|
|
1808
1808
|
if (proof.matrix.length === 0) {
|
|
1809
|
-
checkParts.push(detail.signedCriteria > 0 ? html `<p class="meta">The approved
|
|
1809
|
+
checkParts.push(detail.signedCriteria > 0 ? html `<p class="meta">The approved plan has ${detail.signedCriteria} requirement${detail.signedCriteria === 1 ? "" : "s"}, but this build wasn't checked requirement by requirement.</p>` : html `<p class="meta">This plan names no requirements to check.</p>`);
|
|
1810
1810
|
}
|
|
1811
1811
|
else {
|
|
1812
1812
|
checkParts.push(criterionMatrixHtml(proof.matrix, { runId, links: proof.matrixLinks, fileAnchors: detail.fileAnchors, verdict: proof.verdict,
|
|
@@ -1814,7 +1814,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1814
1814
|
}
|
|
1815
1815
|
checkParts.push(semanticCoverageHtml(proof.matrix, proof.qualityMode));
|
|
1816
1816
|
if (reviewConflict(proof.matrix, proof.machineVerdict, proof.verdict))
|
|
1817
|
-
checkParts.push(html `<p class="meta">An independent review found
|
|
1817
|
+
checkParts.push(html `<p class="meta">An independent review found the report doesn't match the changes.</p>`);
|
|
1818
1818
|
checkParts.push(repairChainHtml(proof.repairChain));
|
|
1819
1819
|
if (detail.reviewerFindings.length > 0) {
|
|
1820
1820
|
checkParts.push(html `<div class="result-section" data-cockpit-source="reviewer"><strong>Independent review</strong><ul>${reviewerNotes}</ul></div>`);
|
|
@@ -1832,8 +1832,8 @@ export function resultPanelParts(detail, o) {
|
|
|
1832
1832
|
? html `<p class="meta" data-cockpit-source="screenshots">${shown.length} validated screenshot${shown.length === 1 ? "" : "s"} shown in Summary${unavailableShots.length > 0 ? `; ${unavailableShots.length} unavailable` : ""}.</p>`
|
|
1833
1833
|
: html `<details class="cockpit-proof-group" data-cockpit-source="screenshots"><summary>Screenshots · ${shown.length}${unavailableShots.length > 0 ? ` (${unavailableShots.length} unavailable)` : ""}</summary><div class="receipt-visuals" aria-label="validated screenshots">${shown.map(picture)}</div></details>`);
|
|
1834
1834
|
checkParts.push(receipt.caveats.length === 0
|
|
1835
|
-
? directAssessment ? html `` : html `<p class="meta" data-cockpit-source="caveats">
|
|
1836
|
-
: html `<details class="cockpit-proof-group" data-cockpit-source="caveats"><summary>
|
|
1835
|
+
? directAssessment ? html `` : html `<p class="meta" data-cockpit-source="caveats">The agent noted no limitations.</p>`
|
|
1836
|
+
: html `<details class="cockpit-proof-group" data-cockpit-source="caveats"><summary>Limitations the agent noted · ${receipt.caveats.length}</summary><ul>${receipt.caveats.map(one => html `<li>${one}</li>`)}</ul></details>`);
|
|
1837
1837
|
}
|
|
1838
1838
|
if (followUps !== null && run.role === "builder")
|
|
1839
1839
|
checkParts.push(followUpsHtml(followUps, runId, o));
|
|
@@ -1863,7 +1863,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1863
1863
|
if (detail.comments.length > 0) {
|
|
1864
1864
|
requestParts.push(html `<p class="meta">Saved for later · ${detail.comments.length}</p><div class="diff-comments" data-result-notes="${detail.comments.length}">${detail.comments.map(one => html `<div class="diff-comment">${imageNote(one)}<span class="diff-comment-pin" aria-hidden="true"></span><p>${one.path === null ? "" : pathWords(one.path, one.line)}${one.note}</p><span class="meta">${one.author} · ${whenTime(one.createdAt)}</span></div>`)}</div>`);
|
|
1865
1865
|
if (o.csrf !== "" && !detail.canAnnotate) {
|
|
1866
|
-
requestParts.push(postForm(`/r/${runId}/revise`, html `${revisionSealFields(detail.comments, detail.sourceDigest)}<div><strong>${detail.comments.length} note${detail.comments.length === 1 ? "" : "s"} ready</strong></div><button type="submit">
|
|
1866
|
+
requestParts.push(postForm(`/r/${runId}/revise`, html `${revisionSealFields(detail.comments, detail.sourceDigest)}<div><strong>${detail.comments.length} note${detail.comments.length === 1 ? "" : "s"} ready</strong></div><button type="submit">Send back</button>`, { attrs: { class: "card revision-from-comments" }, returnTo: o.returnTo }));
|
|
1867
1867
|
}
|
|
1868
1868
|
}
|
|
1869
1869
|
if ((detail.pastComments?.length ?? 0) > 0) {
|
|
@@ -1875,10 +1875,10 @@ export function resultPanelParts(detail, o) {
|
|
|
1875
1875
|
requestParts.push(html `<p class="result-revision" data-result-revision="${revision.id}" data-result-revision-approved="${revision.approved ? "1" : "0"}" data-tone="${revision.tone}"><strong>Revision</strong> <a href="${taskHref(revision.id)}">${revision.title}</a> <span class="meta">· ${revision.standing}</span></p>`);
|
|
1876
1876
|
}
|
|
1877
1877
|
if (o.csrf === "") {
|
|
1878
|
-
requestParts.push(html `<p class="meta">Sign in with a browser session to
|
|
1878
|
+
requestParts.push(html `<p class="meta">Sign in with a browser session to send it back.</p>`);
|
|
1879
1879
|
}
|
|
1880
1880
|
else if (!detail.canAnnotate) {
|
|
1881
|
-
requestParts.push(html `<p class="meta" data-result-feedback="unavailable">${terminal === null ? "This result has no
|
|
1881
|
+
requestParts.push(html `<p class="meta" data-result-feedback="unavailable">${terminal === null ? "This result has no saved diff to attach notes to." : "The saved diff no longer checks out, so notes can't attach to it."} <a href="${taskChatHref(detail.rootId ?? detail.taskId)}">Discuss in chat →</a></p>`);
|
|
1882
1882
|
}
|
|
1883
1883
|
else {
|
|
1884
1884
|
requestParts.push(html `<details class="result-request-open result-request-form"${detail.comments.length > 0 ? " open" : ""}><summary>What should change?</summary>${postForm(`/r/${runId}/comment`, joinHtml([
|
|
@@ -1890,7 +1890,7 @@ export function resultPanelParts(detail, o) {
|
|
|
1890
1890
|
html `<details class="result-pin"><summary>Attach to a file or line</summary>`,
|
|
1891
1891
|
html `<div class="diff-comment-target"><label>File<input type="text" name="path" placeholder="src/…" aria-label="file" class="mono"></label>`,
|
|
1892
1892
|
html `<label>Line<input type="text" name="line" placeholder="—" aria-label="line" inputmode="numeric"></label></div></details>`,
|
|
1893
|
-
html `<div class="result-feedback-actions"><button type="submit" name="intent" value="revise" data-request-changes>
|
|
1893
|
+
html `<div class="result-feedback-actions"><button type="submit" name="intent" value="revise" data-request-changes>Send back</button><button type="submit" name="intent" value="note" class="quiet" data-save-feedback>Save for later</button></div>`,
|
|
1894
1894
|
]), { attrs: { class: "diff-comment-form", id: "comment-form" }, returnTo: o.returnTo, hidden: { tab: o.tab, request: o.requestToken } })}</details>`);
|
|
1895
1895
|
}
|
|
1896
1896
|
// ---- the panel ---------------------------------------------------------
|
|
@@ -2009,12 +2009,10 @@ export function needActionOf(assignment, status, csrf, returnTo, result) {
|
|
|
2009
2009
|
if (status.need.key === "review-result" || here)
|
|
2010
2010
|
return null;
|
|
2011
2011
|
}
|
|
2012
|
-
const confirm = action?.code === "
|
|
2013
|
-
? { action: `${taskHref(assignment.rootId)}/
|
|
2012
|
+
const confirm = action?.code === "recheck-stopped" && action.target.runId !== null && csrf !== ""
|
|
2013
|
+
? { action: `${taskHref(assignment.rootId)}/recheck-stopped`, run: action.target.runId, returnTo } : null;
|
|
2014
2014
|
return { label: status.need.action.label, href: assignmentActionHref(assignment) ?? taskHref(assignment.rootId), confirm };
|
|
2015
2015
|
}
|
|
2016
|
-
/** A build Toolroll can't check at all: the approver ticks that they checked before confirming. */
|
|
2017
|
-
export const needsCheck = (assignment) => assignment.need != null && "key" in assignment.need && assignment.need.key === "check-stopped";
|
|
2018
2016
|
/** The server page's form of the same: the need's action first, Request changes as the quiet second. */
|
|
2019
2017
|
export function resultNeedAction(need, o, canRequest) {
|
|
2020
2018
|
const control = need.accept != null
|
|
@@ -2022,9 +2020,9 @@ export function resultNeedAction(need, o, canRequest) {
|
|
|
2022
2020
|
: need.rebuild != null
|
|
2023
2021
|
? postForm(need.rebuild.action, html `<button type="submit" data-primary-action data-rebuild style="min-height:44px">${need.label}</button>`, { attrs: { class: "rebuild" } })
|
|
2024
2022
|
: need.confirm !== null
|
|
2025
|
-
? postForm(need.confirm.action, html
|
|
2023
|
+
? postForm(need.confirm.action, html `<button type="submit" data-primary-action style="min-height:44px">${need.label}</button>`, { attrs: { id: "recheck-stopped", class: "recheck-stopped" }, returnTo: need.confirm.returnTo, hidden: { run: need.confirm.run } })
|
|
2026
2024
|
: html `<a class="button-link" href="${need.href ?? "#"}" data-primary-action>${need.label}</a>`;
|
|
2027
|
-
return html `<div class="result-action" data-result-action="need">${control}${canRequest && o.csrf !== "" ? html `<a class="result-feedback-link" href="#request-changes">
|
|
2025
|
+
return html `<div class="result-action" data-result-action="need">${control}${canRequest && o.csrf !== "" ? html `<a class="result-feedback-link" href="#request-changes">Send back</a>` : ""}</div>`;
|
|
2028
2026
|
}
|
|
2029
2027
|
/** The outcome in one bounded sentence (repair 2026-09-14): the handoff's
|
|
2030
2028
|
* first sentence, cut at a word when it runs past 180 characters. The
|
|
@@ -2043,7 +2041,7 @@ export function conciseOutcomeOf(conclusion) {
|
|
|
2043
2041
|
export function resultPrimaryAction(detail, o, prUrl) {
|
|
2044
2042
|
const wrap = (kind, control) => html `<div class="result-action" data-result-action="${kind}">${control}</div>`;
|
|
2045
2043
|
if (detail.ciFailing && o.csrf !== "") {
|
|
2046
|
-
return wrap("draft-repair", postForm(`/r/${detail.run.id}/draft-repair`, html `<button type="submit">
|
|
2044
|
+
return wrap("draft-repair", postForm(`/r/${detail.run.id}/draft-repair`, html `<p class="meta">${SEND_BACK_PUBLISHED}</p><button type="submit">Send back</button>`));
|
|
2047
2045
|
}
|
|
2048
2046
|
if (detail.comments.length > 0 && o.csrf !== "")
|
|
2049
2047
|
return wrap("revise", html `<a class="result-feedback-link" href="#request-changes">Review saved notes</a>`);
|
|
@@ -2052,9 +2050,9 @@ export function resultPrimaryAction(detail, o, prUrl) {
|
|
|
2052
2050
|
if (detail.assignment == null && detail.proof?.matrix.some(row => row.assessment !== undefined) && detail.proof.reasons.includes(GOAL_ASSESSMENT_PENDING))
|
|
2053
2051
|
return wrap("open-result", html `<a class="button-link" href="${reviewHref(detail.taskId)}">Open result</a>`);
|
|
2054
2052
|
if (detail.assignment == null && detail.proof?.matrix.some(row => row.assessment !== undefined && row.review?.judgement === "cannot-tell"))
|
|
2055
|
-
return wrap("review-evidence", html `<a class="button-link" href="${o.hrefFor("checks")}">Review
|
|
2053
|
+
return wrap("review-evidence", html `<a class="button-link" href="${o.hrefFor("checks")}">Review the checks</a>`);
|
|
2056
2054
|
if (detail.canAnnotate && o.csrf !== "")
|
|
2057
|
-
return wrap("request-changes", html `<a class="result-feedback-link" href="#request-changes">
|
|
2055
|
+
return wrap("request-changes", html `<a class="result-feedback-link" href="#request-changes">Send back</a>`);
|
|
2058
2056
|
return html ``;
|
|
2059
2057
|
}
|
|
2060
2058
|
/** The run's facts as rows — one renderer for the page and its live
|
|
@@ -155,13 +155,18 @@ export declare class PermissionsWouldChange extends Error {
|
|
|
155
155
|
}
|
|
156
156
|
/** Evidence kinds in plain words, for the signed criteria in Details. */
|
|
157
157
|
export declare const EVIDENCE_PLAIN: Record<string, string>;
|
|
158
|
+
/** The kinds a requirement's "How we'll know" picker offers, in the order it lists them (#19). */
|
|
159
|
+
export declare const HOW_WE_KNOW: readonly ["check", "screenshot", "changed-path", "manual-review"];
|
|
160
|
+
export declare const HOW_WE_KNOW_WORDS: Record<(typeof HOW_WE_KNOW)[number], string>;
|
|
158
161
|
/** The permission choice a sealed profile carries, as the scope form names it. */
|
|
159
162
|
export declare function permissionModeOfProfile(profile: Scope["profile"] | null | undefined): UnattendedPermissionMode | null;
|
|
160
163
|
/** Done when, from the in-place editor: each line keeps its requirement's
|
|
161
164
|
* id by position, and its evidence and guidance while its words stand; a
|
|
162
165
|
* rewritten one is yours to check, like an added one; an emptied one is
|
|
163
|
-
* dropped.
|
|
164
|
-
|
|
166
|
+
* dropped. A "How we'll know" choice beside a line (#19) names its one kind
|
|
167
|
+
* instead; "keep", or no choice at all (an older form), changes nothing. The
|
|
168
|
+
* saved plan is a new version either way: it needs approving like any edit. */
|
|
169
|
+
export declare function requirementsFromEditor(body: FormView<"requirement" | "requirement-new" | "requirement-how" | "requirement-new-how">, current: readonly AcceptanceCriterion[]): unknown[];
|
|
165
170
|
/**
|
|
166
171
|
* THE CONSENT DOOR (v48): whether a yes can be given on this scope right
|
|
167
172
|
* now — one answer for the task page, the focused chat, and /next, so no
|
|
@@ -563,6 +568,10 @@ export declare function taskBodyParts(data: {
|
|
|
563
568
|
steerRecent?: number[];
|
|
564
569
|
/** Cockpit B2: when this person's remembered password was given, when it may approve these terms. */
|
|
565
570
|
approvalFresh?: string | null;
|
|
571
|
+
/** A new route waiting for its one Approve (route-change.ts): what changed. */
|
|
572
|
+
routeChange?: string | null;
|
|
573
|
+
/** A fast start's result grew past a small change (fast-start.ts): its sentence, and the one act on. */
|
|
574
|
+
fastGrown?: string | null;
|
|
566
575
|
/** Easy-start C5: the viewer is a laptop's local owner — whether this plan is one it approves without a password. */
|
|
567
576
|
approvalLocal?: LocalApprovalView | null;
|
|
568
577
|
/** Cockpit B2: how the current approval's person was proved (approval proved ledger), when it was a remembered one. */
|
|
@@ -748,3 +757,5 @@ export declare function approvedKitOf(scope: Scope, approval: {
|
|
|
748
757
|
method: string;
|
|
749
758
|
at: string;
|
|
750
759
|
} | null): NonNullable<BrowserTaskView["approved"]> | null;
|
|
760
|
+
/** The plan version, in Details: a short handle a person can compare, never on the approval line itself. */
|
|
761
|
+
export declare function planVersionDetailsHtml(digest: string): Html;
|