@wjarka/cezarion 0.15.1 → 0.16.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/README.md +167 -46
- package/dist/agent-config/catalog.d.ts +6 -2
- package/dist/agent-config/catalog.js +78 -3
- package/dist/agent-config/catalog.js.map +1 -1
- package/dist/agent-config/model-settings/shared.js +6 -3
- package/dist/agent-config/model-settings/shared.js.map +1 -1
- package/dist/agent-config/models.js +4 -0
- package/dist/agent-config/models.js.map +1 -1
- package/dist/agent-config/validate.js +6 -0
- package/dist/agent-config/validate.js.map +1 -1
- package/dist/artifacts/cli.js +10 -2
- package/dist/artifacts/cli.js.map +1 -1
- package/dist/automations/coordinator.d.ts +7 -0
- package/dist/automations/coordinator.js +22 -2
- package/dist/automations/coordinator.js.map +1 -1
- package/dist/automations/github-poller.d.ts +4 -4
- package/dist/automations/github-poller.js.map +1 -1
- package/dist/automations/schedule-runner.d.ts +130 -0
- package/dist/automations/schedule-runner.js +326 -0
- package/dist/automations/schedule-runner.js.map +1 -0
- package/dist/automations/scheduler.d.ts +38 -7
- package/dist/automations/scheduler.js +90 -22
- package/dist/automations/scheduler.js.map +1 -1
- package/dist/automations/store.d.ts +80 -3
- package/dist/automations/store.js +208 -16
- package/dist/automations/store.js.map +1 -1
- package/dist/automations/task-template.d.ts +42 -6
- package/dist/automations/task-template.js +152 -24
- package/dist/automations/task-template.js.map +1 -1
- package/dist/automations/types.d.ts +142 -6
- package/dist/automations/types.js +64 -6
- package/dist/automations/types.js.map +1 -1
- package/dist/autosave-holders.js +8 -12
- package/dist/autosave-holders.js.map +1 -1
- package/dist/ci-wait/client.d.ts +8 -1
- package/dist/ci-wait/client.js +43 -1
- package/dist/ci-wait/client.js.map +1 -1
- package/dist/ci-wait/controller.d.ts +83 -4
- package/dist/ci-wait/controller.js +76 -11
- package/dist/ci-wait/controller.js.map +1 -1
- package/dist/ci-wait/errors.d.ts +7 -1
- package/dist/ci-wait/errors.js +36 -0
- package/dist/ci-wait/errors.js.map +1 -1
- package/dist/ci-wait/github.d.ts +2 -0
- package/dist/ci-wait/github.js +3 -1
- package/dist/ci-wait/github.js.map +1 -1
- package/dist/ci-wait/mcp.d.ts +2 -98
- package/dist/ci-wait/mcp.js +11 -25
- package/dist/ci-wait/mcp.js.map +1 -1
- package/dist/ci-wait/supervisor.d.ts +2 -1
- package/dist/ci-wait/supervisor.js +2 -1
- package/dist/ci-wait/supervisor.js.map +1 -1
- package/dist/ci-wait/tools.d.ts +307 -0
- package/dist/ci-wait/tools.js +63 -0
- package/dist/ci-wait/tools.js.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/contract/agent-config.d.ts +5 -0
- package/dist/contract/agent-profiles.d.ts +15 -0
- package/dist/contract/automation-schedule.d.ts +60 -0
- package/dist/contract/automations.d.ts +208 -36
- package/dist/contract/delegation.d.ts +96 -0
- package/dist/contract/discovery.d.ts +7 -0
- package/dist/contract/github.d.ts +1 -0
- package/dist/contract/health.d.ts +6 -0
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.js +1445 -745
- package/dist/contract/preview.d.ts +508 -0
- package/dist/contract/runs.d.ts +716 -15
- package/dist/contract/skills.d.ts +39 -0
- package/dist/contract/workflows.d.ts +6 -0
- package/dist/contract/workspace.d.ts +65 -0
- package/dist/contract/zoned-time.d.ts +35 -0
- package/dist/core/agent-env.d.ts +11 -0
- package/dist/core/agent-env.js +27 -5
- package/dist/core/agent-env.js.map +1 -1
- package/dist/core/agent-profiles.js +7 -0
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/agent-runner.d.ts +49 -1
- package/dist/core/agent-runner.js +2 -1
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/backend-detect.d.ts +3 -2
- package/dist/core/backend-detect.js +27 -1
- package/dist/core/backend-detect.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +1 -0
- package/dist/core/claude-cli-runner.js +69 -19
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/codex-app-server-runner.d.ts +1 -0
- package/dist/core/codex-app-server-runner.js +200 -25
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.d.ts +7 -3
- package/dist/core/codex-app-server-transport.js +11 -9
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/cursor-acp-runner.d.ts +1 -0
- package/dist/core/cursor-acp-runner.js +24 -9
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/host-model-catalog.js +2 -0
- package/dist/core/host-model-catalog.js.map +1 -1
- package/dist/core/managed-session.js +2 -0
- package/dist/core/managed-session.js.map +1 -1
- package/dist/core/model-identity.js +2 -0
- package/dist/core/model-identity.js.map +1 -1
- package/dist/core/model-presets.js +3 -0
- package/dist/core/model-presets.js.map +1 -1
- package/dist/core/omp-model-catalog.d.ts +43 -0
- package/dist/core/omp-model-catalog.js +205 -0
- package/dist/core/omp-model-catalog.js.map +1 -0
- package/dist/core/omp-runner.d.ts +73 -0
- package/dist/core/omp-runner.js +990 -0
- package/dist/core/omp-runner.js.map +1 -0
- package/dist/core/omp-ui-mapper.d.ts +106 -0
- package/dist/core/omp-ui-mapper.js +882 -0
- package/dist/core/omp-ui-mapper.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +18 -4
- package/dist/core/opencode-server-runner.js +337 -96
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/opencode-session-error.d.ts +11 -0
- package/dist/core/opencode-session-error.js +26 -0
- package/dist/core/opencode-session-error.js.map +1 -0
- package/dist/core/opencode-ui-mapper.js +4 -36
- package/dist/core/opencode-ui-mapper.js.map +1 -1
- package/dist/core/pi-runner.d.ts +1 -0
- package/dist/core/pi-runner.js +75 -12
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/core/provider-auth.d.ts +9 -2
- package/dist/core/provider-auth.js +43 -6
- package/dist/core/provider-auth.js.map +1 -1
- package/dist/core/runner-factory.js +3 -0
- package/dist/core/runner-factory.js.map +1 -1
- package/dist/core/runner-model-catalog.js +1 -0
- package/dist/core/runner-model-catalog.js.map +1 -1
- package/dist/core/runner-stderr.d.ts +2 -0
- package/dist/core/runner-stderr.js +20 -0
- package/dist/core/runner-stderr.js.map +1 -0
- package/dist/core/session-process.d.ts +22 -0
- package/dist/core/session-process.js +202 -0
- package/dist/core/session-process.js.map +1 -0
- package/dist/core/ui-events.d.ts +1 -1
- package/dist/core/usage-limit.js +3 -60
- package/dist/core/usage-limit.js.map +1 -1
- package/dist/data-gitignore.d.ts +6 -0
- package/dist/data-gitignore.js +57 -0
- package/dist/data-gitignore.js.map +1 -0
- package/dist/delegation/capacity.d.ts +19 -0
- package/dist/delegation/capacity.js +34 -0
- package/dist/delegation/capacity.js.map +1 -0
- package/dist/delegation/cli.js +13 -4
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/conversations.d.ts +4 -2
- package/dist/delegation/conversations.js +8 -12
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/credentials.d.ts +2 -0
- package/dist/delegation/credentials.js +10 -0
- package/dist/delegation/credentials.js.map +1 -1
- package/dist/delegation/destroy-observation.d.ts +42 -0
- package/dist/delegation/destroy-observation.js +115 -0
- package/dist/delegation/destroy-observation.js.map +1 -0
- package/dist/delegation/execution-identity.d.ts +6 -0
- package/dist/delegation/execution-identity.js +1 -1
- package/dist/delegation/execution-identity.js.map +1 -1
- package/dist/delegation/policy.d.ts +3 -2
- package/dist/delegation/policy.js +7 -5
- package/dist/delegation/policy.js.map +1 -1
- package/dist/delegation/process-liveness.d.ts +57 -20
- package/dist/delegation/process-liveness.js +114 -92
- package/dist/delegation/process-liveness.js.map +1 -1
- package/dist/delegation/provision.js +6 -6
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/results.js +4 -2
- package/dist/delegation/results.js.map +1 -1
- package/dist/delegation/retry-backoff.d.ts +23 -0
- package/dist/delegation/retry-backoff.js +18 -0
- package/dist/delegation/retry-backoff.js.map +1 -0
- package/dist/delegation/routes.d.ts +64 -58
- package/dist/delegation/scratch-cleanup.d.ts +29 -0
- package/dist/delegation/scratch-cleanup.js +143 -0
- package/dist/delegation/scratch-cleanup.js.map +1 -0
- package/dist/delegation/service.d.ts +20 -1
- package/dist/delegation/service.js +233 -70
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +12 -6
- package/dist/delegation/workspace.d.ts +23 -4
- package/dist/delegation/workspace.js +147 -31
- package/dist/delegation/workspace.js.map +1 -1
- package/dist/git-worktree-lock-helper.js +8 -3
- package/dist/git-worktree-lock-helper.js.map +1 -1
- package/dist/git-worktree-lock.d.ts +6 -1
- package/dist/git-worktree-lock.js +10 -4
- package/dist/git-worktree-lock.js.map +1 -1
- package/dist/git-worktree-release.d.ts +20 -0
- package/dist/git-worktree-release.js +27 -0
- package/dist/git-worktree-release.js.map +1 -0
- package/dist/git-worktree.d.ts +8 -2
- package/dist/git-worktree.js +19 -2
- package/dist/git-worktree.js.map +1 -1
- package/dist/handoff.d.ts +2 -2
- package/dist/handoff.js +1 -1
- package/dist/index.js +109 -76
- package/dist/index.js.map +1 -1
- package/dist/paths.d.ts +1 -1
- package/dist/paths.js +5 -1
- package/dist/paths.js.map +1 -1
- package/dist/preview/cdp.d.ts +13 -0
- package/dist/preview/cdp.js +69 -0
- package/dist/preview/cdp.js.map +1 -0
- package/dist/preview/chromium.d.ts +75 -0
- package/dist/preview/chromium.js +394 -0
- package/dist/preview/chromium.js.map +1 -0
- package/dist/preview/dev-server.d.ts +68 -0
- package/dist/preview/dev-server.js +341 -0
- package/dist/preview/dev-server.js.map +1 -0
- package/dist/preview/host.d.ts +154 -0
- package/dist/preview/host.js +681 -0
- package/dist/preview/host.js.map +1 -0
- package/dist/preview/registration.d.ts +63 -0
- package/dist/preview/registration.js +109 -0
- package/dist/preview/registration.js.map +1 -0
- package/dist/preview/session.d.ts +73 -0
- package/dist/preview/session.js +347 -0
- package/dist/preview/session.js.map +1 -0
- package/dist/preview/url.d.ts +6 -0
- package/dist/preview/url.js +17 -0
- package/dist/preview/url.js.map +1 -0
- package/dist/runs/agent-tmpdir-removal.d.ts +15 -0
- package/dist/runs/agent-tmpdir-removal.js +60 -0
- package/dist/runs/agent-tmpdir-removal.js.map +1 -0
- package/dist/runs/agent-tmpdir.d.ts +12 -1
- package/dist/runs/agent-tmpdir.js +123 -34
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/delegation-state.d.ts +5 -1
- package/dist/runs/delegation-state.js +9 -0
- package/dist/runs/delegation-state.js.map +1 -1
- package/dist/runs/event-history.d.ts +4 -4
- package/dist/runs/event-history.js +97 -117
- package/dist/runs/event-history.js.map +1 -1
- package/dist/runs/history-compressor.d.ts +29 -0
- package/dist/runs/history-compressor.js +116 -0
- package/dist/runs/history-compressor.js.map +1 -0
- package/dist/runs/history-file.d.ts +36 -0
- package/dist/runs/history-file.js +463 -0
- package/dist/runs/history-file.js.map +1 -0
- package/dist/runs/human-ask-summary.js +18 -13
- package/dist/runs/human-ask-summary.js.map +1 -1
- package/dist/runs/legacy-index.d.ts +62 -0
- package/dist/runs/legacy-index.js +168 -0
- package/dist/runs/legacy-index.js.map +1 -0
- package/dist/runs/raw-record.d.ts +52 -0
- package/dist/runs/raw-record.js +145 -0
- package/dist/runs/raw-record.js.map +1 -0
- package/dist/runs/retention.d.ts +13 -6
- package/dist/runs/retention.js +42 -13
- package/dist/runs/retention.js.map +1 -1
- package/dist/runs/run-claims.d.ts +23 -0
- package/dist/runs/run-claims.js +24 -0
- package/dist/runs/run-claims.js.map +1 -0
- package/dist/runs/run-database.d.ts +385 -0
- package/dist/runs/run-database.js +930 -0
- package/dist/runs/run-database.js.map +1 -0
- package/dist/runs/run-index.d.ts +35 -9
- package/dist/runs/run-index.js +200 -25
- package/dist/runs/run-index.js.map +1 -1
- package/dist/runs/run-row.d.ts +44 -0
- package/dist/runs/run-row.js +84 -0
- package/dist/runs/run-row.js.map +1 -0
- package/dist/runs/run-search.d.ts +29 -0
- package/dist/runs/run-search.js +63 -0
- package/dist/runs/run-search.js.map +1 -0
- package/dist/runs/store-open-error.d.ts +24 -0
- package/dist/runs/store-open-error.js +61 -0
- package/dist/runs/store-open-error.js.map +1 -0
- package/dist/runs/store.d.ts +667 -32
- package/dist/runs/store.js +2153 -324
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/transcript-facts.d.ts +77 -0
- package/dist/runs/transcript-facts.js +302 -0
- package/dist/runs/transcript-facts.js.map +1 -0
- package/dist/runs/webhook.js +5 -4
- package/dist/runs/webhook.js.map +1 -1
- package/dist/runs/worker-execution.d.ts +22 -0
- package/dist/runs/worker-execution.js +30 -0
- package/dist/runs/worker-execution.js.map +1 -0
- package/dist/server/capabilities.d.ts +1 -0
- package/dist/server/capabilities.js +2 -0
- package/dist/server/capabilities.js.map +1 -1
- package/dist/server/cockpit-ownership.d.ts +8 -0
- package/dist/server/cockpit-ownership.js +19 -0
- package/dist/server/cockpit-ownership.js.map +1 -1
- package/dist/server/forge/github.d.ts +1 -4
- package/dist/server/forge/github.js +47 -23
- package/dist/server/forge/github.js.map +1 -1
- package/dist/server/git.js +1 -1
- package/dist/server/git.js.map +1 -1
- package/dist/server/open-in-app.js +1 -0
- package/dist/server/open-in-app.js.map +1 -1
- package/dist/server/preview-socket.d.ts +36 -0
- package/dist/server/preview-socket.js +126 -0
- package/dist/server/preview-socket.js.map +1 -0
- package/dist/server/project-context.d.ts +31 -4
- package/dist/server/project-context.js +73 -9
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/provider-action-gate.js +1 -0
- package/dist/server/provider-action-gate.js.map +1 -1
- package/dist/server/repo-branches.d.ts +4 -3
- package/dist/server/repo-branches.js +5 -4
- package/dist/server/repo-branches.js.map +1 -1
- package/dist/server/server.d.ts +4500 -2727
- package/dist/server/server.js +651 -202
- package/dist/server/server.js.map +1 -1
- package/dist/server/upgrade-router.d.ts +23 -0
- package/dist/server/upgrade-router.js +53 -0
- package/dist/server/upgrade-router.js.map +1 -0
- package/dist/server/validators.d.ts +6 -1
- package/dist/server/validators.js +4 -4
- package/dist/server/validators.js.map +1 -1
- package/dist/server/ws.d.ts +16 -16
- package/dist/server/ws.js +56 -54
- package/dist/server/ws.js.map +1 -1
- package/dist/skills-remote.d.ts +14 -0
- package/dist/skills-remote.js +91 -15
- package/dist/skills-remote.js.map +1 -1
- package/dist/task-cli/cli.js +40 -16
- package/dist/task-cli/cli.js.map +1 -1
- package/dist/task-cli/discovery.d.ts +4 -3
- package/dist/task-cli/discovery.js +4 -3
- package/dist/task-cli/discovery.js.map +1 -1
- package/dist/task-cli/http.d.ts +2 -0
- package/dist/task-cli/http.js +10 -4
- package/dist/task-cli/http.js.map +1 -1
- package/dist/task-cli/projections.d.ts +5 -2
- package/dist/task-cli/projections.js +13 -0
- package/dist/task-cli/projections.js.map +1 -1
- package/dist/task-cli/watch.d.ts +15 -2
- package/dist/task-cli/watch.js +31 -9
- package/dist/task-cli/watch.js.map +1 -1
- package/dist/ui-state.d.ts +4 -3
- package/dist/ui-state.js +8 -3
- package/dist/ui-state.js.map +1 -1
- package/dist/workflows/grouped-command.d.ts +31 -0
- package/dist/workflows/grouped-command.js +143 -0
- package/dist/workflows/grouped-command.js.map +1 -0
- package/dist/workflows/run.d.ts +223 -42
- package/dist/workflows/run.js +1316 -398
- package/dist/workflows/run.js.map +1 -1
- package/dist/workflows/types.d.ts +12 -0
- package/dist/workflows/types.js +20 -0
- package/dist/workflows/types.js.map +1 -1
- package/dist/workspace/agent-accounts.d.ts +5 -1
- package/dist/workspace/agent-accounts.js +1 -0
- package/dist/workspace/agent-accounts.js.map +1 -1
- package/dist/workspace/agent-profiles.js +1 -1
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.d.ts +3 -1
- package/dist/workspace/config.js +1 -0
- package/dist/workspace/config.js.map +1 -1
- package/dist/worktree-setup.d.ts +85 -0
- package/dist/worktree-setup.js +164 -0
- package/dist/worktree-setup.js.map +1 -0
- package/package.json +7 -5
- package/scripts/benchmark-run-store-fixture.ts +428 -0
- package/scripts/benchmark-run-store.ts +743 -0
- package/scripts/benchmark-stuck-destroys.ts +143 -0
- package/scripts/mock-autonomous.mjs +11 -0
- package/scripts/mock-ci-tool.mjs +20 -5
- package/scripts/mock-claude.mjs +110 -1
- package/scripts/mock-codex-app-server.mjs +117 -2
- package/scripts/mock-codex-coalesce-steer.mjs +59 -0
- package/scripts/mock-codex-reverse-steer.mjs +130 -0
- package/scripts/mock-cursor-acp.mjs +75 -1
- package/scripts/mock-omp-rpc.mjs +605 -0
- package/scripts/mock-opencode-serve.mjs +312 -22
- package/scripts/mock-pi-rpc.mjs +109 -3
- package/scripts/mock-runner-crash.mjs +42 -0
- package/scripts/mock-silent-tail.mjs +78 -0
- package/scripts/mock-turn-messages.mjs +5 -0
- package/scripts/omp-ci-wait.mjs +29 -0
- package/scripts/omp-restrict-delegation.yml +4 -0
- package/scripts/pi-ci-wait.mjs +12 -9
- package/scripts/seed-archive-profile.ts +3 -3
- package/web/dist/assets/agent-accounts-CFOBMVHc.js +1 -0
- package/web/dist/assets/alert-dialog-BrpNUwMt.js +1 -0
- package/web/dist/assets/app-window-CSHwDX9N.js +1 -0
- package/web/dist/assets/button-C_rd7CPp.js +43 -0
- package/web/dist/assets/compare-variants-D6WXhvXA.js +1 -0
- package/web/dist/assets/diff-DrEARXTV.js +3 -0
- package/web/dist/assets/diff-controls-B1-j7nFg.js +1 -0
- package/web/dist/assets/{diff-view-DPn6bQ5W.js → diff-view-DvGLjdTk.js} +3 -3
- package/web/dist/assets/dropdown-menu-BegOZFrj.js +1 -0
- package/web/dist/assets/format-DpNe3S0A.js +1 -0
- package/web/dist/assets/git-toolbar-Cw4ljmhB.js +1 -0
- package/web/dist/assets/github-CfV5sqL0.js +1 -0
- package/web/dist/assets/{image-preview-DJ8cgb1Z.js → image-preview-FOEfqpZP.js} +1 -1
- package/web/dist/assets/index-DgWWlOLy.js +13 -0
- package/web/dist/assets/index-fBFnuvxu.css +1 -0
- package/web/dist/assets/{nav-row-styles-3j64kH5s.js → nav-row-styles-vp2JbhuJ.js} +1 -1
- package/web/dist/assets/play-CmVAj_fu.js +1 -0
- package/web/dist/assets/popover-BohP6WTx.js +1 -0
- package/web/dist/assets/preview-pane-connected-qTA5KNoJ.js +3 -0
- package/web/dist/assets/preview-state-vuMviq6q.js +1 -0
- package/web/dist/assets/prompt-templates-Cubdut_C.js +15 -0
- package/web/dist/assets/repo-git-Cf4t5PD0.js +1 -0
- package/web/dist/assets/{run-diff-5-RRdcVz.js → run-diff-BpkUW37Z.js} +3 -3
- package/web/dist/assets/run-header-68WHf9wV.js +1 -0
- package/web/dist/assets/skills-DiVIgKeU.js +1 -0
- package/web/dist/assets/square-terminal-B6RYYieR.js +1 -0
- package/web/dist/assets/status-dot-CqTJHSP9.js +1 -0
- package/web/dist/assets/{tab-link-K0hjzEXR.js → tab-link-B07Hu4QX.js} +1 -1
- package/web/dist/assets/task-changes--lQF6EYf.js +1 -0
- package/web/dist/assets/task-commits-Cx0qy4DN.js +1 -0
- package/web/dist/assets/task-files-D50s-gKW.js +2 -0
- package/web/dist/assets/task-github-item-DaqmSwYT.js +1 -0
- package/web/dist/assets/task-thread-BPQ64lui.js +7 -0
- package/web/dist/assets/{task-thread-Bw_nQuTx.css → task-thread-zNE2Q9E-.css} +1 -1
- package/web/dist/assets/textarea-D20O4Pw0.js +1 -0
- package/web/dist/assets/thread-state-DWcFMrvb.js +4 -0
- package/web/dist/assets/use-hand-to-agent-state-BLIGmwbd.css +1 -0
- package/web/dist/assets/use-hand-to-agent-state-Cy9eyyfL.js +1 -0
- package/web/dist/assets/{utils-fzNfbPzA.js → utils-JsL3ZsJf.js} +1 -1
- package/web/dist/assets/workflows-jwG7uxqi.js +11 -0
- package/web/dist/assets/{zoomable-image-CDmZ_Rtl.js → zoomable-image-BJJ64KGc.js} +1 -1
- package/web/dist/cezarion-lockup-dark.svg +1 -13
- package/web/dist/cezarion-lockup-light.svg +1 -13
- package/web/dist/cezarion-mark-dark.svg +1 -12
- package/web/dist/cezarion-mark-light.svg +1 -12
- package/web/dist/index.html +16 -21
- package/web/dist/assets/agent-accounts-CU2ZDv24.js +0 -1
- package/web/dist/assets/alert-dialog-C-xYE_dg.js +0 -43
- package/web/dist/assets/chevron-right-BENZ-1ZN.js +0 -1
- package/web/dist/assets/collapsible-DD9J91Iv.js +0 -1
- package/web/dist/assets/compare-variants-5FmqpFSN.js +0 -1
- package/web/dist/assets/diff-controls-Bj0YrioE.js +0 -1
- package/web/dist/assets/diff-rE8rm75J2.js +0 -3
- package/web/dist/assets/diff-stat-BKDCSVfJ.js +0 -1
- package/web/dist/assets/dropdown-menu-Ch5BYQh_.js +0 -1
- package/web/dist/assets/format-dBiNDNVe.js +0 -1
- package/web/dist/assets/git-toolbar-ClVvf5iF.js +0 -1
- package/web/dist/assets/github-BkNOyour.css +0 -1
- package/web/dist/assets/github-DeZMeMwJ.js +0 -1
- package/web/dist/assets/github-item-detail-W5F6GVjF.js +0 -1
- package/web/dist/assets/github-sidebar-model-DcMu-IK2.js +0 -1
- package/web/dist/assets/highlighter-CdHqIwFr.js +0 -3
- package/web/dist/assets/index-CatemBEL.js +0 -8
- package/web/dist/assets/index-MvfD8bZJ.css +0 -1
- package/web/dist/assets/markdown-zdKeLIYA.js +0 -2
- package/web/dist/assets/mobile-run-bar-BCfmFi8V.js +0 -1
- package/web/dist/assets/prompt-templates-CBPp39IU.js +0 -15
- package/web/dist/assets/reference-chip-D6owncJT.js +0 -1
- package/web/dist/assets/repo-git-CtdkZFey.js +0 -1
- package/web/dist/assets/run-header-BcjoDi0W.js +0 -1
- package/web/dist/assets/sheet-ChnYVrp1.js +0 -1
- package/web/dist/assets/skills-C8YKp2vr.js +0 -1
- package/web/dist/assets/task-changes-BW8YdWG8.js +0 -1
- package/web/dist/assets/task-commits-q2kB2y6L.js +0 -1
- package/web/dist/assets/task-files-pPL6_3Cr.js +0 -2
- package/web/dist/assets/task-github-item-BXF5R52U.js +0 -1
- package/web/dist/assets/task-thread-DtkFL3EC.js +0 -10
- package/web/dist/assets/textarea-DxlkE-Yd.js +0 -1
- package/web/dist/assets/token-metrics-DIAjrPlM.js +0 -1
- package/web/dist/assets/use-desktop-CrDny2uG.js +0 -1
- package/web/dist/assets/use-submit-shortcut-KWJsC906.js +0 -1
- package/web/dist/assets/workflows-TmcPEj2K.js +0 -11
- /package/web/dist/assets/{lib-BQXq3kEf2.js → lib-BQXq3kEf.js} +0 -0
|
@@ -7,20 +7,30 @@ import { prepareWorkerContext, workerContextTask } from './context.js';
|
|
|
7
7
|
import { acceptedWorkerIdentitySchema, workerContextHash, workerWorkflowHash } from './execution-identity.js';
|
|
8
8
|
import { createHash, randomUUID } from 'node:crypto';
|
|
9
9
|
import { discoveryRequestSchema, conversationSendRequestSchema, conversationInspectRequestSchema, conversationCancelRequestSchema, inboxReceiptRequestSchema, requestWaitRequestSchema, workerSpawnRequestSchema, workerSteerRequestSchema, workerWaitRequestSchema, workerParamsSchema, workerCancelWaitRequestSchema, } from '../contract/index.js';
|
|
10
|
-
import { workerOutcome } from '../runs/delegation-state.js';
|
|
11
|
-
import { QUICK_TASK_WORKFLOW, allowedToolsForStep, stepKind } from '../workflows/types.js';
|
|
10
|
+
import { workerDestroyView, workerOutcome } from '../runs/delegation-state.js';
|
|
11
|
+
import { QUICK_TASK_WORKFLOW, skillTaskSteps, plannedWorkflow, allowedToolsForStep, stepKind } from '../workflows/types.js';
|
|
12
|
+
import { discoverSkills } from '../skills.js';
|
|
12
13
|
import { findWorkflow } from '../workflows/load.js';
|
|
13
14
|
import { isAuthenticatedCaller } from './credentials.js';
|
|
14
15
|
import { parseDelegationEffort } from './effort.js';
|
|
15
16
|
import { authorizeSpawn, authorizeSpawnReplay, authorizeWorker, authorizeCancelWait, authorizeRetainedResult, DelegationPolicyError } from './policy.js';
|
|
16
|
-
import {
|
|
17
|
+
import { releaseThenRemoveOwnedWorkspace } from '../git-worktree-release.js';
|
|
18
|
+
import { gitCommonDir, planOwnedWorkspace, readOwnedDiff, resolveWorkerBaseline, WorkspaceHeldError } from './workspace.js';
|
|
19
|
+
import { holdersStillHold, observeDestroy, recordHolders } from './destroy-observation.js';
|
|
20
|
+
import { DESTROY_ATTENTION_ATTEMPTS, DESTROY_BACKOFF, retryDelayMs } from './retry-backoff.js';
|
|
17
21
|
/**
|
|
18
22
|
* The catalog definition a spawn runs (#451): the built-in quick-task constant when the request
|
|
19
|
-
* names
|
|
20
|
-
* path — else the named
|
|
23
|
+
* names neither workflow nor skill — never the catalog's `quick-task` entry, so a repo file cannot change the default
|
|
24
|
+
* path — else the named workflow or a one-step discovered skill task. Every agent step resolves its own runner and account (#452), so a
|
|
21
25
|
* chain may mix providers; a chain with no agent step has nothing for a worker to run.
|
|
22
26
|
*/
|
|
23
27
|
async function resolveSpawnWorkflow(root, request) {
|
|
28
|
+
if (request.skill !== undefined) {
|
|
29
|
+
const skills = await discoverSkills(root);
|
|
30
|
+
if (!skills.some(skill => skill.name === request.skill))
|
|
31
|
+
throw new DelegationPolicyError('invalid_input', `Unknown skill "${request.skill}"; available: ${skills.map(skill => skill.name).join(', ')}`);
|
|
32
|
+
return plannedWorkflow(skillTaskSteps(request.skill));
|
|
33
|
+
}
|
|
24
34
|
if (request.workflow === undefined)
|
|
25
35
|
return QUICK_TASK_WORKFLOW;
|
|
26
36
|
const workflow = await findWorkflow(root, request.workflow);
|
|
@@ -119,7 +129,13 @@ export class DelegationService {
|
|
|
119
129
|
serial = new Map();
|
|
120
130
|
destroyRetryTimers = new Map();
|
|
121
131
|
destroyRetryInFlight = new Map();
|
|
122
|
-
|
|
132
|
+
/** What each pending destroy's last full attempt observed (hearsay-tools/cezarion#879). */
|
|
133
|
+
destroyObservations = new Map();
|
|
134
|
+
/** Each project's common Git dir, resolved once per registration for the change check. */
|
|
135
|
+
commonDirs = new Map();
|
|
136
|
+
// Private and overridable so tests need not wait out production cadence.
|
|
137
|
+
destroyBackoff = DESTROY_BACKOFF;
|
|
138
|
+
destroyAttentionAttempts = DESTROY_ATTENTION_ATTEMPTS;
|
|
123
139
|
/** How long destroy waits for proven termination; private and overridable so tests need not wait it out. */
|
|
124
140
|
terminationTimeoutMs = 30_000;
|
|
125
141
|
registerProject(project) {
|
|
@@ -127,9 +143,11 @@ export class DelegationService {
|
|
|
127
143
|
if (existing?.store === project.store && existing.manager === project.manager)
|
|
128
144
|
return () => { };
|
|
129
145
|
this.clearDestroyRetries(project.id);
|
|
146
|
+
existing?.manager.pauseWorkerCleanup();
|
|
130
147
|
this.projects.set(project.id, project);
|
|
131
148
|
return () => { if (this.projects.get(project.id) === project) {
|
|
132
149
|
this.clearDestroyRetries(project.id);
|
|
150
|
+
project.manager.pauseWorkerCleanup();
|
|
133
151
|
this.projects.delete(project.id);
|
|
134
152
|
} };
|
|
135
153
|
}
|
|
@@ -138,15 +156,22 @@ export class DelegationService {
|
|
|
138
156
|
clearTimeout(timer);
|
|
139
157
|
this.destroyRetryTimers.delete(projectId);
|
|
140
158
|
this.destroyRetryInFlight.delete(projectId);
|
|
159
|
+
this.destroyObservations.delete(projectId);
|
|
160
|
+
this.commonDirs.delete(projectId);
|
|
141
161
|
}
|
|
142
162
|
/** Called only after manager recovery, when persisted destroy intents may be retried. */
|
|
143
163
|
armDestroyRetries(projectId) {
|
|
144
164
|
const project = this.projects.get(projectId);
|
|
145
165
|
if (!project)
|
|
146
166
|
return;
|
|
167
|
+
project.manager.recoverWorkerCleanup();
|
|
168
|
+
// A pending destroy keeps its worker in the live set (`isLiveRecord`), so this is every one.
|
|
147
169
|
for (const run of project.store.listRuns())
|
|
148
170
|
this.scheduleDestroyRetry(project, run.id);
|
|
149
171
|
}
|
|
172
|
+
/** Arms the next automatic attempt of a pending destroy. A retry state written before a restart
|
|
173
|
+
* resumes where it was; the fast cadence is the floor, and a little over the cap the ceiling, so
|
|
174
|
+
* a clock that jumped cannot park a destroy for days (hearsay-tools/cezarion#879). */
|
|
150
175
|
scheduleDestroyRetry(project, workerId) {
|
|
151
176
|
if (this.projects.get(project.id) !== project)
|
|
152
177
|
return;
|
|
@@ -160,6 +185,9 @@ export class DelegationService {
|
|
|
160
185
|
}
|
|
161
186
|
if (timers.has(workerId) || this.destroyRetryInFlight.get(project.id)?.has(workerId))
|
|
162
187
|
return;
|
|
188
|
+
const { fastMs, capMs } = this.destroyBackoff;
|
|
189
|
+
const nextAt = run.destroyRetry ? Date.parse(run.destroyRetry.nextAt) - Date.now() : 0;
|
|
190
|
+
const delay = Math.min(Math.max(fastMs, nextAt), capMs * 1.1);
|
|
163
191
|
const timer = setTimeout(() => {
|
|
164
192
|
timers.delete(workerId);
|
|
165
193
|
if (this.projects.get(project.id) !== project)
|
|
@@ -170,6 +198,19 @@ export class DelegationService {
|
|
|
170
198
|
this.destroyRetryInFlight.set(project.id, inFlight);
|
|
171
199
|
}
|
|
172
200
|
inFlight.add(workerId);
|
|
201
|
+
void this.destroyTick(project, workerId).catch(() => undefined).finally(() => {
|
|
202
|
+
inFlight.delete(workerId);
|
|
203
|
+
this.scheduleDestroyRetry(project, workerId);
|
|
204
|
+
});
|
|
205
|
+
}, delay);
|
|
206
|
+
timer.unref?.();
|
|
207
|
+
timers.set(workerId, timer);
|
|
208
|
+
}
|
|
209
|
+
/** One automatic attempt. It runs in full only when something its last full attempt observed has
|
|
210
|
+
* changed, or a holder it named has exited; either way it records the attempt and when the next
|
|
211
|
+
* is due, and from the attention threshold on the cockpit says the cleanup needs attention. */
|
|
212
|
+
destroyTick(project, workerId) {
|
|
213
|
+
return this.serialized(`worker:${project.id}:${workerId}`, async () => {
|
|
173
214
|
const check = () => {
|
|
174
215
|
if (this.projects.get(project.id) !== project)
|
|
175
216
|
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
@@ -179,13 +220,48 @@ export class DelegationService {
|
|
|
179
220
|
}
|
|
180
221
|
return current;
|
|
181
222
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
223
|
+
check();
|
|
224
|
+
const seen = this.destroyObservations.get(project.id)?.get(workerId);
|
|
225
|
+
const dataDir = join(project.root, '.ai/cezar');
|
|
226
|
+
const unchanged = !!seen && holdersStillHold({ store: project.store, dataDir, workerId, holders: seen.holders }) &&
|
|
227
|
+
seen.key === observeDestroy({ store: project.store, dataDir, commonDir: await this.commonDir(project), workerId });
|
|
228
|
+
// One automatic full attempt at a time per project: attempts that coincide (every pending destroy after a
|
|
229
|
+
// restart) would otherwise contend for the worktree mutation lock and come back lock-busy, never skipped.
|
|
230
|
+
if (!unchanged)
|
|
231
|
+
await this.serialized(`destroy-retries:${project.id}`, () => this.destroyAttempt(project, workerId, check, 'scheduled')).catch(() => undefined);
|
|
232
|
+
if (this.projects.get(project.id) !== project)
|
|
233
|
+
return;
|
|
234
|
+
const current = project.store.getRun(workerId);
|
|
235
|
+
if (current?.delegation?.role !== 'worker' || !current.delegation.destroy || current.delegation.destroy.phase === 'complete')
|
|
236
|
+
return;
|
|
237
|
+
const attempts = (current.destroyRetry?.attempts ?? 0) + 1;
|
|
238
|
+
const retry = { attempts, nextAt: new Date(Date.now() + retryDelayMs(attempts, this.destroyBackoff)).toISOString(),
|
|
239
|
+
...(attempts >= this.destroyAttentionAttempts ? { needsAttention: true } : {}) };
|
|
240
|
+
project.store.commitDestroyRetry(workerId, retry);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
commonDir(project) {
|
|
244
|
+
let dir = this.commonDirs.get(project.id);
|
|
245
|
+
if (!dir) {
|
|
246
|
+
// A failure is not cached: the next attempt asks again, and until then the check is record-only.
|
|
247
|
+
dir = gitCommonDir(project.root).catch(() => { this.commonDirs.delete(project.id); return undefined; });
|
|
248
|
+
this.commonDirs.set(project.id, dir);
|
|
249
|
+
}
|
|
250
|
+
return dir;
|
|
251
|
+
}
|
|
252
|
+
observeAttempt(project, workerId, seen) {
|
|
253
|
+
if (this.projects.get(project.id) !== project)
|
|
254
|
+
return;
|
|
255
|
+
let observations = this.destroyObservations.get(project.id);
|
|
256
|
+
if (!seen) {
|
|
257
|
+
observations?.delete(workerId);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!observations) {
|
|
261
|
+
observations = new Map();
|
|
262
|
+
this.destroyObservations.set(project.id, observations);
|
|
263
|
+
}
|
|
264
|
+
observations.set(workerId, seen);
|
|
189
265
|
}
|
|
190
266
|
context(caller) {
|
|
191
267
|
if (!delegationEnabled())
|
|
@@ -234,7 +310,7 @@ export class DelegationService {
|
|
|
234
310
|
return { project, sender, recipient, root, worker };
|
|
235
311
|
}
|
|
236
312
|
currentConversation(project, root) {
|
|
237
|
-
const state = reconcileConversationState(root, project.store.
|
|
313
|
+
const state = reconcileConversationState(root, (id) => project.store.getRun(id), new Date().toISOString(), run => run.delegation?.role === 'worker'
|
|
238
314
|
? project.store.readWorkerExecution(run.id)?.phase === 'complete' : !project.manager.isActive(run.id));
|
|
239
315
|
if (root.delegation?.role === 'root' && state && state !== root.delegation.conversation)
|
|
240
316
|
project.store.commitConversation(root.id, state);
|
|
@@ -482,6 +558,7 @@ export class DelegationService {
|
|
|
482
558
|
...(request.model === undefined ? {} : { model: request.model }),
|
|
483
559
|
...(effortPin === undefined ? {} : { effort: effortPin }),
|
|
484
560
|
...(request.workflow === undefined ? {} : { workflow: request.workflow }),
|
|
561
|
+
...(request.skill === undefined ? {} : { skill: request.skill }),
|
|
485
562
|
})).digest('hex');
|
|
486
563
|
const receipt = parent.delegation.receipts.find(r => r.requestId === request.requestId);
|
|
487
564
|
if (receipt) {
|
|
@@ -492,7 +569,7 @@ export class DelegationService {
|
|
|
492
569
|
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
493
570
|
return { workerId: worker.id, baselineSha: worker.delegation.workspace.baselineSha };
|
|
494
571
|
}
|
|
495
|
-
authorizeSpawn(caller, parent, project.id);
|
|
572
|
+
authorizeSpawn(caller, parent, project.id, id => project.store.getRun(id));
|
|
496
573
|
const catalog = await resolveSpawnWorkflow(project.root, request);
|
|
497
574
|
const resolvedSteps = await resolveSpawnSteps(project.manager, parent.id, request, catalog, (step, settings) => this.validateModels(request, [{ step, settings }]));
|
|
498
575
|
// Run-level fields hold the first agent step (cockpit columns, pre-#452 evidence readers);
|
|
@@ -514,7 +591,7 @@ export class DelegationService {
|
|
|
514
591
|
const current = this.context(caller);
|
|
515
592
|
if (current !== project)
|
|
516
593
|
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
517
|
-
authorizeSpawn(caller, project.store.getRun(parent.id), project.id);
|
|
594
|
+
authorizeSpawn(caller, project.store.getRun(parent.id), project.id, id => project.store.getRun(id));
|
|
518
595
|
// The public definition carries what each agent step RESOLVED to — runner, account,
|
|
519
596
|
// model, effort and the narrowed grants — so the bound `workflowDef` and the private
|
|
520
597
|
// per-step identity describe the same launch and the manager can hold them against each
|
|
@@ -537,8 +614,8 @@ export class DelegationService {
|
|
|
537
614
|
steps: workflowDef.steps.map(step => ({ id: step.id, name: step.name ?? step.id, kind: stepKind(step) })),
|
|
538
615
|
}, parent.id, request.requestId, { role: 'worker', permissions: [], parentRunId: parent.id, workspace, ...(context ? { context } : {}) }, requestHash, {
|
|
539
616
|
...identity, ...(context ? { contextHash: workerContextHash(context) } : {}),
|
|
540
|
-
// A named catalog chain is bound like the context recipe; the default quick-task leaves the identity as before.
|
|
541
|
-
...(request.workflow === undefined ? {} : { workflowHash: workerWorkflowHash(workflowDef) }),
|
|
617
|
+
// A named catalog chain or skill is bound like the context recipe; the default quick-task leaves the identity as before.
|
|
618
|
+
...(request.workflow === undefined && request.skill === undefined ? {} : { workflowHash: workerWorkflowHash(workflowDef) }),
|
|
542
619
|
});
|
|
543
620
|
accepted = true;
|
|
544
621
|
project.manager.enqueueOwnedRun(worker.id);
|
|
@@ -562,7 +639,7 @@ export class DelegationService {
|
|
|
562
639
|
...(worker.delegation.context === undefined ? {} : { inputs: worker.delegation.context.inputs }),
|
|
563
640
|
...(worker.currentStepId === undefined ? {} : { currentStepId: worker.currentStepId }),
|
|
564
641
|
...(worker.activity === undefined ? {} : { activity: worker.activity }),
|
|
565
|
-
...(wait ? { wait } : {}), ...(worker.delegation.destroy ? { destroy: worker
|
|
642
|
+
...(wait ? { wait } : {}), ...(worker.delegation.destroy ? { destroy: workerDestroyView(worker) } : {}), ...(outcome ? { outcome } : {}) };
|
|
566
643
|
}
|
|
567
644
|
async collect(caller, params) {
|
|
568
645
|
const project = this.context(caller);
|
|
@@ -655,36 +732,74 @@ export class DelegationService {
|
|
|
655
732
|
check();
|
|
656
733
|
return this.destroySerialized(project, workerId, check);
|
|
657
734
|
}
|
|
735
|
+
/** An explicit destroy (Clean up, `cez worker destroy`): always a full attempt, and it restarts the
|
|
736
|
+
* backoff, so a timer armed for a later automatic attempt is dropped and re-armed at the fast cadence. */
|
|
658
737
|
destroySerialized(project, workerId, check) {
|
|
659
|
-
return this.serialized(`worker:${project.id}:${workerId}`,
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
738
|
+
return this.serialized(`worker:${project.id}:${workerId}`, () => this.destroyAttempt(project, workerId, check, 'manual')).finally(() => {
|
|
739
|
+
// A replaced registration owns its own timers under the same project id: leave them alone.
|
|
740
|
+
if (this.projects.get(project.id) !== project)
|
|
741
|
+
return;
|
|
742
|
+
const timers = this.destroyRetryTimers.get(project.id);
|
|
743
|
+
clearTimeout(timers?.get(workerId));
|
|
744
|
+
timers?.delete(workerId);
|
|
745
|
+
this.scheduleDestroyRetry(project, workerId);
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
/** One full destroy attempt; the caller holds the worker's serialization key. A manual attempt
|
|
749
|
+
* clears the run's `destroyRetry`, which resets the backoff; a completed destroy drops it. */
|
|
750
|
+
async destroyAttempt(project, workerId, check, mode) {
|
|
751
|
+
const assertAttached = () => {
|
|
752
|
+
if (this.projects.get(project.id) !== project)
|
|
753
|
+
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
754
|
+
};
|
|
755
|
+
assertAttached();
|
|
756
|
+
let worker = check();
|
|
757
|
+
if (worker.delegation?.role !== 'worker')
|
|
758
|
+
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
759
|
+
const parent = project.store.getRun(worker.delegation.parentRunId);
|
|
760
|
+
if (parent?.delegation?.role === 'root' && parent.delegation.receipts.some(receipt => receipt.workerId === workerId && receipt.deletion)) {
|
|
761
|
+
throw new DelegationPolicyError('incompatible_state', 'Worker history deletion has begun; retry history deletion');
|
|
762
|
+
}
|
|
763
|
+
const commonDir = await this.commonDir(project);
|
|
764
|
+
assertAttached();
|
|
765
|
+
worker = check();
|
|
766
|
+
if (worker.delegation?.role !== 'worker')
|
|
767
|
+
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
768
|
+
// What this attempt decided on (hearsay-tools/cezarion#879): a later tick that would see the same skips its
|
|
769
|
+
// work. Retaken where the attempt decides (after termination, at each holder proof), so its own writes up
|
|
770
|
+
// to there (stopping the worker, the removal's checkpoint) are not a change, and anything later is.
|
|
771
|
+
const observe = () => observeDestroy({ store: project.store, dataDir: join(project.root, '.ai/cezar'), commonDir, workerId });
|
|
772
|
+
let key = observe();
|
|
773
|
+
const workspace = worker.delegation.workspace;
|
|
774
|
+
const requestedAt = worker.delegation.destroy?.requestedAt ?? new Date().toISOString();
|
|
775
|
+
const resources = (worker.delegation.destroy?.remaining ?? ['worktree', 'branch']).filter((resource) => resource !== 'process');
|
|
776
|
+
const persist = (phase, remaining, error) => {
|
|
664
777
|
assertAttached();
|
|
665
|
-
|
|
778
|
+
worker = project.store.getRun(workerId);
|
|
666
779
|
if (worker.delegation?.role !== 'worker')
|
|
667
780
|
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
781
|
+
project.store.commitDelegation([{ id: workerId, delegation: { ...worker.delegation, destroy: { requestedAt, phase, remaining,
|
|
782
|
+
...(error ? { error: error.slice(0, 2_000) } : {}) } } }]);
|
|
783
|
+
// The retry state lives beside the delegation: an explicit destroy and a completed one both drop it.
|
|
784
|
+
if (worker.destroyRetry && (phase === 'complete' || (mode === 'manual' && phase === 'requested')))
|
|
785
|
+
project.store.commitDestroyRetry(workerId, undefined);
|
|
786
|
+
};
|
|
787
|
+
/** What the attempt decided on, and the holders it ran into, kept only when that explains the
|
|
788
|
+
* failure. A complete destroy keeps nothing, and neither does a failure no key input or named
|
|
789
|
+
* holder accounts for (lock contention, a failed Git step, an unnamed blocker): it can clear
|
|
790
|
+
* without changing anything a tick could see, so the next tick attempts in full. */
|
|
791
|
+
const observed = (result, holders, explained) => {
|
|
792
|
+
this.observeAttempt(project, workerId, result.state === 'complete' || !explained ? undefined : { key, holders: recordHolders(holders) });
|
|
793
|
+
return result;
|
|
794
|
+
};
|
|
795
|
+
persist('requested', worker.delegation.destroy?.remaining ?? ['process', 'worktree', 'branch']);
|
|
796
|
+
try {
|
|
683
797
|
persist('terminating', ['process', ...resources]);
|
|
684
798
|
project.manager.requestWorkerStop(workerId);
|
|
685
799
|
let result;
|
|
686
800
|
const terminated = await project.manager.awaitRunTermination(workerId, this.terminationTimeoutMs, { reapOrphans: true });
|
|
687
801
|
assertAttached();
|
|
802
|
+
key = observe();
|
|
688
803
|
if (!terminated) {
|
|
689
804
|
// #469: name what blocks a crashed generation; other causes keep the generic message.
|
|
690
805
|
const taken = project.manager.takeWorkerTerminationBlocker(workerId);
|
|
@@ -695,41 +810,89 @@ export class DelegationService {
|
|
|
695
810
|
project.store.appendEvent(workerId, { type: 'lifecycle', message: `destroy blocked: ${reason}` });
|
|
696
811
|
result = { workerId, state: 'incomplete', remaining: ['process', ...resources], error: !taken ? 'Worker termination is not proven; retry cleanup later'
|
|
697
812
|
: taken.blocker.kind === 'unreadable' ? reason : `Worker termination is not proven: ${reason}; retry cleanup later` };
|
|
813
|
+
persist(result.state, result.remaining, result.error);
|
|
814
|
+
return observed(result, taken?.blocker.kind === 'processes' ? taken.blocker.pids : taken?.blocker.kind === 'controller' ? [taken.blocker.pid] : [], !!taken);
|
|
698
815
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
816
|
+
persist('cleaning', resources);
|
|
817
|
+
const snapshot = structuredClone(check());
|
|
818
|
+
const proof = project.store.readWorkerExecution(workerId);
|
|
819
|
+
const evidence = await collectWorkerEvidence(project.root, project.store, snapshot);
|
|
820
|
+
assertAttached();
|
|
821
|
+
const current = check();
|
|
822
|
+
if (proof?.phase !== 'complete' || project.store.readWorkerExecution(workerId)?.generation !== proof.generation ||
|
|
823
|
+
project.store.readWorkerExecution(workerId)?.phase !== 'complete' || current.status !== snapshot.status ||
|
|
824
|
+
JSON.stringify(current.delegation) !== JSON.stringify(snapshot.delegation))
|
|
825
|
+
throw new Error('Worker changed before cleanup checkpoint');
|
|
826
|
+
// This immutable parent payload must be durable before the first destructive operation. A
|
|
827
|
+
// payload already on disk is durable, whatever cleanup phase it names (hearsay-tools/cezarion#879).
|
|
828
|
+
project.store.commitWorkerResult(evidence.result.parentRunId, evidence.result, evidence.diffSnapshot, { ignoreCleanup: true });
|
|
829
|
+
assertAttached();
|
|
830
|
+
check();
|
|
831
|
+
const release = project.manager.claimWorkerCleanup(workerId);
|
|
832
|
+
const assertCurrent = () => {
|
|
704
833
|
assertAttached();
|
|
705
834
|
const current = check();
|
|
706
|
-
if (
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
835
|
+
if (!release || current.delegation?.role !== 'worker' ||
|
|
836
|
+
JSON.stringify(current.delegation.workspace) !== JSON.stringify(workspace) ||
|
|
837
|
+
project.store.readWorkerExecution(workerId)?.generation !== proof.generation ||
|
|
838
|
+
project.store.readWorkerExecution(workerId)?.phase !== 'complete') {
|
|
839
|
+
throw new Error('Worker resource ownership changed');
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
const assertSafe = () => {
|
|
843
|
+
assertCurrent();
|
|
844
|
+
key = observe();
|
|
845
|
+
const holders = project.store.workerResourceHolders(workerId, proof.generation, workspace.resourceId);
|
|
846
|
+
if (holders === 'safe')
|
|
847
|
+
return;
|
|
848
|
+
throw holders.length ? new WorkspaceHeldError(holders) : new Error('Worker resources may still be held; cleanup will retry');
|
|
849
|
+
};
|
|
850
|
+
// The removal turns being held into an incomplete result; it reports the holders either of its
|
|
851
|
+
// checks named, or that it stopped for a reason no key input explains, an unnamed holder
|
|
852
|
+
// included (hearsay-tools/cezarion#879).
|
|
853
|
+
let holders = [];
|
|
854
|
+
let explained = true;
|
|
855
|
+
try {
|
|
856
|
+
assertCurrent();
|
|
857
|
+
// #781: release preview before the final fresh proof immediately preceding removal.
|
|
858
|
+
result = await releaseThenRemoveOwnedWorkspace({ previewHost: project.manager.previewHost }, project.root, workspace, assertCurrent, assertSafe, { held: pids => { holders = pids; }, unexplained: () => { explained = false; } });
|
|
729
859
|
}
|
|
860
|
+
catch {
|
|
861
|
+
explained = false;
|
|
862
|
+
result = { workerId, state: 'incomplete', remaining: resources, error: 'Worker resources may still be held; cleanup will retry' };
|
|
863
|
+
}
|
|
864
|
+
finally {
|
|
865
|
+
release?.();
|
|
866
|
+
}
|
|
867
|
+
// An already-started checked Git operation may finish after detach. Its
|
|
868
|
+
// checkpoint makes a new controller's retry safe; the old store must not
|
|
869
|
+
// publish a result after ownership of the project has moved.
|
|
870
|
+
assertAttached();
|
|
730
871
|
persist(result.state, result.remaining, result.error);
|
|
731
|
-
|
|
732
|
-
|
|
872
|
+
// Preserve the captured bytes even if Git removal was only partially successful.
|
|
873
|
+
const removed = !result.remaining.includes('worktree');
|
|
874
|
+
project.store.commitWorkerResult(evidence.result.parentRunId, { ...evidence.result, observedAt: new Date().toISOString(),
|
|
875
|
+
cleanup: result.state, outcome: result.state === 'complete' ? 'destroyed' : evidence.result.lastExecutionOutcome,
|
|
876
|
+
workspace: { ...workspace, state: removed ? 'deleted' : evidence.result.workspace.state },
|
|
877
|
+
head: removed ? { state: 'deleted', reason: 'missing', ...('sha' in evidence.result.head ? { sha: evidence.result.head.sha } : {}) } : evidence.result.head,
|
|
878
|
+
diff: evidence.result.diff.state === 'available' ? { ...evidence.result.diff, snapshotId: randomUUID() } : evidence.result.diff,
|
|
879
|
+
}, evidence.diffSnapshot);
|
|
880
|
+
return observed(result, holders, explained);
|
|
881
|
+
}
|
|
882
|
+
catch (error) {
|
|
883
|
+
// hearsay-tools/cezarion#879: an attempt that throws says why, instead of leaving an
|
|
884
|
+
// in-progress phase with no error, as long as this is still the same pending destroy. A
|
|
885
|
+
// throw explains nothing a tick could see clear, so the next tick attempts in full.
|
|
886
|
+
this.observeAttempt(project, workerId, undefined);
|
|
887
|
+
try {
|
|
888
|
+
const current = this.projects.get(project.id) === project ? project.store.getRun(workerId) : undefined;
|
|
889
|
+
if (current?.delegation?.role === 'worker' && current.delegation.destroy?.requestedAt === requestedAt && current.delegation.destroy.phase !== 'complete') {
|
|
890
|
+
persist('incomplete', current.delegation.destroy.remaining, error instanceof Error ? error.message : String(error));
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
catch { /* the attempt's own error is the one to report */ }
|
|
894
|
+
throw error;
|
|
895
|
+
}
|
|
733
896
|
}
|
|
734
897
|
}
|
|
735
898
|
//# sourceMappingURL=service.js.map
|