@timurproko/a1 0.2.7-dev.1245 → 0.2.7-dev.1252
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 +11 -36
- package/bin/cli.js +2 -17
- package/bin/ui.js +7 -48
- package/dist/app/session-shell/exit-notice.d.ts +2 -2
- package/dist/app/session-shell/exit-notice.js +10 -10
- package/dist/app/session-shell/prompt-submission.d.ts +2 -4
- package/dist/app/session-shell/prompt-submission.js +3 -23
- package/dist/app/session-shell/response-copy-transport.js +1 -2
- package/dist/app/session-shell/session-lifecycle.d.ts +1 -2
- package/dist/app/session-shell/session-lifecycle.js +2 -4
- package/dist/app/session-shell/session-shell-root.d.ts +0 -31
- package/dist/app/session-shell/session-shell-root.js +3 -4
- package/dist/app/session-shell/session-shell.js +6 -47
- package/dist/app/session-shell/session-viewport-controller.js +3 -6
- package/dist/app/session-shell/shell-host.js +2 -18
- package/dist/app/session-shell/transcript-document.d.ts +1 -2
- package/dist/app/session-shell/transcript-document.js +3 -28
- package/dist/app/session-shell/workflow-output.js +1 -1
- package/dist/app/session-shell/workflow-router.d.ts +1 -3
- package/dist/app/session-shell/workflow-router.js +1 -4
- package/dist/cli/dispatch.d.ts +1 -11
- package/dist/cli/dispatch.js +5 -92
- package/dist/cli/session-context.js +5 -7
- package/dist/cli/uninstall.d.ts +1 -5
- package/dist/cli/uninstall.js +6 -35
- package/dist/cli/version-stats.js +4 -7
- package/dist/composition/owned-settings.d.ts +0 -1
- package/dist/composition/owned-settings.js +0 -1
- package/dist/composition/owned-ui.d.ts +2 -24
- package/dist/composition/owned-ui.js +11 -87
- package/dist/composition/release-update-observation.d.ts +4 -4
- package/dist/composition/release-update-observation.js +17 -47
- package/dist/composition/session-backend.d.ts +0 -1
- package/dist/composition/session-runtime-registry.d.ts +3 -3
- package/dist/composition/settings-route-host.d.ts +0 -7
- package/dist/composition/settings-route-host.js +4 -10
- package/dist/composition/startup-route.d.ts +0 -1
- package/dist/composition/startup-route.js +0 -1
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/model.d.ts +0 -3
- package/dist/contracts/owned-ui/session-workflows.d.ts +1 -4
- package/dist/features/launch/development-launch.js +0 -1
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/intent.d.ts +1 -3
- package/dist/features/launch/intent.js +2 -4
- package/dist/features/launch/session-context.d.ts +2 -2
- package/dist/features/owned-ui/reference-screen-app.d.ts +0 -2
- package/dist/features/owned-ui/reference-screen-app.js +2 -9
- package/dist/features/owned-ui/settings-app.d.ts +0 -6
- package/dist/features/owned-ui/settings-app.js +5 -36
- package/dist/foundation/launch-context/index.d.ts +0 -12
- package/dist/foundation/launch-context/index.js +0 -26
- package/dist/foundation/lifecycle/claim-gate.d.ts +8 -0
- package/dist/foundation/lifecycle/claim-gate.js +37 -0
- package/dist/foundation/lifecycle/index.d.ts +5 -9
- package/dist/foundation/lifecycle/index.js +3 -4
- package/dist/foundation/lifecycle/model.d.ts +2 -59
- package/dist/foundation/lifecycle/model.js +0 -35
- package/dist/foundation/lifecycle/paths.d.ts +0 -24
- package/dist/foundation/lifecycle/paths.js +0 -40
- package/dist/foundation/lifecycle/process-liveness.d.ts +8 -0
- package/dist/foundation/lifecycle/process-liveness.js +18 -0
- package/dist/foundation/lifecycle/session-claim-lock.d.ts +1 -1
- package/dist/foundation/lifecycle/session-claim-lock.js +2 -2
- package/dist/foundation/lifecycle/session-repository-context.d.ts +6 -6
- package/dist/foundation/lifecycle/session-repository-context.js +2 -3
- package/dist/foundation/release/automatic-update.d.ts +1 -3
- package/dist/foundation/release/automatic-update.js +9 -30
- package/dist/foundation/release/bootstrap.d.ts +2 -25
- package/dist/foundation/release/bootstrap.js +33 -344
- package/dist/foundation/release/cohort-state.d.ts +21 -46
- package/dist/foundation/release/cohort-state.js +30 -62
- package/dist/foundation/release/dependency-certification.d.ts +1 -1
- package/dist/foundation/release/index.d.ts +10 -17
- package/dist/foundation/release/index.js +7 -11
- package/dist/foundation/release/latest-release.d.ts +1 -2
- package/dist/foundation/release/latest-release.js +1 -2
- package/dist/foundation/release/process-liveness.d.ts +2 -0
- package/dist/foundation/release/process-liveness.js +12 -0
- package/dist/foundation/release/release-gc.d.ts +12 -9
- package/dist/foundation/release/release-gc.js +34 -98
- package/dist/foundation/release/release-store.d.ts +2 -2
- package/dist/foundation/release/release-store.js +2 -2
- package/dist/foundation/release/restart-certification.js +1 -1
- package/dist/foundation/release/update-activation.d.ts +2 -9
- package/dist/foundation/release/update-activation.js +28 -43
- package/dist/foundation/release/update-execution-lease.js +1 -1
- package/dist/foundation/release/update-launch.d.ts +0 -2
- package/dist/foundation/release/update-launch.js +0 -7
- package/dist/foundation/release/update-recovery.js +1 -1
- package/dist/foundation/release/update-transaction.d.ts +1 -1
- package/dist/foundation/release/update-transaction.js +5 -2
- package/dist/foundation/release/update.d.ts +2 -10
- package/dist/foundation/release/update.js +23 -200
- package/dist/foundation/session-writer-lock/index.d.ts +14 -6
- package/dist/foundation/session-writer-lock/index.js +48 -103
- package/dist/foundation/startup/startup-runtime.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/exit-notice.d.ts +6 -0
- package/dist/foundation/terminal-cleanup/exit-notice.js +36 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +2 -1
- package/dist/foundation/terminal-cleanup/index.js +2 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +0 -5
- package/dist/foundation/terminal-cleanup/terminal-reset.js +0 -5
- package/dist/integrations/pi/components/index.d.ts +1 -1
- package/dist/integrations/pi/components/index.js +1 -1
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -4
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +2 -2
- package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +2 -5
- package/dist/integrations/pi/components/shell-presenters-info.js +4 -18
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +1 -1
- package/dist/integrations/pi/components/shell-presenters-transcript.js +1 -1
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +0 -2
- package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +2 -5
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -16
- package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +1 -2
- package/dist/integrations/pi/components/upstream/components/session-footer.js +6 -8
- package/dist/integrations/pi/engine/adapter.d.ts +0 -1
- package/dist/integrations/pi/engine/adapter.js +1 -16
- package/dist/integrations/pi/engine/compaction-progress.js +13 -5
- package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -1
- package/dist/integrations/pi/engine/diagnostics-state.js +0 -14
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +0 -1
- package/dist/integrations/pi/engine/prompt-suggestions.js +0 -40
- package/dist/integrations/pi/engine/session-runtime.js +0 -2
- package/dist/integrations/pi/engine/workflow-runner.js +1 -1
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -2
- package/dist/integrations/pi/tui-runtime/adapter.js +2 -2
- package/dist/product-identity.d.ts +4 -6
- package/dist/product-identity.js +6 -11
- package/dist/product-identity.json +1 -40
- package/dist/runtime-payload-inventory.json +0 -3
- package/dist/ui/components/index.d.ts +2 -2
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/submitted-prompt.d.ts +3 -13
- package/dist/ui/components/submitted-prompt.js +8 -41
- package/dist/ui/components/transcript-viewport.d.ts +1 -3
- package/dist/ui/components/transcript-viewport.js +1 -4
- package/dist/ui/settings/declarations.d.ts +3 -97
- package/dist/ui/settings/declarations.js +3 -78
- package/dist/ui/settings/migrations.js +18 -2
- package/docs/architecture/boundaries.md +22 -39
- package/docs/architecture/code-documentation.md +2 -2
- package/docs/architecture/internal-naming.md +9 -17
- package/docs/architecture/project-structure.md +30 -29
- package/docs/architecture/resource-and-data-policy.md +16 -31
- package/docs/architecture/toolchain.md +14 -19
- package/docs/architecture/ui-reference-provenance.md +2 -2
- package/docs/ci-release-runbook.md +6 -4
- package/docs/features/launch-profiles.md +11 -17
- package/docs/features/prompt-history.md +10 -11
- package/docs/local-worktree-cleanup.md +32 -1
- package/docs/manual-owned-ui-checkpoint.md +0 -1
- package/docs/openspec-archive-automation.md +11 -3
- package/docs/validation.md +5 -9
- package/docs/worktree-link-recovery.md +6 -6
- package/package.json +7 -19
- package/bin/guardian.js +0 -42
- package/bin/supervisor.js +0 -7
- package/bin/tab-launch-context.d.ts +0 -27
- package/bin/tab-launch-context.js +0 -94
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +0 -38
- package/dist/app/session-shell/resident-tab-coordinator.js +0 -77
- package/dist/cli/tabs-request.d.ts +0 -7
- package/dist/cli/tabs-request.js +0 -1
- package/dist/cli/tabs.d.ts +0 -14
- package/dist/cli/tabs.js +0 -151
- package/dist/composition/resident-tab-bridge.d.ts +0 -41
- package/dist/composition/resident-tab-bridge.js +0 -209
- package/dist/composition/utility-tab.d.ts +0 -28
- package/dist/composition/utility-tab.js +0 -244
- package/dist/features/owned-ui/plus-menu-dialog.d.ts +0 -28
- package/dist/features/owned-ui/plus-menu-dialog.js +0 -89
- package/dist/features/resident-tab/auto-name.d.ts +0 -11
- package/dist/features/resident-tab/auto-name.js +0 -44
- package/dist/features/resident-tab/index.d.ts +0 -5
- package/dist/features/resident-tab/index.js +0 -7
- package/dist/features/resident-tab/shortcut-bindings-file.d.ts +0 -8
- package/dist/features/resident-tab/shortcut-bindings-file.js +0 -40
- package/dist/features/resident-tab/shortcut-declarations.d.ts +0 -13
- package/dist/features/resident-tab/shortcut-declarations.js +0 -26
- package/dist/features/resident-tab/shortcut-projection.d.ts +0 -29
- package/dist/features/resident-tab/shortcut-projection.js +0 -64
- package/dist/features/resident-tab/status-deriver.d.ts +0 -10
- package/dist/features/resident-tab/status-deriver.js +0 -12
- package/dist/foundation/launch-guardian/exit-watcher.d.ts +0 -14
- package/dist/foundation/launch-guardian/exit-watcher.js +0 -103
- package/dist/foundation/launch-guardian/index.d.ts +0 -2
- package/dist/foundation/launch-guardian/index.js +0 -1
- package/dist/foundation/launch-guardian/main.d.ts +0 -39
- package/dist/foundation/launch-guardian/main.js +0 -232
- package/dist/foundation/lifecycle/commands.d.ts +0 -40
- package/dist/foundation/lifecycle/commands.js +0 -1
- package/dist/foundation/lifecycle/launch-instance.d.ts +0 -46
- package/dist/foundation/lifecycle/launch-instance.js +0 -134
- package/dist/foundation/lifecycle/native-claim-gate.d.ts +0 -5
- package/dist/foundation/lifecycle/native-claim-gate.js +0 -41
- package/dist/foundation/lifecycle/supervisor-startup.d.ts +0 -30
- package/dist/foundation/lifecycle/supervisor-startup.js +0 -106
- package/dist/foundation/process-containment/addon-containment.d.ts +0 -20
- package/dist/foundation/process-containment/addon-containment.js +0 -139
- package/dist/foundation/process-containment/addon-process-inspector.d.ts +0 -11
- package/dist/foundation/process-containment/addon-process-inspector.js +0 -36
- package/dist/foundation/process-containment/addon.d.ts +0 -47
- package/dist/foundation/process-containment/addon.js +0 -57
- package/dist/foundation/process-containment/artifact.d.ts +0 -1
- package/dist/foundation/process-containment/artifact.js +0 -35
- package/dist/foundation/process-containment/contracts.d.ts +0 -33
- package/dist/foundation/process-containment/contracts.js +0 -35
- package/dist/foundation/process-containment/index.d.ts +0 -9
- package/dist/foundation/process-containment/index.js +0 -7
- package/dist/foundation/process-containment/linux-process-inspector.d.ts +0 -7
- package/dist/foundation/process-containment/linux-process-inspector.js +0 -27
- package/dist/foundation/process-containment/native-process-inspector.d.ts +0 -4
- package/dist/foundation/process-containment/native-process-inspector.js +0 -21
- package/dist/foundation/protocol/client.d.ts +0 -18
- package/dist/foundation/protocol/client.js +0 -130
- package/dist/foundation/protocol/index.d.ts +0 -3
- package/dist/foundation/protocol/index.js +0 -2
- package/dist/foundation/protocol/messages.d.ts +0 -90
- package/dist/foundation/protocol/messages.js +0 -100
- package/dist/foundation/release/cohort-selection.d.ts +0 -33
- package/dist/foundation/release/cohort-selection.js +0 -67
- package/dist/foundation/release/endpoint-lock.d.ts +0 -2
- package/dist/foundation/release/endpoint-lock.js +0 -37
- package/dist/foundation/release/endpoint-recovery.d.ts +0 -10
- package/dist/foundation/release/endpoint-recovery.js +0 -45
- package/dist/foundation/release/endpoints.d.ts +0 -32
- package/dist/foundation/release/endpoints.js +0 -152
- package/dist/foundation/release/prepared-update-activation.d.ts +0 -3
- package/dist/foundation/release/prepared-update-activation.js +0 -27
- package/dist/foundation/release/process-cleanup.d.ts +0 -14
- package/dist/foundation/release/process-cleanup.js +0 -76
- package/dist/foundation/release/supervisor-identity.d.ts +0 -15
- package/dist/foundation/release/supervisor-identity.js +0 -63
- package/dist/foundation/resident-tabs/boot-identity.d.ts +0 -6
- package/dist/foundation/resident-tabs/boot-identity.js +0 -16
- package/dist/foundation/resident-tabs/bounded-host-command.d.ts +0 -20
- package/dist/foundation/resident-tabs/bounded-host-command.js +0 -62
- package/dist/foundation/resident-tabs/bridge-client.d.ts +0 -73
- package/dist/foundation/resident-tabs/bridge-client.js +0 -327
- package/dist/foundation/resident-tabs/continuity.d.ts +0 -12
- package/dist/foundation/resident-tabs/continuity.js +0 -63
- package/dist/foundation/resident-tabs/doctor.d.ts +0 -28
- package/dist/foundation/resident-tabs/doctor.js +0 -166
- package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +0 -27
- package/dist/foundation/resident-tabs/draft-checkpoint.js +0 -145
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +0 -36
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +0 -151
- package/dist/foundation/resident-tabs/fault-injection.d.ts +0 -8
- package/dist/foundation/resident-tabs/fault-injection.js +0 -26
- package/dist/foundation/resident-tabs/fixture-control.d.ts +0 -7
- package/dist/foundation/resident-tabs/fixture-control.js +0 -35
- package/dist/foundation/resident-tabs/host-entry.d.ts +0 -1
- package/dist/foundation/resident-tabs/host-entry.js +0 -17
- package/dist/foundation/resident-tabs/index.d.ts +0 -15
- package/dist/foundation/resident-tabs/index.js +0 -10
- package/dist/foundation/resident-tabs/maintenance.d.ts +0 -39
- package/dist/foundation/resident-tabs/maintenance.js +0 -75
- package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +0 -34
- package/dist/foundation/resident-tabs/progress-observation-schema.js +0 -1
- package/dist/foundation/resident-tabs/progress-observation.d.ts +0 -4
- package/dist/foundation/resident-tabs/progress-observation.js +0 -150
- package/dist/foundation/resident-tabs/prompt-journal.d.ts +0 -63
- package/dist/foundation/resident-tabs/prompt-journal.js +0 -213
- package/dist/foundation/resident-tabs/protocol.d.ts +0 -12
- package/dist/foundation/resident-tabs/protocol.js +0 -195
- package/dist/foundation/resident-tabs/recovery.d.ts +0 -26
- package/dist/foundation/resident-tabs/recovery.js +0 -205
- package/dist/foundation/resident-tabs/release-holds.d.ts +0 -28
- package/dist/foundation/resident-tabs/release-holds.js +0 -78
- package/dist/foundation/resident-tabs/routes.d.ts +0 -5
- package/dist/foundation/resident-tabs/routes.js +0 -5
- package/dist/foundation/resident-tabs/routing.d.ts +0 -11
- package/dist/foundation/resident-tabs/routing.js +0 -10
- package/dist/foundation/resident-tabs/runtime-control.d.ts +0 -38
- package/dist/foundation/resident-tabs/runtime-control.js +0 -74
- package/dist/foundation/resident-tabs/session-sync.d.ts +0 -14
- package/dist/foundation/resident-tabs/session-sync.js +0 -37
- package/dist/foundation/resident-tabs/settings.d.ts +0 -16
- package/dist/foundation/resident-tabs/settings.js +0 -60
- package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +0 -14
- package/dist/foundation/resident-tabs/terminal-host-artifact.js +0 -78
- package/dist/foundation/resident-tabs/zip-archive.d.ts +0 -9
- package/dist/foundation/resident-tabs/zip-archive.js +0 -56
- package/dist/foundation/storage/control-store.d.ts +0 -20
- package/dist/foundation/storage/control-store.js +0 -331
- package/dist/foundation/storage/index.d.ts +0 -1
- package/dist/foundation/storage/index.js +0 -1
- package/dist/foundation/supervision/index.d.ts +0 -3
- package/dist/foundation/supervision/index.js +0 -3
- package/dist/foundation/supervision/main.d.ts +0 -1
- package/dist/foundation/supervision/main.js +0 -86
- package/dist/foundation/supervision/paths.d.ts +0 -1
- package/dist/foundation/supervision/paths.js +0 -1
- package/dist/foundation/supervision/server.d.ts +0 -46
- package/dist/foundation/supervision/server.js +0 -606
- package/dist/integrations/pi/engine/offline-settings-port.d.ts +0 -23
- package/dist/integrations/pi/engine/offline-settings-port.js +0 -54
- package/dist/native/darwin-arm64/manifest.json +0 -23
- package/dist/native/darwin-arm64/process-guardian.node +0 -0
- package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10500
- package/dist/native/darwin-arm64/terminal-host.manifest.json +0 -46
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +0 -23
- package/dist/native/darwin-x64/process-guardian.node +0 -0
- package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10737
- package/dist/native/darwin-x64/terminal-host.manifest.json +0 -46
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +0 -23
- package/dist/native/linux-x64/process-guardian.node +0 -0
- package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -11226
- package/dist/native/linux-x64/terminal-host.manifest.json +0 -46
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +0 -23
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10757
- package/dist/native/win32-x64/terminal-host.manifest.json +0 -46
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/docs/architecture/evidence/resident-tabs/linux-x64.md +0 -37
- package/docs/architecture/evidence/resident-tabs/macos-arm64.md +0 -36
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +0 -35
- package/docs/architecture/evidence/resident-tabs/windows-x64.md +0 -36
- package/docs/architecture/evidence/terminal-host-spike/manual-one-pane-terminal-host.md +0 -70
- package/docs/architecture/evidence/terminal-host-spike/manual-two-by-two-basic-terminal-host.md +0 -32
- package/docs/architecture/evidence/terminal-host-spike/milestone-baseline.json +0 -115
- package/docs/architecture/evidence/terminal-host-spike/owned-ui-foundation-prerequisite.json +0 -48
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-provenance.json +0 -125
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-1.json +0 -56
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-3.json +0 -174
- package/docs/architecture/evidence/terminal-host-spike/terminal-spike-acceptance-record.json +0 -18
- package/docs/architecture/native-fixture-isolation.md +0 -23
- package/docs/architecture/process-guardian-provenance.md +0 -36
- package/docs/architecture/resident-tabs-requirements.md +0 -18
- package/docs/architecture/resident-tabs.md +0 -668
- package/docs/architecture/terminal-host-proof-gate.md +0 -34
- package/docs/architecture/terminal-host-provenance.md +0 -81
- package/docs/architecture/terminal-host-spike-evidence.md +0 -39
- package/docs/launch-recovery.md +0 -23
- package/docs/manual-launch-instance-acceptance.md +0 -43
- package/docs/manual-resident-tabs-acceptance.md +0 -51
|
@@ -5,31 +5,32 @@ import { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
|
|
|
5
5
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
6
6
|
export const RELEASE_COHORT_SCHEMA = PRODUCT_IDENTITY.protocol.releaseCohortSchema;
|
|
7
7
|
const RELEASE_ID_PATTERN = /^[0-9A-Za-z.+_-]+-[a-f0-9]{20}$/;
|
|
8
|
+
/** How long a release stays on disk after its approval, so processes started from it keep their files. */
|
|
9
|
+
export const RELEASE_RETENTION_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
+
* Age-based retention. A release stays while a selector names it (active, its rollback, or a
|
|
12
|
+
* candidate still being certified), while an unfinished update may return to it, while the
|
|
13
|
+
* reconciling command runs from it, or while its approval is younger than the retention window.
|
|
14
|
+
* Nothing asks which processes are running: a session that outlives the window and two updates
|
|
15
|
+
* can lose its release files, which is the documented trade-off.
|
|
11
16
|
*/
|
|
12
17
|
export function planProtectedReleases(state, inputs = {}) {
|
|
13
|
-
const holds = inputs.externalHolds ?? [];
|
|
14
|
-
for (const hold of holds) {
|
|
15
|
-
if (hold.authority !== "agent" && hold.authority !== "migration" && hold.authority !== "resident")
|
|
16
|
-
throw new Error(`unknown release hold authority: ${String(hold.authority)}`);
|
|
17
|
-
if (!state.releases[hold.releaseId] && !state.cleanup.pending[hold.releaseId]) {
|
|
18
|
-
throw new Error(`external ${hold.authority} hold names unknown release ${hold.releaseId}`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
18
|
const protectedIds = new Set();
|
|
22
19
|
for (const id of [state.references.active, state.references.pending, state.references.approved, state.references.rollback]) {
|
|
23
20
|
if (id !== null)
|
|
24
21
|
protectedIds.add(id);
|
|
25
22
|
}
|
|
26
|
-
for (const id of inputs.
|
|
23
|
+
for (const id of inputs.ownReleaseIds ?? [])
|
|
27
24
|
protectedIds.add(id);
|
|
28
|
-
for (const hold of holds)
|
|
29
|
-
protectedIds.add(hold.releaseId);
|
|
30
25
|
if (inputs.transaction?.status === "active" && inputs.transaction.priorActiveReleaseId !== null) {
|
|
31
26
|
protectedIds.add(inputs.transaction.priorActiveReleaseId);
|
|
32
27
|
}
|
|
28
|
+
const now = inputs.now ?? Date.now();
|
|
29
|
+
const window = inputs.retentionMs ?? RELEASE_RETENTION_MS;
|
|
30
|
+
for (const release of Object.values(state.releases)) {
|
|
31
|
+
if (withinRetention(release, now, window))
|
|
32
|
+
protectedIds.add(release.releaseId);
|
|
33
|
+
}
|
|
33
34
|
const protectedReleaseIds = [...protectedIds].sort();
|
|
34
35
|
const known = Object.keys(state.releases).sort();
|
|
35
36
|
return {
|
|
@@ -38,6 +39,18 @@ export function planProtectedReleases(state, inputs = {}) {
|
|
|
38
39
|
collectibleReleaseIds: known.filter(id => !protectedIds.has(id)),
|
|
39
40
|
};
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Whether a release is young enough to keep. An approved release counts from its approval; a
|
|
44
|
+
* candidate still awaiting certification counts from its materialization so concurrent work is
|
|
45
|
+
* not collected under it. A record without a readable timestamp is treated as old.
|
|
46
|
+
*/
|
|
47
|
+
export function withinRetention(release, now, retentionMs = RELEASE_RETENTION_MS) {
|
|
48
|
+
if (release.approval === "rejected")
|
|
49
|
+
return false;
|
|
50
|
+
const stamp = release.approval === "approved" ? release.certifiedAt : release.materializedAt;
|
|
51
|
+
const at = stamp === null ? Number.NaN : Date.parse(stamp);
|
|
52
|
+
return Number.isFinite(at) && now - at < retentionMs;
|
|
53
|
+
}
|
|
41
54
|
/** Serializes validated cohort-state revisions under a lock and commits each update atomically. */
|
|
42
55
|
export class CohortStateStore {
|
|
43
56
|
path;
|
|
@@ -103,7 +116,6 @@ export class CohortStateStore {
|
|
|
103
116
|
...current.references,
|
|
104
117
|
pending: current.references.active === release.releaseId ? current.references.pending : release.releaseId,
|
|
105
118
|
},
|
|
106
|
-
activation: activation("pending", "candidate awaits certification and safe activation"),
|
|
107
119
|
};
|
|
108
120
|
});
|
|
109
121
|
}
|
|
@@ -132,7 +144,6 @@ export class CohortStateStore {
|
|
|
132
144
|
approved: releaseId,
|
|
133
145
|
rollback: prior && prior !== releaseId ? prior : current.references.rollback,
|
|
134
146
|
},
|
|
135
|
-
activation: activation("idle", null),
|
|
136
147
|
};
|
|
137
148
|
});
|
|
138
149
|
}
|
|
@@ -153,7 +164,6 @@ export class CohortStateStore {
|
|
|
153
164
|
pending: current.references.pending === releaseId ? null : current.references.pending,
|
|
154
165
|
approved: selectedId,
|
|
155
166
|
},
|
|
156
|
-
activation: activation("idle", null),
|
|
157
167
|
};
|
|
158
168
|
}
|
|
159
169
|
const prior = current.references.active;
|
|
@@ -166,16 +176,10 @@ export class CohortStateStore {
|
|
|
166
176
|
approved: releaseId,
|
|
167
177
|
rollback: prior && prior !== releaseId ? prior : current.references.rollback,
|
|
168
178
|
},
|
|
169
|
-
activation: activation("idle", null),
|
|
170
179
|
};
|
|
171
180
|
});
|
|
172
181
|
}
|
|
173
|
-
async
|
|
174
|
-
return await this.update(current => ({ ...current, activation: { ...activation("blocked", reason), blockerGenerationIds: [...blockerGenerationIds] } }));
|
|
175
|
-
}
|
|
176
|
-
async rollback(ownershipReleased) {
|
|
177
|
-
if (!ownershipReleased)
|
|
178
|
-
throw new Error("cannot roll back before current cohort ownership is released");
|
|
182
|
+
async rollback() {
|
|
179
183
|
return await this.update(current => {
|
|
180
184
|
const rollbackId = current.references.rollback;
|
|
181
185
|
if (!rollbackId)
|
|
@@ -192,17 +196,9 @@ export class CohortStateStore {
|
|
|
192
196
|
approved: rollbackId,
|
|
193
197
|
rollback: current.references.active,
|
|
194
198
|
},
|
|
195
|
-
activation: activation("idle", null),
|
|
196
199
|
};
|
|
197
200
|
});
|
|
198
201
|
}
|
|
199
|
-
async setRetention(releaseIds) {
|
|
200
|
-
return await this.update(current => {
|
|
201
|
-
for (const releaseId of releaseIds)
|
|
202
|
-
requiredRelease(current, releaseId);
|
|
203
|
-
return { ...current, references: { ...current.references, retention: unique(releaseIds) } };
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
202
|
/** Atomically replace legacy retention history and detach every currently collectible record. */
|
|
207
203
|
async reconcileRetention(resolveInputs, orphans = []) {
|
|
208
204
|
let plan = null;
|
|
@@ -318,31 +314,6 @@ export class CohortStateStore {
|
|
|
318
314
|
error: error === null ? null : boundedError(error),
|
|
319
315
|
})));
|
|
320
316
|
}
|
|
321
|
-
async removeUnreferencedRelease(releaseId, externalReferences) {
|
|
322
|
-
return await this.update(current => {
|
|
323
|
-
const release = requiredRelease(current, releaseId);
|
|
324
|
-
const protectedIds = new Set([
|
|
325
|
-
current.references.active,
|
|
326
|
-
current.references.pending,
|
|
327
|
-
current.references.approved,
|
|
328
|
-
current.references.rollback,
|
|
329
|
-
...current.references.retention,
|
|
330
|
-
...externalReferences,
|
|
331
|
-
].filter((value) => value !== null));
|
|
332
|
-
if (protectedIds.has(releaseId))
|
|
333
|
-
throw new Error(`release ${releaseId} is still referenced and cannot be collected`);
|
|
334
|
-
const releases = { ...current.releases };
|
|
335
|
-
delete releases[releaseId];
|
|
336
|
-
return {
|
|
337
|
-
...current,
|
|
338
|
-
releases,
|
|
339
|
-
cleanup: {
|
|
340
|
-
...current.cleanup,
|
|
341
|
-
pending: { ...current.cleanup.pending, [releaseId]: cleanupDisposition(release, "detached", null) },
|
|
342
|
-
},
|
|
343
|
-
};
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
317
|
}
|
|
347
318
|
export function emptyState() {
|
|
348
319
|
return {
|
|
@@ -351,7 +322,6 @@ export function emptyState() {
|
|
|
351
322
|
releases: {},
|
|
352
323
|
references: { active: null, pending: null, approved: null, rollback: null, retention: [] },
|
|
353
324
|
cleanup: { pending: {}, diagnostics: [], workerRuns: [] },
|
|
354
|
-
activation: activation("idle", null),
|
|
355
325
|
};
|
|
356
326
|
}
|
|
357
327
|
function cleanupDisposition(release, stage, trashPath) {
|
|
@@ -382,16 +352,12 @@ function replaceCleanupWorkerRun(current, runId, operation) {
|
|
|
382
352
|
: [...current.cleanup.workerRuns, operation(undefined)];
|
|
383
353
|
return { ...current, cleanup: { ...current.cleanup, workerRuns: workerRuns.slice(-16) } };
|
|
384
354
|
}
|
|
385
|
-
function activation(state, reason) {
|
|
386
|
-
return { state, reason, blockerGenerationIds: [], updatedAt: new Date().toISOString() };
|
|
387
|
-
}
|
|
388
355
|
function requiredRelease(state, releaseId) {
|
|
389
356
|
const release = state.releases[releaseId];
|
|
390
357
|
if (!release)
|
|
391
358
|
throw new Error(`unknown release ${releaseId}`);
|
|
392
359
|
return release;
|
|
393
360
|
}
|
|
394
|
-
function unique(values) { return [...new Set(values)]; }
|
|
395
361
|
async function acquireLock(path) {
|
|
396
362
|
const deadline = Date.now() + 5_000;
|
|
397
363
|
while (true) {
|
|
@@ -452,7 +418,9 @@ async function reclaimAbandonedLock(path) {
|
|
|
452
418
|
function normalizeState(value) {
|
|
453
419
|
if (!value || typeof value !== "object")
|
|
454
420
|
return value;
|
|
455
|
-
|
|
421
|
+
// Compatibility: state written while supervisors coordinated activation carries an
|
|
422
|
+
// `activation` record that nothing reads any more; it is dropped on the next write.
|
|
423
|
+
const { activation: _activation, ...state } = value;
|
|
456
424
|
const cleanup = state.cleanup;
|
|
457
425
|
return {
|
|
458
426
|
...state,
|
|
@@ -4,7 +4,7 @@ type LayerIdentity = {
|
|
|
4
4
|
readonly contentDigest: string;
|
|
5
5
|
};
|
|
6
6
|
export interface ReadDependencyCertificationOptions {
|
|
7
|
-
/** Only authenticated parent
|
|
7
|
+
/** Only an authenticated parent certifying the exact release may upgrade missing platform evidence. */
|
|
8
8
|
readonly allowLegacyParentCertification?: boolean;
|
|
9
9
|
/** Cleanup must validate canonical evidence without migrating or falling back. */
|
|
10
10
|
readonly canonicalOnly?: boolean;
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
export { certifyMaterializedRelease,
|
|
2
|
-
export type { BootstrapOptions
|
|
3
|
-
export { selectCohortLaunch } from "./cohort-selection.js";
|
|
1
|
+
export { certifyMaterializedRelease, recordParentCertifiedRelease, releaseEnvironment, runBootstrap, } from "./bootstrap.js";
|
|
2
|
+
export type { BootstrapOptions } from "./bootstrap.js";
|
|
4
3
|
export { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
|
|
5
|
-
export
|
|
6
|
-
export {
|
|
7
|
-
export type { ActiveReleaseTransactionReference, CohortState, EndpointOwnership, ExternalReleaseHold, ExternalReleaseHoldAuthority, OrphanReleaseDisposition, ProtectedReleaseInputs, ProtectedReleasePlan, ReleaseApproval, ReleaseCleanupDiagnostic, ReleaseCleanupDisposition, ReleaseCleanupStage, ReleaseCleanupState, ReleaseCleanupWorkerRun, ReleaseCleanupWorkerStatus, ReleaseCleanupWorkerSummary, ReleaseRecord, ReleaseReferences, ReleaseRetentionReconciliation, SupervisorEndpointMetadata, } from "./cohort-state.js";
|
|
4
|
+
export { CohortStateStore, RELEASE_COHORT_SCHEMA, RELEASE_RETENTION_MS, emptyState, planProtectedReleases, withinRetention } from "./cohort-state.js";
|
|
5
|
+
export type { ActiveReleaseTransactionReference, CohortState, OrphanReleaseDisposition, ProtectedReleaseInputs, ProtectedReleasePlan, ReleaseApproval, ReleaseCleanupDiagnostic, ReleaseCleanupDisposition, ReleaseCleanupStage, ReleaseCleanupState, ReleaseCleanupWorkerRun, ReleaseCleanupWorkerStatus, ReleaseCleanupWorkerSummary, ReleaseRecord, ReleaseReferences, ReleaseRetentionReconciliation, } from "./cohort-state.js";
|
|
8
6
|
export { DEPENDENCY_LAYER_MANIFEST, DEPENDENCY_LAYER_SCHEMA, RUNTIME_PAYLOAD_INVENTORY, dependencyLayerCertificationPath, dependencyReference, generateDependencyRuntimePayload, legacyDependencyLayerCertificationPath, materializeDependencyLayer, readCertifiedDependencyLayer, selectDependencyRuntimePayload, selectPublishedDependencyRuntimePayload, verifyDependencyLayer, } from "./dependency-layer.js";
|
|
9
7
|
export type { DependencyLayerIdentity, DependencyLayerOperationEvent, DependencyLayerReference, GeneratedRuntimePayload, MaterializeDependencyLayerOptions, MaterializedDependencyLayer, PublishedRuntimeFileClassification, PublishedRuntimePayload, ReadCertifiedDependencyLayerOptions, RuntimePayloadExclusion, RuntimePayloadInventory, SelectedRuntimePayload, } from "./dependency-layer.js";
|
|
10
|
-
export {
|
|
11
|
-
export { currentSupervisorStartIdentity, observeSupervisorProcess, supervisorProcessState } from "./supervisor-identity.js";
|
|
12
|
-
export { withEndpointLock } from "./endpoint-lock.js";
|
|
13
|
-
export type { RecordedEndpoint } from "./endpoints.js";
|
|
14
|
-
export { cleanupProvenIdleOwner, cleanupVerifiedOwner, processIsAlive } from "./process-cleanup.js";
|
|
15
|
-
export type { CleanupDiagnostics } from "./process-cleanup.js";
|
|
8
|
+
export { processIsAlive } from "./process-liveness.js";
|
|
16
9
|
export { PRODUCT_PACKAGE_NAME, createReleaseIdentity, deriveReleaseIdentity, digestManifestFiles, discoverReleasePayload, packageRootFromModule, releaseFileIdentity, resolveWithin, } from "./release.js";
|
|
17
10
|
export type { DiscoverReleasePayloadOptions, DiscoveredReleasePayload, ReleaseFileIdentity, ReleaseIdentity } from "./release.js";
|
|
18
|
-
export {
|
|
11
|
+
export { prepareReleaseCleanup, runBoundedReleaseCleanup, runReleaseCleanupWorker, scheduleReleaseCleanup } from "./release-gc.js";
|
|
19
12
|
export type { ReleaseCleanupLimits, ReleaseCleanupOperations, ReleaseCleanupOptions, ReleaseCleanupResult, ReleaseCleanupWorkerOptions } from "./release-gc.js";
|
|
20
13
|
export { RELEASE_MANIFEST_FILENAME, ReleaseRepairUnavailableError, assertCertifiedFilesPresent, assertImmutableExecutionRoot, consumeMaterializationProof, materializeRelease, readCertifiedReleaseManifest, readMaterializedRelease, repairMaterializedRelease, resolveReleaseEntryPoint, verifyMaterializedRelease, } from "./release-store.js";
|
|
21
14
|
export type { CertifiedReleaseRecord, MaterializeReleaseOptions, MaterializedRelease, ReadCertifiedReleaseManifestOptions, ReleaseContentOperation, ReleaseContentOperationEvent, VerifyMaterializedReleaseOptions, } from "./release-store.js";
|
|
@@ -23,11 +16,11 @@ export { createRestartSeal, readRestartCertifiedRelease, releaseCertificationDoc
|
|
|
23
16
|
export type { RestartSeal, RestartValidationEvent } from "./restart-certification.js";
|
|
24
17
|
export { STABLE_RELEASE_SCHEMA, createStableReleaseEvidence, verifyStableRegistry } from "./stable-release.js";
|
|
25
18
|
export type { StableRegistryState, StableRegistryVerificationOptions, StableReleaseEvidence, StableReleaseEvidenceInput } from "./stable-release.js";
|
|
26
|
-
export { PACKAGE_UNLOCK_PATIENCE_MS,
|
|
27
|
-
export type { ProcessRequest, ProcessResult, SelfUpdateOptions, UpdateActivationPhase, UpdateChannel, UpdateFileMetadata, UpdateFileSystem, UpdateLifecycleCoordinator, UpdateMaterializationProgress, UpdateMeasuredPhase, UpdateOutput,
|
|
28
|
-
export { UPDATE_ACTIVATION_CONTRACT, UPDATE_ACTIVATION_ENTRY, UPDATE_ACTIVATION_MANIFEST_FIELD,
|
|
19
|
+
export { PACKAGE_UNLOCK_PATIENCE_MS, UPDATE_ALREADY_RUNNING_EXIT_CODE, PRODUCT_PACKAGE, assertUpdatePerformanceBudget, createNpmProcessRunner, createUpdateLifecycleCoordinator, isPackageLockError, lockedPackageDiagnostic, renderUpdateProgressBar, runSelfUpdate, } from "./update.js";
|
|
20
|
+
export type { ProcessRequest, ProcessResult, SelfUpdateOptions, UpdateActivationPhase, UpdateChannel, UpdateFileMetadata, UpdateFileSystem, UpdateLifecycleCoordinator, UpdateMaterializationProgress, UpdateMeasuredPhase, UpdateOutput, UpdatePackageReplacementInput, UpdatePerformanceEvidence, UpdatePhaseTimingEvent, UpdateProcessRunner, UpdateTransactionJournal, UpdateUnlockPatience, } from "./update.js";
|
|
21
|
+
export { UPDATE_ACTIVATION_CONTRACT, UPDATE_ACTIVATION_ENTRY, UPDATE_ACTIVATION_MANIFEST_FIELD, activateInstalledRelease, delegateActivation, readActivationContracts, runActivationEntry, } from "./update-activation.js";
|
|
29
22
|
export type { UpdateActivationCallbacks, UpdateActivationEvent, UpdateActivationRequest } from "./update-activation.js";
|
|
30
|
-
export {
|
|
23
|
+
export { selectUpdateLaunchRelease } from "./update-launch.js";
|
|
31
24
|
export { UPDATE_RECOVERY_SCHEMA, cleanupUpdateRecoveryCapsules, inspectUpdateLauncherSet, npmPrefixForGlobalRoot, prepareUpdateRecoveryCapsule, readUpdateRecoveryCapsule, removeUpdateRecoveryCapsule, resolveNpmCli, runProtectedPackageReplacement, updateLauncherPaths, updateNpmInstallArguments, } from "./update-recovery.js";
|
|
32
25
|
export type { ProtectedPackageReplacementOptions, ProtectedPackageReplacementResult, UpdateRecoveryCapsule, UpdateRecoveryResult } from "./update-recovery.js";
|
|
33
26
|
export { UPDATE_JOURNAL_SCHEMA, UpdateTransactionStore } from "./update-transaction.js";
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
export { certifyMaterializedRelease,
|
|
2
|
-
export { selectCohortLaunch } from "./cohort-selection.js";
|
|
1
|
+
export { certifyMaterializedRelease, recordParentCertifiedRelease, releaseEnvironment, runBootstrap, } from "./bootstrap.js";
|
|
3
2
|
export { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
|
|
4
|
-
export { CohortStateStore, RELEASE_COHORT_SCHEMA, emptyState, planProtectedReleases } from "./cohort-state.js";
|
|
3
|
+
export { CohortStateStore, RELEASE_COHORT_SCHEMA, RELEASE_RETENTION_MS, emptyState, planProtectedReleases, withinRetention } from "./cohort-state.js";
|
|
5
4
|
export { DEPENDENCY_LAYER_MANIFEST, DEPENDENCY_LAYER_SCHEMA, RUNTIME_PAYLOAD_INVENTORY, dependencyLayerCertificationPath, dependencyReference, generateDependencyRuntimePayload, legacyDependencyLayerCertificationPath, materializeDependencyLayer, readCertifiedDependencyLayer, selectDependencyRuntimePayload, selectPublishedDependencyRuntimePayload, verifyDependencyLayer, } from "./dependency-layer.js";
|
|
6
|
-
export {
|
|
7
|
-
export { currentSupervisorStartIdentity, observeSupervisorProcess, supervisorProcessState } from "./supervisor-identity.js";
|
|
8
|
-
export { withEndpointLock } from "./endpoint-lock.js";
|
|
9
|
-
export { cleanupProvenIdleOwner, cleanupVerifiedOwner, processIsAlive } from "./process-cleanup.js";
|
|
5
|
+
export { processIsAlive } from "./process-liveness.js";
|
|
10
6
|
export { PRODUCT_PACKAGE_NAME, createReleaseIdentity, deriveReleaseIdentity, digestManifestFiles, discoverReleasePayload, packageRootFromModule, releaseFileIdentity, resolveWithin, } from "./release.js";
|
|
11
|
-
export {
|
|
7
|
+
export { prepareReleaseCleanup, runBoundedReleaseCleanup, runReleaseCleanupWorker, scheduleReleaseCleanup } from "./release-gc.js";
|
|
12
8
|
export { RELEASE_MANIFEST_FILENAME, ReleaseRepairUnavailableError, assertCertifiedFilesPresent, assertImmutableExecutionRoot, consumeMaterializationProof, materializeRelease, readCertifiedReleaseManifest, readMaterializedRelease, repairMaterializedRelease, resolveReleaseEntryPoint, verifyMaterializedRelease, } from "./release-store.js";
|
|
13
9
|
export { createRestartSeal, readRestartCertifiedRelease, releaseCertificationDocument, restartSealDigest } from "./restart-certification.js";
|
|
14
10
|
export { STABLE_RELEASE_SCHEMA, createStableReleaseEvidence, verifyStableRegistry } from "./stable-release.js";
|
|
15
|
-
export { PACKAGE_UNLOCK_PATIENCE_MS,
|
|
16
|
-
export { UPDATE_ACTIVATION_CONTRACT, UPDATE_ACTIVATION_ENTRY, UPDATE_ACTIVATION_MANIFEST_FIELD,
|
|
17
|
-
export {
|
|
11
|
+
export { PACKAGE_UNLOCK_PATIENCE_MS, UPDATE_ALREADY_RUNNING_EXIT_CODE, PRODUCT_PACKAGE, assertUpdatePerformanceBudget, createNpmProcessRunner, createUpdateLifecycleCoordinator, isPackageLockError, lockedPackageDiagnostic, renderUpdateProgressBar, runSelfUpdate, } from "./update.js";
|
|
12
|
+
export { UPDATE_ACTIVATION_CONTRACT, UPDATE_ACTIVATION_ENTRY, UPDATE_ACTIVATION_MANIFEST_FIELD, activateInstalledRelease, delegateActivation, readActivationContracts, runActivationEntry, } from "./update-activation.js";
|
|
13
|
+
export { selectUpdateLaunchRelease } from "./update-launch.js";
|
|
18
14
|
export { UPDATE_RECOVERY_SCHEMA, cleanupUpdateRecoveryCapsules, inspectUpdateLauncherSet, npmPrefixForGlobalRoot, prepareUpdateRecoveryCapsule, readUpdateRecoveryCapsule, removeUpdateRecoveryCapsule, resolveNpmCli, runProtectedPackageReplacement, updateLauncherPaths, updateNpmInstallArguments, } from "./update-recovery.js";
|
|
19
15
|
export { UPDATE_JOURNAL_SCHEMA, UpdateTransactionStore } from "./update-transaction.js";
|
|
20
16
|
export { warmMaterializedRelease } from "./warmup.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Published release channels: stable `X.Y.Z` on dist-tag `latest`, development `X.Y.Z-dev.N` on `next`. */
|
|
2
2
|
export type ReleaseChannel = "stable" | "development";
|
|
3
|
-
export type StartupUpdateMode = "auto" | "
|
|
3
|
+
export type StartupUpdateMode = "auto" | "no";
|
|
4
4
|
export interface DistTagVersions {
|
|
5
5
|
readonly release: string | null;
|
|
6
6
|
readonly develop: string | null;
|
|
@@ -21,7 +21,6 @@ export interface AvailableRelease {
|
|
|
21
21
|
}
|
|
22
22
|
export declare const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
|
|
23
23
|
export declare const UPDATE_CHECK_INTERVAL_MS: number;
|
|
24
|
-
export declare const NOTIFY_CHECK_INTERVAL_MS: number;
|
|
25
24
|
/** One published version with the pull request its manifest records, when it records one. */
|
|
26
25
|
export interface PublishedVersion {
|
|
27
26
|
readonly version: string;
|
|
@@ -6,7 +6,6 @@ import lockfile from "proper-lockfile";
|
|
|
6
6
|
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
7
7
|
export const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
|
|
8
8
|
export const UPDATE_CHECK_INTERVAL_MS = 15 * 60_000;
|
|
9
|
-
export const NOTIFY_CHECK_INTERVAL_MS = 24 * 60 * 60_000;
|
|
10
9
|
const STARTUP_FETCH_TIMEOUT_MS = 3_000;
|
|
11
10
|
const CACHE_FILENAME = "update-check.json";
|
|
12
11
|
const CACHE_VERSION = 2;
|
|
@@ -146,7 +145,7 @@ export async function checkForNewerRelease(options) {
|
|
|
146
145
|
const now = options.now ?? Date.now;
|
|
147
146
|
const cachePath = join(options.configDir, CACHE_FILENAME);
|
|
148
147
|
try {
|
|
149
|
-
const interval =
|
|
148
|
+
const interval = UPDATE_CHECK_INTERVAL_MS;
|
|
150
149
|
const latest = await withCacheLock(options.configDir, async () => {
|
|
151
150
|
if (options.signal?.aborted)
|
|
152
151
|
return null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Whether a process with this id exists; a permission refusal still proves it is running. */
|
|
2
|
+
export function processIsAlive(pid) {
|
|
3
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
4
|
+
return false;
|
|
5
|
+
try {
|
|
6
|
+
process.kill(pid, 0);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
return error instanceof Error && "code" in error && error.code === "EPERM";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { rename, rm } from "node:fs/promises";
|
|
2
|
-
import { CohortStateStore, type
|
|
2
|
+
import { CohortStateStore, type OrphanReleaseDisposition } from "./cohort-state.js";
|
|
3
3
|
import type { ProductPaths } from "../lifecycle/index.js";
|
|
4
4
|
import { UpdateTransactionStore } from "./update-transaction.js";
|
|
5
|
-
import { type ResidentReleaseHoldReport } from "../resident-tabs/index.js";
|
|
6
5
|
export interface ReleaseCleanupLimits {
|
|
7
6
|
readonly maxItems: number;
|
|
8
7
|
readonly maxDurationMs: number;
|
|
@@ -13,7 +12,15 @@ export interface ReleaseCleanupOperations {
|
|
|
13
12
|
readonly remove?: typeof rm;
|
|
14
13
|
}
|
|
15
14
|
export interface ReleaseCleanupOptions {
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Releases the command that started cleanup runs from. Defaults to the release named by this
|
|
17
|
+
* process's launch context, so a command never collects the files it is running.
|
|
18
|
+
*/
|
|
19
|
+
readonly ownReleaseIds?: readonly string[];
|
|
20
|
+
/** Age window measured from approval; defaults to seven days. */
|
|
21
|
+
readonly retentionMs?: number;
|
|
22
|
+
/** Wall clock the retention window is measured against; `now` only paces a batch. */
|
|
23
|
+
readonly wallClock?: () => number;
|
|
17
24
|
readonly transactionStore?: Pick<UpdateTransactionStore, "read">;
|
|
18
25
|
readonly limits?: Partial<ReleaseCleanupLimits>;
|
|
19
26
|
readonly candidateAgeMs?: number;
|
|
@@ -22,8 +29,6 @@ export interface ReleaseCleanupOptions {
|
|
|
22
29
|
readonly operations?: ReleaseCleanupOperations;
|
|
23
30
|
/** Process-start seam for scheduler and continuation tests. */
|
|
24
31
|
readonly workerSpawner?: (entry: string, environment: NodeJS.ProcessEnv) => Promise<void>;
|
|
25
|
-
/** Resident-tab inspection seam; the default asks a verified installed terminal host. */
|
|
26
|
-
readonly residentHolds?: (dataDir: string, releaseRoots: readonly string[]) => Promise<ResidentReleaseHoldReport>;
|
|
27
32
|
}
|
|
28
33
|
export interface ReleaseCleanupWorkerOptions {
|
|
29
34
|
readonly cleanup?: ReleaseCleanupOptions;
|
|
@@ -53,10 +58,10 @@ interface DiscoveredCleanupInputs {
|
|
|
53
58
|
}[];
|
|
54
59
|
}
|
|
55
60
|
/**
|
|
56
|
-
* Reconcile
|
|
61
|
+
* Reconcile age-based retention under the cohort-state lock and durably detach obsolete releases.
|
|
57
62
|
* This operation intentionally reads only manifests and directory metadata, never payload bytes.
|
|
58
63
|
*/
|
|
59
|
-
export declare function prepareReleaseCleanup(dataDir: string,
|
|
64
|
+
export declare function prepareReleaseCleanup(dataDir: string, _paths?: ProductPaths, options?: ReleaseCleanupOptions): Promise<{
|
|
60
65
|
readonly store: CohortStateStore;
|
|
61
66
|
readonly discovered: DiscoveredCleanupInputs;
|
|
62
67
|
}>;
|
|
@@ -69,6 +74,4 @@ export declare function runBoundedReleaseCleanup(dataDir: string, paths?: Produc
|
|
|
69
74
|
export declare function scheduleReleaseCleanup(dataDir: string, paths: ProductPaths, options?: ReleaseCleanupOptions): Promise<void>;
|
|
70
75
|
/** Entry used by the private cleanup executable shipped in every immutable release. */
|
|
71
76
|
export declare function runReleaseCleanupWorker(environment?: NodeJS.ProcessEnv, workerOptions?: ReleaseCleanupWorkerOptions): Promise<ReleaseCleanupResult>;
|
|
72
|
-
/** Compatibility helper: detach one requested release and execute a one-item pass. */
|
|
73
|
-
export declare function collectRelease(store: CohortStateStore, dataDir: string, releaseId: string, externalReferences: readonly string[], paths?: ProductPaths): Promise<void>;
|
|
74
77
|
export {};
|
|
@@ -4,7 +4,6 @@ import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat } fro
|
|
|
4
4
|
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { CohortStateStore, } from "./cohort-state.js";
|
|
7
|
-
import { liveReleaseIds } from "./endpoints.js";
|
|
8
7
|
import { resolveProductPaths } from "../lifecycle/index.js";
|
|
9
8
|
import { RELEASE_MANIFEST_FILENAME } from "./release-store.js";
|
|
10
9
|
import { DEPENDENCY_LAYER_MANIFEST, readCertifiedDependencyLayer } from "./dependency-layer.js";
|
|
@@ -14,24 +13,25 @@ import { UpdateTransactionStore } from "./update-transaction.js";
|
|
|
14
13
|
import { cleanupUpdateRecoveryCapsules } from "./update-recovery.js";
|
|
15
14
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
16
15
|
import { collectCompileCaches, startupCompileCachePath } from "../startup/index.js";
|
|
17
|
-
import {
|
|
16
|
+
import { readLaunchContext } from "../launch-context/index.js";
|
|
17
|
+
import { processIsAlive } from "./process-liveness.js";
|
|
18
18
|
const DEFAULT_CANDIDATE_AGE_MS = 60 * 60 * 1_000;
|
|
19
19
|
const DEFAULT_LIMITS = { maxItems: 8, maxDurationMs: 2_000, concurrency: 1 };
|
|
20
20
|
const DEFAULT_WORKER_DURATION_MS = 10 * 60 * 1_000;
|
|
21
21
|
const DEFAULT_NO_PROGRESS_BATCHES = 5;
|
|
22
22
|
const DEFAULT_RETRY_DELAY_MS = 500;
|
|
23
|
-
const
|
|
23
|
+
const WORKER_KEEP_ENV = "RELEASE_CLEANUP_KEEP";
|
|
24
24
|
const WORKER_RUN_ID_ENV = "RELEASE_CLEANUP_RUN_ID";
|
|
25
25
|
const WORKER_LEASE_FILENAME = "release-cleanup-worker.lock";
|
|
26
26
|
/**
|
|
27
|
-
* Reconcile
|
|
27
|
+
* Reconcile age-based retention under the cohort-state lock and durably detach obsolete releases.
|
|
28
28
|
* This operation intentionally reads only manifests and directory metadata, never payload bytes.
|
|
29
29
|
*/
|
|
30
|
-
export async function prepareReleaseCleanup(dataDir,
|
|
30
|
+
export async function prepareReleaseCleanup(dataDir, _paths, options = {}) {
|
|
31
31
|
const store = new CohortStateStore(dataDir);
|
|
32
32
|
const discovered = await discoverCleanupInputs(dataDir, store, options);
|
|
33
33
|
const transactionStore = options.transactionStore ?? new UpdateTransactionStore(dataDir);
|
|
34
|
-
await store.reconcileRetention(async () => await protectionInputs(
|
|
34
|
+
await store.reconcileRetention(async () => await protectionInputs(transactionStore, options), discovered.orphans);
|
|
35
35
|
for (const diagnostic of discovered.diagnostics.slice(0, 16)) {
|
|
36
36
|
await store.recordCleanupFailure(diagnostic.releaseId, diagnostic.stage, diagnostic.error);
|
|
37
37
|
}
|
|
@@ -42,7 +42,7 @@ export async function runBoundedReleaseCleanup(dataDir, paths, options = {}) {
|
|
|
42
42
|
const now = options.now ?? Date.now;
|
|
43
43
|
const limits = normalizeLimits(options.limits);
|
|
44
44
|
const { store, discovered } = await prepareReleaseCleanup(dataDir, paths, options);
|
|
45
|
-
// Performance: The physical-work allowance begins after discovery
|
|
45
|
+
// Performance: The physical-work allowance begins after discovery and the
|
|
46
46
|
// durable reconciliation write. A slow preparation phase must not starve every worker invocation.
|
|
47
47
|
const startedAt = now();
|
|
48
48
|
const initial = await store.read();
|
|
@@ -67,7 +67,7 @@ export async function runBoundedReleaseCleanup(dataDir, paths, options = {}) {
|
|
|
67
67
|
pendingOffset += size;
|
|
68
68
|
maximum -= size;
|
|
69
69
|
attempted += batch.length;
|
|
70
|
-
const results = await Promise.all(batch.map(async (disposition) => await collectDisposition(store, dataDir,
|
|
70
|
+
const results = await Promise.all(batch.map(async (disposition) => await collectDisposition(store, dataDir, disposition, options)));
|
|
71
71
|
completed += results.filter(Boolean).length;
|
|
72
72
|
guaranteed = false;
|
|
73
73
|
}
|
|
@@ -78,7 +78,7 @@ export async function runBoundedReleaseCleanup(dataDir, paths, options = {}) {
|
|
|
78
78
|
maximum -= 1;
|
|
79
79
|
const certificationId = certificationReleaseId(artifact);
|
|
80
80
|
if (certificationId !== null) {
|
|
81
|
-
const inputs = await protectionInputs(
|
|
81
|
+
const inputs = await protectionInputs(transactionStore, options);
|
|
82
82
|
if (isProtectedDetachedRelease(await store.read(), inputs, certificationId))
|
|
83
83
|
continue;
|
|
84
84
|
}
|
|
@@ -137,7 +137,7 @@ export async function scheduleReleaseCleanup(dataDir, paths, options = {}) {
|
|
|
137
137
|
...process.env,
|
|
138
138
|
[PRODUCT_IDENTITY.environment.dataDir]: dataDir,
|
|
139
139
|
[PRODUCT_IDENTITY.environment.runtimeDir]: paths.runtimeDir,
|
|
140
|
-
[
|
|
140
|
+
[WORKER_KEEP_ENV]: JSON.stringify(ownReleaseIds(options)),
|
|
141
141
|
[WORKER_RUN_ID_ENV]: runId,
|
|
142
142
|
};
|
|
143
143
|
try {
|
|
@@ -158,7 +158,7 @@ export async function runReleaseCleanupWorker(environment = process.env, workerO
|
|
|
158
158
|
const sleep = workerOptions.sleep ?? (async (durationMs) => await new Promise(resolvePromise => setTimeout(resolvePromise, durationMs)));
|
|
159
159
|
const cleanupOptions = {
|
|
160
160
|
...workerOptions.cleanup,
|
|
161
|
-
|
|
161
|
+
ownReleaseIds: workerOptions.cleanup?.ownReleaseIds ?? parseWorkerKeep(environment[WORKER_KEEP_ENV]),
|
|
162
162
|
};
|
|
163
163
|
const summary = { batches: 0, attempted: 0, completed: 0, remaining: Object.keys((await store.read()).cleanup.pending).length };
|
|
164
164
|
let lease = null;
|
|
@@ -227,24 +227,10 @@ export async function runReleaseCleanupWorker(environment = process.env, workerO
|
|
|
227
227
|
durationMs: Math.max(0, now() - startedAt),
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
|
-
|
|
231
|
-
export async function collectRelease(store, dataDir, releaseId, externalReferences, paths) {
|
|
232
|
-
const holds = externalReferences.map(referenced => ({ authority: "migration", releaseId: referenced }));
|
|
233
|
-
const state = await store.read();
|
|
234
|
-
if (!state.releases[releaseId])
|
|
235
|
-
throw new Error(`unknown release ${releaseId}`);
|
|
236
|
-
await store.reconcileRetention(async () => ({ ...(await protectionInputs(dataDir, paths, new UpdateTransactionStore(dataDir), holds)) }));
|
|
237
|
-
const disposition = (await store.read()).cleanup.pending[releaseId];
|
|
238
|
-
if (!disposition)
|
|
239
|
-
throw new Error(`release ${releaseId} is still referenced and cannot be collected`);
|
|
240
|
-
const removed = await collectDisposition(store, dataDir, paths, disposition, { externalHolds: holds, limits: { maxItems: 1 } });
|
|
241
|
-
if (!removed)
|
|
242
|
-
throw new Error(`release ${releaseId} could not be collected`);
|
|
243
|
-
}
|
|
244
|
-
async function collectDisposition(store, dataDir, paths, disposition, options) {
|
|
230
|
+
async function collectDisposition(store, dataDir, disposition, options) {
|
|
245
231
|
const releaseId = disposition.release.releaseId;
|
|
246
232
|
try {
|
|
247
|
-
const inputs = await protectionInputs(
|
|
233
|
+
const inputs = await protectionInputs(options.transactionStore ?? new UpdateTransactionStore(dataDir), options);
|
|
248
234
|
const current = await store.read();
|
|
249
235
|
if (isProtectedDetachedRelease(current, inputs, releaseId))
|
|
250
236
|
return false;
|
|
@@ -285,67 +271,30 @@ async function collectDisposition(store, dataDir, paths, disposition, options) {
|
|
|
285
271
|
function isProtectedDetachedRelease(state, inputs, releaseId) {
|
|
286
272
|
const selected = [state.references.active, state.references.pending, state.references.approved, state.references.rollback]
|
|
287
273
|
.some(reference => reference === releaseId);
|
|
274
|
+
// Concurrency: a launch may have recorded the same release again after it was detached.
|
|
288
275
|
return selected
|
|
289
|
-
||
|
|
290
|
-
|| (inputs.
|
|
276
|
+
|| state.releases[releaseId] !== undefined
|
|
277
|
+
|| (inputs.ownReleaseIds ?? []).includes(releaseId)
|
|
291
278
|
|| (inputs.transaction?.status === "active" && inputs.transaction.priorActiveReleaseId === releaseId);
|
|
292
279
|
}
|
|
293
|
-
async function protectionInputs(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
transactionStore.read(),
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
280
|
+
async function protectionInputs(transactionStore, options) {
|
|
281
|
+
return {
|
|
282
|
+
ownReleaseIds: ownReleaseIds(options),
|
|
283
|
+
transaction: transactionReference(await transactionStore.read()),
|
|
284
|
+
now: (options.wallClock ?? Date.now)(),
|
|
285
|
+
...(options.retentionMs === undefined ? {} : { retentionMs: options.retentionMs }),
|
|
286
|
+
};
|
|
300
287
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
...Object.values(state.releases),
|
|
310
|
-
...Object.values(state.cleanup.pending).map(disposition => disposition.release),
|
|
311
|
-
];
|
|
312
|
-
const preferred = [state.references.active, state.references.rollback]
|
|
313
|
-
.flatMap(id => id && state.releases[id] ? [state.releases[id].releaseRoot] : []);
|
|
314
|
-
const roots = [...new Set([...preferred, ...Object.values(state.releases).map(record => record.releaseRoot)])];
|
|
315
|
-
const report = await (reader ?? ((directory, releaseRoots) => readResidentReleaseHolds({ dataDir: directory, releaseRoots })))(dataDir, roots);
|
|
316
|
-
const everything = () => [...new Set(records.map(record => record.releaseId))].map(releaseId => ({ authority: "resident", releaseId }));
|
|
317
|
-
if (!report.complete)
|
|
318
|
-
return everything();
|
|
319
|
-
if (report.releaseRoots.length === 0)
|
|
288
|
+
function ownReleaseIds(options) {
|
|
289
|
+
if (options.ownReleaseIds !== undefined)
|
|
290
|
+
return options.ownReleaseIds;
|
|
291
|
+
try {
|
|
292
|
+
const own = readLaunchContext(process.env).releaseId;
|
|
293
|
+
return own === undefined ? [] : [own];
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
320
296
|
return [];
|
|
321
|
-
|
|
322
|
-
const byRoot = new Map();
|
|
323
|
-
for (const record of records) {
|
|
324
|
-
const canonical = await realpath(record.releaseRoot).catch(() => record.releaseRoot);
|
|
325
|
-
byRoot.set(comparablePath(canonical), record.releaseId);
|
|
326
|
-
}
|
|
327
|
-
const directory = await realpath(resolve(dataDir, "releases")).catch(() => null);
|
|
328
|
-
if (directory === null)
|
|
329
|
-
return everything();
|
|
330
|
-
const store = comparablePath(directory);
|
|
331
|
-
const holds = new Set();
|
|
332
|
-
for (const root of report.releaseRoots) {
|
|
333
|
-
// Security: an unresolved live root may alias managed content; uncertainty must retain it.
|
|
334
|
-
const canonical = await realpath(root).catch(() => null);
|
|
335
|
-
if (canonical === null)
|
|
336
|
-
return everything();
|
|
337
|
-
const key = comparablePath(canonical);
|
|
338
|
-
const releaseId = byRoot.get(key);
|
|
339
|
-
if (releaseId)
|
|
340
|
-
holds.add(releaseId);
|
|
341
|
-
else if (key.startsWith(`${store}${sep}`))
|
|
342
|
-
return everything();
|
|
343
|
-
}
|
|
344
|
-
return [...holds].sort().map(releaseId => ({ authority: "resident", releaseId }));
|
|
345
|
-
}
|
|
346
|
-
function comparablePath(path) {
|
|
347
|
-
const absolute = resolve(path);
|
|
348
|
-
return process.platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
297
|
+
}
|
|
349
298
|
}
|
|
350
299
|
function transactionReference(transaction) {
|
|
351
300
|
return transaction === null ? null : { status: transaction.status, priorActiveReleaseId: transaction.priorActiveReleaseId };
|
|
@@ -779,25 +728,12 @@ async function readWorkerLease(path) {
|
|
|
779
728
|
return null;
|
|
780
729
|
}
|
|
781
730
|
}
|
|
782
|
-
function
|
|
783
|
-
try {
|
|
784
|
-
process.kill(pid, 0);
|
|
785
|
-
return true;
|
|
786
|
-
}
|
|
787
|
-
catch (error) {
|
|
788
|
-
return error instanceof Error && "code" in error && error.code === "EPERM";
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
function parseWorkerHolds(value) {
|
|
731
|
+
function parseWorkerKeep(value) {
|
|
792
732
|
if (!value)
|
|
793
733
|
return [];
|
|
794
734
|
try {
|
|
795
735
|
const parsed = JSON.parse(value);
|
|
796
|
-
|
|
797
|
-
return [];
|
|
798
|
-
return parsed.filter((hold) => Boolean(hold) && typeof hold === "object"
|
|
799
|
-
&& ["agent", "migration", "resident"].includes(hold.authority)
|
|
800
|
-
&& typeof hold.releaseId === "string");
|
|
736
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string" && id.length > 0) : [];
|
|
801
737
|
}
|
|
802
738
|
catch {
|
|
803
739
|
return [];
|
|
@@ -51,8 +51,8 @@ export declare function assertCertifiedFilesPresent(releaseRoot: string): Promis
|
|
|
51
51
|
export declare function repairMaterializedRelease(packageRoot: string, releaseRoot: string): Promise<MaterializedRelease>;
|
|
52
52
|
/**
|
|
53
53
|
* Load metadata for a release whose bytes were already certified by the
|
|
54
|
-
* current parent process or an authenticated
|
|
55
|
-
* establish
|
|
54
|
+
* current parent process or recorded by an authenticated certification. Callers must
|
|
55
|
+
* establish that precondition; untrusted releases require full
|
|
56
56
|
* verification.
|
|
57
57
|
*/
|
|
58
58
|
export declare function readCertifiedReleaseManifest(record: CertifiedReleaseRecord, selectedStoreRoot: string, options?: ReadCertifiedReleaseManifestOptions): Promise<MaterializedRelease>;
|