@retaw106/mmc-oc 2.2.1 → 2.3.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.
- package/dist/cli.js +2 -2
- package/dist/config/deprecated-config.d.ts +4 -0
- package/dist/config/deprecated-config.d.ts.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +2 -2
- package/dist/config/schema/magic-context.d.ts +3 -3
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config-init.js +2 -2
- package/dist/{context-mrvm92n8.js → context-wt7g4f8k.js} +1641 -1543
- package/dist/{derive-budgets-rjjz5f7y.js → derive-budgets-s1p37t2g.js} +2 -2
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/historian-failure-reason.d.ts +7 -0
- package/dist/features/magic-context/historian-failure-reason.d.ts.map +1 -0
- package/dist/features/magic-context/message-index-async.d.ts +21 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +29 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts +2 -0
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
- package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -5
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts +5 -1
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +155 -5
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +2 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +3 -0
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +7 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts +2 -2
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/history-boundary-repair.d.ts +11 -2
- package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +10 -13
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-replay.d.ts +16 -9
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +141 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
- package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
- package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
- package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
- package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +22 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +123 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +41 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +38 -24
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
- package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +18 -5
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +19 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +14 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts +2 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +7 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +21 -4
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index-18yrysyj.js +1477 -0
- package/dist/{index-g2z2k5m4.js → index-3gj1ak4c.js} +2 -2
- package/dist/{index-5cep2r9n.js → index-5ty9rnbx.js} +60 -258
- package/dist/{index-amycb7b1.js → index-a5mw0xp3.js} +3 -3
- package/dist/{index-1j34a56j.js → index-czba8tw3.js} +266 -32
- package/dist/{index-qbkzdkk0.js → index-k59af64t.js} +6 -2
- package/dist/{index-53g38ggt.js → index-kmbme1v1.js} +1 -1
- package/dist/{index-5b7x80ec.js → index-kw21z5pe.js} +6055 -3973
- package/dist/{index-33gprt9g.js → index-yjv8dpht.js} +1 -1
- package/dist/{index-btp5tdc8.js → index-z2w1eq3y.js} +840 -456
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +114 -2
- package/dist/{message-time-backfill-phrwp2fz.js → message-time-backfill-sykevdax.js} +3 -3
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-2xm4sc4y.js → read-session-chunk-863d6c06.js} +6 -4
- package/dist/recomp-orchestrator-wrjy3qym.js +21 -0
- package/dist/{safe-notification-target-ph3xd1ve.js → safe-notification-target-1jkf0m82.js} +2 -2
- package/dist/{send-session-notification-rnc4nrsr.js → send-session-notification-cz6ev088.js} +5 -5
- package/dist/shared/auto-search-lifecycle.d.ts +14 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/models-dev-temperature.d.ts +18 -0
- package/dist/shared/models-dev-temperature.d.ts.map +1 -0
- package/dist/shared/processed-image-eligibility.d.ts +22 -0
- package/dist/shared/processed-image-eligibility.d.ts.map +1 -0
- package/dist/shared/project-directory-key.d.ts +16 -0
- package/dist/shared/project-directory-key.d.ts.map +1 -1
- package/dist/shared/recovery-reasoning-prefix.d.ts +9 -0
- package/dist/shared/recovery-reasoning-prefix.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +33 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/storage-file-mutex.d.ts +9 -0
- package/dist/shared/storage-file-mutex.d.ts.map +1 -0
- package/dist/shared/storage-permissions.d.ts +6 -0
- package/dist/shared/storage-permissions.d.ts.map +1 -1
- package/dist/shared/subagent-temperature.d.ts +46 -0
- package/dist/shared/subagent-temperature.d.ts.map +1 -0
- package/dist/shared/tag-owner-id.d.ts +1 -0
- package/dist/shared/tag-owner-id.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +9 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +9 -66
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/standalone-plugin-marker.d.ts +8 -0
- package/dist/standalone-plugin-marker.d.ts.map +1 -0
- package/dist/tools/ctx-expand/search-archive.d.ts +4 -0
- package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts +1 -2
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
- package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
- package/dist/v2/hooks/generate.d.ts +9 -2
- package/dist/v2/hooks/generate.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
- package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
- package/dist/v2/server.d.ts.map +1 -1
- package/dist/v2/server.js +34550 -30855
- package/dist/web/main.js +373 -19
- package/dist/{wrapup-orchestrator-yknks3ad.js → wrapup-orchestrator-bmybc5p5.js} +10 -10
- package/package.json +1 -1
- package/src/config/deprecated-config.ts +18 -0
- package/src/config/index.test.ts +13 -37
- package/src/config/index.ts +2 -2
- package/src/config/project-security.ts +3 -3
- package/src/config/schema/magic-context.ts +10 -6
- package/src/shared/auto-search-lifecycle.ts +43 -0
- package/src/shared/logger.ts +10 -2
- package/src/shared/models-dev-cache.ts +1 -7
- package/src/shared/models-dev-temperature.ts +107 -0
- package/src/shared/processed-image-eligibility.test.ts +68 -0
- package/src/shared/processed-image-eligibility.ts +41 -0
- package/src/shared/processed-image-position-review.json +20 -0
- package/src/shared/processed-image-position-review.test.ts +19 -0
- package/src/shared/project-directory-key.ts +20 -0
- package/src/shared/recovery-reasoning-prefix.test.ts +34 -0
- package/src/shared/recovery-reasoning-prefix.ts +35 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +4 -3
- package/src/shared/sqlite-foreground-wait.test.ts +68 -0
- package/src/shared/sqlite-pass-scope.test.ts +4 -4
- package/src/shared/sqlite-writer-diagnostics.test.ts +52 -12
- package/src/shared/sqlite.ts +380 -39
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/storage-file-mutex.test.ts +50 -0
- package/src/shared/storage-file-mutex.ts +130 -0
- package/src/shared/storage-permissions.ts +46 -0
- package/src/shared/subagent-temperature.ts +110 -0
- package/src/shared/tag-owner-id.ts +13 -0
- package/src/shared/tag-transcript.ts +118 -0
- package/src/shared/window-geometry.test.ts +102 -236
- package/src/shared/window-geometry.ts +23 -413
- package/dist/index-ramz5kkm.js +0 -514
- package/dist/recomp-orchestrator-frmwj9hz.js +0 -21
- package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { log } from "./logger";
|
|
6
|
+
import {
|
|
7
|
+
Database,
|
|
8
|
+
guardSqliteTransformPass,
|
|
9
|
+
registerSqliteDiagnosticSink,
|
|
10
|
+
SqliteAcquisitionBusyError,
|
|
11
|
+
withPrivilegedWriter,
|
|
12
|
+
withSqliteTransformPass,
|
|
13
|
+
} from "./sqlite";
|
|
14
|
+
import { createTestTempDirFromPath } from "./test-temp-dir";
|
|
15
|
+
|
|
16
|
+
function fixture() {
|
|
17
|
+
const dir = createTestTempDirFromPath(join(tmpdir(), "mc-foreground-wait-"));
|
|
18
|
+
const path = join(dir, "context.db");
|
|
19
|
+
const db = new Database(path);
|
|
20
|
+
db.exec(`
|
|
21
|
+
PRAGMA journal_mode=WAL;
|
|
22
|
+
PRAGMA busy_timeout=5000;
|
|
23
|
+
CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER);
|
|
24
|
+
CREATE TABLE result(value TEXT);
|
|
25
|
+
`);
|
|
26
|
+
return {
|
|
27
|
+
db,
|
|
28
|
+
path,
|
|
29
|
+
close() {
|
|
30
|
+
db.close();
|
|
31
|
+
rmSync(dir, { recursive: true, force: true });
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Upstream also drives two cases through the OC1 messages-transform handler
|
|
37
|
+
// (1 s hold served, 2.5 s hold refused with StorageBusyRefusalError). That
|
|
38
|
+
// adapter is deleted in this fork; the in-pass acquisition-wait behavior those
|
|
39
|
+
// cases cover is exercised here against the core primitives instead, and the
|
|
40
|
+
// 1 s/2.5 s boundaries are additionally covered by scripts/smoke-node-sqlite.ts.
|
|
41
|
+
for (const mode of ["BEGIN", "autocommit"]) {
|
|
42
|
+
test(`foreground ${mode} wait is capped by the pass deadline`, () => {
|
|
43
|
+
const { db, path, close } = fixture();
|
|
44
|
+
const blocker = new Database(path);
|
|
45
|
+
blocker.exec("BEGIN IMMEDIATE");
|
|
46
|
+
const diagnostics: string[] = [];
|
|
47
|
+
registerSqliteDiagnosticSink((line) => diagnostics.push(line));
|
|
48
|
+
try {
|
|
49
|
+
const started = performance.now();
|
|
50
|
+
withSqliteTransformPass(() => {
|
|
51
|
+
guardSqliteTransformPass({ assert() {}, remainingMs: () => 100 });
|
|
52
|
+
expect(() => {
|
|
53
|
+
if (mode === "BEGIN") withPrivilegedWriter(db, () => undefined);
|
|
54
|
+
else db.prepare("INSERT INTO result VALUES ('late')").run();
|
|
55
|
+
}).toThrow(SqliteAcquisitionBusyError);
|
|
56
|
+
});
|
|
57
|
+
expect(performance.now() - started).toBeGreaterThanOrEqual(75);
|
|
58
|
+
expect(performance.now() - started).toBeLessThan(700);
|
|
59
|
+
expect(db.prepare("SELECT * FROM result").all()).toEqual([]);
|
|
60
|
+
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
61
|
+
} finally {
|
|
62
|
+
registerSqliteDiagnosticSink(log);
|
|
63
|
+
blocker.exec("ROLLBACK");
|
|
64
|
+
blocker.close();
|
|
65
|
+
close();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -100,7 +100,7 @@ test("foreground admission keeps the loop ticking while a separate writer holds
|
|
|
100
100
|
}
|
|
101
101
|
}, 30000);
|
|
102
102
|
|
|
103
|
-
test("a foreground in-pass writer has bounded
|
|
103
|
+
test("a foreground in-pass writer has bounded 2000ms tolerance and restores its timeout", () => {
|
|
104
104
|
const { db, path, close } = fixture();
|
|
105
105
|
const blocker = new Database(path);
|
|
106
106
|
blocker.exec("BEGIN IMMEDIATE");
|
|
@@ -109,15 +109,15 @@ test("a foreground in-pass writer has bounded 250ms tolerance and restores its t
|
|
|
109
109
|
expect(() =>
|
|
110
110
|
withSqliteTransformPass(() => withPrivilegedWriter(db, () => undefined)),
|
|
111
111
|
).toThrow(SqliteAcquisitionBusyError);
|
|
112
|
-
expect(performance.now() - start).toBeGreaterThanOrEqual(
|
|
113
|
-
expect(performance.now() - start).toBeLessThan(
|
|
112
|
+
expect(performance.now() - start).toBeGreaterThanOrEqual(1900);
|
|
113
|
+
expect(performance.now() - start).toBeLessThan(2500);
|
|
114
114
|
expect(db.prepare("PRAGMA busy_timeout").get()).toEqual({ timeout: 5000 });
|
|
115
115
|
} finally {
|
|
116
116
|
blocker.exec("ROLLBACK");
|
|
117
117
|
blocker.close();
|
|
118
118
|
close();
|
|
119
119
|
}
|
|
120
|
-
});
|
|
120
|
+
}, 30000);
|
|
121
121
|
|
|
122
122
|
test("ready background publication retries on a timer and retains its write", async () => {
|
|
123
123
|
const { db, path, close } = fixture();
|
|
@@ -7,11 +7,13 @@ import { createTestTempDirFromPath } from "./test-temp-dir";
|
|
|
7
7
|
// The scenario runs in a child process with NODE_ENV=production because the
|
|
8
8
|
// shared logger is silent under test. It imports storage-db for its side effect
|
|
9
9
|
// of registering the real log sink, then drives three privileged writes and one
|
|
10
|
-
// background writer through two connections on a throwaway database
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
10
|
+
// background writer through two connections on a throwaway database.
|
|
11
|
+
// Acquisition measures waiting for BEGIN to succeed; hold measures time from
|
|
12
|
+
// successful BEGIN through COMMIT. The injected clock separates those costs:
|
|
13
|
+
// wait - 300 ms before BEGIN and 0 ms held: log a foreground acquisition
|
|
14
|
+
// hold - 0 ms before BEGIN and 300 ms held: log a foreground hold
|
|
15
|
+
// fast - 0 ms for both: do not log anything
|
|
16
|
+
// async - 0 ms before BEGIN and 300 ms held: log the background writer's own site
|
|
15
17
|
const scenario = `
|
|
16
18
|
await import(${JSON.stringify(new URL("../features/magic-context/storage-db.ts", import.meta.url).href)});
|
|
17
19
|
const sqlite = await import(${JSON.stringify(new URL("./sqlite.ts", import.meta.url).href)});
|
|
@@ -20,19 +22,38 @@ const scenario = `
|
|
|
20
22
|
const holder = new sqlite.Database(dbPath);
|
|
21
23
|
holder.exec("PRAGMA journal_mode=WAL; CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER)");
|
|
22
24
|
const writer = new sqlite.Database(dbPath);
|
|
23
|
-
|
|
25
|
+
let now = 0;
|
|
26
|
+
performance.now = () => now;
|
|
27
|
+
const hold = () => { now += 300; };
|
|
24
28
|
|
|
25
29
|
holder.exec("BEGIN IMMEDIATE");
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
await sqlite.withAsyncPrivilegedWriter(writer, () => undefined, {
|
|
31
|
+
beforeRetry: () => { now += 300; holder.exec("COMMIT"); },
|
|
32
|
+
});
|
|
28
33
|
|
|
29
|
-
await sqlite.withAsyncPrivilegedWriter(writer,
|
|
34
|
+
await sqlite.withAsyncPrivilegedWriter(writer, hold);
|
|
30
35
|
|
|
31
36
|
await sqlite.withAsyncPrivilegedWriter(writer, () => undefined);
|
|
32
37
|
|
|
33
38
|
await sqlite.beginSqliteWriterAsync(writer, "historian-publish");
|
|
34
|
-
|
|
39
|
+
hold();
|
|
40
|
+
writer.exec("COMMIT");
|
|
41
|
+
|
|
42
|
+
writer.exec("BEGIN IMMEDIATE");
|
|
43
|
+
now += 101;
|
|
44
|
+
writer.exec("ROLLBACK");
|
|
45
|
+
|
|
46
|
+
writer.exec("CREATE TABLE result(value)");
|
|
47
|
+
const statementTimes = [now, now + 101];
|
|
48
|
+
performance.now = () => statementTimes.shift() ?? now;
|
|
49
|
+
writer.prepare("INSERT INTO result VALUES (1)").run();
|
|
50
|
+
now += 101;
|
|
51
|
+
|
|
52
|
+
let clockReads = 0;
|
|
53
|
+
performance.now = () => { clockReads++; return now; };
|
|
54
|
+
writer.exec("BEGIN IMMEDIATE");
|
|
35
55
|
writer.exec("COMMIT");
|
|
56
|
+
if (clockReads !== 2) throw new Error("fast unscoped transaction clock reads=" + clockReads);
|
|
36
57
|
|
|
37
58
|
logger.flushLogger();
|
|
38
59
|
writer.close();
|
|
@@ -61,8 +82,6 @@ describe("sqlite writer diagnostics", () => {
|
|
|
61
82
|
SCENARIO_DB_PATH: join(root, "writer.db"),
|
|
62
83
|
};
|
|
63
84
|
for (const key of [
|
|
64
|
-
"HOME",
|
|
65
|
-
"OPENCODE_CONFIG_DIR",
|
|
66
85
|
"XDG_DATA_HOME",
|
|
67
86
|
"XDG_CONFIG_HOME",
|
|
68
87
|
"XDG_STATE_HOME",
|
|
@@ -103,6 +122,21 @@ describe("sqlite writer diagnostics", () => {
|
|
|
103
122
|
expect(consoleOutput).not.toContain("sqlite writer");
|
|
104
123
|
});
|
|
105
124
|
|
|
125
|
+
test("unscoped rollback names the host, pid and caller at the 100ms threshold", () => {
|
|
126
|
+
const rolledBack = logLines.find((line) => line.includes("outcome=rolled_back"));
|
|
127
|
+
expect(rolledBack).toContain("lane=background");
|
|
128
|
+
expect(rolledBack).toContain("hold_ms=101");
|
|
129
|
+
expect(rolledBack).toMatch(/pid=\d+ host=opencode/);
|
|
130
|
+
expect(rolledBack).toContain("caller=");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("native autocommit time is labelled as including acquisition, not lock ownership", () => {
|
|
134
|
+
const statement = logLines.find((line) => line.includes("site=autocommit"));
|
|
135
|
+
expect(statement).toContain("elapsed_ms=101");
|
|
136
|
+
expect(statement).toContain("timing=statement_including_acquisition");
|
|
137
|
+
expect(statement).not.toContain("hold_ms=");
|
|
138
|
+
});
|
|
139
|
+
|
|
106
140
|
test("a writer that waited for the lock reports the wait, not its short hold", () => {
|
|
107
141
|
const waited = logLines.find((line) => line.includes("attempts=2"));
|
|
108
142
|
if (!waited) throw new Error(`no retried acquisition logged:\n${logLines.join("\n")}`);
|
|
@@ -111,6 +145,8 @@ describe("sqlite writer diagnostics", () => {
|
|
|
111
145
|
expect(waited).toContain("outcome=committed");
|
|
112
146
|
expect(field(waited, "acquire_ms")).toBeGreaterThanOrEqual(250);
|
|
113
147
|
expect(field(waited, "hold_ms")).toBeLessThan(250);
|
|
148
|
+
expect(field(waited, "acquire_ms")).toBe(300);
|
|
149
|
+
expect(field(waited, "hold_ms")).toBe(0);
|
|
114
150
|
});
|
|
115
151
|
|
|
116
152
|
test("a writer that held the lock reports the hold, not its quick acquisition", () => {
|
|
@@ -120,6 +156,8 @@ describe("sqlite writer diagnostics", () => {
|
|
|
120
156
|
expect(held).toHaveLength(1);
|
|
121
157
|
expect(field(held[0], "acquire_ms")).toBeLessThan(250);
|
|
122
158
|
expect(field(held[0], "hold_ms")).toBeGreaterThanOrEqual(300);
|
|
159
|
+
expect(field(held[0], "acquire_ms")).toBe(0);
|
|
160
|
+
expect(field(held[0], "hold_ms")).toBe(300);
|
|
123
161
|
});
|
|
124
162
|
|
|
125
163
|
test("an async background writer reports its hold under its own site", () => {
|
|
@@ -128,6 +166,8 @@ describe("sqlite writer diagnostics", () => {
|
|
|
128
166
|
expect(held[0]).toContain("lane=background");
|
|
129
167
|
expect(field(held[0], "acquire_ms")).toBeLessThan(250);
|
|
130
168
|
expect(field(held[0], "hold_ms")).toBeGreaterThanOrEqual(300);
|
|
169
|
+
expect(field(held[0], "acquire_ms")).toBe(0);
|
|
170
|
+
expect(field(held[0], "hold_ms")).toBe(300);
|
|
131
171
|
});
|
|
132
172
|
|
|
133
173
|
test("a fast writer stays out of the log", () => {
|