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/assets/catalog.yaml +2 -2
- package/bin/archctx.mjs +631 -1000
- package/package.json +2 -2
- package/schemas/repo/architecture-flow.schema.json +2 -2
- package/schemas/runtime/projection-apply-readback.schema.json +2 -2
- package/schemas/runtime/projection-apply-recovery.schema.json +1 -1
- package/schemas/runtime/projection-result.schema.json +1 -1
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.
|
|
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.
|
|
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(
|
|
11355
|
-
this.releaseRollbacks.push(
|
|
11356
|
-
return { rolledBack: true, version
|
|
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
|
|
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 =
|
|
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 =
|
|
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 &&
|
|
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 (
|
|
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 (
|
|
15361
|
+
if (koffi.errno() === koffi.os.errno.ENOENT && expectedHash === "missing")
|
|
15824
15362
|
return;
|
|
15825
|
-
if (
|
|
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 ${
|
|
15406
|
+
return new Error(`${action} failed with errno ${koffi.errno()}`);
|
|
15869
15407
|
}
|
|
15870
15408
|
function writeWithLockedWindowsParents(request) {
|
|
15871
|
-
const kernel32 =
|
|
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 =
|
|
15412
|
+
const attributeTagInfo = koffi.struct({ FileAttributes: "uint32", ReparseTag: "uint32" });
|
|
15875
15413
|
const getFileInformationByHandleEx = kernel32.func("GetFileInformationByHandleEx", "int", [
|
|
15876
15414
|
"void *",
|
|
15877
15415
|
"int",
|
|
15878
|
-
|
|
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 (
|
|
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,
|
|
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
|
|
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 =
|
|
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 =
|
|
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) ??
|
|
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(
|
|
20171
|
-
if (!VERSION_PATTERN.test(
|
|
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((
|
|
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
|
|
20446
|
-
import { dirname as dirname15, join as join18, resolve as
|
|
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(
|
|
22730
|
-
const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(
|
|
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
|
|
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 =
|
|
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
|
|
30790
|
-
if (
|
|
30791
|
-
return
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 ??
|
|
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
|
|
48177
|
-
import { resolve as
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 || !
|
|
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 (!
|
|
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
|
|
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}@${
|
|
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 (
|
|
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 =
|
|
51982
|
-
if (!
|
|
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 =
|
|
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(
|
|
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:
|
|
52786
|
+
exists: existsSync26(path),
|
|
53156
52787
|
migrations: productVersionManifest().runtime.sqliteMigrations,
|
|
53157
52788
|
legacyPath: paths.legacyLocalStorePath,
|
|
53158
|
-
legacyExists:
|
|
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 =
|
|
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((
|
|
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((
|
|
53661
|
-
resolveStopped =
|
|
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, {
|