@arcbridge/core 0.1.2 → 0.1.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import Database from 'better-sqlite3';
2
+ import { DatabaseSync } from 'node:sqlite';
3
3
 
4
4
  declare const ServiceSchema: z.ZodObject<{
5
5
  name: z.ZodString;
@@ -720,13 +720,24 @@ declare const AgentRoleSchema: z.ZodObject<{
720
720
  }>;
721
721
  type AgentRole = z.infer<typeof AgentRoleSchema>;
722
722
 
723
- declare function openDatabase(dbPath: string): Database.Database;
724
- declare function openMemoryDatabase(): Database.Database;
723
+ /** Re-export DatabaseSync as Database for use across the codebase. */
724
+ type Database = DatabaseSync;
725
+ declare function suppressSqliteWarning(): void;
726
+ declare function openDatabase(dbPath: string): Database;
727
+ declare function openMemoryDatabase(): Database;
728
+ /**
729
+ * Wrap a synchronous function in a SQLite transaction (BEGIN/COMMIT/ROLLBACK).
730
+ * Supports nesting via SAVEPOINTs — inner calls create savepoints
731
+ * instead of starting a new transaction.
732
+ *
733
+ * fn must be synchronous — passing an async function will throw.
734
+ */
735
+ declare function transaction<T>(db: Database, fn: () => T): T;
725
736
 
726
737
  declare const CURRENT_SCHEMA_VERSION = 2;
727
- declare function initializeSchema(db: Database.Database): void;
738
+ declare function initializeSchema(db: Database): void;
728
739
 
729
- declare function migrate(db: Database.Database): void;
740
+ declare function migrate(db: Database): void;
730
741
 
731
742
  interface InitProjectInput {
732
743
  name: string;
@@ -751,14 +762,14 @@ declare function generatePlan(targetDir: string, input: InitProjectInput): void;
751
762
  declare function generateAgentRoles(targetDir: string, template?: string): AgentRole[];
752
763
 
753
764
  interface GenerateDatabaseResult {
754
- db: Database.Database;
765
+ db: Database;
755
766
  warnings: string[];
756
767
  }
757
768
  /**
758
769
  * Re-read arc42 files from disk and update the database.
759
770
  * Uses INSERT OR REPLACE to pick up changes made since initial generation.
760
771
  */
761
- declare function refreshFromDocs(db: Database.Database, targetDir: string): string[];
772
+ declare function refreshFromDocs(db: Database, targetDir: string): string[];
762
773
  declare function generateDatabase(targetDir: string, input: InitProjectInput): GenerateDatabaseResult;
763
774
 
764
775
  interface IndexerOptions {
@@ -818,7 +829,7 @@ declare function discoverDotnetServices(projectRoot: string): DotnetProjectInfo[
818
829
  * Scan the project root for package dependency manifests (package.json, .csproj)
819
830
  * and write discovered dependencies to the package_dependencies table.
820
831
  */
821
- declare function indexPackageDependencies(db: Database.Database, projectRoot: string, service?: string): number;
832
+ declare function indexPackageDependencies(db: Database, projectRoot: string, service?: string): number;
822
833
 
823
834
  type ProjectLanguage = "typescript" | "csharp" | "auto";
824
835
  /**
@@ -831,7 +842,7 @@ declare function detectProjectLanguage(projectRoot: string): "typescript" | "csh
831
842
  * Index a project, auto-detecting the language unless explicitly specified.
832
843
  * Dispatches to the TypeScript or .NET indexer accordingly.
833
844
  */
834
- declare function indexProject(db: Database.Database, options: IndexerOptions): Promise<IndexResult>;
845
+ declare function indexProject(db: Database, options: IndexerOptions): Promise<IndexResult>;
835
846
 
836
847
  type DriftKind = "undocumented_module" | "missing_module" | "dependency_violation" | "unlinked_test" | "stale_adr" | "new_dependency";
837
848
  type DriftSeverity = "info" | "warning" | "error";
@@ -853,12 +864,12 @@ interface DriftOptions {
853
864
  * Compares building block code_paths against actual indexed files,
854
865
  * checks cross-block dependencies, and validates ADR references.
855
866
  */
856
- declare function detectDrift(db: Database.Database, options?: DriftOptions): DriftEntry[];
867
+ declare function detectDrift(db: Database, options?: DriftOptions): DriftEntry[];
857
868
  /**
858
869
  * Write drift entries to the drift_log table.
859
870
  * Clears existing unresolved entries and inserts fresh ones.
860
871
  */
861
- declare function writeDriftLog(db: Database.Database, entries: DriftEntry[]): void;
872
+ declare function writeDriftLog(db: Database, entries: DriftEntry[]): void;
862
873
 
863
874
  interface TaskInferenceResult {
864
875
  taskId: string;
@@ -870,11 +881,11 @@ interface TaskInferenceResult {
870
881
  * Infer task status from code state.
871
882
  * Checks if building block code exists, acceptance criteria symbols are present, etc.
872
883
  */
873
- declare function inferTaskStatuses(db: Database.Database, phaseId: string): TaskInferenceResult[];
884
+ declare function inferTaskStatuses(db: Database, phaseId: string): TaskInferenceResult[];
874
885
  /**
875
886
  * Apply inferred statuses to the database and optionally write back to YAML.
876
887
  */
877
- declare function applyInferences(db: Database.Database, inferences: TaskInferenceResult[], projectRoot: string): void;
888
+ declare function applyInferences(db: Database, inferences: TaskInferenceResult[], projectRoot: string): void;
878
889
 
879
890
  /**
880
891
  * Update a task's status in the YAML task file.
@@ -998,10 +1009,10 @@ interface MetricsResult {
998
1009
  }
999
1010
  type ExportFormat = "json" | "csv" | "markdown";
1000
1011
 
1001
- declare function insertActivity(db: Database.Database, params: InsertActivityParams): number;
1002
- declare function getSessionTotals(db: Database.Database, since?: string, model?: string): SessionTotals;
1003
- declare function queryMetrics(db: Database.Database, params: QueryMetricsParams): MetricsResult;
1004
- declare function exportMetrics(db: Database.Database, projectRoot: string, format: ExportFormat, params: Omit<QueryMetricsParams, "groupBy" | "limit">, maxRows?: number): string;
1012
+ declare function insertActivity(db: Database, params: InsertActivityParams): number;
1013
+ declare function getSessionTotals(db: Database, since?: string, model?: string): SessionTotals;
1014
+ declare function queryMetrics(db: Database, params: QueryMetricsParams): MetricsResult;
1015
+ declare function exportMetrics(db: Database, projectRoot: string, format: ExportFormat, params: Omit<QueryMetricsParams, "groupBy" | "limit">, maxRows?: number): string;
1005
1016
 
1006
1017
  interface ChangedFile {
1007
1018
  status: "added" | "modified" | "deleted" | "renamed";
@@ -1020,7 +1031,7 @@ interface GitRef {
1020
1031
  * - "last-phase" → commit stored in arcbridge_meta under "phase_sync_commit", or HEAD~5 fallback
1021
1032
  * - anything else → treated as a literal git ref (branch, tag, SHA)
1022
1033
  */
1023
- declare function resolveRef(projectRoot: string, since: string, db?: Database.Database): GitRef;
1034
+ declare function resolveRef(projectRoot: string, since: string, db?: Database): GitRef;
1024
1035
  /**
1025
1036
  * Get list of changed files between a ref and HEAD.
1026
1037
  */
@@ -1036,7 +1047,7 @@ declare function getHeadSha(projectRoot: string): string | null;
1036
1047
  /**
1037
1048
  * Store the current sync point in arcbridge_meta.
1038
1049
  */
1039
- declare function setSyncCommit(db: Database.Database, key: "last_sync_commit" | "phase_sync_commit", sha: string): void;
1050
+ declare function setSyncCommit(db: Database, key: "last_sync_commit" | "phase_sync_commit", sha: string): void;
1040
1051
 
1041
1052
  type TestOutcome = "passed" | "failed" | "missing" | "error";
1042
1053
  interface ScenarioTestResult {
@@ -1062,7 +1073,7 @@ interface VerifyResult {
1062
1073
  *
1063
1074
  * Optionally filter by specific scenario IDs.
1064
1075
  */
1065
- declare function verifyScenarios(db: Database.Database, projectRoot: string, options: {
1076
+ declare function verifyScenarios(db: Database, projectRoot: string, options: {
1066
1077
  testCommand: string;
1067
1078
  timeoutMs: number;
1068
1079
  scenarioIds?: string[];
@@ -1097,4 +1108,4 @@ declare function loadConfig(projectRoot: string): {
1097
1108
  error: string | null;
1098
1109
  };
1099
1110
 
1100
- export { type ActivityRow, type AdrFrontmatter, AdrFrontmatterSchema, type AgentRole, AgentRoleSchema, type AggregatedRow, type ArcBridgeConfig, ArcBridgeConfigSchema, type BuildingBlock, BuildingBlockSchema, type BuildingBlocksFrontmatter, BuildingBlocksFrontmatterSchema, CURRENT_SCHEMA_VERSION, type ChangedFile, type DotnetProjectInfo, type DriftEntry, type DriftKind, type DriftOptions, type DriftSeverity, type ExportFormat, type ExtractedSymbol, type GenerateDatabaseResult, type GitRef, type IndexResult, type IndexerOptions, type InitProjectInput, type InsertActivityParams, type LatestQualitySnapshot, type LoadRolesResult, type MetricsResult, type Phase, PhaseSchema, type PhasesFile, PhasesFileSchema, type ProjectLanguage, QualityCategorySchema, QualityPrioritySchema, type QualityScenario, QualityScenarioSchema, QualityScenarioStatusSchema, type QualityScenariosFile, QualityScenariosFileSchema, type QueryMetricsParams, type ScenarioTestResult, type Service, type SessionTotals, type SymbolKind, type Task, type TaskFile, TaskFileSchema, type TaskInferenceResult, TaskSchema, type TestOutcome, type VerifyResult, addTaskToYaml, applyInferences, detectDrift, detectProjectLanguage, discoverDotnetServices, exportMetrics, generateAgentRoles, generateArc42, generateConfig, generateDatabase, generatePlan, generateSyncFiles, getChangedFiles, getHeadSha, getSessionTotals, getUncommittedChanges, indexPackageDependencies, indexProject, inferTaskStatuses, initializeSchema, insertActivity, loadConfig, loadRole, loadRoles, migrate, openDatabase, openMemoryDatabase, queryMetrics, refreshFromDocs, resolveRef, setSyncCommit, syncPhaseToYaml, syncScenarioToYaml, syncTaskToYaml, verifyScenarios, writeDriftLog };
1111
+ export { type ActivityRow, type AdrFrontmatter, AdrFrontmatterSchema, type AgentRole, AgentRoleSchema, type AggregatedRow, type ArcBridgeConfig, ArcBridgeConfigSchema, type BuildingBlock, BuildingBlockSchema, type BuildingBlocksFrontmatter, BuildingBlocksFrontmatterSchema, CURRENT_SCHEMA_VERSION, type ChangedFile, type Database, type DotnetProjectInfo, type DriftEntry, type DriftKind, type DriftOptions, type DriftSeverity, type ExportFormat, type ExtractedSymbol, type GenerateDatabaseResult, type GitRef, type IndexResult, type IndexerOptions, type InitProjectInput, type InsertActivityParams, type LatestQualitySnapshot, type LoadRolesResult, type MetricsResult, type Phase, PhaseSchema, type PhasesFile, PhasesFileSchema, type ProjectLanguage, QualityCategorySchema, QualityPrioritySchema, type QualityScenario, QualityScenarioSchema, QualityScenarioStatusSchema, type QualityScenariosFile, QualityScenariosFileSchema, type QueryMetricsParams, type ScenarioTestResult, type Service, type SessionTotals, type SymbolKind, type Task, type TaskFile, TaskFileSchema, type TaskInferenceResult, TaskSchema, type TestOutcome, type VerifyResult, addTaskToYaml, applyInferences, detectDrift, detectProjectLanguage, discoverDotnetServices, exportMetrics, generateAgentRoles, generateArc42, generateConfig, generateDatabase, generatePlan, generateSyncFiles, getChangedFiles, getHeadSha, getSessionTotals, getUncommittedChanges, indexPackageDependencies, indexProject, inferTaskStatuses, initializeSchema, insertActivity, loadConfig, loadRole, loadRoles, migrate, openDatabase, openMemoryDatabase, queryMetrics, refreshFromDocs, resolveRef, setSyncCommit, suppressSqliteWarning, syncPhaseToYaml, syncScenarioToYaml, syncTaskToYaml, transaction, verifyScenarios, writeDriftLog };
package/dist/index.js CHANGED
@@ -210,15 +210,93 @@ var AgentRoleSchema = z6.object({
210
210
  });
211
211
 
212
212
  // src/db/connection.ts
213
- import Database from "better-sqlite3";
213
+ import { DatabaseSync } from "node:sqlite";
214
+ var suppressed = false;
215
+ function suppressSqliteWarning() {
216
+ if (suppressed) return;
217
+ suppressed = true;
218
+ const origEmit = process.emit;
219
+ process.emit = function(event, ...args) {
220
+ if (event === "warning" && args[0]?.name === "ExperimentalWarning" && typeof args[0]?.message === "string" && args[0].message.includes("SQLite")) {
221
+ return true;
222
+ }
223
+ return origEmit.apply(process, [event, ...args]);
224
+ };
225
+ }
226
+ function sanitizeParams(params) {
227
+ return params.map((p) => p === void 0 ? null : p);
228
+ }
214
229
  function openDatabase(dbPath) {
215
- const db = new Database(dbPath);
216
- db.pragma("journal_mode = WAL");
217
- db.pragma("foreign_keys = ON");
230
+ const db = new DatabaseSync(dbPath);
231
+ db.exec("PRAGMA journal_mode = WAL");
232
+ db.exec("PRAGMA foreign_keys = ON");
233
+ patchPrepare(db);
218
234
  return db;
219
235
  }
220
236
  function openMemoryDatabase() {
221
- return openDatabase(":memory:");
237
+ const db = new DatabaseSync(":memory:");
238
+ db.exec("PRAGMA foreign_keys = ON");
239
+ patchPrepare(db);
240
+ return db;
241
+ }
242
+ function patchPrepare(db) {
243
+ const originalPrepare = db.prepare.bind(db);
244
+ db.prepare = (sql) => {
245
+ const stmt = originalPrepare(sql);
246
+ const origRun = stmt.run.bind(stmt);
247
+ const origGet = stmt.get.bind(stmt);
248
+ const origAll = stmt.all.bind(stmt);
249
+ stmt.run = (...params) => origRun(...sanitizeParams(params));
250
+ stmt.get = (...params) => origGet(...sanitizeParams(params));
251
+ stmt.all = (...params) => origAll(...sanitizeParams(params));
252
+ return stmt;
253
+ };
254
+ }
255
+ function rejectAsync(fn) {
256
+ if (fn.constructor.name === "AsyncFunction") {
257
+ throw new Error(
258
+ "transaction() received an async function. Use a synchronous function \u2014 node:sqlite is synchronous and the transaction would commit before the async work completes."
259
+ );
260
+ }
261
+ }
262
+ var txDepth = /* @__PURE__ */ new WeakMap();
263
+ function transaction(db, fn) {
264
+ rejectAsync(fn);
265
+ const depth = txDepth.get(db) ?? 0;
266
+ if (depth === 0) {
267
+ db.exec("BEGIN");
268
+ txDepth.set(db, 1);
269
+ try {
270
+ const result = fn();
271
+ db.exec("COMMIT");
272
+ return result;
273
+ } catch (err) {
274
+ try {
275
+ db.exec("ROLLBACK");
276
+ } catch {
277
+ }
278
+ throw err;
279
+ } finally {
280
+ txDepth.set(db, 0);
281
+ }
282
+ }
283
+ const name = `sp_${depth}`;
284
+ db.exec(`SAVEPOINT ${name}`);
285
+ txDepth.set(db, depth + 1);
286
+ try {
287
+ const result = fn();
288
+ db.exec(`RELEASE ${name}`);
289
+ return result;
290
+ } catch (err) {
291
+ try {
292
+ db.exec(`ROLLBACK TO ${name}`);
293
+ db.exec(`RELEASE ${name}`);
294
+ } catch {
295
+ }
296
+ throw err;
297
+ } finally {
298
+ txDepth.set(db, depth);
299
+ }
222
300
  }
223
301
 
224
302
  // src/db/schema.ts
@@ -477,12 +555,12 @@ function migrate(db) {
477
555
  }
478
556
  const pending = migrations.filter((m) => m.version > currentVersion).sort((a, b) => a.version - b.version);
479
557
  for (const migration of pending) {
480
- db.transaction(() => {
558
+ transaction(db, () => {
481
559
  migration.up(db);
482
560
  db.prepare(
483
561
  "UPDATE arcbridge_meta SET value = ? WHERE key = 'schema_version'"
484
562
  ).run(String(migration.version));
485
- })();
563
+ });
486
564
  }
487
565
  }
488
566
 
@@ -3275,7 +3353,7 @@ function refreshFromDocs(db, targetDir) {
3275
3353
  const scenarioStatusMap = new Map(
3276
3354
  existingScenarios.map((s) => [s.id, s.status])
3277
3355
  );
3278
- const refresh = db.transaction(() => {
3356
+ const refresh = () => transaction(db, () => {
3279
3357
  db.prepare("DELETE FROM tasks").run();
3280
3358
  db.prepare("DELETE FROM phases").run();
3281
3359
  db.prepare("UPDATE contracts SET building_block = NULL").run();
@@ -3326,12 +3404,12 @@ function generateDatabase(targetDir, input) {
3326
3404
  upsert.run("project_name", input.name);
3327
3405
  upsert.run("project_type", input.template);
3328
3406
  upsert.run("last_full_index", (/* @__PURE__ */ new Date()).toISOString());
3329
- db.transaction(() => {
3407
+ transaction(db, () => {
3330
3408
  allWarnings.push(...populateBuildingBlocks(db, targetDir));
3331
3409
  allWarnings.push(...populateQualityScenarios(db, targetDir));
3332
3410
  allWarnings.push(...populatePhases(db, targetDir));
3333
3411
  allWarnings.push(...populateAdrs(db, targetDir));
3334
- })();
3412
+ });
3335
3413
  ensureGitignore(targetDir);
3336
3414
  return { db, warnings: allWarnings };
3337
3415
  }
@@ -4130,7 +4208,7 @@ function writeComponents(db, components) {
4130
4208
  const existingIds = new Set(
4131
4209
  db.prepare("SELECT id FROM symbols").all().map((r) => r.id)
4132
4210
  );
4133
- const run = db.transaction(() => {
4211
+ transaction(db, () => {
4134
4212
  for (const c of components) {
4135
4213
  if (!existingIds.has(c.symbolId)) continue;
4136
4214
  insert.run(
@@ -4144,7 +4222,6 @@ function writeComponents(db, components) {
4144
4222
  );
4145
4223
  }
4146
4224
  });
4147
- run();
4148
4225
  }
4149
4226
 
4150
4227
  // src/indexer/route-analyzer.ts
@@ -4273,7 +4350,7 @@ function writeRoutes(db, routes) {
4273
4350
  id, route_path, kind, http_methods, has_auth, parent_layout, service
4274
4351
  ) VALUES (?, ?, ?, ?, ?, ?, ?)
4275
4352
  `);
4276
- const run = db.transaction(() => {
4353
+ transaction(db, () => {
4277
4354
  for (const r of routes) {
4278
4355
  insert.run(
4279
4356
  r.id,
@@ -4286,7 +4363,6 @@ function writeRoutes(db, routes) {
4286
4363
  );
4287
4364
  }
4288
4365
  });
4289
- run();
4290
4366
  }
4291
4367
 
4292
4368
  // src/indexer/content-hash.ts
@@ -4320,7 +4396,7 @@ function removeSymbolsForFiles(db, filePaths) {
4320
4396
  const deleteComponents = db.prepare(
4321
4397
  "DELETE FROM components WHERE symbol_id IN (SELECT id FROM symbols WHERE file_path = ?)"
4322
4398
  );
4323
- const run = db.transaction(() => {
4399
+ transaction(db, () => {
4324
4400
  for (const fp of filePaths) {
4325
4401
  deleteDepsSource.run(fp);
4326
4402
  deleteDepsTarget.run(fp);
@@ -4328,7 +4404,6 @@ function removeSymbolsForFiles(db, filePaths) {
4328
4404
  deleteSymbols.run(fp);
4329
4405
  }
4330
4406
  });
4331
- run();
4332
4407
  }
4333
4408
  function writeSymbols(db, symbols, service, language = "typescript") {
4334
4409
  if (symbols.length === 0) return;
@@ -4348,7 +4423,7 @@ function writeSymbols(db, symbols, service, language = "typescript") {
4348
4423
  )
4349
4424
  `);
4350
4425
  const now = (/* @__PURE__ */ new Date()).toISOString();
4351
- const run = db.transaction(() => {
4426
+ transaction(db, () => {
4352
4427
  for (const s of symbols) {
4353
4428
  insert.run(
4354
4429
  s.id,
@@ -4372,7 +4447,6 @@ function writeSymbols(db, symbols, service, language = "typescript") {
4372
4447
  );
4373
4448
  }
4374
4449
  });
4375
- run();
4376
4450
  }
4377
4451
  function writeDependencies(db, dependencies) {
4378
4452
  if (dependencies.length === 0) return;
@@ -4380,12 +4454,11 @@ function writeDependencies(db, dependencies) {
4380
4454
  INSERT OR IGNORE INTO dependencies (source_symbol, target_symbol, kind)
4381
4455
  VALUES (?, ?, ?)
4382
4456
  `);
4383
- const run = db.transaction(() => {
4457
+ transaction(db, () => {
4384
4458
  for (const dep of dependencies) {
4385
4459
  insert.run(dep.sourceSymbolId, dep.targetSymbolId, dep.kind);
4386
4460
  }
4387
4461
  });
4388
- run();
4389
4462
  }
4390
4463
 
4391
4464
  // src/indexer/dotnet-indexer.ts
@@ -4582,7 +4655,7 @@ function indexDotnetProjectRoslyn(db, options) {
4582
4655
  INSERT OR REPLACE INTO routes (id, route_path, kind, http_methods, has_auth, service)
4583
4656
  VALUES (?, ?, ?, ?, ?, ?)
4584
4657
  `);
4585
- const runRoutes = db.transaction(() => {
4658
+ transaction(db, () => {
4586
4659
  for (const route of output.routes) {
4587
4660
  insertRoute.run(
4588
4661
  route.id,
@@ -4594,7 +4667,6 @@ function indexDotnetProjectRoslyn(db, options) {
4594
4667
  );
4595
4668
  }
4596
4669
  });
4597
- runRoutes();
4598
4670
  }
4599
4671
  return {
4600
4672
  symbolsIndexed: output.symbols.length,
@@ -5513,7 +5585,7 @@ async function indexCSharpTreeSitter(db, options) {
5513
5585
  INSERT OR REPLACE INTO routes (id, route_path, kind, http_methods, has_auth, service)
5514
5586
  VALUES (?, ?, ?, ?, ?, ?)
5515
5587
  `);
5516
- const runRoutes = db.transaction(() => {
5588
+ transaction(db, () => {
5517
5589
  for (const route of allRoutes) {
5518
5590
  insertRoute.run(
5519
5591
  route.id,
@@ -5525,7 +5597,6 @@ async function indexCSharpTreeSitter(db, options) {
5525
5597
  );
5526
5598
  }
5527
5599
  });
5528
- runRoutes();
5529
5600
  }
5530
5601
  return {
5531
5602
  symbolsIndexed: allNewSymbols.length,
@@ -5557,12 +5628,11 @@ function indexPackageDependencies(db, projectRoot, service = "main") {
5557
5628
  const insert = db.prepare(
5558
5629
  "INSERT OR IGNORE INTO package_dependencies (name, version, source, service) VALUES (?, ?, ?, ?)"
5559
5630
  );
5560
- const run = db.transaction(() => {
5631
+ transaction(db, () => {
5561
5632
  for (const dep of deps) {
5562
5633
  insert.run(dep.name, dep.version, dep.source, service);
5563
5634
  }
5564
5635
  });
5565
- run();
5566
5636
  return deps.length;
5567
5637
  }
5568
5638
  function parsePackageJson(filePath) {
@@ -5815,12 +5885,11 @@ function writeDriftLog(db, entries) {
5815
5885
  VALUES (?, ?, ?, ?, ?, ?)
5816
5886
  `);
5817
5887
  const now = (/* @__PURE__ */ new Date()).toISOString();
5818
- const run = db.transaction(() => {
5888
+ transaction(db, () => {
5819
5889
  for (const e of entries) {
5820
5890
  insert.run(now, e.kind, e.severity, e.description, e.affectedBlock, e.affectedFile);
5821
5891
  }
5822
5892
  });
5823
- run();
5824
5893
  }
5825
5894
  function detectUndocumentedModules(db, entries, ignorePaths = []) {
5826
5895
  const blocks = db.prepare("SELECT id, name, code_paths FROM building_blocks").all();
@@ -6139,12 +6208,11 @@ function applyInferences(db, inferences, projectRoot) {
6139
6208
  "UPDATE tasks SET status = ?, completed_at = CASE WHEN ? = 'done' THEN ? ELSE completed_at END WHERE id = ?"
6140
6209
  );
6141
6210
  const now = (/* @__PURE__ */ new Date()).toISOString();
6142
- const run = db.transaction(() => {
6211
+ transaction(db, () => {
6143
6212
  for (const inf of inferences) {
6144
6213
  update.run(inf.inferredStatus, inf.inferredStatus, now, inf.taskId);
6145
6214
  }
6146
6215
  });
6147
- run();
6148
6216
  for (const inf of inferences) {
6149
6217
  const task = db.prepare("SELECT phase_id FROM tasks WHERE id = ?").get(inf.taskId);
6150
6218
  if (task) {
@@ -7086,9 +7154,11 @@ export {
7086
7154
  refreshFromDocs,
7087
7155
  resolveRef,
7088
7156
  setSyncCommit,
7157
+ suppressSqliteWarning,
7089
7158
  syncPhaseToYaml,
7090
7159
  syncScenarioToYaml,
7091
7160
  syncTaskToYaml,
7161
+ transaction,
7092
7162
  verifyScenarios,
7093
7163
  writeDriftLog
7094
7164
  };