archctx 0.6.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/archctx.mjs CHANGED
@@ -1,38 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // @bun
3
3
  import { createRequire } from "node:module";
4
- var __create = Object.create;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __defProp = Object.defineProperty;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- function __accessProp(key) {
10
- return this[key];
11
- }
12
- var __toESMCache_node;
13
- var __toESMCache_esm;
14
- var __toESM = (mod, isNodeMode, target) => {
15
- var canCache = mod != null && typeof mod === "object";
16
- if (canCache) {
17
- var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
18
- var cached = cache.get(mod);
19
- if (cached)
20
- return cached;
21
- }
22
- target = mod != null ? __create(__getProtoOf(mod)) : {};
23
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
24
- if (mod && typeof mod === "object" || typeof mod === "function") {
25
- for (let key of __getOwnPropNames(mod))
26
- if (!__hasOwnProp.call(to, key))
27
- __defProp(to, key, {
28
- get: __accessProp.bind(mod, key),
29
- enumerable: true
30
- });
31
- }
32
- if (canCache)
33
- cache.set(mod, to);
34
- return to;
35
- };
36
5
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
37
6
  var __returnValue = (v) => v;
38
7
  function __exportSetter(name, newValue) {
@@ -1356,13 +1325,13 @@ function productVersionManifest() {
1356
1325
  sqliteMigrations: "0001_runtime_state..0012_explorer_projection_index",
1357
1326
  codeGraph: {
1358
1327
  packageName: "@colbymchenry/codegraph",
1359
- requiredVersion: "1.5.0",
1328
+ requiredVersion: "1.6.1",
1360
1329
  adapter: "codegraph-cli"
1361
1330
  }
1362
1331
  }
1363
1332
  };
1364
1333
  }
1365
- var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.6.0", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.4.0", ARCHCONTEXT_NODE_RANGE = ">=22.22 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-07-11.explorer-view-v2";
1334
+ var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.6.3", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.4.0", ARCHCONTEXT_NODE_RANGE = ">=22.22 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-07-11.explorer-view-v2";
1366
1335
 
1367
1336
  // packages/contracts/src/refactor.ts
1368
1337
  function refactorProposalDigest(proposal) {
@@ -2111,42 +2080,6 @@ var init_src = __esm(() => {
2111
2080
  init_validator();
2112
2081
  });
2113
2082
 
2114
- // node_modules/.bun/@colbymchenry+codegraph@1.5.0/node_modules/@colbymchenry/codegraph/npm-sdk.js
2115
- var require_npm_sdk = __commonJS(function(exports, module) {
2116
- var __dirname = "/Users/chris/Projects/arch-context-publish-0600/node_modules/.bun/@colbymchenry+codegraph@1.5.0/node_modules/@colbymchenry/codegraph";
2117
- var path = __require("path");
2118
- var os = __require("os");
2119
- var fs = __require("fs");
2120
- var target = process.platform + "-" + process.arch;
2121
- var pkg = "@colbymchenry/codegraph-" + target;
2122
- module.exports = __require(resolveLibrary());
2123
- function resolveLibrary() {
2124
- try {
2125
- return __require.resolve(pkg + "/lib/dist/index.js");
2126
- } catch (e) {}
2127
- var cached = cachedLibrary();
2128
- if (cached)
2129
- return cached;
2130
- throw new Error(`codegraph: the programmatic API is unavailable because the platform bundle
2131
- ` + "(" + pkg + `) is not installed.
2132
- ` + `The compiled library ships inside that per-platform optional dependency.
2133
- ` + `Fixes:
2134
- ` + ` - install from the official npm registry so the matching bundle is fetched:
2135
- ` + ` npm i @colbymchenry/codegraph --registry=https://registry.npmjs.org
2136
- ` + " - or run the CLI once (e.g. `npx @colbymchenry/codegraph status`) to\n" + " self-heal the bundle into ~/.codegraph, then require() will find it.");
2137
- }
2138
- function cachedLibrary() {
2139
- try {
2140
- var version = __require(path.join(__dirname, "package.json")).version;
2141
- var base = process.env.CODEGRAPH_INSTALL_DIR || path.join(os.homedir(), ".codegraph");
2142
- var lib = path.join(base, "bundles", target + "-" + version, "lib", "dist", "index.js");
2143
- if (fs.existsSync(lib))
2144
- return lib;
2145
- } catch (e) {}
2146
- return null;
2147
- }
2148
- });
2149
-
2150
2083
  // node_modules/.bun/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js
2151
2084
  var require_identity = __commonJS(function(exports) {
2152
2085
  var ALIAS = Symbol.for("yaml.alias");
@@ -11351,9 +11284,9 @@ class ControlPlane {
11351
11284
  rollback: "versioned-cloud-metadata-release"
11352
11285
  };
11353
11286
  }
11354
- rollbackChatGptRelease(version2) {
11355
- this.releaseRollbacks.push(version2);
11356
- return { rolledBack: true, version: version2 };
11287
+ rollbackChatGptRelease(version) {
11288
+ this.releaseRollbacks.push(version);
11289
+ return { rolledBack: true, version };
11357
11290
  }
11358
11291
  redactLog(value) {
11359
11292
  return value.replace(/(access|refresh|secret|token)_[a-zA-Z0-9_-]+/g, "[REDACTED]");
@@ -13550,11 +13483,10 @@ function withLocalEgress2(channel, operation, env = process.env) {
13550
13483
  }
13551
13484
 
13552
13485
  // packages/local-runtime/codegraph-adapter/src/index.ts
13553
- var import_codegraph = __toESM(require_npm_sdk(), 1);
13554
13486
  import { execFileSync as execFileSync2 } from "node:child_process";
13555
13487
  import { createHash as createHash5 } from "node:crypto";
13556
13488
  import { accessSync, closeSync as closeSync3, constants as fsConstants2, existsSync as existsSync6, openSync as openSync3, readFileSync as readFileSync7, readSync, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
13557
- import { createRequire as createRequire4 } from "node:module";
13489
+ import { createRequire as createRequire2 } from "node:module";
13558
13490
  import { basename as basename3, delimiter, dirname as dirname4, isAbsolute as isAbsolute4, join as join4, posix as posix2, resolve as resolve8 } from "node:path";
13559
13491
 
13560
13492
  // packages/core/architecture-delta/src/index.ts
@@ -15314,401 +15246,7 @@ function evaluateChangeSetPaths(root, paths, scope) {
15314
15246
  init_src();
15315
15247
  import { chmodSync as chmodSync2, closeSync, constants as fsConstants, fstatSync, fsyncSync, linkSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync3, renameSync, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
15316
15248
  import { dirname as dirname2, join as join3, resolve as resolve4 } from "node:path";
15317
-
15318
- // node_modules/.bun/koffi@3.1.6/node_modules/koffi/src/koffi/index.js
15319
- import util from "node:util";
15320
- import fs2 from "node:fs";
15321
- import { createRequire as createRequire3 } from "node:module";
15322
- import fs from "node:fs";
15323
-
15324
- // node_modules/.bun/koffi@3.1.6/node_modules/koffi/src/koffi/src/static.js
15325
- import { createRequire as createRequire2 } from "node:module";
15326
- var require2 = createRequire2(import.meta.url);
15327
- function loadStatic(pkg) {
15328
- let native = null;
15329
- if (pkg == "linux-arm64") {
15330
- try {
15331
- native = require2("@koromix/koffi-linux-arm64");
15332
- } catch (err) {}
15333
- }
15334
- if (pkg == "linux-ia32") {
15335
- try {
15336
- native = require2("@koromix/koffi-linux-ia32");
15337
- } catch (err) {}
15338
- }
15339
- if (pkg == "linux-x64") {
15340
- try {
15341
- native = require2("@koromix/koffi-linux-x64");
15342
- } catch (err) {}
15343
- }
15344
- if (pkg == "linux-riscv64") {
15345
- try {
15346
- native = require2("@koromix/koffi-linux-riscv64");
15347
- } catch (err) {}
15348
- }
15349
- if (pkg == "freebsd-ia32") {
15350
- try {
15351
- native = require2("@koromix/koffi-freebsd-ia32");
15352
- } catch (err) {}
15353
- }
15354
- if (pkg == "freebsd-x64") {
15355
- try {
15356
- native = require2("@koromix/koffi-freebsd-x64");
15357
- } catch (err) {}
15358
- }
15359
- if (pkg == "freebsd-arm64") {
15360
- try {
15361
- native = require2("@koromix/koffi-freebsd-arm64");
15362
- } catch (err) {}
15363
- }
15364
- if (pkg == "openbsd-ia32") {
15365
- try {
15366
- native = require2("@koromix/koffi-openbsd-ia32");
15367
- } catch (err) {}
15368
- }
15369
- if (pkg == "openbsd-x64") {
15370
- try {
15371
- native = require2("@koromix/koffi-openbsd-x64");
15372
- } catch (err) {}
15373
- }
15374
- if (pkg == "win32-ia32") {
15375
- try {
15376
- native = require2("@koromix/koffi-win32-ia32");
15377
- } catch (err) {}
15378
- }
15379
- if (pkg == "win32-x64") {
15380
- try {
15381
- native = require2("@koromix/koffi-win32-x64");
15382
- } catch (err) {}
15383
- }
15384
- if (pkg == "win32-arm64") {
15385
- try {
15386
- native = require2("@koromix/koffi-win32-arm64");
15387
- } catch (err) {}
15388
- }
15389
- if (pkg == "darwin-x64") {
15390
- try {
15391
- native = require2("@koromix/koffi-darwin-x64");
15392
- } catch (err) {}
15393
- }
15394
- if (pkg == "darwin-arm64") {
15395
- try {
15396
- native = require2("@koromix/koffi-darwin-arm64");
15397
- } catch (err) {}
15398
- }
15399
- if (pkg == "linux-loong64") {
15400
- try {
15401
- native = require2("@koromix/koffi-linux-loong64");
15402
- } catch (err) {}
15403
- }
15404
- return native;
15405
- }
15406
-
15407
- // node_modules/.bun/koffi@3.1.6/node_modules/koffi/src/koffi/index.js
15408
- var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
15409
- var __typeError = (msg) => {
15410
- throw TypeError(msg);
15411
- };
15412
- var __using = (stack, value, async) => {
15413
- if (value != null) {
15414
- if (typeof value !== "object" && typeof value !== "function")
15415
- __typeError("Object expected");
15416
- var dispose, inner;
15417
- if (async)
15418
- dispose = value[__knownSymbol("asyncDispose")];
15419
- if (dispose === undefined) {
15420
- dispose = value[__knownSymbol("dispose")];
15421
- if (async)
15422
- inner = dispose;
15423
- }
15424
- if (typeof dispose !== "function")
15425
- __typeError("Object not disposable");
15426
- if (inner)
15427
- dispose = function() {
15428
- try {
15429
- inner.call(this);
15430
- } catch (e) {
15431
- return Promise.reject(e);
15432
- }
15433
- };
15434
- stack.push([async, dispose, value]);
15435
- } else if (async) {
15436
- stack.push([async]);
15437
- }
15438
- return value;
15439
- };
15440
- var __callDispose = (stack, error, hasError) => {
15441
- var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
15442
- return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
15443
- };
15444
- var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
15445
- var next = (it) => {
15446
- while (it = stack.pop()) {
15447
- try {
15448
- var result = it[1] && it[1].call(it[2]);
15449
- if (it[0])
15450
- return Promise.resolve(result).then(next, (e) => (fail(e), next()));
15451
- } catch (e) {
15452
- fail(e);
15453
- }
15454
- }
15455
- if (hasError)
15456
- throw error;
15457
- };
15458
- return next();
15459
- };
15460
- function determineAbi() {
15461
- let abi = process.arch.toString();
15462
- if (abi == "riscv32" || abi == "riscv64") {
15463
- var _stack = [];
15464
- try {
15465
- const file = __using(_stack, openFile(process.execPath, "r"));
15466
- let header = readElfHeader(file);
15467
- let float_abi = header.e_flags & 6;
15468
- switch (float_abi) {
15469
- case 0:
15470
- {}
15471
- break;
15472
- case 2:
15473
- {
15474
- abi += "f";
15475
- }
15476
- break;
15477
- case 4:
15478
- {
15479
- abi += "d";
15480
- }
15481
- break;
15482
- case 6:
15483
- {
15484
- abi += "q";
15485
- }
15486
- break;
15487
- }
15488
- } catch (_) {
15489
- var _error = _, _hasError = true;
15490
- } finally {
15491
- __callDispose(_stack, _error, _hasError);
15492
- }
15493
- } else if (abi == "arm") {
15494
- var _stack2 = [];
15495
- try {
15496
- const file = __using(_stack2, openFile(process.execPath, "r"));
15497
- let header = readElfHeader(file);
15498
- if (header.e_flags & 1024) {
15499
- abi += "hf";
15500
- } else if (header.e_flags & 512) {
15501
- abi += "sf";
15502
- } else {
15503
- throw new Error("Unknown ARM floating-point ABI");
15504
- }
15505
- } catch (_2) {
15506
- var _error2 = _2, _hasError2 = true;
15507
- } finally {
15508
- __callDispose(_stack2, _error2, _hasError2);
15509
- }
15510
- }
15511
- return abi;
15512
- }
15513
- function readElfHeader(file, offset = 0) {
15514
- let buf = file.read(offset, 512);
15515
- if (buf.length < 16)
15516
- throw new Error("Truncated header");
15517
- if (buf[0] != 127 || buf[1] != 69 || buf[2] != 76 || buf[3] != 70)
15518
- throw new Error("Invalid magic number");
15519
- if (buf[6] != 1)
15520
- throw new Error("Invalid ELF version");
15521
- if (buf[5] != 1)
15522
- throw new Error("Big-endian architectures are not supported");
15523
- switch (buf[4]) {
15524
- case 1:
15525
- {
15526
- if (buf.length < 68)
15527
- throw new Error("Truncated ELF header");
15528
- return {
15529
- ei_class: 32,
15530
- e_machine: buf.readUInt16LE(18),
15531
- e_flags: buf.readUInt32LE(36),
15532
- e_phoff: buf.readUInt32LE(28),
15533
- e_phentsize: buf.readUInt16LE(42),
15534
- e_phnum: buf.readUInt16LE(44)
15535
- };
15536
- }
15537
- break;
15538
- case 2:
15539
- {
15540
- if (buf.length < 120)
15541
- throw new Error("Truncated ELF header");
15542
- return {
15543
- ei_class: 64,
15544
- e_machine: buf.readUInt16LE(18),
15545
- e_flags: buf.readUInt32LE(48),
15546
- e_phoff: buf.readBigUInt64LE(32),
15547
- e_phentsize: buf.readUInt16LE(54),
15548
- e_phnum: buf.readUInt16LE(56)
15549
- };
15550
- }
15551
- break;
15552
- default:
15553
- throw new Error("Invalid ELF class");
15554
- }
15555
- }
15556
- function openFile(filename, flags) {
15557
- let fd = fs.openSync(filename, flags);
15558
- return new FileHandle(fd);
15559
- }
15560
- var FileHandle = class {
15561
- constructor(fd) {
15562
- this.fd = fd;
15563
- }
15564
- close() {
15565
- fs.closeSync(this.fd);
15566
- }
15567
- [Symbol.dispose]() {
15568
- fs.closeSync(this.fd);
15569
- }
15570
- read(offset, len) {
15571
- let buf = Buffer.allocUnsafe(len);
15572
- let read = fs.readSync(this.fd, buf, 0, len, offset);
15573
- return buf.subarray(0, read);
15574
- }
15575
- };
15576
- var package_default = { name: "koffi", version: "3.1.6", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
15577
- var require22 = createRequire3(import.meta.url);
15578
- function detectPlatform() {
15579
- if (process.versions.napi == null || process.versions.napi < package_default.cnoke.napi) {
15580
- let major = parseInt(process.versions.node, 10);
15581
- throw new Error(`This engine is based on Node ${process.versions.node}, but ${package_default.name} does not support the Node ${major}.x branch (Node-API < ${package_default.cnoke.napi})`);
15582
- }
15583
- let abi = determineAbi();
15584
- let pkg2 = `${process.platform}-${process.arch}`;
15585
- let triplets2 = [`${process.platform}_${abi}`];
15586
- if (process.platform == "linux")
15587
- triplets2.push(`musl_${abi}`);
15588
- return [package_default.version, pkg2, triplets2];
15589
- }
15590
- function loadDynamic(dirname2, pkg2, triplets2) {
15591
- let suffix = "/../../build/koffi";
15592
- let root = dirname2 + suffix;
15593
- let roots = [root];
15594
- let native2 = null;
15595
- let err = null;
15596
- if (process["resourcesPath"] != null) {
15597
- let suffixes = [
15598
- "/koffi",
15599
- "/koffi/build",
15600
- "/node_modules/koffi/build"
15601
- ];
15602
- for (let suffix2 of suffixes)
15603
- roots.push(process["resourcesPath"] + suffix2);
15604
- }
15605
- let names = [
15606
- `${import.meta.dirname}/../../../@koromix/koffi-${pkg2}`,
15607
- ...triplets2.flatMap((triplet) => roots.map((dir) => `${dir}/${triplet}/koffi.node`))
15608
- ];
15609
- for (let name of names) {
15610
- if (!fs2.existsSync(name))
15611
- continue;
15612
- try {
15613
- native2 = require22(name);
15614
- break;
15615
- } catch (e) {
15616
- err ??= e;
15617
- }
15618
- }
15619
- if (native2 == null && err != null)
15620
- throw err;
15621
- return native2;
15622
- }
15623
- function wrapNative(native2, version2) {
15624
- if (native2 == null)
15625
- throw new Error("Cannot find the native Koffi module; did you bundle it correctly?");
15626
- if (native2.version != version2)
15627
- throw new Error("Mismatched native Koffi modules");
15628
- let load = native2.load;
15629
- let register = native2.register;
15630
- let introspect = native2.introspect ?? native2.type;
15631
- native2.sizeof = (spec) => introspect(spec).size;
15632
- native2.alignof = (spec) => introspect(spec).alignment;
15633
- native2.offsetof = (spec, name) => {
15634
- let info = introspect(spec);
15635
- if (info.primitive != "Record")
15636
- throw new TypeError("The offsetof() function can only be used with record types");
15637
- let member = info.members[name];
15638
- if (member == null)
15639
- throw new Error(`Record type ${info.name} does not have member '${name}'`);
15640
- return member.offset;
15641
- };
15642
- native2.register = (...args) => {
15643
- if (args.length >= 3 && typeof args[1] == "function") {
15644
- process.emitWarning("Using koffi.register() with a custom this value was deprecated in Koffi 2.17, use function.bind() instead", "DeprecationWarning", "KOFFI009");
15645
- args[1] = args[1].bind(args[0]);
15646
- args = args.slice(1);
15647
- }
15648
- return register(...args);
15649
- };
15650
- native2.load = (...args) => {
15651
- let lib = load(...args);
15652
- lib.cdecl = util.deprecate((...args2) => lib.func("__cdecl", ...args2), "The koffi.cdecl() function was deprecated in Koffi 2.7, use koffi.func(...) instead", "KOFFI003");
15653
- lib.stdcall = util.deprecate((...args2) => lib.func("__stdcall", ...args2), 'The koffi.stdcall() function was deprecated in Koffi 2.7, use koffi.func("__stdcall", ...) instead', "KOFFI004");
15654
- lib.fastcall = util.deprecate((...args2) => lib.func("__fastcall", ...args2), 'The koffi.fastcall() function was deprecated in Koffi 2.7, use koffi.func("__fastcall", ...) instead', "KOFFI005");
15655
- lib.thiscall = util.deprecate((...args2) => lib.func("__thiscall", ...args2), 'The koffi.thiscall() function was deprecated in Koffi 2.7, use koffi.func("__thiscall", ...) instead', "KOFFI006");
15656
- return lib;
15657
- };
15658
- if (native2.introspect == null) {
15659
- native2.resolve = util.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
15660
- native2.introspect = util.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
15661
- } else {
15662
- native2.resolve = native2.type;
15663
- }
15664
- }
15665
- var [version, pkg, triplets] = detectPlatform();
15666
- var native = loadStatic(pkg) ?? loadDynamic(import.meta.dirname, pkg, triplets);
15667
- wrapNative(native, version);
15668
- var mod_LibraryHandle = native.LibraryHandle;
15669
- var mod_TypeObject = native.TypeObject;
15670
- var mod_Union = native.Union;
15671
- var mod_address = native.address;
15672
- var mod_alias = native.alias;
15673
- var mod_alignof = native.alignof;
15674
- var mod_alloc = native.alloc;
15675
- var mod_array = native.array;
15676
- var mod_as = native.as;
15677
- var mod_call = native.call;
15678
- var mod_config = native.config;
15679
- var mod_decode = native.decode;
15680
- var mod_disposable = native.disposable;
15681
- var mod_encode = native.encode;
15682
- var mod_enumeration = native.enumeration;
15683
- var mod_errno = native.errno;
15684
- var mod_extension = native.extension;
15685
- var mod_free = native.free;
15686
- var mod_in = native.in;
15687
- var mod_inout = native.inout;
15688
- var mod_introspect = native.introspect;
15689
- var mod_load = native.load;
15690
- var mod_node = native.node;
15691
- var mod_offsetof = native.offsetof;
15692
- var mod_opaque = native.opaque;
15693
- var mod_os = native.os;
15694
- var mod_out = native.out;
15695
- var mod_pack = native.pack;
15696
- var mod_pointer = native.pointer;
15697
- var mod_proto = native.proto;
15698
- var mod_register = native.register;
15699
- var mod_reset = native.reset;
15700
- var mod_resolve = native.resolve;
15701
- var mod_sizeof = native.sizeof;
15702
- var mod_stats = native.stats;
15703
- var mod_struct = native.struct;
15704
- var mod_type = native.type;
15705
- var mod_types = native.types;
15706
- var mod_union = native.union;
15707
- var mod_unregister = native.unregister;
15708
- var mod_version = native.version;
15709
- var mod_view = native.view;
15710
- var index_default = native;
15711
- // packages/core/changeset-engine/src/descriptor-relative-write.ts
15249
+ import koffi from "koffi";
15712
15250
  var beforeCommitTestHook;
15713
15251
  var POSIX_FLAGS = {
15714
15252
  darwin: {
@@ -15748,7 +15286,7 @@ function descriptorRelativeWrite(request) {
15748
15286
  writeWithPosixDirectoryDescriptor(request, flags);
15749
15287
  }
15750
15288
  function writeWithPosixDirectoryDescriptor(request, flags) {
15751
- const libc = index_default.load(null);
15289
+ const libc = koffi.load(null);
15752
15290
  const open = libc.func("open", "int", ["str", "int"]);
15753
15291
  const openat = libc.func("openat", "int", ["int", "str", "int", "uint"]);
15754
15292
  const mkdirat = libc.func("mkdirat", "int", ["int", "str", "uint"]);
@@ -15760,7 +15298,7 @@ function writeWithPosixDirectoryDescriptor(request, flags) {
15760
15298
  const linkat = libc.func("linkat", "int", ["int", "str", "int", "str", "int"]);
15761
15299
  const unlinkat = libc.func("unlinkat", "int", ["int", "str", "int"]);
15762
15300
  const close = libc.func("close", "int", ["int"]);
15763
- const errno = index_default.os.errno;
15301
+ const errno = koffi.os.errno;
15764
15302
  const segments = request.path.split(/[\\/]/u);
15765
15303
  const leaf = segments.pop();
15766
15304
  if (!leaf || segments.some((segment) => !segment || segment === "." || segment === "..")) {
@@ -15771,7 +15309,7 @@ function writeWithPosixDirectoryDescriptor(request, flags) {
15771
15309
  try {
15772
15310
  for (const segment of segments) {
15773
15311
  let nextFd = openat(directoryFd, segment, flags.readOnly | flags.directory | flags.noFollow | flags.closeOnExec, 0);
15774
- if (nextFd < 0 && index_default.errno() === errno.ENOENT) {
15312
+ if (nextFd < 0 && koffi.errno() === errno.ENOENT) {
15775
15313
  checkedResult(mkdirat(directoryFd, segment, 511), `mkdirat ${segment}`);
15776
15314
  nextFd = openat(directoryFd, segment, flags.readOnly | flags.directory | flags.noFollow | flags.closeOnExec, 0);
15777
15315
  }
@@ -15794,7 +15332,7 @@ function writeWithPosixDirectoryDescriptor(request, flags) {
15794
15332
  }
15795
15333
  if (request.expectedHash === "missing") {
15796
15334
  if (linkat(directoryFd, request.tempName, directoryFd, leaf, 0) < 0) {
15797
- if (index_default.errno() === index_default.os.errno.EEXIST)
15335
+ if (koffi.errno() === koffi.os.errno.EEXIST)
15798
15336
  throw new Error(`Expected hash mismatch: ${leaf}`);
15799
15337
  throw posixError(`linkat ${leaf}`);
15800
15338
  }
@@ -15820,9 +15358,9 @@ function assertPinnedParentVisible(request, pinnedParent) {
15820
15358
  function assertExpectedHashAt(directoryFd, leaf, expectedHash, flags, openat, read, close) {
15821
15359
  const fd = openat(directoryFd, leaf, flags.readOnly | flags.noFollow | flags.closeOnExec, 0);
15822
15360
  if (fd < 0) {
15823
- if (index_default.errno() === index_default.os.errno.ENOENT && expectedHash === "missing")
15361
+ if (koffi.errno() === koffi.os.errno.ENOENT && expectedHash === "missing")
15824
15362
  return;
15825
- if (index_default.errno() === index_default.os.errno.ENOENT)
15363
+ if (koffi.errno() === koffi.os.errno.ENOENT)
15826
15364
  throw new Error(`Expected missing file hash for new path: ${leaf}`);
15827
15365
  throw posixError(`openat destination ${leaf}`);
15828
15366
  }
@@ -15865,17 +15403,17 @@ function checkedResult(result, action) {
15865
15403
  throw posixError(action);
15866
15404
  }
15867
15405
  function posixError(action) {
15868
- return new Error(`${action} failed with errno ${index_default.errno()}`);
15406
+ return new Error(`${action} failed with errno ${koffi.errno()}`);
15869
15407
  }
15870
15408
  function writeWithLockedWindowsParents(request) {
15871
- const kernel32 = index_default.load("kernel32.dll");
15409
+ const kernel32 = koffi.load("kernel32.dll");
15872
15410
  const createFileW = kernel32.func("CreateFileW", "void *", ["str16", "uint32", "uint32", "void *", "uint32", "uint32", "void *"]);
15873
15411
  const closeHandle = kernel32.func("CloseHandle", "int", ["void *"]);
15874
- const attributeTagInfo = index_default.struct({ FileAttributes: "uint32", ReparseTag: "uint32" });
15412
+ const attributeTagInfo = koffi.struct({ FileAttributes: "uint32", ReparseTag: "uint32" });
15875
15413
  const getFileInformationByHandleEx = kernel32.func("GetFileInformationByHandleEx", "int", [
15876
15414
  "void *",
15877
15415
  "int",
15878
- index_default.out(index_default.pointer(attributeTagInfo)),
15416
+ koffi.out(koffi.pointer(attributeTagInfo)),
15879
15417
  "uint32"
15880
15418
  ]);
15881
15419
  const handles = [];
@@ -15902,11 +15440,11 @@ function writeWithLockedWindowsParents(request) {
15902
15440
  }
15903
15441
  }
15904
15442
  const handle = createFileW(current, FILE_READ_ATTRIBUTES, FILE_SHARE_READ_WRITE, null, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | (index === 0 ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), null);
15905
- if (index_default.address(handle) === 0xffffffffffffffffn)
15443
+ if (koffi.address(handle) === 0xffffffffffffffffn)
15906
15444
  throw new Error(`CreateFileW failed for protected parent: ${current}`);
15907
15445
  handles.push(handle);
15908
15446
  const info = {};
15909
- if (!getFileInformationByHandleEx(handle, FILE_ATTRIBUTE_TAG_INFO, info, index_default.sizeof(attributeTagInfo))) {
15447
+ if (!getFileInformationByHandleEx(handle, FILE_ATTRIBUTE_TAG_INFO, info, koffi.sizeof(attributeTagInfo))) {
15910
15448
  throw new Error(`GetFileInformationByHandleEx failed for protected parent: ${current}`);
15911
15449
  }
15912
15450
  if (!(info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) || index > 0 && info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
@@ -18576,6 +18114,14 @@ ${wrapped}`;
18576
18114
  }
18577
18115
  return `${existing.slice(0, region.start)}${wrapped}${existing.slice(region.end)}`;
18578
18116
  }
18117
+ function comparableExpectedManifestDigest(expected, actual) {
18118
+ const baseline = actual && typeof actual === "object" && !Array.isArray(actual) ? actual.semanticBaseline : undefined;
18119
+ if (!baseline || typeof baseline !== "object" || Array.isArray(baseline) || "evidence" in baseline)
18120
+ return expected.digest;
18121
+ const value = JSON.parse(expected.body);
18122
+ const { evidence: _evidence, ...semanticBaseline } = value.semanticBaseline;
18123
+ return digestJson({ ...value, semanticBaseline });
18124
+ }
18579
18125
  function architectureDocumentationProjectionDrift(input) {
18580
18126
  const existingByPath = new Map(input.existingFiles.map((file) => [file.path, file]));
18581
18127
  const expectedByPath = new Map(input.expectedFiles.map((file) => [file.path, file]));
@@ -18592,7 +18138,7 @@ function architectureDocumentationProjectionDrift(input) {
18592
18138
  try {
18593
18139
  const parsed = JSON.parse(existingManifest.body);
18594
18140
  const actualDigest = digestJson(parsed);
18595
- if (actualDigest !== input.expectedManifest.digest) {
18141
+ if (actualDigest !== comparableExpectedManifestDigest(input.expectedManifest, parsed)) {
18596
18142
  diffs.push({
18597
18143
  path: input.expectedManifest.path,
18598
18144
  reasonCode: "projection-manifest-stale",
@@ -19005,7 +18551,8 @@ var REQUIRED_CODEGRAPH_VERSION = productVersionManifest().runtime.codeGraph.requ
19005
18551
  var CODEGRAPH_TELEMETRY_ENV = "DO_NOT_TRACK";
19006
18552
  var CODEGRAPH_TELEMETRY_DISABLED_VALUE = "1";
19007
18553
  var DEFAULT_CODEGRAPH_BINARY = "codegraph";
19008
- var requireFromAdapter = createRequire4(import.meta.url);
18554
+ var requireFromAdapter = createRequire2(import.meta.url);
18555
+ var { CodeGraph } = requireFromAdapter(REQUIRED_CODEGRAPH_PACKAGE);
19009
18556
  var CODEGRAPH_OUTPUT_MAX_BYTES = 32 * 1024 * 1024;
19010
18557
  var CODEGRAPH_QUERY_TIMEOUT_MS = 30000;
19011
18558
  function disableCodeGraphTelemetryByDefault(env = process.env) {
@@ -19169,7 +18716,7 @@ function resolvePackagedCodeGraphShim() {
19169
18716
  function packagedCodeGraphRuntimeDigest() {
19170
18717
  try {
19171
18718
  const manifestPath = requireFromAdapter.resolve(`${REQUIRED_CODEGRAPH_PACKAGE}/package.json`);
19172
- const packageRequire = createRequire4(manifestPath);
18719
+ const packageRequire = createRequire2(manifestPath);
19173
18720
  const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
19174
18721
  if (manifest.version !== REQUIRED_CODEGRAPH_VERSION || !manifest.bin?.codegraph) {
19175
18722
  throw new Error(`package manifest is not exact ${REQUIRED_CODEGRAPH_VERSION}`);
@@ -19735,7 +19282,7 @@ function loadCapabilityCodeGraphProjectionInputs(root, model, options = {}) {
19735
19282
  disableCodeGraphTelemetryByDefault();
19736
19283
  const binary = options.binary ?? DEFAULT_CODEGRAPH_BINARY;
19737
19284
  const importGraphs = footprints.length > 0 ? capabilityImportGraphs(root, binary, footprints, options.importNodeLimit ?? CODEGRAPH_IMPORT_NODE_QUERY_LIMIT) : [];
19738
- const selectorIndex = entrypointNodes.length > 0 ? options.selectorIndexFactory?.(root) ?? import_codegraph.CodeGraph.openSync(root) : undefined;
19285
+ const selectorIndex = entrypointNodes.length > 0 ? options.selectorIndexFactory?.(root) ?? CodeGraph.openSync(root) : undefined;
19739
19286
  let selectorEvidence;
19740
19287
  try {
19741
19288
  selectorEvidence = entrypointNodes.flatMap((entry) => entry.entrypoints.flatMap((entrypoint) => entrypoint.symbols.flatMap((source) => source.sinks.map((sink) => exactSelectorEvidence(selectorIndex, {
@@ -20167,8 +19714,8 @@ function assertContext7LibraryId(libraryId) {
20167
19714
  if (!LIBRARY_ID_PATTERN.test(libraryId))
20168
19715
  throw new Error("Context7 libraryId must be /owner/project and repo-pinned");
20169
19716
  }
20170
- function assertContext7Version(version2) {
20171
- if (!VERSION_PATTERN.test(version2))
19717
+ function assertContext7Version(version) {
19718
+ if (!VERSION_PATTERN.test(version))
20172
19719
  throw new Error("Context7 version must be an exact pinned version");
20173
19720
  }
20174
19721
  function buildExternalDocumentationResource(input) {
@@ -20223,7 +19770,7 @@ function projectLibraryCandidate(result) {
20223
19770
  id: result.id,
20224
19771
  title: result.title,
20225
19772
  ...result.description ? { description: cleanExternalText(result.description).slice(0, 240) } : {},
20226
- versions: [...new Set(result.versions ?? [])].filter((version2) => VERSION_PATTERN.test(version2)).sort(),
19773
+ versions: [...new Set(result.versions ?? [])].filter((version) => VERSION_PATTERN.test(version)).sort(),
20227
19774
  ...typeof result.trustScore === "number" ? { trustScore: result.trustScore } : {},
20228
19775
  ...typeof result.benchmarkScore === "number" ? { benchmarkScore: result.benchmarkScore } : {}
20229
19776
  };
@@ -20442,8 +19989,8 @@ function localEgressStatus(env = process.env, live = {}) {
20442
19989
 
20443
19990
  // packages/surfaces/cli/src/main.ts
20444
19991
  import { spawn as spawn2, spawnSync as spawnSync3 } from "child_process";
20445
- import { accessSync as accessSync2, closeSync as closeSync10, constants as constants2, existsSync as existsSync25, mkdirSync as mkdirSync13, openSync as openSync10, readFileSync as readFileSync27, rmSync as rmSync16, statSync as statSync10 } from "fs";
20446
- import { dirname as dirname15, join as join18, resolve as resolve26 } from "path";
19992
+ import { accessSync as accessSync2, closeSync as closeSync10, constants as constants2, existsSync as existsSync26, mkdirSync as mkdirSync13, openSync as openSync10, readFileSync as readFileSync27, rmSync as rmSync16, statSync as statSync10 } from "fs";
19993
+ import { dirname as dirname15, join as join18, resolve as resolve27 } from "path";
20447
19994
  import { fileURLToPath as fileURLToPath2 } from "url";
20448
19995
 
20449
19996
  // packages/contracts/src/index.ts
@@ -22726,8 +22273,8 @@ function diagnostics(egress) {
22726
22273
  egress
22727
22274
  };
22728
22275
  }
22729
- function isSupportedNodeVersion(version2) {
22730
- const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(version2);
22276
+ function isSupportedNodeVersion(version) {
22277
+ const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(version);
22731
22278
  if (!match)
22732
22279
  return false;
22733
22280
  const major = Number(match[1]);
@@ -22970,7 +22517,7 @@ function isProcessAlive(pid) {
22970
22517
  // packages/local-runtime/local-store-sqlite/src/index.ts
22971
22518
  import { createHash as createHash8, randomUUID } from "node:crypto";
22972
22519
  import { chmodSync as chmodSync5, closeSync as closeSync6, copyFileSync, existsSync as existsSync9, fsyncSync as fsyncSync4, lstatSync as lstatSync4, mkdirSync as mkdirSync5, openSync as openSync6, readFileSync as readFileSync12, readSync as readSync2, realpathSync as realpathSync6, renameSync as renameSync4, rmSync as rmSync6, statfsSync, statSync as statSync6, writeFileSync as writeFileSync6 } from "node:fs";
22973
- import { createRequire as createRequire5 } from "node:module";
22520
+ import { createRequire as createRequire3 } from "node:module";
22974
22521
  import { dirname as dirname6, isAbsolute as isAbsolute6, join as join6, relative as relative7, resolve as resolve12 } from "node:path";
22975
22522
  init_src();
22976
22523
  // schemas/runtime/explorer-projection-v2.schema.json
@@ -23527,7 +23074,7 @@ var explorer_projection_v2_schema_default = {
23527
23074
  };
23528
23075
 
23529
23076
  // packages/local-runtime/local-store-sqlite/src/index.ts
23530
- var runtimeRequire = createRequire5(import.meta.url);
23077
+ var runtimeRequire = createRequire3(import.meta.url);
23531
23078
  var SQLITE_SIDECAR_SUFFIXES = ["", "-wal", "-shm"];
23532
23079
  var LEGACY_MIGRATION_MARKER_FILE = "runtime.sqlite.migration.json";
23533
23080
  var LEGACY_MIGRATION_LOCK_FILE = "runtime.sqlite.migration.lock";
@@ -30786,9 +30333,9 @@ function readExactPackageVersion(root, packageName) {
30786
30333
  return lockVersion;
30787
30334
  for (const manifestPath of packageManifestPaths(root)) {
30788
30335
  const manifest = readJsonFile(manifestPath);
30789
- const version2 = exactVersionFromManifest(manifest, packageName);
30790
- if (version2)
30791
- return version2;
30336
+ const version = exactVersionFromManifest(manifest, packageName);
30337
+ if (version)
30338
+ return version;
30792
30339
  }
30793
30340
  return;
30794
30341
  }
@@ -35338,10 +34885,10 @@ init_src();
35338
34885
  import { createHash as createHash9, randomUUID as randomUUID2 } from "node:crypto";
35339
34886
  import { chmodSync as chmodSync7, closeSync as closeSync7, copyFileSync as copyFileSync2, existsSync as existsSync19, fsyncSync as fsyncSync5, lstatSync as lstatSync9, mkdirSync as mkdirSync10, openSync as openSync8, readFileSync as readFileSync20, readSync as readSync3, realpathSync as realpathSync8, renameSync as renameSync5, rmSync as rmSync12, statfsSync as statfsSync2, statSync as statSync9, writeFileSync as writeFileSync8 } from "node:fs";
35340
34887
  import { readdir, readFile } from "node:fs/promises";
35341
- import { createRequire as createRequire6 } from "node:module";
34888
+ import { createRequire as createRequire4 } from "node:module";
35342
34889
  import { dirname as dirname12, isAbsolute as isAbsolute7, join as join12, relative as relative10, resolve as resolve21 } from "node:path";
35343
34890
  init_src();
35344
- var runtimeRequire2 = createRequire6(import.meta.url);
34891
+ var runtimeRequire2 = createRequire4(import.meta.url);
35345
34892
  var SQLITE_SIDECAR_SUFFIXES2 = ["", "-wal", "-shm"];
35346
34893
  var LEGACY_MIGRATION_MARKER_FILE2 = "runtime.sqlite.migration.json";
35347
34894
  var LEGACY_MIGRATION_LOCK_FILE2 = "runtime.sqlite.migration.lock";
@@ -46510,7 +46057,7 @@ function readCodeFacts(root, worktreeDigest, edgeLimit) {
46510
46057
  }
46511
46058
  function attestCodeGraphBinary(root) {
46512
46059
  const invocation = codeGraphCliInvocation(CODEGRAPH_BINARY, root);
46513
- const version2 = execFileSync9(invocation.command, [...invocation.argsPrefix, "--version"], {
46060
+ const version = execFileSync9(invocation.command, [...invocation.argsPrefix, "--version"], {
46514
46061
  cwd: root,
46515
46062
  encoding: "utf8",
46516
46063
  stdio: ["ignore", "pipe", "pipe"],
@@ -46518,7 +46065,7 @@ function attestCodeGraphBinary(root) {
46518
46065
  }).trim();
46519
46066
  const binaryPath = invocation.argsPrefix[0] ?? invocation.command;
46520
46067
  return {
46521
- version: version2,
46068
+ version,
46522
46069
  binaryDigest: `sha256:${createHash10("sha256").update(readFileSync24(binaryPath)).digest("hex")}`
46523
46070
  };
46524
46071
  }
@@ -47399,6 +46946,12 @@ function recommendationActorKind(input) {
47399
46946
  return "cli";
47400
46947
  }
47401
46948
 
46949
+ // packages/local-runtime/runtime-daemon/src/changeset-authority.ts
46950
+ import { randomBytes as randomBytes5 } from "node:crypto";
46951
+ import { existsSync as existsSync24, readFileSync as readFileSync26 } from "node:fs";
46952
+ import { resolve as resolve25 } from "node:path";
46953
+ init_src();
46954
+
47402
46955
  // packages/local-runtime/runtime-daemon/src/committed-change-acceptance.ts
47403
46956
  import { execFileSync as execFileSync10 } from "node:child_process";
47404
46957
  import { closeSync as closeSync8, constants as fsConstants3, fstatSync as fstatSync3, lstatSync as lstatSync11, openSync as openSync9, readdirSync as readdirSync12, readFileSync as readFileSync25 } from "node:fs";
@@ -47830,12 +47383,546 @@ function sameStrings(left, right) {
47830
47383
  return left.length === right.length && left.every((value, index) => value === right[index]);
47831
47384
  }
47832
47385
 
47386
+ // packages/local-runtime/runtime-daemon/src/changeset-authority.ts
47387
+ class RuntimeUpdateInputError extends Error {
47388
+ }
47389
+ function decodeRuntimeWorktreeDigestProfile(value, field) {
47390
+ switch (value) {
47391
+ case "repository":
47392
+ case "architecture-documentation-projection":
47393
+ return value;
47394
+ default:
47395
+ throw new RuntimeUpdateInputError(`${field} must be repository or architecture-documentation-projection`);
47396
+ }
47397
+ }
47398
+ function decodeRuntimePlanUpdateInput(value) {
47399
+ const input = runtimeUpdateInputRecord(value, "plan_update input");
47400
+ if (typeof input.id !== "string" || input.id.length === 0) {
47401
+ throw new RuntimeUpdateInputError("plan_update id must be a non-empty string");
47402
+ }
47403
+ if (!Array.isArray(input.operations)) {
47404
+ throw new RuntimeUpdateInputError("plan_update operations must be an array");
47405
+ }
47406
+ if (input.approvalChannel !== undefined && input.approvalChannel !== "mcp") {
47407
+ throw new RuntimeUpdateInputError("plan_update approvalChannel must be mcp");
47408
+ }
47409
+ let worktreeDigestPrecondition;
47410
+ if (input.worktreeDigestPrecondition !== undefined) {
47411
+ const precondition = runtimeUpdateInputRecord(input.worktreeDigestPrecondition, "plan_update worktreeDigestPrecondition");
47412
+ const profile = decodeRuntimeWorktreeDigestProfile(precondition.profile, "plan_update worktreeDigestPrecondition.profile");
47413
+ if (profile !== "architecture-documentation-projection") {
47414
+ throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.profile must be architecture-documentation-projection");
47415
+ }
47416
+ if (typeof precondition.expectedDigest !== "string" || precondition.expectedDigest.length === 0) {
47417
+ throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.expectedDigest must be a non-empty string");
47418
+ }
47419
+ worktreeDigestPrecondition = { profile, expectedDigest: precondition.expectedDigest };
47420
+ }
47421
+ return {
47422
+ id: input.id,
47423
+ operations: input.operations,
47424
+ ...input.approvalChannel === "mcp" ? { approvalChannel: "mcp" } : {},
47425
+ ...input.reason === undefined ? {} : { reason: input.reason },
47426
+ ...worktreeDigestPrecondition === undefined ? {} : { worktreeDigestPrecondition }
47427
+ };
47428
+ }
47429
+ function decodeRuntimeApplyUpdateInput(value) {
47430
+ const input = runtimeUpdateInputRecord(value, "apply_update input");
47431
+ if (typeof input.id !== "string" || input.id.length === 0) {
47432
+ throw new RuntimeUpdateInputError("apply_update id must be a non-empty string");
47433
+ }
47434
+ if (typeof input.approved !== "boolean") {
47435
+ throw new RuntimeUpdateInputError("apply_update approved must be a boolean");
47436
+ }
47437
+ if (typeof input.expectedWorktreeDigest !== "string" || input.expectedWorktreeDigest.length === 0) {
47438
+ throw new RuntimeUpdateInputError("apply_update expectedWorktreeDigest must be a non-empty string");
47439
+ }
47440
+ const worktreeDigestProfile = input.worktreeDigestProfile === undefined ? undefined : decodeRuntimeWorktreeDigestProfile(input.worktreeDigestProfile, "apply_update worktreeDigestProfile");
47441
+ return {
47442
+ id: input.id,
47443
+ approved: input.approved,
47444
+ expectedWorktreeDigest: input.expectedWorktreeDigest,
47445
+ ...worktreeDigestProfile === undefined ? {} : { worktreeDigestProfile },
47446
+ ...input.projectionApplyReceipt === undefined ? {} : { projectionApplyReceipt: input.projectionApplyReceipt }
47447
+ };
47448
+ }
47449
+ function runtimeUpdateInputRecord(value, field) {
47450
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
47451
+ throw new RuntimeUpdateInputError(`${field} must be an object`);
47452
+ }
47453
+ return value;
47454
+ }
47455
+
47456
+ class ChangeSetAuthorityService {
47457
+ context;
47458
+ readModelStore;
47459
+ localStore;
47460
+ changeSetEngine;
47461
+ architectureLedger;
47462
+ changesets = new Map;
47463
+ changeSetRoots = new Map;
47464
+ mcpChangeSets = new Set;
47465
+ mcpApprovals = new Map;
47466
+ changeSetWorktreeDigestProfiles = new Map;
47467
+ constructor(context) {
47468
+ this.context = context;
47469
+ this.readModelStore = context.readModelStore;
47470
+ this.localStore = context.localStore;
47471
+ this.changeSetEngine = context.changeSetEngine;
47472
+ this.architectureLedger = context.architectureLedger;
47473
+ }
47474
+ clearApprovals() {
47475
+ this.mcpApprovals.clear();
47476
+ }
47477
+ async planPracticeWaiver(root, input) {
47478
+ this.assertRunning();
47479
+ const session = await this.openSession(root);
47480
+ const model = await this.readModelStore.validateModel(session.workspace);
47481
+ let ownerRegistry;
47482
+ try {
47483
+ ownerRegistry = loadPracticeWaiverOwnerRegistry(session.workspace.root);
47484
+ } catch (error) {
47485
+ return errorEnvelope("practices.waive", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
47486
+ }
47487
+ const waiver = {
47488
+ schemaVersion: "archcontext.practice-waiver/v1",
47489
+ practiceId: input.practiceId,
47490
+ ...input.checkId === undefined ? {} : { checkId: input.checkId },
47491
+ scope: {
47492
+ ...input.pathGlobs && input.pathGlobs.length > 0 ? { pathGlobs: input.pathGlobs } : {},
47493
+ ...input.subjects && input.subjects.length > 0 ? { subjects: input.subjects } : {}
47494
+ },
47495
+ owner: input.owner,
47496
+ reason: input.reason,
47497
+ createdAt: input.createdAt ?? this.clock(),
47498
+ reviewAt: input.reviewAt,
47499
+ expiresAt: input.expiresAt,
47500
+ evidenceDigest: input.evidenceDigest
47501
+ };
47502
+ let waiverId;
47503
+ try {
47504
+ validatePracticeWaiver(waiver, "practice waiver input", { allowedOwners: ownerRegistry.owners });
47505
+ waiverId = safePracticeWaiverId(input.waiverId, waiver);
47506
+ } catch (error) {
47507
+ return errorEnvelope("practices.waive", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
47508
+ }
47509
+ const path = `.archcontext/waivers/${waiverId}.json`;
47510
+ const absolute = resolve25(session.workspace.root, path);
47511
+ const body = `${JSON.stringify(waiver, null, 2)}
47512
+ `;
47513
+ const expectedHash = existsSync24(absolute) ? digestJson({ body: readFileSync26(absolute, "utf8") }) : "missing";
47514
+ const draft = this.changeSetEngine.plan({
47515
+ id: input.id ?? `changeset.practice-waiver-${waiverId.replace(/[^A-Za-z0-9_-]/g, "-")}`,
47516
+ base: {
47517
+ headSha: session.workspace.headSha,
47518
+ worktreeDigest: session.snapshot.worktreeDigest,
47519
+ modelDigest: model.modelDigest
47520
+ },
47521
+ reason: { taskSessionId: input.taskSessionId ?? "task_runtime" },
47522
+ operations: [{ op: "write_waiver", path, expectedHash, body }]
47523
+ });
47524
+ this.changesets.set(draft.id, draft);
47525
+ this.changeSetRoots.set(draft.id, canonicalRepositoryRoot(root));
47526
+ this.changeSetWorktreeDigestProfiles.set(draft.id, "repository");
47527
+ this.mcpChangeSets.delete(draft.id);
47528
+ return okEnvelope("practices.waive", {
47529
+ schemaVersion: "archcontext.practice-waiver-plan/v1",
47530
+ waiver,
47531
+ waiverDigest: digestJson(waiver),
47532
+ ownerRegistry,
47533
+ path,
47534
+ draft,
47535
+ preview: this.changeSetEngine.preview(session.workspace.root, draft)
47536
+ });
47537
+ }
47538
+ async planUpdate(root, rawInput) {
47539
+ this.assertRunning();
47540
+ let input;
47541
+ try {
47542
+ input = decodeRuntimePlanUpdateInput(rawInput);
47543
+ } catch (error) {
47544
+ if (error instanceof RuntimeUpdateInputError) {
47545
+ return errorEnvelope("plan_update", "AC_SCHEMA_INVALID", error.message);
47546
+ }
47547
+ throw error;
47548
+ }
47549
+ const session = await this.openSession(root);
47550
+ const model = await this.readModelStore.validateModel(session.workspace);
47551
+ const worktreeDigestProfile = input.worktreeDigestPrecondition?.profile ?? "repository";
47552
+ const worktreeDigest = runtimeWorktreeDigest(root, worktreeDigestProfile);
47553
+ if (input.worktreeDigestPrecondition && input.worktreeDigestPrecondition.expectedDigest !== worktreeDigest) {
47554
+ throw new Error("Worktree digest changed before plan");
47555
+ }
47556
+ const draft = this.changeSetEngine.plan({
47557
+ id: input.id,
47558
+ base: {
47559
+ headSha: session.workspace.headSha,
47560
+ worktreeDigest,
47561
+ modelDigest: model.modelDigest
47562
+ },
47563
+ reason: input.reason ?? { taskSessionId: "task_runtime" },
47564
+ operations: input.operations
47565
+ });
47566
+ this.changesets.set(draft.id, draft);
47567
+ this.changeSetRoots.set(draft.id, canonicalRepositoryRoot(root));
47568
+ this.changeSetWorktreeDigestProfiles.set(draft.id, worktreeDigestProfile);
47569
+ if (input.approvalChannel === "mcp")
47570
+ this.mcpChangeSets.add(draft.id);
47571
+ else
47572
+ this.mcpChangeSets.delete(draft.id);
47573
+ return okEnvelope("plan_update", {
47574
+ draft,
47575
+ changeSetDigest: digestJson(draft),
47576
+ preview: this.changeSetEngine.preview(root, draft)
47577
+ });
47578
+ }
47579
+ async approveMcpProjection(root, input) {
47580
+ this.assertRunning();
47581
+ try {
47582
+ validateProjectionInvocation(input);
47583
+ if (!projectionInvocationWrites(input))
47584
+ throw new Error("Projection approval requires an apply, adopt or recover invocation");
47585
+ assertProjectionInvocationSnapshot(root, input);
47586
+ } catch (error) {
47587
+ return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
47588
+ }
47589
+ const now = Date.parse(this.clock());
47590
+ if (!Number.isFinite(now))
47591
+ return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", "Approval clock is invalid");
47592
+ for (const [key, grant] of this.mcpApprovals)
47593
+ if (grant.expiresAt <= now)
47594
+ this.mcpApprovals.delete(key);
47595
+ if (this.mcpApprovals.size >= 256)
47596
+ return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", "Too many outstanding approvals; consume an approval or wait for expiry");
47597
+ const approvalToken = randomBytes5(32).toString("hex");
47598
+ const expiresAt = now + 5 * 60000;
47599
+ this.mcpApprovals.set(digestJson(approvalToken), { scope: "projection", root: canonicalRepositoryRoot(root), invocationDigest: digestJson(input), expiresAt });
47600
+ return okEnvelope("projection.approve", { approvalToken, expiresAt: new Date(expiresAt).toISOString() });
47601
+ }
47602
+ async mcpProjection(root, input, approvalToken) {
47603
+ this.assertRunning();
47604
+ try {
47605
+ validateProjectionInvocation(input);
47606
+ } catch (error) {
47607
+ return errorEnvelope("projection", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
47608
+ }
47609
+ if (projectionInvocationWrites(input)) {
47610
+ const denied = () => errorEnvelope("projection", "AC_USER_CONFIRMATION_REQUIRED", "A fresh one-time token from archctx projection approve is required");
47611
+ if (typeof approvalToken !== "string" || !/^[a-f0-9]{64}$/.test(approvalToken))
47612
+ return denied();
47613
+ const key = digestJson(approvalToken);
47614
+ const grant = this.mcpApprovals.get(key);
47615
+ this.mcpApprovals.delete(key);
47616
+ const now = Date.parse(this.clock());
47617
+ if (!grant || grant.scope !== "projection" || !Number.isFinite(now) || grant.expiresAt <= now || grant.root !== canonicalRepositoryRoot(root) || grant.invocationDigest !== digestJson(input))
47618
+ return denied();
47619
+ }
47620
+ return this.projection(root, input);
47621
+ }
47622
+ async approveMcpUpdate(root, input) {
47623
+ this.assertRunning();
47624
+ const draft = this.changesets.get(input?.id);
47625
+ const canonicalRoot = canonicalRepositoryRoot(root);
47626
+ const now = Date.parse(this.clock());
47627
+ if (!draft || this.changeSetRoots.get(input.id) !== canonicalRoot || this.changeSetWorktreeDigestProfiles.get(input.id) !== "repository" || input.expectedChangeSetDigest !== digestJson(draft) || input.expectedWorktreeDigest !== draft.base.worktreeDigest || input.expectedWorktreeDigest !== runtimeWorktreeDigest(root, "repository") || !Number.isFinite(now)) {
47628
+ return errorEnvelope("approve_mcp_update", "AC_PRECONDITION_FAILED", "Approval must match the current ChangeSet preview and repository");
47629
+ }
47630
+ for (const [key, grant] of this.mcpApprovals)
47631
+ if (grant.expiresAt <= now)
47632
+ this.mcpApprovals.delete(key);
47633
+ if (this.mcpApprovals.size >= 256)
47634
+ return errorEnvelope("approve_mcp_update", "AC_PRECONDITION_FAILED", "Too many outstanding approvals; consume an approval or wait for expiry");
47635
+ const approvalToken = randomBytes5(32).toString("hex");
47636
+ const expiresAt = now + 5 * 60000;
47637
+ this.mcpApprovals.set(digestJson(approvalToken), {
47638
+ scope: "changeset",
47639
+ root: canonicalRoot,
47640
+ id: input.id,
47641
+ draftDigest: input.expectedChangeSetDigest,
47642
+ worktreeDigest: input.expectedWorktreeDigest,
47643
+ expiresAt
47644
+ });
47645
+ return okEnvelope("approve_mcp_update", { approvalToken, expiresAt: new Date(expiresAt).toISOString() });
47646
+ }
47647
+ async applyMcpUpdate(root, input) {
47648
+ this.assertRunning();
47649
+ const denied = () => errorEnvelope("apply_update", "AC_USER_CONFIRMATION_REQUIRED", "A fresh one-time token from archctx approve is required");
47650
+ if (typeof input?.approvalToken !== "string" || !/^[a-f0-9]{64}$/.test(input.approvalToken))
47651
+ return denied();
47652
+ const key = digestJson(input.approvalToken);
47653
+ const grant = this.mcpApprovals.get(key);
47654
+ if (!grant)
47655
+ return denied();
47656
+ this.mcpApprovals.delete(key);
47657
+ const draft = this.changesets.get(input.id);
47658
+ const now = Date.parse(this.clock());
47659
+ if (grant.scope !== "changeset" || !Number.isFinite(now) || grant.expiresAt <= now || grant.root !== canonicalRepositoryRoot(root) || grant.id !== input.id || grant.worktreeDigest !== input.expectedWorktreeDigest || !draft || grant.draftDigest !== digestJson(draft))
47660
+ return denied();
47661
+ return this.applyAuthorizedUpdate(root, { id: input.id, expectedWorktreeDigest: input.expectedWorktreeDigest, approved: true });
47662
+ }
47663
+ async applyUpdate(root, rawInput) {
47664
+ this.assertRunning();
47665
+ if (this.mcpChangeSets.has(rawInput?.id)) {
47666
+ return errorEnvelope("apply_update", "AC_USER_CONFIRMATION_REQUIRED", "MCP ChangeSets require a one-time approval token through applyMcpUpdate");
47667
+ }
47668
+ return this.applyAuthorizedUpdate(root, rawInput);
47669
+ }
47670
+ async applyAuthorizedUpdate(root, rawInput) {
47671
+ this.assertRunning();
47672
+ let input;
47673
+ try {
47674
+ input = decodeRuntimeApplyUpdateInput(rawInput);
47675
+ } catch (error) {
47676
+ if (error instanceof RuntimeUpdateInputError) {
47677
+ return errorEnvelope("apply_update", "AC_SCHEMA_INVALID", error.message);
47678
+ }
47679
+ throw error;
47680
+ }
47681
+ return this.withWriter(async () => {
47682
+ const draft = this.changesets.get(input.id);
47683
+ if (!draft)
47684
+ throw new Error(`Unknown ChangeSet: ${input.id}`);
47685
+ const plannedProfile = this.changeSetWorktreeDigestProfiles.get(input.id);
47686
+ if (!plannedProfile)
47687
+ throw new Error("ChangeSet worktree digest profile missing before apply");
47688
+ const requestedProfile = input.worktreeDigestProfile ?? "repository";
47689
+ if (requestedProfile !== plannedProfile)
47690
+ throw new Error("ChangeSet worktree digest profile changed before apply");
47691
+ const current = runtimeWorktreeDigest(root, plannedProfile);
47692
+ if (current !== input.expectedWorktreeDigest)
47693
+ throw new Error("Worktree digest changed before apply");
47694
+ const session = await this.openSession(root);
47695
+ if (draft.base.headSha !== session.workspace.headSha)
47696
+ throw new Error("ChangeSet HEAD changed before apply");
47697
+ if (draft.base.worktreeDigest !== current)
47698
+ throw new Error("ChangeSet worktree digest changed before apply");
47699
+ const currentModel = await this.readModelStore.validateModel(session.workspace);
47700
+ const baseErrors = baseModelBlockingErrors(currentModel);
47701
+ if (baseErrors.length > 0) {
47702
+ throw new Error(`ChangeSet base model is invalid: ${baseErrors.join("; ")}`);
47703
+ }
47704
+ if (draft.base.modelDigest !== currentModel.modelDigest)
47705
+ throw new Error("ChangeSet model digest changed before apply");
47706
+ if (input.projectionApplyReceipt && await this.localStore.inspectProjectionApplyReceipt(input.projectionApplyReceipt.identity.lookupKey)) {
47707
+ return errorEnvelope("apply_update", "AC_PRECONDITION_FAILED", "committed projection receipt requires explicit projection recover");
47708
+ }
47709
+ const approved = input.approved ? this.changeSetEngine.approve(draft) : draft;
47710
+ const transitionBase = captureModelTransitionBase(root, approved);
47711
+ let ledgerAppend;
47712
+ let appliedJournalId;
47713
+ const writesLedger = architectureLedgerWriteAppendsEvents(this.architectureLedger.writeMode);
47714
+ const result = await this.changeSetEngine.apply(root, approved, {
47715
+ approved: input.approved,
47716
+ afterModelValidatedBeforeCommit: async ({ journalId }) => {
47717
+ appliedJournalId = journalId;
47718
+ if (transitionBase && journalId)
47719
+ await recordModelTransitionEvidence(this.localStore, root, journalId, transitionBase);
47720
+ if (journalId && this.context.projectionPlannedDrafts.has(draft))
47721
+ await this.localStore.recordChangeSetProjectionOwner(journalId);
47722
+ if (input.projectionApplyReceipt) {
47723
+ if (!journalId)
47724
+ throw new Error("projection apply receipt requires a durable ChangeSet journal");
47725
+ await this.localStore.recordProjectionApplyReceipt(journalId, input.projectionApplyReceipt);
47726
+ }
47727
+ if (writesLedger) {
47728
+ const appended = await this.appendAppliedChangeSetToArchitectureLedger(root, session, approved, journalId);
47729
+ ledgerAppend = {
47730
+ status: "appended",
47731
+ appendedEventCount: appended.appendedEvents.length,
47732
+ duplicateEventCount: appended.duplicateEvents.length,
47733
+ graphDigest: appended.graphDigest,
47734
+ entityCount: appended.entityCount,
47735
+ relationCount: appended.relationCount,
47736
+ constraintCount: appended.constraintCount
47737
+ };
47738
+ }
47739
+ return { journalCommitted: writesLedger && Boolean(journalId) };
47740
+ }
47741
+ });
47742
+ return okEnvelope("apply_update", {
47743
+ ...result,
47744
+ ...appliedJournalId ? { journalId: appliedJournalId } : {},
47745
+ architectureLedger: {
47746
+ ...this.architectureLedger,
47747
+ append: writesLedger ? ledgerAppend ?? { status: "not-appended" } : { status: "not-applicable" }
47748
+ }
47749
+ });
47750
+ });
47751
+ }
47752
+ async appendAppliedChangeSetToArchitectureLedger(root, session, draft, journalId) {
47753
+ const paths = runtimeStatePaths(root);
47754
+ const scope = {
47755
+ repository: {
47756
+ repositoryId: session.workspace.repositoryId,
47757
+ storageRepositoryId: paths.storageRepositoryId
47758
+ },
47759
+ worktree: {
47760
+ workspaceId: paths.workspaceId,
47761
+ storageWorkspaceId: paths.storageWorkspaceId,
47762
+ branch: readCurrentBranch(root),
47763
+ headSha: session.workspace.headSha,
47764
+ worktreeDigest: computeWorktreeDigest(root)
47765
+ }
47766
+ };
47767
+ const plan = planChangeSetApplyToArchitectureLedgerEvent({
47768
+ ...scope,
47769
+ draft,
47770
+ files: listModelFiles(root),
47771
+ previousEvidenceState: await this.localStore.replayArchitectureLedgerEvidence(scope),
47772
+ createdAt: this.clock(),
47773
+ writeMode: this.architectureLedger.writeMode === "ledger-with-projection" ? "ledger-with-projection" : "dual",
47774
+ command: "archctx apply"
47775
+ });
47776
+ if (journalId)
47777
+ await this.localStore.recordChangeSetLedgerPlan(journalId, { event: plan.event });
47778
+ const appendInput = { writer: "runtime-daemon", events: [plan.event] };
47779
+ const result = await this.appendArchitectureEventsWithFeed(root, appendInput, journalId);
47780
+ return result;
47781
+ }
47782
+ async acceptCommittedChange(root, rawInput) {
47783
+ this.assertRunning();
47784
+ let input;
47785
+ try {
47786
+ input = decodeAcceptCommittedChangeInput(rawInput);
47787
+ } catch (error) {
47788
+ if (error instanceof AcceptCommittedChangeInputError)
47789
+ return errorEnvelope("ledger.accept-committed", "AC_SCHEMA_INVALID", error.message);
47790
+ throw error;
47791
+ }
47792
+ if (this.architectureLedger.readMode !== "yaml" || this.architectureLedger.writeMode !== "yaml") {
47793
+ return errorEnvelope("ledger.accept-committed", "AC_PRECONDITION_FAILED", "committed YAML acceptance requires YAML read and write authority");
47794
+ }
47795
+ return this.withWriter(async () => {
47796
+ try {
47797
+ const canonicalRoot = canonicalRepositoryRoot(root);
47798
+ const journals = [];
47799
+ for (const ref of input.journals)
47800
+ journals.push(await this.localStore.readCommittedChangeSet(canonicalRoot, ref.journalId));
47801
+ const model = loadNativeModelFromArchContext(canonicalRoot);
47802
+ const worktreeDigest = architectureDocumentationProjectionWorktreeDigest(canonicalRoot, model);
47803
+ const projection3 = buildArchitectureDocsProjection(this.projectionHost(), canonicalRoot, new Date(0).toISOString(), "repo-harness/v1");
47804
+ const scope = acceptedCommittedChangeScope(canonicalRoot, worktreeDigest, resolveAcceptanceHeadSha(canonicalRoot));
47805
+ const manifestWrite = await this.localStore.readLatestCommittedChangeSetFile(canonicalRoot, "docs/architecture/.projection-manifest.json");
47806
+ const acceptance = planCommittedChangeAcceptance(canonicalRoot, {
47807
+ requested: input.journals,
47808
+ journals,
47809
+ model,
47810
+ existingFiles: projection3.loaded.existingFiles,
47811
+ latestJournaledManifest: manifestWrite,
47812
+ projection: projection3.plan,
47813
+ currentEvidence: projection3.snapshotEvidence,
47814
+ projectionWorktreeDigest: worktreeDigest,
47815
+ scope
47816
+ });
47817
+ if (!input.approved) {
47818
+ return okEnvelope("ledger.accept-committed", { status: "preview", plan: acceptance.plan, acceptancePlanId: acceptance.acceptancePlanId, expectedWorktreeDigest: worktreeDigest });
47819
+ }
47820
+ if (input.expectedWorktreeDigest !== worktreeDigest)
47821
+ throw new Error("accepted ChangeSet expected worktree digest mismatch");
47822
+ if (input.acceptancePlanId !== acceptance.acceptancePlanId)
47823
+ throw new Error("accepted ChangeSet acceptance plan changed since preview");
47824
+ const accepted = (event2, replayed) => {
47825
+ const recorded = acceptedChangeFromEventV2(event2);
47826
+ if (!recorded || !event2.eventHash)
47827
+ throw new Error("committed ChangeSet acceptance readback failed");
47828
+ return okEnvelope("ledger.accept-committed", {
47829
+ status: "accepted",
47830
+ replayed,
47831
+ acceptedChange: recorded.acceptedChange,
47832
+ acceptancePlanId: recorded.acceptancePlanId,
47833
+ journalIds: input.journals.map((journal) => journal.journalId),
47834
+ eventHash: event2.eventHash,
47835
+ fileSetDigest: acceptance.plan.fileSetDigest
47836
+ });
47837
+ };
47838
+ const existing = await this.localStore.readArchitectureEvent({ ...scope, eventId: acceptance.acceptedChange.eventId });
47839
+ if (existing) {
47840
+ if (acceptedChangeFromEventV2(existing)?.acceptancePlanId === acceptance.acceptancePlanId)
47841
+ return accepted(existing, true);
47842
+ throw new Error(`committed ChangeSet already has a different acceptance event at this snapshot: ${existing.eventId}`);
47843
+ }
47844
+ const ledgerGraphDigest = architectureLedgerStateDigest(await this.localStore.readArchitectureLedgerState(scope));
47845
+ const event = acceptedCommittedChangeEventV2({ acceptance, scope, ledgerGraphDigest, timestamp: this.clock() });
47846
+ const appended = await this.appendArchitectureEventsWithFeed(canonicalRoot, { writer: "runtime-daemon", events: [event] });
47847
+ if (appended.appendedEvents.length !== 1)
47848
+ throw new Error("committed ChangeSet acceptance event was not appended");
47849
+ const readback = await this.localStore.readArchitectureEvent({ ...scope, eventId: event.eventId });
47850
+ if (!readback || readback.eventType !== event.eventType || readback.payloadVersion !== event.payloadVersion) {
47851
+ throw new Error("committed ChangeSet acceptance readback failed");
47852
+ }
47853
+ return accepted(readback, false);
47854
+ } catch (error) {
47855
+ return errorEnvelope("ledger.accept-committed", "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
47856
+ }
47857
+ });
47858
+ }
47859
+ assertRunning() {
47860
+ this.context.assertRunning();
47861
+ }
47862
+ clock() {
47863
+ return this.context.clock();
47864
+ }
47865
+ openSession(root) {
47866
+ return this.context.openSession(root);
47867
+ }
47868
+ withWriter(fn) {
47869
+ return this.context.withWriter(fn);
47870
+ }
47871
+ appendArchitectureEventsWithFeed(root, input, journalId) {
47872
+ return this.context.appendArchitectureEventsWithFeed(root, input, journalId);
47873
+ }
47874
+ projectionHost() {
47875
+ return this.context.projectionHost();
47876
+ }
47877
+ projection(root, input) {
47878
+ return this.context.projection(root, input);
47879
+ }
47880
+ }
47881
+ function runtimeWorktreeDigest(root, profile) {
47882
+ switch (profile) {
47883
+ case "repository":
47884
+ return computeWorktreeDigest(root);
47885
+ case "architecture-documentation-projection":
47886
+ return architectureDocumentationProjectionWorktreeDigest(root, loadNativeModelFromArchContext(root));
47887
+ default:
47888
+ throw new RuntimeUpdateInputError(`unsupported worktree digest profile: ${String(profile)}`);
47889
+ }
47890
+ }
47891
+ function acceptedCommittedChangeScope(root, worktreeDigest, headSha) {
47892
+ const paths = runtimeStatePaths(root);
47893
+ return {
47894
+ repository: { repositoryId: repositoryFingerprint(root), storageRepositoryId: paths.storageRepositoryId },
47895
+ worktree: {
47896
+ workspaceId: projectionWorkspaceId(root),
47897
+ storageWorkspaceId: paths.storageWorkspaceId,
47898
+ branch: readCurrentBranch(root),
47899
+ headSha,
47900
+ worktreeDigest
47901
+ }
47902
+ };
47903
+ }
47904
+ function safePracticeWaiverId(explicit, waiver) {
47905
+ const explicitTrimmed = explicit?.trim();
47906
+ if (explicitTrimmed && (explicitTrimmed === "." || explicitTrimmed === ".." || explicitTrimmed.includes("/") || explicitTrimmed.includes("\\"))) {
47907
+ throw new Error("practice-waiver-id-invalid");
47908
+ }
47909
+ const evidencePrefix = waiver.evidenceDigest.startsWith("sha256:") ? waiver.evidenceDigest.slice("sha256:".length, "sha256:".length + 12) : waiver.evidenceDigest.slice(0, 12);
47910
+ const candidate = (explicitTrimmed || [waiver.practiceId.replace(/\./g, "-"), waiver.checkId ?? "all", evidencePrefix].join("-")).replace(/[^A-Za-z0-9_.-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 96);
47911
+ if (!candidate || candidate === "." || candidate === ".." || candidate.includes("/") || candidate.includes("\\")) {
47912
+ throw new Error("practice-waiver-id-invalid");
47913
+ }
47914
+ return candidate;
47915
+ }
47916
+ function architectureLedgerWriteAppendsEvents(mode) {
47917
+ return mode === "dual" || mode === "ledger-with-projection";
47918
+ }
47919
+
47833
47920
  // packages/local-runtime/runtime-daemon/src/rpc-server.ts
47834
47921
  init_src();
47835
47922
  import { createServer as createServer2 } from "node:http";
47836
47923
  import { closeSync as closeSync9, mkdirSync as mkdirSync12, rmSync as rmSync15 } from "node:fs";
47837
47924
  import { dirname as dirname14 } from "node:path";
47838
- import { randomBytes as randomBytes5 } from "node:crypto";
47925
+ import { randomBytes as randomBytes6 } from "node:crypto";
47839
47926
  var DEFAULT_DAEMON_IDLE_TIMEOUT_MS = 30 * 60000;
47840
47927
  var DAEMON_IDLE_TIMEOUT_ENV = "ARCHCONTEXT_DAEMON_IDLE_TIMEOUT_MS";
47841
47928
  function resolveDaemonIdleTimeoutMs(explicit) {
@@ -47905,7 +47992,7 @@ class ArchctxRuntimeRpcServer {
47905
47992
  mkdirSync12(dirname14(connectionPath), { recursive: true });
47906
47993
  mkdirSync12(dirname14(lockPath), { recursive: true });
47907
47994
  this.lockFd = acquireDaemonLock(lockPath, root);
47908
- const token = this.options.token ?? randomBytes5(18).toString("base64url");
47995
+ const token = this.options.token ?? randomBytes6(18).toString("base64url");
47909
47996
  const server = createServer2((request, response) => {
47910
47997
  this.handleRequest(request, response).catch((error) => {
47911
47998
  writeJson(response, 500, { schemaVersion: RUNTIME_RPC_VERSION, ok: false, error: error instanceof Error ? error.message : String(error) });
@@ -48171,10 +48258,9 @@ async function readRpcRequestBody(request, limits) {
48171
48258
  }
48172
48259
 
48173
48260
  // packages/local-runtime/runtime-daemon/src/index.ts
48174
- import { randomBytes as randomBytes6 } from "node:crypto";
48175
48261
  import { execFileSync as execFileSync11 } from "node:child_process";
48176
- import { existsSync as existsSync24, readFileSync as readFileSync26 } from "node:fs";
48177
- import { resolve as resolve25 } from "node:path";
48262
+ import { existsSync as existsSync25 } from "node:fs";
48263
+ import { resolve as resolve26 } from "node:path";
48178
48264
  init_src();
48179
48265
 
48180
48266
  // packages/local-runtime/runtime-daemon/src/egress.ts
@@ -48244,75 +48330,6 @@ function localEgressStatus2(env = process.env, live = {}) {
48244
48330
  }
48245
48331
 
48246
48332
  // packages/local-runtime/runtime-daemon/src/index.ts
48247
- class RuntimeUpdateInputError extends Error {
48248
- }
48249
- function decodeRuntimeWorktreeDigestProfile(value, field) {
48250
- switch (value) {
48251
- case "repository":
48252
- case "architecture-documentation-projection":
48253
- return value;
48254
- default:
48255
- throw new RuntimeUpdateInputError(`${field} must be repository or architecture-documentation-projection`);
48256
- }
48257
- }
48258
- function decodeRuntimePlanUpdateInput(value) {
48259
- const input = runtimeUpdateInputRecord(value, "plan_update input");
48260
- if (typeof input.id !== "string" || input.id.length === 0) {
48261
- throw new RuntimeUpdateInputError("plan_update id must be a non-empty string");
48262
- }
48263
- if (!Array.isArray(input.operations)) {
48264
- throw new RuntimeUpdateInputError("plan_update operations must be an array");
48265
- }
48266
- if (input.approvalChannel !== undefined && input.approvalChannel !== "mcp") {
48267
- throw new RuntimeUpdateInputError("plan_update approvalChannel must be mcp");
48268
- }
48269
- let worktreeDigestPrecondition;
48270
- if (input.worktreeDigestPrecondition !== undefined) {
48271
- const precondition = runtimeUpdateInputRecord(input.worktreeDigestPrecondition, "plan_update worktreeDigestPrecondition");
48272
- const profile = decodeRuntimeWorktreeDigestProfile(precondition.profile, "plan_update worktreeDigestPrecondition.profile");
48273
- if (profile !== "architecture-documentation-projection") {
48274
- throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.profile must be architecture-documentation-projection");
48275
- }
48276
- if (typeof precondition.expectedDigest !== "string" || precondition.expectedDigest.length === 0) {
48277
- throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.expectedDigest must be a non-empty string");
48278
- }
48279
- worktreeDigestPrecondition = { profile, expectedDigest: precondition.expectedDigest };
48280
- }
48281
- return {
48282
- id: input.id,
48283
- operations: input.operations,
48284
- ...input.approvalChannel === "mcp" ? { approvalChannel: "mcp" } : {},
48285
- ...input.reason === undefined ? {} : { reason: input.reason },
48286
- ...worktreeDigestPrecondition === undefined ? {} : { worktreeDigestPrecondition }
48287
- };
48288
- }
48289
- function decodeRuntimeApplyUpdateInput(value) {
48290
- const input = runtimeUpdateInputRecord(value, "apply_update input");
48291
- if (typeof input.id !== "string" || input.id.length === 0) {
48292
- throw new RuntimeUpdateInputError("apply_update id must be a non-empty string");
48293
- }
48294
- if (typeof input.approved !== "boolean") {
48295
- throw new RuntimeUpdateInputError("apply_update approved must be a boolean");
48296
- }
48297
- if (typeof input.expectedWorktreeDigest !== "string" || input.expectedWorktreeDigest.length === 0) {
48298
- throw new RuntimeUpdateInputError("apply_update expectedWorktreeDigest must be a non-empty string");
48299
- }
48300
- const worktreeDigestProfile = input.worktreeDigestProfile === undefined ? undefined : decodeRuntimeWorktreeDigestProfile(input.worktreeDigestProfile, "apply_update worktreeDigestProfile");
48301
- return {
48302
- id: input.id,
48303
- approved: input.approved,
48304
- expectedWorktreeDigest: input.expectedWorktreeDigest,
48305
- ...worktreeDigestProfile === undefined ? {} : { worktreeDigestProfile },
48306
- ...input.projectionApplyReceipt === undefined ? {} : { projectionApplyReceipt: input.projectionApplyReceipt }
48307
- };
48308
- }
48309
- function runtimeUpdateInputRecord(value, field) {
48310
- if (!value || typeof value !== "object" || Array.isArray(value)) {
48311
- throw new RuntimeUpdateInputError(`${field} must be an object`);
48312
- }
48313
- return value;
48314
- }
48315
-
48316
48333
  class ArchitectureLedgerReadModelStore {
48317
48334
  fallback;
48318
48335
  localStore;
@@ -48401,12 +48418,8 @@ class ArchctxDaemon {
48401
48418
  maxRepoSessions;
48402
48419
  composition;
48403
48420
  sessions = new Map;
48404
- changesets = new Map;
48405
- changeSetRoots = new Map;
48406
- mcpChangeSets = new Set;
48421
+ changeSetAuthority;
48407
48422
  projectionPlannedDrafts = new WeakSet;
48408
- mcpApprovals = new Map;
48409
- changeSetWorktreeDigestProfiles = new Map;
48410
48423
  auditRunAbortControllers = new Map;
48411
48424
  landscapes;
48412
48425
  explorerServer;
@@ -48538,6 +48551,20 @@ class ArchctxDaemon {
48538
48551
  worktreeDigest: runtimeWorktreeDigest,
48539
48552
  loadSourceChanges: loadCapabilitySourceChangesSinceStamps
48540
48553
  });
48554
+ this.changeSetAuthority = new ChangeSetAuthorityService({
48555
+ projectionPlannedDrafts: this.projectionPlannedDrafts,
48556
+ assertRunning: () => this.assertRunning(),
48557
+ clock: this.clock,
48558
+ openSession: (root) => this.openSession(root),
48559
+ withWriter: (run) => this.withWriter(run),
48560
+ appendArchitectureEventsWithFeed: (root, input, journalId) => this.appendArchitectureEventsWithFeed(root, input, journalId),
48561
+ projectionHost: () => this.projectionHost(),
48562
+ projection: (root, input) => this.projection(root, input),
48563
+ readModelStore: this.readModelStore,
48564
+ localStore: this.localStore,
48565
+ changeSetEngine: this.changeSetEngine,
48566
+ architectureLedger: this.architectureLedger
48567
+ });
48541
48568
  this.developerReviewRuns = new DeveloperReviewRunService(() => this.assertRunning(), this.clock);
48542
48569
  this.externalDocumentation = deps.externalDocumentation ?? new Context7ExternalDocumentationAdapter({
48543
48570
  enabled: process.env[CONTEXT7_ENABLED_ENV] === "1",
@@ -48607,7 +48634,7 @@ class ArchctxDaemon {
48607
48634
  try {
48608
48635
  for (const controller of this.auditRunAbortControllers.values())
48609
48636
  controller.abort();
48610
- this.mcpApprovals.clear();
48637
+ this.changeSetAuthority.clearApprovals();
48611
48638
  this.sessions.clear();
48612
48639
  this.practiceCheckpoints.clear();
48613
48640
  this.explorerProjections.clearDeferredChangeFeedFailures();
@@ -48751,65 +48778,7 @@ class ArchctxDaemon {
48751
48778
  return this.practiceCheckpoints.practiceWaivers(root);
48752
48779
  }
48753
48780
  async planPracticeWaiver(root, input) {
48754
- this.assertRunning();
48755
- const session = await this.openSession(root);
48756
- const model = await this.readModelStore.validateModel(session.workspace);
48757
- let ownerRegistry;
48758
- try {
48759
- ownerRegistry = loadPracticeWaiverOwnerRegistry(session.workspace.root);
48760
- } catch (error) {
48761
- return errorEnvelope("practices.waive", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
48762
- }
48763
- const waiver = {
48764
- schemaVersion: "archcontext.practice-waiver/v1",
48765
- practiceId: input.practiceId,
48766
- ...input.checkId === undefined ? {} : { checkId: input.checkId },
48767
- scope: {
48768
- ...input.pathGlobs && input.pathGlobs.length > 0 ? { pathGlobs: input.pathGlobs } : {},
48769
- ...input.subjects && input.subjects.length > 0 ? { subjects: input.subjects } : {}
48770
- },
48771
- owner: input.owner,
48772
- reason: input.reason,
48773
- createdAt: input.createdAt ?? this.clock(),
48774
- reviewAt: input.reviewAt,
48775
- expiresAt: input.expiresAt,
48776
- evidenceDigest: input.evidenceDigest
48777
- };
48778
- let waiverId;
48779
- try {
48780
- validatePracticeWaiver(waiver, "practice waiver input", { allowedOwners: ownerRegistry.owners });
48781
- waiverId = safePracticeWaiverId(input.waiverId, waiver);
48782
- } catch (error) {
48783
- return errorEnvelope("practices.waive", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
48784
- }
48785
- const path = `.archcontext/waivers/${waiverId}.json`;
48786
- const absolute = resolve25(session.workspace.root, path);
48787
- const body = `${JSON.stringify(waiver, null, 2)}
48788
- `;
48789
- const expectedHash = existsSync24(absolute) ? digestJson({ body: readFileSync26(absolute, "utf8") }) : "missing";
48790
- const draft = this.changeSetEngine.plan({
48791
- id: input.id ?? `changeset.practice-waiver-${waiverId.replace(/[^A-Za-z0-9_-]/g, "-")}`,
48792
- base: {
48793
- headSha: session.workspace.headSha,
48794
- worktreeDigest: session.snapshot.worktreeDigest,
48795
- modelDigest: model.modelDigest
48796
- },
48797
- reason: { taskSessionId: input.taskSessionId ?? "task_runtime" },
48798
- operations: [{ op: "write_waiver", path, expectedHash, body }]
48799
- });
48800
- this.changesets.set(draft.id, draft);
48801
- this.changeSetRoots.set(draft.id, canonicalRepositoryRoot(root));
48802
- this.changeSetWorktreeDigestProfiles.set(draft.id, "repository");
48803
- this.mcpChangeSets.delete(draft.id);
48804
- return okEnvelope("practices.waive", {
48805
- schemaVersion: "archcontext.practice-waiver-plan/v1",
48806
- waiver,
48807
- waiverDigest: digestJson(waiver),
48808
- ownerRegistry,
48809
- path,
48810
- draft,
48811
- preview: this.changeSetEngine.preview(session.workspace.root, draft)
48812
- });
48781
+ return this.changeSetAuthority.planPracticeWaiver(root, input);
48813
48782
  }
48814
48783
  async docs(root, input) {
48815
48784
  return this.externalDocumentationService.docs(root, input);
@@ -48818,45 +48787,7 @@ class ArchctxDaemon {
48818
48787
  return this.externalDocumentationService.readResource(root, uri);
48819
48788
  }
48820
48789
  async planUpdate(root, rawInput) {
48821
- this.assertRunning();
48822
- let input;
48823
- try {
48824
- input = decodeRuntimePlanUpdateInput(rawInput);
48825
- } catch (error) {
48826
- if (error instanceof RuntimeUpdateInputError) {
48827
- return errorEnvelope("plan_update", "AC_SCHEMA_INVALID", error.message);
48828
- }
48829
- throw error;
48830
- }
48831
- const session = await this.openSession(root);
48832
- const model = await this.readModelStore.validateModel(session.workspace);
48833
- const worktreeDigestProfile = input.worktreeDigestPrecondition?.profile ?? "repository";
48834
- const worktreeDigest = runtimeWorktreeDigest(root, worktreeDigestProfile);
48835
- if (input.worktreeDigestPrecondition && input.worktreeDigestPrecondition.expectedDigest !== worktreeDigest) {
48836
- throw new Error("Worktree digest changed before plan");
48837
- }
48838
- const draft = this.changeSetEngine.plan({
48839
- id: input.id,
48840
- base: {
48841
- headSha: session.workspace.headSha,
48842
- worktreeDigest,
48843
- modelDigest: model.modelDigest
48844
- },
48845
- reason: input.reason ?? { taskSessionId: "task_runtime" },
48846
- operations: input.operations
48847
- });
48848
- this.changesets.set(draft.id, draft);
48849
- this.changeSetRoots.set(draft.id, canonicalRepositoryRoot(root));
48850
- this.changeSetWorktreeDigestProfiles.set(draft.id, worktreeDigestProfile);
48851
- if (input.approvalChannel === "mcp")
48852
- this.mcpChangeSets.add(draft.id);
48853
- else
48854
- this.mcpChangeSets.delete(draft.id);
48855
- return okEnvelope("plan_update", {
48856
- draft,
48857
- changeSetDigest: digestJson(draft),
48858
- preview: this.changeSetEngine.preview(root, draft)
48859
- });
48790
+ return this.changeSetAuthority.planUpdate(root, rawInput);
48860
48791
  }
48861
48792
  async completeTask(root, input = {}) {
48862
48793
  this.assertRunning();
@@ -48965,177 +48896,19 @@ class ArchctxDaemon {
48965
48896
  return runProjectionProtocolCommand(input, root, this.projectionHost());
48966
48897
  }
48967
48898
  async approveMcpProjection(root, input) {
48968
- this.assertRunning();
48969
- try {
48970
- validateProjectionInvocation(input);
48971
- if (!projectionInvocationWrites(input))
48972
- throw new Error("Projection approval requires an apply, adopt or recover invocation");
48973
- assertProjectionInvocationSnapshot(root, input);
48974
- } catch (error) {
48975
- return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
48976
- }
48977
- const now = Date.parse(this.clock());
48978
- if (!Number.isFinite(now))
48979
- return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", "Approval clock is invalid");
48980
- for (const [key, grant] of this.mcpApprovals)
48981
- if (grant.expiresAt <= now)
48982
- this.mcpApprovals.delete(key);
48983
- if (this.mcpApprovals.size >= 256)
48984
- return errorEnvelope("projection.approve", "AC_PRECONDITION_FAILED", "Too many outstanding approvals; consume an approval or wait for expiry");
48985
- const approvalToken = randomBytes6(32).toString("hex");
48986
- const expiresAt = now + 5 * 60000;
48987
- this.mcpApprovals.set(digestJson(approvalToken), { scope: "projection", root: canonicalRepositoryRoot(root), invocationDigest: digestJson(input), expiresAt });
48988
- return okEnvelope("projection.approve", { approvalToken, expiresAt: new Date(expiresAt).toISOString() });
48899
+ return this.changeSetAuthority.approveMcpProjection(root, input);
48989
48900
  }
48990
48901
  async mcpProjection(root, input, approvalToken) {
48991
- this.assertRunning();
48992
- try {
48993
- validateProjectionInvocation(input);
48994
- } catch (error) {
48995
- return errorEnvelope("projection", "AC_SCHEMA_INVALID", error instanceof Error ? error.message : String(error));
48996
- }
48997
- if (projectionInvocationWrites(input)) {
48998
- const denied = () => errorEnvelope("projection", "AC_USER_CONFIRMATION_REQUIRED", "A fresh one-time token from archctx projection approve is required");
48999
- if (typeof approvalToken !== "string" || !/^[a-f0-9]{64}$/.test(approvalToken))
49000
- return denied();
49001
- const key = digestJson(approvalToken);
49002
- const grant = this.mcpApprovals.get(key);
49003
- this.mcpApprovals.delete(key);
49004
- const now = Date.parse(this.clock());
49005
- if (!grant || grant.scope !== "projection" || !Number.isFinite(now) || grant.expiresAt <= now || grant.root !== canonicalRepositoryRoot(root) || grant.invocationDigest !== digestJson(input))
49006
- return denied();
49007
- }
49008
- return this.projection(root, input);
48902
+ return this.changeSetAuthority.mcpProjection(root, input, approvalToken);
49009
48903
  }
49010
48904
  async approveMcpUpdate(root, input) {
49011
- this.assertRunning();
49012
- const draft = this.changesets.get(input?.id);
49013
- const canonicalRoot = canonicalRepositoryRoot(root);
49014
- const now = Date.parse(this.clock());
49015
- if (!draft || this.changeSetRoots.get(input.id) !== canonicalRoot || this.changeSetWorktreeDigestProfiles.get(input.id) !== "repository" || input.expectedChangeSetDigest !== digestJson(draft) || input.expectedWorktreeDigest !== draft.base.worktreeDigest || input.expectedWorktreeDigest !== runtimeWorktreeDigest(root, "repository") || !Number.isFinite(now)) {
49016
- return errorEnvelope("approve_mcp_update", "AC_PRECONDITION_FAILED", "Approval must match the current ChangeSet preview and repository");
49017
- }
49018
- for (const [key, grant] of this.mcpApprovals)
49019
- if (grant.expiresAt <= now)
49020
- this.mcpApprovals.delete(key);
49021
- if (this.mcpApprovals.size >= 256)
49022
- return errorEnvelope("approve_mcp_update", "AC_PRECONDITION_FAILED", "Too many outstanding approvals; consume an approval or wait for expiry");
49023
- const approvalToken = randomBytes6(32).toString("hex");
49024
- const expiresAt = now + 5 * 60000;
49025
- this.mcpApprovals.set(digestJson(approvalToken), {
49026
- scope: "changeset",
49027
- root: canonicalRoot,
49028
- id: input.id,
49029
- draftDigest: input.expectedChangeSetDigest,
49030
- worktreeDigest: input.expectedWorktreeDigest,
49031
- expiresAt
49032
- });
49033
- return okEnvelope("approve_mcp_update", { approvalToken, expiresAt: new Date(expiresAt).toISOString() });
48905
+ return this.changeSetAuthority.approveMcpUpdate(root, input);
49034
48906
  }
49035
48907
  async applyMcpUpdate(root, input) {
49036
- this.assertRunning();
49037
- const denied = () => errorEnvelope("apply_update", "AC_USER_CONFIRMATION_REQUIRED", "A fresh one-time token from archctx approve is required");
49038
- if (typeof input?.approvalToken !== "string" || !/^[a-f0-9]{64}$/.test(input.approvalToken))
49039
- return denied();
49040
- const key = digestJson(input.approvalToken);
49041
- const grant = this.mcpApprovals.get(key);
49042
- if (!grant)
49043
- return denied();
49044
- this.mcpApprovals.delete(key);
49045
- const draft = this.changesets.get(input.id);
49046
- const now = Date.parse(this.clock());
49047
- if (grant.scope !== "changeset" || !Number.isFinite(now) || grant.expiresAt <= now || grant.root !== canonicalRepositoryRoot(root) || grant.id !== input.id || grant.worktreeDigest !== input.expectedWorktreeDigest || !draft || grant.draftDigest !== digestJson(draft))
49048
- return denied();
49049
- return this.applyAuthorizedUpdate(root, { id: input.id, expectedWorktreeDigest: input.expectedWorktreeDigest, approved: true });
48908
+ return this.changeSetAuthority.applyMcpUpdate(root, input);
49050
48909
  }
49051
48910
  async applyUpdate(root, rawInput) {
49052
- this.assertRunning();
49053
- if (this.mcpChangeSets.has(rawInput?.id)) {
49054
- return errorEnvelope("apply_update", "AC_USER_CONFIRMATION_REQUIRED", "MCP ChangeSets require a one-time approval token through applyMcpUpdate");
49055
- }
49056
- return this.applyAuthorizedUpdate(root, rawInput);
49057
- }
49058
- async applyAuthorizedUpdate(root, rawInput) {
49059
- this.assertRunning();
49060
- let input;
49061
- try {
49062
- input = decodeRuntimeApplyUpdateInput(rawInput);
49063
- } catch (error) {
49064
- if (error instanceof RuntimeUpdateInputError) {
49065
- return errorEnvelope("apply_update", "AC_SCHEMA_INVALID", error.message);
49066
- }
49067
- throw error;
49068
- }
49069
- return this.withWriter(async () => {
49070
- const draft = this.changesets.get(input.id);
49071
- if (!draft)
49072
- throw new Error(`Unknown ChangeSet: ${input.id}`);
49073
- const plannedProfile = this.changeSetWorktreeDigestProfiles.get(input.id);
49074
- if (!plannedProfile)
49075
- throw new Error("ChangeSet worktree digest profile missing before apply");
49076
- const requestedProfile = input.worktreeDigestProfile ?? "repository";
49077
- if (requestedProfile !== plannedProfile)
49078
- throw new Error("ChangeSet worktree digest profile changed before apply");
49079
- const current = runtimeWorktreeDigest(root, plannedProfile);
49080
- if (current !== input.expectedWorktreeDigest)
49081
- throw new Error("Worktree digest changed before apply");
49082
- const session = await this.openSession(root);
49083
- if (draft.base.headSha !== session.workspace.headSha)
49084
- throw new Error("ChangeSet HEAD changed before apply");
49085
- if (draft.base.worktreeDigest !== current)
49086
- throw new Error("ChangeSet worktree digest changed before apply");
49087
- const currentModel = await this.readModelStore.validateModel(session.workspace);
49088
- const baseErrors = baseModelBlockingErrors(currentModel);
49089
- if (baseErrors.length > 0) {
49090
- throw new Error(`ChangeSet base model is invalid: ${baseErrors.join("; ")}`);
49091
- }
49092
- if (draft.base.modelDigest !== currentModel.modelDigest)
49093
- throw new Error("ChangeSet model digest changed before apply");
49094
- if (input.projectionApplyReceipt && await this.localStore.inspectProjectionApplyReceipt(input.projectionApplyReceipt.identity.lookupKey)) {
49095
- return errorEnvelope("apply_update", "AC_PRECONDITION_FAILED", "committed projection receipt requires explicit projection recover");
49096
- }
49097
- const approved = input.approved ? this.changeSetEngine.approve(draft) : draft;
49098
- const transitionBase = captureModelTransitionBase(root, approved);
49099
- let ledgerAppend;
49100
- let appliedJournalId;
49101
- const writesLedger = architectureLedgerWriteAppendsEvents(this.architectureLedger.writeMode);
49102
- const result = await this.changeSetEngine.apply(root, approved, {
49103
- approved: input.approved,
49104
- afterModelValidatedBeforeCommit: async ({ journalId }) => {
49105
- appliedJournalId = journalId;
49106
- if (transitionBase && journalId)
49107
- await recordModelTransitionEvidence(this.localStore, root, journalId, transitionBase);
49108
- if (journalId && this.projectionPlannedDrafts.has(draft))
49109
- await this.localStore.recordChangeSetProjectionOwner(journalId);
49110
- if (input.projectionApplyReceipt) {
49111
- if (!journalId)
49112
- throw new Error("projection apply receipt requires a durable ChangeSet journal");
49113
- await this.localStore.recordProjectionApplyReceipt(journalId, input.projectionApplyReceipt);
49114
- }
49115
- if (writesLedger) {
49116
- const appended = await this.appendAppliedChangeSetToArchitectureLedger(root, session, approved, journalId);
49117
- ledgerAppend = {
49118
- status: "appended",
49119
- appendedEventCount: appended.appendedEvents.length,
49120
- duplicateEventCount: appended.duplicateEvents.length,
49121
- graphDigest: appended.graphDigest,
49122
- entityCount: appended.entityCount,
49123
- relationCount: appended.relationCount,
49124
- constraintCount: appended.constraintCount
49125
- };
49126
- }
49127
- return { journalCommitted: writesLedger && Boolean(journalId) };
49128
- }
49129
- });
49130
- return okEnvelope("apply_update", {
49131
- ...result,
49132
- ...appliedJournalId ? { journalId: appliedJournalId } : {},
49133
- architectureLedger: {
49134
- ...this.architectureLedger,
49135
- append: writesLedger ? ledgerAppend ?? { status: "not-appended" } : { status: "not-applicable" }
49136
- }
49137
- });
49138
- });
48911
+ return this.changeSetAuthority.applyUpdate(root, rawInput);
49139
48912
  }
49140
48913
  async inspectProjectionApplyReceipt(root, lookupKey) {
49141
48914
  return this.projectionApplies.inspectProjectionApplyReceipt(root, lookupKey);
@@ -49149,112 +48922,8 @@ class ArchctxDaemon {
49149
48922
  async recoverProjectionApply(root, intent) {
49150
48923
  return this.projectionApplies.recoverProjectionApply(root, intent);
49151
48924
  }
49152
- async appendAppliedChangeSetToArchitectureLedger(root, session, draft, journalId) {
49153
- const paths = runtimeStatePaths(root);
49154
- const scope = {
49155
- repository: {
49156
- repositoryId: session.workspace.repositoryId,
49157
- storageRepositoryId: paths.storageRepositoryId
49158
- },
49159
- worktree: {
49160
- workspaceId: paths.workspaceId,
49161
- storageWorkspaceId: paths.storageWorkspaceId,
49162
- branch: readCurrentBranch(root),
49163
- headSha: session.workspace.headSha,
49164
- worktreeDigest: computeWorktreeDigest(root)
49165
- }
49166
- };
49167
- const plan = planChangeSetApplyToArchitectureLedgerEvent({
49168
- ...scope,
49169
- draft,
49170
- files: listModelFiles(root),
49171
- previousEvidenceState: await this.localStore.replayArchitectureLedgerEvidence(scope),
49172
- createdAt: this.clock(),
49173
- writeMode: this.architectureLedger.writeMode === "ledger-with-projection" ? "ledger-with-projection" : "dual",
49174
- command: "archctx apply"
49175
- });
49176
- if (journalId)
49177
- await this.localStore.recordChangeSetLedgerPlan(journalId, { event: plan.event });
49178
- const appendInput = { writer: "runtime-daemon", events: [plan.event] };
49179
- const result = await this.appendArchitectureEventsWithFeed(root, appendInput, journalId);
49180
- return result;
49181
- }
49182
48925
  async acceptCommittedChange(root, rawInput) {
49183
- this.assertRunning();
49184
- let input;
49185
- try {
49186
- input = decodeAcceptCommittedChangeInput(rawInput);
49187
- } catch (error) {
49188
- if (error instanceof AcceptCommittedChangeInputError)
49189
- return errorEnvelope("ledger.accept-committed", "AC_SCHEMA_INVALID", error.message);
49190
- throw error;
49191
- }
49192
- if (this.architectureLedger.readMode !== "yaml" || this.architectureLedger.writeMode !== "yaml") {
49193
- return errorEnvelope("ledger.accept-committed", "AC_PRECONDITION_FAILED", "committed YAML acceptance requires YAML read and write authority");
49194
- }
49195
- return this.withWriter(async () => {
49196
- try {
49197
- const canonicalRoot = canonicalRepositoryRoot(root);
49198
- const journals = [];
49199
- for (const ref of input.journals)
49200
- journals.push(await this.localStore.readCommittedChangeSet(canonicalRoot, ref.journalId));
49201
- const model = loadNativeModelFromArchContext(canonicalRoot);
49202
- const worktreeDigest = architectureDocumentationProjectionWorktreeDigest(canonicalRoot, model);
49203
- const projection3 = buildArchitectureDocsProjection(this.projectionHost(), canonicalRoot, new Date(0).toISOString(), "repo-harness/v1");
49204
- const scope = acceptedCommittedChangeScope(canonicalRoot, worktreeDigest, resolveAcceptanceHeadSha(canonicalRoot));
49205
- const manifestWrite = await this.localStore.readLatestCommittedChangeSetFile(canonicalRoot, "docs/architecture/.projection-manifest.json");
49206
- const acceptance = planCommittedChangeAcceptance(canonicalRoot, {
49207
- requested: input.journals,
49208
- journals,
49209
- model,
49210
- existingFiles: projection3.loaded.existingFiles,
49211
- latestJournaledManifest: manifestWrite,
49212
- projection: projection3.plan,
49213
- currentEvidence: projection3.snapshotEvidence,
49214
- projectionWorktreeDigest: worktreeDigest,
49215
- scope
49216
- });
49217
- if (!input.approved) {
49218
- return okEnvelope("ledger.accept-committed", { status: "preview", plan: acceptance.plan, acceptancePlanId: acceptance.acceptancePlanId, expectedWorktreeDigest: worktreeDigest });
49219
- }
49220
- if (input.expectedWorktreeDigest !== worktreeDigest)
49221
- throw new Error("accepted ChangeSet expected worktree digest mismatch");
49222
- if (input.acceptancePlanId !== acceptance.acceptancePlanId)
49223
- throw new Error("accepted ChangeSet acceptance plan changed since preview");
49224
- const accepted = (event2, replayed) => {
49225
- const recorded = acceptedChangeFromEventV2(event2);
49226
- if (!recorded || !event2.eventHash)
49227
- throw new Error("committed ChangeSet acceptance readback failed");
49228
- return okEnvelope("ledger.accept-committed", {
49229
- status: "accepted",
49230
- replayed,
49231
- acceptedChange: recorded.acceptedChange,
49232
- acceptancePlanId: recorded.acceptancePlanId,
49233
- journalIds: input.journals.map((journal) => journal.journalId),
49234
- eventHash: event2.eventHash,
49235
- fileSetDigest: acceptance.plan.fileSetDigest
49236
- });
49237
- };
49238
- const existing = await this.localStore.readArchitectureEvent({ ...scope, eventId: acceptance.acceptedChange.eventId });
49239
- if (existing) {
49240
- if (acceptedChangeFromEventV2(existing)?.acceptancePlanId === acceptance.acceptancePlanId)
49241
- return accepted(existing, true);
49242
- throw new Error(`committed ChangeSet already has a different acceptance event at this snapshot: ${existing.eventId}`);
49243
- }
49244
- const ledgerGraphDigest = architectureLedgerStateDigest(await this.localStore.readArchitectureLedgerState(scope));
49245
- const event = acceptedCommittedChangeEventV2({ acceptance, scope, ledgerGraphDigest, timestamp: this.clock() });
49246
- const appended = await this.appendArchitectureEventsWithFeed(canonicalRoot, { writer: "runtime-daemon", events: [event] });
49247
- if (appended.appendedEvents.length !== 1)
49248
- throw new Error("committed ChangeSet acceptance event was not appended");
49249
- const readback = await this.localStore.readArchitectureEvent({ ...scope, eventId: event.eventId });
49250
- if (!readback || readback.eventType !== event.eventType || readback.payloadVersion !== event.payloadVersion) {
49251
- throw new Error("committed ChangeSet acceptance readback failed");
49252
- }
49253
- return accepted(readback, false);
49254
- } catch (error) {
49255
- return errorEnvelope("ledger.accept-committed", "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
49256
- }
49257
- });
48926
+ return this.changeSetAuthority.acceptCommittedChange(root, rawInput);
49258
48927
  }
49259
48928
  async ledgerState(root) {
49260
48929
  this.assertRunning();
@@ -49534,7 +49203,7 @@ class ArchctxDaemon {
49534
49203
  }
49535
49204
  async restoreRepositorySessions() {
49536
49205
  for (const record3 of await this.localStore.listRepositorySessions()) {
49537
- if (!record3.root || !existsSync24(record3.root))
49206
+ if (!record3.root || !existsSync25(record3.root))
49538
49207
  continue;
49539
49208
  if (repositoryFingerprint(record3.root) !== record3.repositoryId)
49540
49209
  continue;
@@ -49596,16 +49265,6 @@ class ArchctxDaemon {
49596
49265
  function shortDigest3(digest2) {
49597
49266
  return digest2.replace(/^sha256:/, "").slice(0, 16);
49598
49267
  }
49599
- function runtimeWorktreeDigest(root, profile) {
49600
- switch (profile) {
49601
- case "repository":
49602
- return computeWorktreeDigest(root);
49603
- case "architecture-documentation-projection":
49604
- return architectureDocumentationProjectionWorktreeDigest(root, loadNativeModelFromArchContext(root));
49605
- default:
49606
- throw new RuntimeUpdateInputError(`unsupported worktree digest profile: ${String(profile)}`);
49607
- }
49608
- }
49609
49268
  function codeFactsDigest(snapshot) {
49610
49269
  return digestJson({
49611
49270
  schemaVersion: "archcontext.code-facts-digest/v1",
@@ -49631,19 +49290,6 @@ function architectureLedgerScopeForWorkspace(workspace) {
49631
49290
  }
49632
49291
  };
49633
49292
  }
49634
- function acceptedCommittedChangeScope(root, worktreeDigest, headSha) {
49635
- const paths = runtimeStatePaths(root);
49636
- return {
49637
- repository: { repositoryId: repositoryFingerprint(root), storageRepositoryId: paths.storageRepositoryId },
49638
- worktree: {
49639
- workspaceId: projectionWorkspaceId(root),
49640
- storageWorkspaceId: paths.storageWorkspaceId,
49641
- branch: readCurrentBranch(root),
49642
- headSha,
49643
- worktreeDigest
49644
- }
49645
- };
49646
- }
49647
49293
  function validateModelFiles(files) {
49648
49294
  const errors2 = [];
49649
49295
  const paths = new Set(files.map((file) => file.path));
@@ -49688,18 +49334,6 @@ function schemaVersionFromModelBody(body) {
49688
49334
  } catch {}
49689
49335
  return "";
49690
49336
  }
49691
- function safePracticeWaiverId(explicit, waiver) {
49692
- const explicitTrimmed = explicit?.trim();
49693
- if (explicitTrimmed && (explicitTrimmed === "." || explicitTrimmed === ".." || explicitTrimmed.includes("/") || explicitTrimmed.includes("\\"))) {
49694
- throw new Error("practice-waiver-id-invalid");
49695
- }
49696
- const evidencePrefix = waiver.evidenceDigest.startsWith("sha256:") ? waiver.evidenceDigest.slice("sha256:".length, "sha256:".length + 12) : waiver.evidenceDigest.slice(0, 12);
49697
- const candidate = (explicitTrimmed || [waiver.practiceId.replace(/\./g, "-"), waiver.checkId ?? "all", evidencePrefix].join("-")).replace(/[^A-Za-z0-9_.-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 96);
49698
- if (!candidate || candidate === "." || candidate === ".." || candidate.includes("/") || candidate.includes("\\")) {
49699
- throw new Error("practice-waiver-id-invalid");
49700
- }
49701
- return candidate;
49702
- }
49703
49337
  async function createStartedDaemon(deps = {}) {
49704
49338
  const daemon = new ArchctxDaemon(deps);
49705
49339
  await daemon.start();
@@ -49820,9 +49454,6 @@ function readRuntimeArchitectureLedgerWriteMode(value) {
49820
49454
  function architectureLedgerReadAuthority(mode) {
49821
49455
  return mode === "ledger" ? "ledger" : "yaml";
49822
49456
  }
49823
- function architectureLedgerWriteAppendsEvents(mode) {
49824
- return mode === "dual" || mode === "ledger-with-projection";
49825
- }
49826
49457
  var GIT_OBJECT_NAME_PATTERN = /^[0-9a-f]{7,64}$/;
49827
49458
  function readChangedPathsSince(root, commit) {
49828
49459
  if (!GIT_OBJECT_NAME_PATTERN.test(commit)) {
@@ -49861,7 +49492,7 @@ function blockedProductionInjections(deps) {
49861
49492
  ].filter((key) => (key in deps));
49862
49493
  }
49863
49494
  function completeTaskProjectionDrift(root) {
49864
- if (!existsSync24(resolve25(root, "docs/architecture/.projection-manifest.json")))
49495
+ if (!existsSync25(resolve26(root, "docs/architecture/.projection-manifest.json")))
49865
49496
  return;
49866
49497
  const profile = loadArchitectureDocumentationProfile(root);
49867
49498
  const loaded = loadArchitectureDocumentationInputs(root, profile);
@@ -50375,10 +50006,10 @@ class McpLocalServer {
50375
50006
  ...localResources,
50376
50007
  ...cacheEntries.filter((entry) => typeof entry.contentDigest === "string" && /^sha256:[0-9a-f]{64}$/.test(entry.contentDigest)).map((entry) => {
50377
50008
  const library = typeof entry.libraryId === "string" ? entry.libraryId : "context7";
50378
- const version2 = typeof entry.version === "string" ? entry.version : "unknown";
50009
+ const version = typeof entry.version === "string" ? entry.version : "unknown";
50379
50010
  return {
50380
50011
  uri: `archcontext://external-docs/context7/${entry.contentDigest}`,
50381
- name: `Context7 ${library}@${version2}`,
50012
+ name: `Context7 ${library}@${version}`,
50382
50013
  description: "Read-only external documentation resource from the local daemon cache.",
50383
50014
  mimeType: "application/json",
50384
50015
  annotations: { safety: "read-only" }
@@ -50741,7 +50372,7 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
50741
50372
  const subcommand = args2[0] ?? "list";
50742
50373
  if (subcommand === "add") {
50743
50374
  const root = readFlag(args2, "--root") ?? cwd;
50744
- if (resolve26(root) !== resolve26(cwd)) {
50375
+ if (resolve27(root) !== resolve27(cwd)) {
50745
50376
  return errorEnvelope("repo.add", "AC_CAPABILITY_UNSUPPORTED", "Multi-repo architecture context is outside the Local Core MVP; run archctx inside one Git repository.");
50746
50377
  }
50747
50378
  const daemon2 = await runtime();
@@ -51978,8 +51609,8 @@ function auditManifestGateRoot(cwd) {
51978
51609
  }
51979
51610
  }
51980
51611
  function auditGithubIssuesEnabled(cwd) {
51981
- const manifestPath = resolve26(auditManifestGateRoot(cwd), ".archcontext/manifest.yaml");
51982
- if (!existsSync25(manifestPath))
51612
+ const manifestPath = resolve27(auditManifestGateRoot(cwd), ".archcontext/manifest.yaml");
51613
+ if (!existsSync26(manifestPath))
51983
51614
  return false;
51984
51615
  let raw;
51985
51616
  try {
@@ -52365,7 +51996,7 @@ async function runGithubCommand(args2, cwd, deps) {
52365
51996
  }
52366
51997
  if (subcommand === "disconnect") {
52367
51998
  const connection = await deps.githubConnectionReader?.readVerifiedConnection({ repositoryRoot: cwd });
52368
- const localRecordRemoved = existsSync25(connectionPath);
51999
+ const localRecordRemoved = existsSync26(connectionPath);
52369
52000
  rmSync16(connectionPath, { force: true });
52370
52001
  return okEnvelope("github.disconnect", {
52371
52002
  connected: connection !== undefined,
@@ -52677,7 +52308,7 @@ async function readReviewChallengeV2Arg(args2, cwd, commandName = "github verify
52677
52308
  if (!inline && !challengePath)
52678
52309
  return { ok: false, message: `${commandName} requires --challenge-json or --challenge-path` };
52679
52310
  try {
52680
- const raw = inline ?? readFileSync27(resolve26(cwd, challengePath), "utf8");
52311
+ const raw = inline ?? readFileSync27(resolve27(cwd, challengePath), "utf8");
52681
52312
  const parsed = JSON.parse(raw);
52682
52313
  const attestation = await Promise.resolve().then(() => (init_src6(), exports_src2));
52683
52314
  const assertReviewChallengeV23 = attestation.assertReviewChallengeV2;
@@ -53152,10 +52783,10 @@ function doctorSqlite(cwd) {
53152
52783
  const legacyLocalStore = inspectLegacyLocalStoreMigration(cwd);
53153
52784
  return {
53154
52785
  path,
53155
- exists: existsSync25(path),
52786
+ exists: existsSync26(path),
53156
52787
  migrations: productVersionManifest().runtime.sqliteMigrations,
53157
52788
  legacyPath: paths.legacyLocalStorePath,
53158
- legacyExists: existsSync25(paths.legacyLocalStorePath),
52789
+ legacyExists: existsSync26(paths.legacyLocalStorePath),
53159
52790
  legacyLocalStore
53160
52791
  };
53161
52792
  }
@@ -53186,7 +52817,7 @@ function runtimePathsReport(cwd) {
53186
52817
  };
53187
52818
  }
53188
52819
  function pathAccess(path) {
53189
- const exists = existsSync25(path);
52820
+ const exists = existsSync26(path);
53190
52821
  return {
53191
52822
  path,
53192
52823
  exists,
@@ -53644,7 +53275,7 @@ async function waitForDaemonReady(cwd, timeoutMs, shouldStop) {
53644
53275
  return;
53645
53276
  }
53646
53277
  function sleep(ms) {
53647
- return new Promise((resolve27) => setTimeout(resolve27, ms));
53278
+ return new Promise((resolve28) => setTimeout(resolve28, ms));
53648
53279
  }
53649
53280
  function readFileTail(path, maxBytes = 4096) {
53650
53281
  try {
@@ -53657,8 +53288,8 @@ function readFileTail(path, maxBytes = 4096) {
53657
53288
  async function runForegroundDaemon(cwd, args2) {
53658
53289
  const daemon = await createStartedProductionDaemon({ root: cwd });
53659
53290
  let resolveStopped;
53660
- const stopped = new Promise((resolve27) => {
53661
- resolveStopped = resolve27;
53291
+ const stopped = new Promise((resolve28) => {
53292
+ resolveStopped = resolve28;
53662
53293
  });
53663
53294
  const idleTimeoutFlag = readFlag(args2, "--idle-timeout-ms");
53664
53295
  const server = new ArchctxRuntimeRpcServer(daemon, {