archctx 0.1.4-beta.0 → 0.1.5

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "archcontext.practice-catalog-manifest/v1",
3
3
  "catalogVersion": "2026.06.0",
4
- "productVersion": "0.1.4-beta.0",
4
+ "productVersion": "0.1.5",
5
5
  "generatedAt": "1970-01-01T00:00:00.000Z",
6
6
  "entries": [
7
7
  {
@@ -389,5 +389,5 @@
389
389
  "structurizr.dsl",
390
390
  "twelve-factor"
391
391
  ],
392
- "catalogDigest": "sha256:19c4fdf4068eaf19f782d92373354cff071947134e76eb6927998d5a9a1146c3"
392
+ "catalogDigest": "sha256:6da748c8c6230d18597951e5ff2de7d483e90caed61435cbd80418a5339c0299"
393
393
  }
package/bin/archctx.mjs CHANGED
@@ -702,7 +702,7 @@ function productVersionManifest() {
702
702
  }
703
703
  };
704
704
  }
705
- var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.1.4-beta.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-25.al0-ledger";
705
+ var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.1.5", 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-25.al0-ledger";
706
706
  // packages/contracts/src/index.ts
707
707
  var init_src = __esm(() => {
708
708
  init_control_plane_routes();
@@ -9485,7 +9485,7 @@ function migrateLegacyLocalStoreIfNeeded(root = process.cwd(), env = process.env
9485
9485
  integrityCheck.target = "failed";
9486
9486
  integrityCheck.error = error instanceof Error ? error.message : String(error);
9487
9487
  if (!legacyExists) {
9488
- throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}`);
9488
+ return upgradeExistingLocalStoreTarget(paths, integrityCheck);
9489
9489
  }
9490
9490
  }
9491
9491
  }
@@ -9524,6 +9524,28 @@ function migrateLegacyLocalStoreIfNeeded(root = process.cwd(), env = process.env
9524
9524
  releaseLegacyMigrationLock(lock);
9525
9525
  }
9526
9526
  }
9527
+ function upgradeExistingLocalStoreTarget(paths, integrityCheck) {
9528
+ const lock = acquireLegacyMigrationLock(paths);
9529
+ try {
9530
+ assertUpgradeableLocalStoreTarget(paths.localStorePath);
9531
+ integrityCheck.target = assertSqliteIntegrity(paths.localStorePath);
9532
+ migrateSqliteDatabaseSync(paths.localStorePath);
9533
+ compactSqliteDatabase(paths.localStorePath);
9534
+ integrityCheck.target = assertCurrentLocalStore(paths.localStorePath);
9535
+ delete integrityCheck.error;
9536
+ const markerPath = writeLegacyMigrationMarker(paths, integrityCheck, []);
9537
+ return legacyMigrationResult(true, undefined, paths, [paths.localStorePath], {
9538
+ status: "target-upgraded",
9539
+ integrityCheck,
9540
+ markerPath,
9541
+ quarantinedFiles: []
9542
+ });
9543
+ } catch (error) {
9544
+ throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}; target upgrade failed: ${error instanceof Error ? error.message : String(error)}`);
9545
+ } finally {
9546
+ releaseLegacyMigrationLock(lock);
9547
+ }
9548
+ }
9527
9549
  function applyLocalSqliteMigrations(db) {
9528
9550
  for (const pragma of SQLITE_PRAGMAS)
9529
9551
  db.exec(pragma);
@@ -9640,6 +9662,21 @@ function assertCurrentLocalStoreSchema(db, path) {
9640
9662
  throw new Error(`SQLite local store schema incomplete for ${path}: missing migrations ${missingMigrations.join(", ")}`);
9641
9663
  }
9642
9664
  }
9665
+ function assertUpgradeableLocalStoreTarget(path) {
9666
+ const db = openSqliteDatabaseSync(path);
9667
+ try {
9668
+ const integrity = sqliteIntegrityCheckOpenDatabase(db, path);
9669
+ const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((row) => String(row.name)));
9670
+ const hasArchContextMarker = ["schema_migrations", "task_states", "repository_sessions", "snapshots"].some((table) => tables.has(table));
9671
+ if (!hasArchContextMarker) {
9672
+ throw new Error(`SQLite target is not an ArchContext local store candidate: ${path}`);
9673
+ }
9674
+ if (integrity !== "ok")
9675
+ throw new Error(`SQLite integrity_check failed for ${path}: ${integrity}`);
9676
+ } finally {
9677
+ db.close();
9678
+ }
9679
+ }
9643
9680
  function assertTrustedLegacyLocalStoreSource(paths) {
9644
9681
  const stat = lstatSync(paths.legacyLocalStorePath);
9645
9682
  if (stat.isSymbolicLink()) {
@@ -15961,7 +15998,7 @@ function migrateLegacyLocalStoreIfNeeded2(root = process.cwd(), env = process.en
15961
15998
  integrityCheck.target = "failed";
15962
15999
  integrityCheck.error = error instanceof Error ? error.message : String(error);
15963
16000
  if (!legacyExists) {
15964
- throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}`);
16001
+ return upgradeExistingLocalStoreTarget2(paths, integrityCheck);
15965
16002
  }
15966
16003
  }
15967
16004
  }
@@ -16000,6 +16037,28 @@ function migrateLegacyLocalStoreIfNeeded2(root = process.cwd(), env = process.en
16000
16037
  releaseLegacyMigrationLock2(lock);
16001
16038
  }
16002
16039
  }
16040
+ function upgradeExistingLocalStoreTarget2(paths, integrityCheck) {
16041
+ const lock = acquireLegacyMigrationLock2(paths);
16042
+ try {
16043
+ assertUpgradeableLocalStoreTarget2(paths.localStorePath);
16044
+ integrityCheck.target = assertSqliteIntegrity2(paths.localStorePath);
16045
+ migrateSqliteDatabaseSync2(paths.localStorePath);
16046
+ compactSqliteDatabase2(paths.localStorePath);
16047
+ integrityCheck.target = assertCurrentLocalStore2(paths.localStorePath);
16048
+ delete integrityCheck.error;
16049
+ const markerPath = writeLegacyMigrationMarker2(paths, integrityCheck, []);
16050
+ return legacyMigrationResult2(true, undefined, paths, [paths.localStorePath], {
16051
+ status: "target-upgraded",
16052
+ integrityCheck,
16053
+ markerPath,
16054
+ quarantinedFiles: []
16055
+ });
16056
+ } catch (error) {
16057
+ throw new Error(`ArchContext runtime state target is not a valid SQLite database and no legacy store is available: ${paths.localStorePath}; target upgrade failed: ${error instanceof Error ? error.message : String(error)}`);
16058
+ } finally {
16059
+ releaseLegacyMigrationLock2(lock);
16060
+ }
16061
+ }
16003
16062
  var RUNTIME_AGENT_JOB_STATUSES = ["queued", "running", "succeeded", "failed", "cancelled", "superseded", "expired"];
16004
16063
 
16005
16064
  class SqliteLocalStore {
@@ -17334,6 +17393,21 @@ function assertCurrentLocalStoreSchema2(db, path) {
17334
17393
  throw new Error(`SQLite local store schema incomplete for ${path}: missing migrations ${missingMigrations.join(", ")}`);
17335
17394
  }
17336
17395
  }
17396
+ function assertUpgradeableLocalStoreTarget2(path) {
17397
+ const db = openSqliteDatabaseSync2(path);
17398
+ try {
17399
+ const integrity = sqliteIntegrityCheckOpenDatabase2(db, path);
17400
+ const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((row) => String(row.name)));
17401
+ const hasArchContextMarker = ["schema_migrations", "task_states", "repository_sessions", "snapshots"].some((table) => tables.has(table));
17402
+ if (!hasArchContextMarker) {
17403
+ throw new Error(`SQLite target is not an ArchContext local store candidate: ${path}`);
17404
+ }
17405
+ if (integrity !== "ok")
17406
+ throw new Error(`SQLite integrity_check failed for ${path}: ${integrity}`);
17407
+ } finally {
17408
+ db.close();
17409
+ }
17410
+ }
17337
17411
  function assertTrustedLegacyLocalStoreSource2(paths) {
17338
17412
  const stat = lstatSync5(paths.legacyLocalStorePath);
17339
17413
  if (stat.isSymbolicLink()) {
@@ -25904,8 +25978,14 @@ var ARCHITECTURE_BOOK_RESOURCES = [
25904
25978
  class McpLocalServer {
25905
25979
  resources = new Map;
25906
25980
  runtimeInstance;
25907
- constructor(runtime) {
25908
- this.runtimeInstance = runtime;
25981
+ runtimeResolver;
25982
+ constructor(runtimeOrOptions) {
25983
+ if (isMcpLocalServerOptions(runtimeOrOptions)) {
25984
+ this.runtimeInstance = runtimeOrOptions.runtime;
25985
+ this.runtimeResolver = runtimeOrOptions.runtimeResolver;
25986
+ } else {
25987
+ this.runtimeInstance = runtimeOrOptions;
25988
+ }
25909
25989
  }
25910
25990
  listTools() {
25911
25991
  return LOCAL_MCP_TOOLS;
@@ -26027,7 +26107,7 @@ class McpLocalServer {
26027
26107
  }))
26028
26108
  ];
26029
26109
  try {
26030
- const status = await (await this.runtime(root)).docs(root, { command: "status", provider: "context7" });
26110
+ const status = await (await this.runtime(root, { allowResolver: false })).docs(root, { command: "status", provider: "context7" });
26031
26111
  if (!status.ok)
26032
26112
  return localResources;
26033
26113
  const cacheEntries = status.data?.cacheEntries ?? [];
@@ -26090,7 +26170,7 @@ class McpLocalServer {
26090
26170
  dataClassification: "local-architecture"
26091
26171
  };
26092
26172
  }
26093
- async runtime(root = process.cwd()) {
26173
+ async runtime(root = process.cwd(), options = { allowResolver: true }) {
26094
26174
  if (this.runtimeInstance)
26095
26175
  return this.runtimeInstance;
26096
26176
  const client = createRuntimeRpcClientFromConnectionFile2(root);
@@ -26103,9 +26183,16 @@ class McpLocalServer {
26103
26183
  return this.runtimeInstance;
26104
26184
  }
26105
26185
  }
26186
+ if (options.allowResolver !== false && this.runtimeResolver) {
26187
+ this.runtimeInstance = await this.runtimeResolver(root);
26188
+ return this.runtimeInstance;
26189
+ }
26106
26190
  throw new Error("archctxd RPC is unavailable; run `archctx daemon start` before using the local MCP surface");
26107
26191
  }
26108
26192
  }
26193
+ function isMcpLocalServerOptions(value) {
26194
+ return Boolean(value && typeof value === "object" && (("runtime" in value) || ("runtimeResolver" in value)));
26195
+ }
26109
26196
  function requiredArg(args, key) {
26110
26197
  const value = args[key];
26111
26198
  if (typeof value !== "string" || value.length === 0)
@@ -26119,8 +26206,8 @@ function runtimeUnavailable(requestId, error) {
26119
26206
  };
26120
26207
  }
26121
26208
  async function runStdioMcpLoop(input, output, log = (line) => process.stderr.write(`${line}
26122
- `)) {
26123
- const server = new McpLocalServer;
26209
+ `), options = {}) {
26210
+ const server = new McpLocalServer(options);
26124
26211
  log("[archctx-mcp] started");
26125
26212
  for await (const line of input) {
26126
26213
  const message = JSON.parse(line);
@@ -26173,7 +26260,8 @@ class RuntimeVersionUnsupportedError extends Error {
26173
26260
  if (__require.main == __require.module) {
26174
26261
  if (command === "mcp" && args.length === 0) {
26175
26262
  await runStdioMcpLoop(stdinLines(), (line) => process.stdout.write(`${line}
26176
- `));
26263
+ `), (line) => process.stderr.write(`${line}
26264
+ `), { runtimeResolver: (root) => createOrStartRuntimeRpcClient(root) });
26177
26265
  } else if (command === "daemon" && args[0] === "start" && args.includes("--foreground")) {
26178
26266
  await runForegroundDaemon(process.cwd(), args).catch((error) => {
26179
26267
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}
@@ -26446,7 +26534,7 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
26446
26534
  requestId: "help",
26447
26535
  data: {
26448
26536
  commands: ["init", "sync", "validate", "context", "status", "daemon", "repo", "landscape", "ledger", "book", "recommendations", "explore", "prepare", "practices", "checkpoint", "hook", "hooks", "investigate", "agents", "jobs", "plan", "apply", "review", "complete", "github", "config", "mcp", "install", "uninstall", "doctor", "update", "paths", "privacy-audit", "export", "import", "tunnel"],
26449
- examples: ["archctx init --name MyApp", "archctx ledger migrate --from-yaml --dry-run", "archctx book recommendations --open --explain", "archctx recommendations accept --id recommendation.<id> --reason 'Accepted after local readback.'", "archctx recommendations metrics", "archctx practices validate --strict", "archctx practices list --json", "archctx practices waivers", "archctx practices waive --practice-id modularity.no-new-cycle --owner team-architecture --reason 'External migration window requires this edge until cutover.' --review-at 2026-07-10T00:00:00.000Z --expires-at 2026-07-24T00:00:00.000Z --evidence-digest sha256:<64-hex> --subject module.a->module.b", "archctx checkpoint --task-session-id task_cli", "archctx investigate --runner-port codex", "archctx agents status --status queued,running", "archctx agents budget", "archctx hook enqueue --event post-edit --path src/app.ts", "archctx jobs list --status queued", "archctx hooks install --host codex", "archctx paths", "archctx update --check", "archctx doctor --check-updates", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx tunnel"]
26537
+ examples: ["archctx init --name MyApp", "archctx ledger migrate --from-yaml --dry-run", "archctx ledger promote --mode authoritative --preflight --rollback-plan", "archctx book recommendations --open --explain", "archctx recommendations accept --id recommendation.<id> --reason 'Accepted after local readback.'", "archctx recommendations metrics", "archctx practices validate --strict", "archctx practices list --json", "archctx practices waivers", "archctx practices waive --practice-id modularity.no-new-cycle --owner team-architecture --reason 'External migration window requires this edge until cutover.' --review-at 2026-07-10T00:00:00.000Z --expires-at 2026-07-24T00:00:00.000Z --evidence-digest sha256:<64-hex> --subject module.a->module.b", "archctx checkpoint --task-session-id task_cli", "archctx investigate --runner-port codex", "archctx agents status --status queued,running", "archctx agents budget", "archctx hook enqueue --event post-edit --path src/app.ts", "archctx jobs list --status queued", "archctx hooks install --host codex", "archctx paths", "archctx update --check", "archctx doctor --check-updates", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx tunnel"]
26450
26538
  }
26451
26539
  };
26452
26540
  }
@@ -26465,6 +26553,24 @@ async function runLedgerCommand(args2, cwd, runtime) {
26465
26553
  const daemon = await requiredLedgerRuntime(runtime);
26466
26554
  return daemon.ledgerDrift(cwd);
26467
26555
  }
26556
+ if (subcommand === "promote") {
26557
+ if (args2.includes("--write") || args2.includes("--enable") || args2.includes("--apply")) {
26558
+ return errorEnvelope("ledger.promote", "AC_SCHEMA_INVALID", "ledger promote is preflight-only; it does not write runtime config or enable authority");
26559
+ }
26560
+ const mode = readFlag(args2, "--mode") ?? args2[1];
26561
+ const targetMode = normalizeLedgerPromotionTargetMode(mode);
26562
+ if (!targetMode) {
26563
+ return errorEnvelope("ledger.promote", "AC_SCHEMA_INVALID", "ledger promote requires --mode authoritative");
26564
+ }
26565
+ if (!args2.includes("--preflight")) {
26566
+ return errorEnvelope("ledger.promote", "AC_SCHEMA_INVALID", "ledger promote requires --preflight");
26567
+ }
26568
+ if (!args2.includes("--rollback-plan")) {
26569
+ return errorEnvelope("ledger.promote", "AC_SCHEMA_INVALID", "ledger promote requires --rollback-plan");
26570
+ }
26571
+ const daemon = await requiredLedgerRuntime(runtime);
26572
+ return runLedgerPromotionPreflight(cwd, daemon, targetMode);
26573
+ }
26468
26574
  if (subcommand === "project") {
26469
26575
  if (!args2.includes("--to-git")) {
26470
26576
  return errorEnvelope("ledger.project", "AC_SCHEMA_INVALID", "ledger project currently requires --to-git");
@@ -26533,13 +26639,124 @@ async function runLedgerCommand(args2, cwd, runtime) {
26533
26639
  expectedWorktreeDigest
26534
26640
  });
26535
26641
  }
26536
- return errorEnvelope("ledger", "AC_SCHEMA_INVALID", "ledger requires status, state, drift --json, migrate --from-yaml, rebuild --from-git, rollback --to-yaml, or project --to-git");
26642
+ return errorEnvelope("ledger", "AC_SCHEMA_INVALID", "ledger requires status, state, drift --json, promote --mode authoritative --preflight --rollback-plan, migrate --from-yaml, rebuild --from-git, rollback --to-yaml, or project --to-git");
26537
26643
  }
26538
26644
  async function requiredLedgerRuntime(runtime) {
26539
26645
  if (!runtime)
26540
26646
  throw new Error("ledger command requires runtime daemon");
26541
26647
  return runtime();
26542
26648
  }
26649
+ function normalizeLedgerPromotionTargetMode(value) {
26650
+ if (value === "authoritative" || value === "ledger-authoritative" || value === "ledger")
26651
+ return "ledger-authoritative";
26652
+ return;
26653
+ }
26654
+ async function runLedgerPromotionPreflight(cwd, daemon, targetMode) {
26655
+ const stateEnvelope = await daemon.ledgerState(cwd);
26656
+ if (!stateEnvelope.ok)
26657
+ return stateEnvelope;
26658
+ const driftEnvelope = await daemon.ledgerDrift(cwd);
26659
+ if (!driftEnvelope.ok)
26660
+ return driftEnvelope;
26661
+ const state = readObject(stateEnvelope.data);
26662
+ const driftData = readObject(driftEnvelope.data);
26663
+ const architectureLedger = readObject(state.architectureLedger);
26664
+ const phaseFlags = readObject(architectureLedger.phaseFlags);
26665
+ const currentPhase = String(phaseFlags.activePhase ?? architectureLedger.rolloutMode ?? "unknown");
26666
+ const worktree = readObject(state.worktree);
26667
+ const ledger3 = readObject(state.ledger);
26668
+ const yaml = readObject(state.yaml);
26669
+ const drift = readObject(driftData.drift ?? state.drift);
26670
+ const reconcile = readObject(driftData.reconcile ?? state.reconcile);
26671
+ const worktreeDigest = typeof worktree.worktreeDigest === "string" ? worktree.worktreeDigest : "<current>";
26672
+ const nextRequiredPhase = nextLedgerPromotionPhase(currentPhase);
26673
+ const preconditions = {
26674
+ currentPhase,
26675
+ targetMode,
26676
+ noModeSkip: currentPhase === "ledger-shadow" || currentPhase === targetMode,
26677
+ driftClean: drift.ok === true,
26678
+ reconcileClean: reconcile.ok === true,
26679
+ unsupportedYamlFilesAbsent: Number(yaml.unsupportedFileCount ?? 0) === 0,
26680
+ ledgerStatePresent: Number(ledger3.entityCount ?? 0) + Number(ledger3.relationCount ?? 0) + Number(ledger3.constraintCount ?? 0) > 0,
26681
+ rollbackPlanPresent: true,
26682
+ hardEnforcementUnchanged: true
26683
+ };
26684
+ const alreadyActive = currentPhase === targetMode;
26685
+ const ready = !alreadyActive && Object.values(preconditions).every((value) => value === true || typeof value === "string");
26686
+ const reasonCodes = [
26687
+ ...alreadyActive ? ["already-ledger-authoritative"] : [],
26688
+ ...preconditions.noModeSkip ? [] : [`mode-sequence-not-ready:${currentPhase}->${nextRequiredPhase ?? "ledger-shadow"}`],
26689
+ ...preconditions.driftClean ? [] : ["ledger-yaml-drift-not-clean"],
26690
+ ...preconditions.reconcileClean ? [] : ["ledger-reconcile-not-clean"],
26691
+ ...preconditions.unsupportedYamlFilesAbsent ? [] : ["unsupported-yaml-files-present"],
26692
+ ...preconditions.ledgerStatePresent ? [] : ["ledger-state-empty"]
26693
+ ];
26694
+ return okEnvelope("ledger.promote", {
26695
+ schemaVersion: "archcontext.runtime-architecture-ledger-promotion-preflight/v1",
26696
+ targetMode,
26697
+ status: alreadyActive ? "already-active" : ready ? "ready" : "blocked",
26698
+ ready,
26699
+ writes: "none",
26700
+ sideEffects: {
26701
+ ledgerModeChanged: false,
26702
+ hardEnforcementChanged: false,
26703
+ sqliteMutated: false,
26704
+ yamlMutated: false
26705
+ },
26706
+ repository: state.repository,
26707
+ worktree: state.worktree,
26708
+ current: {
26709
+ phase: currentPhase,
26710
+ readMode: architectureLedger.readMode,
26711
+ writeMode: architectureLedger.writeMode,
26712
+ readAuthority: architectureLedger.readAuthority,
26713
+ writeAuthority: architectureLedger.writeAuthority,
26714
+ graphDigest: state.graphDigest,
26715
+ ledgerGraphDigest: ledger3.graphDigest,
26716
+ yamlGraphDigest: yaml.graphDigest
26717
+ },
26718
+ preconditions,
26719
+ reasonCodes,
26720
+ nextRequiredPhase,
26721
+ recommendedEnvironment: {
26722
+ ARCHCONTEXT_LEDGER_MODE: targetMode,
26723
+ ARCHCONTEXT_LEDGER_READ_MODE: "ledger",
26724
+ ARCHCONTEXT_LEDGER_WRITE_MODE: "ledger-with-projection"
26725
+ },
26726
+ rollbackPlan: {
26727
+ required: true,
26728
+ targetAuthority: "yaml",
26729
+ dryRunCommand: "archctx ledger rollback --to-yaml --dry-run",
26730
+ command: `archctx ledger rollback --to-yaml --write --expected-worktree-digest ${worktreeDigest}`,
26731
+ commandTemplate: "archctx ledger rollback --to-yaml --write --expected-worktree-digest <current>",
26732
+ environment: {
26733
+ ARCHCONTEXT_LEDGER_MODE: "yaml",
26734
+ ARCHCONTEXT_LEDGER_READ_MODE: "yaml",
26735
+ ARCHCONTEXT_LEDGER_WRITE_MODE: "yaml"
26736
+ }
26737
+ },
26738
+ boundary: {
26739
+ advisoryDefaultPreserved: true,
26740
+ productionGaClaimed: false,
26741
+ hardEnforcementEnabled: false,
26742
+ operatorActionRequired: true
26743
+ }
26744
+ });
26745
+ }
26746
+ function nextLedgerPromotionPhase(currentPhase) {
26747
+ if (currentPhase === "yaml")
26748
+ return "dual";
26749
+ if (currentPhase === "dual")
26750
+ return "ledger-shadow";
26751
+ if (currentPhase === "ledger-shadow")
26752
+ return "ledger-authoritative";
26753
+ if (currentPhase === "ledger-authoritative")
26754
+ return null;
26755
+ return "yaml";
26756
+ }
26757
+ function readObject(value) {
26758
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
26759
+ }
26543
26760
  async function runBookCommand(args2, cwd, daemon) {
26544
26761
  const subcommand = args2[0] ?? "status";
26545
26762
  const maxItems = readOptionalNonNegativeIntegerFlag(args2, "--max-items", "book");
@@ -28241,39 +28458,9 @@ async function createCliRuntime(cwd, deps) {
28241
28458
  return;
28242
28459
  } };
28243
28460
  if (!deps.disableRpcDiscovery && !hasEmbeddedRuntimeDeps(deps)) {
28244
- const fileIssue = runtimeRpcCompatibilityIssue(cwd);
28245
- if (fileIssue?.pidAlive)
28246
- throw new RuntimeVersionUnsupportedError(fileIssue);
28247
- const client = createRuntimeRpcClientFromConnectionFile(cwd);
28248
- if (client) {
28249
- const health = await client.health().catch(() => {
28250
- return;
28251
- });
28252
- const healthIssue = runtimeRpcCompatibilityIssueFromHealth(cwd, client, health);
28253
- if (healthIssue)
28254
- throw new RuntimeVersionUnsupportedError(healthIssue);
28255
- if (health?.ok === true)
28256
- return { client, close: async () => {
28257
- return;
28258
- } };
28259
- recoverStaleDaemonControlFiles(cwd, { removeUnhealthyConnection: true });
28260
- } else {
28261
- recoverStaleDaemonControlFiles(cwd);
28262
- }
28263
- const started = await startBackgroundDaemon([], cwd);
28264
- if (!started.ok)
28265
- throw new Error(started.error?.message ?? "archctxd did not start");
28266
- const startedClient = createRuntimeRpcClientFromConnectionFile(cwd);
28267
- if (startedClient) {
28268
- const health = await startedClient.health().catch(() => {
28269
- return;
28270
- });
28271
- if (health?.ok === true)
28272
- return { client: startedClient, close: async () => {
28273
- return;
28274
- } };
28275
- }
28276
- throw new Error("archctxd started but no healthy runtime RPC connection was available");
28461
+ return { client: await createOrStartRuntimeRpcClient(cwd), close: async () => {
28462
+ return;
28463
+ } };
28277
28464
  }
28278
28465
  const {
28279
28466
  runtimeClient: _runtimeClient,
@@ -28294,6 +28481,40 @@ async function createCliRuntime(cwd, deps) {
28294
28481
  });
28295
28482
  return { client: daemon, close: () => daemon.stop() };
28296
28483
  }
28484
+ async function createOrStartRuntimeRpcClient(cwd) {
28485
+ const fileIssue = runtimeRpcCompatibilityIssue(cwd);
28486
+ if (fileIssue?.pidAlive)
28487
+ throw new RuntimeVersionUnsupportedError(fileIssue);
28488
+ const client = createRuntimeRpcClientFromConnectionFile(cwd);
28489
+ if (client) {
28490
+ const health = await client.health().catch(() => {
28491
+ return;
28492
+ });
28493
+ const healthIssue = runtimeRpcCompatibilityIssueFromHealth(cwd, client, health);
28494
+ if (healthIssue)
28495
+ throw new RuntimeVersionUnsupportedError(healthIssue);
28496
+ if (health?.ok === true)
28497
+ return client;
28498
+ recoverStaleDaemonControlFiles(cwd, { removeUnhealthyConnection: true });
28499
+ } else {
28500
+ recoverStaleDaemonControlFiles(cwd);
28501
+ }
28502
+ const started = await startBackgroundDaemon([], cwd);
28503
+ if (!started.ok)
28504
+ throw new Error(mcpDaemonStartRecoveryMessage(started.error?.message ?? "archctxd did not start"));
28505
+ const startedClient = createRuntimeRpcClientFromConnectionFile(cwd);
28506
+ if (startedClient) {
28507
+ const health = await startedClient.health().catch(() => {
28508
+ return;
28509
+ });
28510
+ if (health?.ok === true)
28511
+ return startedClient;
28512
+ }
28513
+ throw new Error(mcpDaemonStartRecoveryMessage("archctxd started but no healthy runtime RPC connection was available"));
28514
+ }
28515
+ function mcpDaemonStartRecoveryMessage(message) {
28516
+ return message.includes("archctx daemon") ? message : `${message}; run \`archctx daemon start\` before using the local MCP surface`;
28517
+ }
28297
28518
  function hasEmbeddedRuntimeDeps(deps) {
28298
28519
  return [
28299
28520
  "codeFacts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archctx",
3
- "version": "0.1.4-beta.0",
3
+ "version": "0.1.5",
4
4
  "description": "Local architecture context CLI for agentic coding workflows.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  "README.md"
17
17
  ],
18
18
  "homepage": "https://archcontext.repoharness.com",
19
- "license": "UNLICENSED",
19
+ "license": "Apache-2.0",
20
20
  "publishConfig": {
21
21
  "registry": "https://registry.npmjs.org/"
22
22
  },