@timurproko/a1 0.2.7-dev.1275 → 0.2.7-dev.1285

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 (220) hide show
  1. package/README.md +5 -1
  2. package/dist/app/session-shell/apps-dialog.d.ts +1 -1
  3. package/dist/app/session-shell/apps-dialog.js +2 -1
  4. package/dist/app/session-shell/dialog-coordinator.d.ts +4 -5
  5. package/dist/app/session-shell/dialog-coordinator.js +41 -12
  6. package/dist/app/session-shell/input-route.d.ts +23 -0
  7. package/dist/app/session-shell/input-route.js +59 -0
  8. package/dist/app/session-shell/session-selectors.d.ts +3 -3
  9. package/dist/app/session-shell/session-selectors.js +7 -2
  10. package/dist/app/session-shell/session-shell-root.d.ts +4 -68
  11. package/dist/app/session-shell/session-shell-root.js +6 -2
  12. package/dist/app/session-shell/session-shell.js +9 -13
  13. package/dist/app/session-shell/shell-host.js +2 -2
  14. package/dist/app/session-shell/shell-options.d.ts +65 -0
  15. package/dist/app/session-shell/shell-options.js +1 -0
  16. package/dist/app/session-shell/viewport-pointer.js +5 -1
  17. package/dist/app/session-shell/workflow-router.d.ts +4 -2
  18. package/dist/app/session-shell/workflow-router.js +12 -0
  19. package/dist/cli/dispatch.js +27 -1
  20. package/dist/cli/packages.js +18 -2
  21. package/dist/cli/session-context.js +6 -2
  22. package/dist/composition/owned-ui.js +20 -8
  23. package/dist/composition/session-naming.js +1 -1
  24. package/dist/composition/session-runtime-registry.d.ts +2 -0
  25. package/dist/composition/session-runtime-registry.js +49 -9
  26. package/dist/composition/settings-route-host.js +1 -0
  27. package/dist/contracts/agent-engine/package-ports.d.ts +10 -14
  28. package/dist/contracts/agent-engine/package-ports.js +5 -9
  29. package/dist/contracts/owned-ui/session-workflows.d.ts +6 -0
  30. package/dist/contracts/owned-ui/shell-components.d.ts +10 -0
  31. package/dist/contracts/presentation/component.d.ts +7 -0
  32. package/dist/contracts/presentation/index.d.ts +3 -0
  33. package/dist/contracts/presentation/index.js +4 -0
  34. package/dist/contracts/presentation/progress-palette.generated.d.ts +25 -1
  35. package/dist/contracts/presentation/progress-palette.generated.js +2 -135
  36. package/dist/contracts/presentation/progress-spinner.d.ts +7 -0
  37. package/dist/contracts/presentation/progress-spinner.js +1 -0
  38. package/dist/features/launch/session-context.d.ts +8 -0
  39. package/dist/features/launch/session-context.js +19 -10
  40. package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
  41. package/dist/features/owned-ui/project-trust-dialog.js +5 -5
  42. package/dist/features/owned-ui/project-trust-prompt.js +2 -2
  43. package/dist/features/owned-ui/reference-screen-app.d.ts +2 -0
  44. package/dist/features/owned-ui/reference-screen-app.js +12 -5
  45. package/dist/features/owned-ui/session-fork-prompt.d.ts +2 -1
  46. package/dist/features/owned-ui/session-fork-prompt.js +11 -5
  47. package/dist/features/owned-ui/settings-app.d.ts +1 -1
  48. package/dist/features/owned-ui/settings-app.js +20 -13
  49. package/dist/features/owned-ui/settings-model-dialog.js +3 -3
  50. package/dist/features/owned-ui/settings-spinner-preview.d.ts +9 -0
  51. package/dist/features/owned-ui/settings-spinner-preview.js +29 -0
  52. package/dist/features/session-naming/context.d.ts +17 -0
  53. package/dist/features/session-naming/context.js +39 -0
  54. package/dist/features/session-naming/controller.d.ts +1 -5
  55. package/dist/features/session-naming/controller.js +7 -4
  56. package/dist/features/session-naming/generate.d.ts +2 -1
  57. package/dist/features/session-naming/generate.js +14 -10
  58. package/dist/features/session-naming/index.d.ts +1 -1
  59. package/dist/foundation/lifecycle/index.d.ts +3 -1
  60. package/dist/foundation/lifecycle/index.js +3 -1
  61. package/dist/foundation/lifecycle/session-claim-lock.d.ts +2 -2
  62. package/dist/foundation/lifecycle/session-claim-lock.js +36 -10
  63. package/dist/foundation/lifecycle/session-context-retry.d.ts +2 -0
  64. package/dist/foundation/lifecycle/session-context-retry.js +17 -0
  65. package/dist/foundation/lifecycle/session-repository-context.d.ts +7 -1
  66. package/dist/foundation/lifecycle/session-repository-context.js +105 -39
  67. package/dist/foundation/lifecycle/session-worktree-entry.d.ts +3 -0
  68. package/dist/foundation/lifecycle/session-worktree-entry.js +87 -0
  69. package/dist/foundation/release/automatic-update.js +2 -2
  70. package/dist/foundation/release/bootstrap.js +19 -3
  71. package/dist/foundation/release/release-gc.js +20 -5
  72. package/dist/foundation/release/release-state.d.ts +12 -3
  73. package/dist/foundation/release/release-state.js +55 -24
  74. package/dist/foundation/release/release-use.d.ts +10 -0
  75. package/dist/foundation/release/release-use.js +70 -0
  76. package/dist/foundation/release/update-activation.js +2 -2
  77. package/dist/foundation/release/update-recovery.js +2 -2
  78. package/dist/foundation/release/update.js +1 -1
  79. package/dist/foundation/release/warmup.js +8 -9
  80. package/dist/foundation/session-writer-lock/index.d.ts +2 -2
  81. package/dist/foundation/session-writer-lock/index.js +82 -12
  82. package/dist/foundation/startup/startup-descriptor.js +2 -2
  83. package/dist/foundation/terminal-cleanup/fatal-diagnostic.d.ts +2 -0
  84. package/dist/foundation/terminal-cleanup/fatal-diagnostic.js +59 -0
  85. package/dist/foundation/terminal-cleanup/fatal-exit.js +1 -29
  86. package/dist/integrations/pi/components/deferred-selector.d.ts +6 -0
  87. package/dist/integrations/pi/components/deferred-selector.js +40 -0
  88. package/dist/integrations/pi/components/login-dialog-loader.d.ts +3 -0
  89. package/dist/integrations/pi/components/login-dialog-loader.js +57 -0
  90. package/dist/integrations/pi/components/login-links.d.ts +6 -0
  91. package/dist/integrations/pi/components/login-links.js +31 -0
  92. package/dist/integrations/pi/components/login-text.d.ts +7 -0
  93. package/dist/integrations/pi/components/login-text.js +17 -0
  94. package/dist/integrations/pi/components/modal-frame.d.ts +5 -0
  95. package/dist/integrations/pi/components/modal-frame.js +30 -2
  96. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  97. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  98. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -1
  99. package/dist/integrations/pi/components/share-operation-dialog.js +13 -5
  100. package/dist/integrations/pi/components/shell-footer-status.d.ts +2 -1
  101. package/dist/integrations/pi/components/shell-footer-status.js +15 -8
  102. package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +11 -8
  103. package/dist/integrations/pi/components/shell-selectors-dialogs.js +36 -35
  104. package/dist/integrations/pi/components/shell-session-info-reference.d.ts +1 -1
  105. package/dist/integrations/pi/components/shell-session-info-reference.js +55 -49
  106. package/dist/integrations/pi/components/theme.d.ts +2 -0
  107. package/dist/integrations/pi/components/theme.js +4 -0
  108. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  109. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  110. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  111. package/dist/integrations/pi/components/upstream/components/auth-url.d.ts +16 -0
  112. package/dist/integrations/pi/components/upstream/components/auth-url.js +49 -0
  113. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  114. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  115. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  116. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  117. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  118. package/dist/integrations/pi/components/upstream/components/extension-selector.d.ts +1 -0
  119. package/dist/integrations/pi/components/upstream/components/extension-selector.js +22 -11
  120. package/dist/integrations/pi/components/upstream/components/login-dialog.d.ts +3 -0
  121. package/dist/integrations/pi/components/upstream/components/login-dialog.js +216 -0
  122. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  123. package/dist/integrations/pi/components/upstream/components/oauth-selector.d.ts +19 -0
  124. package/dist/integrations/pi/components/upstream/components/oauth-selector.js +123 -0
  125. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  126. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  127. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  128. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  129. package/dist/integrations/pi/components/upstream/components/session-footer.js +22 -13
  130. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  131. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  132. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  133. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  134. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  135. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  136. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  137. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  138. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  139. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  140. package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
  141. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  142. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  143. package/dist/integrations/pi/components/upstream/components/trust-selector.d.ts +2 -0
  144. package/dist/integrations/pi/components/upstream/components/trust-selector.js +30 -13
  145. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  146. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  147. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  148. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  149. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  150. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  151. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  152. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  153. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  154. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  155. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  156. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  157. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  158. package/dist/integrations/pi/engine/adapter.d.ts +3 -1
  159. package/dist/integrations/pi/engine/adapter.js +24 -6
  160. package/dist/integrations/pi/engine/changelog.js +5 -2
  161. package/dist/integrations/pi/engine/delivery-retention.d.ts +7 -0
  162. package/dist/integrations/pi/engine/delivery-retention.js +66 -0
  163. package/dist/integrations/pi/engine/event-delivery.d.ts +17 -1
  164. package/dist/integrations/pi/engine/event-delivery.js +25 -3
  165. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -1
  166. package/dist/integrations/pi/engine/extension-ui-binding.js +45 -0
  167. package/dist/integrations/pi/engine/host-ports.d.ts +2 -0
  168. package/dist/integrations/pi/engine/host.d.ts +3 -0
  169. package/dist/integrations/pi/engine/host.js +2 -0
  170. package/dist/integrations/pi/engine/package-integration.js +19 -4
  171. package/dist/integrations/pi/engine/pending-delivery.d.ts +4 -1
  172. package/dist/integrations/pi/engine/pending-delivery.js +51 -18
  173. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  174. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -0
  175. package/dist/integrations/pi/engine/runtime-integration.js +58 -9
  176. package/dist/integrations/pi/engine/session-cwd-recovery.d.ts +11 -0
  177. package/dist/integrations/pi/engine/session-cwd-recovery.js +18 -0
  178. package/dist/integrations/pi/engine/session-runtime.d.ts +3 -0
  179. package/dist/integrations/pi/engine/session-runtime.js +2 -0
  180. package/dist/integrations/pi/engine/session-selection.d.ts +3 -2
  181. package/dist/integrations/pi/engine/session-selection.js +25 -5
  182. package/dist/integrations/pi/engine/transcript-image-assets.d.ts +3 -0
  183. package/dist/integrations/pi/engine/transcript-image-assets.js +65 -14
  184. package/dist/integrations/pi/engine/view-state.d.ts +14 -0
  185. package/dist/integrations/pi/engine/view-state.js +17 -0
  186. package/dist/integrations/pi/engine/workflow-runner.d.ts +2 -0
  187. package/dist/integrations/pi/engine/workflow-runner.js +47 -26
  188. package/dist/integrations/pi/engine/worktree-tools.d.ts +4 -0
  189. package/dist/integrations/pi/engine/worktree-tools.js +26 -0
  190. package/dist/integrations/pi/session-presenters/components.d.ts +2 -1
  191. package/dist/integrations/pi/session-presenters/components.js +12 -10
  192. package/dist/integrations/pi/session-presenters/presenters.d.ts +3 -1
  193. package/dist/integrations/pi/session-presenters/presenters.js +2 -2
  194. package/dist/integrations/pi/startup-public.d.ts +1 -1
  195. package/dist/integrations/pi/startup-public.js +16 -20
  196. package/dist/integrations/pi/startup-public.manifest.json +29 -29
  197. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  198. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  199. package/dist/product-identity.json +1 -1
  200. package/dist/runtime-payload-inventory.json +5027 -5027
  201. package/dist/ui/components/index.d.ts +1 -1
  202. package/dist/ui/components/index.js +1 -1
  203. package/dist/ui/components/list-block.d.ts +2 -2
  204. package/dist/ui/components/list-block.js +4 -3
  205. package/dist/ui/components/progress-status.d.ts +7 -0
  206. package/dist/ui/components/progress-status.js +21 -0
  207. package/dist/ui/components/value-menu.d.ts +1 -1
  208. package/dist/ui/components/value-menu.js +4 -2
  209. package/dist/ui/settings/declarations.d.ts +16 -4
  210. package/dist/ui/settings/declarations.js +13 -4
  211. package/dist/ui/settings/early-accent.d.ts +24 -0
  212. package/docs/architecture/internal-naming.md +1 -1
  213. package/docs/architecture/project-structure.md +7 -11
  214. package/docs/features/session-exports.md +1 -1
  215. package/docs/features/session-naming.md +8 -6
  216. package/docs/features/worktrees.md +38 -0
  217. package/docs/local-worktree-cleanup.md +27 -4
  218. package/docs/openspec-archive-automation.md +30 -4
  219. package/docs/worktree-link-recovery.md +2 -2
  220. package/package.json +5 -5
@@ -1,3 +1,4 @@
1
+ import type { DeliveryFailure } from "./event-delivery.js";
1
2
  import { PiEngineAdapter } from "./adapter.js";
2
3
  import { type StartupPhase } from "../../../foundation/startup/startup-runtime.js";
3
4
  import type { PiEnginePackageUpdateProbe, PiEngineRuntimeFactory, PiRepositoryContextReader } from "./session-runtime.js";
@@ -21,6 +22,7 @@ export interface PiEngineHostTheme {
21
22
  }
22
23
  export interface PiEngineHostOptions {
23
24
  readonly productMode: "bare" | "comparison";
25
+ readonly deliveryIncident?: (failure: DeliveryFailure) => void;
24
26
  readonly theme: PiEngineHostTheme;
25
27
  /** Themes installed on this machine, listed by the component adapter that owns the theme unit. */
26
28
  readonly availableThemes?: () => readonly string[];
@@ -41,6 +43,7 @@ export interface PiEngineSessionRequest extends OwnedUiSessionRequest {
41
43
  readonly sessionSelection?: PiSessionSelection;
42
44
  readonly sessionForkPrompt?: PiSessionForkPrompt;
43
45
  readonly repositoryContextReader?: PiRepositoryContextReader;
46
+ readonly worktreeCwdReader?: import("./worktree-tools.js").PiWorktreeCwdReader;
44
47
  }
45
48
  /** The dispatcher policy in force for the process and the session that put it there. */
46
49
  export interface PiEngineHttpPolicy {
@@ -26,6 +26,7 @@ class ProcessPiEngineHost {
26
26
  this.#markStartupPhase = options.markStartupPhase ?? (phase => markStartupPhase(process.env, phase));
27
27
  this.#sessionPorts = {
28
28
  signal: this.#abort.signal,
29
+ deliveryIncident: failure => options.deliveryIncident?.(failure),
29
30
  markStartupPhase: phase => this.#tracePhase(phase),
30
31
  httpPolicyLoaded: (timeoutMs, sessionId) => { this.#applyHttpPolicy(timeoutMs, sessionId, "startup"); },
31
32
  httpPolicyChanged: (timeoutMs, sessionId) => { this.#applyHttpPolicy(timeoutMs, sessionId, "setting"); },
@@ -68,6 +69,7 @@ class ProcessPiEngineHost {
68
69
  ...(request.sessionSelection === undefined ? {} : { sessionSelection: request.sessionSelection }),
69
70
  ...(request.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: request.sessionForkPrompt }),
70
71
  ...(request.repositoryContextReader === undefined ? {} : { repositoryContextReader: request.repositoryContextReader }),
72
+ ...(request.worktreeCwdReader === undefined ? {} : { worktreeCwdReader: request.worktreeCwdReader }),
71
73
  });
72
74
  this.#sessions.set(sessionId, adapter);
73
75
  try {
@@ -17,6 +17,8 @@ export function createPiPackagesPort(input) {
17
17
  const { profileRoot, cwd } = input;
18
18
  // Compatibility: model-only refresh bypasses package settings and their diagnostics, as Pi does.
19
19
  let packageManager;
20
+ let updateChanges = [];
21
+ let updateWarningCount = 0;
20
22
  const manager = () => {
21
23
  if (packageManager)
22
24
  return packageManager;
@@ -29,9 +31,16 @@ export function createPiPackagesPort(input) {
29
31
  }
30
32
  packageManager = new DefaultPackageManager({ cwd, agentDir: profileRoot, settingsManager });
31
33
  packageManager.setProgressCallback(event => {
32
- if (event.type !== "start")
33
- return;
34
- input.onProgress?.({ operation: operationFor(event.action), message: String(event.message) });
34
+ if (event.type === "result" && event.action === "update" && event.message) {
35
+ updateChanges.push(event.message);
36
+ }
37
+ else if (event.type === "start") {
38
+ input.onProgress?.({ operation: operationFor(event.action), message: String(event.message) });
39
+ }
40
+ else if (event.type === "progress" && event.message) {
41
+ updateWarningCount++;
42
+ input.onProgress?.({ operation: operationFor(event.action), message: event.message, severity: "warning" });
43
+ }
35
44
  });
36
45
  return packageManager;
37
46
  };
@@ -65,8 +74,14 @@ export function createPiPackagesPort(input) {
65
74
  async update(source) {
66
75
  return await attempt("update", source ?? null, async () => {
67
76
  // Compatibility: Pi owns source identity and its contextual no-match suggestions.
77
+ updateChanges = [];
78
+ updateWarningCount = 0;
68
79
  await manager().update(source);
69
- return agentPackageOutcome("update", "completed", null, source ?? null, configured());
80
+ // Compatibility: Pi's offline predicate is not part of its package-root public API.
81
+ const offline = ["1", "true", "yes"].includes(process.env.PI_OFFLINE?.toLowerCase() ?? "");
82
+ return agentPackageOutcome("update", "completed", null, source ?? null, configured(), {
83
+ offline, warningCount: updateWarningCount, changes: updateChanges,
84
+ });
70
85
  });
71
86
  },
72
87
  async refreshModels() {
@@ -2,8 +2,11 @@ import type { OwnedUiEvent } from "../../../contracts/owned-ui/index.js";
2
2
  /** Intrusive FIFO + segment index: replacement unlinks in O(1), never changes source ordering. */
3
3
  export declare class PendingEngineDelivery {
4
4
  #private;
5
+ rejection: "event-count" | "retained-bytes" | null;
5
6
  private readonly retain;
6
- constructor(retain?: (event: OwnedUiEvent) => () => void);
7
+ private readonly current;
8
+ private readonly externalBytes;
9
+ constructor(retain?: (event: OwnedUiEvent) => () => void, current?: () => unknown, externalBytes?: (excluding?: OwnedUiEvent) => number);
7
10
  get size(): number;
8
11
  diagnostics(): {
9
12
  pending: number;
@@ -1,3 +1,4 @@
1
+ import { DeliveryRetention } from "./delivery-retention.js";
1
2
  const MAX_PENDING_EVENTS = 1024;
2
3
  const MAX_PENDING_EVENT_BYTES = 8 * 1024 * 1024;
3
4
  /** Actual shell semantics: only live complete block state has no independent side effect. */
@@ -29,21 +30,32 @@ export class PendingEngineDelivery {
29
30
  #head;
30
31
  #tail;
31
32
  #size = 0;
32
- #bytes = 0;
33
+ #retention = new DeliveryRetention();
33
34
  #protected = 0;
34
35
  #generation = -1;
35
36
  #superseded = 0;
36
37
  #peakNodes = 0;
37
38
  #peakBytes = 0;
39
+ rejection = null;
38
40
  retain;
39
- constructor(retain) { this.retain = retain; }
41
+ current;
42
+ externalBytes;
43
+ constructor(retain, current, externalBytes) {
44
+ this.retain = retain;
45
+ this.current = current;
46
+ this.externalBytes = externalBytes;
47
+ }
40
48
  get size() { return this.#size; }
49
+ get #bytes() { return this.#retention.bytes + this.#size * 128 + (this.externalBytes?.() ?? 0); }
41
50
  diagnostics() {
42
51
  return { pending: this.#size, bytes: this.#bytes, protected: this.#protected,
43
52
  superseded: this.#superseded, peakNodes: this.#peakNodes, peakBytes: this.#peakBytes };
44
53
  }
45
54
  /** False means not admitted. The caller must enter its reserved recovery protocol, never evict. */
46
55
  push(event, generation, reconcile) {
56
+ this.rejection = null;
57
+ if (this.current)
58
+ this.#retention.baseline(this.current());
47
59
  const key = replaceableEventKey(event);
48
60
  if (generation !== this.#generation || key === null) {
49
61
  if (!this.seal())
@@ -51,14 +63,23 @@ export class PendingEngineDelivery {
51
63
  this.#generation = generation;
52
64
  }
53
65
  const prior = key === null ? undefined : this.#replaceable.get(key);
54
- let bytes = retainedEventBytes(event);
55
- const marker = key !== null && bytes > 64 * 1024 && reconcile !== undefined;
56
- if (marker)
57
- bytes = 128;
66
+ // Compatibility: production owns exact immutable revisions through the ledger. Legacy standalone
67
+ // queues retain the compact-marker contract when no authoritative owner is supplied.
68
+ const marker = this.current === undefined && key !== null && retainedEventBytes(event) > 64 * 1024 && reconcile !== undefined;
69
+ const charge = marker ? undefined : this.#retention.retain(event);
70
+ const release = marker ? undefined : this.retain?.(event);
71
+ prior?.charge?.();
72
+ const bytes = this.#retention.bytes + this.#size * 128 + (this.externalBytes?.(prior?.event) ?? 0);
58
73
  if (this.#size - (prior === undefined ? 0 : 1) >= MAX_PENDING_EVENTS
59
- || this.#bytes - (prior?.bytes ?? 0) + bytes > MAX_PENDING_EVENT_BYTES)
74
+ || bytes + (prior === undefined ? 128 : 0) > MAX_PENDING_EVENT_BYTES) {
75
+ this.rejection = this.#size - (prior === undefined ? 0 : 1) >= MAX_PENDING_EVENTS ? "event-count" : "retained-bytes";
76
+ charge?.();
77
+ release?.();
78
+ if (prior?.event)
79
+ prior.charge = this.#retention.retain(prior.event);
60
80
  return false;
61
- const node = { key, generation, bytes, ...(marker ? { resolve: reconcile } : { event, release: this.retain?.(event) }) };
81
+ }
82
+ const node = { key, generation, charge, ...(marker ? { resolve: reconcile } : { event, release }) };
62
83
  if (prior !== undefined) {
63
84
  this.#unlink(prior);
64
85
  this.#superseded = Math.min(Number.MAX_SAFE_INTEGER, this.#superseded + 1);
@@ -70,7 +91,6 @@ export class PendingEngineDelivery {
70
91
  this.#head = node;
71
92
  this.#tail = node;
72
93
  this.#size++;
73
- this.#bytes += bytes;
74
94
  if (key === null)
75
95
  this.#protected++;
76
96
  else
@@ -101,9 +121,17 @@ export class PendingEngineDelivery {
101
121
  return undefined;
102
122
  const event = node.event ?? node.resolve();
103
123
  const release = node.release ?? this.retain?.(event);
124
+ const charge = node.charge;
104
125
  this.#unlink(node, false);
105
- // Invariant: a consumed snapshot retains its assets through synchronous listener delivery, including reentrant production.
106
- return { event, generation: node.generation, ...(release === undefined ? {} : { release }) };
126
+ // Invariant: keep the exact revision and assets charged through reentrant listener production.
127
+ let released = false;
128
+ return { event, generation: node.generation, release: () => {
129
+ if (released)
130
+ return;
131
+ released = true;
132
+ charge?.();
133
+ release?.();
134
+ } };
107
135
  }
108
136
  // Invariant: a barrier freezes lazy authoritative markers before a later segment can change them.
109
137
  seal() {
@@ -111,22 +139,28 @@ export class PendingEngineDelivery {
111
139
  if (node.resolve === undefined)
112
140
  continue;
113
141
  const event = node.resolve();
114
- const bytes = retainedEventBytes(event);
115
- if (this.#bytes - node.bytes + bytes > MAX_PENDING_EVENT_BYTES)
142
+ const charge = this.#retention.retain(event);
143
+ const release = this.retain?.(event);
144
+ if (this.#bytes > MAX_PENDING_EVENT_BYTES) {
145
+ this.rejection = "retained-bytes";
146
+ charge();
147
+ release?.();
116
148
  return false;
117
- this.#bytes += bytes - node.bytes;
118
- node.bytes = bytes;
149
+ }
150
+ node.charge = charge;
119
151
  node.event = event;
120
152
  node.resolve = undefined;
121
- node.release = this.retain?.(event);
153
+ node.release = release;
122
154
  this.#peakBytes = Math.max(this.#peakBytes, this.#bytes);
123
155
  }
124
156
  this.#replaceable.clear();
125
157
  return true;
126
158
  }
127
159
  #unlink(node, release = true) {
128
- if (release)
160
+ if (release) {
161
+ node.charge?.();
129
162
  node.release?.();
163
+ }
130
164
  if (node.previous !== undefined)
131
165
  node.previous.next = node.next;
132
166
  else
@@ -136,7 +170,6 @@ export class PendingEngineDelivery {
136
170
  else
137
171
  this.#tail = node.previous;
138
172
  this.#size--;
139
- this.#bytes -= node.bytes;
140
173
  if (node.key === null)
141
174
  this.#protected--;
142
175
  else if (this.#replaceable.get(node.key) === node)