@indigoai-us/hq-cloud 6.18.49 → 6.18.50-alpha.0

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 (63) hide show
  1. package/dist/bin/sync-runner-company.d.ts +5 -0
  2. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  3. package/dist/bin/sync-runner-company.js +24 -2
  4. package/dist/bin/sync-runner-company.js.map +1 -1
  5. package/dist/bin/sync-runner-watch-loop.d.ts +85 -5
  6. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  7. package/dist/bin/sync-runner-watch-loop.js +1062 -123
  8. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  9. package/dist/bin/sync-runner.d.ts +30 -11
  10. package/dist/bin/sync-runner.d.ts.map +1 -1
  11. package/dist/bin/sync-runner.js +133 -15
  12. package/dist/bin/sync-runner.js.map +1 -1
  13. package/dist/bin/watcher-catchup-skip-store.d.ts +60 -0
  14. package/dist/bin/watcher-catchup-skip-store.d.ts.map +1 -0
  15. package/dist/bin/watcher-catchup-skip-store.js +282 -0
  16. package/dist/bin/watcher-catchup-skip-store.js.map +1 -0
  17. package/dist/cli/share.d.ts +12 -0
  18. package/dist/cli/share.d.ts.map +1 -1
  19. package/dist/cli/share.js +57 -4
  20. package/dist/cli/share.js.map +1 -1
  21. package/dist/cli/sync.d.ts +3 -0
  22. package/dist/cli/sync.d.ts.map +1 -1
  23. package/dist/cli/sync.js +27 -7
  24. package/dist/cli/sync.js.map +1 -1
  25. package/dist/cli/tombstones.d.ts.map +1 -1
  26. package/dist/cli/tombstones.js +7 -2
  27. package/dist/cli/tombstones.js.map +1 -1
  28. package/dist/ignore.d.ts +1 -1
  29. package/dist/ignore.d.ts.map +1 -1
  30. package/dist/ignore.js +2 -2
  31. package/dist/ignore.js.map +1 -1
  32. package/dist/lib/cloud-authoritative.d.ts +9 -2
  33. package/dist/lib/cloud-authoritative.d.ts.map +1 -1
  34. package/dist/lib/cloud-authoritative.js +34 -2
  35. package/dist/lib/cloud-authoritative.js.map +1 -1
  36. package/dist/local-path-codec.d.ts.map +1 -1
  37. package/dist/local-path-codec.js +3 -2
  38. package/dist/local-path-codec.js.map +1 -1
  39. package/dist/personal-vault-exclusions.d.ts +2 -2
  40. package/dist/personal-vault-exclusions.d.ts.map +1 -1
  41. package/dist/personal-vault-exclusions.js +5 -3
  42. package/dist/personal-vault-exclusions.js.map +1 -1
  43. package/dist/personal-vault.d.ts +7 -0
  44. package/dist/personal-vault.d.ts.map +1 -1
  45. package/dist/personal-vault.js +10 -0
  46. package/dist/personal-vault.js.map +1 -1
  47. package/dist/symlink-target-policy.d.ts +11 -0
  48. package/dist/symlink-target-policy.d.ts.map +1 -1
  49. package/dist/symlink-target-policy.js +80 -0
  50. package/dist/symlink-target-policy.js.map +1 -1
  51. package/dist/sync/parallel-sync-coordinator.d.ts +29 -0
  52. package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
  53. package/dist/sync/parallel-sync-coordinator.js +229 -16
  54. package/dist/sync/parallel-sync-coordinator.js.map +1 -1
  55. package/dist/sync/push-receiver.d.ts +5 -0
  56. package/dist/sync/push-receiver.d.ts.map +1 -1
  57. package/dist/sync/push-receiver.js +32 -10
  58. package/dist/sync/push-receiver.js.map +1 -1
  59. package/dist/watcher.d.ts +16 -3
  60. package/dist/watcher.d.ts.map +1 -1
  61. package/dist/watcher.js +114 -21
  62. package/dist/watcher.js.map +1 -1
  63. package/package.json +1 -1
@@ -4,6 +4,86 @@ import fs from "node:fs";
4
4
  export function personalSymlinkTargetLinkPath(relativePath) {
5
5
  return relativePath;
6
6
  }
7
+ /** Inspect a local link without relying on a previous push pass to resolve policy. */
8
+ export function inspectLocalSymlinkScope(input) {
9
+ let stat;
10
+ try {
11
+ stat = fs.lstatSync(input.absoluteLinkPath);
12
+ }
13
+ catch {
14
+ return { isSymlink: false, classification: "in-scope", refused: false, shape: "missing" };
15
+ }
16
+ if (!stat.isSymbolicLink()) {
17
+ return { isSymlink: false, classification: "in-scope", refused: false, shape: "regular" };
18
+ }
19
+ const refuse = (classification, shape) => ({
20
+ isSymlink: true,
21
+ classification,
22
+ refused: true,
23
+ shape,
24
+ });
25
+ let target;
26
+ try {
27
+ target = fs.readlinkSync(input.absoluteLinkPath);
28
+ }
29
+ catch {
30
+ return refuse("escapes-scope", "unreadable-link");
31
+ }
32
+ const targetIsAbsolute = path.isAbsolute(target) || path.win32.isAbsolute(target);
33
+ let lexicalClassification;
34
+ if (targetIsAbsolute && isLegacyAbsoluteKnowledgeLink(input.linkPath, target, input.scopeRoot, input.scope)) {
35
+ return { isSymlink: true, classification: "allowlisted-legacy", refused: false, shape: "allowlisted-legacy" };
36
+ }
37
+ if (!targetIsAbsolute) {
38
+ const lexical = inspectSymlinkTarget({
39
+ linkPath: input.linkPath,
40
+ target,
41
+ scope: input.scope,
42
+ refuse: true,
43
+ emit: () => undefined,
44
+ });
45
+ if (lexical.refused) {
46
+ return refuse(lexical.classification, redactShape(target, lexical.classification));
47
+ }
48
+ if (lexical.classification === "allowlisted-legacy") {
49
+ return { isSymlink: true, classification: lexical.classification, refused: false, shape: "allowlisted-legacy" };
50
+ }
51
+ lexicalClassification = lexical.classification;
52
+ }
53
+ let canonicalScope;
54
+ try {
55
+ canonicalScope = fs.realpathSync.native(input.scopeRoot);
56
+ }
57
+ catch {
58
+ return refuse("escapes-scope", "realpath-unavailable");
59
+ }
60
+ let canonicalTarget;
61
+ try {
62
+ canonicalTarget = fs.realpathSync.native(input.absoluteLinkPath);
63
+ }
64
+ catch (error) {
65
+ if (error.code === "ENOENT" &&
66
+ lexicalClassification === "in-scope") {
67
+ return { isSymlink: true, classification: "in-scope", refused: false, shape: "in-scope-dangling" };
68
+ }
69
+ return refuse("escapes-scope", "realpath-unavailable");
70
+ }
71
+ const relative = path.relative(canonicalScope, canonicalTarget);
72
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
73
+ return refuse("escapes-scope", targetIsAbsolute ? "absolute-outside-scope" : "realpath-outside-scope");
74
+ }
75
+ return { isSymlink: true, classification: "in-scope", refused: false, shape: "in-scope" };
76
+ }
77
+ function isLegacyAbsoluteKnowledgeLink(linkPath, target, scopeRoot, scope) {
78
+ if (scope.kind !== "company")
79
+ return false;
80
+ const normalizedLink = normalizeVaultPath(linkPath);
81
+ if (normalizedLink !== `companies/${scope.companySlug}/knowledge`)
82
+ return false;
83
+ const hqRoot = path.resolve(scopeRoot, "..", "..");
84
+ const expectedTarget = path.resolve(hqRoot, "repos", "private", `knowledge-${scope.companySlug}`);
85
+ return path.resolve(target) === expectedTarget;
86
+ }
7
87
  /** Compare a materialized path with the portable wire target across Windows aliases. */
8
88
  export function materializedTargetMatchesWire(linkPath, localTarget, wireTarget, platform = process.platform) {
9
89
  const paths = platform === "win32" ? path.win32 : path;
@@ -1 +1 @@
1
- {"version":3,"file":"symlink-target-policy.js","sourceRoot":"","sources":["../src/symlink-target-policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"symlink-target-policy.js","sourceRoot":"","sources":["../src/symlink-target-policy.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,27 @@ export type CoordinatorSnapshot = {
22
22
  realtimeQueued: number;
23
23
  choreQueued: number;
24
24
  realtimeRunning: boolean;
25
+ realtimeLanes: {
26
+ fast: {
27
+ direction?: "push" | "pull";
28
+ source?: string;
29
+ paths: number;
30
+ } | null;
31
+ slow: {
32
+ direction?: "push" | "pull";
33
+ source?: string;
34
+ paths: number;
35
+ } | null;
36
+ overflowPush: {
37
+ direction?: "push" | "pull";
38
+ source?: string;
39
+ paths: number;
40
+ } | null;
41
+ };
25
42
  choreRunning: boolean;
43
+ retainedPullYieldStates: number;
44
+ lastRealtimeAdmissionAt: number | null;
45
+ lastChoreAdmissionAt: number | null;
26
46
  leases: ReturnType<PathLeaseManager["inspect"]>;
27
47
  now: number;
28
48
  };
@@ -48,12 +68,17 @@ export declare class DefaultParallelSyncCoordinator implements ParallelSyncCoord
48
68
  private nextId;
49
69
  private nextEpoch;
50
70
  private readonly realtimeRunningByLane;
71
+ private realtimeOverflowPush?;
72
+ private readonly pullYieldStates;
73
+ private lastRealtimeAdmissionAt;
74
+ private lastChoreAdmissionAt;
51
75
  private choreRunning?;
52
76
  private stopping;
53
77
  private shutdownPromise?;
54
78
  constructor(options: ParallelSyncCoordinatorOptions);
55
79
  submit(work: SyncWork): Promise<WorkOutcome>;
56
80
  inspect(): CoordinatorSnapshot;
81
+ private snapshotRealtimeLane;
57
82
  shutdown(): Promise<void>;
58
83
  private createSubmission;
59
84
  private pathsFor;
@@ -61,6 +86,8 @@ export declare class DefaultParallelSyncCoordinator implements ParallelSyncCoord
61
86
  private hasInternallyConflictingPaths;
62
87
  private preemptForRealtime;
63
88
  private drain;
89
+ /** A single bounded push slot keeps disjoint watcher work moving under two held lanes. */
90
+ private startNextOverflowPush;
64
91
  private startNext;
65
92
  private requestsFor;
66
93
  private execute;
@@ -68,6 +95,8 @@ export declare class DefaultParallelSyncCoordinator implements ParallelSyncCoord
68
95
  private isStale;
69
96
  private completeAfterWorkerFailure;
70
97
  private setResult;
98
+ private expireInactivePullYieldStates;
99
+ private touchPullYieldStates;
71
100
  private completeRemaining;
72
101
  private finishIfEmpty;
73
102
  private pruneEpochs;
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-sync-coordinator.d.ts","sourceRoot":"","sources":["../../src/sync/parallel-sync-coordinator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parallel-sync-coordinator.d.ts","sourceRoot":"","sources":["../../src/sync/parallel-sync-coordinator.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,7 @@
1
1
  import { assertCanonicalPath, PathLeaseManager, pathsConflict } from "./path-leases.js";
2
+ const MAX_REALTIME_PULL_YIELDS = 3;
3
+ const MAX_REALTIME_PULL_YIELD_MS = 60_000;
4
+ const REALTIME_PULL_YIELD_STATE_TTL_MS = 10 * 60_000;
2
5
  function identityKey(path) {
3
6
  return `${path.targetUid}\u0000${path.areaId}\u0000${path.canonicalPath}`;
4
7
  }
@@ -28,8 +31,13 @@ export class DefaultParallelSyncCoordinator {
28
31
  planChorePaths;
29
32
  nextId = 1;
30
33
  nextEpoch = 1;
31
- // Each lane owns one slot. Path leases retain the cross-lane mutation fence.
34
+ // Fast and slow realtime lanes retain separate slots. Pulls use both when
35
+ // possible; a queued push can preempt them at the next worker boundary.
32
36
  realtimeRunningByLane = {};
37
+ realtimeOverflowPush;
38
+ pullYieldStates = new Map();
39
+ lastRealtimeAdmissionAt = null;
40
+ lastChoreAdmissionAt = null;
33
41
  choreRunning;
34
42
  stopping = false;
35
43
  shutdownPromise;
@@ -60,6 +68,8 @@ export class DefaultParallelSyncCoordinator {
60
68
  });
61
69
  return;
62
70
  }
71
+ this.touchPullYieldStates(submission);
72
+ this.expireInactivePullYieldStates();
63
73
  if (work.class === "chore" &&
64
74
  work.cursor?.phase !== undefined &&
65
75
  work.cursor.phase !== "apply" &&
@@ -85,12 +95,30 @@ export class DefaultParallelSyncCoordinator {
85
95
  return {
86
96
  realtimeQueued: this.realtimeQueue.filter((submission) => !submission.finished).length,
87
97
  choreQueued: this.choreQueue.filter((submission) => !submission.finished).length,
88
- realtimeRunning: this.realtimeRunningByLane.fast !== undefined || this.realtimeRunningByLane.slow !== undefined,
98
+ realtimeRunning: this.realtimeRunningByLane.fast !== undefined ||
99
+ this.realtimeRunningByLane.slow !== undefined || this.realtimeOverflowPush !== undefined,
100
+ realtimeLanes: {
101
+ fast: this.snapshotRealtimeLane(this.realtimeRunningByLane.fast),
102
+ slow: this.snapshotRealtimeLane(this.realtimeRunningByLane.slow),
103
+ overflowPush: this.snapshotRealtimeLane(this.realtimeOverflowPush),
104
+ },
89
105
  choreRunning: this.choreRunning !== undefined,
106
+ retainedPullYieldStates: this.pullYieldStates.size,
107
+ lastRealtimeAdmissionAt: this.lastRealtimeAdmissionAt,
108
+ lastChoreAdmissionAt: this.lastChoreAdmissionAt,
90
109
  leases: this.leases.inspect(),
91
110
  now: this.clock.now(),
92
111
  };
93
112
  }
113
+ snapshotRealtimeLane(submission) {
114
+ return submission
115
+ ? {
116
+ direction: submission.work.class === "realtime" ? submission.work.direction : undefined,
117
+ source: submission.work.class === "realtime" ? submission.work.source : undefined,
118
+ paths: submission.paths.length,
119
+ }
120
+ : null;
121
+ }
94
122
  shutdown() {
95
123
  if (this.shutdownPromise)
96
124
  return this.shutdownPromise;
@@ -102,10 +130,13 @@ export class DefaultParallelSyncCoordinator {
102
130
  this.choreQueue.length = 0;
103
131
  this.realtimeRunningByLane.fast?.controller.abort();
104
132
  this.realtimeRunningByLane.slow?.controller.abort();
133
+ this.realtimeOverflowPush?.controller.abort();
105
134
  this.choreRunning?.controller.abort();
135
+ this.pullYieldStates.clear();
106
136
  const executions = [
107
137
  this.realtimeRunningByLane.fast?.execution,
108
138
  this.realtimeRunningByLane.slow?.execution,
139
+ this.realtimeOverflowPush?.execution,
109
140
  this.choreRunning?.execution,
110
141
  ]
111
142
  .filter((execution) => execution !== undefined);
@@ -125,6 +156,8 @@ export class DefaultParallelSyncCoordinator {
125
156
  results: new Map(),
126
157
  resolve,
127
158
  controller: new AbortController(),
159
+ supersededPaths: new Set(),
160
+ yieldedToPush: false,
128
161
  running: false,
129
162
  finished: false,
130
163
  };
@@ -174,14 +207,81 @@ export class DefaultParallelSyncCoordinator {
174
207
  queued.paths = queued.paths.filter((path) => !revoked.includes(path));
175
208
  this.finishIfEmpty(queued);
176
209
  }
210
+ if (direction === "push" &&
211
+ this.realtimeRunningByLane.fast &&
212
+ this.realtimeRunningByLane.slow &&
213
+ this.realtimeRunningByLane.fast.work.class === "realtime" &&
214
+ this.realtimeRunningByLane.slow.work.class === "realtime" &&
215
+ this.realtimeRunningByLane.fast.work.direction === "pull" &&
216
+ this.realtimeRunningByLane.slow.work.direction === "pull") {
217
+ const pullToYield = ["slow", "fast"]
218
+ .map((lane) => this.realtimeRunningByLane[lane])
219
+ .find((running) => running?.work.class === "realtime" &&
220
+ running.work.direction === "pull" &&
221
+ !running.paths.some((path) => incoming.paths.some((candidate) => overlaps(path, candidate))));
222
+ if (pullToYield) {
223
+ const pathKeys = pullToYield.paths.map(identityKey);
224
+ const existingStates = pathKeys.map((key) => this.pullYieldStates.get(key)).filter((state) => state !== undefined);
225
+ const now = this.clock.now();
226
+ const state = {
227
+ yields: existingStates.reduce((max, item) => Math.max(max, item.yields), 0),
228
+ startedAt: existingStates.reduce((min, item) => Math.min(min, item.startedAt), now),
229
+ lastSeenAt: now,
230
+ capLogged: existingStates.some((item) => item.capLogged),
231
+ };
232
+ const cumulativeMs = Math.max(0, now - state.startedAt);
233
+ const cap = state.yields >= MAX_REALTIME_PULL_YIELDS
234
+ ? "yield-count"
235
+ : cumulativeMs >= MAX_REALTIME_PULL_YIELD_MS
236
+ ? "cumulative-time"
237
+ : undefined;
238
+ if (cap) {
239
+ for (const key of pathKeys)
240
+ this.pullYieldStates.set(key, { ...state, capLogged: true });
241
+ if (!state.capLogged) {
242
+ process.stderr.write(`hq-sync: realtime pull yield cap reached ${JSON.stringify({
243
+ pullId: pullToYield.id,
244
+ pathCount: pullToYield.paths.length,
245
+ yields: state.yields,
246
+ cumulativeMs,
247
+ cap,
248
+ })}\n`);
249
+ }
250
+ }
251
+ else {
252
+ state.yields += 1;
253
+ for (const key of pathKeys)
254
+ this.pullYieldStates.set(key, state);
255
+ pullToYield.yieldedToPush = true;
256
+ pullToYield.controller.abort();
257
+ if (state.yields === MAX_REALTIME_PULL_YIELDS && !state.capLogged) {
258
+ for (const key of pathKeys)
259
+ this.pullYieldStates.set(key, { ...state, capLogged: true });
260
+ process.stderr.write(`hq-sync: realtime pull yield cap reached ${JSON.stringify({
261
+ pullId: pullToYield.id,
262
+ pathCount: pullToYield.paths.length,
263
+ yields: state.yields,
264
+ cumulativeMs,
265
+ cap: "yield-count",
266
+ })}\n`);
267
+ }
268
+ }
269
+ }
270
+ }
177
271
  for (const running of [
178
272
  this.realtimeRunningByLane.fast,
179
273
  this.realtimeRunningByLane.slow,
274
+ this.realtimeOverflowPush,
180
275
  this.choreRunning,
181
276
  ]) {
182
277
  if (running &&
183
278
  (running.work.class === "chore" || running.work.direction === direction) &&
184
279
  running.paths.some((path) => incoming.paths.some((candidate) => overlaps(path, candidate)))) {
280
+ for (const path of running.paths) {
281
+ if (incoming.paths.some((candidate) => overlaps(path, candidate))) {
282
+ running.supersededPaths.add(identityKey(path));
283
+ }
284
+ }
185
285
  running.controller.abort();
186
286
  }
187
287
  }
@@ -193,27 +293,103 @@ export class DefaultParallelSyncCoordinator {
193
293
  this.startNext("realtime", "fast");
194
294
  if (!this.realtimeRunningByLane.slow)
195
295
  this.startNext("realtime", "slow");
296
+ if (this.realtimeRunningByLane.fast &&
297
+ this.realtimeRunningByLane.slow &&
298
+ !this.realtimeOverflowPush)
299
+ this.startNextOverflowPush();
196
300
  if (!this.choreRunning)
197
301
  this.startNext("chore");
198
302
  }
303
+ /** A single bounded push slot keeps disjoint watcher work moving under two held lanes. */
304
+ startNextOverflowPush() {
305
+ if (this.stopping || this.realtimeOverflowPush)
306
+ return;
307
+ const cappedActivePull = [
308
+ this.realtimeRunningByLane.fast,
309
+ this.realtimeRunningByLane.slow,
310
+ ].some((submission) => submission?.work.class === "realtime" &&
311
+ submission.work.direction === "pull" &&
312
+ submission.paths.some((path) => this.pullYieldStates.get(identityKey(path))?.capLogged));
313
+ if (cappedActivePull)
314
+ return;
315
+ for (const submission of this.realtimeQueue) {
316
+ if (submission.finished || submission.work.class !== "realtime" || submission.work.direction !== "push") {
317
+ continue;
318
+ }
319
+ const lease = this.leases.tryAcquire(submission.id, this.requestsFor(submission));
320
+ if (!lease)
321
+ continue;
322
+ const selectedQueueIndex = this.realtimeQueue.indexOf(submission);
323
+ if (selectedQueueIndex < 0) {
324
+ lease.release();
325
+ continue;
326
+ }
327
+ this.realtimeQueue.splice(selectedQueueIndex, 1);
328
+ submission.lease = lease;
329
+ submission.running = true;
330
+ submission.runningLane = "overflow-push";
331
+ this.realtimeOverflowPush = submission;
332
+ this.lastRealtimeAdmissionAt = this.clock.now();
333
+ submission.execution = this.execute("realtime", submission);
334
+ return;
335
+ }
336
+ }
199
337
  startNext(kind, lane) {
200
338
  const queue = kind === "realtime" ? this.realtimeQueue : this.choreQueue;
201
- for (let index = 0; index < queue.length; index += 1) {
202
- const submission = queue[index];
203
- if (submission.finished)
339
+ const entries = queue.map((candidate, queueIndex) => ({ candidate, queueIndex }));
340
+ const protectedPulls = new Set();
341
+ for (const push of entries) {
342
+ if (push.candidate.work.class !== "realtime" || push.candidate.work.direction !== "push")
204
343
  continue;
205
- if (kind === "realtime" && this.realtimeLane(submission) !== lane)
344
+ for (const earlier of entries) {
345
+ if (earlier.queueIndex >= push.queueIndex)
346
+ break;
347
+ if (earlier.candidate.work.class === "realtime" &&
348
+ earlier.candidate.work.direction === "pull" &&
349
+ earlier.candidate.paths.some((pullPath) => push.candidate.paths.some((pushPath) => overlaps(pullPath, pushPath))))
350
+ protectedPulls.add(earlier.queueIndex);
351
+ }
352
+ }
353
+ const ordered = [
354
+ ...entries.filter((entry) => protectedPulls.has(entry.queueIndex)),
355
+ ...entries.filter((entry) => !protectedPulls.has(entry.queueIndex) && entry.candidate.work.class === "realtime" && entry.candidate.work.direction === "push"),
356
+ ...entries.filter((entry) => !protectedPulls.has(entry.queueIndex) && !(entry.candidate.work.class === "realtime" && entry.candidate.work.direction === "push")),
357
+ ];
358
+ for (const selected of ordered) {
359
+ const submission = selected.candidate;
360
+ if (submission.finished)
206
361
  continue;
362
+ let assignedLane;
363
+ if (kind === "realtime") {
364
+ const preferredLane = this.realtimeLane(submission);
365
+ const pushMayUseFreeLane = submission.work.class === "realtime" &&
366
+ submission.work.direction === "push" && preferredLane !== lane &&
367
+ this.realtimeRunningByLane[preferredLane]?.work.class === "realtime" &&
368
+ this.realtimeRunningByLane[preferredLane]?.work.direction === "pull";
369
+ assignedLane = pushMayUseFreeLane ? lane : preferredLane;
370
+ if (assignedLane !== lane)
371
+ continue;
372
+ }
207
373
  const lease = this.leases.tryAcquire(submission.id, this.requestsFor(submission));
208
374
  if (!lease)
209
375
  continue;
210
- queue.splice(index, 1);
376
+ const selectedQueueIndex = queue.indexOf(submission);
377
+ if (selectedQueueIndex === -1)
378
+ continue;
379
+ queue.splice(selectedQueueIndex, 1);
211
380
  submission.lease = lease;
212
381
  submission.running = true;
213
- if (kind === "realtime")
214
- this.realtimeRunningByLane[this.realtimeLane(submission)] = submission;
215
- else
382
+ if (kind === "realtime") {
383
+ submission.runningLane = assignedLane;
384
+ // Keep the original work object as the execution registry key. The
385
+ // physical lane is tracked separately in runningLane.
386
+ this.realtimeRunningByLane[assignedLane] = submission;
387
+ this.lastRealtimeAdmissionAt = this.clock.now();
388
+ }
389
+ else {
216
390
  this.choreRunning = submission;
391
+ this.lastChoreAdmissionAt = this.clock.now();
392
+ }
217
393
  submission.execution = this.execute(kind, submission);
218
394
  return;
219
395
  }
@@ -245,8 +421,13 @@ export class DefaultParallelSyncCoordinator {
245
421
  finally {
246
422
  submission.lease?.release();
247
423
  submission.running = false;
248
- if (kind === "realtime")
249
- this.realtimeRunningByLane[this.realtimeLane(submission)] = undefined;
424
+ if (kind === "realtime") {
425
+ if (submission.runningLane === "overflow-push")
426
+ this.realtimeOverflowPush = undefined;
427
+ else
428
+ this.realtimeRunningByLane[submission.runningLane ?? this.realtimeLane(submission)] = undefined;
429
+ submission.runningLane = undefined;
430
+ }
250
431
  else
251
432
  this.choreRunning = undefined;
252
433
  this.finishIfEmpty(submission);
@@ -260,7 +441,8 @@ export class DefaultParallelSyncCoordinator {
260
441
  }
261
442
  const byPath = new Map(outcome.paths.map((result) => [result.path, result]));
262
443
  for (const path of submission.paths) {
263
- if (this.isStale(path, submission.work.class === "realtime" ? submission.work.direction : undefined)) {
444
+ if (submission.supersededPaths.has(identityKey(path)) ||
445
+ this.isStale(path, submission.work.class === "realtime" ? submission.work.direction : undefined)) {
264
446
  this.setResult(submission, path, "refused", "stale path epoch");
265
447
  continue;
266
448
  }
@@ -269,7 +451,9 @@ export class DefaultParallelSyncCoordinator {
269
451
  this.setResult(submission, path, "retryable", outcome.error ?? "worker omitted or mismatched a path outcome");
270
452
  continue;
271
453
  }
272
- this.setResult(submission, path, result.status, result.reason);
454
+ this.setResult(submission, path, result.status, submission.yieldedToPush && result.status === "retryable"
455
+ ? "yielded to queued watcher push"
456
+ : result.reason);
273
457
  }
274
458
  }
275
459
  isStale(path, direction) {
@@ -284,16 +468,45 @@ export class DefaultParallelSyncCoordinator {
284
468
  for (const path of submission.paths) {
285
469
  if (submission.results.has(identityKey(path)))
286
470
  continue;
287
- if (this.isStale(path, submission.work.class === "realtime" ? submission.work.direction : undefined)) {
471
+ if (submission.supersededPaths.has(identityKey(path)) ||
472
+ this.isStale(path, submission.work.class === "realtime" ? submission.work.direction : undefined)) {
288
473
  this.setResult(submission, path, "refused", "stale path epoch");
289
474
  }
290
475
  else
291
- this.setResult(submission, path, "retryable", reason);
476
+ this.setResult(submission, path, "retryable", submission.yieldedToPush ? "yielded to queued watcher push" : reason);
292
477
  }
293
478
  this.finishIfEmpty(submission);
294
479
  }
295
480
  setResult(submission, path, status, reason) {
296
481
  submission.results.set(identityKey(path), { path: path.canonicalPath, status, epoch: path.epoch, ...(reason ? { reason } : {}) });
482
+ if (submission.work.class === "realtime" &&
483
+ submission.work.direction === "pull" &&
484
+ (status !== "retryable" || reason !== "yielded to queued watcher push")) {
485
+ for (const path of submission.paths)
486
+ this.pullYieldStates.delete(identityKey(path));
487
+ }
488
+ }
489
+ expireInactivePullYieldStates() {
490
+ const activePaths = new Set([
491
+ this.realtimeRunningByLane.fast,
492
+ this.realtimeRunningByLane.slow,
493
+ this.realtimeOverflowPush,
494
+ ].flatMap((submission) => submission?.paths.map(identityKey) ?? []));
495
+ const now = this.clock.now();
496
+ for (const [key, state] of this.pullYieldStates) {
497
+ if (!activePaths.has(key) && now - state.lastSeenAt >= REALTIME_PULL_YIELD_STATE_TTL_MS) {
498
+ this.pullYieldStates.delete(key);
499
+ }
500
+ }
501
+ }
502
+ touchPullYieldStates(submission) {
503
+ const now = this.clock.now();
504
+ for (const path of submission.paths) {
505
+ const key = identityKey(path);
506
+ const state = this.pullYieldStates.get(key);
507
+ if (state)
508
+ this.pullYieldStates.set(key, { ...state, lastSeenAt: now });
509
+ }
297
510
  }
298
511
  completeRemaining(submission, status, reason) {
299
512
  for (const path of submission.paths) {