toolroll 0.5.0
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/LICENSE +21 -0
- package/README.md +1113 -0
- package/THIRD_PARTY_NOTICES.md +449 -0
- package/dist/accent-colors.d.ts +48 -0
- package/dist/accent-colors.js +122 -0
- package/dist/action-ledger.d.ts +26 -0
- package/dist/action-ledger.js +75 -0
- package/dist/agent-fence.d.ts +42 -0
- package/dist/agent-fence.js +183 -0
- package/dist/agentconfig.d.ts +216 -0
- package/dist/agentconfig.js +454 -0
- package/dist/api-tokens.d.ts +16 -0
- package/dist/api-tokens.js +27 -0
- package/dist/approval-policy.d.ts +69 -0
- package/dist/approval-policy.js +137 -0
- package/dist/approval-rules-ui.d.ts +25 -0
- package/dist/approval-rules-ui.js +39 -0
- package/dist/assignment-adapters.d.ts +180 -0
- package/dist/assignment-adapters.js +239 -0
- package/dist/assignment-brief.d.ts +71 -0
- package/dist/assignment-brief.js +129 -0
- package/dist/assignment-delivery.d.ts +56 -0
- package/dist/assignment-delivery.js +160 -0
- package/dist/assignment-presentation.d.ts +26 -0
- package/dist/assignment-presentation.js +80 -0
- package/dist/assignment-status.d.ts +62 -0
- package/dist/assignment-status.js +152 -0
- package/dist/assignment-ui.d.ts +71 -0
- package/dist/assignment-ui.js +103 -0
- package/dist/assignment.d.ts +222 -0
- package/dist/assignment.js +399 -0
- package/dist/attest.d.ts +56 -0
- package/dist/attest.js +153 -0
- package/dist/backend.d.ts +97 -0
- package/dist/backend.js +166 -0
- package/dist/backup-ui.d.ts +22 -0
- package/dist/backup-ui.js +59 -0
- package/dist/backup.d.ts +84 -0
- package/dist/backup.js +421 -0
- package/dist/beads.d.ts +34 -0
- package/dist/beads.js +135 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +22 -0
- package/dist/board.d.ts +150 -0
- package/dist/board.js +210 -0
- package/dist/boot-identity.d.ts +63 -0
- package/dist/boot-identity.js +99 -0
- package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
- package/dist/browser/workspace.css +4 -0
- package/dist/browser/workspace.js +225 -0
- package/dist/browser-crew.d.ts +11 -0
- package/dist/browser-crew.js +50 -0
- package/dist/browser-shell.d.ts +8 -0
- package/dist/browser-shell.js +60 -0
- package/dist/browser-workspace.d.ts +780 -0
- package/dist/browser-workspace.js +47 -0
- package/dist/budget-alerts.d.ts +19 -0
- package/dist/budget-alerts.js +46 -0
- package/dist/builder.d.ts +370 -0
- package/dist/builder.js +3262 -0
- package/dist/capscan.d.ts +35 -0
- package/dist/capscan.js +113 -0
- package/dist/chat-acceptance.d.ts +71 -0
- package/dist/chat-acceptance.js +120 -0
- package/dist/chat-actions.d.ts +265 -0
- package/dist/chat-actions.js +1273 -0
- package/dist/chat-channel.d.ts +109 -0
- package/dist/chat-channel.js +652 -0
- package/dist/chat-continuity.d.ts +32 -0
- package/dist/chat-continuity.js +317 -0
- package/dist/chat-controls.d.ts +113 -0
- package/dist/chat-controls.js +53 -0
- package/dist/chat-delivery-state.d.ts +159 -0
- package/dist/chat-delivery-state.js +309 -0
- package/dist/chat-delivery.d.ts +38 -0
- package/dist/chat-delivery.js +693 -0
- package/dist/chat-display.d.ts +1 -0
- package/dist/chat-display.js +18 -0
- package/dist/chat-evidence.d.ts +123 -0
- package/dist/chat-evidence.js +207 -0
- package/dist/chat-flow.d.ts +44 -0
- package/dist/chat-flow.js +215 -0
- package/dist/chat-inbox.d.ts +57 -0
- package/dist/chat-inbox.js +123 -0
- package/dist/chat-polish.d.ts +16 -0
- package/dist/chat-polish.js +135 -0
- package/dist/chat-review.d.ts +46 -0
- package/dist/chat-review.js +98 -0
- package/dist/chat-rooms.d.ts +123 -0
- package/dist/chat-rooms.js +216 -0
- package/dist/chat-task-actions.d.ts +44 -0
- package/dist/chat-task-actions.js +79 -0
- package/dist/check-progress.d.ts +51 -0
- package/dist/check-progress.js +290 -0
- package/dist/child-database.d.ts +12 -0
- package/dist/child-database.js +30 -0
- package/dist/claim.d.ts +688 -0
- package/dist/claim.js +1740 -0
- package/dist/cli.d.ts +137 -0
- package/dist/cli.js +1461 -0
- package/dist/codex-limits.d.ts +15 -0
- package/dist/codex-limits.js +145 -0
- package/dist/coding-context.d.ts +55 -0
- package/dist/coding-context.js +92 -0
- package/dist/coding-handoff.d.ts +57 -0
- package/dist/coding-handoff.js +277 -0
- package/dist/coding-provider.d.ts +72 -0
- package/dist/coding-provider.js +424 -0
- package/dist/coding-shipping-ui.d.ts +4 -0
- package/dist/coding-shipping-ui.js +12 -0
- package/dist/coding-types.d.ts +62 -0
- package/dist/coding-types.js +1 -0
- package/dist/coding-ui.d.ts +17 -0
- package/dist/coding-ui.js +364 -0
- package/dist/coding-update.d.ts +15 -0
- package/dist/coding-update.js +149 -0
- package/dist/coding-workspace.d.ts +124 -0
- package/dist/coding-workspace.js +768 -0
- package/dist/container-state.d.ts +5 -0
- package/dist/container-state.js +62 -0
- package/dist/containment.d.ts +197 -0
- package/dist/containment.js +559 -0
- package/dist/contest.d.ts +318 -0
- package/dist/contest.js +753 -0
- package/dist/control-setup.d.ts +35 -0
- package/dist/control-setup.js +40 -0
- package/dist/control-ui.d.ts +29 -0
- package/dist/control-ui.js +53 -0
- package/dist/controller-service.d.ts +1 -0
- package/dist/controller-service.js +19 -0
- package/dist/controller-supervisor.d.ts +30 -0
- package/dist/controller-supervisor.js +104 -0
- package/dist/converse.d.ts +304 -0
- package/dist/converse.js +849 -0
- package/dist/coordinator-proposals.d.ts +29 -0
- package/dist/coordinator-proposals.js +137 -0
- package/dist/coordinator.d.ts +186 -0
- package/dist/coordinator.js +447 -0
- package/dist/credentials-ui.d.ts +25 -0
- package/dist/credentials-ui.js +48 -0
- package/dist/daemon.d.ts +209 -0
- package/dist/daemon.js +604 -0
- package/dist/decision.d.ts +120 -0
- package/dist/decision.js +388 -0
- package/dist/demo.d.ts +55 -0
- package/dist/demo.js +992 -0
- package/dist/desktop-access.d.ts +28 -0
- package/dist/desktop-access.js +88 -0
- package/dist/desktop-bundle.d.ts +16 -0
- package/dist/desktop-bundle.js +74 -0
- package/dist/desktop-host.d.ts +54 -0
- package/dist/desktop-host.js +508 -0
- package/dist/desktop-update-gate.d.ts +12 -0
- package/dist/desktop-update-gate.js +91 -0
- package/dist/desktop-update-recovery.d.ts +14 -0
- package/dist/desktop-update-recovery.js +243 -0
- package/dist/desktop-update.d.ts +110 -0
- package/dist/desktop-update.js +740 -0
- package/dist/discord-api.d.ts +20 -0
- package/dist/discord-api.js +138 -0
- package/dist/discord-chat.d.ts +16 -0
- package/dist/discord-chat.js +381 -0
- package/dist/discord-settings.d.ts +7 -0
- package/dist/discord-settings.js +75 -0
- package/dist/discord.d.ts +10 -0
- package/dist/discord.js +169 -0
- package/dist/discover.d.ts +75 -0
- package/dist/discover.js +150 -0
- package/dist/dispatch.d.ts +100 -0
- package/dist/dispatch.js +311 -0
- package/dist/dispose.d.ts +161 -0
- package/dist/dispose.js +803 -0
- package/dist/email-settings.d.ts +34 -0
- package/dist/email-settings.js +50 -0
- package/dist/envelope.d.ts +47 -0
- package/dist/envelope.js +105 -0
- package/dist/evidence-pack.d.ts +185 -0
- package/dist/evidence-pack.js +258 -0
- package/dist/evidence.d.ts +345 -0
- package/dist/evidence.js +782 -0
- package/dist/exec.d.ts +285 -0
- package/dist/exec.js +1841 -0
- package/dist/exhaustion.d.ts +85 -0
- package/dist/exhaustion.js +141 -0
- package/dist/export-ui.d.ts +4 -0
- package/dist/export-ui.js +17 -0
- package/dist/export.d.ts +48 -0
- package/dist/export.js +305 -0
- package/dist/flow-actions.d.ts +77 -0
- package/dist/flow-actions.js +203 -0
- package/dist/flow-code.d.ts +50 -0
- package/dist/flow-code.js +159 -0
- package/dist/flow-draft.d.ts +38 -0
- package/dist/flow-draft.js +80 -0
- package/dist/flow-engine.d.ts +66 -0
- package/dist/flow-engine.js +416 -0
- package/dist/flow-insights.d.ts +95 -0
- package/dist/flow-insights.js +149 -0
- package/dist/flow-live.d.ts +24 -0
- package/dist/flow-live.js +150 -0
- package/dist/flow-people.d.ts +24 -0
- package/dist/flow-people.js +91 -0
- package/dist/flow-replies.d.ts +48 -0
- package/dist/flow-replies.js +113 -0
- package/dist/flow-scripts.d.ts +38 -0
- package/dist/flow-scripts.js +73 -0
- package/dist/flow-secrets.d.ts +13 -0
- package/dist/flow-secrets.js +45 -0
- package/dist/flow-sort.d.ts +82 -0
- package/dist/flow-sort.js +153 -0
- package/dist/flow-steps.d.ts +40 -0
- package/dist/flow-steps.js +408 -0
- package/dist/flow-triggers.d.ts +244 -0
- package/dist/flow-triggers.js +959 -0
- package/dist/flows-ui.d.ts +20 -0
- package/dist/flows-ui.js +175 -0
- package/dist/flows.d.ts +229 -0
- package/dist/flows.js +968 -0
- package/dist/fonts.d.ts +19 -0
- package/dist/fonts.js +19 -0
- package/dist/gaps.d.ts +35 -0
- package/dist/gaps.js +101 -0
- package/dist/gate-failure.d.ts +40 -0
- package/dist/gate-failure.js +66 -0
- package/dist/git.d.ts +54 -0
- package/dist/git.js +94 -0
- package/dist/google-mail.d.ts +58 -0
- package/dist/google-mail.js +151 -0
- package/dist/grant.d.ts +136 -0
- package/dist/grant.js +238 -0
- package/dist/graph.d.ts +164 -0
- package/dist/graph.js +383 -0
- package/dist/guides.d.ts +22 -0
- package/dist/guides.js +363 -0
- package/dist/held.d.ts +150 -0
- package/dist/held.js +799 -0
- package/dist/invoke.d.ts +112 -0
- package/dist/invoke.js +780 -0
- package/dist/issues.d.ts +41 -0
- package/dist/issues.js +131 -0
- package/dist/job-object-helper.ps1 +252 -0
- package/dist/jsonl-discriminants.d.ts +11 -0
- package/dist/jsonl-discriminants.js +93 -0
- package/dist/keys.d.ts +104 -0
- package/dist/keys.js +229 -0
- package/dist/kits-ui.d.ts +17 -0
- package/dist/kits-ui.js +46 -0
- package/dist/kits.d.ts +86 -0
- package/dist/kits.js +215 -0
- package/dist/knowledge-cli.d.ts +101 -0
- package/dist/knowledge-cli.js +92 -0
- package/dist/knowledge-ui.d.ts +24 -0
- package/dist/knowledge-ui.js +40 -0
- package/dist/lead-context.d.ts +8 -0
- package/dist/lead-context.js +56 -0
- package/dist/lead-follow.d.ts +22 -0
- package/dist/lead-follow.js +167 -0
- package/dist/lead-status.d.ts +75 -0
- package/dist/lead-status.js +285 -0
- package/dist/ledger-chain.d.ts +46 -0
- package/dist/ledger-chain.js +187 -0
- package/dist/ledger-csv.d.ts +4 -0
- package/dist/ledger-csv.js +11 -0
- package/dist/ledger-view.d.ts +24 -0
- package/dist/ledger-view.js +58 -0
- package/dist/limits-ui.d.ts +26 -0
- package/dist/limits-ui.js +67 -0
- package/dist/link.d.ts +72 -0
- package/dist/link.js +217 -0
- package/dist/live.d.ts +96 -0
- package/dist/live.js +366 -0
- package/dist/liveness.d.ts +30 -0
- package/dist/liveness.js +42 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +25 -0
- package/dist/mailbox.d.ts +57 -0
- package/dist/mailbox.js +150 -0
- package/dist/maintenance.d.ts +11 -0
- package/dist/maintenance.js +35 -0
- package/dist/mate-cli.d.ts +52 -0
- package/dist/mate-cli.js +345 -0
- package/dist/mate-contract.d.ts +10 -0
- package/dist/mate-contract.js +30 -0
- package/dist/mate-doors.d.ts +69 -0
- package/dist/mate-doors.js +548 -0
- package/dist/mate-progress.d.ts +29 -0
- package/dist/mate-progress.js +121 -0
- package/dist/mate-tools.d.ts +94 -0
- package/dist/mate-tools.js +1878 -0
- package/dist/mate.d.ts +92 -0
- package/dist/mate.js +435 -0
- package/dist/mcp-connect.d.ts +103 -0
- package/dist/mcp-connect.js +252 -0
- package/dist/mcp.d.ts +27 -0
- package/dist/mcp.js +651 -0
- package/dist/memory-cli.d.ts +466 -0
- package/dist/memory-cli.js +111 -0
- package/dist/memory-pass.d.ts +160 -0
- package/dist/memory-pass.js +409 -0
- package/dist/metrics.d.ts +3 -0
- package/dist/metrics.js +56 -0
- package/dist/mobile-viewport.d.ts +3 -0
- package/dist/mobile-viewport.js +37 -0
- package/dist/model-catalog.d.ts +118 -0
- package/dist/model-catalog.js +376 -0
- package/dist/models-cli.d.ts +102 -0
- package/dist/models-cli.js +66 -0
- package/dist/models-ui.d.ts +34 -0
- package/dist/models-ui.js +68 -0
- package/dist/modes.d.ts +80 -0
- package/dist/modes.js +182 -0
- package/dist/monitoring-settings.d.ts +44 -0
- package/dist/monitoring-settings.js +173 -0
- package/dist/monitoring-ui.d.ts +20 -0
- package/dist/monitoring-ui.js +51 -0
- package/dist/monitoring.d.ts +34 -0
- package/dist/monitoring.js +221 -0
- package/dist/names.d.ts +67 -0
- package/dist/names.js +102 -0
- package/dist/observations.d.ts +40 -0
- package/dist/observations.js +211 -0
- package/dist/oidc.d.ts +71 -0
- package/dist/oidc.js +182 -0
- package/dist/onboard.d.ts +108 -0
- package/dist/onboard.js +325 -0
- package/dist/openrouter-models.d.ts +30 -0
- package/dist/openrouter-models.js +120 -0
- package/dist/operate.d.ts +118 -0
- package/dist/operate.js +11321 -0
- package/dist/peek-cli.d.ts +97 -0
- package/dist/peek-cli.js +215 -0
- package/dist/peek.d.ts +134 -0
- package/dist/peek.js +578 -0
- package/dist/phase-routing.d.ts +307 -0
- package/dist/phase-routing.js +658 -0
- package/dist/plan-auto.d.ts +14 -0
- package/dist/plan-auto.js +92 -0
- package/dist/plan.d.ts +186 -0
- package/dist/plan.js +401 -0
- package/dist/planner-source.d.ts +251 -0
- package/dist/planner-source.js +460 -0
- package/dist/planner.d.ts +75 -0
- package/dist/planner.js +992 -0
- package/dist/policy-ui.d.ts +20 -0
- package/dist/policy-ui.js +41 -0
- package/dist/policy.d.ts +111 -0
- package/dist/policy.js +231 -0
- package/dist/prepared-evidence.d.ts +16 -0
- package/dist/prepared-evidence.js +96 -0
- package/dist/pricing.d.ts +45 -0
- package/dist/pricing.js +77 -0
- package/dist/principal.d.ts +42 -0
- package/dist/principal.js +82 -0
- package/dist/probe.d.ts +46 -0
- package/dist/probe.js +79 -0
- package/dist/process-custody.d.ts +17 -0
- package/dist/process-custody.js +91 -0
- package/dist/process-liveness.d.ts +10 -0
- package/dist/process-liveness.js +81 -0
- package/dist/process-recovery-anchor.d.ts +75 -0
- package/dist/process-recovery-anchor.js +188 -0
- package/dist/process-recovery-coalition.d.ts +25 -0
- package/dist/process-recovery-coalition.js +105 -0
- package/dist/process-recovery-eligibility.d.ts +178 -0
- package/dist/process-recovery-eligibility.js +170 -0
- package/dist/process-recovery-native.d.ts +172 -0
- package/dist/process-recovery-native.js +592 -0
- package/dist/process-recovery-provenance.d.ts +163 -0
- package/dist/process-recovery-provenance.js +292 -0
- package/dist/process-recovery-services.d.ts +56 -0
- package/dist/process-recovery-services.js +191 -0
- package/dist/process-recovery-settlement.d.ts +32 -0
- package/dist/process-recovery-settlement.js +132 -0
- package/dist/process-recovery.d.ts +41 -0
- package/dist/process-recovery.js +91 -0
- package/dist/process-tree.d.ts +41 -0
- package/dist/process-tree.js +264 -0
- package/dist/project-access.d.ts +14 -0
- package/dist/project-access.js +34 -0
- package/dist/project-cli.d.ts +18 -0
- package/dist/project-cli.js +104 -0
- package/dist/project-delete-ui.d.ts +22 -0
- package/dist/project-delete-ui.js +48 -0
- package/dist/project-delete.d.ts +55 -0
- package/dist/project-delete.js +413 -0
- package/dist/project-knowledge.d.ts +111 -0
- package/dist/project-knowledge.js +241 -0
- package/dist/project-learning.d.ts +100 -0
- package/dist/project-learning.js +438 -0
- package/dist/project-memory.d.ts +81 -0
- package/dist/project-memory.js +264 -0
- package/dist/project-skills.d.ts +152 -0
- package/dist/project-skills.js +660 -0
- package/dist/project-tools.d.ts +219 -0
- package/dist/project-tools.js +796 -0
- package/dist/project.d.ts +61 -0
- package/dist/project.js +125 -0
- package/dist/prompt.d.ts +22 -0
- package/dist/prompt.js +72 -0
- package/dist/proof.d.ts +513 -0
- package/dist/proof.js +1140 -0
- package/dist/proposal.d.ts +82 -0
- package/dist/proposal.js +210 -0
- package/dist/provider-connection.d.ts +22 -0
- package/dist/provider-connection.js +98 -0
- package/dist/provider-limits.d.ts +35 -0
- package/dist/provider-limits.js +95 -0
- package/dist/provider.d.ts +279 -0
- package/dist/provider.js +935 -0
- package/dist/publish.d.ts +107 -0
- package/dist/publish.js +650 -0
- package/dist/pulls.d.ts +118 -0
- package/dist/pulls.js +240 -0
- package/dist/push.d.ts +95 -0
- package/dist/push.js +353 -0
- package/dist/quality.d.ts +8 -0
- package/dist/quality.js +6 -0
- package/dist/recipe-ui.d.ts +18 -0
- package/dist/recipe-ui.js +152 -0
- package/dist/recipes.d.ts +81 -0
- package/dist/recipes.js +332 -0
- package/dist/remote.d.ts +67 -0
- package/dist/remote.js +122 -0
- package/dist/render.d.ts +64 -0
- package/dist/render.js +587 -0
- package/dist/report-summary.d.ts +13 -0
- package/dist/report-summary.js +15 -0
- package/dist/repos.d.ts +65 -0
- package/dist/repos.js +277 -0
- package/dist/repository-context-ui.d.ts +2 -0
- package/dist/repository-context-ui.js +10 -0
- package/dist/repository-context.d.ts +67 -0
- package/dist/repository-context.js +376 -0
- package/dist/restart-certification.d.ts +134 -0
- package/dist/restart-certification.js +226 -0
- package/dist/result-actions.d.ts +28 -0
- package/dist/result-actions.js +270 -0
- package/dist/result-completion.d.ts +18 -0
- package/dist/result-completion.js +66 -0
- package/dist/result-review.d.ts +213 -0
- package/dist/result-review.js +430 -0
- package/dist/retention-ui.d.ts +12 -0
- package/dist/retention-ui.js +39 -0
- package/dist/retention.d.ts +72 -0
- package/dist/retention.js +288 -0
- package/dist/review-context.d.ts +243 -0
- package/dist/review-context.js +1043 -0
- package/dist/review-evidence.d.ts +33 -0
- package/dist/review-evidence.js +56 -0
- package/dist/reviewer.d.ts +97 -0
- package/dist/reviewer.js +202 -0
- package/dist/routine.d.ts +228 -0
- package/dist/routine.js +764 -0
- package/dist/runner.d.ts +266 -0
- package/dist/runner.js +399 -0
- package/dist/scan.d.ts +32 -0
- package/dist/scan.js +92 -0
- package/dist/scope.d.ts +695 -0
- package/dist/scope.js +1176 -0
- package/dist/scout-report.d.ts +42 -0
- package/dist/scout-report.js +108 -0
- package/dist/scout.d.ts +69 -0
- package/dist/scout.js +351 -0
- package/dist/serve.d.ts +313 -0
- package/dist/serve.js +21776 -0
- package/dist/session-brief.d.ts +8 -0
- package/dist/session-brief.js +24 -0
- package/dist/session-cli.d.ts +13 -0
- package/dist/session-cli.js +284 -0
- package/dist/session-contract.d.ts +183 -0
- package/dist/session-contract.js +122 -0
- package/dist/session-http.d.ts +19 -0
- package/dist/session-http.js +154 -0
- package/dist/session-server.d.ts +12 -0
- package/dist/session-server.js +37 -0
- package/dist/session-service.d.ts +22 -0
- package/dist/session-service.js +157 -0
- package/dist/setup-guide.d.ts +39 -0
- package/dist/setup-guide.js +93 -0
- package/dist/sign-in-guard.d.ts +45 -0
- package/dist/sign-in-guard.js +74 -0
- package/dist/skills-ui.d.ts +11 -0
- package/dist/skills-ui.js +58 -0
- package/dist/skills.d.ts +97 -0
- package/dist/skills.js +276 -0
- package/dist/slack-api.d.ts +55 -0
- package/dist/slack-api.js +229 -0
- package/dist/slack-chat.d.ts +28 -0
- package/dist/slack-chat.js +413 -0
- package/dist/slack-settings.d.ts +7 -0
- package/dist/slack-settings.js +75 -0
- package/dist/slack-state.d.ts +13 -0
- package/dist/slack-state.js +9 -0
- package/dist/slack.d.ts +13 -0
- package/dist/slack.js +167 -0
- package/dist/spend-ui.d.ts +28 -0
- package/dist/spend-ui.js +95 -0
- package/dist/spend.d.ts +142 -0
- package/dist/spend.js +313 -0
- package/dist/sqlite-runtime.d.ts +3 -0
- package/dist/sqlite-runtime.js +6 -0
- package/dist/sso-settings.d.ts +33 -0
- package/dist/sso-settings.js +103 -0
- package/dist/sso-ui.d.ts +22 -0
- package/dist/sso-ui.js +39 -0
- package/dist/storage.d.ts +15 -0
- package/dist/storage.js +84 -0
- package/dist/store.d.ts +7754 -0
- package/dist/store.js +23279 -0
- package/dist/structured-output.d.ts +58 -0
- package/dist/structured-output.js +103 -0
- package/dist/style-asset.d.ts +7 -0
- package/dist/style-asset.js +41 -0
- package/dist/subscription-chat.d.ts +46 -0
- package/dist/subscription-chat.js +275 -0
- package/dist/summary.d.ts +33 -0
- package/dist/summary.js +71 -0
- package/dist/supervisor.mjs +297 -0
- package/dist/surface.d.ts +63 -0
- package/dist/surface.js +352 -0
- package/dist/sync.d.ts +94 -0
- package/dist/sync.js +279 -0
- package/dist/task-composer.d.ts +13 -0
- package/dist/task-composer.js +52 -0
- package/dist/task-control.d.ts +165 -0
- package/dist/task-control.js +214 -0
- package/dist/task-outcome-cli.d.ts +10 -0
- package/dist/task-outcome-cli.js +92 -0
- package/dist/task-text.d.ts +30 -0
- package/dist/task-text.js +41 -0
- package/dist/team-cli.d.ts +15 -0
- package/dist/team-cli.js +618 -0
- package/dist/team-contract.d.ts +92 -0
- package/dist/team-contract.js +1 -0
- package/dist/team-http.d.ts +17 -0
- package/dist/team-http.js +144 -0
- package/dist/team-leads.d.ts +81 -0
- package/dist/team-leads.js +565 -0
- package/dist/team-runtime.d.ts +27 -0
- package/dist/team-runtime.js +264 -0
- package/dist/team-ui.d.ts +3 -0
- package/dist/team-ui.js +9 -0
- package/dist/team-updates.d.ts +8 -0
- package/dist/team-updates.js +57 -0
- package/dist/teammate-admin.d.ts +53 -0
- package/dist/teammate-admin.js +111 -0
- package/dist/teammate-desk.d.ts +60 -0
- package/dist/teammate-desk.js +154 -0
- package/dist/teammate-memory.d.ts +64 -0
- package/dist/teammate-memory.js +196 -0
- package/dist/teammate-question.d.ts +59 -0
- package/dist/teammate-question.js +175 -0
- package/dist/teammate-tools.d.ts +108 -0
- package/dist/teammate-tools.js +271 -0
- package/dist/teammate-week.d.ts +68 -0
- package/dist/teammate-week.js +132 -0
- package/dist/teammate-work.d.ts +76 -0
- package/dist/teammate-work.js +280 -0
- package/dist/teammates-ui.d.ts +20 -0
- package/dist/teammates-ui.js +166 -0
- package/dist/teammates.d.ts +180 -0
- package/dist/teammates.js +253 -0
- package/dist/teams-api.d.ts +33 -0
- package/dist/teams-api.js +204 -0
- package/dist/teams-chat.d.ts +26 -0
- package/dist/teams-chat.js +215 -0
- package/dist/teams-settings.d.ts +12 -0
- package/dist/teams-settings.js +57 -0
- package/dist/teams.d.ts +21 -0
- package/dist/teams.js +124 -0
- package/dist/telegram-flow.d.ts +49 -0
- package/dist/telegram-flow.js +110 -0
- package/dist/telegram-mate.d.ts +137 -0
- package/dist/telegram-mate.js +707 -0
- package/dist/telegram-progress.d.ts +14 -0
- package/dist/telegram-progress.js +129 -0
- package/dist/telegram-settings.d.ts +9 -0
- package/dist/telegram-settings.js +36 -0
- package/dist/telegram-status.d.ts +75 -0
- package/dist/telegram-status.js +265 -0
- package/dist/telegram-team.d.ts +85 -0
- package/dist/telegram-team.js +359 -0
- package/dist/telegram.d.ts +230 -0
- package/dist/telegram.js +1931 -0
- package/dist/templates.d.ts +65 -0
- package/dist/templates.js +118 -0
- package/dist/tool-launcher.d.ts +1 -0
- package/dist/tool-launcher.js +101 -0
- package/dist/tools-ui.d.ts +30 -0
- package/dist/tools-ui.js +40 -0
- package/dist/transitions-recipes.d.ts +1 -0
- package/dist/transitions-recipes.js +203 -0
- package/dist/tree-proof.d.ts +34 -0
- package/dist/tree-proof.js +58 -0
- package/dist/verification-evidence.d.ts +44 -0
- package/dist/verification-evidence.js +238 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +10 -0
- package/dist/webhooks.d.ts +91 -0
- package/dist/webhooks.js +283 -0
- package/dist/work-index.d.ts +68 -0
- package/dist/work-index.js +384 -0
- package/dist/work-summary.d.ts +57 -0
- package/dist/work-summary.js +116 -0
- package/dist/workspace-motion.d.ts +4 -0
- package/dist/workspace-motion.js +133 -0
- package/dist/workspace-revision.d.ts +19 -0
- package/dist/workspace-revision.js +92 -0
- package/dist/workspace-ui.d.ts +204 -0
- package/dist/workspace-ui.js +411 -0
- package/dist/worktree-notices.d.ts +13 -0
- package/dist/worktree-notices.js +17 -0
- package/dist/worktree.d.ts +249 -0
- package/dist/worktree.js +720 -0
- package/package.json +122 -0
- package/scripts/canary-assertions.mjs +42 -0
- package/scripts/crash-canary.mjs +253 -0
- package/scripts/fixtures/crash-process.mjs +74 -0
- package/scripts/fixtures/pilot-scenarios.mjs +85 -0
- package/scripts/fixtures/restart-service.mjs +27 -0
- package/scripts/launchd-certification.mjs +143 -0
- package/scripts/pilot.mjs +121 -0
- package/scripts/proof-preflight.mjs +140 -0
- package/scripts/provider-canary.mjs +379 -0
- package/scripts/recovery-canary.mjs +135 -0
- package/scripts/restart-certification.mjs +98 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings → Retention (v105): how long each kind of data is kept, and what
|
|
3
|
+
* the next daily sweep would remove. An instance operator's page; changes
|
|
4
|
+
* take a step-up.
|
|
5
|
+
*/
|
|
6
|
+
import { bytesWords } from "./storage.js";
|
|
7
|
+
import { PERIOD_CHOICES, RETENTION_KINDS, countWords, periodWords } from "./retention.js";
|
|
8
|
+
const e = (value) => String(value ?? "").replace(/[&<>"']/g, c => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
9
|
+
export const RETENTION_CSS = `.retention{max-width:720px;min-width:0}.retention-next{margin:0 0 16px}` +
|
|
10
|
+
`.retention form{display:grid;gap:0}.retention .kind{display:grid;grid-template-columns:minmax(0,1fr) 11rem;gap:4px 16px;align-items:center;padding:12px 0;border-bottom:1px solid var(--border)}` +
|
|
11
|
+
`.retention .kind .name{font-weight:500;font-size:.875rem}.retention .kind .meta{grid-column:1;margin:0}.retention .kind select{grid-column:2;grid-row:1/span 2;width:100%;min-height:44px}` +
|
|
12
|
+
`.retention .step-up{display:grid;gap:4px;font-size:.8125rem;margin:16px 0 8px;max-width:20rem}.retention .step-up input{min-height:44px}.retention button{justify-self:start;min-height:44px}` +
|
|
13
|
+
`@media (max-width:560px){.retention .kind{grid-template-columns:minmax(0,1fr)}.retention .kind select{grid-column:1;grid-row:auto}}`;
|
|
14
|
+
const listWords = (parts) => parts.length < 2 ? parts.join("") : `${parts.slice(0, -1).join(", ")} and ${parts.at(-1)}`;
|
|
15
|
+
/** The next sweep in a line: what goes and about how much space, or that nothing is due. */
|
|
16
|
+
function nextWords(view) {
|
|
17
|
+
if (RETENTION_KINDS.every(({ kind }) => view.periods[kind] === null))
|
|
18
|
+
return "Everything is kept forever.";
|
|
19
|
+
const due = view.next.filter(one => one.count > 0);
|
|
20
|
+
if (due.length === 0)
|
|
21
|
+
return "Nothing is old enough to remove yet.";
|
|
22
|
+
const bytes = due.reduce((sum, one) => sum + one.bytes, 0);
|
|
23
|
+
return `The next daily sweep removes ${listWords(due.map(countWords))} (about ${bytesWords(bytes)}).`;
|
|
24
|
+
}
|
|
25
|
+
export function retentionHtml(view, notice) {
|
|
26
|
+
const note = notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : notice.said ? `<p role="status">${e(notice.said)}</p>` : "";
|
|
27
|
+
const rows = RETENTION_KINDS.map(({ kind, label, detail }) => {
|
|
28
|
+
const current = view.periods[kind];
|
|
29
|
+
const choices = PERIOD_CHOICES.includes(current) ? PERIOD_CHOICES : [...PERIOD_CHOICES.slice(0, -1), current, null].sort((a, b) => (a ?? Infinity) - (b ?? Infinity));
|
|
30
|
+
const options = choices.map(days => `<option value="${days === null ? "forever" : days}"${days === current ? " selected" : ""}>${days === null ? "Forever" : `${periodWords(days)[0].toUpperCase()}${periodWords(days).slice(1)}`}</option>`).join("");
|
|
31
|
+
return `<div class="kind" data-kind="${kind}"><label class="name" for="keep-${kind}">${e(label)}</label><p class="meta">${e(detail)}</p><select id="keep-${kind}" name="${kind}">${options}</select></div>`;
|
|
32
|
+
}).join("");
|
|
33
|
+
const last = view.lastSweep === null ? "" : ` Last sweep ${e(view.lastSweep.slice(0, 10))}.`;
|
|
34
|
+
return `<article class="retention">${note}<p class="retention-next" data-retention-next>${e(nextWords(view))}${last}</p>` +
|
|
35
|
+
`<form method="post" action="/settings/retention"><input type="hidden" name="csrf" value="${e(view.csrf)}">${rows}` +
|
|
36
|
+
`<label class="step-up">Your Toolroll password<input type="password" name="password" autocomplete="current-password" required></label>` +
|
|
37
|
+
`<button type="submit">Save</button></form>` +
|
|
38
|
+
`<p class="meta">Never removed: the action ledger, and anything a task still needs (unfinished tasks, results not yet completed, anything on hold).</p></article>`;
|
|
39
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Store } from "./store.js";
|
|
2
|
+
export declare const RETENTION_SCHEMA = "\nCREATE TABLE IF NOT EXISTS retention_setting (\n kind TEXT PRIMARY KEY CHECK (kind IN ('evidence', 'checkouts', 'chat', 'notifications')),\n -- NULL is forever; a row only exists once someone chose.\n days INTEGER CHECK (days IS NULL OR (days >= 7 AND days <= 3650)),\n updated_by TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n";
|
|
3
|
+
export type RetentionKind = "evidence" | "checkouts" | "chat" | "notifications";
|
|
4
|
+
export type RetentionPeriods = Record<RetentionKind, number | null>;
|
|
5
|
+
export declare const RETENTION_KINDS: readonly {
|
|
6
|
+
kind: RetentionKind;
|
|
7
|
+
label: string;
|
|
8
|
+
detail: string;
|
|
9
|
+
}[];
|
|
10
|
+
/** The periods the page offers; the command line takes any number of days from 7 to 3650. */
|
|
11
|
+
export declare const PERIOD_CHOICES: readonly (number | null)[];
|
|
12
|
+
export declare const MIN_DAYS = 7;
|
|
13
|
+
export declare const MAX_DAYS = 3650;
|
|
14
|
+
/** A sweep is due once a day. */
|
|
15
|
+
export declare const SWEEP_EVERY_MS = 86400000;
|
|
16
|
+
/** At most this many runs, messages, notifications or records go per kind per sweep; the next sweep takes the rest. */
|
|
17
|
+
export declare const SWEEP_BATCH = 2000;
|
|
18
|
+
export declare const FOREVER: RetentionPeriods;
|
|
19
|
+
export declare function isRetentionKind(value: string): value is RetentionKind;
|
|
20
|
+
/** "forever", or a number of days ("90", "90d"), weeks ("12w") or years ("1y"); undefined when it's none of those or out of range. */
|
|
21
|
+
export declare function parsePeriod(text: string): number | null | undefined;
|
|
22
|
+
export declare function periodWords(days: number | null): string;
|
|
23
|
+
export type RetentionCount = {
|
|
24
|
+
kind: RetentionKind;
|
|
25
|
+
days: number | null;
|
|
26
|
+
count: number;
|
|
27
|
+
bytes: number;
|
|
28
|
+
more: boolean;
|
|
29
|
+
};
|
|
30
|
+
export type RetentionPlan = {
|
|
31
|
+
at: string;
|
|
32
|
+
counts: RetentionCount[];
|
|
33
|
+
items: RetentionItems;
|
|
34
|
+
};
|
|
35
|
+
type RetentionItems = {
|
|
36
|
+
evidence: {
|
|
37
|
+
run: number;
|
|
38
|
+
bytes: number;
|
|
39
|
+
}[];
|
|
40
|
+
checkouts: {
|
|
41
|
+
path: string;
|
|
42
|
+
releasedAt: string;
|
|
43
|
+
bytes: number;
|
|
44
|
+
}[];
|
|
45
|
+
chat: {
|
|
46
|
+
id: number;
|
|
47
|
+
bytes: number;
|
|
48
|
+
}[];
|
|
49
|
+
notifications: {
|
|
50
|
+
id: number;
|
|
51
|
+
bytes: number;
|
|
52
|
+
}[];
|
|
53
|
+
};
|
|
54
|
+
/** What a sweep would delete now under `periods`, and how much space it would free. Reads only. */
|
|
55
|
+
export declare function retentionPlan(store: Store, evidenceRoot: string, now: Date, periods?: RetentionPeriods): RetentionPlan;
|
|
56
|
+
export type RetentionSweep = {
|
|
57
|
+
at: string;
|
|
58
|
+
counts: RetentionCount[];
|
|
59
|
+
freed: number;
|
|
60
|
+
ledgerId: number | null;
|
|
61
|
+
};
|
|
62
|
+
/** Delete what the plan names (checking each again first) and write one ledger entry. Nothing to do when every kind is forever. */
|
|
63
|
+
export declare function sweepRetention(store: Store, evidenceRoot: string, now: Date, actor?: string): RetentionSweep;
|
|
64
|
+
/** Whether a day has passed since the last sweep. */
|
|
65
|
+
export declare function retentionDue(store: Store, now: Date): boolean;
|
|
66
|
+
/** The daily sweep, when it's due: one worker takes it (the cursor moves in the same transaction). */
|
|
67
|
+
export declare function dailyRetention(store: Store, evidenceRoot: string, now: Date): RetentionSweep | null;
|
|
68
|
+
export declare function lastSweepAt(store: Store): string | null;
|
|
69
|
+
export declare function countWords(one: Pick<RetentionCount, "kind" | "count">): string;
|
|
70
|
+
/** "3 runs' evidence, 120 chat messages; about 41 MB freed", or "nothing was due". */
|
|
71
|
+
export declare function sweepWords(counts: readonly RetentionCount[], freed: number): string;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retention (v105): how long Toolroll keeps run evidence and logs,
|
|
3
|
+
* finished checkouts' records, chat messages and notifications. Each kind
|
|
4
|
+
* keeps everything ("forever") until an instance operator chooses a period;
|
|
5
|
+
* a daily sweep then deletes what is older than it and writes one action
|
|
6
|
+
* ledger entry saying what went and about how much space it freed.
|
|
7
|
+
*
|
|
8
|
+
* Never deleted, whatever the settings: the action ledger (it is append-only),
|
|
9
|
+
* and anything a task still needs. A task still needs its things until it is
|
|
10
|
+
* cancelled, or done with its result marked complete: an unfinished task
|
|
11
|
+
* (failed included: it can be requeued), a result not yet completed, a task
|
|
12
|
+
* on hold, one with a live run, a release candidate, and the source of an
|
|
13
|
+
* unfinished revision all keep theirs.
|
|
14
|
+
*
|
|
15
|
+
* Evidence goes as files: a run's evidence folder is emptied and a note left
|
|
16
|
+
* in it, so its pages say the files were removed by retention rather than
|
|
17
|
+
* damaged. Its database records (hashes, sizes, how each was captured) stay.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, lstatSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { RETENTION_NOTE } from "./evidence.js";
|
|
22
|
+
import { COMPLETION_ACTION } from "./result-completion.js";
|
|
23
|
+
import { bytesWords, treeBytes } from "./storage.js";
|
|
24
|
+
export const RETENTION_SCHEMA = `
|
|
25
|
+
CREATE TABLE IF NOT EXISTS retention_setting (
|
|
26
|
+
kind TEXT PRIMARY KEY CHECK (kind IN ('evidence', 'checkouts', 'chat', 'notifications')),
|
|
27
|
+
-- NULL is forever; a row only exists once someone chose.
|
|
28
|
+
days INTEGER CHECK (days IS NULL OR (days >= 7 AND days <= 3650)),
|
|
29
|
+
updated_by TEXT NOT NULL,
|
|
30
|
+
updated_at TEXT NOT NULL
|
|
31
|
+
);
|
|
32
|
+
`;
|
|
33
|
+
export const RETENTION_KINDS = [
|
|
34
|
+
{ kind: "evidence", label: "Run evidence and logs", detail: "Diffs, check logs, screenshots and reports saved for each run" },
|
|
35
|
+
{ kind: "checkouts", label: "Finished checkout records", detail: "Records of build checkouts that were let go and are no longer on disk" },
|
|
36
|
+
{ kind: "chat", label: "Chat messages", detail: "Messages in lead and team chats" },
|
|
37
|
+
{ kind: "notifications", label: "Notifications", detail: "Delivered or dismissed notifications" },
|
|
38
|
+
];
|
|
39
|
+
/** The periods the page offers; the command line takes any number of days from 7 to 3650. */
|
|
40
|
+
export const PERIOD_CHOICES = [30, 90, 180, 365, 730, null];
|
|
41
|
+
export const MIN_DAYS = 7;
|
|
42
|
+
export const MAX_DAYS = 3650;
|
|
43
|
+
const DAY_MS = 86_400_000;
|
|
44
|
+
/** A sweep is due once a day. */
|
|
45
|
+
export const SWEEP_EVERY_MS = DAY_MS;
|
|
46
|
+
/** At most this many runs, messages, notifications or records go per kind per sweep; the next sweep takes the rest. */
|
|
47
|
+
export const SWEEP_BATCH = 2000;
|
|
48
|
+
const SWEEP_CURSOR = "retention:last-sweep";
|
|
49
|
+
export const FOREVER = { evidence: null, checkouts: null, chat: null, notifications: null };
|
|
50
|
+
export function isRetentionKind(value) {
|
|
51
|
+
return RETENTION_KINDS.some(one => one.kind === value);
|
|
52
|
+
}
|
|
53
|
+
/** "forever", or a number of days ("90", "90d"), weeks ("12w") or years ("1y"); undefined when it's none of those or out of range. */
|
|
54
|
+
export function parsePeriod(text) {
|
|
55
|
+
const value = text.trim().toLowerCase();
|
|
56
|
+
if (value === "forever" || value === "never")
|
|
57
|
+
return null;
|
|
58
|
+
const match = /^(\d{1,4})\s*(d|days?|w|weeks?|y|years?)?$/.exec(value);
|
|
59
|
+
if (match === null)
|
|
60
|
+
return undefined;
|
|
61
|
+
const unit = match[2]?.[0] ?? "d";
|
|
62
|
+
const days = Number(match[1]) * (unit === "y" ? 365 : unit === "w" ? 7 : 1);
|
|
63
|
+
return days >= MIN_DAYS && days <= MAX_DAYS ? days : undefined;
|
|
64
|
+
}
|
|
65
|
+
export function periodWords(days) {
|
|
66
|
+
if (days === null)
|
|
67
|
+
return "forever";
|
|
68
|
+
if (days % 365 === 0)
|
|
69
|
+
return days === 365 ? "1 year" : `${days / 365} years`;
|
|
70
|
+
return `${days} days`;
|
|
71
|
+
}
|
|
72
|
+
/** Tasks that no longer need anything kept: cancelled, or done with their result marked complete; not on hold, not
|
|
73
|
+
* running, not a release candidate, and no revision below it (at any depth) still unfinished — cancelled or completed,
|
|
74
|
+
* not merely Ready: a revision's review reads its ancestors' evidence. `r` is the task_ref alias. */
|
|
75
|
+
function finishedTask(r) {
|
|
76
|
+
return `EXISTS (SELECT 1 FROM task t WHERE t.id = ${r}.external_id AND ${r}.backend = 'built-in' AND (t.state = 'cancelled' OR (t.state = 'done' AND EXISTS (
|
|
77
|
+
SELECT 1 FROM action_ledger a WHERE a.action = '${COMPLETION_ACTION}' AND (a.task_id = ${r}.external_id OR a.run_id IN (SELECT id FROM run WHERE task_ref = ${r}.id))))))
|
|
78
|
+
AND NOT EXISTS (SELECT 1 FROM hold h WHERE h.task_ref = ${r}.id)
|
|
79
|
+
AND NOT EXISTS (SELECT 1 FROM run live WHERE live.task_ref = ${r}.id AND live.finished_at IS NULL)
|
|
80
|
+
AND NOT EXISTS (SELECT 1 FROM task_scope s WHERE s.task_id = ${r}.external_id AND s.candidate IS NOT NULL)
|
|
81
|
+
AND NOT EXISTS (WITH RECURSIVE family(ext) AS (
|
|
82
|
+
SELECT rv.external_id FROM task_ref rv WHERE rv.revision_of = ${r}.external_id
|
|
83
|
+
UNION SELECT rv.external_id FROM task_ref rv JOIN family ON rv.revision_of = family.ext)
|
|
84
|
+
SELECT 1 FROM family JOIN task tv ON tv.id = family.ext
|
|
85
|
+
WHERE NOT (tv.state = 'cancelled' OR (tv.state = 'done' AND EXISTS (SELECT 1 FROM action_ledger a WHERE a.action = '${COMPLETION_ACTION}'
|
|
86
|
+
AND (a.task_id = family.ext OR a.run_id IN (SELECT run.id FROM run JOIN task_ref x ON x.id = run.task_ref WHERE x.external_id = family.ext))))))`;
|
|
87
|
+
}
|
|
88
|
+
function cutoff(now, days) {
|
|
89
|
+
return new Date(now.getTime() - days * DAY_MS).toISOString();
|
|
90
|
+
}
|
|
91
|
+
/** Whether a folder holds anything but the retention note. */
|
|
92
|
+
function holdsFiles(dir) {
|
|
93
|
+
try {
|
|
94
|
+
return readdirSync(dir).some(name => name !== RETENTION_NOTE);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** What a sweep would delete now under `periods`, and how much space it would free. Reads only. */
|
|
101
|
+
export function retentionPlan(store, evidenceRoot, now, periods = store.retentionPeriods()) {
|
|
102
|
+
const db = store.handle;
|
|
103
|
+
const items = { evidence: [], checkouts: [], chat: [], notifications: [] };
|
|
104
|
+
const more = { evidence: false, checkouts: false, chat: false, notifications: false };
|
|
105
|
+
if (periods.evidence !== null) {
|
|
106
|
+
const rows = db.prepare(`SELECT run.id AS id FROM run JOIN task_ref r ON r.id = run.task_ref
|
|
107
|
+
WHERE run.finished_at IS NOT NULL AND run.finished_at < ? AND ${finishedTask("r")} ORDER BY run.id`).all(cutoff(now, periods.evidence));
|
|
108
|
+
for (const row of rows) {
|
|
109
|
+
const run = Number(row["id"]);
|
|
110
|
+
const dir = join(evidenceRoot, String(run));
|
|
111
|
+
if (!holdsFiles(dir))
|
|
112
|
+
continue;
|
|
113
|
+
if (items.evidence.length >= SWEEP_BATCH) {
|
|
114
|
+
more.evidence = true;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
items.evidence.push({ run, bytes: folderBytes(dir) });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (periods.checkouts !== null) {
|
|
121
|
+
const rows = db.prepare(`SELECT w.path AS path, w.released_at AS released_at, length(w.path) + length(w.repo) + length(w.branch) + 64 AS bytes FROM worktree w
|
|
122
|
+
WHERE w.runner IS NULL AND w.released_at IS NOT NULL AND w.released_at < ?
|
|
123
|
+
AND (w.task_ref IS NULL OR EXISTS (SELECT 1 FROM task_ref r WHERE r.id = w.task_ref AND ${finishedTask("r")})) ORDER BY w.released_at`).all(cutoff(now, periods.checkouts));
|
|
124
|
+
for (const row of rows) {
|
|
125
|
+
const path = String(row["path"]);
|
|
126
|
+
// Only the record of a checkout that's gone from disk: the checkout itself is storage retention's (two days after it's let go).
|
|
127
|
+
if (existsSync(path))
|
|
128
|
+
continue;
|
|
129
|
+
if (items.checkouts.length >= SWEEP_BATCH) {
|
|
130
|
+
more.checkouts = true;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
items.checkouts.push({ path, releasedAt: String(row["released_at"]), bytes: Number(row["bytes"]) });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (periods.chat !== null) {
|
|
137
|
+
const rows = db.prepare(`SELECT m.id AS id, length(m.text) + COALESCE(length(m.activity), 0) + 64 AS bytes FROM mate_message m JOIN mate_thread th ON th.id = m.thread
|
|
138
|
+
WHERE m.created_at < ?
|
|
139
|
+
AND NOT EXISTS (SELECT 1 FROM team_message tm WHERE tm.message = m.id AND tm.status IN ('queued', 'running', 'uncertain'))
|
|
140
|
+
AND NOT EXISTS (SELECT 1 FROM mate_turn turn WHERE turn.id = m.turn AND turn.state IN ('queued', 'running'))
|
|
141
|
+
AND NOT (th.scope_kind = 'task' AND NOT EXISTS (SELECT 1 FROM task_ref r WHERE r.external_id = th.scope_key AND ${finishedTask("r")}))
|
|
142
|
+
ORDER BY m.id LIMIT ?`).all(cutoff(now, periods.chat), SWEEP_BATCH + 1);
|
|
143
|
+
more.chat = rows.length > SWEEP_BATCH;
|
|
144
|
+
items.chat = rows.slice(0, SWEEP_BATCH).map(row => ({ id: Number(row["id"]), bytes: Number(row["bytes"]) }));
|
|
145
|
+
}
|
|
146
|
+
if (periods.notifications !== null) {
|
|
147
|
+
const rows = db.prepare(`SELECT n.id AS id, length(n.subject) + length(n.body) + COALESCE(length(n.receipt), 0) + COALESCE(length(n.last_error), 0) + 64 AS bytes FROM notification n
|
|
148
|
+
WHERE n.created_at < ? AND (n.resolved_at IS NOT NULL OR n.delivered_at IS NOT NULL)
|
|
149
|
+
AND NOT (n.claim_owner IS NOT NULL AND n.claim_expires_at > ?)
|
|
150
|
+
AND NOT EXISTS (SELECT 1 FROM notification_delivery d WHERE d.notification = n.id AND d.claim_owner IS NOT NULL AND d.claim_expires_at > ?)
|
|
151
|
+
AND NOT (n.resolved_at IS NULL AND n.task_ref IS NOT NULL AND NOT EXISTS (SELECT 1 FROM task_ref r WHERE r.id = n.task_ref AND ${finishedTask("r")}))
|
|
152
|
+
ORDER BY n.id LIMIT ?`).all(cutoff(now, periods.notifications), now.toISOString(), now.toISOString(), SWEEP_BATCH + 1);
|
|
153
|
+
more.notifications = rows.length > SWEEP_BATCH;
|
|
154
|
+
items.notifications = rows.slice(0, SWEEP_BATCH).map(row => ({ id: Number(row["id"]), bytes: Number(row["bytes"]) }));
|
|
155
|
+
}
|
|
156
|
+
const counts = RETENTION_KINDS.map(({ kind }) => ({
|
|
157
|
+
kind, days: periods[kind], count: items[kind].length,
|
|
158
|
+
bytes: items[kind].reduce((sum, one) => sum + one.bytes, 0), more: more[kind],
|
|
159
|
+
}));
|
|
160
|
+
return { at: now.toISOString(), counts, items };
|
|
161
|
+
}
|
|
162
|
+
/** Bytes a folder holds, the retention note aside. */
|
|
163
|
+
function folderBytes(dir) {
|
|
164
|
+
let total = 0;
|
|
165
|
+
for (const name of readdirSync(dir))
|
|
166
|
+
if (name !== RETENTION_NOTE)
|
|
167
|
+
total += treeBytes(join(dir, name));
|
|
168
|
+
return total;
|
|
169
|
+
}
|
|
170
|
+
/** Delete what the plan names (checking each again first) and write one ledger entry. Nothing to do when every kind is forever. */
|
|
171
|
+
export function sweepRetention(store, evidenceRoot, now, actor = "worker") {
|
|
172
|
+
const periods = store.retentionPeriods();
|
|
173
|
+
store.setServiceCursor(SWEEP_CURSOR, now.getTime(), now);
|
|
174
|
+
if (RETENTION_KINDS.every(({ kind }) => periods[kind] === null))
|
|
175
|
+
return { at: now.toISOString(), counts: [], freed: 0, ledgerId: null };
|
|
176
|
+
const plan = retentionPlan(store, evidenceRoot, now, periods);
|
|
177
|
+
const db = store.handle;
|
|
178
|
+
const done = { evidence: { count: 0, bytes: 0 }, checkouts: { count: 0, bytes: 0 }, chat: { count: 0, bytes: 0 }, notifications: { count: 0, bytes: 0 } };
|
|
179
|
+
// Evidence: each run's folder is emptied and a note left, so its pages say why the files are gone.
|
|
180
|
+
if (periods.evidence !== null) {
|
|
181
|
+
const still = db.prepare(`SELECT 1 FROM run JOIN task_ref r ON r.id = run.task_ref WHERE run.id = ? AND run.finished_at IS NOT NULL AND run.finished_at < ? AND ${finishedTask("r")}`);
|
|
182
|
+
const before = cutoff(now, periods.evidence);
|
|
183
|
+
for (const one of plan.items.evidence) {
|
|
184
|
+
if (still.get(one.run, before) === undefined)
|
|
185
|
+
continue;
|
|
186
|
+
const dir = join(evidenceRoot, String(one.run));
|
|
187
|
+
try {
|
|
188
|
+
if (!lstatSync(dir).isDirectory())
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
let freed = 0;
|
|
195
|
+
for (const name of readdirSync(dir)) {
|
|
196
|
+
if (name === RETENTION_NOTE)
|
|
197
|
+
continue;
|
|
198
|
+
const bytes = treeBytes(join(dir, name));
|
|
199
|
+
try {
|
|
200
|
+
rmSync(join(dir, name), { recursive: true, force: true });
|
|
201
|
+
freed += bytes;
|
|
202
|
+
}
|
|
203
|
+
catch { /* left for the next sweep */ }
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
writeFileSync(join(dir, RETENTION_NOTE), `Removed by the retention setting on ${now.toISOString().slice(0, 10)}.\n`, { mode: 0o600 });
|
|
207
|
+
}
|
|
208
|
+
catch { /* the folder's emptiness says it */ }
|
|
209
|
+
done.evidence.count++;
|
|
210
|
+
done.evidence.bytes += freed;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
store.transact(() => {
|
|
214
|
+
if (periods.checkouts !== null) {
|
|
215
|
+
const forget = db.prepare("DELETE FROM worktree WHERE path = ? AND runner IS NULL AND released_at = ?");
|
|
216
|
+
for (const one of plan.items.checkouts) {
|
|
217
|
+
if (existsSync(one.path))
|
|
218
|
+
continue;
|
|
219
|
+
if (Number(forget.run(one.path, one.releasedAt).changes) === 1) {
|
|
220
|
+
done.checkouts.count++;
|
|
221
|
+
done.checkouts.bytes += one.bytes;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (periods.chat !== null) {
|
|
226
|
+
const team = db.prepare("DELETE FROM team_message WHERE message = ? AND status NOT IN ('queued', 'running', 'uncertain')");
|
|
227
|
+
const message = db.prepare("DELETE FROM mate_message WHERE id = ? AND NOT EXISTS (SELECT 1 FROM team_message WHERE message = ?)");
|
|
228
|
+
for (const one of plan.items.chat) {
|
|
229
|
+
team.run(one.id);
|
|
230
|
+
if (Number(message.run(one.id, one.id).changes) === 1) {
|
|
231
|
+
done.chat.count++;
|
|
232
|
+
done.chat.bytes += one.bytes;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (periods.notifications !== null) {
|
|
237
|
+
const deliveries = db.prepare("DELETE FROM notification_delivery WHERE notification = ?");
|
|
238
|
+
const outbound = db.prepare("DELETE FROM telegram_outbound_message WHERE notification = ?");
|
|
239
|
+
const pushes = db.prepare("DELETE FROM push_delivery WHERE notification = ?");
|
|
240
|
+
const notification = db.prepare("DELETE FROM notification WHERE id = ?");
|
|
241
|
+
for (const one of plan.items.notifications) {
|
|
242
|
+
deliveries.run(one.id);
|
|
243
|
+
outbound.run(one.id);
|
|
244
|
+
pushes.run(one.id);
|
|
245
|
+
if (Number(notification.run(one.id).changes) === 1) {
|
|
246
|
+
done.notifications.count++;
|
|
247
|
+
done.notifications.bytes += one.bytes;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
const counts = plan.counts.map(one => ({ ...one, count: done[one.kind].count, bytes: done[one.kind].bytes }));
|
|
253
|
+
const freed = counts.reduce((sum, one) => sum + one.bytes, 0);
|
|
254
|
+
const ledgerId = store.recordAction({ at: now.toISOString(), actor, repo: null, taskId: null, runId: null, action: "retention sweep", outcome: freed > 0 || counts.some(one => one.count > 0) ? "removed" : "nothing due", source: "policy", detail: sweepWords(counts, freed) });
|
|
255
|
+
return { at: now.toISOString(), counts, freed, ledgerId };
|
|
256
|
+
}
|
|
257
|
+
/** Whether a day has passed since the last sweep. */
|
|
258
|
+
export function retentionDue(store, now) {
|
|
259
|
+
return now.getTime() - store.serviceCursor(SWEEP_CURSOR) >= SWEEP_EVERY_MS;
|
|
260
|
+
}
|
|
261
|
+
/** The daily sweep, when it's due: one worker takes it (the cursor moves in the same transaction). */
|
|
262
|
+
export function dailyRetention(store, evidenceRoot, now) {
|
|
263
|
+
const mine = store.transact(() => {
|
|
264
|
+
if (!retentionDue(store, now))
|
|
265
|
+
return false;
|
|
266
|
+
store.setServiceCursor(SWEEP_CURSOR, now.getTime(), now);
|
|
267
|
+
return true;
|
|
268
|
+
});
|
|
269
|
+
return mine ? sweepRetention(store, evidenceRoot, now) : null;
|
|
270
|
+
}
|
|
271
|
+
export function lastSweepAt(store) {
|
|
272
|
+
const at = store.serviceCursor(SWEEP_CURSOR);
|
|
273
|
+
return at === 0 ? null : new Date(at).toISOString();
|
|
274
|
+
}
|
|
275
|
+
const NOUNS = {
|
|
276
|
+
evidence: ["run's evidence", "runs' evidence"],
|
|
277
|
+
checkouts: ["checkout record", "checkout records"],
|
|
278
|
+
chat: ["chat message", "chat messages"],
|
|
279
|
+
notifications: ["notification", "notifications"],
|
|
280
|
+
};
|
|
281
|
+
export function countWords(one) {
|
|
282
|
+
return `${one.count} ${NOUNS[one.kind][one.count === 1 ? 0 : 1]}`;
|
|
283
|
+
}
|
|
284
|
+
/** "3 runs' evidence, 120 chat messages; about 41 MB freed", or "nothing was due". */
|
|
285
|
+
export function sweepWords(counts, freed) {
|
|
286
|
+
const parts = counts.filter(one => one.count > 0).map(countWords);
|
|
287
|
+
return parts.length === 0 ? "nothing was due" : `${parts.join(", ")}; about ${bytesWords(freed)} freed`;
|
|
288
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { type ObservationEvidence } from "./observations.js";
|
|
2
|
+
import type { ExecResult } from "./exec.js";
|
|
3
|
+
import { type ApprovedCriterion, type CriterionJudgementWord } from "./proof.js";
|
|
4
|
+
import type { Store } from "./store.js";
|
|
5
|
+
/** Explicit bounds. Content bytes are UTF-8 of the stored (possibly
|
|
6
|
+
* redacted) text; the aggregate is the sum over every stored item. */
|
|
7
|
+
export declare const LEGACY_REVIEW_CONTEXT_LIMITS: {
|
|
8
|
+
/** One complete file or partial patch chain. Larger files stay gaps. */
|
|
9
|
+
readonly itemBytes: number;
|
|
10
|
+
/** Every item's bytes together. Whatever would cross it is a named gap. */
|
|
11
|
+
readonly aggregateBytes: number;
|
|
12
|
+
/** Items stored, in deterministic relevance order. */
|
|
13
|
+
readonly items: 24;
|
|
14
|
+
/** Candidate paths considered from the source proof and diff-stat. */
|
|
15
|
+
readonly candidatePaths: 200;
|
|
16
|
+
/** Prior review rows carried as context. */
|
|
17
|
+
readonly priorReviews: 48;
|
|
18
|
+
readonly ancestors: 16;
|
|
19
|
+
};
|
|
20
|
+
/** Storage ceilings, independent of delivery. Ordinary large files remain whole.
|
|
21
|
+
* The encoded artifact allows worst-case JSON escaping plus metadata. */
|
|
22
|
+
export declare const REVIEW_CONTEXT_LIMITS: {
|
|
23
|
+
/** Candidate paths considered from the source proof and diff-stat. */
|
|
24
|
+
readonly candidatePaths: 200;
|
|
25
|
+
/** Prior review rows carried as context. */
|
|
26
|
+
readonly priorReviews: 48;
|
|
27
|
+
readonly ancestors: 16;
|
|
28
|
+
readonly itemBytes: number;
|
|
29
|
+
readonly aggregateBytes: number;
|
|
30
|
+
readonly items: 200;
|
|
31
|
+
};
|
|
32
|
+
/** Only this compact projection enters prompts. Full bytes remain sealed in
|
|
33
|
+
* the artifact and are materialized under generated, flat scratch names. */
|
|
34
|
+
export declare function reviewContextFileName(id: string): string;
|
|
35
|
+
export declare function reviewContextManifest(inventory: ReviewContextInventory): string;
|
|
36
|
+
export type ContextGapReason = "source-missing" | "source-unverified" | "source-proof-missing" | "source-scope-changed" | "criterion-changed" | "stale-ancestry" | "missing-at-head" | "not-a-file" | "binary" | "over-limit" | "aggregate-limit" | "item-cap" | "secret-redacted" | "capture-failed";
|
|
37
|
+
export type ContextItemWhy = "source-criterion-evidence" | "source-changed-path" | "candidate-changed-path";
|
|
38
|
+
export type ReviewContextItem = {
|
|
39
|
+
/** `ctx-<n>`: the provenance token a reviewer cites in its notes. */
|
|
40
|
+
id: string;
|
|
41
|
+
path: string;
|
|
42
|
+
/** The exact commit the blob was read at — this run's sealed head. */
|
|
43
|
+
commit: string;
|
|
44
|
+
/** The git blob id at that commit and path. */
|
|
45
|
+
blob: string;
|
|
46
|
+
/** SHA-256 of `content` exactly as stored (after any redaction). */
|
|
47
|
+
sha256: string;
|
|
48
|
+
bytes: number;
|
|
49
|
+
content: string;
|
|
50
|
+
/** The ancestor run whose verified artifacts made this path relevant. */
|
|
51
|
+
sourceRun: number;
|
|
52
|
+
/** Signed criterion ids this path is relevant to. */
|
|
53
|
+
criteria: string[];
|
|
54
|
+
why: ContextItemWhy[];
|
|
55
|
+
/** Whether the blob is byte-identical at the source run's head. null
|
|
56
|
+
* when ancestry could not be verified, so nothing is claimed. */
|
|
57
|
+
unchangedSinceSource: boolean | null;
|
|
58
|
+
redacted: boolean;
|
|
59
|
+
/** Schema 2/3 only. Content is concatenated exact artifact ranges, NEVER
|
|
60
|
+
* a complete file. Segments are ordered from oldest to newest. */
|
|
61
|
+
patch?: {
|
|
62
|
+
coverage: "partial";
|
|
63
|
+
segments: AncestorPatchSegment[];
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
type AncestorPatchSegment = {
|
|
67
|
+
run: number;
|
|
68
|
+
base: string;
|
|
69
|
+
head: string;
|
|
70
|
+
artifact: number;
|
|
71
|
+
sha256: string;
|
|
72
|
+
offset: number;
|
|
73
|
+
bytes: number;
|
|
74
|
+
};
|
|
75
|
+
export type ReviewContextIdentity = {
|
|
76
|
+
path: string;
|
|
77
|
+
commit: string;
|
|
78
|
+
blob: string;
|
|
79
|
+
mode: string;
|
|
80
|
+
bytes: number;
|
|
81
|
+
sourceRun: number;
|
|
82
|
+
sourceBlob: string | null;
|
|
83
|
+
sourceMode: string | null;
|
|
84
|
+
unchangedSinceSource: boolean | null;
|
|
85
|
+
};
|
|
86
|
+
export type ReviewContextGap = {
|
|
87
|
+
reason: ContextGapReason;
|
|
88
|
+
path: string | null;
|
|
89
|
+
criteria: string[];
|
|
90
|
+
detail: string;
|
|
91
|
+
};
|
|
92
|
+
export type PriorReviewSupport = {
|
|
93
|
+
criterionId: string;
|
|
94
|
+
sourceRun: number;
|
|
95
|
+
reviewerRun: number;
|
|
96
|
+
author: string;
|
|
97
|
+
judgement: CriterionJudgementWord;
|
|
98
|
+
note: string;
|
|
99
|
+
statementMatches: boolean;
|
|
100
|
+
ancestryVerified: boolean;
|
|
101
|
+
relevantPaths: string[];
|
|
102
|
+
relevantUnchanged: boolean;
|
|
103
|
+
bindingsVerified: boolean;
|
|
104
|
+
/** `eligible` = every proof above holds, so the reviewer may weigh it;
|
|
105
|
+
* `invalid` = at least one failed, and the reasons say which. Neither
|
|
106
|
+
* is a judgement on THIS run. */
|
|
107
|
+
support: "eligible" | "invalid";
|
|
108
|
+
reasons: string[];
|
|
109
|
+
};
|
|
110
|
+
export type CriterionContextCoverage = {
|
|
111
|
+
id: string;
|
|
112
|
+
/** `patch`: judged from this revision's own diff (a criterion new to this
|
|
113
|
+
* rubric, or one whose relevant code the patch touches). `context`:
|
|
114
|
+
* inherited, partly or wholly outside the patch, every relevant path sealed as an
|
|
115
|
+
* item. `gap`: inherited and some relevant context is
|
|
116
|
+
* missing — see `gaps`. */
|
|
117
|
+
state: "patch" | "context" | "gap";
|
|
118
|
+
/** Same id AND same statement as the source run's signed rubric. */
|
|
119
|
+
inherited: boolean;
|
|
120
|
+
paths: string[];
|
|
121
|
+
items: string[];
|
|
122
|
+
gaps: string[];
|
|
123
|
+
priorSupport: "eligible" | "invalid" | "none";
|
|
124
|
+
};
|
|
125
|
+
export type ReviewContextInventory = {
|
|
126
|
+
schema: 1 | 2 | 3;
|
|
127
|
+
/** Optional builder caveats, bound to the captured handoff, never evidence
|
|
128
|
+
* that a criterion passed. Older inventories remain byte-compatible. */
|
|
129
|
+
handoff?: {
|
|
130
|
+
artifact: number;
|
|
131
|
+
sha256: string;
|
|
132
|
+
content: string;
|
|
133
|
+
};
|
|
134
|
+
observations?: ObservationEvidence;
|
|
135
|
+
/** Tree identity is independent of whether content fits capture bounds. */
|
|
136
|
+
identities?: ReviewContextIdentity[];
|
|
137
|
+
bindings?: {
|
|
138
|
+
run: number;
|
|
139
|
+
sha256: string;
|
|
140
|
+
candidate?: true;
|
|
141
|
+
}[];
|
|
142
|
+
run: number;
|
|
143
|
+
head: string;
|
|
144
|
+
base: string | null;
|
|
145
|
+
source: {
|
|
146
|
+
task: string;
|
|
147
|
+
run: number;
|
|
148
|
+
head: string | null;
|
|
149
|
+
scopeDigest: string | null;
|
|
150
|
+
/** The source run's sealed proof AND diff-stat both verified. */
|
|
151
|
+
verified: boolean;
|
|
152
|
+
problems: string[];
|
|
153
|
+
};
|
|
154
|
+
ancestry: {
|
|
155
|
+
verified: boolean;
|
|
156
|
+
detail: string;
|
|
157
|
+
};
|
|
158
|
+
items: ReviewContextItem[];
|
|
159
|
+
gaps: ReviewContextGap[];
|
|
160
|
+
priorReview: PriorReviewSupport[];
|
|
161
|
+
coverage: CriterionContextCoverage[];
|
|
162
|
+
limits: {
|
|
163
|
+
itemBytes: number;
|
|
164
|
+
aggregateBytes: number;
|
|
165
|
+
items: number;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
/** Fingerprint every input the ancestor review depended on, including
|
|
169
|
+
* absent inputs and later additions. No transcript or checkout is copied. */
|
|
170
|
+
export declare function reviewContextBindingOf(store: Store, runId: number, candidate?: boolean): {
|
|
171
|
+
run: number;
|
|
172
|
+
sha256: string;
|
|
173
|
+
candidate?: true;
|
|
174
|
+
};
|
|
175
|
+
/** Re-prove sealed context before spending and inside final ingestion. */
|
|
176
|
+
export declare function reviewContextCustodyProblem(store: Store, root: string, inventory: ReviewContextInventory): string | null;
|
|
177
|
+
/** A candidate path the object reader will accept on argv: repository-
|
|
178
|
+
* relative, no `..` or `.` segments, no leading dash, no control bytes. */
|
|
179
|
+
export declare function safeContextPath(path: string): boolean;
|
|
180
|
+
export declare function serializeReviewContext(inventory: ReviewContextInventory): string;
|
|
181
|
+
/**
|
|
182
|
+
* The strict reader every consumer uses (the reviewer pass, the surfaces,
|
|
183
|
+
* the tests): shape, bounds, unique ids, and every item's SHA-256
|
|
184
|
+
* recomputed from its content. What this refuses, nothing shows.
|
|
185
|
+
*/
|
|
186
|
+
export declare function parseReviewContext(raw: string): {
|
|
187
|
+
ok: true;
|
|
188
|
+
inventory: ReviewContextInventory;
|
|
189
|
+
} | {
|
|
190
|
+
ok: false;
|
|
191
|
+
problem: string;
|
|
192
|
+
};
|
|
193
|
+
/** What the reviewer's parser needs from an inventory: the provenance
|
|
194
|
+
* tokens a note may cite, and the criteria whose judgement must cite one —
|
|
195
|
+
* every criterion NOT judged from the patch alone. */
|
|
196
|
+
export declare function reviewContextRules(inventory: ReviewContextInventory): {
|
|
197
|
+
itemIds: ReadonlySet<string>;
|
|
198
|
+
provenanceRequired: ReadonlySet<string>;
|
|
199
|
+
};
|
|
200
|
+
/** Whether a reviewer's note cites supplied provenance: a `ctx-<n>` item
|
|
201
|
+
* id from the inventory, a path the patch names, or a sealed file name. */
|
|
202
|
+
export declare function citesSuppliedProvenance(note: string, supplied: {
|
|
203
|
+
itemIds: ReadonlySet<string>;
|
|
204
|
+
patchPaths: ReadonlySet<string>;
|
|
205
|
+
sealedFiles: ReadonlySet<string>;
|
|
206
|
+
}): boolean;
|
|
207
|
+
type GitRunner = (file: string, args: readonly string[], options?: {
|
|
208
|
+
cwd?: string;
|
|
209
|
+
maxBuffer?: number;
|
|
210
|
+
}) => Promise<ExecResult>;
|
|
211
|
+
export type CaptureReviewContextArgs = {
|
|
212
|
+
runId: number;
|
|
213
|
+
taskRef: number;
|
|
214
|
+
/** This run's sealed head — the exact commit every item is read at. */
|
|
215
|
+
head: string;
|
|
216
|
+
base: string | null;
|
|
217
|
+
/** The signed rubric this run built against, in id order. */
|
|
218
|
+
rubric: readonly ApprovedCriterion[];
|
|
219
|
+
/** Paths this run's own sealed diff-stat names (empty when unknown). */
|
|
220
|
+
patchPaths: ReadonlySet<string>;
|
|
221
|
+
worktree: string;
|
|
222
|
+
root: string;
|
|
223
|
+
now: () => Date;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Capture complete criterion-relevant files for every rubric-bearing build.
|
|
227
|
+
* Ordinary builds bind their own candidate; revisions also bind their ancestry.
|
|
228
|
+
* Every capture stores a parseable inventory; problems become gaps in it, never a
|
|
229
|
+
* missing or truncated file.
|
|
230
|
+
*/
|
|
231
|
+
export declare function captureReviewContext(store: Store, git: GitRunner, args: CaptureReviewContextArgs): Promise<{
|
|
232
|
+
inventory: ReviewContextInventory;
|
|
233
|
+
artifactId: number;
|
|
234
|
+
} | null>;
|
|
235
|
+
/**
|
|
236
|
+
* The derivation, separated from storage so a test can hold the inventory
|
|
237
|
+
* against a real repository without an evidence root.
|
|
238
|
+
*/
|
|
239
|
+
export declare function deriveReviewContext(store: Store, git: GitRunner, args: CaptureReviewContextArgs, lineage: {
|
|
240
|
+
sourceTask: string;
|
|
241
|
+
sourceRun: number;
|
|
242
|
+
}): Promise<ReviewContextInventory>;
|
|
243
|
+
export {};
|