@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
@@ -3,7 +3,7 @@ import { mkdir, open, readFile, rename, rm, stat } from "node:fs/promises";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
5
5
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
6
- export const RELEASE_COHORT_SCHEMA = PRODUCT_IDENTITY.protocol.releaseCohortSchema;
6
+ export const RELEASE_STATE_SCHEMA = PRODUCT_IDENTITY.protocol.releaseCohortSchema;
7
7
  const RELEASE_ID_PATTERN = /^[0-9A-Za-z.+_-]+-[a-f0-9]{20}$/;
8
8
  /** How long a release stays on disk after its approval, so processes started from it keep their files. */
9
9
  export const RELEASE_RETENTION_MS = 7 * 24 * 60 * 60 * 1_000;
@@ -51,8 +51,8 @@ export function withinRetention(release, now, retentionMs = RELEASE_RETENTION_MS
51
51
  const at = stamp === null ? Number.NaN : Date.parse(stamp);
52
52
  return Number.isFinite(at) && now - at < retentionMs;
53
53
  }
54
- /** Serializes validated cohort-state revisions under a lock and commits each update atomically. */
55
- export class CohortStateStore {
54
+ /** Serializes validated release-state revisions under a lock and commits each update atomically. */
55
+ export class ReleaseStateStore {
56
56
  path;
57
57
  constructor(dataDir) {
58
58
  this.path = resolve(dataDir, "release-state.json");
@@ -317,7 +317,7 @@ export class CohortStateStore {
317
317
  }
318
318
  export function emptyState() {
319
319
  return {
320
- schema: RELEASE_COHORT_SCHEMA,
320
+ schema: RELEASE_STATE_SCHEMA,
321
321
  revision: 0,
322
322
  releases: {},
323
323
  references: { active: null, pending: null, approved: null, rollback: null, retention: [] },
@@ -430,11 +430,11 @@ function normalizeState(value) {
430
430
  };
431
431
  }
432
432
  function validateState(state) {
433
- if (!state || state.schema !== RELEASE_COHORT_SCHEMA || !Number.isSafeInteger(state.revision) || state.revision < 0
433
+ if (!state || state.schema !== RELEASE_STATE_SCHEMA || !Number.isSafeInteger(state.revision) || state.revision < 0
434
434
  || !state.releases || typeof state.releases !== "object" || !state.references || !Array.isArray(state.references.retention)
435
435
  || !state.cleanup || typeof state.cleanup.pending !== "object" || !Array.isArray(state.cleanup.diagnostics)
436
436
  || !Array.isArray(state.cleanup.workerRuns)) {
437
- throw new Error("invalid release cohort state");
437
+ throw new Error("invalid release state");
438
438
  }
439
439
  for (const run of state.cleanup.workerRuns) {
440
440
  if (!run || typeof run.runId !== "string" || run.runId.length === 0
@@ -469,9 +469,9 @@ function validateReleaseRecord(releaseId, release) {
469
469
  function validateTransition(current, next) {
470
470
  validateState(next);
471
471
  if (next.schema !== current.schema)
472
- throw new Error("release cohort schema cannot change during a state update");
472
+ throw new Error("release schema cannot change during a state update");
473
473
  if (next.revision !== current.revision)
474
- throw new Error("release cohort revision is controlled by the state store");
474
+ throw new Error("release revision is controlled by the state store");
475
475
  }
476
476
  function boundedError(error) {
477
477
  return (error instanceof Error ? error.message : String(error)).replace(/[\r\n]+/g, " ").slice(0, 1_000);
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { lstat, readFile, realpath, stat } from "node:fs/promises";
3
- import { basename, isAbsolute, relative, resolve, sep } from "node:path";
3
+ import { basename, resolve } from "node:path";
4
4
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
5
5
  import { PRIVATE_LAUNCH_CONTRACT, launchContractTarget } from "../launch-context/index.js";
6
6
  import { DEPENDENCY_LAYER_MANIFEST, dependencyLayerCertificationPath, legacyDependencyLayerCertificationPath, readCertifiedDependencyLayer } from "./dependency-layer.js";
@@ -9,6 +9,7 @@ import { immutablePlatformPolicy } from "./immutable-platform.js";
9
9
  import { PRODUCT_PACKAGE_NAME } from "./release.js";
10
10
  import { RELEASE_MANIFEST_FILENAME } from "./release-store.js";
11
11
  import { UpdateTransactionStore } from "./update-transaction.js";
12
+ import { isDirectChild } from "./managed-path.js";
12
13
  const RESTART_SEAL_VERSION = 1;
13
14
  const REQUIRED_LAUNCH_ENTRIES = ["bin/ui.js"];
14
15
  /** Build compact restart authority after complete content verification established read-only payload files. */
@@ -219,9 +220,7 @@ async function observedRealpath(path, onEvent) {
219
220
  return await realpath(path);
220
221
  }
221
222
  function assertDirectChild(parent, child, expectedName, kind) {
222
- const fromParent = relative(parent, child);
223
- if (isAbsolute(fromParent) || fromParent === ".." || fromParent.startsWith(`..${sep}`) || fromParent.includes(sep)
224
- || basename(child) !== expectedName) {
223
+ if (!isDirectChild(parent, child) || basename(child) !== expectedName) {
225
224
  throw new Error(`restart ${kind} is outside its managed store: ${child}`);
226
225
  }
227
226
  }
@@ -4,10 +4,11 @@ import { resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { PRODUCT_TEXT } from "../../product-identity.js";
6
6
  import { certifyMaterializedRelease } from "./bootstrap.js";
7
- import { CohortStateStore } from "./cohort-state.js";
7
+ import { ReleaseStateStore } from "./release-state.js";
8
8
  import { resolveProductPaths } from "../lifecycle/index.js";
9
9
  import { materializeRelease } from "./release-store.js";
10
10
  import { warmMaterializedRelease } from "./warmup.js";
11
+ import { errorMessage } from "./managed-path.js";
11
12
  /**
12
13
  * The one activation contract an installed tree can offer the updater that installed it.
13
14
  * The updater knows nothing else about the tree: the manifest names the contracts the tree
@@ -27,7 +28,7 @@ const ACTIVATION_LINE_LIMIT = 64 * 1_024;
27
28
  * its activation entry, and what an updater runs in-process for a tree older than the contract.
28
29
  */
29
30
  export async function activateInstalledRelease(request, callbacks) {
30
- const stateStore = new CohortStateStore(request.dataDir);
31
+ const stateStore = new ReleaseStateStore(request.dataDir);
31
32
  let total = 0;
32
33
  let completed = 0;
33
34
  const candidate = await materializeRelease(request.packageRoot, request.dataDir, {
@@ -211,4 +212,3 @@ function summarize(text) {
211
212
  const lines = text.split(/\r?\n/).map(line => line.trim()).filter(line => line.length > 0);
212
213
  return lines.length === 0 ? "" : `: ${lines.slice(0, 4).join(" | ")}`;
213
214
  }
214
- function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
@@ -1,8 +1,7 @@
1
1
  import type { UpdateChannel } from "./types.js";
2
2
  import { type UpdateTransaction } from "./update-transaction.js";
3
- export declare const UPDATE_EXECUTION_LEASE_FILENAME = "update-execution.json";
4
3
  declare const LEASE_SCHEMA = 1;
5
- export type UpdateExecutionMode = "manual" | "automatic";
4
+ type UpdateExecutionMode = "manual" | "automatic";
6
5
  export interface UpdateExecutionOwner {
7
6
  readonly schema: typeof LEASE_SCHEMA;
8
7
  readonly ownerId: string;
@@ -14,7 +13,7 @@ export interface UpdateExecutionOwner {
14
13
  readonly mode: UpdateExecutionMode;
15
14
  readonly acquiredAt: string;
16
15
  }
17
- export type UpdateExecutionLeaseResult = {
16
+ type UpdateExecutionLeaseResult = {
18
17
  readonly status: "acquired";
19
18
  readonly owner: UpdateExecutionOwner;
20
19
  release(): Promise<void>;
@@ -4,7 +4,8 @@ import { dirname, resolve } from "node:path";
4
4
  import lockfile from "proper-lockfile";
5
5
  import { processIsAlive } from "./process-liveness.js";
6
6
  import { UpdateTransactionStore } from "./update-transaction.js";
7
- export const UPDATE_EXECUTION_LEASE_FILENAME = "update-execution.json";
7
+ import { samePath } from "./managed-path.js";
8
+ const UPDATE_EXECUTION_LEASE_FILENAME = "update-execution.json";
8
9
  const LEASE_SCHEMA = 1;
9
10
  const MAX_LEASE_BYTES = 8_192;
10
11
  /**
@@ -146,13 +147,6 @@ async function foreignActiveTransaction(dataDir, owner, requested) {
146
147
  && samePath(requested.packageRoot, owner.packageRoot);
147
148
  return matches ? null : transaction;
148
149
  }
149
- function samePath(left, right) {
150
- const canonicalLeft = resolve(left);
151
- const canonicalRight = resolve(right);
152
- return process.platform === "win32"
153
- ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase()
154
- : canonicalLeft === canonicalRight;
155
- }
156
150
  function currentProcessStartIdentity() {
157
151
  return `${process.pid}:${Math.floor(Date.now() - process.uptime() * 1_000)}`;
158
152
  }
@@ -0,0 +1,45 @@
1
+ import type { ProductPaths } from "../lifecycle/index.js";
2
+ import type { UpdateRecoveryState, UpdateTransaction } from "./update-transaction.js";
3
+ import { type ProtectedPackageReplacementResult } from "./update-recovery.js";
4
+ /** The approved release protected replacement restores when the new package cannot launch. */
5
+ export interface UpdatePriorRelease {
6
+ readonly releaseId: string;
7
+ readonly releaseRoot: string;
8
+ readonly contentDigest: string;
9
+ }
10
+ /** What an update knows about the release that was active when it began. */
11
+ export interface UpdatePriorReleaseProtection {
12
+ /** The active release to roll back to, or null when none was recorded. */
13
+ readonly priorActiveReleaseId: string | null;
14
+ /** The approved record for a release id, or undefined when it cannot protect replacement. */
15
+ approvedRelease(releaseId: string | null): UpdatePriorRelease | undefined;
16
+ }
17
+ export interface UpdatePackageReplacementInput {
18
+ readonly globalRoot: string;
19
+ readonly npmCliRoot: string;
20
+ readonly npmCli?: string;
21
+ readonly packageRoot: string;
22
+ readonly transaction: UpdateTransaction;
23
+ readonly priorRelease: UpdatePriorRelease;
24
+ readonly output: {
25
+ stderr(message: string): void;
26
+ };
27
+ readonly onRecoveryState: (state: UpdateRecoveryState) => Promise<void>;
28
+ }
29
+ /**
30
+ * The update steps that touch npm and release storage. Every update runs all of them in the same
31
+ * order; a test replaces a step's behaviour, never which steps run.
32
+ */
33
+ export interface UpdateInstaller {
34
+ /** Resolve npm's CLI entry before anything changes; a throw stops the update with nothing changed. */
35
+ preflight(npmCliRoot: string): Promise<string | undefined>;
36
+ /** Make sure an approved release can launch while npm replaces the package. */
37
+ protectPriorRelease(packageRoot: string): Promise<UpdatePriorReleaseProtection>;
38
+ replacePackage(input: UpdatePackageReplacementInput): Promise<ProtectedPackageReplacementResult>;
39
+ /** Return to the prior release after a failure, describing what happened. "rolled back" means it did. */
40
+ rollback(priorReleaseId: string | null): Promise<string>;
41
+ /** Release cleanup committed after activation and before success is reported. */
42
+ maintenance(): Promise<void>;
43
+ }
44
+ /** The production installer: npm preflight, recovery release, protected replacement, rollback and release cleanup. */
45
+ export declare function createProtectedUpdateInstaller(paths: ProductPaths, environment: NodeJS.ProcessEnv): UpdateInstaller;
@@ -0,0 +1,57 @@
1
+ import { certifyMaterializedRelease } from "./bootstrap.js";
2
+ import { scheduleReleaseCleanup } from "./release-gc.js";
3
+ import { ReleaseStateStore } from "./release-state.js";
4
+ import { materializeRelease, readMaterializedRelease } from "./release-store.js";
5
+ import { resolveNpmCli, runProtectedPackageReplacement } from "./update-recovery.js";
6
+ /** The production installer: npm preflight, recovery release, protected replacement, rollback and release cleanup. */
7
+ export function createProtectedUpdateInstaller(paths, environment) {
8
+ const dataDir = paths.dataDir;
9
+ return {
10
+ preflight: async (npmCliRoot) => await resolveNpmCli(npmCliRoot, environment),
11
+ protectPriorRelease: async (packageRoot) => await protectPriorRelease(dataDir, packageRoot),
12
+ replacePackage: async (input) => await runProtectedPackageReplacement({ ...input, dataDir, environment }),
13
+ rollback: async (priorReleaseId) => await rollbackPriorRelease(dataDir, priorReleaseId),
14
+ maintenance: async () => { await scheduleReleaseCleanup(dataDir, paths); },
15
+ };
16
+ }
17
+ async function protectPriorRelease(dataDir, packageRoot) {
18
+ const releaseStateStore = new ReleaseStateStore(dataDir);
19
+ let state = await releaseStateStore.read();
20
+ let priorActiveReleaseId = state.references.active;
21
+ if (priorActiveReleaseId === null || state.releases[priorActiveReleaseId]?.approval !== "approved") {
22
+ // Invariant: protected replacement needs an immutable launch authority that npm cannot rename.
23
+ const recoveryRelease = await materializeRelease(packageRoot, dataDir);
24
+ await releaseStateStore.recordCandidate(recoveryRelease);
25
+ const diagnostics = await certifyMaterializedRelease(recoveryRelease, dataDir);
26
+ await releaseStateStore.approve(recoveryRelease.releaseId, diagnostics);
27
+ await releaseStateStore.activate(recoveryRelease.releaseId);
28
+ state = await releaseStateStore.read();
29
+ priorActiveReleaseId = recoveryRelease.releaseId;
30
+ }
31
+ const releases = state.releases;
32
+ return {
33
+ priorActiveReleaseId,
34
+ approvedRelease: releaseId => {
35
+ const record = releaseId === null ? undefined : releases[releaseId];
36
+ return record?.approval === "approved" ? record : undefined;
37
+ },
38
+ };
39
+ }
40
+ async function rollbackPriorRelease(dataDir, priorReleaseId) {
41
+ if (!priorReleaseId)
42
+ return "no prior release was available for rollback";
43
+ const stateStore = new ReleaseStateStore(dataDir);
44
+ const state = await stateStore.read();
45
+ const prior = state.releases[priorReleaseId];
46
+ if (!prior || prior.approval !== "approved")
47
+ return "prior release is not a verified rollback candidate";
48
+ if (state.references.active !== priorReleaseId) {
49
+ if (state.references.rollback === priorReleaseId)
50
+ await stateStore.rollback();
51
+ else
52
+ throw new Error(`prior release ${priorReleaseId} is not the recorded rollback release`);
53
+ }
54
+ // Invariant: rollback selects only a prior release whose retained content still verifies.
55
+ await readMaterializedRelease(prior.releaseRoot);
56
+ return "rolled back";
57
+ }
@@ -1,4 +1,4 @@
1
- import type { CohortState, ReleaseRecord } from "./cohort-state.js";
1
+ import type { ReleaseState, ReleaseRecord } from "./release-state.js";
2
2
  import type { UpdateTransaction } from "./update-transaction.js";
3
3
  /** Keep interactive launches on the last successful release until the update commits success. */
4
- export declare function selectUpdateLaunchRelease(state: CohortState, transaction: UpdateTransaction | null): ReleaseRecord | null;
4
+ export declare function selectUpdateLaunchRelease(state: ReleaseState, transaction: UpdateTransaction | null): ReleaseRecord | null;
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
6
6
  import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
7
7
  import { processIsAlive } from "./process-liveness.js";
8
8
  import { PRIVATE_LAUNCH_CONTRACT, assertCurrentLaunchContract } from "../launch-context/index.js";
9
+ import { isDirectChild, samePath } from "./managed-path.js";
9
10
  export const UPDATE_RECOVERY_SCHEMA = "a1-update-recovery-v1";
10
11
  const WORKER_TIMEOUT_MS = 15 * 60 * 1_000;
11
12
  const POLL_MS = 50;
@@ -429,9 +430,6 @@ async function writeDurableJson(path, value) {
429
430
  await rename(temporary, path);
430
431
  }
431
432
  async function readJson(path) { return JSON.parse(await readFile(path, "utf8")); }
432
- function samePath(left, right) {
433
- return process.platform === "win32" ? resolve(left).toLowerCase() === resolve(right).toLowerCase() : resolve(left) === resolve(right);
434
- }
435
433
  function sameSegment(left, right, platform) {
436
434
  return platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
437
435
  }
@@ -443,11 +441,6 @@ function containedBy(parent, child) {
443
441
  return fromParent.length > 0 && fromParent !== ".." && !fromParent.startsWith(`..${sep}`) && !isAbsolute(fromParent);
444
442
  }
445
443
  function assertDirectChild(parent, child) {
446
- const expectedParent = resolve(parent);
447
- const actualParent = dirname(resolve(child));
448
- const matches = process.platform === "win32"
449
- ? actualParent.toLowerCase() === expectedParent.toLowerCase()
450
- : actualParent === expectedParent;
451
- if (!matches)
444
+ if (!isDirectChild(parent, child))
452
445
  throw new Error(`update recovery path is outside its managed root: ${child}`);
453
446
  }
@@ -3,7 +3,8 @@ import { type RegistryFetcher } from "./latest-release.js";
3
3
  import { type UpdateActivationPhase, type UpdateMaterializationProgress } from "./update-activation.js";
4
4
  import { type UpdateRecoveryState, type UpdateTransaction, type UpdateTransactionPhase } from "./update-transaction.js";
5
5
  import { type UpdateExecutionOwner } from "./update-execution-lease.js";
6
- import { resolveNpmCli, type ProtectedPackageReplacementResult } from "./update-recovery.js";
6
+ import { type UpdateInstaller } from "./update-installer.js";
7
+ export type { UpdateInstaller, UpdatePackageReplacementInput, UpdatePriorRelease, UpdatePriorReleaseProtection, } from "./update-installer.js";
7
8
  export declare const PRODUCT_PACKAGE: string;
8
9
  export type { UpdateChannel } from "./types.js";
9
10
  export interface ProcessRequest {
@@ -76,12 +77,8 @@ export interface SelfUpdateOptions {
76
77
  fetcher?: RegistryFetcher;
77
78
  lifecycle?: UpdateLifecycleCoordinator;
78
79
  transactionStore?: UpdateTransactionJournal;
79
- /** Test seam for protected global package replacement. */
80
- packageReplacement?: (input: UpdatePackageReplacementInput) => Promise<ProtectedPackageReplacementResult>;
81
- /** Test seam for proving replacement-authority preflight ordering. */
82
- npmCliResolver?: typeof resolveNpmCli;
83
- /** Test or embedding seam for post-activation release maintenance. */
84
- maintenance?: () => Promise<void>;
80
+ /** The npm and release-storage steps; defaults to protected replacement of the managed package. */
81
+ installer?: UpdateInstaller;
85
82
  progress?: boolean;
86
83
  onPhaseTiming?: (event: UpdatePhaseTimingEvent) => void;
87
84
  now?: () => number;
@@ -107,22 +104,6 @@ export interface UpdateTransactionJournal {
107
104
  finish(status: "completed" | "rolled-back" | "failed", error?: string | null): Promise<UpdateTransaction>;
108
105
  clearCompleted(): Promise<void>;
109
106
  }
110
- export interface UpdatePackageReplacementInput {
111
- readonly dataDir: string;
112
- readonly globalRoot: string;
113
- readonly npmCliRoot: string;
114
- readonly npmCli?: string;
115
- readonly packageRoot: string;
116
- readonly transaction: UpdateTransaction;
117
- readonly priorRelease: {
118
- readonly releaseId: string;
119
- readonly releaseRoot: string;
120
- readonly contentDigest: string;
121
- };
122
- readonly output: UpdateOutput;
123
- readonly environment: NodeJS.ProcessEnv;
124
- readonly onRecoveryState: (state: UpdateRecoveryState) => Promise<void>;
125
- }
126
107
  /**
127
108
  * The package tree is checked for holders by renaming it and renaming it back, because on
128
109
  * Windows that is the one operation that fails while any file under it is open. A holder is
@@ -135,8 +116,6 @@ export declare const UPDATE_ALREADY_RUNNING_EXIT_CODE = 75;
135
116
  export declare function isPackageLockError(error: unknown): boolean;
136
117
  /** What the user reads when the package stayed held for the whole patience window. */
137
118
  export declare function lockedPackageDiagnostic(packageRoot: string, waitedMs: number, attempts: number, error: unknown): string;
138
- /** Bound on the child diagnostics an update keeps: enough for npm's failure reason, never a log. */
139
- export declare const CHILD_DIAGNOSTIC_LIMIT = 8000;
140
119
  export declare function createNpmProcessRunner(platform?: NodeJS.Platform): UpdateProcessRunner;
141
120
  export declare function createUpdateLifecycleCoordinator(environment?: NodeJS.ProcessEnv, fileSystem?: UpdateFileSystem, _output?: UpdateOutput, patience?: UpdateUnlockPatience): UpdateLifecycleCoordinator;
142
121
  /** Renders the terminal-only update meter; the visual preview shares this exact frame. */