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,264 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { processMayBeAlive } from "./process-liveness.js";
|
|
3
|
+
const observed = new Map();
|
|
4
|
+
let timer = null;
|
|
5
|
+
/** Read identifiers only: command lines can contain private provider inputs. */
|
|
6
|
+
function snapshot() {
|
|
7
|
+
return execFileSync("/bin/ps", ["-axo", "pid=,ppid=,pgid="], { encoding: "utf8", timeout: 2000, maxBuffer: 4 * 1024 * 1024 })
|
|
8
|
+
.trim().split("\n").map(line => {
|
|
9
|
+
const [pid, parent, group] = line.trim().split(/\s+/).map(Number);
|
|
10
|
+
if (!pid || !Number.isSafeInteger(pid) || !Number.isSafeInteger(parent) || parent < 0 || !Number.isSafeInteger(group) || group < 0 || line.trim().split(/\s+/).length !== 3)
|
|
11
|
+
throw Object.assign(new Error("unreadable process ancestry"), { code: "MALFORMED_SNAPSHOT" });
|
|
12
|
+
return { pid, parent: parent, group: group };
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function descendants(rows, root) {
|
|
16
|
+
const ids = new Set([root]);
|
|
17
|
+
const found = [];
|
|
18
|
+
for (let changed = true; changed;) {
|
|
19
|
+
changed = false;
|
|
20
|
+
for (const row of rows)
|
|
21
|
+
if (!ids.has(row.pid) && ids.has(row.parent)) {
|
|
22
|
+
ids.add(row.pid);
|
|
23
|
+
found.push(row);
|
|
24
|
+
changed = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return found;
|
|
28
|
+
}
|
|
29
|
+
function live(child) { return child.pid !== undefined && child.exitCode === null && child.signalCode === null; }
|
|
30
|
+
function remember(child, rows, phase) {
|
|
31
|
+
const tracked = observed.get(child);
|
|
32
|
+
if (!tracked)
|
|
33
|
+
return;
|
|
34
|
+
// Keep the entire observed set before a persistence callback can throw.
|
|
35
|
+
const fresh = rows.map(row => ({ pid: row.pid, group: row.group === row.pid }))
|
|
36
|
+
.filter(row => !tracked.seen.has(`${row.pid}:${row.group}`));
|
|
37
|
+
for (let index = 0; index < fresh.length; index++) {
|
|
38
|
+
const row = fresh[index];
|
|
39
|
+
try {
|
|
40
|
+
tracked.observer.onDescendant?.(row.pid, row.group);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// A stop must not signal from a snapshot made stale by waiting for a
|
|
44
|
+
// fallback write. Preserve its existing conservative failure path.
|
|
45
|
+
if (phase === "stop")
|
|
46
|
+
throw error;
|
|
47
|
+
const remaining = fresh.slice(index);
|
|
48
|
+
let preserved = false;
|
|
49
|
+
try {
|
|
50
|
+
preserved = tracked.observer.onDescendantWriteFailure?.(remaining) === true;
|
|
51
|
+
}
|
|
52
|
+
catch { /* The unknown safeguard remains. */ }
|
|
53
|
+
if (!preserved)
|
|
54
|
+
throw error;
|
|
55
|
+
for (const one of remaining)
|
|
56
|
+
tracked.seen.set(`${one.pid}:${one.group}`, one);
|
|
57
|
+
failed(child, phase, "descendant-write", error, true);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
tracked.seen.set(`${row.pid}:${row.group}`, row);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function recordExits(child, rows) {
|
|
64
|
+
const tracked = observed.get(child);
|
|
65
|
+
if (!tracked)
|
|
66
|
+
return;
|
|
67
|
+
const pids = new Set(rows.map(row => row.pid)), groups = new Set(rows.map(row => row.group));
|
|
68
|
+
for (const [key, prior] of tracked.seen) {
|
|
69
|
+
if (pids.has(prior.pid) || (prior.group && groups.has(prior.pid)))
|
|
70
|
+
continue;
|
|
71
|
+
// A missing ancestry edge proves nothing. Require both the complete
|
|
72
|
+
// system snapshot and an ESRCH-only probe; no birth inference or signal.
|
|
73
|
+
if (processMayBeAlive(prior.pid, prior.group))
|
|
74
|
+
continue;
|
|
75
|
+
tracked.observer.onDescendantExit?.(prior.pid, prior.group);
|
|
76
|
+
tracked.seen.delete(key); // The same number can later identify a NEW child.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Only fixed error codes survive; error messages/output can contain private data.
|
|
80
|
+
const observationCodes = new Set(["EAGAIN", "EMFILE", "ENFILE", "ETIMEDOUT", "ENOBUFS", "ENOENT", "EPERM", "EACCES", "EIO", "ESRCH", "MALFORMED_SNAPSHOT", "SUPERVISOR_DIAGNOSTIC", "SQLITE_BUSY", "SQLITE_LOCKED", "SQLITE_READONLY", "SQLITE_IOERR", "SQLITE_CORRUPT", "SQLITE_FULL", "SQLITE_CONSTRAINT"]);
|
|
81
|
+
/** Private supervisor pipe input. Keep only validated identifier diagnostics. */
|
|
82
|
+
export function readProcessObservationFailure(value) {
|
|
83
|
+
if (typeof value !== "object" || value === null)
|
|
84
|
+
return null;
|
|
85
|
+
const row = value;
|
|
86
|
+
const { phase, operation, code, rootPid, at, identityUnknown } = row;
|
|
87
|
+
if (!["sample", "periodic", "final-exit", "stop", "supervisor"].includes(String(phase)) || !["snapshot", "descendant-write", "exit-write", "signal", "diagnostic-read"].includes(String(operation)) || typeof code !== "string" || (code !== "UNKNOWN" && !observationCodes.has(code)) || (rootPid !== null && (!Number.isSafeInteger(rootPid) || Number(rootPid) <= 0)) || typeof at !== "string" || !Number.isFinite(Date.parse(at)) || new Date(at).toISOString() !== at || typeof identityUnknown !== "boolean")
|
|
88
|
+
return null;
|
|
89
|
+
return { phase: phase, operation: operation, code, rootPid: rootPid, at, identityUnknown };
|
|
90
|
+
}
|
|
91
|
+
function failed(child, phase, operation, error, identitiesPreserved = false) {
|
|
92
|
+
const tracked = observed.get(child);
|
|
93
|
+
if (!tracked)
|
|
94
|
+
return;
|
|
95
|
+
const rawCode = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
96
|
+
const sqliteCodes = { 5: "SQLITE_BUSY", 6: "SQLITE_LOCKED", 8: "SQLITE_READONLY", 10: "SQLITE_IOERR", 11: "SQLITE_CORRUPT", 13: "SQLITE_FULL", 19: "SQLITE_CONSTRAINT" };
|
|
97
|
+
const sqlite = typeof error === "object" && error !== null && "errcode" in error && Number.isSafeInteger(error.errcode)
|
|
98
|
+
? sqliteCodes[Number(error.errcode) & 0xff] : undefined;
|
|
99
|
+
const code = sqlite ?? (typeof rawCode === "string" && observationCodes.has(rawCode) ? rawCode : "UNKNOWN");
|
|
100
|
+
// Exit-only checks retire already-durable identities; they discover no
|
|
101
|
+
// children. Any failure leaves those witnesses intact for later OS probes.
|
|
102
|
+
// Discovery and descendant persistence failures can lose an identity.
|
|
103
|
+
const identityUnknown = !identitiesPreserved && phase !== "final-exit" && operation !== "exit-write";
|
|
104
|
+
const key = `${phase}:${operation}:${code}:${identityUnknown}`;
|
|
105
|
+
if (!tracked.failures.has(key)) {
|
|
106
|
+
try {
|
|
107
|
+
tracked.observer.onObservationFailure?.({ phase, operation, code, rootPid: child.pid ?? null, at: new Date().toISOString(), identityUnknown });
|
|
108
|
+
tracked.failures.add(key);
|
|
109
|
+
}
|
|
110
|
+
catch { /* No diagnostic, but no witness was retired by this callback. */ }
|
|
111
|
+
}
|
|
112
|
+
if (identityUnknown) {
|
|
113
|
+
// A failed persistence callback never becomes an uncaught timer error or
|
|
114
|
+
// permission to release custody. The existing unknown road stays closed.
|
|
115
|
+
try {
|
|
116
|
+
tracked.observer.onUnknown?.();
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function observeRows(child, rows, phase) {
|
|
122
|
+
try {
|
|
123
|
+
recordExits(child, rows);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
failed(child, phase, "exit-write", error);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
remember(child, descendants(rows, child.pid), phase);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
failed(child, phase, "descendant-write", error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Capture current descendants before asking an owned process to exit.
|
|
136
|
+
* A cooperative root may exit before the next periodic observation; even
|
|
137
|
+
* a killed tool can retain its PID briefly after its process group is gone. */
|
|
138
|
+
export function sampleProcessTree(child) {
|
|
139
|
+
if (!live(child) || !observed.has(child))
|
|
140
|
+
return;
|
|
141
|
+
let rows;
|
|
142
|
+
try {
|
|
143
|
+
rows = snapshot();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
failed(child, "sample", "snapshot", error);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
observeRows(child, rows, "sample");
|
|
150
|
+
}
|
|
151
|
+
/** Observe escaped process groups while their ancestry is still provable.
|
|
152
|
+
* Durable witnesses prevent recovery from mistaking a dead harness for a dead
|
|
153
|
+
* shell. They never grant permission to send a signal after worker recovery. */
|
|
154
|
+
export function observeProcessTree(child, observer) {
|
|
155
|
+
if (process.platform === "win32" || observer.onDescendant === undefined)
|
|
156
|
+
return;
|
|
157
|
+
observed.set(child, { observer, seen: new Map(), failures: new Set() });
|
|
158
|
+
child.once("close", () => {
|
|
159
|
+
if (observed.get(child)?.seen.size) {
|
|
160
|
+
let rows = null;
|
|
161
|
+
try {
|
|
162
|
+
rows = snapshot();
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
failed(child, "final-exit", "snapshot", error);
|
|
166
|
+
}
|
|
167
|
+
if (rows !== null) {
|
|
168
|
+
try {
|
|
169
|
+
recordExits(child, rows);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
failed(child, "final-exit", "exit-write", error);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
observed.delete(child);
|
|
177
|
+
if (observed.size === 0 && timer !== null) {
|
|
178
|
+
clearInterval(timer);
|
|
179
|
+
timer = null;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
if (timer !== null)
|
|
183
|
+
return;
|
|
184
|
+
timer = setInterval(() => {
|
|
185
|
+
let rows;
|
|
186
|
+
try {
|
|
187
|
+
rows = snapshot();
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
for (const [one] of observed)
|
|
191
|
+
if (live(one))
|
|
192
|
+
failed(one, "periodic", "snapshot", error);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
for (const [one] of observed)
|
|
196
|
+
if (live(one))
|
|
197
|
+
observeRows(one, rows, "periodic");
|
|
198
|
+
}, 500);
|
|
199
|
+
timer.unref();
|
|
200
|
+
}
|
|
201
|
+
/** Freeze the owned handle, then its live descendants before killing them.
|
|
202
|
+
* Claude's tool shells create new process groups, so killing only -rootPid
|
|
203
|
+
* leaves writers behind. Re-scan after freezing parents to catch a child born
|
|
204
|
+
* during the previous scan. Every target comes from current ancestry of the
|
|
205
|
+
* still-owned handle, never from a saved PID. Unknown ancestry stays blocked. */
|
|
206
|
+
export function stopProcessTree(child) {
|
|
207
|
+
if (process.platform === "win32" || !live(child))
|
|
208
|
+
return false;
|
|
209
|
+
const stopped = new Set();
|
|
210
|
+
let operation = "signal";
|
|
211
|
+
try {
|
|
212
|
+
if (!child.kill("SIGSTOP"))
|
|
213
|
+
return false;
|
|
214
|
+
for (let pass = 0; pass < 8; pass++) {
|
|
215
|
+
operation = "snapshot";
|
|
216
|
+
const rows = descendants(snapshot(), child.pid);
|
|
217
|
+
operation = "descendant-write";
|
|
218
|
+
remember(child, rows, "stop");
|
|
219
|
+
operation = "signal";
|
|
220
|
+
const fresh = rows.filter(row => !stopped.has(row.pid));
|
|
221
|
+
if (fresh.length === 0) {
|
|
222
|
+
// Parents are frozen, so none can fork between this seal and kill.
|
|
223
|
+
for (const row of rows.reverse()) {
|
|
224
|
+
try {
|
|
225
|
+
process.kill(row.pid, "SIGKILL");
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
if (error.code !== "ESRCH")
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
child.kill("SIGKILL");
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
for (const row of fresh) {
|
|
236
|
+
try {
|
|
237
|
+
process.kill(row.pid, "SIGSTOP");
|
|
238
|
+
stopped.add(row.pid);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (error.code !== "ESRCH")
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
throw new Error("process ancestry did not settle");
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
failed(child, "stop", operation, error);
|
|
250
|
+
// Do not leave any process frozen after a failed observation. The caller
|
|
251
|
+
// can still stop its known group; unresolved custody prevents Resume.
|
|
252
|
+
for (const pid of stopped) {
|
|
253
|
+
try {
|
|
254
|
+
process.kill(pid, "SIGCONT");
|
|
255
|
+
}
|
|
256
|
+
catch { }
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
child.kill("SIGCONT");
|
|
260
|
+
}
|
|
261
|
+
catch { }
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
/** null explicitly means instance access; [] grants no project access. */
|
|
3
|
+
export type ProjectAccess = readonly string[] | null;
|
|
4
|
+
export declare function normalizeProjectAccess(value: unknown): string[] | null;
|
|
5
|
+
/** Corrupt or missing authority never falls back to instance access. */
|
|
6
|
+
export declare function readProjectAccess(value: unknown): ProjectAccess;
|
|
7
|
+
export declare function projectAccessAllows(access: ProjectAccess, repo: string | null): boolean;
|
|
8
|
+
/** A server-proved resource, never an unchecked header or submitted path.
|
|
9
|
+
* CLI ceremonies must pass their resource explicitly; global ceremonies
|
|
10
|
+
* without a project refuse project-scoped credentials. */
|
|
11
|
+
export declare const projectAuthority: AsyncLocalStorage<{
|
|
12
|
+
actor: string;
|
|
13
|
+
repo: string | null;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { canonicalProject } from "./project.js";
|
|
4
|
+
export function normalizeProjectAccess(value) {
|
|
5
|
+
if (value === null)
|
|
6
|
+
return null;
|
|
7
|
+
if (!Array.isArray(value) || value.length > 100 || value.some(path => typeof path !== "string" || !isAbsolute(path) || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path))) {
|
|
8
|
+
throw new Error("Project access must name at most 100 absolute project paths.");
|
|
9
|
+
}
|
|
10
|
+
return [...new Set(value.map(path => canonicalProject(path) ?? resolve(path)))].sort();
|
|
11
|
+
}
|
|
12
|
+
/** Corrupt or missing authority never falls back to instance access. */
|
|
13
|
+
export function readProjectAccess(value) {
|
|
14
|
+
if (value === null)
|
|
15
|
+
return null;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(String(value));
|
|
18
|
+
if (!Array.isArray(parsed) || parsed.length > 100 || parsed.some(path => typeof path !== "string" || !isAbsolute(path) || resolve(path) !== path || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path)))
|
|
19
|
+
return [];
|
|
20
|
+
// Preserve the granted identity. Re-canonicalizing stored grants after
|
|
21
|
+
// a symlink changes would transfer access to its new target.
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function projectAccessAllows(access, repo) {
|
|
29
|
+
return access === null || (repo !== null && access.includes(canonicalProject(repo) ?? resolve(repo)));
|
|
30
|
+
}
|
|
31
|
+
/** A server-proved resource, never an unchecked header or submitted path.
|
|
32
|
+
* CLI ceremonies must pass their resource explicitly; global ceremonies
|
|
33
|
+
* without a project refuse project-scoped credentials. */
|
|
34
|
+
export const projectAuthority = new AsyncLocalStorage();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Store } from './store.js';
|
|
2
|
+
export type ProjectProfile = {
|
|
3
|
+
version: 1;
|
|
4
|
+
repo: string;
|
|
5
|
+
tokenFile: string | null;
|
|
6
|
+
};
|
|
7
|
+
export declare const projectProfilePath: (databaseFile: string) => string;
|
|
8
|
+
export declare function readProjectProfile(databaseFile: string): ProjectProfile | null;
|
|
9
|
+
export declare function runProjectCommand(positional: readonly string[], flags: Map<string, string | true>, context: {
|
|
10
|
+
store: Store;
|
|
11
|
+
databaseFile: string;
|
|
12
|
+
write: (line: string) => void;
|
|
13
|
+
json: boolean;
|
|
14
|
+
registryFile?: string;
|
|
15
|
+
}): Promise<number>;
|
|
16
|
+
/** Only known credential-aware adapters consume the remembered reference.
|
|
17
|
+
* Explicit credentials always win; no legacy action gains implicit authority. */
|
|
18
|
+
export declare function applyProjectProfile(command: string, positional: readonly string[], flags: Map<string, string | true>, databaseFile: string): void;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** Local convenience only: a selected project and optional credential reference.
|
|
2
|
+
* Every action still authenticates against the current database. */
|
|
3
|
+
import { lstatSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSync } from 'node:fs';
|
|
4
|
+
import { dirname, join, resolve, isAbsolute } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { randomBytes } from 'node:crypto';
|
|
7
|
+
import { configPath, loadRepos } from './repos.js';
|
|
8
|
+
import { authenticateCoordinator } from './coordinator.js';
|
|
9
|
+
import { canonicalProject } from './project.js';
|
|
10
|
+
import { envelopeJson } from './envelope.js';
|
|
11
|
+
export const projectProfilePath = (databaseFile) => join(dirname(databaseFile), 'cli-project.json');
|
|
12
|
+
export function readProjectProfile(databaseFile) {
|
|
13
|
+
const file = projectProfilePath(databaseFile);
|
|
14
|
+
const stat = lstatSync(file, { throwIfNoEntry: false });
|
|
15
|
+
if (!stat)
|
|
16
|
+
return null;
|
|
17
|
+
if (!stat.isFile() || stat.size > 16_384)
|
|
18
|
+
throw new Error('The saved CLI project is not a readable profile. Select it again with project use.');
|
|
19
|
+
const value = JSON.parse(readFileSync(file, 'utf8'));
|
|
20
|
+
if (!value || typeof value !== 'object')
|
|
21
|
+
throw new Error('The saved CLI project is invalid. Select it again with project use.');
|
|
22
|
+
const p = value;
|
|
23
|
+
if (p['version'] !== 1 || typeof p['repo'] !== 'string' || !isAbsolute(p['repo']) || /[\x00-\x1f]/.test(p['repo']) ||
|
|
24
|
+
(p['tokenFile'] !== null && (typeof p['tokenFile'] !== 'string' || !isAbsolute(p['tokenFile']) || /[\x00-\x1f]/.test(p['tokenFile']))))
|
|
25
|
+
throw new Error('The saved CLI project is invalid. Select it again with project use.');
|
|
26
|
+
return { version: 1, repo: p['repo'], tokenFile: p['tokenFile'] };
|
|
27
|
+
}
|
|
28
|
+
export async function runProjectCommand(positional, flags, context) {
|
|
29
|
+
const action = positional[0] ?? 'show', command = `project ${action}`;
|
|
30
|
+
const fail = (reason, message) => { context.write(context.json ? envelopeJson({ ok: false, command, reason, message }) : message); return reason === 'usage' ? 2 : 3; };
|
|
31
|
+
if (!['use', 'show'].includes(action) || positional.length > (action === 'use' ? 2 : 1))
|
|
32
|
+
return fail('usage', 'Use project use <saved checkout path> [--token-file PATH], or project show.');
|
|
33
|
+
const allowed = new Set(['db', 'json', ...(action === 'use' ? ['token-file'] : [])]);
|
|
34
|
+
for (const name of flags.keys())
|
|
35
|
+
if (!allowed.has(name))
|
|
36
|
+
return fail('usage', `--${name} is not a project ${action} option.`);
|
|
37
|
+
const registry = await loadRepos(context.registryFile ?? configPath(process.env, homedir()));
|
|
38
|
+
if ('error' in registry)
|
|
39
|
+
return fail('configuration', registry.error);
|
|
40
|
+
const repos = [...new Set([...registry.repos, ...context.store.knownRepos()].map(repo => canonicalProject(repo) ?? repo))];
|
|
41
|
+
let profile;
|
|
42
|
+
if (action === 'use') {
|
|
43
|
+
const path = positional[1];
|
|
44
|
+
if (!path || /[\x00-\x1f]/.test(path))
|
|
45
|
+
return fail('usage', 'Choose the exact saved checkout path.');
|
|
46
|
+
const repo = canonicalProject(path) ?? resolve(path);
|
|
47
|
+
if (!repos.includes(repo))
|
|
48
|
+
return fail('not-found', 'That checkout is not a saved project. Use repos to see or connect projects.');
|
|
49
|
+
try {
|
|
50
|
+
if (!statSync(repo).isDirectory())
|
|
51
|
+
return fail('not-found', 'That checkout is unavailable.');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return fail('not-found', 'That checkout is unavailable.');
|
|
55
|
+
}
|
|
56
|
+
const credential = flags.get('token-file');
|
|
57
|
+
if (credential !== undefined && (typeof credential !== 'string' || !credential || /[\x00-\x1f]/.test(credential)))
|
|
58
|
+
return fail('usage', '--token-file requires a path.');
|
|
59
|
+
const tokenFile = typeof credential === 'string' ? resolve(credential) : null;
|
|
60
|
+
if (tokenFile !== null) {
|
|
61
|
+
let token;
|
|
62
|
+
try {
|
|
63
|
+
const info = statSync(tokenFile);
|
|
64
|
+
if (!info.isFile() || info.size > 16_384)
|
|
65
|
+
return fail('unauthenticated', 'The scoped credential file is unavailable.');
|
|
66
|
+
token = readFileSync(tokenFile, 'utf8').trim();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return fail('unauthenticated', 'The scoped credential file is unavailable.');
|
|
70
|
+
}
|
|
71
|
+
const auth = authenticateCoordinator(context.store, token);
|
|
72
|
+
if (!auth.ok)
|
|
73
|
+
return fail('unauthenticated', 'The scoped credential is invalid or revoked.');
|
|
74
|
+
if (!auth.who.repos.includes(repo))
|
|
75
|
+
return fail('not-found', 'That project is unavailable to this credential.');
|
|
76
|
+
}
|
|
77
|
+
profile = { version: 1, repo, tokenFile };
|
|
78
|
+
const file = projectProfilePath(context.databaseFile), temp = `${file}.${randomBytes(6).toString('hex')}.tmp`;
|
|
79
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
80
|
+
writeFileSync(temp, `${JSON.stringify(profile, null, 2)}\n`, { mode: 0o600, flag: 'wx' });
|
|
81
|
+
renameSync(temp, file);
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
profile = readProjectProfile(context.databaseFile);
|
|
85
|
+
const result = { profile, saved: profile !== null && repos.includes(profile.repo) };
|
|
86
|
+
context.write(context.json ? envelopeJson({ ok: true, command, result }) : profile === null ? 'No project selected. Use project use <saved checkout path>.' : `${profile.repo}${result.saved ? '' : ' (no longer saved)'}\n${profile.tokenFile === null ? 'Uses your existing local sign-in for operator actions.' : `Scoped credential reference: ${profile.tokenFile}`}`);
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
/** Only known credential-aware adapters consume the remembered reference.
|
|
90
|
+
* Explicit credentials always win; no legacy action gains implicit authority. */
|
|
91
|
+
export function applyProjectProfile(command, positional, flags, databaseFile) {
|
|
92
|
+
const scoped = command === 'assignment' || command === 'knowledge' || (command === 'brief' && !flags.has('history')) ||
|
|
93
|
+
(command === 'task' && ['complete', 'revise'].includes(positional[0] ?? ''));
|
|
94
|
+
const repoDefault = command === 'knowledge' || command === 'brief' || (command === 'assignment' && positional[0] === 'brief');
|
|
95
|
+
if (!scoped && !repoDefault)
|
|
96
|
+
return;
|
|
97
|
+
const profile = readProjectProfile(databaseFile);
|
|
98
|
+
if (!profile)
|
|
99
|
+
return;
|
|
100
|
+
if (repoDefault && !flags.has('repo'))
|
|
101
|
+
flags.set('repo', profile.repo);
|
|
102
|
+
if (scoped && profile.tokenFile && !['token-file', 'token-env', 'token', 'as'].some(name => flags.has(name)))
|
|
103
|
+
flags.set('token-file', profile.tokenFile);
|
|
104
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings → Project: what Toolroll holds for a project, and deleting
|
|
3
|
+
* it. An instance operator deletes in two steps: type the project's name,
|
|
4
|
+
* then read exactly what goes and confirm with their password (or a fresh
|
|
5
|
+
* sign-in with the identity provider). The repository itself stays.
|
|
6
|
+
*/
|
|
7
|
+
import { type ProjectHoldings } from "./project-delete.js";
|
|
8
|
+
export declare const PROJECT_DELETE_CSS: string;
|
|
9
|
+
export type ProjectSettingsView = {
|
|
10
|
+
repo: string;
|
|
11
|
+
name: string;
|
|
12
|
+
holdings: ProjectHoldings;
|
|
13
|
+
running: string[];
|
|
14
|
+
canDelete: boolean;
|
|
15
|
+
};
|
|
16
|
+
/** The project's page: its path, what Toolroll holds for it, and (for an instance operator) Delete project. */
|
|
17
|
+
export declare function projectSettingsHtml(view: ProjectSettingsView, csrf: string, notice: {
|
|
18
|
+
said?: string | null;
|
|
19
|
+
problem?: string | null;
|
|
20
|
+
}): string;
|
|
21
|
+
/** The second step: exactly what goes, and the password. */
|
|
22
|
+
export declare function projectDeleteConfirmHtml(view: ProjectSettingsView, csrf: string, problem: string | null): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings → Project: what Toolroll holds for a project, and deleting
|
|
3
|
+
* it. An instance operator deletes in two steps: type the project's name,
|
|
4
|
+
* then read exactly what goes and confirm with their password (or a fresh
|
|
5
|
+
* sign-in with the identity provider). The repository itself stays.
|
|
6
|
+
*/
|
|
7
|
+
import { holdingsWords } from "./project-delete.js";
|
|
8
|
+
const e = (value) => String(value ?? "").replace(/[&<>"']/g, c => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
9
|
+
export const PROJECT_DELETE_CSS = `.project-settings,.project-delete{max-width:720px;min-width:0}.project-settings .path,.project-delete .path{font-family:var(--font-mono);font-size:.8125rem;overflow-wrap:anywhere;word-break:break-all}` +
|
|
10
|
+
`.project-settings details.danger-zone{margin-top:24px;border:1px solid var(--border);border-radius:10px;padding:0 14px}.project-settings details.danger-zone summary{min-height:44px;display:flex;align-items:center;cursor:pointer;font-weight:500;color:var(--danger)}` +
|
|
11
|
+
`.project-settings details.danger-zone[open]{padding-bottom:14px}.project-settings form,.project-delete form{display:grid;gap:12px;margin-top:12px}.project-settings label,.project-delete label{display:grid;gap:4px;font-size:.8125rem;font-weight:500}` +
|
|
12
|
+
`.project-settings input,.project-delete input{max-width:100%;min-height:36px}.project-delete .removes{margin:12px 0;padding-left:20px}.project-delete .removes li{margin:2px 0}` +
|
|
13
|
+
`.project-delete .actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center}.project-delete button.danger,.project-settings button.danger{background:var(--danger);color:#fff;border-color:var(--danger);white-space:nowrap}` +
|
|
14
|
+
`.project-settings button,.project-delete button{justify-self:start;min-height:36px;white-space:nowrap}.project-delete .actions a{min-height:36px;display:inline-flex;align-items:center}`;
|
|
15
|
+
const note = (notice) => notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : notice.said ? `<p role="status">${e(notice.said)}</p>` : "";
|
|
16
|
+
/** The project's page: its path, what Toolroll holds for it, and (for an instance operator) Delete project. */
|
|
17
|
+
export function projectSettingsHtml(view, csrf, notice) {
|
|
18
|
+
const held = `<p>Toolroll holds ${e(holdingsWords(view.holdings))} for <strong>${e(view.name)}</strong>.</p>`;
|
|
19
|
+
const head = `<section class="project-settings">${note(notice)}<p class="path">${e(view.repo)}</p>${held}`;
|
|
20
|
+
if (!view.canDelete)
|
|
21
|
+
return `${head}<p class="meta">An instance operator can delete a project.</p></section>`;
|
|
22
|
+
const body = view.running.length > 0
|
|
23
|
+
? `<p class="problem">Its work is running: ${e(view.running.join(", "))}. Stop it before deleting the project.</p>`
|
|
24
|
+
: `<p>Removes everything Toolroll holds for ${e(view.name)}. The repository and its own branches stay. There's no undo.</p>` +
|
|
25
|
+
`<form method="post" action="/settings/project/delete"><input type="hidden" name="csrf" value="${e(csrf)}"><input type="hidden" name="repo" value="${e(view.repo)}">` +
|
|
26
|
+
`<label><span>Type <strong>${e(view.name)}</strong> to continue</span><input name="name" autocomplete="off" autocapitalize="off" spellcheck="false" required></label>` +
|
|
27
|
+
`<button type="submit">Continue</button></form>`;
|
|
28
|
+
return `${head}<details class="danger-zone"${notice.problem ? " open" : ""}><summary>Delete project</summary>${body}</details></section>`;
|
|
29
|
+
}
|
|
30
|
+
/** The second step: exactly what goes, and the password. */
|
|
31
|
+
export function projectDeleteConfirmHtml(view, csrf, problem) {
|
|
32
|
+
const h = view.holdings;
|
|
33
|
+
const count = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
34
|
+
const items = [
|
|
35
|
+
`${count(h.tasks, "task")}${h.versions > 0 ? ` and ${count(h.versions, "version")}` : ""}, with ${count(h.runs, "run")} and their evidence`,
|
|
36
|
+
"The checkouts and branches Toolroll made",
|
|
37
|
+
...(h.chats > 0 ? [count(h.chats, "chat")] : []),
|
|
38
|
+
...(h.flows > 0 ? [`${count(h.flows, "flow")} and ${count(h.cards, "card")}`] : []),
|
|
39
|
+
...(h.teammates > 0 ? [count(h.teammates, "teammate")] : []),
|
|
40
|
+
"Its budgets, settings and knowledge",
|
|
41
|
+
];
|
|
42
|
+
return `<section class="project-delete">${problem === null ? "" : `<p class="problem" role="alert">${e(problem)}</p>`}` +
|
|
43
|
+
`<p>This removes:</p><ul class="removes">${items.map(one => `<li>${e(one)}</li>`).join("")}</ul>` +
|
|
44
|
+
`<p>The repository at <span class="path">${e(view.repo)}</span> and its own branches stay. The ledger keeps its history. There's no undo.</p>` +
|
|
45
|
+
`<form method="post" action="/settings/project/delete"><input type="hidden" name="csrf" value="${e(csrf)}"><input type="hidden" name="repo" value="${e(view.repo)}"><input type="hidden" name="name" value="${e(view.name)}"><input type="hidden" name="step" value="delete">` +
|
|
46
|
+
`<label>Your Toolroll password<input type="password" name="password" autocomplete="current-password"></label>` +
|
|
47
|
+
`<div class="actions"><button type="submit" class="danger">Delete project</button><a href="/settings/project?repo=${e(encodeURIComponent(view.repo))}">Cancel</a></div></form></section>`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type ExecResult } from "./exec.js";
|
|
2
|
+
import { type Store } from "./store.js";
|
|
3
|
+
/** What Toolroll names the branches it makes: toolroll/…, and standing-orders/… from before the rename. */
|
|
4
|
+
export declare const OWN_BRANCH = "toolroll/";
|
|
5
|
+
export declare const OWN_BRANCHES: readonly string[];
|
|
6
|
+
export type ProjectHoldings = {
|
|
7
|
+
tasks: number;
|
|
8
|
+
versions: number;
|
|
9
|
+
runs: number;
|
|
10
|
+
evidence: number;
|
|
11
|
+
checkouts: number;
|
|
12
|
+
chats: number;
|
|
13
|
+
flows: number;
|
|
14
|
+
cards: number;
|
|
15
|
+
teammates: number;
|
|
16
|
+
budgets: number;
|
|
17
|
+
settings: number;
|
|
18
|
+
};
|
|
19
|
+
export type ProjectDeleteResult = {
|
|
20
|
+
ok: true;
|
|
21
|
+
repo: string;
|
|
22
|
+
removed: ProjectHoldings & {
|
|
23
|
+
branches: number;
|
|
24
|
+
rows: number;
|
|
25
|
+
};
|
|
26
|
+
left: string[];
|
|
27
|
+
ledgerId: number;
|
|
28
|
+
} | {
|
|
29
|
+
ok: false;
|
|
30
|
+
reason: "running" | "failed";
|
|
31
|
+
said: string;
|
|
32
|
+
running?: string[];
|
|
33
|
+
};
|
|
34
|
+
/** What Toolroll holds for a project, counted. */
|
|
35
|
+
export declare function projectHoldings(store: Store, repo: string): ProjectHoldings;
|
|
36
|
+
/** What's in it, in words: "12 tasks, 3 versions, 30 runs, …". Empty kinds are left out. */
|
|
37
|
+
export declare function holdingsWords(held: ProjectHoldings & {
|
|
38
|
+
branches?: number;
|
|
39
|
+
}): string;
|
|
40
|
+
/** The project's work that is running right now, in words; empty when none is. */
|
|
41
|
+
export declare function projectRunning(store: Store, repo: string, now: Date): string[];
|
|
42
|
+
export type GitRunner = (args: readonly string[], cwd: string) => Promise<ExecResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Delete the project. Refuses while any of its work is running (checked
|
|
45
|
+
* again inside the deletion). Its tasks are held first so nothing new
|
|
46
|
+
* starts while the checkouts and branches go.
|
|
47
|
+
*/
|
|
48
|
+
export declare function deleteProject(store: Store, repo: string, options: {
|
|
49
|
+
actor: string;
|
|
50
|
+
via: "console" | "command line";
|
|
51
|
+
now: Date;
|
|
52
|
+
evidenceRoot: string | null;
|
|
53
|
+
poolRoot: string | null;
|
|
54
|
+
git?: GitRunner;
|
|
55
|
+
}): Promise<ProjectDeleteResult>;
|