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
package/dist/peek.js
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live peek's NATIVE reader (attended finding 7, CRITICAL): the whole
|
|
3
|
+
* point of this module is what it does not do. No git invocation ever has
|
|
4
|
+
* the agent's worktree as its working tree; nothing here consults
|
|
5
|
+
* gitattributes, hooks, clean/process filters, or external diff drivers —
|
|
6
|
+
* the mechanisms finding 7 proved can execute repository-configured
|
|
7
|
+
* commands. Change detection is a git-blob sha1 computed IN PROCESS against
|
|
8
|
+
* the frozen base tree; the diff is a line-based Myers implemented here.
|
|
9
|
+
*
|
|
10
|
+
* Two layers, deliberately separated: the PURE core (sha1, diff, parsers,
|
|
11
|
+
* aggregation — bytes in, structures out) and ONE I/O function,
|
|
12
|
+
* observeWorktree — descriptor-DISCIPLINED, not descriptor-confined: Node
|
|
13
|
+
* has no openat, so traversal is by pathname and a same-UID attacker
|
|
14
|
+
* renaming ancestors mid-walk can misdirect it (round-3 finding 44 owns
|
|
15
|
+
* the honest disclosure). What IS held: files open O_NOFOLLOW|O_NONBLOCK
|
|
16
|
+
* and must fstat as regular files on the root's device before a byte is
|
|
17
|
+
* read; reads go through that descriptor, bounded to the accepted size,
|
|
18
|
+
* with growth re-checked after; directories must prove the root's device
|
|
19
|
+
* before descent; symlinks are never followed; `.git` is never entered;
|
|
20
|
+
* every cap is explicit; unreadable corners make the look PARTIAL rather
|
|
21
|
+
* than silently narrower. Guarding, caching, and serving stay with their
|
|
22
|
+
* owners (serve.ts).
|
|
23
|
+
*/
|
|
24
|
+
import { createHash } from "node:crypto";
|
|
25
|
+
import { open, opendir, readlink } from "node:fs/promises";
|
|
26
|
+
import { constants } from "node:fs";
|
|
27
|
+
import { join } from "node:path";
|
|
28
|
+
/** git's own blob identity: sha1 over "blob <len>\0" + bytes. Computing it
|
|
29
|
+
* here is what lets change detection never ask git about a working tree. */
|
|
30
|
+
export function gitBlobSha1(bytes) {
|
|
31
|
+
return createHash("sha1")
|
|
32
|
+
.update(`blob ${bytes.length}\0`)
|
|
33
|
+
.update(bytes)
|
|
34
|
+
.digest("hex");
|
|
35
|
+
}
|
|
36
|
+
/** git's heuristic, near enough: a NUL in the first 8 KiB means binary —
|
|
37
|
+
* named on the page, never diffed. */
|
|
38
|
+
export function looksBinary(bytes) {
|
|
39
|
+
return bytes.subarray(0, 8192).includes(0);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Line-based Myers (the O(ND) greedy walk), bounded by the caller's caps —
|
|
43
|
+
* inputs beyond the byte caps never reach here. Returns unified hunks with
|
|
44
|
+
* three lines of context, or null when the edit distance exceeds `maxD`
|
|
45
|
+
* (a rewrite is not usefully rendered as a diff — the caller says so).
|
|
46
|
+
*/
|
|
47
|
+
export function diffLines(aText, bText, maxD = 2000) {
|
|
48
|
+
const a = aText.split("\n");
|
|
49
|
+
const b = bText.split("\n");
|
|
50
|
+
// A trailing newline yields one empty tail element on both sides; keep it —
|
|
51
|
+
// it makes "no newline at end" edits visible as a real line change.
|
|
52
|
+
const n = a.length;
|
|
53
|
+
const m = b.length;
|
|
54
|
+
const max = Math.min(n + m, maxD);
|
|
55
|
+
const offset = max;
|
|
56
|
+
// v[k] = furthest x on diagonal k; trace keeps a snapshot per d for backtrack.
|
|
57
|
+
let v = new Array(2 * max + 1).fill(0);
|
|
58
|
+
const trace = [];
|
|
59
|
+
let found = -1;
|
|
60
|
+
for (let d = 0; d <= max; d++) {
|
|
61
|
+
trace.push([...v]);
|
|
62
|
+
for (let k = -d; k <= d; k += 2) {
|
|
63
|
+
let x = k === -d || (k !== d && v[offset + k - 1] < v[offset + k + 1])
|
|
64
|
+
? v[offset + k + 1]
|
|
65
|
+
: v[offset + k - 1] + 1;
|
|
66
|
+
let y = x - k;
|
|
67
|
+
while (x < n && y < m && a[x] === b[y]) {
|
|
68
|
+
x++;
|
|
69
|
+
y++;
|
|
70
|
+
}
|
|
71
|
+
v[offset + k] = x;
|
|
72
|
+
if (x >= n && y >= m) {
|
|
73
|
+
found = d;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (found >= 0)
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
if (found < 0)
|
|
81
|
+
return null; // edit distance beyond maxD — not a diff, a replacement
|
|
82
|
+
const ops = [];
|
|
83
|
+
let x = n;
|
|
84
|
+
let y = m;
|
|
85
|
+
for (let d = found; d > 0; d--) {
|
|
86
|
+
const vd = trace[d];
|
|
87
|
+
const k = x - y;
|
|
88
|
+
const prevK = k === -d || (k !== d && vd[offset + k - 1] < vd[offset + k + 1])
|
|
89
|
+
? k + 1
|
|
90
|
+
: k - 1;
|
|
91
|
+
const prevX = vd[offset + prevK];
|
|
92
|
+
const prevY = prevX - prevK;
|
|
93
|
+
while (x > prevX && y > prevY) {
|
|
94
|
+
ops.push("=");
|
|
95
|
+
x--;
|
|
96
|
+
y--;
|
|
97
|
+
}
|
|
98
|
+
if (d > 0) {
|
|
99
|
+
if (x === prevX) {
|
|
100
|
+
ops.push("+");
|
|
101
|
+
y--;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
ops.push("-");
|
|
105
|
+
x--;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
while (x > 0 && y > 0) {
|
|
110
|
+
ops.push("=");
|
|
111
|
+
x--;
|
|
112
|
+
y--;
|
|
113
|
+
}
|
|
114
|
+
while (x > 0) {
|
|
115
|
+
ops.push("-");
|
|
116
|
+
x--;
|
|
117
|
+
}
|
|
118
|
+
while (y > 0) {
|
|
119
|
+
ops.push("+");
|
|
120
|
+
y--;
|
|
121
|
+
}
|
|
122
|
+
ops.reverse();
|
|
123
|
+
// Fold ops into hunks with 3 lines of context.
|
|
124
|
+
const CONTEXT = 3;
|
|
125
|
+
const hunks = [];
|
|
126
|
+
let ai = 0;
|
|
127
|
+
let bi = 0;
|
|
128
|
+
let current = null;
|
|
129
|
+
let trailingContext = 0;
|
|
130
|
+
const flush = () => {
|
|
131
|
+
if (current === null)
|
|
132
|
+
return;
|
|
133
|
+
// Trim context beyond CONTEXT at the tail.
|
|
134
|
+
while (trailingContext > CONTEXT) {
|
|
135
|
+
current.lines.pop();
|
|
136
|
+
current.aLines--;
|
|
137
|
+
current.bLines--;
|
|
138
|
+
trailingContext--;
|
|
139
|
+
}
|
|
140
|
+
hunks.push(current);
|
|
141
|
+
current = null;
|
|
142
|
+
trailingContext = 0;
|
|
143
|
+
};
|
|
144
|
+
for (const op of ops) {
|
|
145
|
+
if (op === "=") {
|
|
146
|
+
const line = a[ai];
|
|
147
|
+
if (current !== null) {
|
|
148
|
+
current.lines.push(` ${line}`);
|
|
149
|
+
current.aLines++;
|
|
150
|
+
current.bLines++;
|
|
151
|
+
trailingContext++;
|
|
152
|
+
if (trailingContext > CONTEXT * 2)
|
|
153
|
+
flush();
|
|
154
|
+
}
|
|
155
|
+
ai++;
|
|
156
|
+
bi++;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (current === null) {
|
|
160
|
+
const aStart = Math.max(0, ai - CONTEXT);
|
|
161
|
+
const bStart = Math.max(0, bi - CONTEXT);
|
|
162
|
+
current = { aStart: aStart + 1, aLines: 0, bStart: bStart + 1, bLines: 0, lines: [] };
|
|
163
|
+
for (let c = aStart; c < ai; c++) {
|
|
164
|
+
current.lines.push(` ${a[c]}`);
|
|
165
|
+
current.aLines++;
|
|
166
|
+
current.bLines++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
trailingContext = 0;
|
|
170
|
+
if (op === "-") {
|
|
171
|
+
current.lines.push(`-${a[ai]}`);
|
|
172
|
+
current.aLines++;
|
|
173
|
+
ai++;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
current.lines.push(`+${b[bi]}`);
|
|
177
|
+
current.bLines++;
|
|
178
|
+
bi++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
flush();
|
|
182
|
+
return hunks;
|
|
183
|
+
}
|
|
184
|
+
/** Render hunks as a unified patch body for one file, capped in bytes.
|
|
185
|
+
* The cap drops the incomplete final line (finding 9), and says so. */
|
|
186
|
+
export function renderUnified(path, hunks, capBytes) {
|
|
187
|
+
const header = `--- a/${path}\n+++ b/${path}\n`;
|
|
188
|
+
const parts = [header];
|
|
189
|
+
let bytes = Buffer.byteLength(header);
|
|
190
|
+
for (const hunk of hunks) {
|
|
191
|
+
const head = `@@ -${hunk.aStart},${hunk.aLines} +${hunk.bStart},${hunk.bLines} @@\n`;
|
|
192
|
+
const body = hunk.lines.join("\n") + "\n";
|
|
193
|
+
const size = Buffer.byteLength(head) + Buffer.byteLength(body);
|
|
194
|
+
if (bytes + size > capBytes) {
|
|
195
|
+
return { text: parts.join(""), truncated: true };
|
|
196
|
+
}
|
|
197
|
+
parts.push(head, body);
|
|
198
|
+
bytes += size;
|
|
199
|
+
}
|
|
200
|
+
return { text: parts.join(""), truncated: false };
|
|
201
|
+
}
|
|
202
|
+
export function aggregateNewNames(paths, groupAt = 10, rowCap = 200) {
|
|
203
|
+
const bySegment = new Map();
|
|
204
|
+
for (const path of paths) {
|
|
205
|
+
const segment = path.includes("/") ? path.split("/")[0] : "";
|
|
206
|
+
const bucket = bySegment.get(segment) ?? [];
|
|
207
|
+
bucket.push(path);
|
|
208
|
+
bySegment.set(segment, bucket);
|
|
209
|
+
}
|
|
210
|
+
// The HARD row cap covers grouped rows too (round-2 finding 31): many
|
|
211
|
+
// eleven-file groups must saturate the cap exactly like loose names —
|
|
212
|
+
// an agent choosing segment names cannot amplify the output. Largest
|
|
213
|
+
// groups first, so saturation drops the least information.
|
|
214
|
+
const grouped = [];
|
|
215
|
+
const loose = [];
|
|
216
|
+
for (const [segment, bucket] of bySegment.entries()) {
|
|
217
|
+
if (segment !== "" && bucket.length > groupAt)
|
|
218
|
+
grouped.push({ label: `${segment}/`, count: bucket.length, collapsed: true });
|
|
219
|
+
else
|
|
220
|
+
loose.push(...bucket);
|
|
221
|
+
}
|
|
222
|
+
grouped.sort((a, b) => b.count - a.count || a.label.localeCompare(b.label));
|
|
223
|
+
loose.sort();
|
|
224
|
+
const rows = [];
|
|
225
|
+
let renderedFiles = 0;
|
|
226
|
+
for (const row of grouped) {
|
|
227
|
+
if (rows.length >= rowCap)
|
|
228
|
+
break;
|
|
229
|
+
rows.push(row);
|
|
230
|
+
renderedFiles += row.count;
|
|
231
|
+
}
|
|
232
|
+
for (const path of loose) {
|
|
233
|
+
if (rows.length >= rowCap)
|
|
234
|
+
break;
|
|
235
|
+
rows.push({ label: path, count: 1, collapsed: false });
|
|
236
|
+
renderedFiles += 1;
|
|
237
|
+
}
|
|
238
|
+
return { rows, total: paths.length, renderedFiles };
|
|
239
|
+
}
|
|
240
|
+
const KNOWN_MODES = new Set(["100644", "100755", "120000", "160000"]);
|
|
241
|
+
const SHA40 = /^[0-9a-f]{40}$/;
|
|
242
|
+
export function encodeBaseTreeSnapshot(snapshot) {
|
|
243
|
+
return JSON.stringify({
|
|
244
|
+
v: "base-tree/1",
|
|
245
|
+
repo: snapshot.repo,
|
|
246
|
+
run: snapshot.run,
|
|
247
|
+
base: snapshot.base,
|
|
248
|
+
entries: snapshot.entries.map(entry => [entry.path, entry.mode, entry.sha, entry.size]),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
export function parseBaseTreeSnapshot(json, entryCap = 20_000) {
|
|
252
|
+
let parsed;
|
|
253
|
+
try {
|
|
254
|
+
parsed = JSON.parse(json);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
260
|
+
return null;
|
|
261
|
+
const document = parsed;
|
|
262
|
+
if (document["v"] !== "base-tree/1")
|
|
263
|
+
return null;
|
|
264
|
+
const repo = document["repo"];
|
|
265
|
+
const run = document["run"];
|
|
266
|
+
const base = document["base"];
|
|
267
|
+
if (typeof repo !== "string" || repo === "")
|
|
268
|
+
return null;
|
|
269
|
+
if (typeof run !== "number" || !Number.isInteger(run) || run <= 0)
|
|
270
|
+
return null;
|
|
271
|
+
if (typeof base !== "string" || !SHA40.test(base))
|
|
272
|
+
return null;
|
|
273
|
+
const entries = parseBaseTree(JSON.stringify(document["entries"] ?? null), entryCap);
|
|
274
|
+
if (entries === null)
|
|
275
|
+
return null;
|
|
276
|
+
return { repo, run, base, entries };
|
|
277
|
+
}
|
|
278
|
+
export function parseBaseTree(json, entryCap = 20_000) {
|
|
279
|
+
let parsed;
|
|
280
|
+
try {
|
|
281
|
+
parsed = JSON.parse(json);
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
if (!Array.isArray(parsed) || parsed.length > entryCap)
|
|
287
|
+
return null;
|
|
288
|
+
const entries = [];
|
|
289
|
+
const seen = new Set();
|
|
290
|
+
for (const raw of parsed) {
|
|
291
|
+
if (!Array.isArray(raw) || raw.length !== 4)
|
|
292
|
+
return null;
|
|
293
|
+
const [path, mode, sha, size] = raw;
|
|
294
|
+
if (typeof path !== "string" || typeof mode !== "string" || typeof sha !== "string" || typeof size !== "number")
|
|
295
|
+
return null;
|
|
296
|
+
if (path === "" ||
|
|
297
|
+
path.startsWith("/") ||
|
|
298
|
+
path.includes("\\") ||
|
|
299
|
+
path.split("/").some(part => part === "" || part === "." || part === "..") ||
|
|
300
|
+
/[\u0000-\u001f\u007f\ufffd]/.test(path) ||
|
|
301
|
+
seen.has(path)) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
if (!KNOWN_MODES.has(mode) || !SHA40.test(sha) || !Number.isInteger(size) || size < 0 || size > 8_589_934_592)
|
|
305
|
+
return null;
|
|
306
|
+
seen.add(path);
|
|
307
|
+
entries.push({ path, mode, sha, size });
|
|
308
|
+
}
|
|
309
|
+
return entries;
|
|
310
|
+
}
|
|
311
|
+
export const PEEK_LIMITS = {
|
|
312
|
+
maxEntries: 20_000,
|
|
313
|
+
maxRows: 400,
|
|
314
|
+
maxFileBytes: 1_048_576,
|
|
315
|
+
maxHashedBytes: 64 * 1_048_576,
|
|
316
|
+
deadlineMs: 3_000,
|
|
317
|
+
};
|
|
318
|
+
/** The lease marker every occupied checkout carries — ours, never news. */
|
|
319
|
+
const LEASE_MARKER = ".standing-orders-lease";
|
|
320
|
+
/**
|
|
321
|
+
* One best-effort observation of a working tree against its frozen base
|
|
322
|
+
* (v2 brief §2). Descriptor-confined throughout: directories via opendir
|
|
323
|
+
* handles, files via O_NOFOLLOW descriptors, sizes from fstat on the OPEN
|
|
324
|
+
* descriptor (never a path-racy stat), bytes hashed through the same
|
|
325
|
+
* descriptor. Symlinks are typed by lstat-equivalent dirent info and never
|
|
326
|
+
* opened. Nothing here writes, spawns, or evaluates anything.
|
|
327
|
+
*/
|
|
328
|
+
export async function observeWorktree(root, base, limits = PEEK_LIMITS) {
|
|
329
|
+
const started = Date.now();
|
|
330
|
+
// Device pinning (round-2 finding 27 mitigation): the root's filesystem
|
|
331
|
+
// is the only one this walk will ever read from — a symlinked or
|
|
332
|
+
// bind-mounted escape onto another device is reported, never read.
|
|
333
|
+
let rootDevice;
|
|
334
|
+
try {
|
|
335
|
+
const rootHandle = await open(root, constants.O_RDONLY | constants.O_DIRECTORY);
|
|
336
|
+
try {
|
|
337
|
+
rootDevice = (await rootHandle.stat()).dev;
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
await rootHandle.close();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
return { ok: false, reason: "the checkout could not be opened" };
|
|
345
|
+
}
|
|
346
|
+
const baseByPath = new Map(base.map(entry => [entry.path, entry]));
|
|
347
|
+
const gitlinks = new Set(base.filter(entry => entry.mode === "160000").map(entry => entry.path));
|
|
348
|
+
const seen = new Set();
|
|
349
|
+
const rows = [];
|
|
350
|
+
let rowOverflow = 0;
|
|
351
|
+
// ONE combined bound over every row kind (finding 38): past it, rows are
|
|
352
|
+
// counted, not collected — the fragment states the exact overflow.
|
|
353
|
+
const push = (row) => {
|
|
354
|
+
if (rows.length >= limits.maxRows)
|
|
355
|
+
rowOverflow += 1;
|
|
356
|
+
else
|
|
357
|
+
rows.push(row);
|
|
358
|
+
};
|
|
359
|
+
const newPaths = [];
|
|
360
|
+
let scanned = 0;
|
|
361
|
+
let hashedBytes = 0;
|
|
362
|
+
let sizeOnly = 0;
|
|
363
|
+
let unverified = 0;
|
|
364
|
+
let partialDirs = 0;
|
|
365
|
+
let partial = null;
|
|
366
|
+
const overdue = () => Date.now() - started >= limits.deadlineMs;
|
|
367
|
+
const stack = [""];
|
|
368
|
+
while (stack.length > 0) {
|
|
369
|
+
if (overdue()) {
|
|
370
|
+
partial = "the look ran out of time — showing what was seen";
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
const relative = stack.pop();
|
|
374
|
+
if (gitlinks.has(relative))
|
|
375
|
+
continue; // a vendored repo is opaque, like git treats it
|
|
376
|
+
// Directories prove the root's device BEFORE descent (finding 44): a
|
|
377
|
+
// swapped ancestor pointing cross-device is typed, never enumerated.
|
|
378
|
+
if (relative !== "") {
|
|
379
|
+
try {
|
|
380
|
+
const gate = await open(join(root, relative), constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
381
|
+
try {
|
|
382
|
+
if ((await gate.stat()).dev !== rootDevice) {
|
|
383
|
+
push({ kind: "unchecked", path: relative, detail: "directory on a different filesystem — not entered" });
|
|
384
|
+
partialDirs += 1;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
finally {
|
|
389
|
+
await gate.close();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
push({ kind: "unchecked", path: relative, detail: "directory could not be opened" });
|
|
394
|
+
partialDirs += 1;
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
let dir;
|
|
399
|
+
try {
|
|
400
|
+
dir = await opendir(relative === "" ? root : join(root, relative));
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
push({ kind: "unchecked", path: relative, detail: "directory could not be read" });
|
|
404
|
+
partialDirs += 1;
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
for await (const entry of dir) {
|
|
409
|
+
if (overdue()) {
|
|
410
|
+
partial = "the look ran out of time — showing what was seen";
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
const path = relative === "" ? entry.name : `${relative}/${entry.name}`;
|
|
414
|
+
if (path === ".git" || path === LEASE_MARKER)
|
|
415
|
+
continue;
|
|
416
|
+
scanned += 1;
|
|
417
|
+
if (scanned > limits.maxEntries) {
|
|
418
|
+
return { ok: false, reason: "this tree is too large to watch live" };
|
|
419
|
+
}
|
|
420
|
+
const inBase = baseByPath.get(path);
|
|
421
|
+
if (entry.isDirectory()) {
|
|
422
|
+
stack.push(path);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (entry.isSymbolicLink()) {
|
|
426
|
+
seen.add(path);
|
|
427
|
+
if (inBase === undefined)
|
|
428
|
+
newPaths.push(path);
|
|
429
|
+
else if (inBase.mode !== "120000")
|
|
430
|
+
push({ kind: "changed", path, detail: "became a link" });
|
|
431
|
+
else {
|
|
432
|
+
// The link's TARGET is the tracked content: readlink never
|
|
433
|
+
// follows, and a 120000 blob's bytes are exactly the target
|
|
434
|
+
// string — so the in-process sha decides (finding 34).
|
|
435
|
+
try {
|
|
436
|
+
const target = await readlink(join(root, path));
|
|
437
|
+
if (gitBlobSha1(Buffer.from(target, "utf8")) !== inBase.sha) {
|
|
438
|
+
push({ kind: "changed", path, detail: "link points elsewhere" });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
push({ kind: "unchecked", path, detail: "link target could not be read" });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
continue; // never opened, never followed
|
|
446
|
+
}
|
|
447
|
+
if (!entry.isFile()) {
|
|
448
|
+
seen.add(path);
|
|
449
|
+
if (inBase !== undefined)
|
|
450
|
+
push({ kind: "changed", path, detail: "became something else" });
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
seen.add(path);
|
|
454
|
+
if (inBase === undefined) {
|
|
455
|
+
newPaths.push(path);
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
if (inBase.mode === "120000") {
|
|
459
|
+
push({ kind: "changed", path, detail: "was a link, now a file" });
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
// The file: O_NOFOLLOW descriptor; size and mode from fstat ON that
|
|
463
|
+
// descriptor; bytes through it. A path swapped underneath yields a
|
|
464
|
+
// typed miss, never a follow.
|
|
465
|
+
let handle;
|
|
466
|
+
try {
|
|
467
|
+
handle = await open(join(root, path), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
468
|
+
}
|
|
469
|
+
catch {
|
|
470
|
+
push({ kind: "changed", path, detail: "could not be read just now" });
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
try {
|
|
474
|
+
const stat = await handle.stat();
|
|
475
|
+
if (stat.dev !== rootDevice) {
|
|
476
|
+
push({ kind: "unchecked", path, detail: "lives on a different filesystem — not read" });
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
if (!stat.isFile()) {
|
|
480
|
+
// A FIFO or device node planted at a tracked path: opened
|
|
481
|
+
// non-blocking, typed, and never read (finding 44).
|
|
482
|
+
push({ kind: "unchecked", path, detail: "not a regular file — not read" });
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
const executable = (stat.mode & 0o100) !== 0;
|
|
486
|
+
const baseExecutable = inBase.mode === "100755";
|
|
487
|
+
if (stat.size !== inBase.size) {
|
|
488
|
+
push({ kind: "changed", path, detail: `${inBase.size} → ${stat.size} bytes` });
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (executable !== baseExecutable) {
|
|
492
|
+
push({ kind: "changed", path, detail: executable ? "became executable" : "lost its executable bit" });
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
if (stat.size > limits.maxFileBytes) {
|
|
496
|
+
// Same size, too big to hash: SAID, never silently "unchanged".
|
|
497
|
+
push({ kind: "unchecked", path, detail: "same size, too large to verify live" });
|
|
498
|
+
sizeOnly += 1;
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
if (hashedBytes + stat.size > limits.maxHashedBytes) {
|
|
502
|
+
push({ kind: "unchecked", path, detail: "the verification budget ran out before this file" });
|
|
503
|
+
unverified += 1;
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
// Read AT MOST the size fstat accepted (finding 33): a file
|
|
507
|
+
// growing underneath is a change, not an unbounded read.
|
|
508
|
+
const hash = createHash("sha1").update(`blob ${stat.size}\0`);
|
|
509
|
+
const buffer = Buffer.alloc(65_536);
|
|
510
|
+
let position = 0;
|
|
511
|
+
let grew = false;
|
|
512
|
+
while (position < stat.size) {
|
|
513
|
+
if (overdue()) {
|
|
514
|
+
partial = "the look ran out of time — showing what was seen";
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
const want = Math.min(buffer.length, stat.size - position);
|
|
518
|
+
const { bytesRead } = await handle.read(buffer, 0, want, position);
|
|
519
|
+
if (bytesRead <= 0)
|
|
520
|
+
break;
|
|
521
|
+
hash.update(buffer.subarray(0, bytesRead));
|
|
522
|
+
position += bytesRead;
|
|
523
|
+
}
|
|
524
|
+
hashedBytes += position;
|
|
525
|
+
const after = await handle.stat();
|
|
526
|
+
if (position < stat.size || after.size !== stat.size) {
|
|
527
|
+
push({ kind: "unchecked", path, detail: "changed underneath the look" });
|
|
528
|
+
grew = true;
|
|
529
|
+
}
|
|
530
|
+
if (!grew && hash.digest("hex") !== inBase.sha) {
|
|
531
|
+
push({ kind: "changed", path, detail: "edited (same size)" });
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
catch {
|
|
535
|
+
push({ kind: "changed", path, detail: "could not be read just now" });
|
|
536
|
+
}
|
|
537
|
+
finally {
|
|
538
|
+
await handle.close();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
catch {
|
|
543
|
+
// Iteration died mid-stream: this corner was not fully seen, so the
|
|
544
|
+
// look is partial and the deleted sweep must not run (finding 44).
|
|
545
|
+
push({ kind: "unchecked", path: relative, detail: "directory could not be fully read" });
|
|
546
|
+
partialDirs += 1;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (partial === null && stack.length === 0 && partialDirs === 0) {
|
|
550
|
+
for (const entry of base) {
|
|
551
|
+
if (!seen.has(entry.path) && entry.mode !== "160000" && !isUnder(entry.path, gitlinks)) {
|
|
552
|
+
push({ kind: "deleted", path: entry.path, detail: "gone" });
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
// A timed-out walk cannot distinguish "deleted" from "not reached".
|
|
558
|
+
}
|
|
559
|
+
const notes = [];
|
|
560
|
+
if (partial !== null)
|
|
561
|
+
notes.push(partial);
|
|
562
|
+
if (partialDirs > 0)
|
|
563
|
+
notes.push(`${partialDirs} folder(s) could not be fully seen — deletions are not reported`);
|
|
564
|
+
if (rowOverflow > 0)
|
|
565
|
+
notes.push(`${rowOverflow} more change(s) than the live view will render`);
|
|
566
|
+
if (sizeOnly > 0)
|
|
567
|
+
notes.push(`${sizeOnly} large file(s) compared by size only`);
|
|
568
|
+
if (unverified > 0)
|
|
569
|
+
notes.push(`${unverified} file(s) unverified — the hashing budget ran out`);
|
|
570
|
+
return { ok: true, rows, newPaths, partial: notes.length === 0 ? null : notes.join("; "), scanned };
|
|
571
|
+
}
|
|
572
|
+
function isUnder(path, roots) {
|
|
573
|
+
for (const root of roots) {
|
|
574
|
+
if (path.startsWith(`${root}/`))
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
return false;
|
|
578
|
+
}
|