@canhta/dsh-autopilot 0.1.0-alpha.1
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/AGENTS.md +41 -0
- package/CONTEXT.md +39 -0
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/cordis.patch.yml +13 -0
- package/deploy/dsh-autopilot.service +26 -0
- package/docs/CONTRIBUTING.md +60 -0
- package/docs/README.md +34 -0
- package/docs/agents/domain.md +7 -0
- package/docs/agents/issue-tracker.md +21 -0
- package/docs/agents/triage-labels.md +13 -0
- package/docs/assets/banner.png +0 -0
- package/docs/deployment.md +138 -0
- package/docs/engineering.md +43 -0
- package/docs/specs/execution.md +65 -0
- package/docs/specs/integrations.md +89 -0
- package/docs/specs/lifecycle.md +81 -0
- package/docs/specs/operations.md +89 -0
- package/docs/specs/plugin.md +49 -0
- package/docs/specs/providers.md +62 -0
- package/docs/specs/scope.md +35 -0
- package/docs/specs/ui-components.md +96 -0
- package/docs/specs/web-ui.md +64 -0
- package/lib/admission/cancellation-control.d.ts +11 -0
- package/lib/admission/cancellation-control.js +72 -0
- package/lib/admission/cancellation-control.js.map +1 -0
- package/lib/admission/candidates.d.ts +2 -0
- package/lib/admission/candidates.js +23 -0
- package/lib/admission/candidates.js.map +1 -0
- package/lib/admission/composition-claim.d.ts +10 -0
- package/lib/admission/composition-claim.js +13 -0
- package/lib/admission/composition-claim.js.map +1 -0
- package/lib/admission/constants.d.ts +12 -0
- package/lib/admission/constants.js +13 -0
- package/lib/admission/constants.js.map +1 -0
- package/lib/admission/deliveries.d.ts +6 -0
- package/lib/admission/deliveries.js +175 -0
- package/lib/admission/deliveries.js.map +1 -0
- package/lib/admission/delivery-control.d.ts +28 -0
- package/lib/admission/delivery-control.js +294 -0
- package/lib/admission/delivery-control.js.map +1 -0
- package/lib/admission/execution-control.d.ts +29 -0
- package/lib/admission/execution-control.js +177 -0
- package/lib/admission/execution-control.js.map +1 -0
- package/lib/admission/index.d.ts +4 -0
- package/lib/admission/index.js +4 -0
- package/lib/admission/index.js.map +1 -0
- package/lib/admission/model.d.ts +296 -0
- package/lib/admission/model.js +13 -0
- package/lib/admission/model.js.map +1 -0
- package/lib/admission/pause-control.d.ts +44 -0
- package/lib/admission/pause-control.js +220 -0
- package/lib/admission/pause-control.js.map +1 -0
- package/lib/admission/policy.d.ts +39 -0
- package/lib/admission/policy.js +238 -0
- package/lib/admission/policy.js.map +1 -0
- package/lib/admission/ports.d.ts +13 -0
- package/lib/admission/ports.js +2 -0
- package/lib/admission/ports.js.map +1 -0
- package/lib/admission/publication-control.d.ts +16 -0
- package/lib/admission/publication-control.js +153 -0
- package/lib/admission/publication-control.js.map +1 -0
- package/lib/admission/reconciler.d.ts +7 -0
- package/lib/admission/reconciler.js +121 -0
- package/lib/admission/reconciler.js.map +1 -0
- package/lib/admission/resume-control.d.ts +27 -0
- package/lib/admission/resume-control.js +213 -0
- package/lib/admission/resume-control.js.map +1 -0
- package/lib/admission/run-fence.d.ts +11 -0
- package/lib/admission/run-fence.js +49 -0
- package/lib/admission/run-fence.js.map +1 -0
- package/lib/admission/service.d.ts +130 -0
- package/lib/admission/service.js +415 -0
- package/lib/admission/service.js.map +1 -0
- package/lib/admission/state-domain.d.ts +11 -0
- package/lib/admission/state-domain.js +33 -0
- package/lib/admission/state-domain.js.map +1 -0
- package/lib/admission/state-integrity.d.ts +19 -0
- package/lib/admission/state-integrity.js +102 -0
- package/lib/admission/state-integrity.js.map +1 -0
- package/lib/admission/state-migration.d.ts +4 -0
- package/lib/admission/state-migration.js +46 -0
- package/lib/admission/state-migration.js.map +1 -0
- package/lib/admission/state.d.ts +4524 -0
- package/lib/admission/state.js +394 -0
- package/lib/admission/state.js.map +1 -0
- package/lib/admission.d.ts +1 -0
- package/lib/admission.js +2 -0
- package/lib/admission.js.map +1 -0
- package/lib/client-types/client/OperationsAtoms.d.ts +30 -0
- package/lib/client-types/client/OperationsPanel.d.ts +34 -0
- package/lib/client-types/client/RunsView.d.ts +14 -0
- package/lib/client-types/client/SettingsCapabilitySections.d.ts +16 -0
- package/lib/client-types/client/SettingsPanel.d.ts +40 -0
- package/lib/client-types/client/SettingsPolicySections.d.ts +13 -0
- package/lib/client-types/client/SettingsProviderSection.d.ts +21 -0
- package/lib/client-types/client/SummaryView.d.ts +10 -0
- package/lib/client-types/client/WorktreesView.d.ts +9 -0
- package/lib/client-types/client/index.d.ts +9 -0
- package/lib/client-types/client/locales/en.d.ts +154 -0
- package/lib/client-types/client/locales/index.d.ts +9 -0
- package/lib/client-types/client/locales/zh.d.ts +155 -0
- package/lib/client-types/client/settings-draft.d.ts +29 -0
- package/lib/client-types/client/state.d.ts +63 -0
- package/lib/client-types/code-host/index.d.ts +2 -0
- package/lib/client-types/code-host/model.d.ts +118 -0
- package/lib/client-types/code-host/registry.d.ts +23 -0
- package/lib/client-types/code-host/validation.d.ts +51 -0
- package/lib/client-types/code-host.d.ts +2 -0
- package/lib/client-types/config/index.d.ts +2 -0
- package/lib/client-types/config/settings.d.ts +51 -0
- package/lib/client-types/config.d.ts +2 -0
- package/lib/client-types/notification/index.d.ts +2 -0
- package/lib/client-types/notification/model.d.ts +57 -0
- package/lib/client-types/notification/registry.d.ts +16 -0
- package/lib/client-types/notification.d.ts +2 -0
- package/lib/client-types/providers/generation-registry.d.ts +20 -0
- package/lib/client-types/remote.d.ts +65 -0
- package/lib/client-types/tracker/index.d.ts +2 -0
- package/lib/client-types/tracker/model.d.ts +222 -0
- package/lib/client-types/tracker/registry.d.ts +49 -0
- package/lib/client-types/tracker/validation.d.ts +60 -0
- package/lib/client-types/tracker.d.ts +2 -0
- package/lib/client-types/web/contract.d.ts +958 -0
- package/lib/client.js +7961 -0
- package/lib/client.js.map +1 -0
- package/lib/code-host/index.d.ts +2 -0
- package/lib/code-host/index.js +3 -0
- package/lib/code-host/index.js.map +1 -0
- package/lib/code-host/model.d.ts +118 -0
- package/lib/code-host/model.js +23 -0
- package/lib/code-host/model.js.map +1 -0
- package/lib/code-host/registry.d.ts +23 -0
- package/lib/code-host/registry.js +90 -0
- package/lib/code-host/registry.js.map +1 -0
- package/lib/code-host/validation.d.ts +51 -0
- package/lib/code-host/validation.js +30 -0
- package/lib/code-host/validation.js.map +1 -0
- package/lib/code-host.d.ts +2 -0
- package/lib/code-host.js +3 -0
- package/lib/code-host.js.map +1 -0
- package/lib/config/index.d.ts +2 -0
- package/lib/config/index.js +3 -0
- package/lib/config/index.js.map +1 -0
- package/lib/config/settings.d.ts +51 -0
- package/lib/config/settings.js +195 -0
- package/lib/config/settings.js.map +1 -0
- package/lib/config.d.ts +2 -0
- package/lib/config.js +3 -0
- package/lib/config.js.map +1 -0
- package/lib/delivery/index.d.ts +1 -0
- package/lib/delivery/index.js +2 -0
- package/lib/delivery/index.js.map +1 -0
- package/lib/delivery/service.d.ts +29 -0
- package/lib/delivery/service.js +140 -0
- package/lib/delivery/service.js.map +1 -0
- package/lib/delivery.d.ts +2 -0
- package/lib/delivery.js +3 -0
- package/lib/delivery.js.map +1 -0
- package/lib/dispatch/composition.d.ts +18 -0
- package/lib/dispatch/composition.js +109 -0
- package/lib/dispatch/composition.js.map +1 -0
- package/lib/dispatch/contract.d.ts +2 -0
- package/lib/dispatch/contract.js +2 -0
- package/lib/dispatch/contract.js.map +1 -0
- package/lib/dispatch/execute.d.ts +10 -0
- package/lib/dispatch/execute.js +138 -0
- package/lib/dispatch/execute.js.map +1 -0
- package/lib/dispatch/execution-state.d.ts +12 -0
- package/lib/dispatch/execution-state.js +24 -0
- package/lib/dispatch/execution-state.js.map +1 -0
- package/lib/dispatch/git.d.ts +5 -0
- package/lib/dispatch/git.js +95 -0
- package/lib/dispatch/git.js.map +1 -0
- package/lib/dispatch/index.d.ts +2 -0
- package/lib/dispatch/index.js +2 -0
- package/lib/dispatch/index.js.map +1 -0
- package/lib/dispatch/report.d.ts +11 -0
- package/lib/dispatch/report.js +141 -0
- package/lib/dispatch/report.js.map +1 -0
- package/lib/dispatch/resume.d.ts +17 -0
- package/lib/dispatch/resume.js +89 -0
- package/lib/dispatch/resume.js.map +1 -0
- package/lib/dispatch/service.d.ts +56 -0
- package/lib/dispatch/service.js +231 -0
- package/lib/dispatch/service.js.map +1 -0
- package/lib/dispatch/usage.d.ts +10 -0
- package/lib/dispatch/usage.js +47 -0
- package/lib/dispatch/usage.js.map +1 -0
- package/lib/dispatch.d.ts +2 -0
- package/lib/dispatch.js +3 -0
- package/lib/dispatch.js.map +1 -0
- package/lib/github-code-host.d.ts +1 -0
- package/lib/github-code-host.js +2 -0
- package/lib/github-code-host.js.map +1 -0
- package/lib/github-issues.d.ts +1 -0
- package/lib/github-issues.js +2 -0
- package/lib/github-issues.js.map +1 -0
- package/lib/index.d.ts +21 -0
- package/lib/index.js +48 -0
- package/lib/index.js.map +1 -0
- package/lib/ingress.d.ts +2 -0
- package/lib/ingress.js +3 -0
- package/lib/ingress.js.map +1 -0
- package/lib/jira.d.ts +1 -0
- package/lib/jira.js +2 -0
- package/lib/jira.js.map +1 -0
- package/lib/mcp/contracts.d.ts +21 -0
- package/lib/mcp/contracts.js +33 -0
- package/lib/mcp/contracts.js.map +1 -0
- package/lib/mcp/cursor.d.ts +10 -0
- package/lib/mcp/cursor.js +68 -0
- package/lib/mcp/cursor.js.map +1 -0
- package/lib/mcp/definition.d.ts +8 -0
- package/lib/mcp/definition.js +43 -0
- package/lib/mcp/definition.js.map +1 -0
- package/lib/mcp/index.d.ts +6 -0
- package/lib/mcp/index.js +7 -0
- package/lib/mcp/index.js.map +1 -0
- package/lib/mcp/json.d.ts +4 -0
- package/lib/mcp/json.js +20 -0
- package/lib/mcp/json.js.map +1 -0
- package/lib/mcp/mount.d.ts +17 -0
- package/lib/mcp/mount.js +79 -0
- package/lib/mcp/mount.js.map +1 -0
- package/lib/mcp/read-tools.d.ts +27 -0
- package/lib/mcp/read-tools.js +149 -0
- package/lib/mcp/read-tools.js.map +1 -0
- package/lib/notification/index.d.ts +2 -0
- package/lib/notification/index.js +3 -0
- package/lib/notification/index.js.map +1 -0
- package/lib/notification/model.d.ts +57 -0
- package/lib/notification/model.js +20 -0
- package/lib/notification/model.js.map +1 -0
- package/lib/notification/registry.d.ts +16 -0
- package/lib/notification/registry.js +67 -0
- package/lib/notification/registry.js.map +1 -0
- package/lib/notification.d.ts +2 -0
- package/lib/notification.js +3 -0
- package/lib/notification.js.map +1 -0
- package/lib/ntfy-notification.d.ts +1 -0
- package/lib/ntfy-notification.js +2 -0
- package/lib/ntfy-notification.js.map +1 -0
- package/lib/operations/cleanup-inspector.d.ts +16 -0
- package/lib/operations/cleanup-inspector.js +132 -0
- package/lib/operations/cleanup-inspector.js.map +1 -0
- package/lib/operations/cleanup.d.ts +25 -0
- package/lib/operations/cleanup.js +151 -0
- package/lib/operations/cleanup.js.map +1 -0
- package/lib/operations/disposition.d.ts +46 -0
- package/lib/operations/disposition.js +89 -0
- package/lib/operations/disposition.js.map +1 -0
- package/lib/operations/health.d.ts +6 -0
- package/lib/operations/health.js +41 -0
- package/lib/operations/health.js.map +1 -0
- package/lib/operations/index.d.ts +6 -0
- package/lib/operations/index.js +7 -0
- package/lib/operations/index.js.map +1 -0
- package/lib/operations/inspection.d.ts +35 -0
- package/lib/operations/inspection.js +183 -0
- package/lib/operations/inspection.js.map +1 -0
- package/lib/operations/model.d.ts +77 -0
- package/lib/operations/model.js +2 -0
- package/lib/operations/model.js.map +1 -0
- package/lib/operations/recovery.d.ts +11 -0
- package/lib/operations/recovery.js +101 -0
- package/lib/operations/recovery.js.map +1 -0
- package/lib/operations/retention.d.ts +28 -0
- package/lib/operations/retention.js +105 -0
- package/lib/operations/retention.js.map +1 -0
- package/lib/operations/runtime-owner.d.ts +54 -0
- package/lib/operations/runtime-owner.js +281 -0
- package/lib/operations/runtime-owner.js.map +1 -0
- package/lib/operations/service.d.ts +55 -0
- package/lib/operations/service.js +154 -0
- package/lib/operations/service.js.map +1 -0
- package/lib/operations/state.d.ts +79 -0
- package/lib/operations/state.js +51 -0
- package/lib/operations/state.js.map +1 -0
- package/lib/operations/storage-composition.d.ts +16 -0
- package/lib/operations/storage-composition.js +61 -0
- package/lib/operations/storage-composition.js.map +1 -0
- package/lib/operations/store.d.ts +16 -0
- package/lib/operations/store.js +84 -0
- package/lib/operations/store.js.map +1 -0
- package/lib/operations.d.ts +2 -0
- package/lib/operations.js +3 -0
- package/lib/operations.js.map +1 -0
- package/lib/providers/generation-registry.d.ts +20 -0
- package/lib/providers/generation-registry.js +72 -0
- package/lib/providers/generation-registry.js.map +1 -0
- package/lib/providers/github-code-host/contracts.d.ts +224 -0
- package/lib/providers/github-code-host/contracts.js +144 -0
- package/lib/providers/github-code-host/contracts.js.map +1 -0
- package/lib/providers/github-code-host/index.d.ts +2 -0
- package/lib/providers/github-code-host/index.js +2 -0
- package/lib/providers/github-code-host/index.js.map +1 -0
- package/lib/providers/github-code-host/provider.d.ts +5 -0
- package/lib/providers/github-code-host/provider.js +289 -0
- package/lib/providers/github-code-host/provider.js.map +1 -0
- package/lib/providers/github-code-host/schemas.d.ts +81 -0
- package/lib/providers/github-code-host/schemas.js +39 -0
- package/lib/providers/github-code-host/schemas.js.map +1 -0
- package/lib/providers/github-code-host/settings.d.ts +16 -0
- package/lib/providers/github-code-host/settings.js +65 -0
- package/lib/providers/github-code-host/settings.js.map +1 -0
- package/lib/providers/github-issues/contracts.d.ts +151 -0
- package/lib/providers/github-issues/contracts.js +141 -0
- package/lib/providers/github-issues/contracts.js.map +1 -0
- package/lib/providers/github-issues/index.d.ts +1 -0
- package/lib/providers/github-issues/index.js +2 -0
- package/lib/providers/github-issues/index.js.map +1 -0
- package/lib/providers/github-issues/ingress.d.ts +8 -0
- package/lib/providers/github-issues/ingress.js +80 -0
- package/lib/providers/github-issues/ingress.js.map +1 -0
- package/lib/providers/github-issues/normalization.d.ts +11 -0
- package/lib/providers/github-issues/normalization.js +115 -0
- package/lib/providers/github-issues/normalization.js.map +1 -0
- package/lib/providers/github-issues/provider.d.ts +6 -0
- package/lib/providers/github-issues/provider.js +235 -0
- package/lib/providers/github-issues/provider.js.map +1 -0
- package/lib/providers/github-issues/schemas.d.ts +123 -0
- package/lib/providers/github-issues/schemas.js +58 -0
- package/lib/providers/github-issues/schemas.js.map +1 -0
- package/lib/providers/github-issues/settings.d.ts +27 -0
- package/lib/providers/github-issues/settings.js +154 -0
- package/lib/providers/github-issues/settings.js.map +1 -0
- package/lib/providers/jira/contracts.d.ts +193 -0
- package/lib/providers/jira/contracts.js +133 -0
- package/lib/providers/jira/contracts.js.map +1 -0
- package/lib/providers/jira/index.d.ts +1 -0
- package/lib/providers/jira/index.js +2 -0
- package/lib/providers/jira/index.js.map +1 -0
- package/lib/providers/jira/ingress.d.ts +4 -0
- package/lib/providers/jira/ingress.js +60 -0
- package/lib/providers/jira/ingress.js.map +1 -0
- package/lib/providers/jira/normalization.d.ts +8 -0
- package/lib/providers/jira/normalization.js +121 -0
- package/lib/providers/jira/normalization.js.map +1 -0
- package/lib/providers/jira/provider.d.ts +6 -0
- package/lib/providers/jira/provider.js +317 -0
- package/lib/providers/jira/provider.js.map +1 -0
- package/lib/providers/jira/schemas.d.ts +134 -0
- package/lib/providers/jira/schemas.js +76 -0
- package/lib/providers/jira/schemas.js.map +1 -0
- package/lib/providers/jira/settings.d.ts +32 -0
- package/lib/providers/jira/settings.js +163 -0
- package/lib/providers/jira/settings.js.map +1 -0
- package/lib/providers/notification-http.d.ts +13 -0
- package/lib/providers/notification-http.js +136 -0
- package/lib/providers/notification-http.js.map +1 -0
- package/lib/providers/ntfy-notification/index.d.ts +2 -0
- package/lib/providers/ntfy-notification/index.js +2 -0
- package/lib/providers/ntfy-notification/index.js.map +1 -0
- package/lib/providers/ntfy-notification/provider.d.ts +4 -0
- package/lib/providers/ntfy-notification/provider.js +89 -0
- package/lib/providers/ntfy-notification/provider.js.map +1 -0
- package/lib/providers/ntfy-notification/settings.d.ts +12 -0
- package/lib/providers/ntfy-notification/settings.js +34 -0
- package/lib/providers/ntfy-notification/settings.js.map +1 -0
- package/lib/providers/webhook-notification/index.d.ts +2 -0
- package/lib/providers/webhook-notification/index.js +2 -0
- package/lib/providers/webhook-notification/index.js.map +1 -0
- package/lib/providers/webhook-notification/provider.d.ts +4 -0
- package/lib/providers/webhook-notification/provider.js +57 -0
- package/lib/providers/webhook-notification/provider.js.map +1 -0
- package/lib/providers/webhook-notification/settings.d.ts +11 -0
- package/lib/providers/webhook-notification/settings.js +31 -0
- package/lib/providers/webhook-notification/settings.js.map +1 -0
- package/lib/publication/git.d.ts +7 -0
- package/lib/publication/git.js +154 -0
- package/lib/publication/git.js.map +1 -0
- package/lib/publication/index.d.ts +1 -0
- package/lib/publication/index.js +2 -0
- package/lib/publication/index.js.map +1 -0
- package/lib/publication/service.d.ts +27 -0
- package/lib/publication/service.js +166 -0
- package/lib/publication/service.js.map +1 -0
- package/lib/publication.d.ts +2 -0
- package/lib/publication.js +3 -0
- package/lib/publication.js.map +1 -0
- package/lib/reconciliation/index.d.ts +3 -0
- package/lib/reconciliation/index.js +4 -0
- package/lib/reconciliation/index.js.map +1 -0
- package/lib/reconciliation/ingress.d.ts +21 -0
- package/lib/reconciliation/ingress.js +168 -0
- package/lib/reconciliation/ingress.js.map +1 -0
- package/lib/reconciliation/service.d.ts +75 -0
- package/lib/reconciliation/service.js +228 -0
- package/lib/reconciliation/service.js.map +1 -0
- package/lib/reconciliation.d.ts +2 -0
- package/lib/reconciliation.js +3 -0
- package/lib/reconciliation.js.map +1 -0
- package/lib/remote.d.ts +65 -0
- package/lib/remote.js +135 -0
- package/lib/remote.js.map +1 -0
- package/lib/tracker/index.d.ts +2 -0
- package/lib/tracker/index.js +3 -0
- package/lib/tracker/index.js.map +1 -0
- package/lib/tracker/model.d.ts +222 -0
- package/lib/tracker/model.js +66 -0
- package/lib/tracker/model.js.map +1 -0
- package/lib/tracker/registry.d.ts +49 -0
- package/lib/tracker/registry.js +213 -0
- package/lib/tracker/registry.js.map +1 -0
- package/lib/tracker/validation.d.ts +60 -0
- package/lib/tracker/validation.js +52 -0
- package/lib/tracker/validation.js.map +1 -0
- package/lib/tracker.d.ts +2 -0
- package/lib/tracker.js +3 -0
- package/lib/tracker.js.map +1 -0
- package/lib/typert.d.ts +1 -0
- package/lib/typert.js +2 -0
- package/lib/typert.js.map +1 -0
- package/lib/web/commands.d.ts +18 -0
- package/lib/web/commands.js +231 -0
- package/lib/web/commands.js.map +1 -0
- package/lib/web/contract.d.ts +958 -0
- package/lib/web/contract.js +230 -0
- package/lib/web/contract.js.map +1 -0
- package/lib/web/contributions.d.ts +41 -0
- package/lib/web/contributions.js +61 -0
- package/lib/web/contributions.js.map +1 -0
- package/lib/web/integrations.d.ts +13 -0
- package/lib/web/integrations.js +95 -0
- package/lib/web/integrations.js.map +1 -0
- package/lib/web/projection.d.ts +10 -0
- package/lib/web/projection.js +192 -0
- package/lib/web/projection.js.map +1 -0
- package/lib/web/service.d.ts +31 -0
- package/lib/web/service.js +141 -0
- package/lib/web/service.js.map +1 -0
- package/lib/web.d.ts +5 -0
- package/lib/web.js +6 -0
- package/lib/web.js.map +1 -0
- package/lib/webhook-notification.d.ts +1 -0
- package/lib/webhook-notification.js +2 -0
- package/lib/webhook-notification.js.map +1 -0
- package/lib/workflow/index.d.ts +1 -0
- package/lib/workflow/index.js +2 -0
- package/lib/workflow/index.js.map +1 -0
- package/lib/workflow/service.d.ts +31 -0
- package/lib/workflow/service.js +220 -0
- package/lib/workflow/service.js.map +1 -0
- package/lib/workflow.d.ts +2 -0
- package/lib/workflow.js +3 -0
- package/lib/workflow.js.map +1 -0
- package/package.json +276 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { access, lstat, opendir, realpath } from 'node:fs/promises';
|
|
3
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { gitCommand } from '../dispatch/git.js';
|
|
5
|
+
export function cleanupRejections(input) {
|
|
6
|
+
const reasons = [];
|
|
7
|
+
switch (input.run.state) {
|
|
8
|
+
case 'queued':
|
|
9
|
+
case 'implementing':
|
|
10
|
+
case 'pausing':
|
|
11
|
+
reasons.push('run-active');
|
|
12
|
+
break;
|
|
13
|
+
case 'paused':
|
|
14
|
+
reasons.push('run-paused');
|
|
15
|
+
break;
|
|
16
|
+
case 'publishing':
|
|
17
|
+
reasons.push('run-publishing');
|
|
18
|
+
break;
|
|
19
|
+
case 'blocked':
|
|
20
|
+
reasons.push('run-blocked');
|
|
21
|
+
break;
|
|
22
|
+
case 'failed':
|
|
23
|
+
reasons.push('run-failed');
|
|
24
|
+
break;
|
|
25
|
+
case 'completed':
|
|
26
|
+
if (hasUnresolvedExternalIntent(input.run, true)) {
|
|
27
|
+
reasons.push('external-intent-unresolved');
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
case 'cancelled':
|
|
31
|
+
if (hasUnresolvedExternalIntent(input.run, false))
|
|
32
|
+
reasons.push('external-intent-unresolved');
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
input.run;
|
|
36
|
+
}
|
|
37
|
+
if (input.run.execution.recovery !== undefined)
|
|
38
|
+
reasons.push('recovery-required');
|
|
39
|
+
if (!input.ownership)
|
|
40
|
+
reasons.push(input.missing ? 'worktree-missing' : 'ownership-unproven');
|
|
41
|
+
if (input.dirtyFiles.length > 0)
|
|
42
|
+
reasons.push('dirty-files');
|
|
43
|
+
if (input.untrackedFiles.length > 0)
|
|
44
|
+
reasons.push('untracked-files');
|
|
45
|
+
if (input.unpushedCommits === 'unknown' || input.unpushedCommits > 0)
|
|
46
|
+
reasons.push('unpushed-commits');
|
|
47
|
+
if (input.disposition.state === 'open')
|
|
48
|
+
reasons.push('pr-open');
|
|
49
|
+
else if (input.disposition.state === 'unknown')
|
|
50
|
+
reasons.push('pr-unknown');
|
|
51
|
+
else if (input.disposition.state === 'closed-unmerged')
|
|
52
|
+
reasons.push('pr-closed-unmerged');
|
|
53
|
+
if (input.retentionEligibleAt === undefined || Date.parse(input.retentionEligibleAt) > input.now) {
|
|
54
|
+
reasons.push('retention-not-met');
|
|
55
|
+
}
|
|
56
|
+
return [...new Set(reasons)];
|
|
57
|
+
}
|
|
58
|
+
function hasUnresolvedExternalIntent(run, publicationRequired) {
|
|
59
|
+
const publication = 'publication' in run ? run.publication : undefined;
|
|
60
|
+
return ((publicationRequired && publication === undefined) ||
|
|
61
|
+
(publication !== undefined && (publication.status !== 'succeeded' || publication.receipt === undefined)) ||
|
|
62
|
+
run.deliveries.some((delivery) => ['pending', 'in-flight', 'uncertain', 'retryable-failure', 'exhausted'].includes(delivery.status)));
|
|
63
|
+
}
|
|
64
|
+
export async function inspectOwnership(ctx, run, managedRoot) {
|
|
65
|
+
const expected = resolve(managedRoot, run.runId);
|
|
66
|
+
if (resolve(run.execution.worktreePath) !== expected)
|
|
67
|
+
throw new Error('recorded path is not the configured run-owned path');
|
|
68
|
+
const [root, worktree, repository, observedRoot, common, targetCommon] = await Promise.all([
|
|
69
|
+
canonicalExistingPath(managedRoot),
|
|
70
|
+
canonicalExistingPath(run.execution.worktreePath),
|
|
71
|
+
canonicalExistingPath(run.execution.targetRepository),
|
|
72
|
+
gitCommand(ctx.subprocess, run.execution.worktreePath, ['rev-parse', '--show-toplevel']),
|
|
73
|
+
gitCommand(ctx.subprocess, run.execution.worktreePath, ['rev-parse', '--path-format=absolute', '--git-common-dir']),
|
|
74
|
+
gitCommand(ctx.subprocess, run.execution.targetRepository, [
|
|
75
|
+
'rev-parse',
|
|
76
|
+
'--path-format=absolute',
|
|
77
|
+
'--git-common-dir',
|
|
78
|
+
]),
|
|
79
|
+
]);
|
|
80
|
+
if (!inside(root, worktree) || resolve(root, run.runId) !== worktree)
|
|
81
|
+
throw new Error('worktree escaped its managed root');
|
|
82
|
+
if ((await canonicalExistingPath(observedRoot.trim())) !== worktree)
|
|
83
|
+
throw new Error('Git top level differs from recorded path');
|
|
84
|
+
if ((await canonicalExistingPath(common.trim())) !== (await canonicalExistingPath(targetCommon.trim()))) {
|
|
85
|
+
throw new Error('worktree does not belong to the recorded target repository');
|
|
86
|
+
}
|
|
87
|
+
const branch = (await gitCommand(ctx.subprocess, worktree, ['rev-parse', '--abbrev-ref', 'HEAD'])).trim();
|
|
88
|
+
if (branch !== run.execution.branch)
|
|
89
|
+
throw new Error('worktree branch differs from durable ownership');
|
|
90
|
+
const registered = await listWorktrees(ctx, repository);
|
|
91
|
+
if (!registered.some((entry) => resolve(entry.path) === worktree))
|
|
92
|
+
throw new Error('Git does not register the worktree');
|
|
93
|
+
}
|
|
94
|
+
export async function listWorktrees(ctx, repository) {
|
|
95
|
+
if (repository === '')
|
|
96
|
+
return [];
|
|
97
|
+
const output = await gitCommand(ctx.subprocess, repository, ['worktree', 'list', '--porcelain', '-z']);
|
|
98
|
+
const result = [];
|
|
99
|
+
let current;
|
|
100
|
+
for (const field of output.split('\0')) {
|
|
101
|
+
if (field === '') {
|
|
102
|
+
if (current !== undefined)
|
|
103
|
+
result.push(current);
|
|
104
|
+
current = undefined;
|
|
105
|
+
}
|
|
106
|
+
else if (field.startsWith('worktree ')) {
|
|
107
|
+
if (current !== undefined)
|
|
108
|
+
result.push(current);
|
|
109
|
+
current = { path: field.slice('worktree '.length) };
|
|
110
|
+
}
|
|
111
|
+
else if (field.startsWith('branch ') && current !== undefined) {
|
|
112
|
+
current.branch = field.slice('branch refs/heads/'.length);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (current !== undefined)
|
|
116
|
+
result.push(current);
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
export function parseStatus(status) {
|
|
120
|
+
const dirtyFiles = [];
|
|
121
|
+
const untrackedFiles = [];
|
|
122
|
+
for (const entry of status.split('\0')) {
|
|
123
|
+
if (entry.length < 4 || entry[2] !== ' ')
|
|
124
|
+
continue;
|
|
125
|
+
const path = entry.slice(3);
|
|
126
|
+
if (entry.startsWith('?? '))
|
|
127
|
+
untrackedFiles.push(path);
|
|
128
|
+
else
|
|
129
|
+
dirtyFiles.push(path);
|
|
130
|
+
}
|
|
131
|
+
return { dirtyFiles, untrackedFiles };
|
|
132
|
+
}
|
|
133
|
+
export async function directoryBytes(path) {
|
|
134
|
+
const metadata = await lstat(path);
|
|
135
|
+
if (!metadata.isDirectory())
|
|
136
|
+
return metadata.size;
|
|
137
|
+
let total = metadata.size;
|
|
138
|
+
const directory = await opendir(path);
|
|
139
|
+
for await (const entry of directory) {
|
|
140
|
+
const child = join(path, entry.name);
|
|
141
|
+
const childMetadata = await lstat(child);
|
|
142
|
+
total +=
|
|
143
|
+
childMetadata.isDirectory() && !childMetadata.isSymbolicLink() ? await directoryBytes(child) : childMetadata.size;
|
|
144
|
+
}
|
|
145
|
+
return total;
|
|
146
|
+
}
|
|
147
|
+
export function allocatedRun(snapshot, runId) {
|
|
148
|
+
const run = snapshot.runs.find((candidate) => candidate.runId === runId);
|
|
149
|
+
if (run === undefined)
|
|
150
|
+
throw new Error(`run "${runId}" does not exist`);
|
|
151
|
+
if (!hasExecution(run))
|
|
152
|
+
throw new Error(`run "${runId}" has no allocated worktree`);
|
|
153
|
+
return run;
|
|
154
|
+
}
|
|
155
|
+
export function hasExecution(run) {
|
|
156
|
+
return 'execution' in run;
|
|
157
|
+
}
|
|
158
|
+
export function fingerprint(value) {
|
|
159
|
+
return createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
|
160
|
+
}
|
|
161
|
+
export async function canonicalExistingPath(path) {
|
|
162
|
+
return resolve(await realpath(path));
|
|
163
|
+
}
|
|
164
|
+
export function inside(root, candidate) {
|
|
165
|
+
const child = relative(root, candidate);
|
|
166
|
+
return child !== '' && child !== '..' && !child.startsWith(`..${sep}`) && !child.startsWith(sep);
|
|
167
|
+
}
|
|
168
|
+
export async function pathExists(path) {
|
|
169
|
+
try {
|
|
170
|
+
await access(path);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error.code === 'ENOENT')
|
|
175
|
+
return false;
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
export function boundedError(error) {
|
|
180
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
181
|
+
return message.length <= 4096 ? message : message.slice(0, 4096);
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=inspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspection.js","sourceRoot":"","sources":["../../src/operations/inspection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { AdmissionSnapshot, RunId } from '../admission.js';
|
|
3
|
+
import type { PullRequestDisposition } from './disposition.js';
|
|
4
|
+
export type CleanupRejection = 'run-active' | 'run-paused' | 'run-publishing' | 'run-blocked' | 'run-failed' | 'external-intent-unresolved' | 'recovery-required' | 'ownership-unproven' | 'worktree-missing' | 'dirty-files' | 'untracked-files' | 'unpushed-commits' | 'pr-open' | 'pr-unknown' | 'pr-closed-unmerged' | 'retention-not-met';
|
|
5
|
+
export interface CleanupPreview {
|
|
6
|
+
readonly previewId: string;
|
|
7
|
+
readonly runId: RunId;
|
|
8
|
+
readonly admissionRevision: number;
|
|
9
|
+
readonly worktreePath: string;
|
|
10
|
+
readonly branch: string;
|
|
11
|
+
readonly head?: string;
|
|
12
|
+
readonly dirtyFiles: readonly string[];
|
|
13
|
+
readonly untrackedFiles: readonly string[];
|
|
14
|
+
readonly unpushedCommits: number | 'unknown';
|
|
15
|
+
readonly disposition: PullRequestDisposition;
|
|
16
|
+
readonly retentionReference?: string;
|
|
17
|
+
readonly retentionEligibleAt?: string;
|
|
18
|
+
readonly removableBytes: number | 'unknown';
|
|
19
|
+
readonly retainedData: readonly ['run', 'session', 'audit'];
|
|
20
|
+
readonly eligible: boolean;
|
|
21
|
+
readonly rejections: readonly CleanupRejection[];
|
|
22
|
+
}
|
|
23
|
+
export interface RetainedWorktreeFact {
|
|
24
|
+
readonly runId: RunId;
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly state: 'managed' | 'missing' | 'unsafe';
|
|
27
|
+
readonly detail?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface OrphanWorktreeFact {
|
|
30
|
+
readonly path: string;
|
|
31
|
+
readonly branch?: string;
|
|
32
|
+
readonly state: 'orphan-reconciliation-required';
|
|
33
|
+
}
|
|
34
|
+
export interface MaintenanceAudit {
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly operationId?: string | undefined;
|
|
37
|
+
readonly at: string;
|
|
38
|
+
readonly kind: 'merge-observed' | 'cleanup-started' | 'cleanup-removed' | 'cleanup-rejected' | 'cleanup-recovered';
|
|
39
|
+
readonly runId: RunId;
|
|
40
|
+
readonly worktreePath: string;
|
|
41
|
+
readonly outcome?: 'completed' | 'retry-required' | undefined;
|
|
42
|
+
readonly detail: string;
|
|
43
|
+
}
|
|
44
|
+
export interface RecoveryParticipant {
|
|
45
|
+
/** Reconcile this participant's durable unfinished effects; nonzero pending work keeps dispatch fenced. */
|
|
46
|
+
reconcile(signal: AbortSignal): Promise<RecoveryParticipantFact>;
|
|
47
|
+
}
|
|
48
|
+
export interface RecoveryParticipantFact {
|
|
49
|
+
readonly pending: number;
|
|
50
|
+
readonly failure?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface OperationsHealth {
|
|
53
|
+
readonly process: {
|
|
54
|
+
status: 'alive';
|
|
55
|
+
owner: ReturnType<Context['runtimeOwner']['snapshot']>;
|
|
56
|
+
};
|
|
57
|
+
readonly persistence: {
|
|
58
|
+
status: 'ready' | 'unconfigured' | 'failed';
|
|
59
|
+
failure?: string;
|
|
60
|
+
};
|
|
61
|
+
readonly recovery: {
|
|
62
|
+
status: 'complete' | 'required' | 'failed';
|
|
63
|
+
runIds: readonly RunId[];
|
|
64
|
+
pendingCleanup: boolean;
|
|
65
|
+
participants: Readonly<Record<string, RecoveryParticipantFact>>;
|
|
66
|
+
};
|
|
67
|
+
readonly integrations: {
|
|
68
|
+
codeHost: {
|
|
69
|
+
status: 'available' | 'unavailable' | 'failed';
|
|
70
|
+
failure?: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
readonly admission: {
|
|
74
|
+
status: 'permitted' | 'paused' | 'blocked';
|
|
75
|
+
mode: AdmissionSnapshot['scheduler']['mode'];
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/operations/model.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RecoveryParticipant, RecoveryParticipantFact } from './model.js';
|
|
2
|
+
export declare const REQUIRED_RECOVERY_PARTICIPANTS: readonly ['publication-delivery'];
|
|
3
|
+
export declare class RecoveryParticipants {
|
|
4
|
+
private readonly generations;
|
|
5
|
+
private readonly facts;
|
|
6
|
+
register(id: string, participant: RecoveryParticipant): () => Promise<void>;
|
|
7
|
+
reconcileAll(): Promise<void>;
|
|
8
|
+
snapshot(): Readonly<Record<string, RecoveryParticipantFact>>;
|
|
9
|
+
dispose(): Promise<void>;
|
|
10
|
+
private reconcile;
|
|
11
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export const REQUIRED_RECOVERY_PARTICIPANTS = ['publication-delivery'];
|
|
2
|
+
export class RecoveryParticipants {
|
|
3
|
+
generations = new Map();
|
|
4
|
+
facts = new Map();
|
|
5
|
+
register(id, participant) {
|
|
6
|
+
if (!/^[a-z][a-z0-9-]{0,63}$/.test(id))
|
|
7
|
+
throw new TypeError(`invalid recovery participant id "${id}"`);
|
|
8
|
+
if (this.generations.has(id))
|
|
9
|
+
throw new Error(`recovery participant "${id}" is already registered`);
|
|
10
|
+
const generation = {
|
|
11
|
+
participant,
|
|
12
|
+
controller: new AbortController(),
|
|
13
|
+
active: new Set(),
|
|
14
|
+
accepting: true,
|
|
15
|
+
};
|
|
16
|
+
this.generations.set(id, generation);
|
|
17
|
+
this.facts.set(id, { pending: 1 });
|
|
18
|
+
return async () => {
|
|
19
|
+
if (this.generations.get(id) !== generation)
|
|
20
|
+
return;
|
|
21
|
+
generation.accepting = false;
|
|
22
|
+
generation.controller.abort(new Error(`recovery participant "${id}" was withdrawn`));
|
|
23
|
+
await Promise.allSettled(generation.active);
|
|
24
|
+
if (this.generations.get(id) === generation) {
|
|
25
|
+
this.generations.delete(id);
|
|
26
|
+
this.facts.delete(id);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async reconcileAll() {
|
|
31
|
+
for (const id of REQUIRED_RECOVERY_PARTICIPANTS) {
|
|
32
|
+
if (!this.generations.get(id)?.accepting) {
|
|
33
|
+
throw new Error(`required recovery participant "${id}" is unavailable`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const [id, generation] of [...this.generations])
|
|
37
|
+
await this.reconcile(id, generation);
|
|
38
|
+
}
|
|
39
|
+
snapshot() {
|
|
40
|
+
const facts = new Map(this.facts);
|
|
41
|
+
for (const id of REQUIRED_RECOVERY_PARTICIPANTS) {
|
|
42
|
+
if (!this.generations.get(id)?.accepting) {
|
|
43
|
+
facts.set(id, { pending: 1, failure: `required recovery participant "${id}" is unavailable` });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return Object.fromEntries(facts);
|
|
47
|
+
}
|
|
48
|
+
async dispose() {
|
|
49
|
+
const generations = [...this.generations.entries()];
|
|
50
|
+
this.generations.clear();
|
|
51
|
+
for (const [id, generation] of generations) {
|
|
52
|
+
generation.accepting = false;
|
|
53
|
+
generation.controller.abort(new Error(`recovery participant "${id}" registry was disposed`));
|
|
54
|
+
}
|
|
55
|
+
await Promise.allSettled(generations.flatMap(([, generation]) => [...generation.active]));
|
|
56
|
+
this.facts.clear();
|
|
57
|
+
}
|
|
58
|
+
async reconcile(id, generation) {
|
|
59
|
+
const operation = Promise.resolve()
|
|
60
|
+
.then(() => generation.participant.reconcile(generation.controller.signal))
|
|
61
|
+
.then(validateRecoveryFact);
|
|
62
|
+
generation.active.add(operation);
|
|
63
|
+
try {
|
|
64
|
+
const fact = await operation;
|
|
65
|
+
if (!generation.accepting || generation.controller.signal.aborted)
|
|
66
|
+
throw generation.controller.signal.reason;
|
|
67
|
+
if (this.generations.get(id) !== generation) {
|
|
68
|
+
throw new Error(`recovery participant "${id}" changed during reconciliation`);
|
|
69
|
+
}
|
|
70
|
+
this.facts.set(id, fact);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (this.generations.get(id) !== generation || !generation.accepting)
|
|
74
|
+
throw error;
|
|
75
|
+
this.facts.set(id, { pending: 1, failure: boundedError(error) });
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
generation.active.delete(operation);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function validateRecoveryFact(value) {
|
|
83
|
+
if (typeof value !== 'object' || value === null || !('pending' in value)) {
|
|
84
|
+
throw new TypeError('recovery participant returned an invalid result');
|
|
85
|
+
}
|
|
86
|
+
const fact = value;
|
|
87
|
+
if (!Number.isSafeInteger(fact.pending) || fact.pending < 0) {
|
|
88
|
+
throw new TypeError('recovery participant returned an invalid pending count');
|
|
89
|
+
}
|
|
90
|
+
if (fact.failure !== undefined &&
|
|
91
|
+
(typeof fact.failure !== 'string' || fact.failure.length === 0 || fact.failure.length > 4096)) {
|
|
92
|
+
throw new TypeError('recovery participant returned an invalid failure');
|
|
93
|
+
}
|
|
94
|
+
const pending = fact.pending;
|
|
95
|
+
return fact.failure === undefined ? { pending } : { pending, failure: fact.failure };
|
|
96
|
+
}
|
|
97
|
+
function boundedError(error) {
|
|
98
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
99
|
+
return message.length <= 4096 ? message : message.slice(0, 4096);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/operations/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { CleanupOperations } from './cleanup.js';
|
|
3
|
+
import type { MaintenanceAudit, OrphanWorktreeFact, RetainedWorktreeFact } from './model.js';
|
|
4
|
+
import type { MaintenanceStateStore } from './store.js';
|
|
5
|
+
export declare class RetentionMaintenance {
|
|
6
|
+
private readonly ctx;
|
|
7
|
+
private readonly store;
|
|
8
|
+
private readonly cleanup;
|
|
9
|
+
private readonly ensureReady;
|
|
10
|
+
private timer;
|
|
11
|
+
private attempt;
|
|
12
|
+
private stopping;
|
|
13
|
+
constructor(ctx: Context, store: MaintenanceStateStore, cleanup: CleanupOperations, ensureReady: () => Promise<void>);
|
|
14
|
+
run(): Promise<{
|
|
15
|
+
inspected: number;
|
|
16
|
+
removed: number;
|
|
17
|
+
attention: number;
|
|
18
|
+
}>;
|
|
19
|
+
inspectWorktrees(): Promise<{
|
|
20
|
+
retained: readonly RetainedWorktreeFact[];
|
|
21
|
+
orphans: readonly OrphanWorktreeFact[];
|
|
22
|
+
audit: readonly MaintenanceAudit[];
|
|
23
|
+
}>;
|
|
24
|
+
schedule(delay?: number): void;
|
|
25
|
+
reschedule(): void;
|
|
26
|
+
stop(): Promise<void>;
|
|
27
|
+
private clearTimer;
|
|
28
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { boundedError, canonicalExistingPath, hasExecution, inside, inspectOwnership, listWorktrees, pathExists, } from './inspection.js';
|
|
3
|
+
export class RetentionMaintenance {
|
|
4
|
+
ctx;
|
|
5
|
+
store;
|
|
6
|
+
cleanup;
|
|
7
|
+
ensureReady;
|
|
8
|
+
timer;
|
|
9
|
+
attempt;
|
|
10
|
+
stopping = false;
|
|
11
|
+
constructor(ctx, store, cleanup, ensureReady) {
|
|
12
|
+
this.ctx = ctx;
|
|
13
|
+
this.store = store;
|
|
14
|
+
this.cleanup = cleanup;
|
|
15
|
+
this.ensureReady = ensureReady;
|
|
16
|
+
}
|
|
17
|
+
async run() {
|
|
18
|
+
await this.ensureReady();
|
|
19
|
+
const runs = this.ctx.admission.snapshot().runs.filter(hasExecution);
|
|
20
|
+
let removed = 0;
|
|
21
|
+
let attention = 0;
|
|
22
|
+
for (const run of runs) {
|
|
23
|
+
const preview = await this.cleanup.preview(run.runId);
|
|
24
|
+
if (!preview.eligible) {
|
|
25
|
+
this.cleanup.discardPreview(preview.previewId);
|
|
26
|
+
attention += 1;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
await this.cleanup.remove(preview.previewId);
|
|
30
|
+
removed += 1;
|
|
31
|
+
}
|
|
32
|
+
return { inspected: runs.length, removed, attention };
|
|
33
|
+
}
|
|
34
|
+
async inspectWorktrees() {
|
|
35
|
+
await this.ensureReady();
|
|
36
|
+
const settings = this.ctx.autopilotConfig.get();
|
|
37
|
+
const allocated = this.ctx.admission.snapshot().runs.filter(hasExecution);
|
|
38
|
+
const retained = await Promise.all(allocated.map(async (run) => {
|
|
39
|
+
try {
|
|
40
|
+
await inspectOwnership(this.ctx, run, settings.managedWorktreeRoot);
|
|
41
|
+
return { runId: run.runId, path: run.execution.worktreePath, state: 'managed' };
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return {
|
|
45
|
+
runId: run.runId,
|
|
46
|
+
path: run.execution.worktreePath,
|
|
47
|
+
state: (await pathExists(run.execution.worktreePath)) ? 'unsafe' : 'missing',
|
|
48
|
+
detail: boundedError(error),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
const registered = await listWorktrees(this.ctx, settings.targetRepository);
|
|
53
|
+
const managedRoot = await canonicalExistingPath(settings.managedWorktreeRoot);
|
|
54
|
+
const ownedPaths = new Set(await Promise.all(allocated.map(async (run) => {
|
|
55
|
+
try {
|
|
56
|
+
return await canonicalExistingPath(run.execution.worktreePath);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return resolve(run.execution.worktreePath);
|
|
60
|
+
}
|
|
61
|
+
})));
|
|
62
|
+
const orphans = registered
|
|
63
|
+
.filter((worktree) => inside(managedRoot, resolve(worktree.path)) && !ownedPaths.has(resolve(worktree.path)))
|
|
64
|
+
.map((worktree) => ({
|
|
65
|
+
path: worktree.path,
|
|
66
|
+
...(worktree.branch === undefined ? {} : { branch: worktree.branch }),
|
|
67
|
+
state: 'orphan-reconciliation-required',
|
|
68
|
+
}));
|
|
69
|
+
return { retained, orphans, audit: structuredClone(this.store.current().audit) };
|
|
70
|
+
}
|
|
71
|
+
schedule(delay) {
|
|
72
|
+
const settings = this.ctx.autopilotConfig.get();
|
|
73
|
+
if (this.stopping || this.timer !== undefined || !settings.autoCleanupEnabled) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.timer = setTimeout(() => {
|
|
77
|
+
this.timer = undefined;
|
|
78
|
+
const attempt = this.run()
|
|
79
|
+
.then(() => undefined)
|
|
80
|
+
.catch(() => this.ctx.logger.warn('autopilot retention maintenance failed'))
|
|
81
|
+
.finally(() => {
|
|
82
|
+
if (this.attempt === attempt)
|
|
83
|
+
this.attempt = undefined;
|
|
84
|
+
this.schedule();
|
|
85
|
+
});
|
|
86
|
+
this.attempt = attempt;
|
|
87
|
+
}, delay ?? settings.reconcileIntervalSeconds * 1000);
|
|
88
|
+
}
|
|
89
|
+
reschedule() {
|
|
90
|
+
this.clearTimer();
|
|
91
|
+
if (this.attempt === undefined)
|
|
92
|
+
this.schedule();
|
|
93
|
+
}
|
|
94
|
+
async stop() {
|
|
95
|
+
this.stopping = true;
|
|
96
|
+
this.clearTimer();
|
|
97
|
+
await Promise.all([this.attempt, this.cleanup.activeAttempt()]);
|
|
98
|
+
}
|
|
99
|
+
clearTimer() {
|
|
100
|
+
if (this.timer !== undefined)
|
|
101
|
+
clearTimeout(this.timer);
|
|
102
|
+
this.timer = undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/operations/retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Context, Service } from '@deepseek-ai/cordis';
|
|
2
|
+
import { type RuntimeOwnerOptions } from './storage-composition.js';
|
|
3
|
+
interface OwnerRecord {
|
|
4
|
+
readonly version: 1;
|
|
5
|
+
readonly pid: number;
|
|
6
|
+
readonly nonce: string;
|
|
7
|
+
readonly acquiredAt: string;
|
|
8
|
+
readonly bootId?: string;
|
|
9
|
+
readonly processStart?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class RuntimeStoreOwnedError extends Error {
|
|
12
|
+
readonly owner: Pick<OwnerRecord, 'pid' | 'acquiredAt'> | undefined;
|
|
13
|
+
constructor(owner: Pick<OwnerRecord, 'pid' | 'acquiredAt'> | undefined);
|
|
14
|
+
}
|
|
15
|
+
export declare class RuntimeStoreConfigurationError extends Error {
|
|
16
|
+
constructor(configured: string, authoritative: string);
|
|
17
|
+
}
|
|
18
|
+
declare module '@deepseek-ai/cordis' {
|
|
19
|
+
interface Context {
|
|
20
|
+
runtimeOwner: RuntimeOwner;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Hold the one-VPS fence for the authoritative DSH storage medium before Autopilot opens durable state. */
|
|
24
|
+
export declare class RuntimeOwner extends Service {
|
|
25
|
+
private readonly options;
|
|
26
|
+
static readonly inject: string[];
|
|
27
|
+
private owned;
|
|
28
|
+
private holders;
|
|
29
|
+
private closing;
|
|
30
|
+
private waitForHolders;
|
|
31
|
+
constructor(ctx: Context, options?: RuntimeOwnerOptions);
|
|
32
|
+
[Service.init](): AsyncGenerator<() => Promise<void>, void, void>;
|
|
33
|
+
/**
|
|
34
|
+
* Acquire the authoritative DSH storage-medium fence, or prove this service already owns that exact canonical
|
|
35
|
+
* medium. An optional runtimeStorePath is only a configuration assertion. Unprovable or changed media,
|
|
36
|
+
* unsafe/incomplete targets and a live owner reject; stale local-process ownership is reclaimed atomically.
|
|
37
|
+
*/
|
|
38
|
+
ensureOwned(): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Keep the owner fence alive through a dependent service's complete asynchronous shutdown. Rejects during owner
|
|
41
|
+
* shutdown; the returned idempotent release callback performs no I/O.
|
|
42
|
+
*/
|
|
43
|
+
hold(): () => void;
|
|
44
|
+
/** Return detached owner/fence facts without touching the filesystem; available until this service is disposed. */
|
|
45
|
+
snapshot(): {
|
|
46
|
+
status: 'held';
|
|
47
|
+
storePath: string;
|
|
48
|
+
acquiredAt: string;
|
|
49
|
+
} | {
|
|
50
|
+
status: 'unconfigured';
|
|
51
|
+
};
|
|
52
|
+
private release;
|
|
53
|
+
}
|
|
54
|
+
export default RuntimeOwner;
|