archctx 0.1.0 → 0.1.1

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 (2) hide show
  1. package/bin/archctx.mjs +1123 -186
  2. package/package.json +1 -1
package/bin/archctx.mjs CHANGED
@@ -667,7 +667,7 @@ function productVersionManifest() {
667
667
  }
668
668
  };
669
669
  }
670
- var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.1.0", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.3.10", ARCHCONTEXT_NODE_RANGE = ">=24 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-06-20.fg1";
670
+ var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.1.1", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.3.10", ARCHCONTEXT_NODE_RANGE = ">=24 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-06-20.fg1";
671
671
  // packages/contracts/src/index.ts
672
672
  var init_src = __esm(() => {
673
673
  init_control_plane_routes();
@@ -1288,7 +1288,7 @@ __export(exports_src, {
1288
1288
  DevicePrivateKeyStore: () => DevicePrivateKeyStore
1289
1289
  });
1290
1290
  import {
1291
- createHash as createHash5,
1291
+ createHash as createHash7,
1292
1292
  createPrivateKey,
1293
1293
  generateKeyPairSync,
1294
1294
  randomBytes as randomBytes3,
@@ -1296,7 +1296,7 @@ import {
1296
1296
  } from "node:crypto";
1297
1297
  function createPkceAuthorizationRequest(input) {
1298
1298
  const codeVerifier = input.verifier ?? randomBytes3(32).toString("base64url");
1299
- const codeChallenge = createHash5("sha256").update(codeVerifier).digest("base64url");
1299
+ const codeChallenge = createHash7("sha256").update(codeVerifier).digest("base64url");
1300
1300
  const url = new URL("/oauth/authorize", input.issuer);
1301
1301
  url.searchParams.set("response_type", "code");
1302
1302
  url.searchParams.set("client_id", input.clientId);
@@ -4262,12 +4262,12 @@ __export(exports_src3, {
4262
4262
  assertLocalAttestationV1: () => assertLocalAttestationV1,
4263
4263
  assertAttestationV2: () => assertAttestationV22
4264
4264
  });
4265
- import { createHash as createHash6, sign as sign3, verify as verify2 } from "node:crypto";
4265
+ import { createHash as createHash8, sign as sign3, verify as verify2 } from "node:crypto";
4266
4266
  function publicKeyFingerprint2(publicKey) {
4267
4267
  if (publicKey.type !== "public")
4268
4268
  throw new Error("public-key-required");
4269
4269
  const der = publicKey.export({ format: "der", type: "spki" });
4270
- return `sha256:${createHash6("sha256").update(der).digest("hex")}`;
4270
+ return `sha256:${createHash8("sha256").update(der).digest("hex")}`;
4271
4271
  }
4272
4272
  function createReviewChallenge(input) {
4273
4273
  const nonce = digestJson({ repo: input.repository, headSha: input.headSha, expiresAt: input.expiresAt });
@@ -4708,7 +4708,7 @@ function deviceIntegritySignals2(input) {
4708
4708
  function signAttestation(input) {
4709
4709
  const unsigned = unsignedPayload2({
4710
4710
  schemaVersion: "archcontext.attestation/v1",
4711
- attestationId: `att_${createHash6("sha256").update(input.challenge.challengeId + input.reviewDigest + input.trustLevel).digest("hex").slice(0, 16)}`,
4711
+ attestationId: `att_${createHash8("sha256").update(input.challenge.challengeId + input.reviewDigest + input.trustLevel).digest("hex").slice(0, 16)}`,
4712
4712
  challengeId: input.challenge.challengeId,
4713
4713
  repository: input.challenge.repository,
4714
4714
  headSha: input.challenge.headSha,
@@ -5109,7 +5109,7 @@ var init_src7 = __esm(() => {
5109
5109
 
5110
5110
  // packages/surfaces/cli/src/main.ts
5111
5111
  import { spawn } from "child_process";
5112
- import { accessSync, chmodSync as chmodSync3, closeSync as closeSync6, constants, existsSync as existsSync10, mkdirSync as mkdirSync8, openSync as openSync6, readFileSync as readFileSync9, rmSync as rmSync8, statSync as statSync6, writeFileSync as writeFileSync5 } from "fs";
5112
+ import { accessSync, chmodSync as chmodSync5, closeSync as closeSync7, constants, existsSync as existsSync11, mkdirSync as mkdirSync9, openSync as openSync7, readFileSync as readFileSync11, rmSync as rmSync9, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
5113
5113
  import { dirname as dirname9, join as join8, resolve as resolve14 } from "path";
5114
5114
  import { fileURLToPath } from "url";
5115
5115
 
@@ -5134,6 +5134,18 @@ var DEFAULT_IGNORES = new Set([
5134
5134
  ".archcontext/.local",
5135
5135
  ".DS_Store"
5136
5136
  ]);
5137
+ function repositoryFingerprint(root) {
5138
+ const normalized = canonicalRepositoryRoot(root);
5139
+ return `repo.${createHash2("sha256").update(normalized).digest("hex").slice(0, 16)}`;
5140
+ }
5141
+ function canonicalRepositoryRoot(root) {
5142
+ const resolved = resolve(root);
5143
+ try {
5144
+ return realpathSync.native(resolved);
5145
+ } catch {
5146
+ return resolved;
5147
+ }
5148
+ }
5137
5149
  function computeWorktreeDigest(root, options = {}) {
5138
5150
  const ignore = new Set([...DEFAULT_IGNORES, ...options.ignore ?? []]);
5139
5151
  const files = listRepoFiles(root, ignore);
@@ -5198,11 +5210,11 @@ var DEFAULT_IGNORES2 = new Set([
5198
5210
  ".archcontext/.local",
5199
5211
  ".DS_Store"
5200
5212
  ]);
5201
- function repositoryFingerprint(root) {
5202
- const normalized = canonicalRepositoryRoot(root);
5213
+ function repositoryFingerprint2(root) {
5214
+ const normalized = canonicalRepositoryRoot2(root);
5203
5215
  return `repo.${createHash3("sha256").update(normalized).digest("hex").slice(0, 16)}`;
5204
5216
  }
5205
- function canonicalRepositoryRoot(root) {
5217
+ function canonicalRepositoryRoot2(root) {
5206
5218
  const resolved = resolve2(root);
5207
5219
  try {
5208
5220
  return realpathSync2.native(resolved);
@@ -5341,9 +5353,9 @@ function computeReviewWorktreeDigest(input) {
5341
5353
  });
5342
5354
  }
5343
5355
  function bindRepository(root, headSha) {
5344
- const canonicalRoot = canonicalRepositoryRoot(root);
5356
+ const canonicalRoot = canonicalRepositoryRoot2(root);
5345
5357
  return {
5346
- repositoryId: repositoryFingerprint(canonicalRoot),
5358
+ repositoryId: repositoryFingerprint2(canonicalRoot),
5347
5359
  root: canonicalRoot,
5348
5360
  headSha,
5349
5361
  worktreeDigest: computeWorktreeDigest2(canonicalRoot)
@@ -6524,18 +6536,543 @@ function listFiles(root) {
6524
6536
  }
6525
6537
 
6526
6538
  // packages/local-runtime/local-store-sqlite/src/index.ts
6527
- import { dirname as dirname2, join as join2, resolve as resolve6 } from "node:path";
6539
+ import { execFileSync as execFileSync2 } from "node:child_process";
6540
+ import { createHash as createHash5, randomUUID } from "node:crypto";
6541
+ import { chmodSync, closeSync as closeSync3, existsSync as existsSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync2, openSync as openSync3, readFileSync as readFileSync5, realpathSync as realpathSync4, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
6542
+ import { createRequire as createRequire2 } from "node:module";
6543
+ import { homedir } from "node:os";
6544
+ import { dirname as dirname2, isAbsolute as isAbsolute3, join as join2, resolve as resolve6 } from "node:path";
6545
+ var runtimeRequire = createRequire2(import.meta.url);
6546
+ var SQLITE_SIDECAR_SUFFIXES = ["", "-wal", "-shm"];
6547
+ var LEGACY_MIGRATION_MARKER_FILE = "runtime.sqlite.migration.json";
6548
+ var LEGACY_MIGRATION_LOCK_FILE = "runtime.sqlite.migration.lock";
6549
+ var SQLITE_PRAGMAS = [
6550
+ "PRAGMA journal_mode = WAL",
6551
+ "PRAGMA foreign_keys = ON",
6552
+ "PRAGMA busy_timeout = 5000"
6553
+ ];
6554
+ var LOCAL_SQLITE_MIGRATIONS = [
6555
+ {
6556
+ id: "0001_runtime_state",
6557
+ statements: [
6558
+ `CREATE TABLE IF NOT EXISTS schema_migrations (
6559
+ id TEXT PRIMARY KEY,
6560
+ applied_at TEXT NOT NULL
6561
+ )`,
6562
+ `CREATE TABLE IF NOT EXISTS repository_sessions (
6563
+ repository_id TEXT PRIMARY KEY,
6564
+ root TEXT NOT NULL,
6565
+ head_sha TEXT NOT NULL,
6566
+ worktree_digest TEXT NOT NULL,
6567
+ updated_at TEXT NOT NULL
6568
+ )`,
6569
+ `CREATE TABLE IF NOT EXISTS snapshots (
6570
+ id TEXT PRIMARY KEY,
6571
+ repository_id TEXT NOT NULL,
6572
+ head_sha TEXT NOT NULL,
6573
+ worktree_digest TEXT NOT NULL,
6574
+ state TEXT NOT NULL,
6575
+ created_at TEXT NOT NULL,
6576
+ committed_at TEXT
6577
+ )`,
6578
+ `CREATE TABLE IF NOT EXISTS task_states (
6579
+ task_session_id TEXT PRIMARY KEY,
6580
+ payload_json TEXT NOT NULL,
6581
+ updated_at TEXT NOT NULL
6582
+ )`,
6583
+ `CREATE TABLE IF NOT EXISTS observed_evidence (
6584
+ id TEXT PRIMARY KEY,
6585
+ repository_id TEXT NOT NULL,
6586
+ head_sha TEXT NOT NULL,
6587
+ selector_json TEXT NOT NULL,
6588
+ summary TEXT NOT NULL,
6589
+ confidence TEXT NOT NULL,
6590
+ created_at TEXT NOT NULL
6591
+ )`,
6592
+ `CREATE TABLE IF NOT EXISTS review_results (
6593
+ review_id TEXT PRIMARY KEY,
6594
+ task_session_id TEXT NOT NULL,
6595
+ payload_json TEXT NOT NULL,
6596
+ created_at TEXT NOT NULL
6597
+ )`
6598
+ ]
6599
+ },
6600
+ {
6601
+ id: "0002_indexes",
6602
+ statements: [
6603
+ "CREATE INDEX IF NOT EXISTS idx_snapshots_repository ON snapshots(repository_id, head_sha)",
6604
+ "CREATE INDEX IF NOT EXISTS idx_evidence_repository ON observed_evidence(repository_id, head_sha)",
6605
+ "CREATE INDEX IF NOT EXISTS idx_reviews_task ON review_results(task_session_id)"
6606
+ ]
6607
+ },
6608
+ {
6609
+ id: "0003_landscape_state",
6610
+ statements: [
6611
+ `CREATE TABLE IF NOT EXISTS landscapes (
6612
+ id TEXT PRIMARY KEY,
6613
+ digest TEXT NOT NULL,
6614
+ metadata_json TEXT NOT NULL,
6615
+ updated_at TEXT NOT NULL
6616
+ )`,
6617
+ `CREATE TABLE IF NOT EXISTS cross_repo_edges (
6618
+ id TEXT PRIMARY KEY,
6619
+ landscape_id TEXT NOT NULL,
6620
+ from_repository_id TEXT NOT NULL,
6621
+ from_node_id TEXT NOT NULL,
6622
+ to_repository_id TEXT NOT NULL,
6623
+ to_node_id TEXT NOT NULL,
6624
+ via_kind TEXT NOT NULL,
6625
+ via_id TEXT NOT NULL,
6626
+ metadata_json TEXT NOT NULL,
6627
+ updated_at TEXT NOT NULL
6628
+ )`,
6629
+ "CREATE INDEX IF NOT EXISTS idx_cross_repo_edges_from ON cross_repo_edges(from_repository_id, from_node_id)",
6630
+ "CREATE INDEX IF NOT EXISTS idx_cross_repo_edges_to ON cross_repo_edges(to_repository_id, to_node_id)"
6631
+ ]
6632
+ },
6633
+ {
6634
+ id: "0004_changeset_journal",
6635
+ statements: [
6636
+ `CREATE TABLE IF NOT EXISTS changeset_journal (
6637
+ journal_id TEXT PRIMARY KEY,
6638
+ changeset_id TEXT NOT NULL,
6639
+ root TEXT NOT NULL,
6640
+ status TEXT NOT NULL,
6641
+ metadata_json TEXT NOT NULL,
6642
+ files_json TEXT NOT NULL,
6643
+ created_at TEXT NOT NULL,
6644
+ updated_at TEXT NOT NULL,
6645
+ completed_at TEXT
6646
+ )`,
6647
+ "CREATE INDEX IF NOT EXISTS idx_changeset_journal_status ON changeset_journal(status)"
6648
+ ]
6649
+ }
6650
+ ];
6651
+ var ARCHCONTEXT_STATE_DIR_ENV = "ARCHCONTEXT_STATE_DIR";
6652
+ var ARCHCONTEXT_LOCAL_STORE_PATH_ENV = "ARCHCONTEXT_LOCAL_STORE_PATH";
6653
+ function defaultArchContextStateRoot(env = process.env, platform = process.platform, home = homedir()) {
6654
+ const override = env[ARCHCONTEXT_STATE_DIR_ENV];
6655
+ if (override)
6656
+ return { path: resolve6(override), source: "environment" };
6657
+ if (platform === "darwin")
6658
+ return { path: join2(home, "Library", "Application Support", "ArchContext"), source: "os-user-data" };
6659
+ if (platform === "win32")
6660
+ return { path: join2(env.LOCALAPPDATA ?? join2(home, "AppData", "Local"), "ArchContext"), source: "os-user-data" };
6661
+ return { path: join2(env.XDG_DATA_HOME ?? join2(home, ".local", "share"), "archcontext"), source: "os-user-data" };
6662
+ }
6663
+ function runtimeStatePaths(root = process.cwd(), env = process.env) {
6664
+ const repositoryRoot = readGitPath(root, ["rev-parse", "--show-toplevel"]) ?? root;
6665
+ const canonicalRepositoryRoot3 = canonicalPath(repositoryRoot);
6666
+ const gitCommonDir = readGitPath(canonicalRepositoryRoot3, ["rev-parse", "--git-common-dir"]);
6667
+ const repositoryAnchor = canonicalPath(gitCommonDir ? resolveMaybeRelative(canonicalRepositoryRoot3, gitCommonDir) : canonicalRepositoryRoot3);
6668
+ const workspaceAnchor = canonicalRepositoryRoot3;
6669
+ const storageRepositoryId = stableStorageId("repo", repositoryAnchor);
6670
+ const storageWorkspaceId = stableStorageId("ws", workspaceAnchor);
6671
+ const stateRoot = defaultArchContextStateRoot(env);
6672
+ const repositoryStateDir = join2(stateRoot.path, "repositories", storageRepositoryId);
6673
+ const workspaceStateDir = join2(repositoryStateDir, "worktrees", storageWorkspaceId);
6674
+ const legacyControlDir = resolve6(canonicalRepositoryRoot3, ".archcontext", ".local");
6675
+ return {
6676
+ schemaVersion: "archcontext.runtime-state-paths/v1",
6677
+ stateRoot: stateRoot.path,
6678
+ source: stateRoot.source,
6679
+ repositoryRoot: canonicalRepositoryRoot3,
6680
+ repositoryAnchor,
6681
+ workspaceAnchor,
6682
+ storageRepositoryId,
6683
+ storageWorkspaceId,
6684
+ repositoryId: storageRepositoryId,
6685
+ workspaceId: storageWorkspaceId,
6686
+ repositoryStateDir,
6687
+ workspaceStateDir,
6688
+ sharedCacheDir: join2(repositoryStateDir, "shared", "cache"),
6689
+ localStorePath: env[ARCHCONTEXT_LOCAL_STORE_PATH_ENV] ?? join2(workspaceStateDir, "runtime.sqlite"),
6690
+ daemonConnectionPath: join2(workspaceStateDir, "archctxd.json"),
6691
+ daemonLockPath: join2(workspaceStateDir, "archctxd.lock"),
6692
+ daemonLogPath: join2(workspaceStateDir, "archctxd.log"),
6693
+ developerReviewRunStateDir: join2(workspaceStateDir, "developer-review-runs"),
6694
+ legacyControlDir,
6695
+ legacyLocalStorePath: join2(legacyControlDir, "runtime.sqlite")
6696
+ };
6697
+ }
6528
6698
  function defaultLocalStorePath(root = process.cwd()) {
6529
- return process.env.ARCHCONTEXT_LOCAL_STORE_PATH ?? resolve6(root, ".archcontext/.local/runtime.sqlite");
6699
+ return runtimeStatePaths(root).localStorePath;
6700
+ }
6701
+ function inspectLegacyLocalStoreMigration(root = process.cwd(), env = process.env) {
6702
+ const paths = runtimeStatePaths(root, env);
6703
+ if (env[ARCHCONTEXT_LOCAL_STORE_PATH_ENV]) {
6704
+ return legacyMigrationResult(false, "explicit-local-store-override", paths, [], {
6705
+ status: "explicit-local-store-override"
6706
+ });
6707
+ }
6708
+ const legacyExists = existsSync3(paths.legacyLocalStorePath);
6709
+ const targetExists = existsSync3(paths.localStorePath);
6710
+ if (targetExists) {
6711
+ const target = safeSqliteIntegrityCheck(paths.localStorePath);
6712
+ return legacyMigrationResult(false, "target-exists", paths, [], {
6713
+ status: target.ok ? "target-current" : "target-incomplete",
6714
+ integrityCheck: target.ok ? { target: target.result } : { target: "failed", error: target.error }
6715
+ });
6716
+ }
6717
+ if (!legacyExists) {
6718
+ return legacyMigrationResult(false, "legacy-missing", paths, [], {
6719
+ status: "legacy-missing"
6720
+ });
6721
+ }
6722
+ const legacy = safeSqliteIntegrityCheck(paths.legacyLocalStorePath);
6723
+ return legacyMigrationResult(false, undefined, paths, [], {
6724
+ status: legacy.ok ? "pending" : "legacy-invalid",
6725
+ integrityCheck: legacy.ok ? { legacy: legacy.result } : { legacy: "failed", error: legacy.error }
6726
+ });
6727
+ }
6728
+ function migrateLegacyLocalStoreIfNeeded(root = process.cwd(), env = process.env) {
6729
+ const paths = runtimeStatePaths(root, env);
6730
+ if (env[ARCHCONTEXT_LOCAL_STORE_PATH_ENV]) {
6731
+ return legacyMigrationResult(false, "explicit-local-store-override", paths, [], {
6732
+ status: "explicit-local-store-override"
6733
+ });
6734
+ }
6735
+ ensurePrivateDir(dirname2(paths.localStorePath));
6736
+ const legacyExists = existsSync3(paths.legacyLocalStorePath);
6737
+ const integrityCheck = {};
6738
+ const quarantinedFiles = [];
6739
+ if (existsSync3(paths.localStorePath)) {
6740
+ try {
6741
+ integrityCheck.target = assertSqliteIntegrity(paths.localStorePath);
6742
+ return legacyMigrationResult(false, "target-exists", paths, [], {
6743
+ status: "target-current",
6744
+ integrityCheck
6745
+ });
6746
+ } catch (error) {
6747
+ integrityCheck.target = "failed";
6748
+ integrityCheck.error = error instanceof Error ? error.message : String(error);
6749
+ if (!legacyExists) {
6750
+ throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}`);
6751
+ }
6752
+ quarantinedFiles.push(...quarantineExistingLocalStore(paths));
6753
+ }
6754
+ }
6755
+ if (!legacyExists) {
6756
+ return legacyMigrationResult(false, "legacy-missing", paths, [], {
6757
+ status: "legacy-missing",
6758
+ integrityCheck
6759
+ });
6760
+ }
6761
+ const lock = acquireLegacyMigrationLock(paths);
6762
+ const stagingDir = join2(paths.workspaceStateDir, `.runtime.sqlite.migration-${process.pid}-${randomUUID()}`);
6763
+ const stagingPath = join2(stagingDir, "runtime.sqlite");
6764
+ try {
6765
+ ensurePrivateDir(stagingDir);
6766
+ integrityCheck.legacy = vacuumLegacySqliteInto(paths.legacyLocalStorePath, stagingPath);
6767
+ makePrivateFile(stagingPath);
6768
+ migrateSqliteDatabaseSync(stagingPath);
6769
+ compactSqliteDatabase(stagingPath);
6770
+ integrityCheck.staging = assertSqliteIntegrity(stagingPath);
6771
+ publishStagedLocalStore(stagingPath, paths.localStorePath);
6772
+ integrityCheck.target = assertSqliteIntegrity(paths.localStorePath);
6773
+ const markerPath = writeLegacyMigrationMarker(paths, integrityCheck, quarantinedFiles);
6774
+ return legacyMigrationResult(true, undefined, paths, [paths.localStorePath], {
6775
+ status: quarantinedFiles.length > 0 ? "target-quarantined-and-migrated" : "migrated",
6776
+ integrityCheck,
6777
+ markerPath,
6778
+ quarantinedFiles
6779
+ });
6780
+ } catch (error) {
6781
+ throw new Error(`ArchContext legacy SQLite migration failed: ${error instanceof Error ? error.message : String(error)}`);
6782
+ } finally {
6783
+ rmSync2(stagingDir, { recursive: true, force: true });
6784
+ releaseLegacyMigrationLock(lock);
6785
+ }
6786
+ }
6787
+ function openSqliteDatabaseSync(databasePath) {
6788
+ if (databasePath !== ":memory:")
6789
+ ensurePrivateDir(dirname2(databasePath));
6790
+ try {
6791
+ const nodeSqlite = runtimeRequire("node:sqlite");
6792
+ const db2 = new nodeSqlite.DatabaseSync(databasePath);
6793
+ return {
6794
+ exec: (sql) => db2.exec(sql),
6795
+ prepare: (sql) => db2.prepare(sql),
6796
+ close: () => db2.close()
6797
+ };
6798
+ } catch (error) {
6799
+ if (error.code !== "ERR_UNKNOWN_BUILTIN_MODULE" && error.code !== "MODULE_NOT_FOUND") {
6800
+ throw error;
6801
+ }
6802
+ }
6803
+ const bunSqlite = runtimeRequire("bun:sqlite");
6804
+ const db = new bunSqlite.Database(databasePath);
6805
+ return {
6806
+ exec: (sql) => db.exec(sql),
6807
+ prepare: (sql) => db.query(sql),
6808
+ close: () => db.close()
6809
+ };
6810
+ }
6811
+ function legacyMigrationResult(migrated, skippedReason, paths, copiedFiles, details) {
6812
+ return {
6813
+ schemaVersion: "archcontext.legacy-local-store-migration/v1",
6814
+ status: details.status,
6815
+ migrated,
6816
+ skippedReason,
6817
+ legacyLocalStorePath: paths.legacyLocalStorePath,
6818
+ targetLocalStorePath: paths.localStorePath,
6819
+ markerPath: details.markerPath ?? legacyMigrationMarkerPath(paths),
6820
+ lockPath: legacyMigrationLockPath(paths),
6821
+ integrityCheck: details.integrityCheck ?? {},
6822
+ copiedFiles,
6823
+ quarantinedFiles: details.quarantinedFiles ?? []
6824
+ };
6825
+ }
6826
+ function safeSqliteIntegrityCheck(path) {
6827
+ try {
6828
+ return { ok: true, result: assertSqliteIntegrity(path) };
6829
+ } catch (error) {
6830
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
6831
+ }
6832
+ }
6833
+ function assertSqliteIntegrity(path) {
6834
+ const db = openSqliteDatabaseSync(path);
6835
+ try {
6836
+ db.exec("PRAGMA busy_timeout = 5000");
6837
+ const row = db.prepare("PRAGMA integrity_check").get();
6838
+ const result = firstSqliteColumn(row);
6839
+ if (result !== "ok")
6840
+ throw new Error(`SQLite integrity_check failed for ${path}: ${result}`);
6841
+ return result;
6842
+ } finally {
6843
+ db.close();
6844
+ }
6845
+ }
6846
+ function vacuumLegacySqliteInto(sourcePath, targetPath) {
6847
+ const db = openSqliteDatabaseSync(sourcePath);
6848
+ try {
6849
+ db.exec("PRAGMA busy_timeout = 5000");
6850
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
6851
+ const integrity = sqliteIntegrityCheckOpenDatabase(db, sourcePath);
6852
+ db.exec(`VACUUM INTO ${sqliteStringLiteral(targetPath)}`);
6853
+ return integrity;
6854
+ } finally {
6855
+ db.close();
6856
+ }
6857
+ }
6858
+ function migrateSqliteDatabaseSync(databasePath) {
6859
+ const db = openSqliteDatabaseSync(databasePath);
6860
+ try {
6861
+ for (const pragma of SQLITE_PRAGMAS)
6862
+ db.exec(pragma);
6863
+ for (const migration of LOCAL_SQLITE_MIGRATIONS) {
6864
+ for (const statement of migration.statements)
6865
+ db.exec(statement);
6866
+ db.prepare("INSERT OR IGNORE INTO schema_migrations (id, applied_at) VALUES (?, ?)").run(migration.id, nowIso());
6867
+ }
6868
+ } finally {
6869
+ db.close();
6870
+ }
6871
+ }
6872
+ function compactSqliteDatabase(databasePath) {
6873
+ const db = openSqliteDatabaseSync(databasePath);
6874
+ try {
6875
+ db.exec("PRAGMA busy_timeout = 5000");
6876
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
6877
+ db.exec("PRAGMA journal_mode = DELETE");
6878
+ } finally {
6879
+ db.close();
6880
+ }
6881
+ for (const suffix of ["-wal", "-shm"])
6882
+ rmSync2(`${databasePath}${suffix}`, { force: true });
6883
+ }
6884
+ function sqliteIntegrityCheckOpenDatabase(db, path) {
6885
+ const row = db.prepare("PRAGMA integrity_check").get();
6886
+ const result = firstSqliteColumn(row);
6887
+ if (result !== "ok")
6888
+ throw new Error(`SQLite integrity_check failed for ${path}: ${result}`);
6889
+ return result;
6890
+ }
6891
+ function firstSqliteColumn(row) {
6892
+ const value = row ? Object.values(row)[0] : undefined;
6893
+ return typeof value === "string" ? value : String(value ?? "");
6894
+ }
6895
+ function sqliteStringLiteral(value) {
6896
+ return `'${value.replace(/'/g, "''")}'`;
6897
+ }
6898
+ function publishStagedLocalStore(stagingPath, targetPath) {
6899
+ for (const suffix of SQLITE_SIDECAR_SUFFIXES) {
6900
+ const path = `${targetPath}${suffix}`;
6901
+ if (existsSync3(path))
6902
+ throw new Error(`Cannot publish migrated SQLite over existing target file: ${path}`);
6903
+ }
6904
+ renameSync2(stagingPath, targetPath);
6905
+ makePrivateFile(targetPath);
6906
+ fsyncDirectory2(dirname2(targetPath));
6907
+ }
6908
+ function writeLegacyMigrationMarker(paths, integrityCheck, quarantinedFiles) {
6909
+ const markerPath = legacyMigrationMarkerPath(paths);
6910
+ writePrivateJson(markerPath, {
6911
+ schemaVersion: "archcontext.legacy-local-store-migration-marker/v1",
6912
+ migratedAt: nowIso(),
6913
+ legacyLocalStorePath: paths.legacyLocalStorePath,
6914
+ targetLocalStorePath: paths.localStorePath,
6915
+ integrityCheck,
6916
+ quarantinedFiles
6917
+ });
6918
+ return markerPath;
6919
+ }
6920
+ function acquireLegacyMigrationLock(paths) {
6921
+ const lockPath = legacyMigrationLockPath(paths);
6922
+ ensurePrivateDir(dirname2(lockPath));
6923
+ try {
6924
+ const fd = openSync3(lockPath, "wx", 384);
6925
+ writeFileSync2(fd, JSON.stringify({
6926
+ schemaVersion: "archcontext.legacy-local-store-migration-lock/v1",
6927
+ pid: process.pid,
6928
+ root: paths.repositoryRoot,
6929
+ targetLocalStorePath: paths.localStorePath,
6930
+ startedAt: nowIso()
6931
+ }, null, 2), "utf8");
6932
+ fsyncSync2(fd);
6933
+ return { fd, path: lockPath };
6934
+ } catch (error) {
6935
+ const code = error.code;
6936
+ if (code === "EEXIST" && isStaleMigrationLock(lockPath)) {
6937
+ rmSync2(lockPath, { force: true });
6938
+ return acquireLegacyMigrationLock(paths);
6939
+ }
6940
+ if (code === "EEXIST")
6941
+ throw new Error(`Legacy SQLite migration already in progress; lock=${lockPath}`);
6942
+ throw error;
6943
+ }
6944
+ }
6945
+ function releaseLegacyMigrationLock(lock) {
6946
+ closeSync3(lock.fd);
6947
+ rmSync2(lock.path, { force: true });
6948
+ }
6949
+ function isStaleMigrationLock(lockPath) {
6950
+ try {
6951
+ const parsed = JSON.parse(readFileSync5(lockPath, "utf8"));
6952
+ if (typeof parsed.pid !== "number" || parsed.pid <= 0)
6953
+ return true;
6954
+ return !isProcessAlive(parsed.pid);
6955
+ } catch {
6956
+ return true;
6957
+ }
6958
+ }
6959
+ function isProcessAlive(pid) {
6960
+ try {
6961
+ process.kill(pid, 0);
6962
+ return true;
6963
+ } catch (error) {
6964
+ return error.code !== "ESRCH";
6965
+ }
6966
+ }
6967
+ function quarantineExistingLocalStore(paths) {
6968
+ const quarantineDir = join2(paths.workspaceStateDir, "quarantine", `runtime.sqlite-${Date.now()}-${randomUUID()}`);
6969
+ ensurePrivateDir(quarantineDir);
6970
+ const quarantinedFiles = [];
6971
+ for (const suffix of SQLITE_SIDECAR_SUFFIXES) {
6972
+ const source = `${paths.localStorePath}${suffix}`;
6973
+ if (!existsSync3(source))
6974
+ continue;
6975
+ const target = join2(quarantineDir, `runtime.sqlite${suffix}`);
6976
+ renameSync2(source, target);
6977
+ quarantinedFiles.push(target);
6978
+ }
6979
+ const markerPath = legacyMigrationMarkerPath(paths);
6980
+ if (existsSync3(markerPath)) {
6981
+ const target = join2(quarantineDir, LEGACY_MIGRATION_MARKER_FILE);
6982
+ renameSync2(markerPath, target);
6983
+ quarantinedFiles.push(target);
6984
+ }
6985
+ fsyncDirectory2(quarantineDir);
6986
+ fsyncDirectory2(dirname2(paths.localStorePath));
6987
+ return quarantinedFiles;
6988
+ }
6989
+ function legacyMigrationMarkerPath(paths) {
6990
+ return join2(paths.workspaceStateDir, LEGACY_MIGRATION_MARKER_FILE);
6991
+ }
6992
+ function legacyMigrationLockPath(paths) {
6993
+ return join2(paths.workspaceStateDir, LEGACY_MIGRATION_LOCK_FILE);
6994
+ }
6995
+ function writePrivateJson(path, value) {
6996
+ ensurePrivateDir(dirname2(path));
6997
+ const fd = openSync3(path, "w", 384);
6998
+ try {
6999
+ writeFileSync2(fd, JSON.stringify(value, null, 2), "utf8");
7000
+ fsyncSync2(fd);
7001
+ } finally {
7002
+ closeSync3(fd);
7003
+ }
7004
+ makePrivateFile(path);
7005
+ fsyncDirectory2(dirname2(path));
7006
+ }
7007
+ function ensurePrivateDir(path) {
7008
+ mkdirSync2(path, { recursive: true, mode: 448 });
7009
+ if (process.platform !== "win32") {
7010
+ try {
7011
+ chmodSync(path, 448);
7012
+ } catch {}
7013
+ }
7014
+ }
7015
+ function makePrivateFile(path) {
7016
+ if (process.platform !== "win32") {
7017
+ try {
7018
+ chmodSync(path, 384);
7019
+ } catch {}
7020
+ }
7021
+ }
7022
+ function readGitPath(root, args) {
7023
+ try {
7024
+ const value = execFileSync2("git", args, {
7025
+ cwd: root,
7026
+ encoding: "utf8",
7027
+ stdio: ["ignore", "pipe", "ignore"]
7028
+ }).trim();
7029
+ return value.length > 0 ? value : undefined;
7030
+ } catch {
7031
+ return;
7032
+ }
7033
+ }
7034
+ function resolveMaybeRelative(base, path) {
7035
+ return isAbsolute3(path) ? resolve6(path) : resolve6(base, path);
7036
+ }
7037
+ function canonicalPath(path) {
7038
+ const resolved = resolve6(path);
7039
+ try {
7040
+ return realpathSync4.native(resolved);
7041
+ } catch {
7042
+ return resolved;
7043
+ }
7044
+ }
7045
+ function stableStorageId(prefix, value) {
7046
+ return `${prefix}.${createHash5("sha256").update(value).digest("hex").slice(0, 16)}`;
7047
+ }
7048
+ function nowIso() {
7049
+ return new Date().toISOString();
7050
+ }
7051
+ function fsyncDirectory2(path) {
7052
+ try {
7053
+ const fd = openSync3(path, "r");
7054
+ try {
7055
+ fsyncSync2(fd);
7056
+ } finally {
7057
+ closeSync3(fd);
7058
+ }
7059
+ } catch (error) {
7060
+ if (!isIgnorableDirectoryFsyncError2(error))
7061
+ throw error;
7062
+ }
7063
+ }
7064
+ function isIgnorableDirectoryFsyncError2(error) {
7065
+ const code = error.code;
7066
+ return code === "EINVAL" || code === "EISDIR" || process.platform === "win32" && code === "EPERM";
6530
7067
  }
6531
7068
 
6532
7069
  // packages/local-runtime/git-adapter/src/index.ts
6533
- import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
6534
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, rmSync as rmSync2 } from "node:fs";
7070
+ import { execFileSync as execFileSync3, spawnSync } from "node:child_process";
7071
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, mkdtempSync, rmSync as rmSync3 } from "node:fs";
6535
7072
  import { dirname as dirname3, join as join3, resolve as resolve7 } from "node:path";
6536
7073
  function findRepositoryRoot(start) {
6537
7074
  try {
6538
- return resolve7(execFileSync2("git", ["rev-parse", "--show-toplevel"], {
7075
+ return resolve7(execFileSync3("git", ["rev-parse", "--show-toplevel"], {
6539
7076
  cwd: start,
6540
7077
  encoding: "utf8",
6541
7078
  stdio: ["ignore", "pipe", "ignore"]
@@ -6543,7 +7080,7 @@ function findRepositoryRoot(start) {
6543
7080
  } catch {
6544
7081
  let cursor = resolve7(start);
6545
7082
  while (cursor !== "/") {
6546
- if (existsSync3(resolve7(cursor, ".git")))
7083
+ if (existsSync4(resolve7(cursor, ".git")))
6547
7084
  return cursor;
6548
7085
  cursor = resolve7(cursor, "..");
6549
7086
  }
@@ -6552,7 +7089,7 @@ function findRepositoryRoot(start) {
6552
7089
  }
6553
7090
  function readHeadSha(root) {
6554
7091
  try {
6555
- return execFileSync2("git", ["rev-parse", "HEAD"], {
7092
+ return execFileSync3("git", ["rev-parse", "HEAD"], {
6556
7093
  cwd: root,
6557
7094
  encoding: "utf8",
6558
7095
  stdio: ["ignore", "pipe", "ignore"]
@@ -6564,7 +7101,7 @@ function readHeadSha(root) {
6564
7101
 
6565
7102
  // packages/local-runtime/runtime-daemon/src/index.ts
6566
7103
  import { randomBytes } from "node:crypto";
6567
- import { chmodSync, closeSync as closeSync4, existsSync as existsSync7, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync3, openSync as openSync4, readdirSync as readdirSync5, readFileSync as readFileSync6, rmSync as rmSync6, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
7104
+ import { chmodSync as chmodSync3, closeSync as closeSync5, existsSync as existsSync8, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync3, openSync as openSync5, readdirSync as readdirSync5, readFileSync as readFileSync8, rmSync as rmSync7, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
6568
7105
  import { createServer } from "node:http";
6569
7106
  import { tmpdir as tmpdir2 } from "node:os";
6570
7107
  import { dirname as dirname7, join as join6, resolve as resolve11 } from "node:path";
@@ -6599,13 +7136,13 @@ async function prepareTask(input) {
6599
7136
  init_src();
6600
7137
 
6601
7138
  // packages/local-runtime/git-adapter/src/index.ts
6602
- import { execFileSync as execFileSync3, spawnSync as spawnSync2 } from "node:child_process";
6603
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
7139
+ import { execFileSync as execFileSync4, spawnSync as spawnSync2 } from "node:child_process";
7140
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync2, rmSync as rmSync4 } from "node:fs";
6604
7141
  import { dirname as dirname4, join as join4, resolve as resolve8 } from "node:path";
6605
7142
  import { tmpdir } from "node:os";
6606
7143
  function findRepositoryRoot2(start) {
6607
7144
  try {
6608
- return resolve8(execFileSync3("git", ["rev-parse", "--show-toplevel"], {
7145
+ return resolve8(execFileSync4("git", ["rev-parse", "--show-toplevel"], {
6609
7146
  cwd: start,
6610
7147
  encoding: "utf8",
6611
7148
  stdio: ["ignore", "pipe", "ignore"]
@@ -6613,7 +7150,7 @@ function findRepositoryRoot2(start) {
6613
7150
  } catch {
6614
7151
  let cursor = resolve8(start);
6615
7152
  while (cursor !== "/") {
6616
- if (existsSync4(resolve8(cursor, ".git")))
7153
+ if (existsSync5(resolve8(cursor, ".git")))
6617
7154
  return cursor;
6618
7155
  cursor = resolve8(cursor, "..");
6619
7156
  }
@@ -6622,7 +7159,7 @@ function findRepositoryRoot2(start) {
6622
7159
  }
6623
7160
  function readHeadSha2(root) {
6624
7161
  try {
6625
- return execFileSync3("git", ["rev-parse", "HEAD"], {
7162
+ return execFileSync4("git", ["rev-parse", "HEAD"], {
6626
7163
  cwd: root,
6627
7164
  encoding: "utf8",
6628
7165
  stdio: ["ignore", "pipe", "ignore"]
@@ -6682,7 +7219,7 @@ function prepareDetachedReviewWorktree(input) {
6682
7219
  };
6683
7220
  }
6684
7221
  const parent = input.tempRoot ? resolve8(input.tempRoot) : tmpdir();
6685
- mkdirSync3(parent, { recursive: true });
7222
+ mkdirSync4(parent, { recursive: true });
6686
7223
  const temporaryRoot = mkdtempSync2(join4(parent, "archctx-review-worktree-"));
6687
7224
  const worktreeRoot = join4(temporaryRoot, "worktree");
6688
7225
  try {
@@ -6714,7 +7251,7 @@ function prepareDetachedReviewWorktree(input) {
6714
7251
  }
6715
7252
  };
6716
7253
  } catch (error) {
6717
- rmSync3(temporaryRoot, { recursive: true, force: true });
7254
+ rmSync4(temporaryRoot, { recursive: true, force: true });
6718
7255
  if (isGitWorktreeError(error)) {
6719
7256
  return {
6720
7257
  schemaVersion: "archcontext.detached-review-worktree-verification/v1",
@@ -6731,9 +7268,9 @@ function removeDetachedReviewWorktree(worktree) {
6731
7268
  try {
6732
7269
  runGit(worktree.sourceRoot, ["worktree", "remove", "--force", worktree.worktreeRoot]);
6733
7270
  } catch {
6734
- rmSync3(worktree.worktreeRoot, { recursive: true, force: true });
7271
+ rmSync4(worktree.worktreeRoot, { recursive: true, force: true });
6735
7272
  } finally {
6736
- rmSync3(worktree.temporaryRoot || dirname4(worktree.worktreeRoot), { recursive: true, force: true });
7273
+ rmSync4(worktree.temporaryRoot || dirname4(worktree.worktreeRoot), { recursive: true, force: true });
6737
7274
  }
6738
7275
  }
6739
7276
  function readCommitTreeOid(root, headSha) {
@@ -6769,7 +7306,7 @@ function readDetachedWorktreeObserved(worktreeRoot) {
6769
7306
  }
6770
7307
  }
6771
7308
  function runGit(root, args) {
6772
- return execFileSync3("git", args, {
7309
+ return execFileSync4("git", args, {
6773
7310
  cwd: root,
6774
7311
  encoding: "utf8",
6775
7312
  stdio: ["ignore", "pipe", "pipe"]
@@ -6787,16 +7324,23 @@ function isGitWorktreeError(error) {
6787
7324
  }
6788
7325
 
6789
7326
  // packages/local-runtime/local-store-sqlite/src/index.ts
6790
- import { randomUUID } from "node:crypto";
6791
- import { closeSync as closeSync3, existsSync as existsSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync4, openSync as openSync3, renameSync as renameSync2, rmSync as rmSync4 } from "node:fs";
7327
+ import { execFileSync as execFileSync5 } from "node:child_process";
7328
+ import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
7329
+ import { chmodSync as chmodSync2, closeSync as closeSync4, existsSync as existsSync6, fsyncSync as fsyncSync3, mkdirSync as mkdirSync5, openSync as openSync4, readFileSync as readFileSync6, realpathSync as realpathSync5, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync3 } from "node:fs";
6792
7330
  import { readdir, readFile } from "node:fs/promises";
6793
- import { dirname as dirname5, join as join5, resolve as resolve9 } from "node:path";
6794
- var SQLITE_PRAGMAS = [
7331
+ import { createRequire as createRequire3 } from "node:module";
7332
+ import { homedir as homedir2 } from "node:os";
7333
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join5, resolve as resolve9 } from "node:path";
7334
+ var runtimeRequire2 = createRequire3(import.meta.url);
7335
+ var SQLITE_SIDECAR_SUFFIXES2 = ["", "-wal", "-shm"];
7336
+ var LEGACY_MIGRATION_MARKER_FILE2 = "runtime.sqlite.migration.json";
7337
+ var LEGACY_MIGRATION_LOCK_FILE2 = "runtime.sqlite.migration.lock";
7338
+ var SQLITE_PRAGMAS2 = [
6795
7339
  "PRAGMA journal_mode = WAL",
6796
7340
  "PRAGMA foreign_keys = ON",
6797
7341
  "PRAGMA busy_timeout = 5000"
6798
7342
  ];
6799
- var LOCAL_SQLITE_MIGRATIONS = [
7343
+ var LOCAL_SQLITE_MIGRATIONS2 = [
6800
7344
  {
6801
7345
  id: "0001_runtime_state",
6802
7346
  statements: [
@@ -6893,8 +7437,114 @@ var LOCAL_SQLITE_MIGRATIONS = [
6893
7437
  ]
6894
7438
  }
6895
7439
  ];
7440
+ var ARCHCONTEXT_STATE_DIR_ENV2 = "ARCHCONTEXT_STATE_DIR";
7441
+ var ARCHCONTEXT_LOCAL_STORE_PATH_ENV2 = "ARCHCONTEXT_LOCAL_STORE_PATH";
7442
+ function defaultArchContextStateRoot2(env = process.env, platform = process.platform, home = homedir2()) {
7443
+ const override = env[ARCHCONTEXT_STATE_DIR_ENV2];
7444
+ if (override)
7445
+ return { path: resolve9(override), source: "environment" };
7446
+ if (platform === "darwin")
7447
+ return { path: join5(home, "Library", "Application Support", "ArchContext"), source: "os-user-data" };
7448
+ if (platform === "win32")
7449
+ return { path: join5(env.LOCALAPPDATA ?? join5(home, "AppData", "Local"), "ArchContext"), source: "os-user-data" };
7450
+ return { path: join5(env.XDG_DATA_HOME ?? join5(home, ".local", "share"), "archcontext"), source: "os-user-data" };
7451
+ }
7452
+ function runtimeStatePaths2(root = process.cwd(), env = process.env) {
7453
+ const repositoryRoot = readGitPath2(root, ["rev-parse", "--show-toplevel"]) ?? root;
7454
+ const canonicalRepositoryRoot3 = canonicalPath2(repositoryRoot);
7455
+ const gitCommonDir = readGitPath2(canonicalRepositoryRoot3, ["rev-parse", "--git-common-dir"]);
7456
+ const repositoryAnchor = canonicalPath2(gitCommonDir ? resolveMaybeRelative2(canonicalRepositoryRoot3, gitCommonDir) : canonicalRepositoryRoot3);
7457
+ const workspaceAnchor = canonicalRepositoryRoot3;
7458
+ const storageRepositoryId = stableStorageId2("repo", repositoryAnchor);
7459
+ const storageWorkspaceId = stableStorageId2("ws", workspaceAnchor);
7460
+ const stateRoot = defaultArchContextStateRoot2(env);
7461
+ const repositoryStateDir = join5(stateRoot.path, "repositories", storageRepositoryId);
7462
+ const workspaceStateDir = join5(repositoryStateDir, "worktrees", storageWorkspaceId);
7463
+ const legacyControlDir = resolve9(canonicalRepositoryRoot3, ".archcontext", ".local");
7464
+ return {
7465
+ schemaVersion: "archcontext.runtime-state-paths/v1",
7466
+ stateRoot: stateRoot.path,
7467
+ source: stateRoot.source,
7468
+ repositoryRoot: canonicalRepositoryRoot3,
7469
+ repositoryAnchor,
7470
+ workspaceAnchor,
7471
+ storageRepositoryId,
7472
+ storageWorkspaceId,
7473
+ repositoryId: storageRepositoryId,
7474
+ workspaceId: storageWorkspaceId,
7475
+ repositoryStateDir,
7476
+ workspaceStateDir,
7477
+ sharedCacheDir: join5(repositoryStateDir, "shared", "cache"),
7478
+ localStorePath: env[ARCHCONTEXT_LOCAL_STORE_PATH_ENV2] ?? join5(workspaceStateDir, "runtime.sqlite"),
7479
+ daemonConnectionPath: join5(workspaceStateDir, "archctxd.json"),
7480
+ daemonLockPath: join5(workspaceStateDir, "archctxd.lock"),
7481
+ daemonLogPath: join5(workspaceStateDir, "archctxd.log"),
7482
+ developerReviewRunStateDir: join5(workspaceStateDir, "developer-review-runs"),
7483
+ legacyControlDir,
7484
+ legacyLocalStorePath: join5(legacyControlDir, "runtime.sqlite")
7485
+ };
7486
+ }
6896
7487
  function defaultLocalStorePath2(root = process.cwd()) {
6897
- return process.env.ARCHCONTEXT_LOCAL_STORE_PATH ?? resolve9(root, ".archcontext/.local/runtime.sqlite");
7488
+ return runtimeStatePaths2(root).localStorePath;
7489
+ }
7490
+ function migrateLegacyLocalStoreIfNeeded2(root = process.cwd(), env = process.env) {
7491
+ const paths = runtimeStatePaths2(root, env);
7492
+ if (env[ARCHCONTEXT_LOCAL_STORE_PATH_ENV2]) {
7493
+ return legacyMigrationResult2(false, "explicit-local-store-override", paths, [], {
7494
+ status: "explicit-local-store-override"
7495
+ });
7496
+ }
7497
+ ensurePrivateDir2(dirname5(paths.localStorePath));
7498
+ const legacyExists = existsSync6(paths.legacyLocalStorePath);
7499
+ const integrityCheck = {};
7500
+ const quarantinedFiles = [];
7501
+ if (existsSync6(paths.localStorePath)) {
7502
+ try {
7503
+ integrityCheck.target = assertSqliteIntegrity2(paths.localStorePath);
7504
+ return legacyMigrationResult2(false, "target-exists", paths, [], {
7505
+ status: "target-current",
7506
+ integrityCheck
7507
+ });
7508
+ } catch (error) {
7509
+ integrityCheck.target = "failed";
7510
+ integrityCheck.error = error instanceof Error ? error.message : String(error);
7511
+ if (!legacyExists) {
7512
+ throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}`);
7513
+ }
7514
+ quarantinedFiles.push(...quarantineExistingLocalStore2(paths));
7515
+ }
7516
+ }
7517
+ if (!legacyExists) {
7518
+ return legacyMigrationResult2(false, "legacy-missing", paths, [], {
7519
+ status: "legacy-missing",
7520
+ integrityCheck
7521
+ });
7522
+ }
7523
+ const lock = acquireLegacyMigrationLock2(paths);
7524
+ const stagingDir = join5(paths.workspaceStateDir, `.runtime.sqlite.migration-${process.pid}-${randomUUID2()}`);
7525
+ const stagingPath = join5(stagingDir, "runtime.sqlite");
7526
+ try {
7527
+ ensurePrivateDir2(stagingDir);
7528
+ integrityCheck.legacy = vacuumLegacySqliteInto2(paths.legacyLocalStorePath, stagingPath);
7529
+ makePrivateFile2(stagingPath);
7530
+ migrateSqliteDatabaseSync2(stagingPath);
7531
+ compactSqliteDatabase2(stagingPath);
7532
+ integrityCheck.staging = assertSqliteIntegrity2(stagingPath);
7533
+ publishStagedLocalStore2(stagingPath, paths.localStorePath);
7534
+ integrityCheck.target = assertSqliteIntegrity2(paths.localStorePath);
7535
+ const markerPath = writeLegacyMigrationMarker2(paths, integrityCheck, quarantinedFiles);
7536
+ return legacyMigrationResult2(true, undefined, paths, [paths.localStorePath], {
7537
+ status: quarantinedFiles.length > 0 ? "target-quarantined-and-migrated" : "migrated",
7538
+ integrityCheck,
7539
+ markerPath,
7540
+ quarantinedFiles
7541
+ });
7542
+ } catch (error) {
7543
+ throw new Error(`ArchContext legacy SQLite migration failed: ${error instanceof Error ? error.message : String(error)}`);
7544
+ } finally {
7545
+ rmSync5(stagingDir, { recursive: true, force: true });
7546
+ releaseLegacyMigrationLock2(lock);
7547
+ }
6898
7548
  }
6899
7549
 
6900
7550
  class SqliteLocalStore {
@@ -6905,20 +7555,20 @@ class SqliteLocalStore {
6905
7555
  }
6906
7556
  async migrate() {
6907
7557
  const db = await this.database();
6908
- for (const pragma of SQLITE_PRAGMAS)
7558
+ for (const pragma of SQLITE_PRAGMAS2)
6909
7559
  db.exec(pragma);
6910
- for (const migration of LOCAL_SQLITE_MIGRATIONS) {
7560
+ for (const migration of LOCAL_SQLITE_MIGRATIONS2) {
6911
7561
  for (const statement of migration.statements)
6912
7562
  db.exec(statement);
6913
- db.prepare("INSERT OR IGNORE INTO schema_migrations (id, applied_at) VALUES (?, ?)").run(migration.id, nowIso());
7563
+ db.prepare("INSERT OR IGNORE INTO schema_migrations (id, applied_at) VALUES (?, ?)").run(migration.id, nowIso2());
6914
7564
  }
6915
7565
  }
6916
7566
  async beginSnapshot(snapshot) {
6917
7567
  const db = await this.database();
6918
- const snapshotId = `snapshot_${randomUUID()}`;
7568
+ const snapshotId = `snapshot_${randomUUID2()}`;
6919
7569
  db.prepare(`INSERT INTO snapshots
6920
7570
  (id, repository_id, head_sha, worktree_digest, state, created_at)
6921
- VALUES (?, ?, ?, ?, ?, ?)`).run(snapshotId, snapshot.repositoryId, snapshot.headSha, snapshot.worktreeDigest, "pending", nowIso());
7571
+ VALUES (?, ?, ?, ?, ?, ?)`).run(snapshotId, snapshot.repositoryId, snapshot.headSha, snapshot.worktreeDigest, "pending", nowIso2());
6922
7572
  return snapshotId;
6923
7573
  }
6924
7574
  async commitSnapshot(snapshotId) {
@@ -6926,7 +7576,7 @@ class SqliteLocalStore {
6926
7576
  const existing = db.prepare("SELECT id FROM snapshots WHERE id = ?").get(snapshotId);
6927
7577
  if (!existing)
6928
7578
  throw new Error(`Snapshot not found: ${snapshotId}`);
6929
- db.prepare("UPDATE snapshots SET state = ?, committed_at = ? WHERE id = ?").run("committed", nowIso(), snapshotId);
7579
+ db.prepare("UPDATE snapshots SET state = ?, committed_at = ? WHERE id = ?").run("committed", nowIso2(), snapshotId);
6930
7580
  }
6931
7581
  recoverPendingSnapshots() {
6932
7582
  const db = this.requireOpenDatabase();
@@ -6954,10 +7604,10 @@ class SqliteLocalStore {
6954
7604
  }
6955
7605
  async beginChangeSet(root, draft) {
6956
7606
  const db = await this.database();
6957
- const journalId = `changeset_${randomUUID()}`;
7607
+ const journalId = `changeset_${randomUUID2()}`;
6958
7608
  db.prepare(`INSERT INTO changeset_journal
6959
7609
  (journal_id, changeset_id, root, status, metadata_json, files_json, created_at, updated_at)
6960
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(journalId, draft.id, root, "pending", stableJson(changeSetMetadata(draft)), "[]", nowIso(), nowIso());
7610
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(journalId, draft.id, root, "pending", stableJson(changeSetMetadata(draft)), "[]", nowIso2(), nowIso2());
6961
7611
  return journalId;
6962
7612
  }
6963
7613
  async recordChangeSetFile(journalId, file) {
@@ -6967,14 +7617,14 @@ class SqliteLocalStore {
6967
7617
  throw new Error(`ChangeSet journal not found: ${journalId}`);
6968
7618
  const files = JSON.parse(String(row.files_json));
6969
7619
  files.push(file);
6970
- db.prepare("UPDATE changeset_journal SET files_json = ?, updated_at = ? WHERE journal_id = ?").run(stableJson(files), nowIso(), journalId);
7620
+ db.prepare("UPDATE changeset_journal SET files_json = ?, updated_at = ? WHERE journal_id = ?").run(stableJson(files), nowIso2(), journalId);
6971
7621
  }
6972
7622
  async commitChangeSet(journalId) {
6973
7623
  const db = await this.database();
6974
7624
  const existing = db.prepare("SELECT journal_id FROM changeset_journal WHERE journal_id = ?").get(journalId);
6975
7625
  if (!existing)
6976
7626
  throw new Error(`ChangeSet journal not found: ${journalId}`);
6977
- db.prepare("UPDATE changeset_journal SET status = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("committed", nowIso(), nowIso(), journalId);
7627
+ db.prepare("UPDATE changeset_journal SET status = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("committed", nowIso2(), nowIso2(), journalId);
6978
7628
  }
6979
7629
  async abortChangeSet(journalId, reason) {
6980
7630
  const db = await this.database();
@@ -6982,7 +7632,7 @@ class SqliteLocalStore {
6982
7632
  if (!row)
6983
7633
  throw new Error(`ChangeSet journal not found: ${journalId}`);
6984
7634
  const metadata = JSON.parse(String(row.metadata_json));
6985
- db.prepare("UPDATE changeset_journal SET status = ?, metadata_json = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("aborted", stableJson({ ...metadata, abortReason: reason }), nowIso(), nowIso(), journalId);
7635
+ db.prepare("UPDATE changeset_journal SET status = ?, metadata_json = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("aborted", stableJson({ ...metadata, abortReason: reason }), nowIso2(), nowIso2(), journalId);
6986
7636
  }
6987
7637
  recoverPendingChangeSets() {
6988
7638
  const db = this.requireOpenDatabase();
@@ -6994,7 +7644,7 @@ class SqliteLocalStore {
6994
7644
  for (const row of rows) {
6995
7645
  const files = JSON.parse(String(row.files_json));
6996
7646
  recoverJournalFiles(String(row.root), files);
6997
- db.prepare("UPDATE changeset_journal SET status = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("recovered", nowIso(), nowIso(), String(row.journal_id));
7647
+ db.prepare("UPDATE changeset_journal SET status = ?, updated_at = ?, completed_at = ? WHERE journal_id = ?").run("recovered", nowIso2(), nowIso2(), String(row.journal_id));
6998
7648
  }
6999
7649
  return rows.length;
7000
7650
  }
@@ -7002,7 +7652,7 @@ class SqliteLocalStore {
7002
7652
  const db = await this.database();
7003
7653
  db.prepare(`INSERT OR REPLACE INTO task_states
7004
7654
  (task_session_id, payload_json, updated_at)
7005
- VALUES (?, ?, ?)`).run(taskSessionId, stableJson(state), nowIso());
7655
+ VALUES (?, ?, ?)`).run(taskSessionId, stableJson(state), nowIso2());
7006
7656
  }
7007
7657
  async readTaskState(taskSessionId) {
7008
7658
  const db = await this.database();
@@ -7013,13 +7663,13 @@ class SqliteLocalStore {
7013
7663
  const db = await this.database();
7014
7664
  db.prepare(`INSERT OR REPLACE INTO review_results
7015
7665
  (review_id, task_session_id, payload_json, created_at)
7016
- VALUES (?, ?, ?, ?)`).run(reviewId, reviewTaskSessionId(result) ?? reviewId, stableJson(result), nowIso());
7666
+ VALUES (?, ?, ?, ?)`).run(reviewId, reviewTaskSessionId(result) ?? reviewId, stableJson(result), nowIso2());
7017
7667
  }
7018
7668
  async saveLandscape(landscape) {
7019
7669
  const db = await this.database();
7020
7670
  db.prepare(`INSERT OR REPLACE INTO landscapes
7021
7671
  (id, digest, metadata_json, updated_at)
7022
- VALUES (?, ?, ?, ?)`).run(landscape.id, landscapeDigest(landscape), stableJson(landscape), nowIso());
7672
+ VALUES (?, ?, ?, ?)`).run(landscape.id, landscapeDigest(landscape), stableJson(landscape), nowIso2());
7023
7673
  }
7024
7674
  async readLandscape(landscapeId) {
7025
7675
  const db = await this.database();
@@ -7030,7 +7680,7 @@ class SqliteLocalStore {
7030
7680
  const db = await this.database();
7031
7681
  db.prepare(`INSERT OR REPLACE INTO cross_repo_edges
7032
7682
  (id, landscape_id, from_repository_id, from_node_id, to_repository_id, to_node_id, via_kind, via_id, metadata_json, updated_at)
7033
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(relation.id, "unscoped", relation.source.repositoryId, relation.source.nodeId, relation.target.repositoryId, relation.target.nodeId, relation.via.kind, relation.via.id, stableJson(relation), nowIso());
7683
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(relation.id, "unscoped", relation.source.repositoryId, relation.source.nodeId, relation.target.repositoryId, relation.target.nodeId, relation.via.kind, relation.via.id, stableJson(relation), nowIso2());
7034
7684
  }
7035
7685
  async listCrossRepoRelations(landscape) {
7036
7686
  const db = await this.database();
@@ -7090,7 +7740,7 @@ async function rebuildDerivedLandscapeState(store, input) {
7090
7740
  }
7091
7741
  async function openSqliteDatabase(databasePath) {
7092
7742
  if (databasePath !== ":memory:")
7093
- mkdirSync4(dirname5(databasePath), { recursive: true });
7743
+ ensurePrivateDir2(dirname5(databasePath));
7094
7744
  try {
7095
7745
  const nodeSqlite = await import("node:sqlite");
7096
7746
  const db = new nodeSqlite.DatabaseSync(databasePath);
@@ -7109,10 +7759,264 @@ async function openSqliteDatabase(databasePath) {
7109
7759
  };
7110
7760
  }
7111
7761
  }
7762
+ function openSqliteDatabaseSync2(databasePath) {
7763
+ if (databasePath !== ":memory:")
7764
+ ensurePrivateDir2(dirname5(databasePath));
7765
+ try {
7766
+ const nodeSqlite = runtimeRequire2("node:sqlite");
7767
+ const db2 = new nodeSqlite.DatabaseSync(databasePath);
7768
+ return {
7769
+ exec: (sql) => db2.exec(sql),
7770
+ prepare: (sql) => db2.prepare(sql),
7771
+ close: () => db2.close()
7772
+ };
7773
+ } catch (error) {
7774
+ if (error.code !== "ERR_UNKNOWN_BUILTIN_MODULE" && error.code !== "MODULE_NOT_FOUND") {
7775
+ throw error;
7776
+ }
7777
+ }
7778
+ const bunSqlite = runtimeRequire2("bun:sqlite");
7779
+ const db = new bunSqlite.Database(databasePath);
7780
+ return {
7781
+ exec: (sql) => db.exec(sql),
7782
+ prepare: (sql) => db.query(sql),
7783
+ close: () => db.close()
7784
+ };
7785
+ }
7786
+ function legacyMigrationResult2(migrated, skippedReason, paths, copiedFiles, details) {
7787
+ return {
7788
+ schemaVersion: "archcontext.legacy-local-store-migration/v1",
7789
+ status: details.status,
7790
+ migrated,
7791
+ skippedReason,
7792
+ legacyLocalStorePath: paths.legacyLocalStorePath,
7793
+ targetLocalStorePath: paths.localStorePath,
7794
+ markerPath: details.markerPath ?? legacyMigrationMarkerPath2(paths),
7795
+ lockPath: legacyMigrationLockPath2(paths),
7796
+ integrityCheck: details.integrityCheck ?? {},
7797
+ copiedFiles,
7798
+ quarantinedFiles: details.quarantinedFiles ?? []
7799
+ };
7800
+ }
7801
+ function assertSqliteIntegrity2(path) {
7802
+ const db = openSqliteDatabaseSync2(path);
7803
+ try {
7804
+ db.exec("PRAGMA busy_timeout = 5000");
7805
+ const row = db.prepare("PRAGMA integrity_check").get();
7806
+ const result = firstSqliteColumn2(row);
7807
+ if (result !== "ok")
7808
+ throw new Error(`SQLite integrity_check failed for ${path}: ${result}`);
7809
+ return result;
7810
+ } finally {
7811
+ db.close();
7812
+ }
7813
+ }
7814
+ function vacuumLegacySqliteInto2(sourcePath, targetPath) {
7815
+ const db = openSqliteDatabaseSync2(sourcePath);
7816
+ try {
7817
+ db.exec("PRAGMA busy_timeout = 5000");
7818
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
7819
+ const integrity = sqliteIntegrityCheckOpenDatabase2(db, sourcePath);
7820
+ db.exec(`VACUUM INTO ${sqliteStringLiteral2(targetPath)}`);
7821
+ return integrity;
7822
+ } finally {
7823
+ db.close();
7824
+ }
7825
+ }
7826
+ function migrateSqliteDatabaseSync2(databasePath) {
7827
+ const db = openSqliteDatabaseSync2(databasePath);
7828
+ try {
7829
+ for (const pragma of SQLITE_PRAGMAS2)
7830
+ db.exec(pragma);
7831
+ for (const migration of LOCAL_SQLITE_MIGRATIONS2) {
7832
+ for (const statement of migration.statements)
7833
+ db.exec(statement);
7834
+ db.prepare("INSERT OR IGNORE INTO schema_migrations (id, applied_at) VALUES (?, ?)").run(migration.id, nowIso2());
7835
+ }
7836
+ } finally {
7837
+ db.close();
7838
+ }
7839
+ }
7840
+ function compactSqliteDatabase2(databasePath) {
7841
+ const db = openSqliteDatabaseSync2(databasePath);
7842
+ try {
7843
+ db.exec("PRAGMA busy_timeout = 5000");
7844
+ db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
7845
+ db.exec("PRAGMA journal_mode = DELETE");
7846
+ } finally {
7847
+ db.close();
7848
+ }
7849
+ for (const suffix of ["-wal", "-shm"])
7850
+ rmSync5(`${databasePath}${suffix}`, { force: true });
7851
+ }
7852
+ function sqliteIntegrityCheckOpenDatabase2(db, path) {
7853
+ const row = db.prepare("PRAGMA integrity_check").get();
7854
+ const result = firstSqliteColumn2(row);
7855
+ if (result !== "ok")
7856
+ throw new Error(`SQLite integrity_check failed for ${path}: ${result}`);
7857
+ return result;
7858
+ }
7859
+ function firstSqliteColumn2(row) {
7860
+ const value = row ? Object.values(row)[0] : undefined;
7861
+ return typeof value === "string" ? value : String(value ?? "");
7862
+ }
7863
+ function sqliteStringLiteral2(value) {
7864
+ return `'${value.replace(/'/g, "''")}'`;
7865
+ }
7866
+ function publishStagedLocalStore2(stagingPath, targetPath) {
7867
+ for (const suffix of SQLITE_SIDECAR_SUFFIXES2) {
7868
+ const path = `${targetPath}${suffix}`;
7869
+ if (existsSync6(path))
7870
+ throw new Error(`Cannot publish migrated SQLite over existing target file: ${path}`);
7871
+ }
7872
+ renameSync3(stagingPath, targetPath);
7873
+ makePrivateFile2(targetPath);
7874
+ fsyncDirectory3(dirname5(targetPath));
7875
+ }
7876
+ function writeLegacyMigrationMarker2(paths, integrityCheck, quarantinedFiles) {
7877
+ const markerPath = legacyMigrationMarkerPath2(paths);
7878
+ writePrivateJson2(markerPath, {
7879
+ schemaVersion: "archcontext.legacy-local-store-migration-marker/v1",
7880
+ migratedAt: nowIso2(),
7881
+ legacyLocalStorePath: paths.legacyLocalStorePath,
7882
+ targetLocalStorePath: paths.localStorePath,
7883
+ integrityCheck,
7884
+ quarantinedFiles
7885
+ });
7886
+ return markerPath;
7887
+ }
7888
+ function acquireLegacyMigrationLock2(paths) {
7889
+ const lockPath = legacyMigrationLockPath2(paths);
7890
+ ensurePrivateDir2(dirname5(lockPath));
7891
+ try {
7892
+ const fd = openSync4(lockPath, "wx", 384);
7893
+ writeFileSync3(fd, JSON.stringify({
7894
+ schemaVersion: "archcontext.legacy-local-store-migration-lock/v1",
7895
+ pid: process.pid,
7896
+ root: paths.repositoryRoot,
7897
+ targetLocalStorePath: paths.localStorePath,
7898
+ startedAt: nowIso2()
7899
+ }, null, 2), "utf8");
7900
+ fsyncSync3(fd);
7901
+ return { fd, path: lockPath };
7902
+ } catch (error) {
7903
+ const code = error.code;
7904
+ if (code === "EEXIST" && isStaleMigrationLock2(lockPath)) {
7905
+ rmSync5(lockPath, { force: true });
7906
+ return acquireLegacyMigrationLock2(paths);
7907
+ }
7908
+ if (code === "EEXIST")
7909
+ throw new Error(`Legacy SQLite migration already in progress; lock=${lockPath}`);
7910
+ throw error;
7911
+ }
7912
+ }
7913
+ function releaseLegacyMigrationLock2(lock) {
7914
+ closeSync4(lock.fd);
7915
+ rmSync5(lock.path, { force: true });
7916
+ }
7917
+ function isStaleMigrationLock2(lockPath) {
7918
+ try {
7919
+ const parsed = JSON.parse(readFileSync6(lockPath, "utf8"));
7920
+ if (typeof parsed.pid !== "number" || parsed.pid <= 0)
7921
+ return true;
7922
+ return !isProcessAlive2(parsed.pid);
7923
+ } catch {
7924
+ return true;
7925
+ }
7926
+ }
7927
+ function isProcessAlive2(pid) {
7928
+ try {
7929
+ process.kill(pid, 0);
7930
+ return true;
7931
+ } catch (error) {
7932
+ return error.code !== "ESRCH";
7933
+ }
7934
+ }
7935
+ function quarantineExistingLocalStore2(paths) {
7936
+ const quarantineDir = join5(paths.workspaceStateDir, "quarantine", `runtime.sqlite-${Date.now()}-${randomUUID2()}`);
7937
+ ensurePrivateDir2(quarantineDir);
7938
+ const quarantinedFiles = [];
7939
+ for (const suffix of SQLITE_SIDECAR_SUFFIXES2) {
7940
+ const source = `${paths.localStorePath}${suffix}`;
7941
+ if (!existsSync6(source))
7942
+ continue;
7943
+ const target = join5(quarantineDir, `runtime.sqlite${suffix}`);
7944
+ renameSync3(source, target);
7945
+ quarantinedFiles.push(target);
7946
+ }
7947
+ const markerPath = legacyMigrationMarkerPath2(paths);
7948
+ if (existsSync6(markerPath)) {
7949
+ const target = join5(quarantineDir, LEGACY_MIGRATION_MARKER_FILE2);
7950
+ renameSync3(markerPath, target);
7951
+ quarantinedFiles.push(target);
7952
+ }
7953
+ fsyncDirectory3(quarantineDir);
7954
+ fsyncDirectory3(dirname5(paths.localStorePath));
7955
+ return quarantinedFiles;
7956
+ }
7957
+ function legacyMigrationMarkerPath2(paths) {
7958
+ return join5(paths.workspaceStateDir, LEGACY_MIGRATION_MARKER_FILE2);
7959
+ }
7960
+ function legacyMigrationLockPath2(paths) {
7961
+ return join5(paths.workspaceStateDir, LEGACY_MIGRATION_LOCK_FILE2);
7962
+ }
7963
+ function writePrivateJson2(path, value) {
7964
+ ensurePrivateDir2(dirname5(path));
7965
+ const fd = openSync4(path, "w", 384);
7966
+ try {
7967
+ writeFileSync3(fd, JSON.stringify(value, null, 2), "utf8");
7968
+ fsyncSync3(fd);
7969
+ } finally {
7970
+ closeSync4(fd);
7971
+ }
7972
+ makePrivateFile2(path);
7973
+ fsyncDirectory3(dirname5(path));
7974
+ }
7975
+ function ensurePrivateDir2(path) {
7976
+ mkdirSync5(path, { recursive: true, mode: 448 });
7977
+ if (process.platform !== "win32") {
7978
+ try {
7979
+ chmodSync2(path, 448);
7980
+ } catch {}
7981
+ }
7982
+ }
7983
+ function makePrivateFile2(path) {
7984
+ if (process.platform !== "win32") {
7985
+ try {
7986
+ chmodSync2(path, 384);
7987
+ } catch {}
7988
+ }
7989
+ }
7990
+ function readGitPath2(root, args) {
7991
+ try {
7992
+ const value = execFileSync5("git", args, {
7993
+ cwd: root,
7994
+ encoding: "utf8",
7995
+ stdio: ["ignore", "pipe", "ignore"]
7996
+ }).trim();
7997
+ return value.length > 0 ? value : undefined;
7998
+ } catch {
7999
+ return;
8000
+ }
8001
+ }
8002
+ function resolveMaybeRelative2(base, path) {
8003
+ return isAbsolute4(path) ? resolve9(path) : resolve9(base, path);
8004
+ }
8005
+ function canonicalPath2(path) {
8006
+ const resolved = resolve9(path);
8007
+ try {
8008
+ return realpathSync5.native(resolved);
8009
+ } catch {
8010
+ return resolved;
8011
+ }
8012
+ }
8013
+ function stableStorageId2(prefix, value) {
8014
+ return `${prefix}.${createHash6("sha256").update(value).digest("hex").slice(0, 16)}`;
8015
+ }
7112
8016
  function stableJson(value) {
7113
8017
  return JSON.stringify(value);
7114
8018
  }
7115
- function nowIso() {
8019
+ function nowIso2() {
7116
8020
  return new Date().toISOString();
7117
8021
  }
7118
8022
  function changeSetMetadata(draft) {
@@ -7137,36 +8041,36 @@ function recoverJournalFiles(root, files) {
7137
8041
  for (const file of [...files].reverse()) {
7138
8042
  const absolute = resolve9(root, file.path);
7139
8043
  if (file.tempPath)
7140
- rmSync4(file.tempPath, { recursive: true, force: true });
7141
- rmSync4(absolute, { recursive: true, force: true });
7142
- if (file.existed && file.backupPath && existsSync5(file.backupPath)) {
7143
- renameSync2(file.backupPath, absolute);
8044
+ rmSync5(file.tempPath, { recursive: true, force: true });
8045
+ rmSync5(absolute, { recursive: true, force: true });
8046
+ if (file.existed && file.backupPath && existsSync6(file.backupPath)) {
8047
+ renameSync3(file.backupPath, absolute);
7144
8048
  }
7145
- fsyncDirectory2(dirname5(absolute));
8049
+ fsyncDirectory3(dirname5(absolute));
7146
8050
  }
7147
8051
  }
7148
8052
  function cleanupCommittedJournalFiles(files) {
7149
8053
  for (const file of files) {
7150
8054
  if (file.tempPath)
7151
- rmSync4(file.tempPath, { recursive: true, force: true });
8055
+ rmSync5(file.tempPath, { recursive: true, force: true });
7152
8056
  if (file.backupPath)
7153
- rmSync4(file.backupPath, { recursive: true, force: true });
8057
+ rmSync5(file.backupPath, { recursive: true, force: true });
7154
8058
  }
7155
8059
  }
7156
- function fsyncDirectory2(path) {
8060
+ function fsyncDirectory3(path) {
7157
8061
  try {
7158
- const fd = openSync3(path, "r");
8062
+ const fd = openSync4(path, "r");
7159
8063
  try {
7160
- fsyncSync2(fd);
8064
+ fsyncSync3(fd);
7161
8065
  } finally {
7162
- closeSync3(fd);
8066
+ closeSync4(fd);
7163
8067
  }
7164
8068
  } catch (error) {
7165
- if (!isIgnorableDirectoryFsyncError2(error))
8069
+ if (!isIgnorableDirectoryFsyncError3(error))
7166
8070
  throw error;
7167
8071
  }
7168
8072
  }
7169
- function isIgnorableDirectoryFsyncError2(error) {
8073
+ function isIgnorableDirectoryFsyncError3(error) {
7170
8074
  const code = error.code;
7171
8075
  return code === "EINVAL" || code === "EISDIR" || process.platform === "win32" && code === "EPERM";
7172
8076
  }
@@ -7197,7 +8101,7 @@ async function readRelationFiles(root, relationsDir) {
7197
8101
 
7198
8102
  // packages/local-runtime/model-store-yaml/src/index.ts
7199
8103
  init_src();
7200
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync4, readFileSync as readFileSync5, rmSync as rmSync5, writeFileSync as writeFileSync2 } from "node:fs";
8104
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, readdirSync as readdirSync4, readFileSync as readFileSync7, rmSync as rmSync6, writeFileSync as writeFileSync4 } from "node:fs";
7201
8105
  import { dirname as dirname6, resolve as resolve10 } from "node:path";
7202
8106
  function createDefaultManifest(productId, productName) {
7203
8107
  return {
@@ -7251,7 +8155,7 @@ function initializeArchContextModel(root, productName = "ArchContext Project") {
7251
8155
  rebuildGeneratedProjection(root);
7252
8156
  }
7253
8157
  function rebuildGeneratedProjection(root) {
7254
- rmSync5(resolve10(root, ".archcontext/generated"), { recursive: true, force: true });
8158
+ rmSync6(resolve10(root, ".archcontext/generated"), { recursive: true, force: true });
7255
8159
  writeFile(root, ".archcontext/generated/ARCHITECTURE.md", [
7256
8160
  "<!-- Generated by ArchContext. Do not edit by hand. -->",
7257
8161
  "",
@@ -7265,7 +8169,7 @@ function rebuildGeneratedProjection(root) {
7265
8169
 
7266
8170
  class YamlModelStore {
7267
8171
  async loadManifest(workspace) {
7268
- return readFileSync5(resolve10(workspace.root, ".archcontext/manifest.yaml"), "utf8");
8172
+ return readFileSync7(resolve10(workspace.root, ".archcontext/manifest.yaml"), "utf8");
7269
8173
  }
7270
8174
  async loadModel(workspace) {
7271
8175
  return listModelFiles(workspace.root);
@@ -7274,7 +8178,7 @@ class YamlModelStore {
7274
8178
  const errors = [];
7275
8179
  for (const required of [".archcontext/manifest.yaml", ".archcontext/product.yaml"]) {
7276
8180
  try {
7277
- readFileSync5(resolve10(workspace.root, required), "utf8");
8181
+ readFileSync7(resolve10(workspace.root, required), "utf8");
7278
8182
  } catch {
7279
8183
  errors.push(`missing ${required}`);
7280
8184
  }
@@ -7301,7 +8205,7 @@ function listModelFiles(root) {
7301
8205
  ".archcontext/generated"
7302
8206
  ]);
7303
8207
  return paths.map((path) => {
7304
- const body = readFileSync5(resolve10(root, path), "utf8");
8208
+ const body = readFileSync7(resolve10(root, path), "utf8");
7305
8209
  return {
7306
8210
  path,
7307
8211
  body,
@@ -7314,7 +8218,7 @@ function collectArchContextFiles(root, entries) {
7314
8218
  const files = [];
7315
8219
  for (const entry of entries) {
7316
8220
  const absolute = resolve10(root, entry);
7317
- if (!existsSync6(absolute))
8221
+ if (!existsSync7(absolute))
7318
8222
  continue;
7319
8223
  const stat = readdirOrFile(absolute);
7320
8224
  if (stat === "file") {
@@ -7359,8 +8263,8 @@ function writeYaml(root, path, value) {
7359
8263
  }
7360
8264
  function writeFile(root, path, body) {
7361
8265
  const absolute = resolve10(root, path);
7362
- mkdirSync5(dirname6(absolute), { recursive: true });
7363
- writeFileSync2(absolute, body.endsWith(`
8266
+ mkdirSync6(dirname6(absolute), { recursive: true });
8267
+ writeFileSync4(absolute, body.endsWith(`
7364
8268
  `) ? body : `${body}
7365
8269
  `, "utf8");
7366
8270
  }
@@ -7568,9 +8472,9 @@ class ArchctxDaemon {
7568
8472
  tempRoot: input.tempRoot,
7569
8473
  stateDir: input.stateDir
7570
8474
  });
7571
- mkdirSync6(paths.stateDir, { recursive: true });
7572
- mkdirSync6(paths.runRoot, { recursive: true });
7573
- mkdirSync6(paths.worktreeTempRoot, { recursive: true });
8475
+ mkdirSync7(paths.stateDir, { recursive: true });
8476
+ mkdirSync7(paths.runRoot, { recursive: true });
8477
+ mkdirSync7(paths.worktreeTempRoot, { recursive: true });
7574
8478
  const preparing = {
7575
8479
  schemaVersion: "archcontext.developer-review-run/v1",
7576
8480
  runId: paths.runId,
@@ -7589,13 +8493,13 @@ class ArchctxDaemon {
7589
8493
  cleanup: "remove-run-root"
7590
8494
  }
7591
8495
  };
7592
- if (existsSync7(paths.lockPath) || existsSync7(paths.manifestPath)) {
7593
- rmSync6(paths.runRoot, { recursive: true, force: true });
8496
+ if (existsSync8(paths.lockPath) || existsSync8(paths.manifestPath)) {
8497
+ rmSync7(paths.runRoot, { recursive: true, force: true });
7594
8498
  throw new Error(`developer-review-run-already-active: ${input.challenge.challengeId}`);
7595
8499
  }
7596
8500
  let lockAcquired = false;
7597
8501
  try {
7598
- writePrivateJson(paths.lockPath, {
8502
+ writePrivateJson3(paths.lockPath, {
7599
8503
  schemaVersion: "archcontext.developer-review-run-lock/v1",
7600
8504
  runId: paths.runId,
7601
8505
  challengeId: input.challenge.challengeId,
@@ -7625,7 +8529,7 @@ class ArchctxDaemon {
7625
8529
  if (lockAcquired) {
7626
8530
  this.cleanupDeveloperReviewRun(preparing);
7627
8531
  } else {
7628
- rmSync6(paths.runRoot, { recursive: true, force: true });
8532
+ rmSync7(paths.runRoot, { recursive: true, force: true });
7629
8533
  }
7630
8534
  throw error;
7631
8535
  }
@@ -7646,7 +8550,7 @@ class ArchctxDaemon {
7646
8550
  const errors = [];
7647
8551
  if (run.worktree) {
7648
8552
  try {
7649
- const hadWorktree = existsSync7(run.worktree.worktreeRoot);
8553
+ const hadWorktree = existsSync8(run.worktree.worktreeRoot);
7650
8554
  removeDetachedReviewWorktree(run.worktree);
7651
8555
  if (hadWorktree)
7652
8556
  removed.push("worktree");
@@ -7660,8 +8564,8 @@ class ArchctxDaemon {
7660
8564
  ["lock", run.lockPath]
7661
8565
  ]) {
7662
8566
  try {
7663
- const existed = existsSync7(path);
7664
- rmSync6(path, { recursive: true, force: true });
8567
+ const existed = existsSync8(path);
8568
+ rmSync7(path, { recursive: true, force: true });
7665
8569
  if (existed)
7666
8570
  removed.push(kind);
7667
8571
  } catch (error) {
@@ -7689,7 +8593,7 @@ class ArchctxDaemon {
7689
8593
  removedLocks: [],
7690
8594
  skippedActive: []
7691
8595
  };
7692
- if (!existsSync7(stateDir))
8596
+ if (!existsSync8(stateDir))
7693
8597
  return recovery;
7694
8598
  for (const entry of readdirSync5(stateDir).sort()) {
7695
8599
  if (!entry.endsWith(".json"))
@@ -7697,7 +8601,7 @@ class ArchctxDaemon {
7697
8601
  const manifestPath = join6(stateDir, entry);
7698
8602
  const manifest = readDeveloperReviewRunManifest(manifestPath);
7699
8603
  if (!manifest) {
7700
- rmSync6(manifestPath, { force: true });
8604
+ rmSync7(manifestPath, { force: true });
7701
8605
  continue;
7702
8606
  }
7703
8607
  if (!input.force && isDeveloperReviewPidAlive(manifest.pid)) {
@@ -7717,7 +8621,7 @@ class ArchctxDaemon {
7717
8621
  recovery.skippedActive.push(runId);
7718
8622
  continue;
7719
8623
  }
7720
- rmSync6(lockPath, { force: true });
8624
+ rmSync7(lockPath, { force: true });
7721
8625
  recovery.removedLocks.push(lockPath);
7722
8626
  }
7723
8627
  return recovery;
@@ -8010,7 +8914,7 @@ class ArchctxDaemon {
8010
8914
  const status = this.status();
8011
8915
  if (!root)
8012
8916
  return okEnvelope("status", status);
8013
- const repositoryId = repositoryFingerprint(root);
8917
+ const repositoryId = repositoryFingerprint2(root);
8014
8918
  const session = this.sessions.get(repositoryId);
8015
8919
  return okEnvelope("status", {
8016
8920
  ...status,
@@ -8057,9 +8961,9 @@ class ArchctxDaemon {
8057
8961
  }
8058
8962
  async restoreRepositorySessions() {
8059
8963
  for (const record of await this.localStore.listRepositorySessions()) {
8060
- if (!record.root || !existsSync7(record.root))
8964
+ if (!record.root || !existsSync8(record.root))
8061
8965
  continue;
8062
- if (repositoryFingerprint(record.root) !== record.repositoryId)
8966
+ if (repositoryFingerprint2(record.root) !== record.repositoryId)
8063
8967
  continue;
8064
8968
  this.sessions.set(record.repositoryId, {
8065
8969
  workspace: {
@@ -8345,8 +9249,8 @@ class ArchctxRuntimeRpcServer {
8345
9249
  const root = this.options.root ?? process.cwd();
8346
9250
  const connectionPath = this.options.connectionPath ?? defaultDaemonConnectionPath(root);
8347
9251
  const lockPath = this.options.lockPath ?? defaultDaemonLockPath(root);
8348
- mkdirSync6(dirname7(connectionPath), { recursive: true });
8349
- mkdirSync6(dirname7(lockPath), { recursive: true });
9252
+ mkdirSync7(dirname7(connectionPath), { recursive: true });
9253
+ mkdirSync7(dirname7(lockPath), { recursive: true });
8350
9254
  this.lockFd = acquireDaemonLock(lockPath, root);
8351
9255
  const token = this.options.token ?? randomBytes(18).toString("base64url");
8352
9256
  const server = createServer((request, response) => {
@@ -8369,8 +9273,8 @@ class ArchctxRuntimeRpcServer {
8369
9273
  connectionPath,
8370
9274
  startedAt: (this.options.clock ?? (() => new Date().toISOString()))()
8371
9275
  };
8372
- writeFileSync3(connectionPath, JSON.stringify(this.connection, null, 2), { mode: 384 });
8373
- chmodSync(connectionPath, 384);
9276
+ writeFileSync5(connectionPath, JSON.stringify(this.connection, null, 2), { mode: 384 });
9277
+ chmodSync3(connectionPath, 384);
8374
9278
  return this.connection;
8375
9279
  }
8376
9280
  async stop() {
@@ -8385,12 +9289,12 @@ class ArchctxRuntimeRpcServer {
8385
9289
  }
8386
9290
  await this.daemon.stop();
8387
9291
  if (connection)
8388
- rmSync6(connection.connectionPath, { force: true });
9292
+ rmSync7(connection.connectionPath, { force: true });
8389
9293
  if (this.lockFd !== undefined)
8390
- closeSync4(this.lockFd);
9294
+ closeSync5(this.lockFd);
8391
9295
  this.lockFd = undefined;
8392
9296
  if (connection)
8393
- rmSync6(connection.lockPath, { force: true });
9297
+ rmSync7(connection.lockPath, { force: true });
8394
9298
  this.options.onStop?.();
8395
9299
  }
8396
9300
  async handleRequest(request, response) {
@@ -8513,24 +9417,21 @@ class ArchctxRuntimeRpcServer {
8513
9417
  }
8514
9418
  }
8515
9419
  }
8516
- function defaultDaemonControlDir(root = process.cwd()) {
8517
- return join6(root, ".archcontext", ".local");
8518
- }
8519
9420
  function defaultDeveloperReviewRunStateDir(root = process.cwd()) {
8520
- return join6(defaultDaemonControlDir(root), "developer-review-runs");
9421
+ return runtimeStatePaths2(root).developerReviewRunStateDir;
8521
9422
  }
8522
9423
  function defaultDaemonConnectionPath(root = process.cwd()) {
8523
- return join6(defaultDaemonControlDir(root), "archctxd.json");
9424
+ return runtimeStatePaths2(root).daemonConnectionPath;
8524
9425
  }
8525
9426
  function defaultDaemonLockPath(root = process.cwd()) {
8526
- return join6(defaultDaemonControlDir(root), "archctxd.lock");
9427
+ return runtimeStatePaths2(root).daemonLockPath;
8527
9428
  }
8528
9429
  function readRuntimeRpcConnectionFile(root = process.cwd()) {
8529
9430
  const path = defaultDaemonConnectionPath(root);
8530
9431
  try {
8531
9432
  if (!isPrivateControlFile(path))
8532
9433
  return;
8533
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
9434
+ const parsed = JSON.parse(readFileSync8(path, "utf8"));
8534
9435
  if (!parsed || typeof parsed !== "object")
8535
9436
  return;
8536
9437
  return {
@@ -8562,7 +9463,7 @@ function runtimeRpcCompatibilityIssue(root = process.cwd()) {
8562
9463
  connectionPath: connection.connectionPath ?? defaultDaemonConnectionPath(root),
8563
9464
  lockPath: connection.lockPath ?? defaultDaemonLockPath(root),
8564
9465
  pid,
8565
- pidAlive: pid !== undefined ? isProcessAlive(pid) : false,
9466
+ pidAlive: pid !== undefined ? isProcessAlive3(pid) : false,
8566
9467
  upgradeCommand: "archctx daemon upgrade"
8567
9468
  };
8568
9469
  }
@@ -8571,7 +9472,7 @@ function readRuntimeRpcConnection(root = process.cwd()) {
8571
9472
  try {
8572
9473
  if (!isPrivateControlFile(path))
8573
9474
  return;
8574
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
9475
+ const parsed = JSON.parse(readFileSync8(path, "utf8"));
8575
9476
  return isValidRuntimeRpcConnection(parsed) ? parsed : undefined;
8576
9477
  } catch {
8577
9478
  return;
@@ -8587,11 +9488,11 @@ function recoverStaleDaemonControlFiles(root = process.cwd(), options = {}) {
8587
9488
  const removed = [];
8588
9489
  const connectionReason = staleConnectionFileReason(connectionPath, options.removeUnhealthyConnection ?? false);
8589
9490
  if (connectionReason) {
8590
- rmSync6(connectionPath, { force: true });
9491
+ rmSync7(connectionPath, { force: true });
8591
9492
  removed.push(connectionReason);
8592
9493
  }
8593
- if (existsSync7(lockPath) && isStaleLock(lockPath)) {
8594
- rmSync6(lockPath, { force: true });
9494
+ if (existsSync8(lockPath) && isStaleLock(lockPath)) {
9495
+ rmSync7(lockPath, { force: true });
8595
9496
  removed.push("stale-lock-file");
8596
9497
  }
8597
9498
  return { connectionPath, lockPath, removed };
@@ -8687,7 +9588,7 @@ function createDeveloperReviewRunPaths(input) {
8687
9588
  const runId = `${safeChallengeId}-${randomBytes(6).toString("hex")}`;
8688
9589
  const stateDir = input.stateDir ? resolve11(input.stateDir) : defaultDeveloperReviewRunStateDir(input.sourceRoot);
8689
9590
  const tempParent = input.tempRoot ? resolve11(input.tempRoot) : tmpdir2();
8690
- mkdirSync6(tempParent, { recursive: true });
9591
+ mkdirSync7(tempParent, { recursive: true });
8691
9592
  const runRoot = mkdtempSync3(join6(tempParent, `archctx-developer-review-${safeChallengeId.slice(0, 32)}-`));
8692
9593
  return {
8693
9594
  runId,
@@ -8703,12 +9604,12 @@ function safeControlFileSegment(value) {
8703
9604
  return sanitized.length > 0 ? sanitized : "developer-review";
8704
9605
  }
8705
9606
  function writeDeveloperReviewRunManifest(manifest) {
8706
- writePrivateJson(manifest.manifestPath, manifest);
9607
+ writePrivateJson3(manifest.manifestPath, manifest);
8707
9608
  }
8708
- function writePrivateJson(path, value, flag = "w") {
8709
- mkdirSync6(dirname7(path), { recursive: true });
8710
- writeFileSync3(path, JSON.stringify(value, null, 2), { mode: 384, flag });
8711
- chmodSync(path, 384);
9609
+ function writePrivateJson3(path, value, flag = "w") {
9610
+ mkdirSync7(dirname7(path), { recursive: true });
9611
+ writeFileSync5(path, JSON.stringify(value, null, 2), { mode: 384, flag });
9612
+ chmodSync3(path, 384);
8712
9613
  }
8713
9614
  function readDeveloperReviewRunManifest(path) {
8714
9615
  const parsed = readJsonObject(path);
@@ -8730,7 +9631,7 @@ function readDeveloperReviewRunManifest(path) {
8730
9631
  }
8731
9632
  function readJsonObject(path) {
8732
9633
  try {
8733
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
9634
+ const parsed = JSON.parse(readFileSync8(path, "utf8"));
8734
9635
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
8735
9636
  } catch {
8736
9637
  return;
@@ -8739,7 +9640,7 @@ function readJsonObject(path) {
8739
9640
  function isDeveloperReviewPidAlive(pid) {
8740
9641
  if (!pid || pid <= 0)
8741
9642
  return false;
8742
- return isProcessAlive(pid);
9643
+ return isProcessAlive3(pid);
8743
9644
  }
8744
9645
  function cleanupErrorMessage(kind, error) {
8745
9646
  return `${kind}: ${error instanceof Error ? error.message : String(error)}`;
@@ -8750,6 +9651,8 @@ async function createStartedDaemon(deps = {}) {
8750
9651
  return daemon;
8751
9652
  }
8752
9653
  function createProductionDaemon(options = {}) {
9654
+ if (!options.localStorePath)
9655
+ migrateLegacyLocalStoreIfNeeded2(options.root);
8753
9656
  const deps = {
8754
9657
  localStorePath: options.localStorePath ?? defaultLocalStorePath2(options.root),
8755
9658
  maxRepoSessions: options.maxRepoSessions
@@ -8796,15 +9699,15 @@ function blockedProductionInjections(deps) {
8796
9699
  }
8797
9700
  function acquireDaemonLock(lockPath, root) {
8798
9701
  try {
8799
- const fd = openSync4(lockPath, "wx", 384);
8800
- writeFileSync3(fd, JSON.stringify({ pid: process.pid, root, startedAt: new Date().toISOString() }, null, 2), "utf8");
9702
+ const fd = openSync5(lockPath, "wx", 384);
9703
+ writeFileSync5(fd, JSON.stringify({ pid: process.pid, root, startedAt: new Date().toISOString() }, null, 2), "utf8");
8801
9704
  return fd;
8802
9705
  } catch (error) {
8803
9706
  const code = error.code;
8804
9707
  if (code !== "EEXIST")
8805
9708
  throw error;
8806
9709
  if (isStaleLock(lockPath)) {
8807
- rmSync6(lockPath, { force: true });
9710
+ rmSync7(lockPath, { force: true });
8808
9711
  return acquireDaemonLock(lockPath, root);
8809
9712
  }
8810
9713
  throw new Error(`archctxd already running for ${root}; lock=${lockPath}`);
@@ -8814,15 +9717,15 @@ function isValidRuntimeRpcConnection(value) {
8814
9717
  return value.schemaVersion === RUNTIME_RPC_VERSION && value.protocol === "http-loopback" && value.version === 1 && typeof value.url === "string" && value.url.startsWith("http://127.0.0.1:") && typeof value.token === "string" && value.token.length > 0 && typeof value.pid === "number" && typeof value.connectionPath === "string" && typeof value.lockPath === "string";
8815
9718
  }
8816
9719
  function staleConnectionFileReason(path, removeUnhealthyConnection) {
8817
- if (!existsSync7(path))
9720
+ if (!existsSync8(path))
8818
9721
  return;
8819
9722
  try {
8820
9723
  if (!isPrivateControlFile(path))
8821
9724
  return "insecure-connection-file";
8822
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
9725
+ const parsed = JSON.parse(readFileSync8(path, "utf8"));
8823
9726
  if (!isValidRuntimeRpcConnection(parsed))
8824
9727
  return "invalid-connection-file";
8825
- if (!isProcessAlive(parsed.pid))
9728
+ if (!isProcessAlive3(parsed.pid))
8826
9729
  return "dead-connection-pid";
8827
9730
  return removeUnhealthyConnection ? "unhealthy-connection-file" : undefined;
8828
9731
  } catch {
@@ -8837,15 +9740,15 @@ function isPrivateControlFile(path) {
8837
9740
  }
8838
9741
  function isStaleLock(lockPath) {
8839
9742
  try {
8840
- const lock = JSON.parse(readFileSync6(lockPath, "utf8"));
9743
+ const lock = JSON.parse(readFileSync8(lockPath, "utf8"));
8841
9744
  if (typeof lock.pid !== "number" || lock.pid <= 0)
8842
9745
  return true;
8843
- return !isProcessAlive(lock.pid);
9746
+ return !isProcessAlive3(lock.pid);
8844
9747
  } catch {
8845
9748
  return true;
8846
9749
  }
8847
9750
  }
8848
- function isProcessAlive(pid) {
9751
+ function isProcessAlive3(pid) {
8849
9752
  try {
8850
9753
  process.kill(pid, 0);
8851
9754
  return true;
@@ -9031,7 +9934,7 @@ init_src();
9031
9934
 
9032
9935
  // packages/local-runtime/runtime-daemon/src/index.ts
9033
9936
  import { randomBytes as randomBytes2 } from "node:crypto";
9034
- import { chmodSync as chmodSync2, closeSync as closeSync5, existsSync as existsSync8, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync4, openSync as openSync5, readdirSync as readdirSync6, readFileSync as readFileSync7, rmSync as rmSync7, statSync as statSync5, writeFileSync as writeFileSync4 } from "node:fs";
9937
+ import { chmodSync as chmodSync4, closeSync as closeSync6, existsSync as existsSync9, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync4, openSync as openSync6, readdirSync as readdirSync6, readFileSync as readFileSync9, rmSync as rmSync8, statSync as statSync5, writeFileSync as writeFileSync6 } from "node:fs";
9035
9938
  import { createServer as createServer2 } from "node:http";
9036
9939
  import { tmpdir as tmpdir3 } from "node:os";
9037
9940
  import { dirname as dirname8, join as join7, resolve as resolve12 } from "node:path";
@@ -9238,9 +10141,9 @@ class ArchctxDaemon2 {
9238
10141
  tempRoot: input.tempRoot,
9239
10142
  stateDir: input.stateDir
9240
10143
  });
9241
- mkdirSync7(paths.stateDir, { recursive: true });
9242
- mkdirSync7(paths.runRoot, { recursive: true });
9243
- mkdirSync7(paths.worktreeTempRoot, { recursive: true });
10144
+ mkdirSync8(paths.stateDir, { recursive: true });
10145
+ mkdirSync8(paths.runRoot, { recursive: true });
10146
+ mkdirSync8(paths.worktreeTempRoot, { recursive: true });
9244
10147
  const preparing = {
9245
10148
  schemaVersion: "archcontext.developer-review-run/v1",
9246
10149
  runId: paths.runId,
@@ -9259,13 +10162,13 @@ class ArchctxDaemon2 {
9259
10162
  cleanup: "remove-run-root"
9260
10163
  }
9261
10164
  };
9262
- if (existsSync8(paths.lockPath) || existsSync8(paths.manifestPath)) {
9263
- rmSync7(paths.runRoot, { recursive: true, force: true });
10165
+ if (existsSync9(paths.lockPath) || existsSync9(paths.manifestPath)) {
10166
+ rmSync8(paths.runRoot, { recursive: true, force: true });
9264
10167
  throw new Error(`developer-review-run-already-active: ${input.challenge.challengeId}`);
9265
10168
  }
9266
10169
  let lockAcquired = false;
9267
10170
  try {
9268
- writePrivateJson2(paths.lockPath, {
10171
+ writePrivateJson4(paths.lockPath, {
9269
10172
  schemaVersion: "archcontext.developer-review-run-lock/v1",
9270
10173
  runId: paths.runId,
9271
10174
  challengeId: input.challenge.challengeId,
@@ -9295,7 +10198,7 @@ class ArchctxDaemon2 {
9295
10198
  if (lockAcquired) {
9296
10199
  this.cleanupDeveloperReviewRun(preparing);
9297
10200
  } else {
9298
- rmSync7(paths.runRoot, { recursive: true, force: true });
10201
+ rmSync8(paths.runRoot, { recursive: true, force: true });
9299
10202
  }
9300
10203
  throw error;
9301
10204
  }
@@ -9316,7 +10219,7 @@ class ArchctxDaemon2 {
9316
10219
  const errors = [];
9317
10220
  if (run.worktree) {
9318
10221
  try {
9319
- const hadWorktree = existsSync8(run.worktree.worktreeRoot);
10222
+ const hadWorktree = existsSync9(run.worktree.worktreeRoot);
9320
10223
  removeDetachedReviewWorktree(run.worktree);
9321
10224
  if (hadWorktree)
9322
10225
  removed.push("worktree");
@@ -9330,8 +10233,8 @@ class ArchctxDaemon2 {
9330
10233
  ["lock", run.lockPath]
9331
10234
  ]) {
9332
10235
  try {
9333
- const existed = existsSync8(path);
9334
- rmSync7(path, { recursive: true, force: true });
10236
+ const existed = existsSync9(path);
10237
+ rmSync8(path, { recursive: true, force: true });
9335
10238
  if (existed)
9336
10239
  removed.push(kind);
9337
10240
  } catch (error) {
@@ -9359,7 +10262,7 @@ class ArchctxDaemon2 {
9359
10262
  removedLocks: [],
9360
10263
  skippedActive: []
9361
10264
  };
9362
- if (!existsSync8(stateDir))
10265
+ if (!existsSync9(stateDir))
9363
10266
  return recovery;
9364
10267
  for (const entry of readdirSync6(stateDir).sort()) {
9365
10268
  if (!entry.endsWith(".json"))
@@ -9367,7 +10270,7 @@ class ArchctxDaemon2 {
9367
10270
  const manifestPath = join7(stateDir, entry);
9368
10271
  const manifest = readDeveloperReviewRunManifest2(manifestPath);
9369
10272
  if (!manifest) {
9370
- rmSync7(manifestPath, { force: true });
10273
+ rmSync8(manifestPath, { force: true });
9371
10274
  continue;
9372
10275
  }
9373
10276
  if (!input.force && isDeveloperReviewPidAlive2(manifest.pid)) {
@@ -9387,7 +10290,7 @@ class ArchctxDaemon2 {
9387
10290
  recovery.skippedActive.push(runId);
9388
10291
  continue;
9389
10292
  }
9390
- rmSync7(lockPath, { force: true });
10293
+ rmSync8(lockPath, { force: true });
9391
10294
  recovery.removedLocks.push(lockPath);
9392
10295
  }
9393
10296
  return recovery;
@@ -9680,7 +10583,7 @@ class ArchctxDaemon2 {
9680
10583
  const status = this.status();
9681
10584
  if (!root)
9682
10585
  return okEnvelope("status", status);
9683
- const repositoryId = repositoryFingerprint(root);
10586
+ const repositoryId = repositoryFingerprint2(root);
9684
10587
  const session = this.sessions.get(repositoryId);
9685
10588
  return okEnvelope("status", {
9686
10589
  ...status,
@@ -9727,9 +10630,9 @@ class ArchctxDaemon2 {
9727
10630
  }
9728
10631
  async restoreRepositorySessions() {
9729
10632
  for (const record of await this.localStore.listRepositorySessions()) {
9730
- if (!record.root || !existsSync8(record.root))
10633
+ if (!record.root || !existsSync9(record.root))
9731
10634
  continue;
9732
- if (repositoryFingerprint(record.root) !== record.repositoryId)
10635
+ if (repositoryFingerprint2(record.root) !== record.repositoryId)
9733
10636
  continue;
9734
10637
  this.sessions.set(record.repositoryId, {
9735
10638
  workspace: {
@@ -9996,14 +10899,11 @@ class RuntimeRpcClient2 {
9996
10899
  return await response.json();
9997
10900
  }
9998
10901
  }
9999
- function defaultDaemonControlDir2(root = process.cwd()) {
10000
- return join7(root, ".archcontext", ".local");
10001
- }
10002
10902
  function defaultDeveloperReviewRunStateDir2(root = process.cwd()) {
10003
- return join7(defaultDaemonControlDir2(root), "developer-review-runs");
10903
+ return runtimeStatePaths2(root).developerReviewRunStateDir;
10004
10904
  }
10005
10905
  function defaultDaemonConnectionPath2(root = process.cwd()) {
10006
- return join7(defaultDaemonControlDir2(root), "archctxd.json");
10906
+ return runtimeStatePaths2(root).daemonConnectionPath;
10007
10907
  }
10008
10908
  function unwrapRpcData2(result) {
10009
10909
  if (!result.ok)
@@ -10015,7 +10915,7 @@ function readRuntimeRpcConnection2(root = process.cwd()) {
10015
10915
  try {
10016
10916
  if (!isPrivateControlFile2(path))
10017
10917
  return;
10018
- const parsed = JSON.parse(readFileSync7(path, "utf8"));
10918
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
10019
10919
  return isValidRuntimeRpcConnection2(parsed) ? parsed : undefined;
10020
10920
  } catch {
10021
10921
  return;
@@ -10116,7 +11016,7 @@ function createDeveloperReviewRunPaths2(input) {
10116
11016
  const runId = `${safeChallengeId}-${randomBytes2(6).toString("hex")}`;
10117
11017
  const stateDir = input.stateDir ? resolve12(input.stateDir) : defaultDeveloperReviewRunStateDir2(input.sourceRoot);
10118
11018
  const tempParent = input.tempRoot ? resolve12(input.tempRoot) : tmpdir3();
10119
- mkdirSync7(tempParent, { recursive: true });
11019
+ mkdirSync8(tempParent, { recursive: true });
10120
11020
  const runRoot = mkdtempSync4(join7(tempParent, `archctx-developer-review-${safeChallengeId.slice(0, 32)}-`));
10121
11021
  return {
10122
11022
  runId,
@@ -10132,12 +11032,12 @@ function safeControlFileSegment2(value) {
10132
11032
  return sanitized.length > 0 ? sanitized : "developer-review";
10133
11033
  }
10134
11034
  function writeDeveloperReviewRunManifest2(manifest) {
10135
- writePrivateJson2(manifest.manifestPath, manifest);
11035
+ writePrivateJson4(manifest.manifestPath, manifest);
10136
11036
  }
10137
- function writePrivateJson2(path, value, flag = "w") {
10138
- mkdirSync7(dirname8(path), { recursive: true });
10139
- writeFileSync4(path, JSON.stringify(value, null, 2), { mode: 384, flag });
10140
- chmodSync2(path, 384);
11037
+ function writePrivateJson4(path, value, flag = "w") {
11038
+ mkdirSync8(dirname8(path), { recursive: true });
11039
+ writeFileSync6(path, JSON.stringify(value, null, 2), { mode: 384, flag });
11040
+ chmodSync4(path, 384);
10141
11041
  }
10142
11042
  function readDeveloperReviewRunManifest2(path) {
10143
11043
  const parsed = readJsonObject2(path);
@@ -10159,7 +11059,7 @@ function readDeveloperReviewRunManifest2(path) {
10159
11059
  }
10160
11060
  function readJsonObject2(path) {
10161
11061
  try {
10162
- const parsed = JSON.parse(readFileSync7(path, "utf8"));
11062
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
10163
11063
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
10164
11064
  } catch {
10165
11065
  return;
@@ -10168,7 +11068,7 @@ function readJsonObject2(path) {
10168
11068
  function isDeveloperReviewPidAlive2(pid) {
10169
11069
  if (!pid || pid <= 0)
10170
11070
  return false;
10171
- return isProcessAlive2(pid);
11071
+ return isProcessAlive4(pid);
10172
11072
  }
10173
11073
  function cleanupErrorMessage2(kind, error) {
10174
11074
  return `${kind}: ${error instanceof Error ? error.message : String(error)}`;
@@ -10214,7 +11114,7 @@ function isPrivateControlFile2(path) {
10214
11114
  const mode = statSync5(path).mode & 511;
10215
11115
  return (mode & 63) === 0;
10216
11116
  }
10217
- function isProcessAlive2(pid) {
11117
+ function isProcessAlive4(pid) {
10218
11118
  try {
10219
11119
  process.kill(pid, 0);
10220
11120
  return true;
@@ -10401,7 +11301,7 @@ async function runStdioMcpLoop(input, output, log = (line) => process.stderr.wri
10401
11301
 
10402
11302
  // packages/surfaces/renderer/src/index.ts
10403
11303
  init_src();
10404
- import { existsSync as existsSync9, readdirSync as readdirSync7, readFileSync as readFileSync8 } from "node:fs";
11304
+ import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "node:fs";
10405
11305
  import { resolve as resolve13 } from "node:path";
10406
11306
  function normalizeNativeModel2(model) {
10407
11307
  return {
@@ -10437,9 +11337,9 @@ function mermaidId(id) {
10437
11337
  return stableId(id).replace(/-/g, "_").replace(/\./g, "_");
10438
11338
  }
10439
11339
  function readYamlObjects(dir) {
10440
- if (!existsSync9(dir))
11340
+ if (!existsSync10(dir))
10441
11341
  return [];
10442
- return readdirSync7(dir).filter((file) => /\.ya?ml$/.test(file)).sort().map((file) => parseFlatYaml(readFileSync8(resolve13(dir, file), "utf8")));
11342
+ return readdirSync7(dir).filter((file) => /\.ya?ml$/.test(file)).sort().map((file) => parseFlatYaml(readFileSync10(resolve13(dir, file), "utf8")));
10443
11343
  }
10444
11344
  function parseFlatYaml(body) {
10445
11345
  const out = {};
@@ -10464,7 +11364,7 @@ function escapeMermaid(value) {
10464
11364
  // packages/surfaces/cli/src/main.ts
10465
11365
  var [, , command, ...args] = process.argv;
10466
11366
  var CLI_ENTRY = fileURLToPath(import.meta.url);
10467
- var DAEMON_START_TIMEOUT_MS = 5000;
11367
+ var DAEMON_START_TIMEOUT_MS = 15000;
10468
11368
 
10469
11369
  class RuntimeVersionUnsupportedError extends Error {
10470
11370
  issue;
@@ -10679,6 +11579,8 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
10679
11579
  };
10680
11580
  case "doctor":
10681
11581
  return { schemaVersion: "archcontext.envelope/v1", ok: true, requestId: "doctor", data: await doctorReport(cwd) };
11582
+ case "paths":
11583
+ return { schemaVersion: "archcontext.envelope/v1", ok: true, requestId: "paths", data: runtimePathsReport(cwd) };
10682
11584
  case "privacy-audit":
10683
11585
  return {
10684
11586
  schemaVersion: "archcontext.envelope/v1",
@@ -10724,8 +11626,8 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
10724
11626
  ok: true,
10725
11627
  requestId: "help",
10726
11628
  data: {
10727
- commands: ["init", "sync", "validate", "context", "status", "daemon", "repo", "landscape", "explore", "prepare", "checkpoint", "plan", "apply", "review", "complete", "github", "config", "mcp", "install", "uninstall", "doctor", "privacy-audit", "export", "import", "tunnel"],
10728
- examples: ["archctx init --name MyApp", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx tunnel"]
11629
+ commands: ["init", "sync", "validate", "context", "status", "daemon", "repo", "landscape", "explore", "prepare", "checkpoint", "plan", "apply", "review", "complete", "github", "config", "mcp", "install", "uninstall", "doctor", "paths", "privacy-audit", "export", "import", "tunnel"],
11630
+ examples: ["archctx init --name MyApp", "archctx paths", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx tunnel"]
10729
11631
  }
10730
11632
  };
10731
11633
  }
@@ -10811,7 +11713,7 @@ async function runGithubCommand(args2, cwd, deps) {
10811
11713
  tokenStore.clear(record.codeVerifierRef);
10812
11714
  tokenStore.clear(record.refreshTokenRef);
10813
11715
  keyStore.removeDevicePrivateKey(record.deviceKey.keyRef);
10814
- rmSync8(connectionPath, { force: true });
11716
+ rmSync9(connectionPath, { force: true });
10815
11717
  return okEnvelope("github.disconnect", {
10816
11718
  disconnected: true,
10817
11719
  connected: false,
@@ -11094,20 +11996,20 @@ function defaultGithubDeveloperReviewStatePath(cwd, pullRequestNumber) {
11094
11996
  }
11095
11997
  async function writeGithubDeveloperReviewState(cwd, state) {
11096
11998
  const path = defaultGithubDeveloperReviewStatePath(cwd, state.challenge.pullRequestNumber);
11097
- mkdirSync8(dirname9(path), { recursive: true });
11999
+ mkdirSync9(dirname9(path), { recursive: true });
11098
12000
  const serialized = `${JSON.stringify(state, null, 2)}
11099
12001
  `;
11100
12002
  assertNoCliSecretMaterial(serialized);
11101
- writeFileSync5(path, serialized, { mode: 384 });
12003
+ writeFileSync7(path, serialized, { mode: 384 });
11102
12004
  if (process.platform !== "win32")
11103
- chmodSync3(path, 384);
12005
+ chmodSync5(path, 384);
11104
12006
  return { state, path };
11105
12007
  }
11106
12008
  function readGithubDeveloperReviewState(path) {
11107
- if (!existsSync10(path))
12009
+ if (!existsSync11(path))
11108
12010
  return;
11109
12011
  try {
11110
- const parsed = JSON.parse(readFileSync9(path, "utf8"));
12012
+ const parsed = JSON.parse(readFileSync11(path, "utf8"));
11111
12013
  if (parsed.schemaVersion !== "archcontext.github-developer-review-state/v1")
11112
12014
  return;
11113
12015
  if (!parsed.challenge || typeof parsed.challenge.pullRequestNumber !== "number")
@@ -11156,10 +12058,10 @@ function defaultGithubConnectionPath(cwd) {
11156
12058
  return join8(dirname9(defaultDaemonConnectionPath(cwd)), "github-connection.json");
11157
12059
  }
11158
12060
  function readGithubConnection(path) {
11159
- if (!existsSync10(path))
12061
+ if (!existsSync11(path))
11160
12062
  return;
11161
12063
  try {
11162
- const parsed = JSON.parse(readFileSync9(path, "utf8"));
12064
+ const parsed = JSON.parse(readFileSync11(path, "utf8"));
11163
12065
  if (parsed.schemaVersion !== "archcontext.github-connection/v1" || parsed.status !== "connected")
11164
12066
  return;
11165
12067
  return parsed;
@@ -11168,13 +12070,13 @@ function readGithubConnection(path) {
11168
12070
  }
11169
12071
  }
11170
12072
  function writeGithubConnection(path, record) {
11171
- mkdirSync8(dirname9(path), { recursive: true });
12073
+ mkdirSync9(dirname9(path), { recursive: true });
11172
12074
  const serialized = `${JSON.stringify(record, null, 2)}
11173
12075
  `;
11174
12076
  assertNoCliSecretMaterial(serialized);
11175
- writeFileSync5(path, serialized, { mode: 384 });
12077
+ writeFileSync7(path, serialized, { mode: 384 });
11176
12078
  if (process.platform !== "win32")
11177
- chmodSync3(path, 384);
12079
+ chmodSync5(path, 384);
11178
12080
  }
11179
12081
  function sanitizeGithubConnection(record, connectionPath) {
11180
12082
  return {
@@ -11203,7 +12105,7 @@ async function readReviewChallengeV2Arg(args2, cwd, commandName = "github verify
11203
12105
  if (!inline && !challengePath)
11204
12106
  return { ok: false, message: `${commandName} requires --challenge-json or --challenge-path` };
11205
12107
  try {
11206
- const raw = inline ?? readFileSync9(resolve14(cwd, challengePath), "utf8");
12108
+ const raw = inline ?? readFileSync11(resolve14(cwd, challengePath), "utf8");
11207
12109
  const parsed = JSON.parse(raw);
11208
12110
  const attestation = await Promise.resolve().then(() => (init_src7(), exports_src3));
11209
12111
  const assertReviewChallengeV23 = attestation.assertReviewChallengeV2;
@@ -11286,6 +12188,7 @@ function agentHostRemoveConfig(host) {
11286
12188
  }
11287
12189
  async function doctorReport(cwd) {
11288
12190
  const product = productVersionManifest();
12191
+ const paths = runtimePathsReport(cwd);
11289
12192
  const daemon = await doctorDaemon(cwd);
11290
12193
  const git = doctorGit(cwd);
11291
12194
  const sqlite = doctorSqlite(cwd);
@@ -11303,6 +12206,7 @@ async function doctorReport(cwd) {
11303
12206
  },
11304
12207
  daemon,
11305
12208
  sqlite,
12209
+ paths,
11306
12210
  codeGraph: product.runtime.codeGraph,
11307
12211
  git,
11308
12212
  permissions,
@@ -11350,23 +12254,46 @@ function doctorGit(cwd) {
11350
12254
  }
11351
12255
  }
11352
12256
  function doctorSqlite(cwd) {
11353
- const path = defaultLocalStorePath(cwd);
12257
+ const paths = runtimeStatePaths(cwd);
12258
+ const path = paths.localStorePath;
12259
+ const legacyLocalStore = inspectLegacyLocalStoreMigration(cwd);
11354
12260
  return {
11355
12261
  path,
11356
- exists: existsSync10(path),
11357
- migrations: productVersionManifest().runtime.sqliteMigrations
12262
+ exists: existsSync11(path),
12263
+ migrations: productVersionManifest().runtime.sqliteMigrations,
12264
+ legacyPath: paths.legacyLocalStorePath,
12265
+ legacyExists: existsSync11(paths.legacyLocalStorePath),
12266
+ legacyLocalStore
11358
12267
  };
11359
12268
  }
11360
12269
  function doctorPermissions(cwd) {
12270
+ const paths = runtimeStatePaths(cwd);
11361
12271
  const controlDir = dirname9(defaultDaemonConnectionPath(cwd));
11362
12272
  return {
11363
12273
  workspace: pathAccess(cwd),
12274
+ stateRoot: pathAccess(paths.stateRoot),
12275
+ runtimeStateDir: pathAccess(paths.workspaceStateDir),
11364
12276
  controlDir: pathAccess(controlDir),
11365
12277
  sqlite: pathAccess(defaultLocalStorePath(cwd))
11366
12278
  };
11367
12279
  }
12280
+ function runtimePathsReport(cwd) {
12281
+ const paths = runtimeStatePaths(cwd);
12282
+ return {
12283
+ ...paths,
12284
+ legacyLocalStore: inspectLegacyLocalStoreMigration(cwd),
12285
+ runtimeRepositoryId: repositoryFingerprint(paths.repositoryRoot),
12286
+ repositoryTruthDir: join8(paths.repositoryRoot, ".archcontext"),
12287
+ codeGraphIndexDir: join8(paths.repositoryRoot, ".codegraph"),
12288
+ npmGlobalInstallState: "forbidden",
12289
+ overrides: {
12290
+ stateRootEnv: "ARCHCONTEXT_STATE_DIR",
12291
+ localStorePathEnv: "ARCHCONTEXT_LOCAL_STORE_PATH"
12292
+ }
12293
+ };
12294
+ }
11368
12295
  function pathAccess(path) {
11369
- const exists = existsSync10(path);
12296
+ const exists = existsSync11(path);
11370
12297
  return {
11371
12298
  path,
11372
12299
  exists,
@@ -11442,6 +12369,8 @@ async function createCliRuntime(cwd, deps) {
11442
12369
  githubReviewSubmissionPort: _githubReviewSubmissionPort,
11443
12370
  ...runtimeDeps
11444
12371
  } = deps;
12372
+ if (!runtimeDeps.localStorePath)
12373
+ migrateLegacyLocalStoreIfNeeded(cwd);
11445
12374
  const daemon = await createStartedDaemon({
11446
12375
  localStorePath: defaultLocalStorePath(cwd),
11447
12376
  ...runtimeDeps,
@@ -11544,8 +12473,8 @@ async function startBackgroundDaemon(args2, cwd) {
11544
12473
  const connectionPath = defaultDaemonConnectionPath(cwd);
11545
12474
  const controlDir = dirname9(connectionPath);
11546
12475
  const logPath = join8(controlDir, "archctxd.log");
11547
- mkdirSync8(controlDir, { recursive: true });
11548
- const logFd = openSync6(logPath, "a", 384);
12476
+ mkdirSync9(controlDir, { recursive: true });
12477
+ const logFd = openSync7(logPath, "a", 384);
11549
12478
  try {
11550
12479
  const child = spawn(process.execPath, [
11551
12480
  CLI_ENTRY,
@@ -11563,7 +12492,7 @@ async function startBackgroundDaemon(args2, cwd) {
11563
12492
  child.unref();
11564
12493
  const ready = await waitForDaemonReady(cwd, Number(readFlag(args2, "--timeout-ms") ?? DAEMON_START_TIMEOUT_MS));
11565
12494
  if (!ready) {
11566
- return errorEnvelope("daemon.start", "AC_RUNTIME_UNAVAILABLE", `archctxd did not become ready; log=${logPath}`);
12495
+ return errorEnvelope("daemon.start", "AC_RUNTIME_UNAVAILABLE", `archctxd did not become ready; log=${logPath}; logTail=${readFileTail(logPath)}`);
11567
12496
  }
11568
12497
  return okEnvelope("daemon.start", {
11569
12498
  running: true,
@@ -11575,7 +12504,7 @@ async function startBackgroundDaemon(args2, cwd) {
11575
12504
  ...recoveryData(recovery)
11576
12505
  });
11577
12506
  } finally {
11578
- closeSync6(logFd);
12507
+ closeSync7(logFd);
11579
12508
  }
11580
12509
  }
11581
12510
  async function upgradeDaemon(args2, cwd) {
@@ -11712,8 +12641,16 @@ async function waitForDaemonReady(cwd, timeoutMs) {
11712
12641
  function sleep(ms) {
11713
12642
  return new Promise((resolve15) => setTimeout(resolve15, ms));
11714
12643
  }
12644
+ function readFileTail(path, maxBytes = 4096) {
12645
+ try {
12646
+ const content = readFileSync11(path, "utf8");
12647
+ return content.slice(Math.max(0, content.length - maxBytes)).replace(/\s+/g, " ").trim();
12648
+ } catch {
12649
+ return "<unavailable>";
12650
+ }
12651
+ }
11715
12652
  async function runForegroundDaemon(cwd, args2) {
11716
- const daemon = await createStartedProductionDaemon({ root: cwd, localStorePath: defaultLocalStorePath(cwd) });
12653
+ const daemon = await createStartedProductionDaemon({ root: cwd });
11717
12654
  let resolveStopped;
11718
12655
  const stopped = new Promise((resolve15) => {
11719
12656
  resolveStopped = resolve15;