@timurproko/a1 0.2.7-dev.1252 → 0.2.7-dev.1264

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.
Files changed (296) hide show
  1. package/bin/ui.js +3 -3
  2. package/dist/app/session-shell/clipboard-diagnostics.d.ts +2 -2
  3. package/dist/app/session-shell/clipboard-image.d.ts +0 -1
  4. package/dist/app/session-shell/clipboard-image.js +1 -1
  5. package/dist/app/session-shell/dialog-coordinator.d.ts +6 -5
  6. package/dist/app/session-shell/dialog-coordinator.js +3 -4
  7. package/dist/app/session-shell/dock-chrome.d.ts +11 -6
  8. package/dist/app/session-shell/dock-chrome.js +5 -8
  9. package/dist/app/session-shell/editor-hyperlink-budget.d.ts +0 -2
  10. package/dist/app/session-shell/editor-hyperlink-budget.js +1 -1
  11. package/dist/app/session-shell/exit-notice.d.ts +2 -2
  12. package/dist/app/session-shell/exit-notice.js +1 -1
  13. package/dist/app/session-shell/extension-surface.d.ts +8 -7
  14. package/dist/app/session-shell/helper-pool.d.ts +3 -4
  15. package/dist/app/session-shell/helper-pool.js +1 -1
  16. package/dist/app/session-shell/image-preparation-client.d.ts +4 -3
  17. package/dist/app/session-shell/image-preparation.d.ts +0 -2
  18. package/dist/app/session-shell/image-preparation.js +2 -2
  19. package/dist/app/session-shell/image-source.d.ts +2 -3
  20. package/dist/app/session-shell/image-source.js +2 -2
  21. package/dist/app/session-shell/input-surface-switch.d.ts +9 -7
  22. package/dist/app/session-shell/input-surface-switch.js +1 -2
  23. package/dist/app/session-shell/login-interaction.d.ts +5 -4
  24. package/dist/app/session-shell/login-interaction.js +2 -3
  25. package/dist/app/session-shell/paste-executor.d.ts +4 -8
  26. package/dist/app/session-shell/paste-executor.js +2 -2
  27. package/dist/app/session-shell/paste-protocol.d.ts +2 -2
  28. package/dist/app/session-shell/path-chip-presentation.d.ts +0 -5
  29. package/dist/app/session-shell/path-chip-presentation.js +3 -3
  30. package/dist/app/session-shell/prompt-chips.d.ts +8 -7
  31. package/dist/app/session-shell/prompt-history-controller.d.ts +3 -3
  32. package/dist/app/session-shell/prompt-submission.d.ts +5 -2
  33. package/dist/app/session-shell/prompt-submission.js +13 -14
  34. package/dist/app/session-shell/quit-outro-effects.d.ts +3 -3
  35. package/dist/app/session-shell/quit-outro-effects.js +1 -4
  36. package/dist/app/session-shell/quit-outro.d.ts +9 -12
  37. package/dist/app/session-shell/quit-outro.js +11 -11
  38. package/dist/app/session-shell/resource-labels.d.ts +2 -0
  39. package/dist/app/session-shell/resource-labels.js +158 -0
  40. package/dist/app/session-shell/response-copy-protocol.d.ts +3 -2
  41. package/dist/app/session-shell/response-copy-transport.d.ts +2 -14
  42. package/dist/app/session-shell/response-copy-transport.js +1 -1
  43. package/dist/app/session-shell/session-lifecycle.d.ts +2 -1
  44. package/dist/app/session-shell/session-prompt-history.d.ts +29 -0
  45. package/dist/app/session-shell/session-prompt-history.js +80 -0
  46. package/dist/app/session-shell/session-selectors.d.ts +46 -0
  47. package/dist/app/session-shell/session-selectors.js +269 -0
  48. package/dist/app/session-shell/session-shell-root.d.ts +76 -113
  49. package/dist/app/session-shell/session-shell-root.js +103 -329
  50. package/dist/app/session-shell/session-shell.d.ts +14 -37
  51. package/dist/app/session-shell/session-shell.js +177 -612
  52. package/dist/app/session-shell/session-viewport-controller.d.ts +9 -16
  53. package/dist/app/session-shell/session-viewport-controller.js +42 -320
  54. package/dist/app/session-shell/settings-bindings.d.ts +25 -3
  55. package/dist/app/session-shell/settings-bindings.js +26 -2
  56. package/dist/app/session-shell/share-operation.d.ts +3 -3
  57. package/dist/app/session-shell/share-operation.js +4 -6
  58. package/dist/app/session-shell/shell-clipboard.d.ts +59 -0
  59. package/dist/app/session-shell/shell-clipboard.js +119 -0
  60. package/dist/app/session-shell/shell-editor-factory.d.ts +8 -4
  61. package/dist/app/session-shell/shell-editor-factory.js +13 -15
  62. package/dist/app/session-shell/shell-host.d.ts +16 -17
  63. package/dist/app/session-shell/shell-host.js +18 -19
  64. package/dist/app/session-shell/shell-layout.d.ts +2 -2
  65. package/dist/app/session-shell/shell-prompt-suggestions.d.ts +26 -0
  66. package/dist/app/session-shell/shell-prompt-suggestions.js +48 -0
  67. package/dist/app/session-shell/suggestion-surface.d.ts +1 -6
  68. package/dist/app/session-shell/suggestion-surface.js +1 -1
  69. package/dist/app/session-shell/system-clipboard.d.ts +2 -14
  70. package/dist/app/session-shell/system-clipboard.js +2 -7
  71. package/dist/app/session-shell/transcript-document.d.ts +11 -8
  72. package/dist/app/session-shell/transcript-document.js +13 -14
  73. package/dist/app/session-shell/viewport-layout.d.ts +2 -2
  74. package/dist/app/session-shell/viewport-pointer.d.ts +83 -0
  75. package/dist/app/session-shell/viewport-pointer.js +361 -0
  76. package/dist/app/session-shell/workflow-output.d.ts +5 -3
  77. package/dist/app/session-shell/workflow-output.js +13 -15
  78. package/dist/cli/package-messages.d.ts +0 -1
  79. package/dist/cli/package-messages.js +1 -1
  80. package/dist/cli/session-context.d.ts +1 -1
  81. package/dist/cli/uninstall.d.ts +3 -2
  82. package/dist/composition/owned-settings.d.ts +2 -1
  83. package/dist/composition/owned-settings.js +0 -3
  84. package/dist/composition/owned-ui.d.ts +1 -1
  85. package/dist/composition/owned-ui.js +77 -73
  86. package/dist/composition/reference-selection-options.d.ts +1 -1
  87. package/dist/composition/reference-selection-options.js +1 -1
  88. package/dist/composition/session-runtime-registry.d.ts +2 -1
  89. package/dist/composition/settings-route-host.js +3 -10
  90. package/dist/composition/settings-search-input.d.ts +2 -1
  91. package/dist/composition/startup-route.d.ts +2 -2
  92. package/dist/composition/startup-route.js +2 -2
  93. package/dist/contracts/owned-ui/extension-ui.d.ts +2 -1
  94. package/dist/contracts/owned-ui/index.d.ts +2 -1
  95. package/dist/contracts/owned-ui/index.js +1 -1
  96. package/dist/contracts/owned-ui/session-presenters.d.ts +3 -0
  97. package/dist/contracts/owned-ui/shell-components.d.ts +543 -0
  98. package/dist/contracts/owned-ui/validation.d.ts +1 -11
  99. package/dist/contracts/owned-ui/validation.js +8 -104
  100. package/dist/contracts/presentation/component.d.ts +17 -0
  101. package/dist/contracts/presentation/component.js +8 -0
  102. package/dist/contracts/presentation/index.d.ts +6 -15
  103. package/dist/contracts/presentation/index.js +2 -0
  104. package/dist/contracts/presentation/terminal.d.ts +284 -0
  105. package/dist/contracts/presentation/terminal.js +1 -0
  106. package/dist/contracts/presentation/theme.d.ts +46 -0
  107. package/dist/contracts/presentation/theme.js +1 -0
  108. package/dist/features/launch/development-launch.js +1 -1
  109. package/dist/features/launch/runtime-selection.d.ts +2 -2
  110. package/dist/features/launch/runtime-selection.js +2 -2
  111. package/dist/features/owned-ui/project-trust-prompt.d.ts +2 -2
  112. package/dist/features/owned-ui/project-trust-prompt.js +1 -1
  113. package/dist/features/owned-ui/release-note-state.d.ts +2 -1
  114. package/dist/features/owned-ui/settings-app.js +49 -425
  115. package/dist/features/owned-ui/settings-edits.d.ts +31 -0
  116. package/dist/features/owned-ui/settings-edits.js +139 -0
  117. package/dist/features/owned-ui/settings-model-dialog.d.ts +41 -0
  118. package/dist/features/owned-ui/settings-model-dialog.js +194 -0
  119. package/dist/features/owned-ui/settings-scroll-rail.d.ts +29 -0
  120. package/dist/features/owned-ui/settings-scroll-rail.js +79 -0
  121. package/dist/features/owned-ui/settings-search-input.d.ts +2 -1
  122. package/dist/features/prompt-history/service.d.ts +3 -2
  123. package/dist/foundation/lifecycle/claim-gate.d.ts +2 -1
  124. package/dist/foundation/release/automatic-update.d.ts +5 -14
  125. package/dist/foundation/release/automatic-update.js +15 -22
  126. package/dist/foundation/release/bootstrap.js +4 -4
  127. package/dist/foundation/release/dependency-certification.d.ts +0 -1
  128. package/dist/foundation/release/dependency-certification.js +1 -1
  129. package/dist/foundation/release/dependency-layer.js +3 -3
  130. package/dist/foundation/release/early-accent.d.ts +2 -2
  131. package/dist/foundation/release/early-accent.js +1 -1
  132. package/dist/foundation/release/index.d.ts +2 -2
  133. package/dist/foundation/release/index.js +1 -1
  134. package/dist/foundation/release/latest-release.d.ts +3 -18
  135. package/dist/foundation/release/latest-release.js +11 -11
  136. package/dist/foundation/release/managed-path.d.ts +10 -0
  137. package/dist/foundation/release/managed-path.js +26 -0
  138. package/dist/foundation/release/ordinary-launch-selection.d.ts +1 -1
  139. package/dist/foundation/release/ordinary-launch-selection.js +1 -1
  140. package/dist/foundation/release/release-gc.d.ts +3 -3
  141. package/dist/foundation/release/release-gc.js +10 -12
  142. package/dist/foundation/release/{cohort-state.d.ts → release-state.d.ts} +23 -23
  143. package/dist/foundation/release/{cohort-state.js → release-state.js} +8 -8
  144. package/dist/foundation/release/restart-certification.js +3 -4
  145. package/dist/foundation/release/update-activation.js +3 -3
  146. package/dist/foundation/release/update-execution-lease.d.ts +2 -3
  147. package/dist/foundation/release/update-execution-lease.js +2 -8
  148. package/dist/foundation/release/update-installer.d.ts +45 -0
  149. package/dist/foundation/release/update-installer.js +57 -0
  150. package/dist/foundation/release/update-launch.d.ts +2 -2
  151. package/dist/foundation/release/update-recovery.js +2 -9
  152. package/dist/foundation/release/update.d.ts +4 -25
  153. package/dist/foundation/release/update.js +164 -183
  154. package/dist/foundation/startup/startup-budget.d.ts +5 -5
  155. package/dist/foundation/startup/startup-budget.js +2 -2
  156. package/dist/integrations/pi/components/bracketed-paste.d.ts +33 -0
  157. package/dist/integrations/pi/components/bracketed-paste.js +123 -0
  158. package/dist/integrations/pi/components/editor-interaction.d.ts +4 -12
  159. package/dist/integrations/pi/components/index.d.ts +15 -9
  160. package/dist/integrations/pi/components/index.js +9 -5
  161. package/dist/integrations/pi/components/lazy-selectors.d.ts +2 -10
  162. package/dist/integrations/pi/components/lazy-selectors.js +1 -1
  163. package/dist/integrations/pi/components/modal-frame.d.ts +5 -22
  164. package/dist/integrations/pi/components/modal-frame.js +3 -23
  165. package/dist/integrations/pi/components/owned-editor-ux.d.ts +4 -3
  166. package/dist/integrations/pi/components/owned-editor-ux.js +46 -140
  167. package/dist/integrations/pi/components/prompt-input-port.d.ts +2 -19
  168. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -1
  169. package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +3 -2
  170. package/dist/integrations/pi/components/shell-footer-status.d.ts +2 -2
  171. package/dist/integrations/pi/components/shell-footer-status.js +3 -2
  172. package/dist/integrations/pi/components/shell-presenters-info.d.ts +6 -5
  173. package/dist/integrations/pi/components/shell-presenters-info.js +2 -1
  174. package/dist/integrations/pi/components/shell-session-info-reference.d.ts +2 -1
  175. package/dist/integrations/pi/components/shell-shared-facade.d.ts +33 -227
  176. package/dist/integrations/pi/components/shell-shared-facade.js +8 -1
  177. package/dist/integrations/pi/components/skills-command.d.ts +1 -9
  178. package/dist/integrations/pi/components/skills-command.js +5 -5
  179. package/dist/integrations/pi/components/theme.d.ts +9 -2
  180. package/dist/integrations/pi/components/theme.js +17 -2
  181. package/dist/integrations/pi/components/thinking-selector-dialog.d.ts +2 -1
  182. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +2 -2
  183. package/dist/integrations/pi/engine/adapter.d.ts +4 -13
  184. package/dist/integrations/pi/engine/adapter.js +9 -61
  185. package/dist/integrations/pi/engine/changelog.d.ts +2 -2
  186. package/dist/integrations/pi/engine/changelog.js +3 -3
  187. package/dist/integrations/pi/engine/compaction-progress.d.ts +2 -3
  188. package/dist/integrations/pi/engine/compaction-progress.js +1 -1
  189. package/dist/integrations/pi/engine/conformance.d.ts +2 -1
  190. package/dist/integrations/pi/engine/default-model-setting.d.ts +0 -2
  191. package/dist/integrations/pi/engine/default-model-setting.js +1 -2
  192. package/dist/integrations/pi/engine/event-delivery.d.ts +2 -1
  193. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -1
  194. package/dist/integrations/pi/engine/host.js +3 -3
  195. package/dist/integrations/pi/engine/message-values.d.ts +0 -1
  196. package/dist/integrations/pi/engine/message-values.js +1 -1
  197. package/dist/integrations/pi/engine/pending-delivery.d.ts +0 -4
  198. package/dist/integrations/pi/engine/pending-delivery.js +3 -3
  199. package/dist/integrations/pi/engine/ports.d.ts +7 -1
  200. package/dist/integrations/pi/engine/ports.js +4 -0
  201. package/dist/integrations/pi/engine/project-trust-preflight.d.ts +2 -1
  202. package/dist/integrations/pi/engine/prompt-suggestions.d.ts +3 -2
  203. package/dist/integrations/pi/engine/provider-authentication.d.ts +1 -1
  204. package/dist/integrations/pi/engine/public-main-entry.d.ts +1 -5
  205. package/dist/integrations/pi/engine/public-main-entry.js +1 -1
  206. package/dist/integrations/pi/engine/repository-metadata.d.ts +49 -0
  207. package/dist/integrations/pi/engine/repository-metadata.js +189 -0
  208. package/dist/integrations/pi/engine/repository-pr-rest.d.ts +1 -9
  209. package/dist/integrations/pi/engine/repository-pr-rest.js +2 -2
  210. package/dist/integrations/pi/engine/repository-pr.d.ts +1 -3
  211. package/dist/integrations/pi/engine/repository-pr.js +1 -1
  212. package/dist/integrations/pi/engine/resource-catalog.d.ts +2 -1
  213. package/dist/integrations/pi/engine/session-integration.d.ts +1 -1
  214. package/dist/integrations/pi/engine/session-runtime.d.ts +7 -12
  215. package/dist/integrations/pi/engine/session-runtime.js +21 -178
  216. package/dist/integrations/pi/engine/settings-bridge.d.ts +0 -2
  217. package/dist/integrations/pi/engine/settings-bridge.js +1 -1
  218. package/dist/integrations/pi/engine/settings-port.d.ts +3 -2
  219. package/dist/integrations/pi/engine/transcript-projection.d.ts +2 -1
  220. package/dist/integrations/pi/engine/view-state.d.ts +21 -2
  221. package/dist/integrations/pi/engine/view-state.js +129 -1
  222. package/dist/integrations/pi/engine/workflow-contexts.d.ts +1 -1
  223. package/dist/integrations/pi/engine/workflow-runner.d.ts +1 -2
  224. package/dist/integrations/pi/engine/workflow-runner.js +254 -365
  225. package/dist/integrations/pi/engine/workflow-share.d.ts +9 -0
  226. package/dist/integrations/pi/engine/workflow-share.js +168 -0
  227. package/dist/integrations/pi/engine/workflow-support.d.ts +0 -20
  228. package/dist/integrations/pi/engine/workflow-support.js +4 -65
  229. package/dist/integrations/pi/engine/workflows.d.ts +5 -5
  230. package/dist/integrations/pi/session-presenters/components.d.ts +3 -0
  231. package/dist/integrations/pi/session-presenters/components.js +75 -0
  232. package/dist/integrations/pi/session-presenters/index.d.ts +1 -0
  233. package/dist/integrations/pi/session-presenters/index.js +1 -0
  234. package/dist/integrations/pi/session-presenters/presentation.d.ts +3 -0
  235. package/dist/integrations/pi/session-presenters/presentation.js +10 -0
  236. package/dist/integrations/pi/session-presenters/presenters.d.ts +2 -1
  237. package/dist/integrations/pi/session-presenters/presenters.js +3 -1
  238. package/dist/integrations/pi/tui-runtime/adapter.d.ts +9 -19
  239. package/dist/integrations/pi/tui-runtime/adapter.js +56 -174
  240. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +9 -44
  241. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  242. package/dist/integrations/pi/tui-runtime/index.js +1 -0
  243. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +4 -6
  244. package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +4 -10
  245. package/dist/integrations/pi/tui-runtime/overlay-geometry.js +3 -9
  246. package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +2 -2
  247. package/dist/integrations/pi/tui-runtime/runtime-factory.d.ts +3 -0
  248. package/dist/integrations/pi/tui-runtime/runtime-factory.js +11 -0
  249. package/dist/ui/components/index.d.ts +2 -2
  250. package/dist/ui/components/index.js +1 -1
  251. package/dist/ui/components/selection-copy.d.ts +0 -1
  252. package/dist/ui/components/selection-copy.js +0 -12
  253. package/dist/ui/components/theme.d.ts +4 -19
  254. package/dist/ui/components/theme.js +6 -0
  255. package/dist/ui/components/transcript-viewport-frame.d.ts +120 -0
  256. package/dist/ui/components/transcript-viewport-frame.js +314 -0
  257. package/dist/ui/components/transcript-viewport-types.d.ts +147 -0
  258. package/dist/ui/components/transcript-viewport-types.js +1 -0
  259. package/dist/ui/components/transcript-viewport.d.ts +2 -147
  260. package/dist/ui/components/transcript-viewport.js +87 -315
  261. package/dist/ui/settings/declarations.d.ts +2 -3
  262. package/dist/ui/settings/declarations.js +2 -3
  263. package/dist/ui/settings/early-accent.js +1 -1
  264. package/dist/ui/settings/index.d.ts +3 -5
  265. package/dist/ui/settings/index.js +2 -3
  266. package/dist/ui/settings/manager.d.ts +0 -4
  267. package/dist/ui/settings/manager.js +6 -62
  268. package/dist/ui/settings/resolution.d.ts +6 -18
  269. package/dist/ui/settings/resolution.js +4 -103
  270. package/dist/ui/settings/sections.d.ts +0 -4
  271. package/dist/ui/settings/sections.js +1 -1
  272. package/docs/architecture/boundaries.md +2 -2
  273. package/docs/architecture/internal-naming.md +2 -0
  274. package/docs/architecture/project-structure.md +4 -2
  275. package/docs/validation.md +1 -1
  276. package/package.json +3 -4
  277. package/dist/integrations/pi/components/components.d.ts +0 -4
  278. package/dist/integrations/pi/components/components.js +0 -48
  279. package/dist/integrations/pi/components/conformance.d.ts +0 -18
  280. package/dist/integrations/pi/components/conformance.js +0 -70
  281. package/dist/integrations/pi/components/shell-components.d.ts +0 -7
  282. package/dist/integrations/pi/components/shell-components.js +0 -7
  283. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +0 -33
  284. package/dist/integrations/pi/components/upstream/theme/theme-controller.js +0 -114
  285. package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -9
  286. package/dist/integrations/pi/engine/diagnostics-state.js +0 -34
  287. package/dist/integrations/pi/engine/usage-view.d.ts +0 -4
  288. package/dist/integrations/pi/engine/usage-view.js +0 -56
  289. package/dist/integrations/pi/tui-runtime/contracts.d.ts +0 -166
  290. package/dist/ui/settings/migrations.d.ts +0 -19
  291. package/dist/ui/settings/migrations.js +0 -225
  292. package/dist/ui/settings/progress-palette.generated.d.ts +0 -139
  293. package/dist/ui/settings/progress-palette.generated.js +0 -139
  294. /package/dist/{integrations/pi/tui-runtime/contracts.js → contracts/owned-ui/shell-components.js} +0 -0
  295. /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.d.ts +0 -0
  296. /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.js +0 -0
@@ -6,21 +6,22 @@ import { basename, dirname, resolve } from "node:path";
6
6
  import { valid as validSemver } from "semver";
7
7
  import { readLaunchContext } from "../launch-context/index.js";
8
8
  import { resolveProductPaths } from "../lifecycle/index.js";
9
- import { CohortStateStore } from "./cohort-state.js";
9
+ import { ReleaseStateStore } from "./release-state.js";
10
10
  import { processIsAlive } from "./process-liveness.js";
11
11
  import { isNewerRelease, releaseChannelOf } from "./latest-release.js";
12
12
  import { readCertifiedReleaseManifest, resolveReleaseEntryPoint } from "./release-store.js";
13
13
  import { acquireUpdateExecutionLease, readUpdateExecutionOwner } from "./update-execution-lease.js";
14
14
  import { UpdateTransactionStore } from "./update-transaction.js";
15
15
  import { runSelfUpdate, UPDATE_ALREADY_RUNNING_EXIT_CODE } from "./update.js";
16
- export const AUTOMATIC_UPDATE_STATE_SCHEMA = 1;
17
- export const AUTOMATIC_UPDATE_RETRY_MS = 24 * 60 * 60_000;
16
+ import { errorMessage, samePath } from "./managed-path.js";
17
+ const AUTOMATIC_UPDATE_STATE_SCHEMA = 1;
18
+ const AUTOMATIC_UPDATE_RETRY_MS = 24 * 60 * 60_000;
18
19
  const AUTOMATIC_UPDATE_STATE_FILENAME = "automatic-update.json";
19
20
  const MAX_STATE_BYTES = 16_384;
20
21
  const OBSERVER_POLL_MS = 250;
21
22
  const WORKER_START_GRACE_MS = 5_000;
22
- export const ACTIVE_RELEASE_FALLBACK_MS = 5_000;
23
- export class AutomaticUpdateStateStore {
23
+ const ACTIVE_RELEASE_FALLBACK_MS = 5_000;
24
+ class AutomaticUpdateStateStore {
24
25
  path;
25
26
  constructor(dataDir) { this.path = resolve(dataDir, AUTOMATIC_UPDATE_STATE_FILENAME); }
26
27
  async read() {
@@ -65,7 +66,7 @@ export class AutomaticUpdateStateStore {
65
66
  }
66
67
  }
67
68
  /** Read the approved active release only when this process executes an older release on that channel. */
68
- export async function readNewerActiveRelease(runningVersion, environment = process.env) {
69
+ async function readNewerActiveRelease(runningVersion, environment = process.env) {
69
70
  const channel = releaseChannelOf(runningVersion);
70
71
  if (channel === null)
71
72
  return null;
@@ -83,7 +84,7 @@ export function observeNewerActiveRelease(options) {
83
84
  if (releaseChannelOf(options.runningVersion) === null || options.signal?.aborted)
84
85
  return () => { };
85
86
  const paths = resolveProductPaths(options.environment ?? process.env);
86
- const store = new CohortStateStore(paths.dataDir);
87
+ const store = new ReleaseStateStore(paths.dataDir);
87
88
  let closed = false;
88
89
  let checking = false;
89
90
  let requested = false;
@@ -193,8 +194,8 @@ export async function requestAutomaticUpdate(options) {
193
194
  let worker = options.worker;
194
195
  if (worker === undefined) {
195
196
  const launch = readLaunchContext(environment, "release");
196
- const cohort = await new CohortStateStore(paths.dataDir).read();
197
- const record = launch.releaseId === undefined ? undefined : cohort.releases[launch.releaseId];
197
+ const releaseState = await new ReleaseStateStore(paths.dataDir).read();
198
+ const record = launch.releaseId === undefined ? undefined : releaseState.releases[launch.releaseId];
198
199
  if (!record || record.approval !== "approved" || record.releaseRoot !== launch.releaseRoot
199
200
  || record.contentDigest !== launch.releaseDigest)
200
201
  return null;
@@ -248,8 +249,8 @@ export async function runAutomaticUpdateWorker(argv, environment = process.env)
248
249
  let verified = false;
249
250
  try {
250
251
  const launch = readLaunchContext(environment, "release");
251
- const cohort = await new CohortStateStore(paths.dataDir).read();
252
- const record = launch.releaseId === undefined ? undefined : cohort.releases[launch.releaseId];
252
+ const releaseState = await new ReleaseStateStore(paths.dataDir).read();
253
+ const record = launch.releaseId === undefined ? undefined : releaseState.releases[launch.releaseId];
253
254
  if (record?.approval === "approved" && samePath(record.releaseRoot, launch.releaseRoot ?? "")
254
255
  && record.contentDigest === launch.releaseDigest) {
255
256
  const selected = await readCertifiedReleaseManifest(record, resolve(paths.dataDir, "releases"));
@@ -360,11 +361,11 @@ function activeNewerPackageVersion(active, runningVersion, channel, minimum) {
360
361
  ? active.packageVersion : null;
361
362
  }
362
363
  async function activeRelease(dataDir) {
363
- const cohort = await new CohortStateStore(dataDir).read();
364
- const activeId = cohort.references.active;
364
+ const releaseState = await new ReleaseStateStore(dataDir).read();
365
+ const activeId = releaseState.references.active;
365
366
  if (activeId === null)
366
367
  return null;
367
- const active = cohort.releases[activeId];
368
+ const active = releaseState.releases[activeId];
368
369
  return active?.approval === "approved" ? active : null;
369
370
  }
370
371
  function state(parsed, status, attemptedAt, installedVersion, failure) {
@@ -406,14 +407,6 @@ function validateState(value) {
406
407
  throw new Error("invalid automatic update state");
407
408
  }
408
409
  }
409
- function samePath(left, right) {
410
- const canonicalLeft = resolve(left);
411
- const canonicalRight = resolve(right);
412
- return process.platform === "win32"
413
- ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase()
414
- : canonicalLeft === canonicalRight;
415
- }
416
410
  function hasCode(error, code) {
417
411
  return error instanceof Error && "code" in error && error.code === code;
418
412
  }
419
- function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
@@ -4,7 +4,7 @@ import { deliverExitNotice, restoreAfterOwnedExit } from "../terminal-cleanup/in
4
4
  import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
5
5
  import { resolve } from "node:path";
6
6
  import { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
7
- import { CohortStateStore } from "./cohort-state.js";
7
+ import { ReleaseStateStore } from "./release-state.js";
8
8
  import { assertLaunchProfileId, resolveProductPaths, sessionSelectionArguments } from "../lifecycle/index.js";
9
9
  import { UpdateTransactionStore } from "./update-transaction.js";
10
10
  import { selectUpdateLaunchRelease } from "./update-launch.js";
@@ -39,7 +39,7 @@ async function runBootstrapAttempt(options, retriesRemaining) {
39
39
  output.write(`${PRODUCT_TEXT.diagnostic("active release changed repeatedly during startup; launch could not converge")}\n`);
40
40
  return 1;
41
41
  };
42
- const stateStore = new CohortStateStore(paths.dataDir);
42
+ const stateStore = new ReleaseStateStore(paths.dataDir);
43
43
  let state = await stateStore.read();
44
44
  const launchDuringUpdate = async () => {
45
45
  // Concurrency: read the journal before touching npm's mutable tree, including package.json.
@@ -55,7 +55,7 @@ async function runBootstrapAttempt(options, retriesRemaining) {
55
55
  const duringUpdate = await launchDuringUpdate();
56
56
  if (duringUpdate !== null)
57
57
  return duringUpdate;
58
- // Performance: reconciliation is serialized by cohort state, but launch never awaits a physical
58
+ // Performance: reconciliation is serialized by the release state lock, but launch never awaits a physical
59
59
  // backlog. The scheduler commits a plan and starts a detached bounded worker.
60
60
  const scheduleMaintenance = options.scheduleMaintenance ?? scheduleReleaseCleanup;
61
61
  void scheduleMaintenance(paths.dataDir, paths).catch(() => { });
@@ -149,7 +149,7 @@ async function runBootstrapAttempt(options, retriesRemaining) {
149
149
  return await launchSelected(candidate);
150
150
  }
151
151
  /**
152
- * Start the retained active cohort when the installed payload cannot be taken. The
152
+ * Start the retained active release when the installed payload cannot be taken. The
153
153
  * release already carries certified evidence, so this reuses it rather than
154
154
  * certifying anything new, and reports no selection when there is nothing safe
155
155
  * to fall back to.
@@ -1,4 +1,3 @@
1
- export declare const DEPENDENCY_CERTIFICATIONS_DIRECTORY = "dependency-certifications";
2
1
  type LayerIdentity = {
3
2
  readonly layerId: string;
4
3
  readonly contentDigest: string;
@@ -3,7 +3,7 @@ import { chmod, lstat, mkdir, readFile, readdir, realpath, rename, rm, writeFile
3
3
  import { basename, dirname, resolve } from "node:path";
4
4
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
5
5
  import { immutablePlatformPolicy } from "./immutable-platform.js";
6
- export const DEPENDENCY_CERTIFICATIONS_DIRECTORY = "dependency-certifications";
6
+ const DEPENDENCY_CERTIFICATIONS_DIRECTORY = "dependency-certifications";
7
7
  /** Derive the canonical record path without accepting path components as layer identities. */
8
8
  export function dependencyLayerCertificationPath(dataDir, layerId) {
9
9
  assertLayerId(layerId);
@@ -1,12 +1,13 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { chmod, lstat, mkdir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
3
- import { dirname, posix, relative, resolve, sep } from "node:path";
3
+ import { dirname, posix, resolve, sep } from "node:path";
4
4
  import { mapWithConcurrency } from "./concurrency.js";
5
5
  import { assertImmutableFileMode } from "./immutable-platform.js";
6
6
  import { readDependencyCertification, writeDependencyCertification as writeLayerCertification } from "./dependency-certification.js";
7
7
  export { dependencyLayerCertificationPath, legacyDependencyLayerCertificationPath } from "./dependency-certification.js";
8
8
  import { digestManifestFiles, releaseFileIdentity, resolveWithin } from "./release.js";
9
9
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
10
+ import { isDirectChild } from "./managed-path.js";
10
11
  const LAYER_IO_CONCURRENCY = 32;
11
12
  export const DEPENDENCY_LAYER_SCHEMA = PRODUCT_IDENTITY.evidence.dependencyLayerSchema;
12
13
  export const DEPENDENCY_LAYER_MANIFEST = "dependency-layer-manifest.json";
@@ -460,7 +461,6 @@ function isKnownRuntimePath(path) {
460
461
  }
461
462
  function isJavaScriptModule(path) { return /\.(?:js|mjs|cjs)$/.test(path); }
462
463
  function assertDirectChild(parent, child) {
463
- const path = relative(parent, child);
464
- if (path.length === 0 || path === ".." || path.startsWith(`..${sep}`) || path.includes(sep))
464
+ if (!isDirectChild(parent, child))
465
465
  throw new Error(`dependency layer escapes managed storage: ${child}`);
466
466
  }
@@ -1,6 +1,6 @@
1
1
  type UiAccentColor = "blue" | "purple" | "cyan" | "green" | "orange" | "pink";
2
- export type EarlyAccentAppearance = "dark" | "light";
3
- export type EarlyAccentMode = "truecolor" | "256color";
2
+ type EarlyAccentAppearance = "dark" | "light";
3
+ type EarlyAccentMode = "truecolor" | "256color";
4
4
  /** Read only global profile data, never project settings or the interactive resource pipeline. */
5
5
  export declare function resolveEarlyAccentColor(environment?: NodeJS.ProcessEnv, home?: () => string): UiAccentColor;
6
6
  export declare function earlyAccentPalette(color: UiAccentColor, appearance?: EarlyAccentAppearance, mode?: EarlyAccentMode): {
@@ -2,7 +2,7 @@ import { readFileSync, statSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { isAbsolute, join } from "node:path";
4
4
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
5
- import { SHARED_PROGRESS_PALETTE } from "./progress-palette.generated.js";
5
+ import { SHARED_PROGRESS_PALETTE } from "../../contracts/presentation/index.js";
6
6
  const MAX_SETTINGS_BYTES = 256 * 1024;
7
7
  /** Read only global profile data, never project settings or the interactive resource pipeline. */
8
8
  export function resolveEarlyAccentColor(environment = process.env, home = homedir) {
@@ -1,8 +1,8 @@
1
1
  export { certifyMaterializedRelease, recordParentCertifiedRelease, releaseEnvironment, runBootstrap, } from "./bootstrap.js";
2
2
  export type { BootstrapOptions } from "./bootstrap.js";
3
3
  export { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.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";
4
+ export { ReleaseStateStore, RELEASE_STATE_SCHEMA, RELEASE_RETENTION_MS, emptyState, planProtectedReleases, withinRetention } from "./release-state.js";
5
+ export type { ActiveReleaseTransactionReference, ReleaseState, OrphanReleaseDisposition, ProtectedReleaseInputs, ProtectedReleasePlan, ReleaseApproval, ReleaseCleanupDiagnostic, ReleaseCleanupDisposition, ReleaseCleanupStage, ReleaseCleanupState, ReleaseCleanupWorkerRun, ReleaseCleanupWorkerStatus, ReleaseCleanupWorkerSummary, ReleaseRecord, ReleaseReferences, ReleaseRetentionReconciliation, } from "./release-state.js";
6
6
  export { DEPENDENCY_LAYER_MANIFEST, DEPENDENCY_LAYER_SCHEMA, RUNTIME_PAYLOAD_INVENTORY, dependencyLayerCertificationPath, dependencyReference, generateDependencyRuntimePayload, legacyDependencyLayerCertificationPath, materializeDependencyLayer, readCertifiedDependencyLayer, selectDependencyRuntimePayload, selectPublishedDependencyRuntimePayload, verifyDependencyLayer, } from "./dependency-layer.js";
7
7
  export type { DependencyLayerIdentity, DependencyLayerOperationEvent, DependencyLayerReference, GeneratedRuntimePayload, MaterializeDependencyLayerOptions, MaterializedDependencyLayer, PublishedRuntimeFileClassification, PublishedRuntimePayload, ReadCertifiedDependencyLayerOptions, RuntimePayloadExclusion, RuntimePayloadInventory, SelectedRuntimePayload, } from "./dependency-layer.js";
8
8
  export { processIsAlive } from "./process-liveness.js";
@@ -1,6 +1,6 @@
1
1
  export { certifyMaterializedRelease, recordParentCertifiedRelease, releaseEnvironment, runBootstrap, } from "./bootstrap.js";
2
2
  export { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
3
- export { CohortStateStore, RELEASE_COHORT_SCHEMA, RELEASE_RETENTION_MS, emptyState, planProtectedReleases, withinRetention } from "./cohort-state.js";
3
+ export { ReleaseStateStore, RELEASE_STATE_SCHEMA, RELEASE_RETENTION_MS, emptyState, planProtectedReleases, withinRetention } from "./release-state.js";
4
4
  export { DEPENDENCY_LAYER_MANIFEST, DEPENDENCY_LAYER_SCHEMA, RUNTIME_PAYLOAD_INVENTORY, dependencyLayerCertificationPath, dependencyReference, generateDependencyRuntimePayload, legacyDependencyLayerCertificationPath, materializeDependencyLayer, readCertifiedDependencyLayer, selectDependencyRuntimePayload, selectPublishedDependencyRuntimePayload, verifyDependencyLayer, } from "./dependency-layer.js";
5
5
  export { processIsAlive } from "./process-liveness.js";
6
6
  export { PRODUCT_PACKAGE_NAME, createReleaseIdentity, deriveReleaseIdentity, digestManifestFiles, discoverReleasePayload, packageRootFromModule, releaseFileIdentity, resolveWithin, } from "./release.js";
@@ -1,11 +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" | "no";
4
- export interface DistTagVersions {
5
- readonly release: string | null;
6
- readonly develop: string | null;
7
- readonly error: string | null;
8
- }
3
+ export type StartupUpdateMode = "auto" | "manual";
9
4
  export type RegistryFetcher = (url: string) => Promise<{
10
5
  readonly ok: boolean;
11
6
  readonly status: number;
@@ -19,14 +14,13 @@ export interface AvailableRelease {
19
14
  /** The GitHub Release page; development releases have none. */
20
15
  readonly changelogUrl: string | null;
21
16
  }
22
- export declare const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
23
17
  export declare const UPDATE_CHECK_INTERVAL_MS: number;
24
18
  /** One published version with the pull request its manifest records, when it records one. */
25
19
  export interface PublishedVersion {
26
20
  readonly version: string;
27
21
  readonly pullRequest: number | null;
28
22
  }
29
- export interface PublishedVersions {
23
+ interface PublishedVersions {
30
24
  readonly versions: readonly PublishedVersion[];
31
25
  readonly error: string | null;
32
26
  }
@@ -37,23 +31,14 @@ export interface PublishedVersions {
37
31
  export declare function releaseChannelOf(version: string): ReleaseChannel | null;
38
32
  /** True only when both versions are valid semver and the candidate sorts strictly above the current one. */
39
33
  export declare function isNewerRelease(candidate: string, current: string): boolean;
40
- export declare function distTagsUrl(registry?: string): string;
41
- /** Read `latest` (required) and `next` (optional) from a dist-tags object. */
42
- export declare function parseDistTags(metadata: unknown, source: string): DistTagVersions;
43
- export declare function queryRegistryDistTags(fetcher: RegistryFetcher, registry?: string): Promise<DistTagVersions>;
44
- export declare function packageDocumentUrl(registry?: string): string;
45
- /** The pull request a published or installed manifest records under `publication.pullRequest`, when valid. */
46
- export declare function recordedPullRequest(manifest: unknown): number | null;
47
34
  /**
48
35
  * Every published version with its recorded pull request, read from the registry's full package
49
36
  * document: its per-version manifests keep the publication metadata that version lists and the
50
37
  * abbreviated install document leave out.
51
38
  */
52
39
  export declare function queryPublishedVersions(fetcher: RegistryFetcher, registry?: string): Promise<PublishedVersions>;
53
- export declare function parsePublishedVersions(document: unknown): PublishedVersions;
54
40
  /** Forget the startup release check so the next interactive launch asks the registry again. */
55
41
  export declare function invalidateReleaseCheckCache(configDir: string): Promise<void>;
56
- export declare function unavailableDistTags(error: string): DistTagVersions;
57
42
  export declare function createRegistryFetcher(timeoutMs: number, signal?: AbortSignal): RegistryFetcher;
58
43
  export interface StartupReleaseCheckOptions {
59
44
  readonly runningVersion: string;
@@ -77,4 +62,4 @@ export declare function startupReleaseCheckSkipReason(options: StartupReleaseChe
77
62
  * answer replaces the cache. Every failure resolves to null: the notice is best-effort.
78
63
  */
79
64
  export declare function checkForNewerRelease(options: StartupReleaseCheckOptions): Promise<AvailableRelease | null>;
80
- export declare function availableRelease(channel: ReleaseChannel, version: string): AvailableRelease;
65
+ export {};
@@ -4,7 +4,8 @@ import { join } from "node:path";
4
4
  import { gt, prerelease, valid as validSemver } from "semver";
5
5
  import lockfile from "proper-lockfile";
6
6
  import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
7
- export const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
7
+ import { errorMessage } from "./managed-path.js";
8
+ const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
8
9
  export const UPDATE_CHECK_INTERVAL_MS = 15 * 60_000;
9
10
  const STARTUP_FETCH_TIMEOUT_MS = 3_000;
10
11
  const CACHE_FILENAME = "update-check.json";
@@ -30,11 +31,11 @@ export function isNewerRelease(candidate, current) {
30
31
  const right = validSemver(current);
31
32
  return left !== null && right !== null && gt(left, right);
32
33
  }
33
- export function distTagsUrl(registry = DEFAULT_NPM_REGISTRY) {
34
+ function distTagsUrl(registry = DEFAULT_NPM_REGISTRY) {
34
35
  return `${registry.replace(/\/+$/u, "")}/-/package/${encodeURIComponent(PRODUCT_TEXT.packageName)}/dist-tags`;
35
36
  }
36
37
  /** Read `latest` (required) and `next` (optional) from a dist-tags object. */
37
- export function parseDistTags(metadata, source) {
38
+ function parseDistTags(metadata, source) {
38
39
  if (typeof metadata !== "object" || metadata === null || Array.isArray(metadata)) {
39
40
  return unavailableDistTags(`${source} returned a non-object dist-tags value`);
40
41
  }
@@ -48,7 +49,7 @@ export function parseDistTags(metadata, source) {
48
49
  return unavailableDistTags(errorMessage(error));
49
50
  }
50
51
  }
51
- export async function queryRegistryDistTags(fetcher, registry) {
52
+ async function queryRegistryDistTags(fetcher, registry) {
52
53
  try {
53
54
  const response = await fetcher(distTagsUrl(registry));
54
55
  if (!response.ok)
@@ -59,11 +60,11 @@ export async function queryRegistryDistTags(fetcher, registry) {
59
60
  return unavailableDistTags(errorMessage(error));
60
61
  }
61
62
  }
62
- export function packageDocumentUrl(registry = DEFAULT_NPM_REGISTRY) {
63
+ function packageDocumentUrl(registry = DEFAULT_NPM_REGISTRY) {
63
64
  return `${registry.replace(/\/+$/u, "")}/${encodeURIComponent(PRODUCT_TEXT.packageName)}`;
64
65
  }
65
66
  /** The pull request a published or installed manifest records under `publication.pullRequest`, when valid. */
66
- export function recordedPullRequest(manifest) {
67
+ function recordedPullRequest(manifest) {
67
68
  if (typeof manifest !== "object" || manifest === null)
68
69
  return null;
69
70
  const publication = manifest.publication;
@@ -91,7 +92,7 @@ export async function queryPublishedVersions(fetcher, registry) {
91
92
  return { versions: [], error: errorMessage(error) };
92
93
  }
93
94
  }
94
- export function parsePublishedVersions(document) {
95
+ function parsePublishedVersions(document) {
95
96
  if (typeof document !== "object" || document === null || Array.isArray(document)) {
96
97
  return { versions: [], error: "registry returned a non-object package document" };
97
98
  }
@@ -108,7 +109,7 @@ export function parsePublishedVersions(document) {
108
109
  export async function invalidateReleaseCheckCache(configDir) {
109
110
  await withCacheLock(configDir, async () => { await rm(join(configDir, CACHE_FILENAME), { force: true }); });
110
111
  }
111
- export function unavailableDistTags(error) {
112
+ function unavailableDistTags(error) {
112
113
  return { release: null, develop: null, error };
113
114
  }
114
115
  export function createRegistryFetcher(timeoutMs, signal) {
@@ -126,7 +127,7 @@ export function startupReleaseCheckSkipReason(options) {
126
127
  return "ci";
127
128
  if (!options.interactive)
128
129
  return "not-interactive";
129
- if (options.settingMode === "no")
130
+ if (options.settingMode === "manual")
130
131
  return "disabled-by-setting";
131
132
  if (releaseChannelOf(options.runningVersion) === null)
132
133
  return "unpublished-version";
@@ -170,7 +171,7 @@ export async function checkForNewerRelease(options) {
170
171
  return null;
171
172
  }
172
173
  }
173
- export function availableRelease(channel, version) {
174
+ function availableRelease(channel, version) {
174
175
  return {
175
176
  channel,
176
177
  version,
@@ -255,4 +256,3 @@ function parseVersion(value, source) {
255
256
  throw new Error(`${source} did not provide a valid semantic version`);
256
257
  return parsed;
257
258
  }
258
- function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
@@ -0,0 +1,10 @@
1
+ /** Whether two paths name the same location; Windows paths compare without case. */
2
+ export declare function samePath(left: string, right: string): boolean;
3
+ /**
4
+ * Whether `child` is exactly one non-empty segment below `parent`.
5
+ * Invariant: release storage operations act only on such paths, never on the root itself, another drive, a nested descendant,
6
+ * or anything reached through `..`. `path.relative` already ignores case on Windows.
7
+ */
8
+ export declare function isDirectChild(parent: string, child: string): boolean;
9
+ /** The message of a thrown value, whatever was thrown. */
10
+ export declare function errorMessage(error: unknown): string;
@@ -0,0 +1,26 @@
1
+ import { isAbsolute, relative, resolve, sep } from "node:path";
2
+ /** Whether two paths name the same location; Windows paths compare without case. */
3
+ export function samePath(left, right) {
4
+ const canonicalLeft = resolve(left);
5
+ const canonicalRight = resolve(right);
6
+ return process.platform === "win32"
7
+ ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase()
8
+ : canonicalLeft === canonicalRight;
9
+ }
10
+ /**
11
+ * Whether `child` is exactly one non-empty segment below `parent`.
12
+ * Invariant: release storage operations act only on such paths, never on the root itself, another drive, a nested descendant,
13
+ * or anything reached through `..`. `path.relative` already ignores case on Windows.
14
+ */
15
+ export function isDirectChild(parent, child) {
16
+ const fromParent = relative(resolve(parent), resolve(child));
17
+ return fromParent.length > 0
18
+ && fromParent !== ".."
19
+ && !fromParent.startsWith(`..${sep}`)
20
+ && !isAbsolute(fromParent)
21
+ && !fromParent.includes(sep);
22
+ }
23
+ /** The message of a thrown value, whatever was thrown. */
24
+ export function errorMessage(error) {
25
+ return error instanceof Error ? error.message : String(error);
26
+ }
@@ -8,7 +8,7 @@ interface ApprovedOrdinaryLaunchRelease extends OrdinaryLaunchRelease {
8
8
  /**
9
9
  * Ordinary launch has no rollback authority: it may advance to its installed package, but an
10
10
  * older package installation must follow a newer approved active release instead of moving the
11
- * shared selector backward. Explicit update/rollback uses CohortStateStore.activate directly.
11
+ * shared selector backward. Explicit update/rollback uses ReleaseStateStore.activate directly.
12
12
  */
13
13
  export declare function selectOrdinaryLaunchReleaseId(candidate: OrdinaryLaunchRelease, active?: ApprovedOrdinaryLaunchRelease): string;
14
14
  export {};
@@ -2,7 +2,7 @@ import { compare, valid as validSemver } from "semver";
2
2
  /**
3
3
  * Ordinary launch has no rollback authority: it may advance to its installed package, but an
4
4
  * older package installation must follow a newer approved active release instead of moving the
5
- * shared selector backward. Explicit update/rollback uses CohortStateStore.activate directly.
5
+ * shared selector backward. Explicit update/rollback uses ReleaseStateStore.activate directly.
6
6
  */
7
7
  export function selectOrdinaryLaunchReleaseId(candidate, active) {
8
8
  if (!active || active.approval !== "approved")
@@ -1,5 +1,5 @@
1
1
  import { rename, rm } from "node:fs/promises";
2
- import { CohortStateStore, type OrphanReleaseDisposition } from "./cohort-state.js";
2
+ import { ReleaseStateStore, type OrphanReleaseDisposition } from "./release-state.js";
3
3
  import type { ProductPaths } from "../lifecycle/index.js";
4
4
  import { UpdateTransactionStore } from "./update-transaction.js";
5
5
  export interface ReleaseCleanupLimits {
@@ -58,11 +58,11 @@ interface DiscoveredCleanupInputs {
58
58
  }[];
59
59
  }
60
60
  /**
61
- * Reconcile age-based retention under the cohort-state lock and durably detach obsolete releases.
61
+ * Reconcile age-based retention under the release-state lock and durably detach obsolete releases.
62
62
  * This operation intentionally reads only manifests and directory metadata, never payload bytes.
63
63
  */
64
64
  export declare function prepareReleaseCleanup(dataDir: string, _paths?: ProductPaths, options?: ReleaseCleanupOptions): Promise<{
65
- readonly store: CohortStateStore;
65
+ readonly store: ReleaseStateStore;
66
66
  readonly discovered: DiscoveredCleanupInputs;
67
67
  }>;
68
68
  /** Run a bounded, restart-safe physical cleanup pass over detached releases and abandoned artifacts. */
@@ -1,9 +1,9 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { spawn } from "node:child_process";
3
3
  import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat } from "node:fs/promises";
4
- import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
+ import { dirname, resolve, sep } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
- import { CohortStateStore, } from "./cohort-state.js";
6
+ import { ReleaseStateStore, } from "./release-state.js";
7
7
  import { resolveProductPaths } from "../lifecycle/index.js";
8
8
  import { RELEASE_MANIFEST_FILENAME } from "./release-store.js";
9
9
  import { DEPENDENCY_LAYER_MANIFEST, readCertifiedDependencyLayer } from "./dependency-layer.js";
@@ -15,6 +15,7 @@ import { PRODUCT_IDENTITY } from "../../product-identity.js";
15
15
  import { collectCompileCaches, startupCompileCachePath } from "../startup/index.js";
16
16
  import { readLaunchContext } from "../launch-context/index.js";
17
17
  import { processIsAlive } from "./process-liveness.js";
18
+ import { errorMessage, isDirectChild } from "./managed-path.js";
18
19
  const DEFAULT_CANDIDATE_AGE_MS = 60 * 60 * 1_000;
19
20
  const DEFAULT_LIMITS = { maxItems: 8, maxDurationMs: 2_000, concurrency: 1 };
20
21
  const DEFAULT_WORKER_DURATION_MS = 10 * 60 * 1_000;
@@ -24,11 +25,11 @@ const WORKER_KEEP_ENV = "RELEASE_CLEANUP_KEEP";
24
25
  const WORKER_RUN_ID_ENV = "RELEASE_CLEANUP_RUN_ID";
25
26
  const WORKER_LEASE_FILENAME = "release-cleanup-worker.lock";
26
27
  /**
27
- * Reconcile age-based retention under the cohort-state lock and durably detach obsolete releases.
28
+ * Reconcile age-based retention under the release-state lock and durably detach obsolete releases.
28
29
  * This operation intentionally reads only manifests and directory metadata, never payload bytes.
29
30
  */
30
31
  export async function prepareReleaseCleanup(dataDir, _paths, options = {}) {
31
- const store = new CohortStateStore(dataDir);
32
+ const store = new ReleaseStateStore(dataDir);
32
33
  const discovered = await discoverCleanupInputs(dataDir, store, options);
33
34
  const transactionStore = options.transactionStore ?? new UpdateTransactionStore(dataDir);
34
35
  await store.reconcileRetention(async () => await protectionInputs(transactionStore, options), discovered.orphans);
@@ -152,7 +153,7 @@ export async function scheduleReleaseCleanup(dataDir, paths, options = {}) {
152
153
  /** Entry used by the private cleanup executable shipped in every immutable release. */
153
154
  export async function runReleaseCleanupWorker(environment = process.env, workerOptions = {}) {
154
155
  const paths = resolveProductPaths(environment);
155
- const store = new CohortStateStore(paths.dataDir);
156
+ const store = new ReleaseStateStore(paths.dataDir);
156
157
  const runId = environment[WORKER_RUN_ID_ENV] ?? randomUUID();
157
158
  const now = workerOptions.now ?? Date.now;
158
159
  const sleep = workerOptions.sleep ?? (async (durationMs) => await new Promise(resolvePromise => setTimeout(resolvePromise, durationMs)));
@@ -638,12 +639,6 @@ async function protectedCompileCachePaths(dataDir, state) {
638
639
  }
639
640
  return paths;
640
641
  }
641
- function assertDirectChild(parent, child) {
642
- const fromParent = relative(parent, child);
643
- if (fromParent.length === 0 || fromParent === ".." || fromParent.startsWith(`..${sep}`) || isAbsolute(fromParent) || fromParent.includes(sep)) {
644
- throw new Error(`cleanup path is not a direct child of its managed root: ${child}`);
645
- }
646
- }
647
642
  function normalizeLimits(input) {
648
643
  const limits = { ...DEFAULT_LIMITS, ...input };
649
644
  for (const [name, value] of Object.entries(limits)) {
@@ -748,4 +743,7 @@ function artifactName(path) { return path.split(sep).at(-1) ?? "artifact"; }
748
743
  function certificationReleaseId(path) {
749
744
  return /^certification-(.+)\.json$/.exec(artifactName(path))?.[1] ?? null;
750
745
  }
751
- function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
746
+ function assertDirectChild(parent, child) {
747
+ if (!isDirectChild(parent, child))
748
+ throw new Error(`cleanup path is not a direct child of its managed root: ${child}`);
749
+ }
@@ -1,5 +1,5 @@
1
1
  import type { MaterializedRelease } from "./release-store.js";
2
- export declare const RELEASE_COHORT_SCHEMA: string;
2
+ export declare const RELEASE_STATE_SCHEMA: string;
3
3
  /** How long a release stays on disk after its approval, so processes started from it keep their files. */
4
4
  export declare const RELEASE_RETENTION_MS: number;
5
5
  export type ReleaseApproval = "candidate" | "approved" | "rejected";
@@ -66,8 +66,8 @@ export interface ReleaseCleanupState {
66
66
  readonly diagnostics: readonly ReleaseCleanupDiagnostic[];
67
67
  readonly workerRuns: readonly ReleaseCleanupWorkerRun[];
68
68
  }
69
- export interface CohortState {
70
- readonly schema: typeof RELEASE_COHORT_SCHEMA;
69
+ export interface ReleaseState {
70
+ readonly schema: typeof RELEASE_STATE_SCHEMA;
71
71
  readonly revision: number;
72
72
  readonly releases: Readonly<Record<string, ReleaseRecord>>;
73
73
  readonly references: ReleaseReferences;
@@ -93,7 +93,7 @@ export interface OrphanReleaseDisposition {
93
93
  readonly trashPath?: string | null;
94
94
  }
95
95
  export interface ReleaseRetentionReconciliation {
96
- readonly state: CohortState;
96
+ readonly state: ReleaseState;
97
97
  readonly plan: ProtectedReleasePlan;
98
98
  readonly detachedReleaseIds: readonly string[];
99
99
  }
@@ -104,33 +104,33 @@ export interface ReleaseRetentionReconciliation {
104
104
  * Nothing asks which processes are running: a session that outlives the window and two updates
105
105
  * can lose its release files, which is the documented trade-off.
106
106
  */
107
- export declare function planProtectedReleases(state: CohortState, inputs?: ProtectedReleaseInputs): ProtectedReleasePlan;
107
+ export declare function planProtectedReleases(state: ReleaseState, inputs?: ProtectedReleaseInputs): ProtectedReleasePlan;
108
108
  /**
109
109
  * Whether a release is young enough to keep. An approved release counts from its approval; a
110
110
  * candidate still awaiting certification counts from its materialization so concurrent work is
111
111
  * not collected under it. A record without a readable timestamp is treated as old.
112
112
  */
113
113
  export declare function withinRetention(release: ReleaseRecord, now: number, retentionMs?: number): boolean;
114
- /** Serializes validated cohort-state revisions under a lock and commits each update atomically. */
115
- export declare class CohortStateStore {
114
+ /** Serializes validated release-state revisions under a lock and commits each update atomically. */
115
+ export declare class ReleaseStateStore {
116
116
  readonly path: string;
117
117
  constructor(dataDir: string);
118
- read(): Promise<CohortState>;
119
- update(operation: (current: CohortState) => CohortState | Promise<CohortState>): Promise<CohortState>;
120
- recordCandidate(release: MaterializedRelease): Promise<CohortState>;
121
- approve(releaseId: string, diagnosticsPath: string): Promise<CohortState>;
122
- activate(releaseId: string): Promise<CohortState>;
118
+ read(): Promise<ReleaseState>;
119
+ update(operation: (current: ReleaseState) => ReleaseState | Promise<ReleaseState>): Promise<ReleaseState>;
120
+ recordCandidate(release: MaterializedRelease): Promise<ReleaseState>;
121
+ approve(releaseId: string, diagnosticsPath: string): Promise<ReleaseState>;
122
+ activate(releaseId: string): Promise<ReleaseState>;
123
123
  /** Atomically advances ordinary launch without allowing an older installation to roll active state back. */
124
- activateForLaunch(releaseId: string, replaceUnlaunchableActiveId?: string): Promise<CohortState>;
125
- rollback(): Promise<CohortState>;
124
+ activateForLaunch(releaseId: string, replaceUnlaunchableActiveId?: string): Promise<ReleaseState>;
125
+ rollback(): Promise<ReleaseState>;
126
126
  /** Atomically replace legacy retention history and detach every currently collectible record. */
127
- reconcileRetention(resolveInputs: (current: CohortState) => ProtectedReleaseInputs | Promise<ProtectedReleaseInputs>, orphans?: readonly OrphanReleaseDisposition[]): Promise<ReleaseRetentionReconciliation>;
128
- markCleanupTrash(releaseId: string, trashPath: string): Promise<CohortState>;
129
- recordCleanupFailure(releaseId: string, stage: string, error: unknown): Promise<CohortState>;
130
- completeCleanup(releaseId: string): Promise<CohortState>;
131
- recordCleanupWorkerScheduled(runId: string): Promise<CohortState>;
132
- recordCleanupWorkerStarted(runId: string, pid: number): Promise<CohortState>;
133
- recordCleanupWorkerProgress(runId: string, summary: ReleaseCleanupWorkerSummary): Promise<CohortState>;
134
- recordCleanupWorkerFinished(runId: string, status: Exclude<ReleaseCleanupWorkerStatus, "scheduled" | "running">, summary: ReleaseCleanupWorkerSummary, error?: unknown): Promise<CohortState>;
127
+ reconcileRetention(resolveInputs: (current: ReleaseState) => ProtectedReleaseInputs | Promise<ProtectedReleaseInputs>, orphans?: readonly OrphanReleaseDisposition[]): Promise<ReleaseRetentionReconciliation>;
128
+ markCleanupTrash(releaseId: string, trashPath: string): Promise<ReleaseState>;
129
+ recordCleanupFailure(releaseId: string, stage: string, error: unknown): Promise<ReleaseState>;
130
+ completeCleanup(releaseId: string): Promise<ReleaseState>;
131
+ recordCleanupWorkerScheduled(runId: string): Promise<ReleaseState>;
132
+ recordCleanupWorkerStarted(runId: string, pid: number): Promise<ReleaseState>;
133
+ recordCleanupWorkerProgress(runId: string, summary: ReleaseCleanupWorkerSummary): Promise<ReleaseState>;
134
+ recordCleanupWorkerFinished(runId: string, status: Exclude<ReleaseCleanupWorkerStatus, "scheduled" | "running">, summary: ReleaseCleanupWorkerSummary, error?: unknown): Promise<ReleaseState>;
135
135
  }
136
- export declare function emptyState(): CohortState;
136
+ export declare function emptyState(): ReleaseState;