@cortexkit/opencode-magic-context 0.44.2 → 0.44.3

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 (73) hide show
  1. package/dist/{conflict-warning-hook-1msyvb51.js → conflict-warning-hook-hmpzxep6.js} +3 -3
  2. package/dist/{derive-budgets-gd2270s0.js → derive-budgets-vjmvh6pz.js} +3 -1
  3. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  4. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  5. package/dist/features/magic-context/dreamer/lease.d.ts +1 -1
  6. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  7. package/dist/features/magic-context/memory/project-identity.d.ts +3 -0
  8. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  9. package/dist/features/magic-context/message-index-async.d.ts +1 -1
  10. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  11. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  12. package/dist/features/magic-context/session-project-storage.d.ts +5 -5
  13. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  14. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  15. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -1
  16. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  17. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  18. package/dist/hooks/magic-context/compartment-runner-types.d.ts +1 -0
  19. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/derive-budgets.d.ts +4 -0
  21. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/lkg-persist.d.ts +1 -4
  24. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/producer-window-guard.d.ts +4 -1
  26. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/rust-mode-transform.d.ts +1 -0
  28. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/storage-busy-refusal.d.ts +6 -0
  30. package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -1
  31. package/dist/{index-r9vkp4n9.js → index-33q7s9y2.js} +1 -1
  32. package/dist/{index-egkfvhms.js → index-4an2p8qa.js} +80 -14
  33. package/dist/{index-18tjha8g.js → index-638hf49n.js} +1 -1
  34. package/dist/{index-stb5fg12.js → index-9y5p0d50.js} +31 -1
  35. package/dist/{index-esxfcz5z.js → index-dgg5y7er.js} +1 -1
  36. package/dist/{index-3x9caerx.js → index-nf9sk8sh.js} +3 -3
  37. package/dist/{index-gtzcmv90.js → index-q5p1aqvv.js} +5 -5
  38. package/dist/{index-40s1xz22.js → index-rdsaxnf2.js} +1 -1
  39. package/dist/{index-ttdn47aq.js → index-yhm60r53.js} +134 -49
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +453 -226
  42. package/dist/plugin/dream-timer.d.ts.map +1 -1
  43. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  44. package/dist/plugin/messages-transform.d.ts.map +1 -1
  45. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  46. package/dist/{read-session-chunk-wmvgnd24.js → read-session-chunk-n072mcq4.js} +2 -2
  47. package/dist/{recomp-orchestrator-rk40ff15.js → recomp-orchestrator-19tr6zya.js} +6 -6
  48. package/dist/{send-session-notification-6xsrcxnp.js → send-session-notification-04hvd54c.js} +2 -2
  49. package/dist/shared/run-token-log.d.ts +13 -0
  50. package/dist/shared/run-token-log.d.ts.map +1 -0
  51. package/dist/shared/sqlite.d.ts +7 -0
  52. package/dist/shared/sqlite.d.ts.map +1 -1
  53. package/dist/{transform-postprocess-phase-t7xgdhdf.js → transform-postprocess-phase-z2mfc5w1.js} +6 -6
  54. package/dist/v2/hidden-completion.d.ts +7 -1
  55. package/dist/v2/hidden-completion.d.ts.map +1 -1
  56. package/dist/v2/hooks/context.d.ts.map +1 -1
  57. package/dist/v2/hooks/hidden-terminal-error.d.ts +8 -0
  58. package/dist/v2/hooks/hidden-terminal-error.d.ts.map +1 -0
  59. package/dist/v2/hooks/tools.d.ts +1 -1
  60. package/dist/v2/hooks/tools.d.ts.map +1 -1
  61. package/dist/v2/server.js +584 -153
  62. package/dist/{wrapup-orchestrator-h8tr10c6.js → wrapup-orchestrator-sy4m56a7.js} +7 -7
  63. package/package.json +1 -1
  64. package/src/config/latch-permanence-guard.test.ts +4 -0
  65. package/src/shared/data-path.test.ts +1 -1
  66. package/src/shared/models-dev-cache.test.ts +30 -1
  67. package/src/shared/run-token-log.test.ts +65 -0
  68. package/src/shared/run-token-log.ts +39 -0
  69. package/src/shared/sqlite-acquisition-routing.test.ts +19 -11
  70. package/src/shared/sqlite-pass-scope.test.ts +115 -144
  71. package/src/shared/sqlite.ts +123 -20
  72. package/src/shared/storage-busy.test.ts +34 -57
  73. package/src/shared/write-transaction-attribution.test.ts +13 -11
@@ -224,7 +224,9 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
224
224
  writable: true,
225
225
  value: (sql: string) => {
226
226
  if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
227
- retryAcquisition(() => nativeExec(sql), sql.trim());
227
+ if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore())
228
+ acquireShort(db, () => nativeExec(sql), sql.trim());
229
+ else nativeExec(sql);
228
230
  return db;
229
231
  }
230
232
  return nativeExec(sql);
@@ -489,6 +491,13 @@ export type Statement = BetterSqlite3.Statement<unknown[], unknown>;
489
491
 
490
492
  const privilegeDepth = new WeakMap<Database, number>();
491
493
  const transformPassScope = new AsyncLocalStorage<{ active: boolean } | undefined>();
494
+ const admissionScope = new AsyncLocalStorage<boolean>();
495
+ const backgroundWriterScope = new AsyncLocalStorage<boolean>();
496
+
497
+ /** Opt in only a writer that can safely defer its work after a busy acquisition. */
498
+ export function withSqliteBackgroundWriter<T>(operation: () => T): T {
499
+ return backgroundWriterScope.run(true, operation);
500
+ }
492
501
 
493
502
  /** Only an awaited foreground transform may spend the extra acquisition budget.
494
503
  * The mutable lease also expires for detached descendants when that pass ends. */
@@ -530,35 +539,123 @@ export class SqliteAcquisitionBusyError extends Error {
530
539
  readonly code = "SQLITE_BUSY";
531
540
  readonly stage: string;
532
541
  constructor(cause: unknown, stage = "BEGIN IMMEDIATE") {
533
- super("SQLite writer acquisition remained busy after 3 attempts", { cause });
542
+ super("SQLite writer acquisition remained busy", { cause });
534
543
  this.name = "SqliteAcquisitionBusyError";
535
544
  this.stage = stage;
536
545
  }
537
546
  }
538
547
 
539
- /** Retry only acquisition: no privilege flag, callback or in-memory mutation has run yet. */
540
- function retryAcquisition(acquire: () => unknown, stage: string): void {
541
- // Maintenance writers retry on their next tick. Multiplying their native
542
- // busy timeout here would stall every session sharing the host event loop.
543
- if (!transformPassScope.getStore()?.active) {
548
+ const SHORT_BUSY_TIMEOUT_MS = 25;
549
+ const FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 250;
550
+ const FOREGROUND_ACQUISITION_BUDGET_MS = 16_500;
551
+
552
+ /** The connection is never handed back to another caller with a shortened timeout. */
553
+ function acquireShort(db: Database, acquire: () => unknown, site: string): void {
554
+ const started = performance.now();
555
+ const previous = pragmaNumber(db, "busy_timeout");
556
+ let acquired = false;
557
+ try {
558
+ // Async admission retries after yielding, so each of its BEGIN attempts
559
+ // stays short. An ordinary BEGIN inside a transform pass cannot yield;
560
+ // give that single attempt enough time for a brief writer to finish.
561
+ const timeout =
562
+ transformPassScope.getStore()?.active &&
563
+ !admissionScope.getStore() &&
564
+ !backgroundWriterScope.getStore()
565
+ ? FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS
566
+ : SHORT_BUSY_TIMEOUT_MS;
567
+ db.exec(`PRAGMA busy_timeout=${timeout}`);
544
568
  acquire();
545
- return;
569
+ acquired = true;
570
+ } catch (error) {
571
+ if (transformPassScope.getStore()?.active && isTransientSqliteError(error))
572
+ throw new SqliteAcquisitionBusyError(error, site);
573
+ throw error;
574
+ } finally {
575
+ if (previous !== null) db.exec(`PRAGMA busy_timeout=${previous}`);
576
+ const elapsed = performance.now() - started;
577
+ if (elapsed >= 250)
578
+ console.warn(
579
+ `[${new Date().toISOString()}] [magic-context] sqlite acquisition site=${site} lane=${transformPassScope.getStore()?.active ? "foreground" : "background"} elapsed=${Math.round(elapsed)}ms attempts=1 outcome=${acquired ? "acquired" : "busy"}`,
580
+ );
546
581
  }
547
- const delays = [500, 1000];
548
- for (let attempt = 0; ; attempt++) {
582
+ }
583
+
584
+ /** Begin an immediate transaction with bounded asynchronous retries on writer contention.
585
+ * Callers must recheck any lease or source snapshot after this function returns. */
586
+ export async function beginSqliteWriterAsync(db: Database, site: string): Promise<void> {
587
+ const started = performance.now();
588
+ let attempts = 0;
589
+ for (;;) {
590
+ attempts++;
549
591
  try {
550
- acquire();
592
+ withSqliteBackgroundWriter(() => db.exec("BEGIN IMMEDIATE"));
593
+ const elapsed = performance.now() - started;
594
+ if (elapsed >= 250)
595
+ console.warn(
596
+ `[${new Date().toISOString()}] [magic-context] sqlite acquisition site=${site} lane=background elapsed=${Math.round(elapsed)}ms attempts=${attempts} outcome=acquired`,
597
+ );
551
598
  return;
552
599
  } catch (error) {
553
- // Handles created by this module already retry inside exec. Do not
554
- // apply the attempt budget twice; externally supplied handles still
555
- // need the acquisition retry performed by withPrivilegedWriter.
556
- if (error instanceof SqliteAcquisitionBusyError || !isTransientSqliteError(error))
600
+ if (!isTransientSqliteError(error)) throw error;
601
+ const elapsed = performance.now() - started;
602
+ if (elapsed >= FOREGROUND_ACQUISITION_BUDGET_MS) {
603
+ console.warn(
604
+ `[${new Date().toISOString()}] [magic-context] sqlite acquisition site=${site} lane=background elapsed=${Math.round(elapsed)}ms attempts=${attempts} outcome=busy`,
605
+ );
557
606
  throw error;
558
- if (attempt === delays.length) throw new SqliteAcquisitionBusyError(error, stage);
559
- // The database API is synchronous on both hosts. With busy_timeout=5000,
560
- // three attempts plus these waits bound one acquisition to 16.5 seconds.
561
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delays[attempt]);
607
+ }
608
+ await new Promise<void>((resolve) =>
609
+ setTimeout(
610
+ resolve,
611
+ Math.min(
612
+ attempts === 1 ? 500 : 1000,
613
+ FOREGROUND_ACQUISITION_BUDGET_MS - elapsed,
614
+ ),
615
+ ),
616
+ );
617
+ }
618
+ }
619
+ }
620
+
621
+ /** Retry admission before any turn work, yielding between short lock attempts. */
622
+ export async function withAsyncPrivilegedWriter<T>(db: Database, operation: () => T): Promise<T> {
623
+ const started = performance.now();
624
+ let attempts = 0;
625
+ for (;;) {
626
+ attempts++;
627
+ try {
628
+ const result = admissionScope.run(true, () =>
629
+ withSqliteTransformPass(() => withPrivilegedWriter(db, operation)),
630
+ );
631
+ const elapsed = performance.now() - started;
632
+ if (elapsed >= 250)
633
+ console.warn(
634
+ `[${new Date().toISOString()}] [magic-context] sqlite acquisition site=privileged_writer lane=foreground elapsed=${Math.round(elapsed)}ms attempts=${attempts} outcome=acquired`,
635
+ );
636
+ return result;
637
+ } catch (error) {
638
+ // A callback failure can occur after writes; only retry a failed BEGIN.
639
+ if (!(error instanceof SqliteAcquisitionBusyError)) throw error;
640
+ const elapsed = performance.now() - started;
641
+ if (elapsed >= FOREGROUND_ACQUISITION_BUDGET_MS) {
642
+ if (elapsed >= 250)
643
+ console.warn(
644
+ `[${new Date().toISOString()}] [magic-context] sqlite acquisition site=privileged_writer lane=foreground elapsed=${Math.round(elapsed)}ms attempts=${attempts} outcome=busy`,
645
+ );
646
+ throw error instanceof SqliteAcquisitionBusyError
647
+ ? error
648
+ : new SqliteAcquisitionBusyError(error);
649
+ }
650
+ await new Promise<void>((resolve) =>
651
+ setTimeout(
652
+ resolve,
653
+ Math.min(
654
+ attempts === 1 ? 500 : 1000,
655
+ FOREGROUND_ACQUISITION_BUDGET_MS - elapsed,
656
+ ),
657
+ ),
658
+ );
562
659
  }
563
660
  }
564
661
  }
@@ -587,7 +684,13 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
587
684
  if (nested) {
588
685
  db.exec(`SAVEPOINT ${savepoint}`);
589
686
  } else {
590
- retryAcquisition(() => db.exec("BEGIN IMMEDIATE"), "BEGIN IMMEDIATE");
687
+ try {
688
+ db.exec("BEGIN IMMEDIATE");
689
+ } catch (error) {
690
+ if (transformPassScope.getStore()?.active && isTransientSqliteError(error))
691
+ throw new SqliteAcquisitionBusyError(error);
692
+ throw error;
693
+ }
591
694
  }
592
695
  privilegeDepth.set(db, previousDepth + 1);
593
696
  try {
@@ -1,70 +1,47 @@
1
- import { afterAll, afterEach, describe, expect, spyOn, test } from "bun:test";
1
+ import { describe, expect, test } from "bun:test";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
2
5
  import {
3
6
  Database,
4
7
  isTransientSqliteError,
5
- withSqliteTransformPass,
6
- withPrivilegedWriter as writePrivileged,
8
+ withAsyncPrivilegedWriter,
9
+ withPrivilegedWriter,
7
10
  } from "./sqlite";
8
11
 
9
- const withPrivilegedWriter = <T>(db: Database, operation: () => T): T =>
10
- withSqliteTransformPass(() => writePrivileged(db, operation));
11
-
12
- const wait = spyOn(Atomics, "wait");
13
- afterEach(() => wait.mockClear());
14
- afterAll(() => wait.mockRestore());
15
-
16
- describe("writer acquisition backoff", () => {
17
- for (const clearsOn of [2, 3]) {
18
- test(`acquisition clears on attempt ${clearsOn} and invokes callback exactly once`, () => {
19
- const db = new Database(":memory:");
20
- db.exec(
21
- "CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER); CREATE TABLE result(value TEXT)",
22
- );
23
- const exec = db.exec.bind(db);
24
- let attempts = 0;
25
- let callbacks = 0;
26
- const delays: number[] = [];
27
- wait.mockImplementation((_array, _index, _value, timeout) => {
28
- delays.push(timeout!);
29
- return "timed-out";
30
- });
31
- const intercepted = spyOn(db, "exec").mockImplementation((sql) => {
32
- if (sql === "BEGIN IMMEDIATE" && ++attempts < clearsOn)
33
- throw Object.assign(new Error("locked"), { code: "SQLITE_BUSY" });
34
- return exec(sql);
35
- });
36
- try {
37
- const result = withPrivilegedWriter(db, () => {
38
- callbacks++;
39
- db.prepare("INSERT INTO result VALUES (?)").run("managed");
40
- return JSON.stringify(db.prepare("SELECT * FROM result").all());
41
- });
42
- expect(result).toBe('[{"value":"managed"}]');
43
- expect(attempts).toBe(clearsOn);
44
- expect(callbacks).toBe(1);
45
- expect(delays).toEqual([500, 1000].slice(0, clearsOn - 1));
46
- } finally {
47
- intercepted.mockRestore();
48
- db.close();
49
- }
50
- });
51
- }
52
- test("exhausted acquisition never invokes callback", () => {
53
- const db = new Database(":memory:");
12
+ describe("writer acquisition", () => {
13
+ test("exhausted async admission preserves the foreground budget and never invokes the callback", async () => {
14
+ const dir = mkdtempSync(join(tmpdir(), "mc-writer-budget-"));
15
+ const path = join(dir, "context.db");
16
+ const blocker = new Database(path);
17
+ blocker.exec(
18
+ "CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER)",
19
+ );
20
+ const db = new Database(path);
21
+ db.exec("PRAGMA busy_timeout=5000");
22
+ blocker.exec("BEGIN IMMEDIATE");
54
23
  let calls = 0;
55
- wait.mockImplementation(() => "timed-out");
56
- const exec = spyOn(db, "exec").mockImplementation(() => {
57
- throw Object.assign(new Error("original lock"), { code: "SQLITE_LOCKED" });
58
- });
24
+ let ticks = 0;
25
+ const timer = setInterval(() => ticks++, 50);
26
+ const started = performance.now();
59
27
  try {
60
- expect(() => withPrivilegedWriter(db, () => calls++)).toThrow("after 3 attempts");
61
- expect(exec).toHaveBeenCalledTimes(3);
28
+ await expect(withAsyncPrivilegedWriter(db, () => calls++)).rejects.toThrow(
29
+ "acquisition remained busy",
30
+ );
31
+ expect(performance.now() - started).toBeGreaterThanOrEqual(16_500);
32
+ expect(performance.now() - started).toBeLessThan(17_500);
33
+ expect(ticks).toBeGreaterThan(100);
62
34
  expect(calls).toBe(0);
35
+ expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
63
36
  } finally {
64
- exec.mockRestore();
37
+ clearInterval(timer);
38
+ blocker.exec("ROLLBACK");
39
+ blocker.close();
65
40
  db.close();
41
+ rmSync(dir, { recursive: true, force: true });
66
42
  }
67
- });
43
+ }, 30000);
44
+
68
45
  test("busy callback rolls back without retrying mutations", () => {
69
46
  const db = new Database(":memory:");
70
47
  db.exec(
@@ -81,11 +58,11 @@ describe("writer acquisition backoff", () => {
81
58
  ).toThrow("after acquisition");
82
59
  expect(calls).toBe(1);
83
60
  expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
84
- expect(wait).not.toHaveBeenCalled();
85
61
  } finally {
86
62
  db.close();
87
63
  }
88
64
  });
65
+
89
66
  test("recognizes Bun extended and Node numeric contention codes only", () => {
90
67
  expect(isTransientSqliteError({ code: "SQLITE_BUSY_SNAPSHOT" })).toBe(true);
91
68
  expect(isTransientSqliteError({ code: "ERR_SQLITE_ERROR", errcode: 5 })).toBe(true);
@@ -6,7 +6,7 @@ import { join, resolve } from "node:path";
6
6
  const repoRoot = resolve(import.meta.dir, "../../../../");
7
7
  const beginImmediate = /\b(?:[A-Za-z_$][\w$]*\.)?exec\("BEGIN IMMEDIATE"\)/g;
8
8
 
9
- const fencedSources: Array<{ path: string; sites: string[] }> = [
9
+ const fencedSources: Array<{ path: string; sites: string[]; reporterCalls?: string[] }> = [
10
10
  {
11
11
  path: "packages/plugin/src/features/magic-context/smart-notes/storage.ts",
12
12
  sites: ["smart_note_commit"],
@@ -52,8 +52,8 @@ const fencedSources: Array<{ path: string; sites: string[] }> = [
52
52
  // The chokepoint cannot import the logging chain (Node executes it
53
53
  // directly), so it reports through the injected reporter instead.
54
54
  path: "packages/plugin/src/shared/sqlite.ts",
55
- sites: ["privileged_writer"],
56
- reporterCall: "reportSlowPrivilegedWrite?.(",
55
+ sites: ["async_acquisition_dynamic_site", "privileged_writer"],
56
+ reporterCalls: ["console.warn(", "reportSlowPrivilegedWrite?.("],
57
57
  },
58
58
  {
59
59
  path: "packages/plugin/src/features/magic-context/git-commits/sweep-coordinator.ts",
@@ -75,10 +75,6 @@ const fencedSources: Array<{ path: string; sites: string[] }> = [
75
75
  path: "packages/plugin/src/hooks/magic-context/compartment-runner-recomp.ts",
76
76
  sites: ["historian-publish:recomp"],
77
77
  },
78
- {
79
- path: "packages/plugin/src/hooks/magic-context/compartment-runner-incremental.ts",
80
- sites: ["historian-publish"],
81
- },
82
78
  {
83
79
  path: "packages/plugin/src/features/magic-context/dreamer/lease.ts",
84
80
  sites: ["lease_dynamic_site"],
@@ -98,6 +94,10 @@ const fencedSources: Array<{ path: string; sites: string[] }> = [
98
94
  ];
99
95
 
100
96
  const nonBeginCoveredSites: Array<{ path: string; site: string }> = [
97
+ {
98
+ path: "packages/plugin/src/hooks/magic-context/compartment-runner-incremental.ts",
99
+ site: "historian-publish",
100
+ },
101
101
  {
102
102
  path: "packages/plugin/src/features/magic-context/message-index.ts",
103
103
  site: "message_index_clear",
@@ -159,7 +159,7 @@ function sourceFor(relativePath: string): string {
159
159
  function assertCoveredBeginImmediate(
160
160
  source: string,
161
161
  sites: string[],
162
- reporterCall = "logSlowWriteTransaction(",
162
+ reporterCalls: string[] = [],
163
163
  ): void {
164
164
  const matches = [...source.matchAll(beginImmediate)];
165
165
  expect(matches).toHaveLength(sites.length);
@@ -167,8 +167,10 @@ function assertCoveredBeginImmediate(
167
167
  const match = matches[index];
168
168
  const nextBegin = matches[index + 1]?.index ?? source.length;
169
169
  const transactionRegion = source.slice(match.index, nextBegin);
170
- expect(transactionRegion).toContain(reporterCall);
171
- if (sites[index] === "lease_dynamic_site") {
170
+ expect(transactionRegion).toContain(reporterCalls[index] ?? "logSlowWriteTransaction(");
171
+ if (sites[index] === "async_acquisition_dynamic_site") {
172
+ expect(transactionRegion).toContain("site=${site}");
173
+ } else if (sites[index] === "lease_dynamic_site") {
172
174
  expect(transactionRegion).toContain("logSlowWriteTransaction(site");
173
175
  } else {
174
176
  expect(transactionRegion).toContain(`"${sites[index]}"`);
@@ -219,7 +221,7 @@ describe("write transaction attribution fences", () => {
219
221
  assertCoveredBeginImmediate(
220
222
  sourceFor(fencedSource.path),
221
223
  fencedSource.sites,
222
- "reporterCall" in fencedSource ? fencedSource.reporterCall : undefined,
224
+ fencedSource.reporterCalls,
223
225
  );
224
226
  }
225
227
  for (const coveredSite of nonBeginCoveredSites) {