toolroll 0.9.93 → 0.9.95
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 +79 -0
- package/dist/activity-line.d.ts +7 -4
- package/dist/activity-line.js +9 -7
- package/dist/agent-fence.d.ts +10 -0
- package/dist/agent-fence.js +6 -3
- 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 -1
- package/dist/assignment.js +5 -0
- package/dist/attest.d.ts +3 -0
- package/dist/attest.js +10 -0
- 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 +1 -1
- package/dist/browser/workspace.js +32 -32
- package/dist/browser-crew.js +2 -0
- package/dist/browser-shell.d.ts +1 -1
- package/dist/browser-shell.js +2 -2
- package/dist/browser-workspace.d.ts +50 -2
- package/dist/browser-workspace.js +3 -3
- package/dist/build-review.js +2 -0
- package/dist/builder-restart.d.ts +21 -0
- package/dist/builder-restart.js +50 -0
- package/dist/builder.d.ts +11 -2
- package/dist/builder.js +234 -101
- package/dist/card-catalog.d.ts +209 -0
- package/dist/card-catalog.js +133 -0
- package/dist/card-cli.d.ts +43 -0
- package/dist/card-cli.js +44 -0
- package/dist/card-render.d.ts +26 -0
- package/dist/card-render.js +223 -0
- package/dist/card-sources.d.ts +68 -0
- package/dist/card-sources.js +234 -0
- package/dist/chat-acceptance.js +1 -1
- package/dist/chat-actions.d.ts +106 -9
- package/dist/chat-actions.js +473 -46
- package/dist/chat-approval.d.ts +13 -0
- package/dist/chat-approval.js +39 -9
- package/dist/chat-card-part.d.ts +11 -0
- package/dist/chat-card-part.js +18 -0
- package/dist/chat-card.d.ts +46 -0
- package/dist/chat-card.js +99 -0
- package/dist/chat-channel.d.ts +2 -0
- package/dist/chat-channel.js +37 -14
- package/dist/chat-controls.d.ts +4 -0
- package/dist/chat-controls.js +4 -0
- package/dist/chat-decide.d.ts +10 -16
- package/dist/chat-decide.js +79 -62
- package/dist/chat-delivery.js +13 -4
- package/dist/chat-flow.d.ts +0 -27
- package/dist/chat-flow.js +31 -2
- package/dist/chat-quiet.js +4 -4
- package/dist/chat-task-actions.d.ts +3 -2
- package/dist/chat-task-actions.js +19 -5
- package/dist/chat-terms.d.ts +14 -2
- package/dist/chat-terms.js +35 -0
- package/dist/chat-voice.d.ts +1 -1
- package/dist/chat-voice.js +2 -2
- package/dist/check-facts.d.ts +3 -1
- package/dist/check-facts.js +57 -11
- package/dist/check-failure.d.ts +24 -3
- package/dist/check-failure.js +89 -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-repair.d.ts +47 -0
- package/dist/check-repair.js +240 -0
- package/dist/check-report.d.ts +2 -0
- package/dist/check-report.js +1 -1
- 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/claim.d.ts +6 -0
- package/dist/claim.js +13 -2
- package/dist/cli-help.d.ts +4 -1
- package/dist/cli-help.js +49 -30
- package/dist/cli.js +15 -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 +3 -1
- package/dist/coding-provider.js +12 -7
- package/dist/coding-update.js +3 -2
- package/dist/coding-workspace.d.ts +1 -1
- package/dist/coding-workspace.js +8 -8
- 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 +92 -0
- package/dist/contracts/chat-actions.js +20 -0
- package/dist/contracts/chat-card.d.ts +91 -0
- package/dist/contracts/chat-card.js +54 -0
- package/dist/contracts/chat-content.d.ts +191 -0
- package/dist/contracts/chat-content.js +4 -0
- package/dist/contracts/cli.d.ts +52 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +12 -3
- package/dist/contracts/console-api.js +12 -3
- package/dist/contracts/flow-propose.d.ts +8 -1
- package/dist/contracts/flow-propose.js +3 -1
- package/dist/contracts/flow-send.d.ts +126 -0
- package/dist/contracts/flow-send.js +3 -0
- package/dist/contracts/gateway-tools.d.ts +17 -0
- package/dist/contracts/gateway-tools.js +3 -1
- package/dist/contracts/lead-tools.d.ts +234 -0
- package/dist/contracts/lead-tools.js +25 -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/storage.d.ts +14 -0
- package/dist/contracts/storage.js +3 -1
- package/dist/contracts/store-json.d.ts +18 -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/discord-chat.js +14 -0
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +25 -16
- package/dist/dispose.d.ts +19 -0
- package/dist/dispose.js +55 -9
- package/dist/easy-start.js +2 -3
- package/dist/eval-oracle.js +4 -1
- package/dist/evals.js +2 -1
- package/dist/evidence-pair.d.ts +53 -0
- package/dist/evidence-pair.js +128 -0
- package/dist/exhaustion.d.ts +17 -4
- package/dist/exhaustion.js +44 -4
- package/dist/export.js +1 -1
- package/dist/failing-first.d.ts +31 -0
- package/dist/failing-first.js +44 -0
- package/dist/fallback-schema.d.ts +8 -0
- package/dist/fallback-schema.js +40 -0
- package/dist/fallback.d.ts +138 -0
- package/dist/fallback.js +605 -0
- 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/findings.d.ts +224 -0
- package/dist/findings.js +449 -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 +75 -9
- package/dist/flaky.js +255 -0
- package/dist/fleet-schema.d.ts +17 -0
- package/dist/fleet-schema.js +135 -0
- package/dist/flow-browser.js +2 -2
- package/dist/flow-card-task.js +3 -0
- package/dist/flow-code.d.ts +2 -2
- package/dist/flow-code.js +9 -5
- package/dist/flow-result-card.d.ts +22 -0
- package/dist/flow-result-card.js +55 -0
- package/dist/flow-send.js +12 -9
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +1 -1
- package/dist/flow-triggers.js +2 -2
- package/dist/flow-unattended.d.ts +26 -0
- package/dist/flow-unattended.js +12 -3
- package/dist/flows-ui.js +10 -2
- package/dist/follow-through-brief.d.ts +12 -0
- package/dist/follow-through-brief.js +31 -0
- package/dist/follow-through-cli.d.ts +23 -0
- package/dist/follow-through-cli.js +153 -0
- package/dist/git-incident.d.ts +16 -0
- package/dist/git-incident.js +69 -6
- package/dist/github-import.d.ts +62 -0
- package/dist/github-import.js +146 -0
- package/dist/guides.js +15 -10
- package/dist/handover-note.d.ts +33 -0
- package/dist/handover-note.js +106 -0
- package/dist/invoke.d.ts +25 -2
- package/dist/invoke.js +157 -58
- 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-cli.js +26 -24
- package/dist/lead-context.js +1 -1
- package/dist/lead-contract.d.ts +1 -1
- package/dist/lead-contract.js +3 -2
- package/dist/lead-doors.d.ts +4 -0
- package/dist/lead-doors.js +2 -2
- package/dist/lead-progress.js +5 -0
- package/dist/lead-status.d.ts +2 -0
- package/dist/lead-status.js +6 -2
- package/dist/lead-tools.js +162 -34
- package/dist/lead.js +2 -2
- 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 +16 -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/modes.d.ts +6 -6
- package/dist/modes.js +3 -1
- package/dist/needs-you.d.ts +31 -9
- package/dist/needs-you.js +110 -41
- package/dist/nightly-github.d.ts +2 -0
- package/dist/nightly-github.js +4 -4
- package/dist/operate-remote-arguments.js +7 -1
- package/dist/operate-remote.js +3 -1
- package/dist/operate.d.ts +6 -1
- package/dist/operate.js +565 -64
- 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/plan-login.d.ts +14 -0
- package/dist/plan-login.js +58 -0
- package/dist/planner.d.ts +1 -1
- package/dist/planner.js +4 -2
- package/dist/process-liveness.d.ts +2 -0
- package/dist/process-liveness.js +61 -17
- package/dist/project-delete-ui.d.ts +19 -2
- package/dist/project-delete-ui.js +29 -1
- package/dist/project-delete.js +14 -1
- 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/project-tools.d.ts +4 -4
- package/dist/project-tools.js +23 -7
- package/dist/proof.js +30 -5
- package/dist/protected-storage-look.d.ts +1 -0
- package/dist/protected-storage-look.js +13 -0
- package/dist/protected-storage.d.ts +70 -39
- package/dist/protected-storage.js +196 -147
- package/dist/provider-auth.js +1 -1
- package/dist/provider-capture.d.ts +34 -0
- package/dist/provider-capture.js +53 -0
- package/dist/publish.js +9 -1
- package/dist/pull-request-flow.js +5 -0
- package/dist/push.d.ts +18 -2
- package/dist/push.js +40 -16
- package/dist/release-adapters.d.ts +9 -0
- package/dist/release-adapters.js +76 -0
- package/dist/release-auto.js +13 -13
- package/dist/release-card.d.ts +1 -2
- package/dist/release-card.js +11 -0
- package/dist/release-carry.d.ts +7 -2
- package/dist/release-carry.js +49 -10
- package/dist/release-cli.d.ts +4 -0
- package/dist/release-cli.js +29 -22
- 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 +20 -1
- package/dist/release.js +85 -9
- 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 +27 -19
- 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 +28 -4
- package/dist/scope.js +92 -28
- package/dist/scout.d.ts +1 -1
- package/dist/scout.js +2 -1
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +26 -18
- package/dist/server/chat.js +16 -14
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +26 -35
- package/dist/server/console.css +73 -0
- package/dist/server/guards.js +3 -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 +16 -3
- 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-follow-through.d.ts +11 -0
- package/dist/server/render-follow-through.js +68 -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 +2 -0
- package/dist/server/render-release.js +3 -3
- package/dist/server/render-results.d.ts +2 -0
- package/dist/server/render-results.js +68 -68
- package/dist/server/render-tasks.d.ts +16 -2
- package/dist/server/render-tasks.js +177 -141
- package/dist/server/retired-routes.d.ts +17 -0
- package/dist/server/retired-routes.js +53 -0
- package/dist/server/route-table.d.ts +3 -0
- package/dist/server/route-table.js +48 -12
- package/dist/server/settings.js +166 -34
- package/dist/server/task-views.js +66 -26
- package/dist/server/tasks.d.ts +2 -6
- package/dist/server/tasks.js +250 -321
- package/dist/server/welcome.js +1 -1
- package/dist/settings-groups-ui.d.ts +1 -0
- package/dist/settings-groups-ui.js +4 -2
- package/dist/settings-kit.js +3 -2
- package/dist/settings-proofs.js +3 -1
- package/dist/slack-chat.js +14 -1
- package/dist/steer-mailbox.d.ts +8 -1
- package/dist/steer-mailbox.js +164 -6
- package/dist/stop-proof.js +6 -4
- 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 +89 -7
- package/dist/store.js +386 -114
- package/dist/surface.js +67 -6
- 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.d.ts +2 -1
- package/dist/task-control.js +4 -1
- package/dist/task-outcome-cli.d.ts +2 -0
- package/dist/task-outcome-cli.js +17 -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 +45 -49
- package/dist/teardown-git.d.ts +18 -0
- package/dist/teardown-git.js +105 -21
- package/dist/telegram-lead.js +23 -6
- package/dist/telegram-progress.js +5 -3
- package/dist/telegram-status.js +6 -4
- package/dist/telegram.js +12 -1
- 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.js +19 -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 +95 -66
- package/dist/work-summary.d.ts +1 -1
- package/dist/work-summary.js +7 -2
- package/dist/workspace-ui.d.ts +7 -3
- package/dist/workspace-ui.js +38 -23
- package/dist/worktree.d.ts +12 -3
- package/dist/worktree.js +91 -14
- package/package.json +2 -1
- package/dist/server/render-next.d.ts +0 -63
- package/dist/server/render-next.js +0 -109
package/dist/chat-approval.d.ts
CHANGED
|
@@ -27,6 +27,19 @@ export declare function effectiveChatApproval(store: Store, repo: string, approv
|
|
|
27
27
|
ok: false;
|
|
28
28
|
why: string;
|
|
29
29
|
};
|
|
30
|
+
/** What this person's chat on `channel` may approve on this repository now, and under whose limits: their saved setting,
|
|
31
|
+
* else (only with nothing saved) their own live signed mode that names this chat app, else their standing as an
|
|
32
|
+
* approver. A saved setting that refuses refuses here. `digest` names that for
|
|
33
|
+
* the ledger; the yes itself is the person's tap and is sealed as theirs, so it doesn't lapse when the authority does. */
|
|
34
|
+
export declare function chatApproveMode(store: Store, repo: string | null, approver: string, now: Date, channel: "telegram" | "slack" | "discord" | "teams"): {
|
|
35
|
+
ok: true;
|
|
36
|
+
digest: string;
|
|
37
|
+
limits: ChatApprovalLimits;
|
|
38
|
+
source: "setting" | "mode";
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
why: string;
|
|
42
|
+
};
|
|
30
43
|
export type ChatApprovalChange = {
|
|
31
44
|
approver: string;
|
|
32
45
|
scope: string;
|
package/dist/chat-approval.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
/** Approving from chat
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* projects
|
|
1
|
+
/** Approving from chat (owner's decision, docs/plans/toolroll-cards.md): a person with the authority approves from their
|
|
2
|
+
* own linked chat by default, with no limits of their own. This setting is how they say otherwise: off for all their
|
|
3
|
+
* projects or for one, or on with limits (whether a plan may ask for full access, and the most one attempt may cost). A
|
|
4
|
+
* project's own row outranks the all-projects one, and an explicit "off" keeps it off. Turning it off for all projects
|
|
5
|
+
* also disables that owner's saved project rows.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* A saved row ends with the account: a reset password, revoked access or a lost project ends it, and it must be saved
|
|
8
|
+
* again. Saving limits takes the password; turning it off is one step. Every change is a ledger line.
|
|
8
9
|
*
|
|
9
10
|
* What the setting allows is only that the owner's own two taps in their paired chat count as their yes. Every other
|
|
10
11
|
* rule still applies at the offer and again at the tap (chat-decide.ts planInChat): protected paths, separation of
|
|
11
12
|
* duties, organisation policy, written-for-you plans, unresolved routes, and the limits here. */
|
|
12
13
|
import { createHash } from "node:crypto";
|
|
14
|
+
import { chatApproveChatsOf, chatNames, modeTermsFromJson } from "./modes.js";
|
|
13
15
|
/** The all-projects row's scope. */
|
|
14
16
|
export const ALL_PROJECTS = "*";
|
|
15
17
|
const money = (micro) => `$${(micro / 1_000_000).toFixed(2)}`;
|
|
@@ -37,16 +39,44 @@ export function effectiveChatApproval(store, repo, approver) {
|
|
|
37
39
|
const all = store.handle.prepare("SELECT * FROM chat_approval_setting WHERE approver = ? AND scope = ?").get(approver, ALL_PROJECTS);
|
|
38
40
|
const row = project ?? all;
|
|
39
41
|
const setting = row === undefined ? null : readRow(row);
|
|
40
|
-
if (setting === null || !setting.enabled)
|
|
41
|
-
return { ok: false, why: "Approving from chat isn't turned on for this project." };
|
|
42
42
|
const account = store.accountOf(approver);
|
|
43
|
+
if (setting === null) {
|
|
44
|
+
if (account === null || account.revokedAt !== null || account.role !== "approver" || !store.accountCanAccess(approver, repo))
|
|
45
|
+
return { ok: false, why: "Only an approver for this project can approve it." };
|
|
46
|
+
const limits = { fullAccess: true, capMicrousd: null };
|
|
47
|
+
return { ok: true, limits, setting: { ...limits, approver, scope: ALL_PROJECTS, enabled: true, generation: account.generation, digest: digestOf(approver, ALL_PROJECTS, limits, account.generation), updatedBy: approver, updatedAt: "" } };
|
|
48
|
+
}
|
|
49
|
+
if (!setting.enabled)
|
|
50
|
+
return { ok: false, why: "You turned off approving from chat for this project." };
|
|
43
51
|
if (account === null || account.revokedAt !== null || account.role !== "approver" || account.generation !== setting.generation || !store.accountCanAccess(approver, repo)) {
|
|
44
|
-
return { ok: false, why: "Your access changed since you
|
|
52
|
+
return { ok: false, why: "Your access changed since you saved your chat approval setting. Save it again in Settings." };
|
|
45
53
|
}
|
|
46
54
|
if (setting.digest !== digestOf(setting.approver, setting.scope, setting, setting.generation))
|
|
47
55
|
return { ok: false, why: "Your chat approval setting can't be read. Turn it on again in Settings." };
|
|
48
56
|
return { ok: true, setting, limits: { fullAccess: setting.fullAccess, capMicrousd: setting.capMicrousd } };
|
|
49
57
|
}
|
|
58
|
+
/** What this person's chat on `channel` may approve on this repository now, and under whose limits: their saved setting,
|
|
59
|
+
* else (only with nothing saved) their own live signed mode that names this chat app, else their standing as an
|
|
60
|
+
* approver. A saved setting that refuses refuses here. `digest` names that for
|
|
61
|
+
* the ledger; the yes itself is the person's tap and is sealed as theirs, so it doesn't lapse when the authority does. */
|
|
62
|
+
export function chatApproveMode(store, repo, approver, now, channel) {
|
|
63
|
+
if (repo === null)
|
|
64
|
+
return { ok: false, why: "Approving from chat isn't turned on for this project." };
|
|
65
|
+
const setting = effectiveChatApproval(store, repo, approver);
|
|
66
|
+
// A saved setting decides: its "off", a lapse after an access change or an unreadable row refuses before any mode is
|
|
67
|
+
// looked at, so a signed mode never reopens what the person turned off. The mode counts only when nothing is saved.
|
|
68
|
+
if (!setting.ok)
|
|
69
|
+
return setting;
|
|
70
|
+
const chosen = { ok: true, source: "setting" };
|
|
71
|
+
if (setting.setting.updatedAt !== "")
|
|
72
|
+
return { ...chosen, digest: setting.setting.digest, limits: setting.limits };
|
|
73
|
+
// Nothing saved: their own signed mode's limits, where it names this chat app; otherwise their standing as an approver.
|
|
74
|
+
const mode = store.activeMode(repo, now);
|
|
75
|
+
const terms = mode === null ? null : modeTermsFromJson(mode.termsJson);
|
|
76
|
+
if (mode !== null && terms !== null && terms.chatApprove && mode.signedBy === approver && store.accountCanAccess(approver, repo) && chatApproveChatsOf(terms).includes(channel))
|
|
77
|
+
return { ok: true, digest: mode.digest, limits: { fullAccess: terms.permissionDefault === "escalated", capMicrousd: terms.perAttemptBudgetMicrousd }, source: "mode" };
|
|
78
|
+
return { ...chosen, digest: setting.setting.digest, limits: setting.limits };
|
|
79
|
+
}
|
|
50
80
|
/** Save and ledger the setting; all-projects off also disables every saved project row for this owner.
|
|
51
81
|
* The caller has proved who is asking, and for "on" the password. */
|
|
52
82
|
export function setChatApproval(store, change, now) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChatContent } from "./contracts/chat-content.js";
|
|
2
|
+
import type { ChatCard } from "./contracts/chat-card.js";
|
|
3
|
+
/** The buttons of a card, as a part's links. */
|
|
4
|
+
export declare const cardLinks: (card: ChatCard) => Pick<ChatContent, "link" | "also">;
|
|
5
|
+
export declare const cardContent: (card: ChatCard) => ChatContent;
|
|
6
|
+
/** A card that can't be read goes out as the plain words kept with it. */
|
|
7
|
+
export declare function cardPart(proposal: {
|
|
8
|
+
kind: string;
|
|
9
|
+
payload: Record<string, unknown>;
|
|
10
|
+
}): ChatContent;
|
|
11
|
+
export declare function withoutCard(content: ChatContent): ChatContent;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** A card as a chat part: its plain text and link buttons always there, the card beside them. */
|
|
2
|
+
import { cardOfProposal, cardPlainOf } from "./chat-card.js";
|
|
3
|
+
import { cardPlainText } from "./card-render.js";
|
|
4
|
+
/** The buttons of a card, as a part's links. */
|
|
5
|
+
export const cardLinks = (card) => {
|
|
6
|
+
const [first, ...rest] = card.buttons;
|
|
7
|
+
return { ...(first === undefined ? {} : { link: first }), ...(rest.length === 0 ? {} : { also: rest }) };
|
|
8
|
+
};
|
|
9
|
+
export const cardContent = (card) => ({ text: cardPlainText(card), rich: card, ...cardLinks(card) });
|
|
10
|
+
/** A card that can't be read goes out as the plain words kept with it. */
|
|
11
|
+
export function cardPart(proposal) {
|
|
12
|
+
const card = cardOfProposal(proposal);
|
|
13
|
+
return card === null ? { text: cardPlainOf(proposal) } : cardContent(card);
|
|
14
|
+
}
|
|
15
|
+
export function withoutCard(content) {
|
|
16
|
+
const { rich: _rich, ...plain } = content;
|
|
17
|
+
return plain;
|
|
18
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* From a checked spec to a card (docs/plans/toolroll-cards.md): Toolroll fills every data part from its records and every
|
|
3
|
+
* button from its own tables. Nothing the model wrote reaches a card except a Text part, and every app labels that as
|
|
4
|
+
* the lead's note, never as one of Toolroll's records (card-render.ts).
|
|
5
|
+
*/
|
|
6
|
+
import type { CardPlan } from "./card-catalog.js";
|
|
7
|
+
import { type CardReader } from "./card-sources.js";
|
|
8
|
+
import { type ChatCard } from "./contracts/chat-card.js";
|
|
9
|
+
/** How a Button becomes a page or a proposal: the lead's own checks, so a card can't reach what show_control can't. */
|
|
10
|
+
export type CardButtons = (props: Record<string, unknown>) => {
|
|
11
|
+
ok: true;
|
|
12
|
+
button?: ChatCard["buttons"][number];
|
|
13
|
+
action?: ChatCard["actions"][number];
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
message: string;
|
|
17
|
+
};
|
|
18
|
+
/** A plan as a card, read now, or why it can't be one. */
|
|
19
|
+
export declare function buildChatCard(reader: CardReader, plan: CardPlan, repoOf: (id: unknown) => string | null, buttons: CardButtons): {
|
|
20
|
+
ok: true;
|
|
21
|
+
card: ChatCard;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
message: string;
|
|
25
|
+
};
|
|
26
|
+
/** A card kept on a `control` proposal, as its marker says. */
|
|
27
|
+
export declare const CARD_CONTROL = "card";
|
|
28
|
+
export declare function cardOfProposal(proposal: {
|
|
29
|
+
kind: string;
|
|
30
|
+
payload: Record<string, unknown>;
|
|
31
|
+
}): ChatCard | null;
|
|
32
|
+
export declare function isCardProposal(proposal: {
|
|
33
|
+
kind: string;
|
|
34
|
+
payload: Record<string, unknown>;
|
|
35
|
+
}): boolean;
|
|
36
|
+
/** The plain version kept beside a card, for when the card itself can't be read. */
|
|
37
|
+
export declare const cardPlainOf: (proposal: {
|
|
38
|
+
payload: Record<string, unknown>;
|
|
39
|
+
}) => string;
|
|
40
|
+
/** Cards before the proposals they lead to, so each Confirm sits under its card. */
|
|
41
|
+
export declare function cardsFirst<T extends {
|
|
42
|
+
kind: string;
|
|
43
|
+
payload: Record<string, unknown>;
|
|
44
|
+
}>(proposals: readonly T[]): T[];
|
|
45
|
+
/** A card goes only where every project behind it is still reachable. */
|
|
46
|
+
export declare const cardWithin: (card: Pick<ChatCard, "repos">, repos: readonly string[]) => boolean;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { readCardSource } from "./card-sources.js";
|
|
2
|
+
import { publicChatText } from "./chat-display.js";
|
|
3
|
+
import { CARD_LIMITS, readChatCard } from "./contracts/chat-card.js";
|
|
4
|
+
const queryOf = (props, repoOf) => {
|
|
5
|
+
const repo = props["repo"] === undefined ? null : repoOf(props["repo"]);
|
|
6
|
+
if (props["repo"] !== undefined && repo === null)
|
|
7
|
+
return null;
|
|
8
|
+
return { repo, ...(props["task"] === undefined ? {} : { task: String(props["task"]) }), ...(props["state"] === undefined ? {} : { state: String(props["state"]) }), ...(props["limit"] === undefined ? {} : { limit: Number(props["limit"]) }),
|
|
9
|
+
...(props["flow"] === undefined ? {} : { flow: Number(props["flow"]) }), ...(props["days"] === undefined ? {} : { days: Number(props["days"]) }) };
|
|
10
|
+
};
|
|
11
|
+
function tableOf(data, wanted) {
|
|
12
|
+
const ids = Array.isArray(wanted) ? wanted.map(String) : data.columns.slice(0, CARD_LIMITS.columns).map(one => one.id);
|
|
13
|
+
const columns = ids.map(id => data.columns.find(one => one.id === id));
|
|
14
|
+
const missing = ids.filter((_, index) => columns[index] === undefined);
|
|
15
|
+
if (missing.length > 0)
|
|
16
|
+
return `No column ${missing.join(", ")}. This source has: ${data.columns.map(one => one.id).join(", ")}.`;
|
|
17
|
+
return { kind: "table", heading: data.heading, origin: data.origin ?? "records", columns: columns.map(one => ({ label: one.label, numeric: one.numeric === true })), rows: data.rows.map(row => ids.map(id => row[id] ?? "")), more: data.more };
|
|
18
|
+
}
|
|
19
|
+
function factsOf(data, wanted) {
|
|
20
|
+
const ids = Array.isArray(wanted) ? wanted.map(String) : data.facts.map(one => one.id);
|
|
21
|
+
const items = ids.flatMap(id => data.facts.filter(one => one.id === id));
|
|
22
|
+
if (items.length !== ids.length)
|
|
23
|
+
return `This source's facts are: ${data.facts.map(one => one.id).join(", ")}.`;
|
|
24
|
+
if (items.length === 0)
|
|
25
|
+
return "This source has no facts to show now.";
|
|
26
|
+
return { kind: "facts", heading: data.heading, items: items.slice(0, CARD_LIMITS.facts).map(({ label, value }) => ({ label, value })) };
|
|
27
|
+
}
|
|
28
|
+
/** A plan as a card, read now, or why it can't be one. */
|
|
29
|
+
export function buildChatCard(reader, plan, repoOf, buttons) {
|
|
30
|
+
const blocks = [];
|
|
31
|
+
const repos = new Set();
|
|
32
|
+
let title = null;
|
|
33
|
+
for (const part of plan.parts) {
|
|
34
|
+
if (part.type === "Divider") {
|
|
35
|
+
blocks.push({ kind: "divider" });
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (part.type === "Text") {
|
|
39
|
+
const text = publicChatText(String(part.props["text"]), CARD_LIMITS.text);
|
|
40
|
+
if (text !== "")
|
|
41
|
+
blocks.push({ kind: "text", text });
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const query = queryOf(part.props, repoOf);
|
|
45
|
+
if (query === null)
|
|
46
|
+
return { ok: false, message: "repo must be one of the ids from list_repos." };
|
|
47
|
+
const data = readCardSource(reader, part.props["source"], query);
|
|
48
|
+
if ("problem" in data)
|
|
49
|
+
return { ok: false, message: data.problem };
|
|
50
|
+
title ??= data.heading;
|
|
51
|
+
for (const repo of data.repos)
|
|
52
|
+
repos.add(repo);
|
|
53
|
+
if (part.type === "Notes") {
|
|
54
|
+
if (data.notes === undefined || data.notes.length === 0)
|
|
55
|
+
return { ok: false, message: "There are no saved words to show here. Try a Table." };
|
|
56
|
+
const items = data.notes.slice(0, CARD_LIMITS.notes);
|
|
57
|
+
blocks.push({ kind: "notes", heading: data.heading, origin: data.origin ?? "records", items, more: data.notes.length - items.length });
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (part.type === "Chart") {
|
|
61
|
+
if (data.points.length === 0)
|
|
62
|
+
return { ok: false, message: "There are no numbers to chart yet: show a Table or Fields instead." };
|
|
63
|
+
blocks.push({ kind: "chart", heading: data.heading, chart: part.props["chart"], points: [...data.points] });
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const block = part.type === "Table" ? tableOf(data, part.props["columns"]) : factsOf(data, part.props["facts"]);
|
|
67
|
+
if (typeof block === "string")
|
|
68
|
+
return { ok: false, message: block };
|
|
69
|
+
blocks.push(block);
|
|
70
|
+
}
|
|
71
|
+
const links = [], actions = [];
|
|
72
|
+
for (const props of plan.buttons) {
|
|
73
|
+
const made = buttons(props);
|
|
74
|
+
if (!made.ok)
|
|
75
|
+
return made;
|
|
76
|
+
if (made.button !== undefined)
|
|
77
|
+
links.push(made.button);
|
|
78
|
+
if (made.action !== undefined)
|
|
79
|
+
actions.push(made.action);
|
|
80
|
+
}
|
|
81
|
+
const card = readChatCard({ version: 1, title: title ?? "Toolroll", asOf: reader.now.toISOString(), repos: [...repos], blocks, buttons: links.slice(0, CARD_LIMITS.buttons), actions: actions.slice(0, CARD_LIMITS.actions) });
|
|
82
|
+
return card === null ? { ok: false, message: "That card doesn't fit. Show fewer parts." } : { ok: true, card };
|
|
83
|
+
}
|
|
84
|
+
/** A card kept on a `control` proposal, as its marker says. */
|
|
85
|
+
export const CARD_CONTROL = "card";
|
|
86
|
+
export function cardOfProposal(proposal) {
|
|
87
|
+
return proposal.kind === "control" && proposal.payload["control"] === CARD_CONTROL ? readChatCard(proposal.payload["card"]) : null;
|
|
88
|
+
}
|
|
89
|
+
export function isCardProposal(proposal) {
|
|
90
|
+
return proposal.kind === "control" && proposal.payload["control"] === CARD_CONTROL;
|
|
91
|
+
}
|
|
92
|
+
/** The plain version kept beside a card, for when the card itself can't be read. */
|
|
93
|
+
export const cardPlainOf = (proposal) => typeof proposal.payload["plain"] === "string" ? proposal.payload["plain"] : "This card can't be shown.";
|
|
94
|
+
/** Cards before the proposals they lead to, so each Confirm sits under its card. */
|
|
95
|
+
export function cardsFirst(proposals) {
|
|
96
|
+
return [...proposals.filter(isCardProposal), ...proposals.filter(one => !isCardProposal(one))];
|
|
97
|
+
}
|
|
98
|
+
/** A card goes only where every project behind it is still reachable. */
|
|
99
|
+
export const cardWithin = (card, repos) => card.repos.every(one => repos.includes(one));
|
package/dist/chat-channel.d.ts
CHANGED
|
@@ -67,6 +67,8 @@ export type ChatChannelName = "telegram" | "slack" | "discord" | "teams";
|
|
|
67
67
|
/** The card text once its challenge is armed: an irreversible answer or a
|
|
68
68
|
* challenge action, in the same words on every channel. */
|
|
69
69
|
export declare function armedCardText(proposal: LeadProposal, previewText: string): string;
|
|
70
|
+
/** The second question on an action's card, in words true of what it does. */
|
|
71
|
+
export declare function armedQuestion(proposal: LeadProposal): string;
|
|
70
72
|
/** The "yes" button's label for an armed card. */
|
|
71
73
|
export declare function armedYesLabel(proposal: LeadProposal): string;
|
|
72
74
|
export declare function proposalLink(store: Store, proposal: LeadProposal, repos: readonly string[], channel?: ChatChannelName | null): PhoneLink | null;
|
package/dist/chat-channel.js
CHANGED
|
@@ -3,10 +3,11 @@ import { parseFeedbackImage } from "./result-review.js";
|
|
|
3
3
|
import { FLOW_HREF } from "./flow-engine.js";
|
|
4
4
|
import { closedQuestionWords, LIMITS } from "./decision.js";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import { sharedActionPayload, sharedActionNeedsReview, sharedActionReviewPath, sharedActionAllowsChallenge, CHAT_ACTIONS, } from "./chat-actions.js";
|
|
6
|
+
import { sharedActionPayload, sharedActionNeedsReview, sharedActionReviewPath, APPROVAL_TERM_CHARS, sharedActionAllowsChallenge, CHAT_ACTIONS, } from "./chat-actions.js";
|
|
7
7
|
import { isDirectChatProvider, subscriptionCredentialKey } from "./converse.js";
|
|
8
8
|
import { LEAD_MESSAGE_MAX_CHARS } from "./lead.js";
|
|
9
9
|
import { LEAD_TOOL_SCHEMAS } from "./lead-tools.js";
|
|
10
|
+
import { cardPlainOf, isCardProposal } from "./chat-card.js";
|
|
10
11
|
import { verifyApproverStanding } from "./principal.js";
|
|
11
12
|
import { canonicalProject } from "./project.js";
|
|
12
13
|
import { phoneText, projectLabel } from "./telegram-status.js";
|
|
@@ -201,9 +202,14 @@ function taskLink(store, taskId, repos) {
|
|
|
201
202
|
export function armedCardText(proposal, previewText) {
|
|
202
203
|
const body = previewText.split("\n\nConfirm or Dismiss below")[0] ?? previewText;
|
|
203
204
|
if (proposal.kind === "action")
|
|
204
|
-
return `${body}\n\
|
|
205
|
+
return `${body}\n\n${armedQuestion(proposal)}`;
|
|
205
206
|
return `⚠ This answer is IRREVERSIBLE.\n\n${body}\n\nConfirm?`;
|
|
206
207
|
}
|
|
208
|
+
/** The second question on an action's card, in words true of what it does. */
|
|
209
|
+
export function armedQuestion(proposal) {
|
|
210
|
+
const action = proposal.kind === "action" ? sharedActionPayload(proposal.payload) : null;
|
|
211
|
+
return action?.operation === "result_accept" ? "This records that you handled this exact result. Confirm?" : "You approve exactly what's written above. Confirm?";
|
|
212
|
+
}
|
|
207
213
|
/** The "yes" button's label for an armed card. */
|
|
208
214
|
export function armedYesLabel(proposal) {
|
|
209
215
|
if (proposal.kind === "action") {
|
|
@@ -340,7 +346,7 @@ export function proposalPreview(store, proposal, repos, channel = null) {
|
|
|
340
346
|
if (!action)
|
|
341
347
|
return handoff("This action is unavailable.");
|
|
342
348
|
if (channel !== null && sharedActionAllowsChallenge(action))
|
|
343
|
-
return card(phoneText(action.title, 200), action.terms.map((term) => phoneText(term,
|
|
349
|
+
return card(phoneText(action.title, 200), action.terms.map((term) => phoneText(term, APPROVAL_TERM_CHARS)), "Confirm asks once more before anything is recorded.");
|
|
344
350
|
return sharedActionNeedsReview(action)
|
|
345
351
|
? handoff(phoneText(action.title, 200), [
|
|
346
352
|
"Review the full details and confirm this exact action.",
|
|
@@ -405,7 +411,7 @@ export function proposalPreview(store, proposal, repos, channel = null) {
|
|
|
405
411
|
return card(`Rewrite the scope of ${taskName}:`, [
|
|
406
412
|
`Goal: ${t("goal", 600)}`,
|
|
407
413
|
...(t("not") === "" ? [] : [`Not: ${t("not", 300)}`]),
|
|
408
|
-
], "After confirming, the new scope still needs your
|
|
414
|
+
], "After confirming, the new scope still needs your approval before work starts.");
|
|
409
415
|
case "answer": {
|
|
410
416
|
const id = typeof payload["decision"] === "number" ? payload["decision"] : null;
|
|
411
417
|
const decision = id === null ? null : store.getDecision(id);
|
|
@@ -432,9 +438,7 @@ export function proposalPreview(store, proposal, repos, channel = null) {
|
|
|
432
438
|
const dependency = t("dependencyTitle", 120) || t("dependency", 64);
|
|
433
439
|
if (action === null)
|
|
434
440
|
return handoff(`An unavailable action was proposed for ${taskName}.`);
|
|
435
|
-
return card(`${action.label}: ${taskName}${dependency === "" ? "" : ` · ${dependency}`}`, [action.detail],
|
|
436
|
-
? "Confirming only requests the resume. Work resumes after the password step on the task, not from here."
|
|
437
|
-
: null);
|
|
441
|
+
return card(`${action.label}: ${taskName}${dependency === "" ? "" : ` · ${dependency}`}`, [action.detail], null);
|
|
438
442
|
}
|
|
439
443
|
case "review": {
|
|
440
444
|
const revise = payload["operation"] === "revise";
|
|
@@ -469,6 +473,8 @@ export function proposalPreview(store, proposal, repos, channel = null) {
|
|
|
469
473
|
"Cancelling is armed on the task itself, never from a card.",
|
|
470
474
|
]);
|
|
471
475
|
case "control": {
|
|
476
|
+
if (isCardProposal(proposal))
|
|
477
|
+
return handoff(cardPlainOf(proposal));
|
|
472
478
|
const control = payload["control"];
|
|
473
479
|
const label = isChatControl(control)
|
|
474
480
|
? CHAT_CONTROLS[control].label
|
|
@@ -529,6 +535,16 @@ export const CHAT_ACTION_PARITY = {
|
|
|
529
535
|
how: "Reads bounded source excerpts or advisory import impact in an accessible enrolled project through the shared engine, with source-search fallback when its index is unavailable.",
|
|
530
536
|
gap: "Index refresh uses the local CLI. Dedicated Telegram and Slack journeys for this tool and live channel rendering remain unverified.",
|
|
531
537
|
},
|
|
538
|
+
get_code_map: {
|
|
539
|
+
support: "direct",
|
|
540
|
+
how: "Reads the project's generated code map through the shared reader, one labelled answer at most 6 KB, paging one pinned version.",
|
|
541
|
+
gap: null,
|
|
542
|
+
},
|
|
543
|
+
refresh_code_map: {
|
|
544
|
+
support: "direct",
|
|
545
|
+
how: "Queues a check of the project's main, as Check now does on the page.",
|
|
546
|
+
gap: null,
|
|
547
|
+
},
|
|
532
548
|
get_action_status: {
|
|
533
549
|
support: "direct",
|
|
534
550
|
how: "Reads the exact saved shared action and its outcome, including completion through secure review.",
|
|
@@ -569,6 +585,7 @@ export const CHAT_ACTION_PARITY = {
|
|
|
569
585
|
how: "Read during a turn.",
|
|
570
586
|
gap: null,
|
|
571
587
|
},
|
|
588
|
+
get_flaky_tests: { support: "direct", how: "Read during a turn: a project's tests with mixed outcomes, each with the task that would fix it. Fixing one is an ordinary task card.", gap: null },
|
|
572
589
|
get_models: { support: "direct", how: "Read during a turn: default agents with the exact model each runs, CLI versions and new models. Changes use the labelled Settings → Models page.", gap: null },
|
|
573
590
|
get_diff: { support: "direct", how: "Read during a turn: the exact result's changed files, then one file's diff, so a requested change names the right file and line.", gap: null },
|
|
574
591
|
get_check_log: { support: "direct", how: "Read during a turn: the end of the exact result's check log, a page of it, or the lines matching a search.", gap: null },
|
|
@@ -619,6 +636,12 @@ export const CHAT_ACTION_PARITY = {
|
|
|
619
636
|
how: "Pushes the plan's or flow card's own decision card to the owner's paired chat: Approve arms Yes and Cancel, and only the owner's Yes decides, through sealScopeApproval (as a chat-origin approval) or decideFlowCard. Outside the owner's chat-approval setting or a decision's rules it answers why, and the lead opens the console control.",
|
|
620
637
|
gap: "A flow card's Send back, Edit and a Person chooses step act from the pushed card; a plan's Send back stays in the console. Fixture proof only, no physical-phone rendering.",
|
|
621
638
|
},
|
|
639
|
+
get_findings: { support: "direct", how: "Read during a turn; a finding's words are shown as untrusted text.", gap: null },
|
|
640
|
+
show_card: {
|
|
641
|
+
support: "direct",
|
|
642
|
+
how: "A card of Toolroll's own records. Telegram shows it as one message: key facts as lines, tables and charts as monospaced text, its links as url buttons.",
|
|
643
|
+
gap: "A chart is bars of text on Telegram, with every number written out.",
|
|
644
|
+
},
|
|
622
645
|
show_control: {
|
|
623
646
|
support: "handoff",
|
|
624
647
|
how: "The card names the control and the task, with one url button to that exact console control when a trusted https console-url is configured; the button opens the signed-in console and acts on nothing.",
|
|
@@ -627,12 +650,12 @@ export const CHAT_ACTION_PARITY = {
|
|
|
627
650
|
propose_task: {
|
|
628
651
|
support: "direct",
|
|
629
652
|
how: "Card with Confirm/Dismiss through confirmLeadProposal (filed as a lead proposal, via telegram). The confirmed card links Review & start for the filed task while its scope waits; under a signed automatic mode it says the scope is approved and links the task.",
|
|
630
|
-
gap: "Under manual approval the
|
|
653
|
+
gap: "Under manual approval the plan then needs the person's own yes, on its card.",
|
|
631
654
|
},
|
|
632
655
|
propose_sweep: {
|
|
633
656
|
support: "direct",
|
|
634
657
|
how: "A protected shared action (sweep_file): the card lists every item, the shared rules and the success test; confirming files them all and approves each scope.",
|
|
635
|
-
gap: "
|
|
658
|
+
gap: "Terms too long for one message open the review page, in the signed-in console.",
|
|
636
659
|
},
|
|
637
660
|
get_sweep: {
|
|
638
661
|
support: "direct",
|
|
@@ -647,7 +670,7 @@ export const CHAT_ACTION_PARITY = {
|
|
|
647
670
|
propose_scope: {
|
|
648
671
|
support: "direct",
|
|
649
672
|
how: "Confirm rewrites the scope through the shared door; the confirmed card links Review & start for the exact task.",
|
|
650
|
-
gap: "Approving the rewritten scope
|
|
673
|
+
gap: "Approving the rewritten scope is a separate yes, on its own card.",
|
|
651
674
|
},
|
|
652
675
|
propose_next: {
|
|
653
676
|
support: "direct",
|
|
@@ -686,8 +709,8 @@ export const CHAT_ACTION_PARITY = {
|
|
|
686
709
|
},
|
|
687
710
|
propose_task_action: {
|
|
688
711
|
support: "direct",
|
|
689
|
-
how: "stop, retry, plan, wait_for and stop_waiting confirm through the shared door (a stop is audited via telegram); resume
|
|
690
|
-
gap:
|
|
712
|
+
how: "stop, retry, plan, wait_for and stop_waiting confirm through the shared door (a stop is audited via telegram); resume, on a person's own tap, lifts the stop.",
|
|
713
|
+
gap: null,
|
|
691
714
|
},
|
|
692
715
|
propose_answer: {
|
|
693
716
|
support: "direct",
|
|
@@ -744,8 +767,8 @@ export function confirmedCardText(store, outcome, proposal, note) {
|
|
|
744
767
|
: revise && state === "approved"
|
|
745
768
|
? "Revision created under your automatic approval settings."
|
|
746
769
|
: said;
|
|
747
|
-
const next = resume
|
|
748
|
-
? "Nothing has resumed yet:
|
|
770
|
+
const next = resume && said.startsWith("Resume requested")
|
|
771
|
+
? "Nothing has resumed yet: finish it on the task."
|
|
749
772
|
: approval && note !== null
|
|
750
773
|
? "Approve it in Toolroll on the computer."
|
|
751
774
|
: "";
|
package/dist/chat-controls.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export declare const CHAT_CONTROLS: {
|
|
|
26
26
|
readonly label: "Open result";
|
|
27
27
|
readonly target: "task";
|
|
28
28
|
};
|
|
29
|
+
readonly findings: {
|
|
30
|
+
readonly label: "Open findings";
|
|
31
|
+
readonly target: "task";
|
|
32
|
+
};
|
|
29
33
|
readonly acceptance: {
|
|
30
34
|
readonly label: "Inspect result";
|
|
31
35
|
readonly target: "task";
|
package/dist/chat-controls.js
CHANGED
|
@@ -8,6 +8,8 @@ export const CHAT_CONTROLS = {
|
|
|
8
8
|
recovery: { label: "Review recovery options", target: "task" },
|
|
9
9
|
cancel: { label: "Cancel task", target: "task" },
|
|
10
10
|
result: { label: "Open result", target: "task" },
|
|
11
|
+
// A task's findings, failed checks and evidence: closing a finding and starting a repair happen there.
|
|
12
|
+
findings: { label: "Open findings", target: "task" },
|
|
11
13
|
acceptance: { label: "Inspect result", target: "task" },
|
|
12
14
|
publish: { label: "Review publication", target: "task" },
|
|
13
15
|
projects: { label: "Manage projects", href: "/projects" },
|
|
@@ -50,5 +52,7 @@ export function chatControlHref(control, task, run, project) {
|
|
|
50
52
|
// Task details owns cancel, retry, publication and other dedicated ceremonies.
|
|
51
53
|
if (control === "cancel" || control === "recovery" || control === "publish")
|
|
52
54
|
return "/t/" + encodeURIComponent(task);
|
|
55
|
+
if (control === "findings")
|
|
56
|
+
return `/t/${encodeURIComponent(task)}#findings`;
|
|
53
57
|
return base + (control === "approval" || control === "planning" ? "#task-chat-action" : "");
|
|
54
58
|
}
|
package/dist/chat-decide.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DECIDE_ACTS } from "./contracts/chat-callback-rows.js";
|
|
2
|
-
import {
|
|
2
|
+
import { chatApproveMode } from "./chat-approval.js";
|
|
3
3
|
import { type VerifiedApprover } from "./principal.js";
|
|
4
4
|
import type { Scope } from "./scope.js";
|
|
5
5
|
import { type ReleaseCard } from "./release-card.js";
|
|
@@ -51,13 +51,18 @@ export type DecideButton = {
|
|
|
51
51
|
};
|
|
52
52
|
/** The words, said once. */
|
|
53
53
|
export declare const DECIDE_LABELS: {
|
|
54
|
-
readonly accept: "Accept
|
|
55
|
-
readonly changes: "
|
|
54
|
+
readonly accept: "Accept";
|
|
55
|
+
readonly changes: "Send back";
|
|
56
56
|
readonly retry: "Retry";
|
|
57
57
|
readonly approve: "Approve & start";
|
|
58
58
|
readonly "not-now": "Not now";
|
|
59
59
|
readonly merge: "Merge";
|
|
60
60
|
readonly look: "Look first";
|
|
61
|
+
/** A result's one link (docs/plans/plain-toolroll.md P1.5). */
|
|
62
|
+
readonly open: "Open result";
|
|
63
|
+
/** A plan card's one button: it shows the full terms, and the Approve sits under them. Never an approval itself. */
|
|
64
|
+
readonly review: "Review plan";
|
|
65
|
+
readonly details: "Details";
|
|
61
66
|
readonly edit: "Edit";
|
|
62
67
|
readonly yes: "Yes";
|
|
63
68
|
readonly cancel: "Cancel";
|
|
@@ -81,19 +86,7 @@ export type DecideOffer = {
|
|
|
81
86
|
text: string;
|
|
82
87
|
};
|
|
83
88
|
};
|
|
84
|
-
|
|
85
|
-
* (chat-approval.ts), or else a live signed mode carrying the chatApprove term, signed by them, that names this chat
|
|
86
|
-
* app (a mode signed before the term named its apps covers Telegram alone). `digest` names that authority for the
|
|
87
|
-
* ledger; the yes itself is the person's tap and is sealed as theirs, so it doesn't lapse when the authority does. */
|
|
88
|
-
export declare function chatApproveMode(store: Store, repo: string | null, approver: string, now: Date, channel: DecideChannel): {
|
|
89
|
-
ok: true;
|
|
90
|
-
digest: string;
|
|
91
|
-
limits: ChatApprovalLimits;
|
|
92
|
-
source: "setting" | "mode";
|
|
93
|
-
} | {
|
|
94
|
-
ok: false;
|
|
95
|
-
why: string;
|
|
96
|
-
};
|
|
89
|
+
export { chatApproveMode };
|
|
97
90
|
/** A plan this person's chat may approve now: the term, the plan's exact bytes, and none of the reasons it must open
|
|
98
91
|
* Toolroll instead. `digest` binds the scope and the plan document the card shows. */
|
|
99
92
|
export declare function planInChat(store: Store, taskId: string, approver: string, now: Date, channel: DecideChannel, root?: string,
|
|
@@ -104,6 +97,7 @@ from?: "requests"): {
|
|
|
104
97
|
source: "setting" | "mode";
|
|
105
98
|
digest: string;
|
|
106
99
|
scope: Scope;
|
|
100
|
+
whole: boolean;
|
|
107
101
|
} | {
|
|
108
102
|
ok: false;
|
|
109
103
|
why: string;
|