@mrciphersmith/keryx 0.2.51 → 0.2.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +931 -394
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -14032,6 +14032,9 @@ var init_assembly = () => {};
|
|
|
14032
14032
|
// src/session/slate.ts
|
|
14033
14033
|
import { mkdir as mkdir25, readFile as readFile31, rm as rm4 } from "fs/promises";
|
|
14034
14034
|
import path69 from "path";
|
|
14035
|
+
function isSlateSeedKind(value) {
|
|
14036
|
+
return typeof value === "string" && SLATE_SEED_KINDS.includes(value);
|
|
14037
|
+
}
|
|
14035
14038
|
function slatePath(dir) {
|
|
14036
14039
|
return path69.join(dir, "slate.json");
|
|
14037
14040
|
}
|
|
@@ -14171,12 +14174,20 @@ function renderAnchorsBlock(anchors, opts) {
|
|
|
14171
14174
|
return lines.join(`
|
|
14172
14175
|
`);
|
|
14173
14176
|
}
|
|
14174
|
-
var DEFAULT_RENDER_MAX_TOKENS = 2000;
|
|
14177
|
+
var SLATE_SEED_KINDS, SEED_TEXT_MAX_LENGTH = 4000, DEFAULT_RENDER_MAX_TOKENS = 2000;
|
|
14175
14178
|
var init_slate = __esm(() => {
|
|
14176
14179
|
init_fs();
|
|
14177
14180
|
init_assembly();
|
|
14178
14181
|
init_repomap();
|
|
14179
14182
|
init_redact();
|
|
14183
|
+
SLATE_SEED_KINDS = [
|
|
14184
|
+
"decision",
|
|
14185
|
+
"wiki-update",
|
|
14186
|
+
"memory-entry",
|
|
14187
|
+
"follow-up",
|
|
14188
|
+
"contract-change",
|
|
14189
|
+
"risk"
|
|
14190
|
+
];
|
|
14180
14191
|
});
|
|
14181
14192
|
|
|
14182
14193
|
// src/flow/store.ts
|
|
@@ -16372,6 +16383,7 @@ async function writeWrapUpOutcomeArtifact(dir, trigger, now, groups) {
|
|
|
16372
16383
|
} catch {}
|
|
16373
16384
|
}
|
|
16374
16385
|
async function proposeOneGroup(params) {
|
|
16386
|
+
const wrapUpSource = params.wrapUpSource ?? "flow";
|
|
16375
16387
|
try {
|
|
16376
16388
|
const resolved = await resolveMachineWrapUp({
|
|
16377
16389
|
cwd: params.cwd,
|
|
@@ -16393,8 +16405,8 @@ async function proposeOneGroup(params) {
|
|
|
16393
16405
|
const wrapUpAuthority = createTrustedWrapUpAuthority({
|
|
16394
16406
|
now: params.now,
|
|
16395
16407
|
resolveExplicitWrapUp: async (request) => {
|
|
16396
|
-
if (request.source !==
|
|
16397
|
-
throw new Error(`machine-wrap-up only resolves "
|
|
16408
|
+
if (request.source !== wrapUpSource) {
|
|
16409
|
+
throw new Error(`machine-wrap-up only resolves "${wrapUpSource}" wrap-ups, got "${request.source}"`);
|
|
16398
16410
|
}
|
|
16399
16411
|
return resolved.resolution;
|
|
16400
16412
|
}
|
|
@@ -16407,7 +16419,7 @@ async function proposeOneGroup(params) {
|
|
|
16407
16419
|
const actor = await authorizationServer.actorContextFor(undefined, requestCorrelationId);
|
|
16408
16420
|
if (!actor)
|
|
16409
16421
|
throw new Error("trusted ActorContext is required for a machine wrap-up propose");
|
|
16410
|
-
const provenance = await wrapUpAuthority.issue({ actor, source:
|
|
16422
|
+
const provenance = await wrapUpAuthority.issue({ actor, source: wrapUpSource, sourceRef });
|
|
16411
16423
|
try {
|
|
16412
16424
|
const proposal = await service.create({
|
|
16413
16425
|
request: undefined,
|
|
@@ -16450,6 +16462,7 @@ async function runWrapUp(input2) {
|
|
|
16450
16462
|
slate: input2.slate,
|
|
16451
16463
|
kind,
|
|
16452
16464
|
now,
|
|
16465
|
+
...input2.wrapUpSource !== undefined ? { wrapUpSource: input2.wrapUpSource } : {},
|
|
16453
16466
|
...input2.env !== undefined ? { env: input2.env } : {},
|
|
16454
16467
|
...input2.providerFactory !== undefined ? { providerFactory: input2.providerFactory } : {},
|
|
16455
16468
|
...input2.modelTurnTimeoutMs !== undefined ? { modelTurnTimeoutMs: input2.modelTurnTimeoutMs } : {}
|
|
@@ -33541,7 +33554,8 @@ function fileRuntime(id, relativePath) {
|
|
|
33541
33554
|
merge: mcpMerge,
|
|
33542
33555
|
strip: mcpStrip,
|
|
33543
33556
|
validate: mcpValidate(id),
|
|
33544
|
-
hasManaged: mcpHasManaged
|
|
33557
|
+
hasManaged: mcpHasManaged,
|
|
33558
|
+
listServers: (settings) => Object.keys(readServers(settings))
|
|
33545
33559
|
};
|
|
33546
33560
|
}
|
|
33547
33561
|
var CURSOR_RUNTIME = fileRuntime("cursor", ".cursor/mcp.json");
|
|
@@ -33607,7 +33621,8 @@ var OPENCODE_RUNTIME = {
|
|
|
33607
33621
|
merge: opencodeMerge,
|
|
33608
33622
|
strip: opencodeStrip,
|
|
33609
33623
|
validate: opencodeValidate,
|
|
33610
|
-
hasManaged: opencodeHasManaged
|
|
33624
|
+
hasManaged: opencodeHasManaged,
|
|
33625
|
+
listServers: (settings) => Object.keys(readOpencodeMcp(settings))
|
|
33611
33626
|
};
|
|
33612
33627
|
var GENERIC_RUNTIME = {
|
|
33613
33628
|
id: "generic",
|
|
@@ -33615,7 +33630,8 @@ var GENERIC_RUNTIME = {
|
|
|
33615
33630
|
merge: mcpMerge,
|
|
33616
33631
|
strip: mcpStrip,
|
|
33617
33632
|
validate: mcpValidate("generic"),
|
|
33618
|
-
hasManaged: mcpHasManaged
|
|
33633
|
+
hasManaged: mcpHasManaged,
|
|
33634
|
+
listServers: (settings) => Object.keys(readServers(settings))
|
|
33619
33635
|
};
|
|
33620
33636
|
function readVscodeServers(settings) {
|
|
33621
33637
|
return typeof settings.servers === "object" && settings.servers !== null && !Array.isArray(settings.servers) ? { ...settings.servers } : {};
|
|
@@ -33676,7 +33692,8 @@ var VSCODE_RUNTIME = {
|
|
|
33676
33692
|
merge: vscodeMerge,
|
|
33677
33693
|
strip: vscodeStrip,
|
|
33678
33694
|
validate: vscodeValidate,
|
|
33679
|
-
hasManaged: vscodeHasManaged
|
|
33695
|
+
hasManaged: vscodeHasManaged,
|
|
33696
|
+
listServers: (settings) => Object.keys(readVscodeServers(settings))
|
|
33680
33697
|
};
|
|
33681
33698
|
var MCP_CLIENT_RUNTIMES = [
|
|
33682
33699
|
CURSOR_RUNTIME,
|
|
@@ -33716,11 +33733,12 @@ async function mcpClientStatus(projectRoot, ids = mcpRuntimeIds()) {
|
|
|
33716
33733
|
for (const runtime of runtimes) {
|
|
33717
33734
|
const file = runtime.settingsPath(absoluteProjectRoot);
|
|
33718
33735
|
if (file === null) {
|
|
33719
|
-
statuses.push({ id: runtime.id, filePath: null, connected: false });
|
|
33736
|
+
statuses.push({ id: runtime.id, filePath: null, connected: false, otherServers: [] });
|
|
33720
33737
|
continue;
|
|
33721
33738
|
}
|
|
33722
33739
|
const settings = await readSettings2(file);
|
|
33723
|
-
|
|
33740
|
+
const otherServers = runtime.listServers(settings).filter((name) => name !== MCP_SERVER_NAME).sort();
|
|
33741
|
+
statuses.push({ id: runtime.id, filePath: file, connected: runtime.hasManaged(settings), otherServers });
|
|
33724
33742
|
}
|
|
33725
33743
|
return statuses;
|
|
33726
33744
|
}
|
|
@@ -43429,7 +43447,7 @@ function printSecurityHelp() {
|
|
|
43429
43447
|
|
|
43430
43448
|
// src/commands/mcp.ts
|
|
43431
43449
|
init_args();
|
|
43432
|
-
import
|
|
43450
|
+
import path137 from "path";
|
|
43433
43451
|
|
|
43434
43452
|
// src/mcp/discovery.ts
|
|
43435
43453
|
init_fs();
|
|
@@ -43510,7 +43528,7 @@ init_metaproject_adapter();
|
|
|
43510
43528
|
init_service6();
|
|
43511
43529
|
init_service3();
|
|
43512
43530
|
init_service7();
|
|
43513
|
-
import { readFile as
|
|
43531
|
+
import { readFile as readFile76, writeFile as writeFile47 } from "fs/promises";
|
|
43514
43532
|
|
|
43515
43533
|
// src/mcp/metaproject-tools.ts
|
|
43516
43534
|
init_metaproject_adapter();
|
|
@@ -44401,12 +44419,116 @@ function normalizeCollaborationResult(value) {
|
|
|
44401
44419
|
// src/sac/service.ts
|
|
44402
44420
|
init_workspace_service();
|
|
44403
44421
|
|
|
44422
|
+
// src/session/external-slate.ts
|
|
44423
|
+
init_fs();
|
|
44424
|
+
init_machine_wrap_up();
|
|
44425
|
+
import { mkdir as mkdir54, readdir as readdir23, readFile as readFile75 } from "fs/promises";
|
|
44426
|
+
import path135 from "path";
|
|
44427
|
+
function externalSlatesDir(cwd) {
|
|
44428
|
+
return path135.join(cwd, ".keryx", "external-slates");
|
|
44429
|
+
}
|
|
44430
|
+
var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
44431
|
+
function assertValidExternalSessionId(externalSessionId) {
|
|
44432
|
+
if (!EXTERNAL_SESSION_ID_PATTERN.test(externalSessionId)) {
|
|
44433
|
+
throw new Error(`invalid externalSessionId ${JSON.stringify(externalSessionId)} \u2014 must match ${EXTERNAL_SESSION_ID_PATTERN.source} (letters, digits, "-", "_", 1-128 chars, no path separators)`);
|
|
44434
|
+
}
|
|
44435
|
+
}
|
|
44436
|
+
function externalSlatePath(cwd, externalSessionId) {
|
|
44437
|
+
assertValidExternalSessionId(externalSessionId);
|
|
44438
|
+
return path135.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
|
|
44439
|
+
}
|
|
44440
|
+
function externalSlateLockPath(cwd, externalSessionId) {
|
|
44441
|
+
return `${externalSlatePath(cwd, externalSessionId)}.lock`;
|
|
44442
|
+
}
|
|
44443
|
+
function externalSlateEvidenceDir(cwd, externalSessionId) {
|
|
44444
|
+
assertValidExternalSessionId(externalSessionId);
|
|
44445
|
+
return path135.join(externalSlatesDir(cwd), externalSessionId);
|
|
44446
|
+
}
|
|
44447
|
+
async function readExternalSlate(cwd, externalSessionId) {
|
|
44448
|
+
try {
|
|
44449
|
+
const raw = await readFile75(externalSlatePath(cwd, externalSessionId), "utf8");
|
|
44450
|
+
return JSON.parse(raw);
|
|
44451
|
+
} catch (error2) {
|
|
44452
|
+
if (isNotFound(error2))
|
|
44453
|
+
return;
|
|
44454
|
+
throw error2;
|
|
44455
|
+
}
|
|
44456
|
+
}
|
|
44457
|
+
async function writeExternalSlate(cwd, externalSessionId, update) {
|
|
44458
|
+
await mkdir54(externalSlatesDir(cwd), { recursive: true });
|
|
44459
|
+
return withFileLock2(externalSlateLockPath(cwd, externalSessionId), async () => {
|
|
44460
|
+
const prev = await readExternalSlate(cwd, externalSessionId);
|
|
44461
|
+
const next = update(prev);
|
|
44462
|
+
await writeFileAtomic(externalSlatePath(cwd, externalSessionId), `${JSON.stringify(next, null, 2)}
|
|
44463
|
+
`);
|
|
44464
|
+
return next;
|
|
44465
|
+
});
|
|
44466
|
+
}
|
|
44467
|
+
async function listExternalSlateIds(cwd) {
|
|
44468
|
+
try {
|
|
44469
|
+
const entries = await readdir23(externalSlatesDir(cwd));
|
|
44470
|
+
return entries.filter((name) => name.endsWith(".json")).map((name) => name.slice(0, -".json".length));
|
|
44471
|
+
} catch (error2) {
|
|
44472
|
+
if (isNotFound(error2))
|
|
44473
|
+
return [];
|
|
44474
|
+
throw error2;
|
|
44475
|
+
}
|
|
44476
|
+
}
|
|
44477
|
+
function isExternalSlateStale(slate, now = () => new Date) {
|
|
44478
|
+
const lastWriteMs = new Date(slate.lastWriteAt).getTime();
|
|
44479
|
+
if (!Number.isFinite(lastWriteMs))
|
|
44480
|
+
return true;
|
|
44481
|
+
return now().getTime() - lastWriteMs > DEFAULT_LOCK_STALE_MS;
|
|
44482
|
+
}
|
|
44483
|
+
async function closeExternalSlate(cwd, externalSessionId, trigger, now = () => new Date) {
|
|
44484
|
+
await mkdir54(externalSlatesDir(cwd), { recursive: true });
|
|
44485
|
+
return withFileLock2(externalSlateLockPath(cwd, externalSessionId), async () => {
|
|
44486
|
+
const external = await readExternalSlate(cwd, externalSessionId);
|
|
44487
|
+
if (!external || external.closedAt !== undefined)
|
|
44488
|
+
return;
|
|
44489
|
+
const shimSlate = {
|
|
44490
|
+
...external.workspaceId !== undefined ? { workspaceId: external.workspaceId } : {},
|
|
44491
|
+
anchors: { root: external.anchors.root, touched: external.anchors.touched ?? [] },
|
|
44492
|
+
course: {},
|
|
44493
|
+
seeds: external.seeds
|
|
44494
|
+
};
|
|
44495
|
+
await runWrapUp({
|
|
44496
|
+
cwd,
|
|
44497
|
+
dir: externalSlateEvidenceDir(cwd, externalSessionId),
|
|
44498
|
+
slate: shimSlate,
|
|
44499
|
+
trigger,
|
|
44500
|
+
wrapUpSource: "external-slate",
|
|
44501
|
+
now
|
|
44502
|
+
});
|
|
44503
|
+
const next = { ...external, closedAt: now().toISOString() };
|
|
44504
|
+
await writeFileAtomic(externalSlatePath(cwd, externalSessionId), `${JSON.stringify(next, null, 2)}
|
|
44505
|
+
`);
|
|
44506
|
+
});
|
|
44507
|
+
}
|
|
44508
|
+
async function reclaimStaleExternalSlates(cwd, now = () => new Date) {
|
|
44509
|
+
const ids = await listExternalSlateIds(cwd);
|
|
44510
|
+
for (const id of ids) {
|
|
44511
|
+
try {
|
|
44512
|
+
const slate = await readExternalSlate(cwd, id);
|
|
44513
|
+
if (slate && isExternalSlateStale(slate, now)) {
|
|
44514
|
+
await closeExternalSlate(cwd, id, "external-slate-idle-reclaim", now);
|
|
44515
|
+
}
|
|
44516
|
+
} catch {}
|
|
44517
|
+
}
|
|
44518
|
+
}
|
|
44519
|
+
|
|
44520
|
+
// src/sac/service.ts
|
|
44521
|
+
init_slate();
|
|
44522
|
+
init_workspace_resolve();
|
|
44523
|
+
init_redact();
|
|
44524
|
+
|
|
44404
44525
|
// src/mcp/tools.ts
|
|
44405
44526
|
import { randomUUID as randomUUID17 } from "crypto";
|
|
44406
44527
|
function stringParam2(params, key) {
|
|
44407
44528
|
const value = params[key];
|
|
44408
44529
|
return typeof value === "string" ? value : undefined;
|
|
44409
44530
|
}
|
|
44531
|
+
var MAX_EXTERNAL_SLATE_SEEDS = 200;
|
|
44410
44532
|
async function loadGraphSafe(cwd) {
|
|
44411
44533
|
try {
|
|
44412
44534
|
return await loadGraph(cwd);
|
|
@@ -44427,6 +44549,38 @@ function readOnlyFlowService() {
|
|
|
44427
44549
|
now: () => new Date
|
|
44428
44550
|
});
|
|
44429
44551
|
}
|
|
44552
|
+
async function handleSlateOpen(params) {
|
|
44553
|
+
const { cwd, externalSessionId, resolveWorkspace } = params;
|
|
44554
|
+
if (externalSessionId.length === 0)
|
|
44555
|
+
throw new Error("slate.open requires a non-empty 'externalSessionId'");
|
|
44556
|
+
await reclaimStaleExternalSlates(cwd);
|
|
44557
|
+
const existing = await readExternalSlate(cwd, externalSessionId);
|
|
44558
|
+
if (existing)
|
|
44559
|
+
return existing;
|
|
44560
|
+
const rawAnchors = params.anchors && typeof params.anchors === "object" ? params.anchors : {};
|
|
44561
|
+
const anchors = {
|
|
44562
|
+
root: typeof rawAnchors.root === "string" ? rawAnchors.root : "",
|
|
44563
|
+
...Array.isArray(rawAnchors.touched) ? { touched: rawAnchors.touched.filter((t) => typeof t === "string") } : {},
|
|
44564
|
+
...typeof rawAnchors.note === "string" ? { note: rawAnchors.note } : {}
|
|
44565
|
+
};
|
|
44566
|
+
let workspaceId = params.workspaceId;
|
|
44567
|
+
if (workspaceId === undefined) {
|
|
44568
|
+
const resolver = resolveWorkspace ?? resolveOrCreateWorkspace;
|
|
44569
|
+
const topicHint = anchors.note ?? (anchors.root.length > 0 ? anchors.root : externalSessionId);
|
|
44570
|
+
try {
|
|
44571
|
+
const resolved = await resolver({ cwd, topicHint });
|
|
44572
|
+
if (resolved.ok)
|
|
44573
|
+
workspaceId = resolved.workspaceId;
|
|
44574
|
+
} catch {}
|
|
44575
|
+
}
|
|
44576
|
+
return writeExternalSlate(cwd, externalSessionId, () => ({
|
|
44577
|
+
externalSessionId,
|
|
44578
|
+
...workspaceId ? { workspaceId } : {},
|
|
44579
|
+
anchors,
|
|
44580
|
+
seeds: [],
|
|
44581
|
+
lastWriteAt: new Date().toISOString()
|
|
44582
|
+
}));
|
|
44583
|
+
}
|
|
44430
44584
|
function buildToolRegistry() {
|
|
44431
44585
|
return [
|
|
44432
44586
|
...toMcpTools(),
|
|
@@ -44558,6 +44712,102 @@ function buildToolRegistry() {
|
|
|
44558
44712
|
return workspace;
|
|
44559
44713
|
}
|
|
44560
44714
|
},
|
|
44715
|
+
{
|
|
44716
|
+
name: "slate.open",
|
|
44717
|
+
module: "slate",
|
|
44718
|
+
description: "Open (or idempotently re-open) this external hand's own private, task-local Slate \u2014 never readable/writable by a different externalSessionId. `anchors` is stored verbatim (root/touched/note), never harness-enriched.",
|
|
44719
|
+
inputSchema: OBJECT_SCHEMA({
|
|
44720
|
+
externalSessionId: { type: "string" },
|
|
44721
|
+
workspaceId: { type: "string", description: "Bind this slate to an already-known SAC workspace up front; omit to stay unbound (slate.close then preserves Seeds as a local unbound-candidate artifact)." },
|
|
44722
|
+
anchors: {
|
|
44723
|
+
type: "object",
|
|
44724
|
+
description: "{ root: string, touched?: string[], note?: string } \u2014 this hand's own self-report, stored exactly as given.",
|
|
44725
|
+
properties: { root: { type: "string" }, touched: { type: "array", items: { type: "string" } }, note: { type: "string" } }
|
|
44726
|
+
}
|
|
44727
|
+
}, ["externalSessionId"]),
|
|
44728
|
+
mutating: true,
|
|
44729
|
+
async invoke(cwd, params, context) {
|
|
44730
|
+
if (context?.transport === "http")
|
|
44731
|
+
return { code: "slate_transport_denied" };
|
|
44732
|
+
const externalSessionId = stringParam2(params, "externalSessionId") ?? "";
|
|
44733
|
+
const workspaceId = stringParam2(params, "workspaceId");
|
|
44734
|
+
return handleSlateOpen({
|
|
44735
|
+
cwd,
|
|
44736
|
+
externalSessionId,
|
|
44737
|
+
...workspaceId !== undefined ? { workspaceId } : {},
|
|
44738
|
+
anchors: params.anchors
|
|
44739
|
+
});
|
|
44740
|
+
}
|
|
44741
|
+
},
|
|
44742
|
+
{
|
|
44743
|
+
name: "slate.writeSeed",
|
|
44744
|
+
module: "slate",
|
|
44745
|
+
description: "Append a draft Seed (task-local hypothesis, not yet reviewed knowledge) to this external hand's own Slate. `origin`/`trust` are always server-set \u2014 a caller-supplied value for either is never used.",
|
|
44746
|
+
inputSchema: OBJECT_SCHEMA({ externalSessionId: { type: "string" }, text: { type: "string" }, kind: { type: "string", description: "decision | wiki-update | memory-entry | follow-up | contract-change | risk" } }, ["externalSessionId", "text"]),
|
|
44747
|
+
mutating: true,
|
|
44748
|
+
async invoke(cwd, params, context) {
|
|
44749
|
+
if (context?.transport === "http")
|
|
44750
|
+
return { code: "slate_transport_denied" };
|
|
44751
|
+
const externalSessionId = stringParam2(params, "externalSessionId") ?? "";
|
|
44752
|
+
const rawText = stringParam2(params, "text") ?? "";
|
|
44753
|
+
if (externalSessionId.length === 0)
|
|
44754
|
+
throw new Error("slate.writeSeed requires a non-empty 'externalSessionId'");
|
|
44755
|
+
if (rawText.length === 0)
|
|
44756
|
+
throw new Error("slate.writeSeed requires a non-empty 'text'");
|
|
44757
|
+
if (rawText.length > SEED_TEXT_MAX_LENGTH) {
|
|
44758
|
+
throw new Error(`slate.writeSeed: 'text' exceeds the ${SEED_TEXT_MAX_LENGTH}-character limit (got ${rawText.length})`);
|
|
44759
|
+
}
|
|
44760
|
+
await reclaimStaleExternalSlates(cwd);
|
|
44761
|
+
const rawKind = stringParam2(params, "kind");
|
|
44762
|
+
let kind;
|
|
44763
|
+
if (rawKind !== undefined) {
|
|
44764
|
+
if (!isSlateSeedKind(rawKind)) {
|
|
44765
|
+
throw new Error(`slate.writeSeed: unrecognized 'kind' "${rawKind}"`);
|
|
44766
|
+
}
|
|
44767
|
+
kind = rawKind;
|
|
44768
|
+
}
|
|
44769
|
+
const text = redactSensitiveText(rawText);
|
|
44770
|
+
const ts = new Date().toISOString();
|
|
44771
|
+
const seed = {
|
|
44772
|
+
id: `seed-${randomUUID17()}`,
|
|
44773
|
+
text,
|
|
44774
|
+
ts,
|
|
44775
|
+
...kind ? { kind } : {},
|
|
44776
|
+
origin: { harness: "mcp-external" },
|
|
44777
|
+
trust: "external-unverified"
|
|
44778
|
+
};
|
|
44779
|
+
return writeExternalSlate(cwd, externalSessionId, (prev) => {
|
|
44780
|
+
if (!prev)
|
|
44781
|
+
throw new Error(`slate.writeSeed: no open external slate for "${externalSessionId}" \u2014 call slate.open first`);
|
|
44782
|
+
if (prev.closedAt !== undefined)
|
|
44783
|
+
throw new Error(`slate.writeSeed: external slate "${externalSessionId}" is already closed`);
|
|
44784
|
+
if (prev.seeds.length >= MAX_EXTERNAL_SLATE_SEEDS) {
|
|
44785
|
+
throw new Error(`slate.writeSeed: external slate "${externalSessionId}" already has ${MAX_EXTERNAL_SLATE_SEEDS} seeds (the maximum) \u2014 close it and open a fresh one`);
|
|
44786
|
+
}
|
|
44787
|
+
return { ...prev, seeds: [...prev.seeds, seed], lastWriteAt: ts };
|
|
44788
|
+
});
|
|
44789
|
+
}
|
|
44790
|
+
},
|
|
44791
|
+
{
|
|
44792
|
+
name: "slate.close",
|
|
44793
|
+
module: "slate",
|
|
44794
|
+
description: "Close this external hand's Slate: dispatches into the existing SAC propose/review pipeline (mirrors SLATE-18's autonomous workspace_propose) when a workspaceId is bound, else preserves its Seeds as a local unbound-candidate artifact \u2014 never a proposal against a guessed workspaceId.",
|
|
44795
|
+
inputSchema: OBJECT_SCHEMA({ externalSessionId: { type: "string" } }, ["externalSessionId"]),
|
|
44796
|
+
mutating: true,
|
|
44797
|
+
async invoke(cwd, params, context) {
|
|
44798
|
+
if (context?.transport === "http")
|
|
44799
|
+
return { code: "slate_transport_denied" };
|
|
44800
|
+
const externalSessionId = stringParam2(params, "externalSessionId") ?? "";
|
|
44801
|
+
if (externalSessionId.length === 0)
|
|
44802
|
+
throw new Error("slate.close requires a non-empty 'externalSessionId'");
|
|
44803
|
+
await reclaimStaleExternalSlates(cwd);
|
|
44804
|
+
const existing = await readExternalSlate(cwd, externalSessionId);
|
|
44805
|
+
if (!existing)
|
|
44806
|
+
return { externalSessionId, closed: true, alreadyClosed: true };
|
|
44807
|
+
await closeExternalSlate(cwd, externalSessionId, "external-slate-close");
|
|
44808
|
+
return { externalSessionId, closed: true };
|
|
44809
|
+
}
|
|
44810
|
+
},
|
|
44561
44811
|
{
|
|
44562
44812
|
name: "gdgraph.affected",
|
|
44563
44813
|
module: "gdgraph",
|
|
@@ -44620,7 +44870,7 @@ function buildToolRegistry() {
|
|
|
44620
44870
|
async invoke(cwd, params) {
|
|
44621
44871
|
const filePath = stringParam2(params, "path");
|
|
44622
44872
|
const inline = stringParam2(params, "content");
|
|
44623
|
-
const content = inline ?? (filePath ? await
|
|
44873
|
+
const content = inline ?? (filePath ? await readFile76(filePath, "utf8") : "");
|
|
44624
44874
|
const result = await runScan(cwd, {
|
|
44625
44875
|
content,
|
|
44626
44876
|
source: "trusted-project",
|
|
@@ -44741,8 +44991,8 @@ function buildToolRegistry() {
|
|
|
44741
44991
|
|
|
44742
44992
|
// src/mcp/resources.ts
|
|
44743
44993
|
init_fs();
|
|
44744
|
-
import
|
|
44745
|
-
import { readdir as
|
|
44994
|
+
import path136 from "path";
|
|
44995
|
+
import { readdir as readdir24, readFile as readFile77, stat as stat7 } from "fs/promises";
|
|
44746
44996
|
var URI_PREFIX = "metaproject://";
|
|
44747
44997
|
function mimeForPath(filePath) {
|
|
44748
44998
|
if (filePath.endsWith(".json") || filePath.endsWith(".jsonl")) {
|
|
@@ -44754,13 +45004,13 @@ function mimeForPath(filePath) {
|
|
|
44754
45004
|
return "text/plain";
|
|
44755
45005
|
}
|
|
44756
45006
|
function dataRoot3(cwd) {
|
|
44757
|
-
return
|
|
45007
|
+
return path136.join(cwd, ".metaproject", "data");
|
|
44758
45008
|
}
|
|
44759
45009
|
function wikiRoot(cwd) {
|
|
44760
|
-
return
|
|
45010
|
+
return path136.join(cwd, ".metaproject", "wiki");
|
|
44761
45011
|
}
|
|
44762
45012
|
function memoryRoot2(cwd) {
|
|
44763
|
-
return
|
|
45013
|
+
return path136.join(cwd, ".metaproject", "memory");
|
|
44764
45014
|
}
|
|
44765
45015
|
async function walkFiles(root) {
|
|
44766
45016
|
if (!await pathExists(root)) {
|
|
@@ -44769,12 +45019,12 @@ async function walkFiles(root) {
|
|
|
44769
45019
|
const out = [];
|
|
44770
45020
|
let entries;
|
|
44771
45021
|
try {
|
|
44772
|
-
entries = await
|
|
45022
|
+
entries = await readdir24(root, { withFileTypes: true });
|
|
44773
45023
|
} catch {
|
|
44774
45024
|
return [];
|
|
44775
45025
|
}
|
|
44776
45026
|
for (const entry of entries) {
|
|
44777
|
-
const full =
|
|
45027
|
+
const full = path136.join(root, entry.name);
|
|
44778
45028
|
if (entry.isDirectory()) {
|
|
44779
45029
|
out.push(...await walkFiles(full));
|
|
44780
45030
|
} else if (entry.isFile()) {
|
|
@@ -44791,7 +45041,7 @@ async function listArtifacts(cwd) {
|
|
|
44791
45041
|
const listings = [];
|
|
44792
45042
|
let modules;
|
|
44793
45043
|
try {
|
|
44794
|
-
modules = await
|
|
45044
|
+
modules = await readdir24(base, { withFileTypes: true });
|
|
44795
45045
|
} catch {
|
|
44796
45046
|
return [];
|
|
44797
45047
|
}
|
|
@@ -44799,9 +45049,9 @@ async function listArtifacts(cwd) {
|
|
|
44799
45049
|
if (!moduleEntry.isDirectory()) {
|
|
44800
45050
|
continue;
|
|
44801
45051
|
}
|
|
44802
|
-
const artifactsDir2 =
|
|
45052
|
+
const artifactsDir2 = path136.join(base, moduleEntry.name, "artifacts");
|
|
44803
45053
|
for (const file of await walkFiles(artifactsDir2)) {
|
|
44804
|
-
const rel = toPosix(
|
|
45054
|
+
const rel = toPosix(path136.relative(artifactsDir2, file));
|
|
44805
45055
|
const relPath = `${moduleEntry.name}/${rel}`;
|
|
44806
45056
|
listings.push({
|
|
44807
45057
|
uri: `${URI_PREFIX}artifacts/${relPath}`,
|
|
@@ -44815,7 +45065,7 @@ async function listArtifacts(cwd) {
|
|
|
44815
45065
|
async function listUnderRoot(cwd, cls, root) {
|
|
44816
45066
|
const listings = [];
|
|
44817
45067
|
for (const file of await walkFiles(root)) {
|
|
44818
|
-
const rel = toPosix(
|
|
45068
|
+
const rel = toPosix(path136.relative(root, file));
|
|
44819
45069
|
listings.push({
|
|
44820
45070
|
uri: `${URI_PREFIX}${cls}/${rel}`,
|
|
44821
45071
|
name: rel,
|
|
@@ -44865,12 +45115,12 @@ function resolveConfined(cwd, cls, relPath) {
|
|
|
44865
45115
|
if (moduleName.includes("..") || moduleName.length === 0) {
|
|
44866
45116
|
return null;
|
|
44867
45117
|
}
|
|
44868
|
-
const root2 =
|
|
44869
|
-
const absolute2 =
|
|
45118
|
+
const root2 = path136.join(dataRoot3(cwd), moduleName, "artifacts");
|
|
45119
|
+
const absolute2 = path136.resolve(root2, rest);
|
|
44870
45120
|
return isPathInside(root2, absolute2) ? { root: root2, absolute: absolute2 } : null;
|
|
44871
45121
|
}
|
|
44872
45122
|
const root = cls === "wiki" ? wikiRoot(cwd) : memoryRoot2(cwd);
|
|
44873
|
-
const absolute =
|
|
45123
|
+
const absolute = path136.resolve(root, relPath);
|
|
44874
45124
|
return isPathInside(root, absolute) ? { root, absolute } : null;
|
|
44875
45125
|
}
|
|
44876
45126
|
async function readResource(cwd, roots, uri) {
|
|
@@ -44889,7 +45139,7 @@ async function readResource(cwd, roots, uri) {
|
|
|
44889
45139
|
if (!info || !info.isFile()) {
|
|
44890
45140
|
throw new Error(`Resource not found: ${uri}`);
|
|
44891
45141
|
}
|
|
44892
|
-
const text = await
|
|
45142
|
+
const text = await readFile77(resolved.absolute, "utf8");
|
|
44893
45143
|
return { uri, mimeType: mimeForPath(resolved.absolute), text };
|
|
44894
45144
|
}
|
|
44895
45145
|
|
|
@@ -45070,7 +45320,7 @@ async function mcpCommand(args2 = [], cwd = process.cwd()) {
|
|
|
45070
45320
|
}
|
|
45071
45321
|
if (!subcommand || subcommand === "serve") {
|
|
45072
45322
|
const http = args2.includes("--http");
|
|
45073
|
-
const projectRoot =
|
|
45323
|
+
const projectRoot = path137.resolve(optionValue(args2, "--cwd") ?? cwd);
|
|
45074
45324
|
try {
|
|
45075
45325
|
await serveMcp({ cwd: projectRoot, http });
|
|
45076
45326
|
} catch (error2) {
|
|
@@ -45104,7 +45354,7 @@ async function handleInstall2(cwd, args2) {
|
|
|
45104
45354
|
console.log(outcome.snippet ?? "");
|
|
45105
45355
|
continue;
|
|
45106
45356
|
}
|
|
45107
|
-
const rel =
|
|
45357
|
+
const rel = path137.relative(cwd, outcome.filePath);
|
|
45108
45358
|
if (outcome.errors.length > 0) {
|
|
45109
45359
|
for (const e of outcome.errors) {
|
|
45110
45360
|
console.log(` ${style.red(symbols.cross)} ${e}`);
|
|
@@ -45144,7 +45394,7 @@ async function handleUninstall2(cwd, args2) {
|
|
|
45144
45394
|
console.log(` ${style.gray(symbols.off)} ${outcome.id} ${style.dim("no file to change")}`);
|
|
45145
45395
|
continue;
|
|
45146
45396
|
}
|
|
45147
|
-
const rel =
|
|
45397
|
+
const rel = path137.relative(cwd, outcome.filePath);
|
|
45148
45398
|
console.log(` ${outcome.removed ? style.green(symbols.ok) : style.gray(symbols.off)} ${outcome.id} ${style.dim(outcome.removed ? `removed from ${rel}` : "nothing to remove")}`);
|
|
45149
45399
|
}
|
|
45150
45400
|
}
|
|
@@ -45174,14 +45424,14 @@ function printMcpHelp() {
|
|
|
45174
45424
|
// src/commands/status.ts
|
|
45175
45425
|
init_fs();
|
|
45176
45426
|
init_json();
|
|
45177
|
-
import
|
|
45427
|
+
import path138 from "path";
|
|
45178
45428
|
async function statusCommand(args2 = []) {
|
|
45179
45429
|
if (args2.includes("--help") || args2.includes("-h")) {
|
|
45180
45430
|
printHelp14();
|
|
45181
45431
|
return;
|
|
45182
45432
|
}
|
|
45183
|
-
const root =
|
|
45184
|
-
const manifestPath =
|
|
45433
|
+
const root = path138.join(process.cwd(), ".metaproject");
|
|
45434
|
+
const manifestPath = path138.join(root, "metaproject.json");
|
|
45185
45435
|
if (!await pathExists(root)) {
|
|
45186
45436
|
console.log("Metaproject: not initialized");
|
|
45187
45437
|
console.log("Run: keryx init");
|
|
@@ -45221,7 +45471,7 @@ Reports the workspace root and one enabled/disabled line per module. Use
|
|
|
45221
45471
|
|
|
45222
45472
|
// src/commands/harness.ts
|
|
45223
45473
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
45224
|
-
import
|
|
45474
|
+
import path142 from "path";
|
|
45225
45475
|
import { randomUUID as randomUUID18 } from "crypto";
|
|
45226
45476
|
|
|
45227
45477
|
// src/security/harness-scan.ts
|
|
@@ -46294,7 +46544,7 @@ ${command.argv.join(" ")}`);
|
|
|
46294
46544
|
}
|
|
46295
46545
|
|
|
46296
46546
|
// src/harness/process/sandbox/profile.ts
|
|
46297
|
-
import
|
|
46547
|
+
import path139 from "path";
|
|
46298
46548
|
var DEFAULT_SECRET_SUBPATHS = [
|
|
46299
46549
|
".ssh",
|
|
46300
46550
|
".gnupg",
|
|
@@ -46319,7 +46569,7 @@ function defaultReadDenyList(home) {
|
|
|
46319
46569
|
if (!home) {
|
|
46320
46570
|
return [];
|
|
46321
46571
|
}
|
|
46322
|
-
return DEFAULT_SECRET_SUBPATHS.map((sub) =>
|
|
46572
|
+
return DEFAULT_SECRET_SUBPATHS.map((sub) => path139.join(home, sub));
|
|
46323
46573
|
}
|
|
46324
46574
|
function defaultSandboxProfile(cwd, tmpDir, home) {
|
|
46325
46575
|
return {
|
|
@@ -46337,7 +46587,7 @@ function dedupe2(values) {
|
|
|
46337
46587
|
|
|
46338
46588
|
// src/harness/process/sandbox/detect.ts
|
|
46339
46589
|
import { existsSync as realExistsSync } from "fs";
|
|
46340
|
-
import
|
|
46590
|
+
import path140 from "path";
|
|
46341
46591
|
|
|
46342
46592
|
// src/harness/process/sandbox/seatbelt.ts
|
|
46343
46593
|
var SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
|
|
@@ -46531,9 +46781,9 @@ function detectSandboxLauncher(opts = {}) {
|
|
|
46531
46781
|
}
|
|
46532
46782
|
if (platform === "linux") {
|
|
46533
46783
|
const env = opts.env ?? process.env;
|
|
46534
|
-
const dirs = (env.PATH ?? "").split(
|
|
46784
|
+
const dirs = (env.PATH ?? "").split(path140.delimiter).filter(Boolean);
|
|
46535
46785
|
for (const dir of dirs) {
|
|
46536
|
-
const candidate =
|
|
46786
|
+
const candidate = path140.join(dir, BWRAP_PROGRAM);
|
|
46537
46787
|
if (exists2(candidate)) {
|
|
46538
46788
|
return { available: true, platform, path: candidate };
|
|
46539
46789
|
}
|
|
@@ -46563,10 +46813,10 @@ function resolveSandboxAdapter(profile, inner, opts = {}) {
|
|
|
46563
46813
|
init_config_dir();
|
|
46564
46814
|
init_shell_config();
|
|
46565
46815
|
import { existsSync as existsSync22 } from "fs";
|
|
46566
|
-
import
|
|
46816
|
+
import path141 from "path";
|
|
46567
46817
|
var SECRET_KEY_PATTERN2 = /api[_-]?key|secret|token|password|credential/i;
|
|
46568
46818
|
function sandboxConfigPath(dir) {
|
|
46569
|
-
return
|
|
46819
|
+
return path141.join(path141.dirname(shellConfigPath(dir)), "sandbox.json");
|
|
46570
46820
|
}
|
|
46571
46821
|
function isShellDefault(v) {
|
|
46572
46822
|
return v === "off" || v === "workspace" || v === "strict" || v === "1";
|
|
@@ -47685,7 +47935,7 @@ async function harnessExec(args2, deps) {
|
|
|
47685
47935
|
env: commandEnv,
|
|
47686
47936
|
cwd
|
|
47687
47937
|
};
|
|
47688
|
-
const worktreeRoot =
|
|
47938
|
+
const worktreeRoot = path142.parse(path142.resolve(cwd, commandPath)).root || cwd;
|
|
47689
47939
|
const budget = {
|
|
47690
47940
|
reservationId: idSeq(),
|
|
47691
47941
|
maxRuntimeMs: maxRuntimeMs ?? EXEC_DEFAULT_RUNTIME_MS
|
|
@@ -47921,7 +48171,7 @@ async function buildApprovalContext(port, command) {
|
|
|
47921
48171
|
import { randomUUID as randomUUID20 } from "crypto";
|
|
47922
48172
|
|
|
47923
48173
|
// src/harness/tool/builtin/interactive-tools.ts
|
|
47924
|
-
import { readdir as
|
|
48174
|
+
import { readdir as readdir25 } from "fs/promises";
|
|
47925
48175
|
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "path";
|
|
47926
48176
|
import { realpathSync as realpathSync4 } from "fs";
|
|
47927
48177
|
var MAX_READ_BYTES = 20000;
|
|
@@ -47973,7 +48223,7 @@ function builtinReadOnlyTools(root) {
|
|
|
47973
48223
|
return { output: `path escapes the project root: ${requested}`, isError: true };
|
|
47974
48224
|
}
|
|
47975
48225
|
try {
|
|
47976
|
-
const entries = await
|
|
48226
|
+
const entries = await readdir25(target, { withFileTypes: true });
|
|
47977
48227
|
const lines = entries.map((e) => e.isDirectory() ? `${e.name}/` : e.name).sort();
|
|
47978
48228
|
return { output: lines.length > 0 ? lines.join(`
|
|
47979
48229
|
`) : "(empty)", isError: false };
|
|
@@ -48887,13 +49137,13 @@ function builtinMetaprojectTools(root, run = makeKeryxRunner(root), port) {
|
|
|
48887
49137
|
if ("error" in pattern) {
|
|
48888
49138
|
return pattern.error;
|
|
48889
49139
|
}
|
|
48890
|
-
const
|
|
49140
|
+
const path143 = typeof input2.path === "string" && input2.path.length > 0 ? input2.path : undefined;
|
|
48891
49141
|
const args2 = ["ctx", "rg", pattern.value];
|
|
48892
|
-
if (
|
|
48893
|
-
const confined = confineToRoot(root,
|
|
49142
|
+
if (path143 !== undefined) {
|
|
49143
|
+
const confined = confineToRoot(root, path143);
|
|
48894
49144
|
if (confined === null) {
|
|
48895
49145
|
return {
|
|
48896
|
-
output: `search_code: path escapes the project root: ${
|
|
49146
|
+
output: `search_code: path escapes the project root: ${path143}`,
|
|
48897
49147
|
isError: true
|
|
48898
49148
|
};
|
|
48899
49149
|
}
|
|
@@ -48949,18 +49199,6 @@ function builtinMetaprojectTools(root, run = makeKeryxRunner(root), port) {
|
|
|
48949
49199
|
init_slate();
|
|
48950
49200
|
init_slate_course();
|
|
48951
49201
|
init_redact();
|
|
48952
|
-
var SEED_TEXT_MAX_LENGTH = 4000;
|
|
48953
|
-
var SLATE_SEED_KINDS = [
|
|
48954
|
-
"decision",
|
|
48955
|
-
"wiki-update",
|
|
48956
|
-
"memory-entry",
|
|
48957
|
-
"follow-up",
|
|
48958
|
-
"contract-change",
|
|
48959
|
-
"risk"
|
|
48960
|
-
];
|
|
48961
|
-
function isSlateSeedKind(value) {
|
|
48962
|
-
return typeof value === "string" && SLATE_SEED_KINDS.includes(value);
|
|
48963
|
-
}
|
|
48964
49202
|
function slateReadTool(cwd, getSessionDir) {
|
|
48965
49203
|
return {
|
|
48966
49204
|
definition: {
|
|
@@ -49609,7 +49847,7 @@ init_shell_config();
|
|
|
49609
49847
|
init_command_risk();
|
|
49610
49848
|
init_shell_syntax();
|
|
49611
49849
|
import { existsSync as existsSync24 } from "fs";
|
|
49612
|
-
import
|
|
49850
|
+
import path143 from "path";
|
|
49613
49851
|
import { createHash as createHash31 } from "crypto";
|
|
49614
49852
|
var PREFIX_BANNED = new Set([
|
|
49615
49853
|
"sh",
|
|
@@ -49795,7 +50033,7 @@ function emptyShellPermissions() {
|
|
|
49795
50033
|
return { allow: [] };
|
|
49796
50034
|
}
|
|
49797
50035
|
function shellPermissionsPath(dir) {
|
|
49798
|
-
return
|
|
50036
|
+
return path143.join(path143.dirname(shellConfigPath(dir)), "permissions.json");
|
|
49799
50037
|
}
|
|
49800
50038
|
function loadShellPermissionsWithAudit(dir) {
|
|
49801
50039
|
try {
|
|
@@ -49833,7 +50071,7 @@ function loadShellPermissions(dir) {
|
|
|
49833
50071
|
function saveShellPermissions(perms, dir, options = {}) {
|
|
49834
50072
|
try {
|
|
49835
50073
|
const file = shellPermissionsPath(dir);
|
|
49836
|
-
ensureKeryxConfigDir(
|
|
50074
|
+
ensureKeryxConfigDir(path143.dirname(file));
|
|
49837
50075
|
const cleaned = Array.from(new Set(perms.allow.map((p) => p.trim()).filter((p) => p.length > 0)));
|
|
49838
50076
|
const body = {
|
|
49839
50077
|
allow: options.skipValidation === true ? cleaned : cleaned.filter((p) => validateShellPattern(p).ok)
|
|
@@ -50150,12 +50388,12 @@ function remoteRequest(providerId, endpoint, query, key) {
|
|
|
50150
50388
|
// src/lib/search-config.ts
|
|
50151
50389
|
init_config_dir();
|
|
50152
50390
|
import { existsSync as existsSync25 } from "fs";
|
|
50153
|
-
import
|
|
50391
|
+
import path144 from "path";
|
|
50154
50392
|
function searchConfigPath(dir) {
|
|
50155
|
-
return
|
|
50393
|
+
return path144.join(keryxConfigDir(dir), "search-providers.json");
|
|
50156
50394
|
}
|
|
50157
50395
|
function searchCredentialPath(dir) {
|
|
50158
|
-
return
|
|
50396
|
+
return path144.join(keryxConfigDir(dir), "search-credentials.json");
|
|
50159
50397
|
}
|
|
50160
50398
|
function readJson(file) {
|
|
50161
50399
|
try {
|
|
@@ -50284,7 +50522,7 @@ function createDefaultSearchProviderController(configDir) {
|
|
|
50284
50522
|
import { createHash as createHash32, randomUUID as randomUUID21 } from "crypto";
|
|
50285
50523
|
import { mkdtemp, rm as rm8 } from "fs/promises";
|
|
50286
50524
|
import { tmpdir as tmpdir4 } from "os";
|
|
50287
|
-
import
|
|
50525
|
+
import path145 from "path";
|
|
50288
50526
|
init_metaproject_adapter();
|
|
50289
50527
|
init_ledger();
|
|
50290
50528
|
init_orchestrate();
|
|
@@ -50535,8 +50773,8 @@ function createSpawnSubagentTool(deps) {
|
|
|
50535
50773
|
let dispatchId = "";
|
|
50536
50774
|
let closing = false;
|
|
50537
50775
|
try {
|
|
50538
|
-
ephemeralDir = await mkdtemp(
|
|
50539
|
-
dispatchId =
|
|
50776
|
+
ephemeralDir = await mkdtemp(path145.join(tmpdir4(), "keryx-subagent-slate-"));
|
|
50777
|
+
dispatchId = path145.basename(ephemeralDir);
|
|
50540
50778
|
openedChildSlate = await openSlate({
|
|
50541
50779
|
dir: ephemeralDir,
|
|
50542
50780
|
cwd,
|
|
@@ -50778,9 +51016,9 @@ ${boundSummary(folded.text)}`,
|
|
|
50778
51016
|
// src/harness/run-external-factory.ts
|
|
50779
51017
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
50780
51018
|
import { execFile as execFile4 } from "child_process";
|
|
50781
|
-
import { mkdir as
|
|
51019
|
+
import { mkdir as mkdir55 } from "fs/promises";
|
|
50782
51020
|
import { tmpdir as tmpdir6 } from "os";
|
|
50783
|
-
import
|
|
51021
|
+
import path147 from "path";
|
|
50784
51022
|
import { promisify as promisify4 } from "util";
|
|
50785
51023
|
|
|
50786
51024
|
// src/harness/child/git-worktree-port.ts
|
|
@@ -50793,27 +51031,27 @@ function createGitWorktreePort(options) {
|
|
|
50793
51031
|
const paths = new Map;
|
|
50794
51032
|
return {
|
|
50795
51033
|
async create(worktreeId) {
|
|
50796
|
-
const
|
|
50797
|
-
await execFileAsync3("git", ["worktree", "add", "--detach",
|
|
50798
|
-
paths.set(worktreeId,
|
|
50799
|
-
return { worktreeId, path:
|
|
51034
|
+
const path146 = `${worktreesDir}/${worktreeId}`;
|
|
51035
|
+
await execFileAsync3("git", ["worktree", "add", "--detach", path146, ref], { cwd: repoRoot });
|
|
51036
|
+
paths.set(worktreeId, path146);
|
|
51037
|
+
return { worktreeId, path: path146 };
|
|
50800
51038
|
},
|
|
50801
51039
|
async remove(worktreeId) {
|
|
50802
|
-
const
|
|
50803
|
-
if (
|
|
51040
|
+
const path146 = paths.get(worktreeId);
|
|
51041
|
+
if (path146 === undefined)
|
|
50804
51042
|
return;
|
|
50805
|
-
await execFileAsync3("git", ["worktree", "remove", "--force",
|
|
51043
|
+
await execFileAsync3("git", ["worktree", "remove", "--force", path146], { cwd: repoRoot });
|
|
50806
51044
|
paths.delete(worktreeId);
|
|
50807
51045
|
await execFileAsync3("git", ["worktree", "prune"], { cwd: repoRoot }).catch(() => {
|
|
50808
51046
|
return;
|
|
50809
51047
|
});
|
|
50810
51048
|
},
|
|
50811
51049
|
async merge(worktreeId, into) {
|
|
50812
|
-
const
|
|
50813
|
-
if (
|
|
51050
|
+
const path146 = paths.get(worktreeId);
|
|
51051
|
+
if (path146 === undefined) {
|
|
50814
51052
|
return { worktreeId, ok: false, conflicts: [`worktree "${worktreeId}" was not created by this port`] };
|
|
50815
51053
|
}
|
|
50816
|
-
const status = await execFileAsync3("git", ["status", "--porcelain"], { cwd:
|
|
51054
|
+
const status = await execFileAsync3("git", ["status", "--porcelain"], { cwd: path146 });
|
|
50817
51055
|
if (status.stdout.trim().length === 0) {
|
|
50818
51056
|
return { worktreeId, ok: true };
|
|
50819
51057
|
}
|
|
@@ -51079,7 +51317,7 @@ function canNestExternalChild(env, maxDepth) {
|
|
|
51079
51317
|
// src/harness/external/runtime.ts
|
|
51080
51318
|
import { mkdtemp as mkdtemp2, rm as rm9, writeFile as writeFile48 } from "fs/promises";
|
|
51081
51319
|
import { tmpdir as tmpdir5 } from "os";
|
|
51082
|
-
import
|
|
51320
|
+
import path146 from "path";
|
|
51083
51321
|
|
|
51084
51322
|
// src/harness/external/prompt.ts
|
|
51085
51323
|
var EXTERNAL_RUNTIME_DIRECTIVE = [
|
|
@@ -52122,8 +52360,8 @@ async function prepareResultSchema() {
|
|
|
52122
52360
|
try {
|
|
52123
52361
|
const schema = await loadSchema("subagent-result");
|
|
52124
52362
|
const schemaText = JSON.stringify(schema, null, 2);
|
|
52125
|
-
schemaDir = await mkdtemp2(
|
|
52126
|
-
const schemaPath =
|
|
52363
|
+
schemaDir = await mkdtemp2(path146.join(tmpdir5(), "keryx-external-result-schema-"));
|
|
52364
|
+
const schemaPath = path146.join(schemaDir, "subagent-result.schema.json");
|
|
52127
52365
|
await writeFile48(schemaPath, schemaText, "utf8");
|
|
52128
52366
|
return { ok: true, schema, schemaText, schemaPath, schemaDir };
|
|
52129
52367
|
} catch (error2) {
|
|
@@ -52350,7 +52588,7 @@ async function defaultWorkingDiff(cwd) {
|
|
|
52350
52588
|
function ensuringParentDir(port, worktreesDir) {
|
|
52351
52589
|
return {
|
|
52352
52590
|
async create(worktreeId) {
|
|
52353
|
-
await
|
|
52591
|
+
await mkdir55(worktreesDir, { recursive: true });
|
|
52354
52592
|
return port.create(worktreeId);
|
|
52355
52593
|
},
|
|
52356
52594
|
remove: (worktreeId) => port.remove(worktreeId),
|
|
@@ -52380,7 +52618,7 @@ async function createRunExternal(options) {
|
|
|
52380
52618
|
}
|
|
52381
52619
|
const config = gate.config;
|
|
52382
52620
|
const idSeq = options.idSeq ?? (() => randomUUID22());
|
|
52383
|
-
const worktreesDir = options.worktreesDir ??
|
|
52621
|
+
const worktreesDir = options.worktreesDir ?? path147.join(tmpdir6(), "keryx-external-worktrees");
|
|
52384
52622
|
const spawn5 = options.spawn ?? createBunSpawnPort();
|
|
52385
52623
|
const worktree = options.worktree ?? ensuringParentDir(createGitWorktreePort({ repoRoot: options.cwd, worktreesDir }), worktreesDir);
|
|
52386
52624
|
const readWorkingDiff = options.readWorkingDiff ?? (() => defaultWorkingDiff(options.cwd));
|
|
@@ -52565,12 +52803,12 @@ async function approveExternalSpawn(request) {
|
|
|
52565
52803
|
import { homedir as homedir6 } from "os";
|
|
52566
52804
|
var ESC = "\x1B";
|
|
52567
52805
|
var CSI = `${ESC}[`;
|
|
52568
|
-
function collapseHome(
|
|
52806
|
+
function collapseHome(path148) {
|
|
52569
52807
|
const home = homedir6();
|
|
52570
|
-
if (home.length > 0 && (
|
|
52571
|
-
return `~${
|
|
52808
|
+
if (home.length > 0 && (path148 === home || path148.startsWith(`${home}/`))) {
|
|
52809
|
+
return `~${path148.slice(home.length)}`;
|
|
52572
52810
|
}
|
|
52573
|
-
return
|
|
52811
|
+
return path148;
|
|
52574
52812
|
}
|
|
52575
52813
|
|
|
52576
52814
|
// src/lib/live-render.ts
|
|
@@ -52676,7 +52914,7 @@ class LiveMarkdownBlock {
|
|
|
52676
52914
|
// src/tui/theme.ts
|
|
52677
52915
|
init_config_dir();
|
|
52678
52916
|
import { existsSync as existsSync26 } from "fs";
|
|
52679
|
-
import
|
|
52917
|
+
import path148 from "path";
|
|
52680
52918
|
var THEME_NAMES = ["groknight", "grokday", "tokyonight", "keryx"];
|
|
52681
52919
|
var THEME_IDS = ["auto", ...THEME_NAMES];
|
|
52682
52920
|
var DEFAULT_THEME_ID = "groknight";
|
|
@@ -52806,7 +53044,7 @@ function onThemeChange(listener4) {
|
|
|
52806
53044
|
};
|
|
52807
53045
|
}
|
|
52808
53046
|
function tuiConfigPath(dir) {
|
|
52809
|
-
return
|
|
53047
|
+
return path148.join(keryxConfigDir(dir), "tui.json");
|
|
52810
53048
|
}
|
|
52811
53049
|
function loadPersistedThemeId(dir) {
|
|
52812
53050
|
try {
|
|
@@ -52860,28 +53098,63 @@ init_slate_lifecycle();
|
|
|
52860
53098
|
init_slate();
|
|
52861
53099
|
init_workspace_service();
|
|
52862
53100
|
init_workspace_resolve();
|
|
53101
|
+
init_service7();
|
|
53102
|
+
init_fs();
|
|
53103
|
+
import path149 from "path";
|
|
53104
|
+
var POSITIVE_INTEGER = /^[1-9][0-9]*$/;
|
|
53105
|
+
var DEFAULT_AUTO_GOAL_ROUNDS = 8;
|
|
52863
53106
|
function parseGoalArgs(rest) {
|
|
52864
53107
|
const trimmed = rest.trim();
|
|
52865
53108
|
if (trimmed.length === 0) {
|
|
52866
|
-
return {
|
|
53109
|
+
return {
|
|
53110
|
+
error: "a goal <text> is required, e.g. /goal implement the login flow [--workspace <id>] [--auto [N]]"
|
|
53111
|
+
};
|
|
52867
53112
|
}
|
|
52868
|
-
|
|
52869
|
-
const lastToken = tokens[tokens.length - 1];
|
|
52870
|
-
const secondLastToken = tokens[tokens.length - 2];
|
|
53113
|
+
let tokens = trimmed.split(/\s+/);
|
|
52871
53114
|
let workspaceId;
|
|
52872
|
-
let
|
|
52873
|
-
|
|
52874
|
-
|
|
52875
|
-
|
|
52876
|
-
|
|
52877
|
-
|
|
52878
|
-
|
|
53115
|
+
let auto;
|
|
53116
|
+
let sawWorkspace = false;
|
|
53117
|
+
let sawAuto = false;
|
|
53118
|
+
for (let i = 0;i < 2; i++) {
|
|
53119
|
+
const last = tokens[tokens.length - 1];
|
|
53120
|
+
const secondLast = tokens[tokens.length - 2];
|
|
53121
|
+
if (!sawAuto && secondLast === "--auto" && last !== undefined && POSITIVE_INTEGER.test(last)) {
|
|
53122
|
+
auto = { rounds: Number(last) };
|
|
53123
|
+
sawAuto = true;
|
|
53124
|
+
tokens = tokens.slice(0, tokens.length - 2);
|
|
53125
|
+
continue;
|
|
53126
|
+
}
|
|
53127
|
+
if (!sawAuto && last === "--auto") {
|
|
53128
|
+
auto = {};
|
|
53129
|
+
sawAuto = true;
|
|
53130
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
53131
|
+
continue;
|
|
53132
|
+
}
|
|
53133
|
+
if (!sawWorkspace && last === "--workspace") {
|
|
53134
|
+
return { error: "--workspace requires a value, e.g. /goal <text> --workspace <id>" };
|
|
53135
|
+
}
|
|
53136
|
+
if (!sawWorkspace && secondLast === "--workspace") {
|
|
53137
|
+
workspaceId = last;
|
|
53138
|
+
sawWorkspace = true;
|
|
53139
|
+
tokens = tokens.slice(0, tokens.length - 2);
|
|
53140
|
+
continue;
|
|
53141
|
+
}
|
|
53142
|
+
break;
|
|
52879
53143
|
}
|
|
52880
|
-
const text =
|
|
53144
|
+
const text = tokens.join(" ").trim();
|
|
52881
53145
|
if (text.length === 0) {
|
|
52882
|
-
return {
|
|
53146
|
+
return {
|
|
53147
|
+
error: "a goal <text> is required, e.g. /goal implement the login flow [--workspace <id>] [--auto [N]]"
|
|
53148
|
+
};
|
|
53149
|
+
}
|
|
53150
|
+
const parsed = { text };
|
|
53151
|
+
if (workspaceId !== undefined) {
|
|
53152
|
+
parsed.workspaceId = workspaceId;
|
|
52883
53153
|
}
|
|
52884
|
-
|
|
53154
|
+
if (auto !== undefined) {
|
|
53155
|
+
parsed.auto = auto;
|
|
53156
|
+
}
|
|
53157
|
+
return parsed;
|
|
52885
53158
|
}
|
|
52886
53159
|
function systemLine(io, text) {
|
|
52887
53160
|
if (io.onSystem !== undefined) {
|
|
@@ -52890,6 +53163,113 @@ function systemLine(io, text) {
|
|
|
52890
53163
|
io.write(text);
|
|
52891
53164
|
}
|
|
52892
53165
|
}
|
|
53166
|
+
var flowService;
|
|
53167
|
+
function getFlowService() {
|
|
53168
|
+
flowService ??= createFlowService({
|
|
53169
|
+
tracker: null,
|
|
53170
|
+
healthGate: async () => ({ status: "skipped", reasons: [] }),
|
|
53171
|
+
now: () => new Date
|
|
53172
|
+
});
|
|
53173
|
+
return flowService;
|
|
53174
|
+
}
|
|
53175
|
+
async function autoProvisionFlow(cwd, goalText) {
|
|
53176
|
+
const service5 = getFlowService();
|
|
53177
|
+
const result = await service5.init({ cwd, title: goalText });
|
|
53178
|
+
const acFile = path149.join(cwd, result.dir, "acceptance-criteria.md");
|
|
53179
|
+
await writeFileAtomic(acFile, [
|
|
53180
|
+
"# Acceptance Criteria",
|
|
53181
|
+
"",
|
|
53182
|
+
"Rules:",
|
|
53183
|
+
"",
|
|
53184
|
+
"- Criteria lines use the exact format `- ACn: <criterion>`.",
|
|
53185
|
+
"- After `flow freeze` this file is checksum-protected: any edit outside",
|
|
53186
|
+
" `keryx flow ac update` fails every gate and status transition.",
|
|
53187
|
+
"- Completion requires every ACn to be confirmed via",
|
|
53188
|
+
" `keryx flow ac confirm <id> <ACn>`.",
|
|
53189
|
+
"",
|
|
53190
|
+
"Source: auto-provisioned by `/goal --auto` (SLATE-27, flow 186) \u2014 the",
|
|
53191
|
+
"goal text itself is the spec; no separate description/plan pair exists.",
|
|
53192
|
+
"",
|
|
53193
|
+
"## Criteria",
|
|
53194
|
+
"",
|
|
53195
|
+
`- AC1: The stated goal \u2014 "${goalText}" \u2014 is achieved, judged by the`,
|
|
53196
|
+
" verifier subagent this session's continuation loop runs before",
|
|
53197
|
+
" stopping (flow 186 T10).",
|
|
53198
|
+
""
|
|
53199
|
+
].join(`
|
|
53200
|
+
`));
|
|
53201
|
+
await service5.freeze({ cwd, id: result.flow.id });
|
|
53202
|
+
await service5.start({ cwd, id: result.flow.id });
|
|
53203
|
+
return result.flow.id;
|
|
53204
|
+
}
|
|
53205
|
+
async function buildContinuationMessage(cwd, slateSession, round4, roundsCap) {
|
|
53206
|
+
const totalRounds = roundsCap + 1;
|
|
53207
|
+
const generic = `Continue working toward the stated goal (round ${round4} of ${totalRounds}).`;
|
|
53208
|
+
const slate = await readSlate(slateSession.dir).catch(() => {
|
|
53209
|
+
return;
|
|
53210
|
+
});
|
|
53211
|
+
const flowId = slate?.course.flowRef;
|
|
53212
|
+
if (flowId === undefined) {
|
|
53213
|
+
return generic;
|
|
53214
|
+
}
|
|
53215
|
+
try {
|
|
53216
|
+
const flow = await getFlowService().get({ cwd, id: flowId });
|
|
53217
|
+
const remaining = flow.tasks.filter((task) => task.status !== "done");
|
|
53218
|
+
const remainingList = remaining.length > 0 ? remaining.map((task) => `${task.id}: ${task.title}`).join("; ") : "(no open tasks recorded)";
|
|
53219
|
+
return `${generic} Flow ${flowId} tasks remaining: ${remainingList}.`;
|
|
53220
|
+
} catch {
|
|
53221
|
+
return generic;
|
|
53222
|
+
}
|
|
53223
|
+
}
|
|
53224
|
+
function parseVerifierVerdict(output2) {
|
|
53225
|
+
const match = output2.match(/\{[\s\S]*\}/);
|
|
53226
|
+
if (match === null) {
|
|
53227
|
+
return;
|
|
53228
|
+
}
|
|
53229
|
+
try {
|
|
53230
|
+
const parsed = JSON.parse(match[0]);
|
|
53231
|
+
if (typeof parsed !== "object" || parsed === null || !("achieved" in parsed)) {
|
|
53232
|
+
return;
|
|
53233
|
+
}
|
|
53234
|
+
const achieved = parsed.achieved;
|
|
53235
|
+
if (typeof achieved !== "boolean") {
|
|
53236
|
+
return;
|
|
53237
|
+
}
|
|
53238
|
+
const gapsRaw = parsed.gaps;
|
|
53239
|
+
const gaps = Array.isArray(gapsRaw) ? gapsRaw.filter((g) => typeof g === "string") : [];
|
|
53240
|
+
return { achieved, gaps };
|
|
53241
|
+
} catch {
|
|
53242
|
+
return;
|
|
53243
|
+
}
|
|
53244
|
+
}
|
|
53245
|
+
async function runGoalVerifier(deps, goalText) {
|
|
53246
|
+
const tool = deps.tools.find((candidate) => candidate.definition.name === "spawn_subagent");
|
|
53247
|
+
if (tool === undefined) {
|
|
53248
|
+
return;
|
|
53249
|
+
}
|
|
53250
|
+
const task = [
|
|
53251
|
+
"Independently verify whether the following goal has ACTUALLY been achieved, based on the",
|
|
53252
|
+
"current, real state of the repository (read the real files/tests \u2014 never trust a prior",
|
|
53253
|
+
"claim in conversation history without checking it yourself).",
|
|
53254
|
+
"",
|
|
53255
|
+
`Goal: "${goalText}"`,
|
|
53256
|
+
"",
|
|
53257
|
+
"Reply with EXACTLY one JSON object and nothing else, no prose before or after it:",
|
|
53258
|
+
'{"achieved": true or false, "gaps": ["specific reason it is not fully achieved", ...]}',
|
|
53259
|
+
'"gaps" must be empty when "achieved" is true.'
|
|
53260
|
+
].join(`
|
|
53261
|
+
`);
|
|
53262
|
+
let result;
|
|
53263
|
+
try {
|
|
53264
|
+
result = await tool.invoke({ task, mode: "read_only", label: "goal-verifier" });
|
|
53265
|
+
} catch {
|
|
53266
|
+
return;
|
|
53267
|
+
}
|
|
53268
|
+
if (result.isError) {
|
|
53269
|
+
return;
|
|
53270
|
+
}
|
|
53271
|
+
return parseVerifierVerdict(result.output);
|
|
53272
|
+
}
|
|
52893
53273
|
async function runGoalCommand(params) {
|
|
52894
53274
|
const { raw, cwd, io, deps, history, slateSession, mintAttemptId, resolveWorkspace } = params;
|
|
52895
53275
|
const parsed = parseGoalArgs(raw);
|
|
@@ -52898,6 +53278,8 @@ async function runGoalCommand(params) {
|
|
|
52898
53278
|
`);
|
|
52899
53279
|
return;
|
|
52900
53280
|
}
|
|
53281
|
+
let boundFlowRef;
|
|
53282
|
+
let boundWorkspaceId;
|
|
52901
53283
|
if (parsed.workspaceId !== undefined) {
|
|
52902
53284
|
const resolved2 = await resolveWorkspaceForActor(cwd, parsed.workspaceId);
|
|
52903
53285
|
if (!resolved2.ok) {
|
|
@@ -52937,12 +53319,84 @@ async function runGoalCommand(params) {
|
|
|
52937
53319
|
}
|
|
52938
53320
|
}
|
|
52939
53321
|
}
|
|
53322
|
+
if (parsed.auto !== undefined) {
|
|
53323
|
+
const forCourse = await readSlate(slateSession.dir);
|
|
53324
|
+
let flowRefForBinding = forCourse?.course.flowRef;
|
|
53325
|
+
if (forCourse !== undefined && forCourse.course.flowRef === undefined) {
|
|
53326
|
+
const flowId = await autoProvisionFlow(cwd, parsed.text);
|
|
53327
|
+
await writeSlate(slateSession.dir, (prev) => {
|
|
53328
|
+
if (!prev)
|
|
53329
|
+
throw new Error(`SLATE-27 bind: no open slate in ${slateSession.dir}`);
|
|
53330
|
+
return { ...prev, course: { ...prev.course, flowRef: flowId } };
|
|
53331
|
+
});
|
|
53332
|
+
flowRefForBinding = flowId;
|
|
53333
|
+
}
|
|
53334
|
+
slateSession.autoGoalRounds = parsed.auto.rounds ?? DEFAULT_AUTO_GOAL_ROUNDS;
|
|
53335
|
+
boundFlowRef = flowRefForBinding;
|
|
53336
|
+
boundWorkspaceId = forCourse?.workspaceId;
|
|
53337
|
+
}
|
|
52940
53338
|
} catch (err) {
|
|
52941
53339
|
systemLine(io, `/goal: slate bookkeeping failed (ignored): ${err instanceof Error ? err.message : String(err)}
|
|
52942
53340
|
`);
|
|
52943
53341
|
}
|
|
52944
53342
|
}
|
|
52945
|
-
|
|
53343
|
+
const turnOptions = slateSession !== undefined ? { slateSession, skipCloseTrigger: true } : {};
|
|
53344
|
+
await runAgentTurn(io, deps, history, parsed.text, turnOptions);
|
|
53345
|
+
if (slateSession !== undefined && slateSession.autoGoalRounds !== undefined) {
|
|
53346
|
+
const roundsCap = slateSession.autoGoalRounds;
|
|
53347
|
+
delete slateSession.autoGoalRounds;
|
|
53348
|
+
let roundsLeft = roundsCap;
|
|
53349
|
+
let round4 = 1;
|
|
53350
|
+
while (roundsLeft > 0 && slateSession.opened) {
|
|
53351
|
+
roundsLeft -= 1;
|
|
53352
|
+
round4 += 1;
|
|
53353
|
+
const continuationText = await buildContinuationMessage(cwd, slateSession, round4, roundsCap);
|
|
53354
|
+
systemLine(io, `/goal --auto: round ${round4}/${roundsCap + 1} \u2014 continuing toward the goal.
|
|
53355
|
+
`);
|
|
53356
|
+
await runAgentTurn(io, deps, history, continuationText, turnOptions);
|
|
53357
|
+
}
|
|
53358
|
+
const wasOpenBeforeVerifier = slateSession.opened;
|
|
53359
|
+
const verdict = await runGoalVerifier(deps, parsed.text);
|
|
53360
|
+
if (verdict !== undefined && !verdict.achieved) {
|
|
53361
|
+
systemLine(io, `/goal --auto: verifier found the goal not fully achieved${verdict.gaps.length > 0 ? ` \u2014 ${verdict.gaps.join("; ")}` : " (no specific gaps reported)"}
|
|
53362
|
+
`);
|
|
53363
|
+
if (roundsLeft > 0) {
|
|
53364
|
+
let reopenOk = true;
|
|
53365
|
+
if (!wasOpenBeforeVerifier) {
|
|
53366
|
+
try {
|
|
53367
|
+
await ensureSlateOpened(slateSession, mintAttemptId, { provider: deps.providerId, model: deps.modelId });
|
|
53368
|
+
const reopened = await readSlate(slateSession.dir);
|
|
53369
|
+
if (reopened !== undefined) {
|
|
53370
|
+
history.push({ role: "user", content: renderAnchorsBlock(reopened.anchors), provenance: "project" });
|
|
53371
|
+
io.onHistoryChange?.("tool");
|
|
53372
|
+
}
|
|
53373
|
+
await writeSlate(slateSession.dir, (prev) => {
|
|
53374
|
+
if (!prev)
|
|
53375
|
+
throw new Error(`SLATE-27 verifier-reopen: no open slate in ${slateSession.dir}`);
|
|
53376
|
+
return {
|
|
53377
|
+
...prev,
|
|
53378
|
+
course: { ...prev.course, ...boundFlowRef !== undefined ? { flowRef: boundFlowRef } : {} },
|
|
53379
|
+
...boundWorkspaceId !== undefined ? { workspaceId: boundWorkspaceId } : {}
|
|
53380
|
+
};
|
|
53381
|
+
});
|
|
53382
|
+
} catch (err) {
|
|
53383
|
+
reopenOk = false;
|
|
53384
|
+
systemLine(io, `/goal --auto: could not reopen the slate for one more round (ignored): ${err instanceof Error ? err.message : String(err)}
|
|
53385
|
+
`);
|
|
53386
|
+
}
|
|
53387
|
+
}
|
|
53388
|
+
if (!reopenOk) {
|
|
53389
|
+
return;
|
|
53390
|
+
}
|
|
53391
|
+
roundsLeft -= 1;
|
|
53392
|
+
round4 += 1;
|
|
53393
|
+
const continuationText = await buildContinuationMessage(cwd, slateSession, round4, roundsCap);
|
|
53394
|
+
systemLine(io, `/goal --auto: round ${round4}/${roundsCap + 1} \u2014 one more round after the verifier found gaps.
|
|
53395
|
+
`);
|
|
53396
|
+
await runAgentTurn(io, deps, history, continuationText, turnOptions);
|
|
53397
|
+
}
|
|
53398
|
+
}
|
|
53399
|
+
}
|
|
52946
53400
|
}
|
|
52947
53401
|
|
|
52948
53402
|
// src/tui/tui-shell.ts
|
|
@@ -52951,7 +53405,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
52951
53405
|
// package.json
|
|
52952
53406
|
var package_default = {
|
|
52953
53407
|
name: "@mrciphersmith/keryx",
|
|
52954
|
-
version: "0.2.
|
|
53408
|
+
version: "0.2.53",
|
|
52955
53409
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
52956
53410
|
private: false,
|
|
52957
53411
|
publishConfig: {
|
|
@@ -53839,16 +54293,15 @@ var MODAL_PANEL_MARGIN = 1;
|
|
|
53839
54293
|
var MODAL_PANEL_CHROME_X = 4;
|
|
53840
54294
|
var MODAL_PANEL_MIN_WIDTH = 72;
|
|
53841
54295
|
var MODAL_PANEL_MIN_HEIGHT = 18;
|
|
53842
|
-
var
|
|
53843
|
-
var MODAL_PANEL_TARGET_HEIGHT = 28;
|
|
54296
|
+
var MODAL_PANEL_SIZE_RATIO = 0.95;
|
|
53844
54297
|
var MODAL_CHROME_ROWS = 5;
|
|
53845
54298
|
var MODAL_PANEL_WIDTH = MODAL_PANEL_MIN_WIDTH;
|
|
53846
54299
|
var MODAL_PANEL_HEIGHT = MODAL_PANEL_MIN_HEIGHT;
|
|
53847
54300
|
var MODAL_PANEL_INNER_WIDTH = MODAL_PANEL_MIN_WIDTH - MODAL_PANEL_CHROME_X;
|
|
53848
54301
|
function resolveModalPanelSize(cols, rows) {
|
|
53849
54302
|
return {
|
|
53850
|
-
width: Math.
|
|
53851
|
-
height: Math.
|
|
54303
|
+
width: Math.max(MODAL_PANEL_MIN_WIDTH, Math.round(cols * MODAL_PANEL_SIZE_RATIO)),
|
|
54304
|
+
height: Math.max(MODAL_PANEL_MIN_HEIGHT, Math.round(rows * MODAL_PANEL_SIZE_RATIO))
|
|
53852
54305
|
};
|
|
53853
54306
|
}
|
|
53854
54307
|
function modalBodyRows(panelHeight) {
|
|
@@ -54212,8 +54665,8 @@ init_store3();
|
|
|
54212
54665
|
init_proposal_lifecycle();
|
|
54213
54666
|
init_workspace_service();
|
|
54214
54667
|
import { randomUUID as randomUUID24 } from "crypto";
|
|
54215
|
-
import { readdir as
|
|
54216
|
-
import
|
|
54668
|
+
import { readdir as readdir26 } from "fs/promises";
|
|
54669
|
+
import path150 from "path";
|
|
54217
54670
|
|
|
54218
54671
|
// src/sac/lifecycle-flag.ts
|
|
54219
54672
|
init_store();
|
|
@@ -54351,12 +54804,12 @@ async function collectSessionCategories(cwd) {
|
|
|
54351
54804
|
return { blocked: blocked2, unboundCandidates, unknown };
|
|
54352
54805
|
}
|
|
54353
54806
|
async function isSlateEngaged(dir) {
|
|
54354
|
-
if (await pathExists(
|
|
54807
|
+
if (await pathExists(path150.join(dir, "slate.json")))
|
|
54355
54808
|
return true;
|
|
54356
|
-
if (await pathExists(
|
|
54809
|
+
if (await pathExists(path150.join(dir, "terminal-state.json")))
|
|
54357
54810
|
return true;
|
|
54358
54811
|
try {
|
|
54359
|
-
const entries = await
|
|
54812
|
+
const entries = await readdir26(path150.join(dir, "slate-archive"));
|
|
54360
54813
|
return entries.length > 0;
|
|
54361
54814
|
} catch {
|
|
54362
54815
|
return false;
|
|
@@ -54370,7 +54823,7 @@ async function safeReadSlate(dir) {
|
|
|
54370
54823
|
}
|
|
54371
54824
|
}
|
|
54372
54825
|
async function readTerminalState(dir) {
|
|
54373
|
-
const result = readConfigFile(
|
|
54826
|
+
const result = readConfigFile(path150.join(dir, "terminal-state.json"));
|
|
54374
54827
|
if (!result.ok) {
|
|
54375
54828
|
return;
|
|
54376
54829
|
}
|
|
@@ -54381,16 +54834,16 @@ async function readTerminalState(dir) {
|
|
|
54381
54834
|
}
|
|
54382
54835
|
}
|
|
54383
54836
|
async function readNewestUnboundCandidate(dir) {
|
|
54384
|
-
const archiveDir =
|
|
54837
|
+
const archiveDir = path150.join(dir, "slate-archive");
|
|
54385
54838
|
let entries;
|
|
54386
54839
|
try {
|
|
54387
|
-
entries = (await
|
|
54840
|
+
entries = (await readdir26(archiveDir)).filter((name) => name.endsWith("-unbound-candidate.json"));
|
|
54388
54841
|
} catch {
|
|
54389
54842
|
return;
|
|
54390
54843
|
}
|
|
54391
54844
|
entries.sort();
|
|
54392
54845
|
for (let i = entries.length - 1;i >= 0; i--) {
|
|
54393
|
-
const evidencePath =
|
|
54846
|
+
const evidencePath = path150.join(archiveDir, entries[i]);
|
|
54394
54847
|
const result = readConfigFile(evidencePath);
|
|
54395
54848
|
if (!result.ok) {
|
|
54396
54849
|
continue;
|
|
@@ -54418,16 +54871,16 @@ function isFailureOutcome(g) {
|
|
|
54418
54871
|
return g.outcome === "error" || g.outcome === "no_credential" || g.outcome === "conflict";
|
|
54419
54872
|
}
|
|
54420
54873
|
async function readNewestWrapUpOutcome(dir) {
|
|
54421
|
-
const archiveDir =
|
|
54874
|
+
const archiveDir = path150.join(dir, "slate-archive");
|
|
54422
54875
|
let entries;
|
|
54423
54876
|
try {
|
|
54424
|
-
entries = (await
|
|
54877
|
+
entries = (await readdir26(archiveDir)).filter((name) => name.endsWith("-wrap-up-outcome.json"));
|
|
54425
54878
|
} catch {
|
|
54426
54879
|
return;
|
|
54427
54880
|
}
|
|
54428
54881
|
entries.sort();
|
|
54429
54882
|
for (let i = entries.length - 1;i >= 0; i--) {
|
|
54430
|
-
const evidencePath =
|
|
54883
|
+
const evidencePath = path150.join(archiveDir, entries[i]);
|
|
54431
54884
|
const result = readConfigFile(evidencePath);
|
|
54432
54885
|
if (!result.ok) {
|
|
54433
54886
|
continue;
|
|
@@ -55532,6 +55985,7 @@ async function declineProposalViaShell(run, workspaceId, proposalId) {
|
|
|
55532
55985
|
// src/tui/mcp-inspector.ts
|
|
55533
55986
|
var MCP_INSPECTOR_FOOTER = [
|
|
55534
55987
|
{ key: "\u2191/\u2193", label: "select" },
|
|
55988
|
+
{ key: "click", label: "row: select/act" },
|
|
55535
55989
|
{ key: "c/d", label: "connect/disconnect" },
|
|
55536
55990
|
{ key: "y", label: "confirm" },
|
|
55537
55991
|
{ key: "\u2190/\u2192", label: "tabs" },
|
|
@@ -55542,6 +55996,9 @@ function isMcpToolsCommand(line) {
|
|
|
55542
55996
|
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
55543
55997
|
return token === MCP_TOOLS_COMMAND;
|
|
55544
55998
|
}
|
|
55999
|
+
var TOOLS_TAB_HEADER = "Built into keryx \u2014 not from an external MCP server (keryx doesn't consume MCP servers as a client yet).";
|
|
56000
|
+
var MCP_TAB_HEADER_1 = "Connects/disconnects ONLY keryx's own MCP server, one editor config at a time.";
|
|
56001
|
+
var MCP_TAB_HEADER_2 = "Other MCP servers already configured there (context7, playwright, \u2026) show per row, read-only.";
|
|
55545
56002
|
var RUNTIME_LABELS = {
|
|
55546
56003
|
cursor: "Cursor",
|
|
55547
56004
|
claude: "Claude Code",
|
|
@@ -55552,41 +56009,52 @@ var RUNTIME_LABELS = {
|
|
|
55552
56009
|
function runtimeLabel(id) {
|
|
55553
56010
|
return RUNTIME_LABELS[id] ?? id;
|
|
55554
56011
|
}
|
|
55555
|
-
function
|
|
55556
|
-
|
|
55557
|
-
|
|
55558
|
-
}
|
|
55559
|
-
return tools.map((tool) => {
|
|
55560
|
-
const risk = (tool.risk ?? "read").padEnd(6);
|
|
55561
|
-
const name = tool.name.padEnd(28);
|
|
55562
|
-
return `${name} ${risk} ${tool.description ?? ""}`.trimEnd();
|
|
55563
|
-
});
|
|
56012
|
+
function formatToolRowLine(tool) {
|
|
56013
|
+
const risk = (tool.risk ?? "read").padEnd(6);
|
|
56014
|
+
const name = tool.name.padEnd(28);
|
|
56015
|
+
return `${name} ${risk} ${tool.description ?? ""}`.trimEnd();
|
|
55564
56016
|
}
|
|
55565
56017
|
function isActionable(id) {
|
|
55566
56018
|
return id !== "generic";
|
|
55567
56019
|
}
|
|
55568
|
-
|
|
55569
|
-
|
|
55570
|
-
|
|
56020
|
+
var MAX_OTHER_SERVERS_SHOWN = 4;
|
|
56021
|
+
function formatOtherServers(otherServers) {
|
|
56022
|
+
if (otherServers.length === 0) {
|
|
56023
|
+
return "";
|
|
55571
56024
|
}
|
|
55572
|
-
|
|
55573
|
-
|
|
55574
|
-
|
|
55575
|
-
|
|
55576
|
-
|
|
55577
|
-
|
|
55578
|
-
|
|
55579
|
-
|
|
55580
|
-
|
|
55581
|
-
|
|
55582
|
-
|
|
55583
|
-
|
|
55584
|
-
|
|
55585
|
-
|
|
55586
|
-
|
|
55587
|
-
}
|
|
55588
|
-
|
|
55589
|
-
}
|
|
56025
|
+
const shown = otherServers.slice(0, MAX_OTHER_SERVERS_SHOWN);
|
|
56026
|
+
const rest = otherServers.length - shown.length;
|
|
56027
|
+
const list2 = rest > 0 ? `${shown.join(", ")}, +${rest} more` : shown.join(", ");
|
|
56028
|
+
return ` \xB7 also has: ${list2}`;
|
|
56029
|
+
}
|
|
56030
|
+
function formatMcpRowLine(runtime, isSelected, status) {
|
|
56031
|
+
const mark = isSelected ? ">" : " ";
|
|
56032
|
+
const label = runtimeLabel(runtime.id).padEnd(20);
|
|
56033
|
+
const statusText = runtime.connected ? "\u25CF keryx connected" : "\u25CB keryx not connected";
|
|
56034
|
+
let action = "";
|
|
56035
|
+
if (!isActionable(runtime.id)) {
|
|
56036
|
+
action = " (copy snippet manually)";
|
|
56037
|
+
} else if (status.kind === "armed" && status.target.id === runtime.id) {
|
|
56038
|
+
action = ` [click again or press y to ${status.target.action}]`;
|
|
56039
|
+
} else if (status.kind === "running" && status.target.id === runtime.id) {
|
|
56040
|
+
action = ` ${status.target.action === "connect" ? "connecting\u2026" : "disconnecting\u2026"}`;
|
|
56041
|
+
} else if (status.kind === "done" && status.target.id === runtime.id) {
|
|
56042
|
+
action = status.outcome.ok ? " \u2713 done" : ` \u2717 ${status.outcome.message}`;
|
|
56043
|
+
} else {
|
|
56044
|
+
action = runtime.connected ? " [d] disconnect" : " [c] connect";
|
|
56045
|
+
}
|
|
56046
|
+
return `${mark} ${label} ${statusText}${action}${formatOtherServers(runtime.otherServers)}`;
|
|
56047
|
+
}
|
|
56048
|
+
function asRowTarget(body) {
|
|
56049
|
+
const parent = body;
|
|
56050
|
+
if (parent.add === undefined || parent.getChildren === undefined || parent.remove === undefined) {
|
|
56051
|
+
return;
|
|
56052
|
+
}
|
|
56053
|
+
return {
|
|
56054
|
+
add: parent.add.bind(parent),
|
|
56055
|
+
getChildren: parent.getChildren.bind(parent),
|
|
56056
|
+
remove: parent.remove.bind(parent)
|
|
56057
|
+
};
|
|
55590
56058
|
}
|
|
55591
56059
|
function presentMcpTools(openModal2, otui, chrome, options) {
|
|
55592
56060
|
const runtimes = options.runtimes.map((r) => ({ ...r }));
|
|
@@ -55594,25 +56062,55 @@ function presentMcpTools(openModal2, otui, chrome, options) {
|
|
|
55594
56062
|
let toolsScroll = 0;
|
|
55595
56063
|
let mcpScroll = 0;
|
|
55596
56064
|
let status = { kind: "idle" };
|
|
55597
|
-
let
|
|
55598
|
-
let
|
|
56065
|
+
let toolsBody;
|
|
56066
|
+
let mcpBody;
|
|
56067
|
+
let rowCtor;
|
|
56068
|
+
let activeRenderer;
|
|
55599
56069
|
let unsubscribeKey;
|
|
55600
56070
|
const rendererHint = options.renderer ?? chrome?.renderer;
|
|
55601
56071
|
const bodyRows = options.visibleRows ?? (typeof rendererHint?.width === "number" && typeof rendererHint.height === "number" ? modalBodyRows(resolveModalPanelSize(rendererHint.width, rendererHint.height).height) : 13);
|
|
55602
|
-
const
|
|
55603
|
-
|
|
55604
|
-
|
|
55605
|
-
toolsScroll = clampScroll3(toolsScroll, toolLines().length, bodyRows);
|
|
55606
|
-
mcpScroll = scrollToReveal3(mcpSelected, mcpScroll, bodyRows);
|
|
55607
|
-
mcpScroll = clampScroll3(mcpScroll, mcpLines().length, bodyRows);
|
|
55608
|
-
if (toolsNode !== undefined) {
|
|
55609
|
-
toolsNode.content = windowLines3(toolLines(), toolsScroll, bodyRows).join(`
|
|
55610
|
-
`);
|
|
56072
|
+
const paintToolsRows = () => {
|
|
56073
|
+
if (toolsBody === undefined || rowCtor === undefined) {
|
|
56074
|
+
return;
|
|
55611
56075
|
}
|
|
55612
|
-
|
|
55613
|
-
|
|
55614
|
-
|
|
56076
|
+
clearTranscriptChildren(toolsBody);
|
|
56077
|
+
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-header", content: TOOLS_TAB_HEADER }));
|
|
56078
|
+
if (options.tools.length === 0) {
|
|
56079
|
+
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-empty", content: "No tools available." }));
|
|
56080
|
+
return;
|
|
56081
|
+
}
|
|
56082
|
+
const start = clampScroll3(toolsScroll, options.tools.length, bodyRows);
|
|
56083
|
+
for (const [i, tool] of options.tools.slice(start, start + bodyRows).entries()) {
|
|
56084
|
+
toolsBody.add(new rowCtor(activeRenderer, { id: `mcp-tool-row-${start + i}`, content: formatToolRowLine(tool) }));
|
|
56085
|
+
}
|
|
56086
|
+
};
|
|
56087
|
+
const paintMcpRows = () => {
|
|
56088
|
+
if (mcpBody === undefined || rowCtor === undefined) {
|
|
56089
|
+
return;
|
|
55615
56090
|
}
|
|
56091
|
+
clearTranscriptChildren(mcpBody);
|
|
56092
|
+
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-header-1", content: MCP_TAB_HEADER_1 }));
|
|
56093
|
+
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-header-2", content: MCP_TAB_HEADER_2 }));
|
|
56094
|
+
if (runtimes.length === 0) {
|
|
56095
|
+
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-empty", content: "No MCP client runtimes registered." }));
|
|
56096
|
+
return;
|
|
56097
|
+
}
|
|
56098
|
+
const start = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
56099
|
+
for (const [i, runtime] of runtimes.slice(start, start + bodyRows).entries()) {
|
|
56100
|
+
const index = start + i;
|
|
56101
|
+
mcpBody.add(new rowCtor(activeRenderer, {
|
|
56102
|
+
id: `mcp-row-${runtime.id}`,
|
|
56103
|
+
content: formatMcpRowLine(runtime, index === mcpSelected, status),
|
|
56104
|
+
onMouseDown: () => handleRowClick(runtime.id, index)
|
|
56105
|
+
}));
|
|
56106
|
+
}
|
|
56107
|
+
};
|
|
56108
|
+
const paint = () => {
|
|
56109
|
+
toolsScroll = clampScroll3(toolsScroll, options.tools.length, bodyRows);
|
|
56110
|
+
mcpScroll = scrollToReveal3(mcpSelected, mcpScroll, bodyRows);
|
|
56111
|
+
mcpScroll = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
56112
|
+
paintToolsRows();
|
|
56113
|
+
paintMcpRows();
|
|
55616
56114
|
};
|
|
55617
56115
|
const moveMcpSelection = (next) => {
|
|
55618
56116
|
if (runtimes.length === 0) {
|
|
@@ -55646,32 +56144,60 @@ function presentMcpTools(openModal2, otui, chrome, options) {
|
|
|
55646
56144
|
paint();
|
|
55647
56145
|
});
|
|
55648
56146
|
};
|
|
56147
|
+
const armFor = (id) => {
|
|
56148
|
+
const index = runtimes.findIndex((r) => r.id === id);
|
|
56149
|
+
const row = runtimes[index];
|
|
56150
|
+
if (index < 0 || row === undefined || !isActionable(row.id) || status.kind === "running") {
|
|
56151
|
+
return;
|
|
56152
|
+
}
|
|
56153
|
+
mcpSelected = index;
|
|
56154
|
+
status = { kind: "armed", target: { id: row.id, action: row.connected ? "disconnect" : "connect" } };
|
|
56155
|
+
paint();
|
|
56156
|
+
};
|
|
56157
|
+
const handleRowClick = (id, index) => {
|
|
56158
|
+
if (status.kind === "armed" && status.target.id === id) {
|
|
56159
|
+
runAction();
|
|
56160
|
+
return;
|
|
56161
|
+
}
|
|
56162
|
+
if (status.kind === "running") {
|
|
56163
|
+
return;
|
|
56164
|
+
}
|
|
56165
|
+
if (!isActionable(id)) {
|
|
56166
|
+
if (index !== mcpSelected) {
|
|
56167
|
+
mcpSelected = index;
|
|
56168
|
+
status = { kind: "idle" };
|
|
56169
|
+
paint();
|
|
56170
|
+
}
|
|
56171
|
+
return;
|
|
56172
|
+
}
|
|
56173
|
+
armFor(id);
|
|
56174
|
+
};
|
|
55649
56175
|
const handle = openModal2(otui, chrome, {
|
|
55650
56176
|
title: "Tools & MCP",
|
|
55651
56177
|
tabs: [
|
|
55652
56178
|
{ id: "tools", label: "Tools" },
|
|
55653
|
-
{ id: "mcp", label: "MCP" }
|
|
56179
|
+
{ id: "mcp", label: "MCP Clients" }
|
|
55654
56180
|
],
|
|
55655
56181
|
initialTab: "tools",
|
|
55656
56182
|
footer: MCP_INSPECTOR_FOOTER,
|
|
55657
56183
|
renderTab: (tabId, body, ctx) => {
|
|
55658
56184
|
const renderer = options.renderer ?? chrome?.renderer;
|
|
55659
|
-
const parent = body;
|
|
55660
56185
|
const ctor = otui.TextRenderable;
|
|
55661
|
-
|
|
56186
|
+
const target = asRowTarget(body);
|
|
56187
|
+
if (target === undefined || ctor === undefined) {
|
|
55662
56188
|
return;
|
|
55663
56189
|
}
|
|
56190
|
+
rowCtor = ctor;
|
|
56191
|
+
activeRenderer = renderer;
|
|
55664
56192
|
if (tabId === "tools") {
|
|
55665
|
-
|
|
55666
|
-
|
|
55667
|
-
|
|
55668
|
-
parent.add(toolsNode);
|
|
56193
|
+
toolsBody = target;
|
|
56194
|
+
toolsScroll = clampScroll3(toolsScroll, options.tools.length, bodyRows);
|
|
56195
|
+
paintToolsRows();
|
|
55669
56196
|
return;
|
|
55670
56197
|
}
|
|
56198
|
+
mcpBody = target;
|
|
55671
56199
|
mcpScroll = scrollToReveal3(mcpSelected, mcpScroll, bodyRows);
|
|
55672
|
-
|
|
55673
|
-
`) });
|
|
55674
|
-
parent.add(mcpNode);
|
|
56200
|
+
paintMcpRows();
|
|
55675
56201
|
},
|
|
55676
56202
|
onClose: () => {
|
|
55677
56203
|
unsubscribeKey?.();
|
|
@@ -55713,7 +56239,7 @@ function presentMcpTools(openModal2, otui, chrome, options) {
|
|
|
55713
56239
|
if (onMcp) {
|
|
55714
56240
|
moveMcpSelection(mcpSelected - 1);
|
|
55715
56241
|
} else {
|
|
55716
|
-
toolsScroll = clampScroll3(toolsScroll - 1,
|
|
56242
|
+
toolsScroll = clampScroll3(toolsScroll - 1, options.tools.length, bodyRows);
|
|
55717
56243
|
paint();
|
|
55718
56244
|
}
|
|
55719
56245
|
return;
|
|
@@ -55722,7 +56248,7 @@ function presentMcpTools(openModal2, otui, chrome, options) {
|
|
|
55722
56248
|
if (onMcp) {
|
|
55723
56249
|
moveMcpSelection(mcpSelected + 1);
|
|
55724
56250
|
} else {
|
|
55725
|
-
toolsScroll = clampScroll3(toolsScroll + 1,
|
|
56251
|
+
toolsScroll = clampScroll3(toolsScroll + 1, options.tools.length, bodyRows);
|
|
55726
56252
|
paint();
|
|
55727
56253
|
}
|
|
55728
56254
|
return;
|
|
@@ -55730,9 +56256,9 @@ function presentMcpTools(openModal2, otui, chrome, options) {
|
|
|
55730
56256
|
if (token === "pageup" || token === "pagedown") {
|
|
55731
56257
|
const step = token === "pageup" ? -bodyRows : bodyRows;
|
|
55732
56258
|
if (onMcp) {
|
|
55733
|
-
mcpScroll = clampScroll3(mcpScroll + step,
|
|
56259
|
+
mcpScroll = clampScroll3(mcpScroll + step, runtimes.length, bodyRows);
|
|
55734
56260
|
} else {
|
|
55735
|
-
toolsScroll = clampScroll3(toolsScroll + step,
|
|
56261
|
+
toolsScroll = clampScroll3(toolsScroll + step, options.tools.length, bodyRows);
|
|
55736
56262
|
}
|
|
55737
56263
|
paint();
|
|
55738
56264
|
}
|
|
@@ -56092,7 +56618,7 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
56092
56618
|
{ name: "/new", description: "Start a new session (old kept on disk)", modes: BOTH },
|
|
56093
56619
|
{
|
|
56094
56620
|
name: "/goal",
|
|
56095
|
-
description: "Deterministically start a goal \u2014 /goal <text> [--workspace <id>]",
|
|
56621
|
+
description: "Deterministically start a goal \u2014 /goal <text> [--workspace <id>] [--auto [N]]",
|
|
56096
56622
|
modes: AGENT_ONLY
|
|
56097
56623
|
},
|
|
56098
56624
|
{ name: "/resume", description: "Resume a prior session in this project", modes: AGENT_ONLY },
|
|
@@ -56184,7 +56710,7 @@ function commandsForMode(mode) {
|
|
|
56184
56710
|
}));
|
|
56185
56711
|
}
|
|
56186
56712
|
function filterCommands(query, mode) {
|
|
56187
|
-
const q = query.
|
|
56713
|
+
const q = query.toLowerCase();
|
|
56188
56714
|
if (!q.startsWith("/")) {
|
|
56189
56715
|
return [];
|
|
56190
56716
|
}
|
|
@@ -56542,10 +57068,10 @@ function describeElicitationPrompt(tool, inputJson) {
|
|
|
56542
57068
|
// src/lib/permission-mode-config.ts
|
|
56543
57069
|
init_permission_mode();
|
|
56544
57070
|
init_config_dir();
|
|
56545
|
-
import
|
|
57071
|
+
import path151 from "path";
|
|
56546
57072
|
var EMPTY3 = { schemaVersion: 1, projects: {} };
|
|
56547
57073
|
function permissionModeConfigPath(dir) {
|
|
56548
|
-
return
|
|
57074
|
+
return path151.join(keryxConfigDir(dir), "permission-mode.json");
|
|
56549
57075
|
}
|
|
56550
57076
|
function withRegistryLock2(dir, fn) {
|
|
56551
57077
|
return withFileLock(`${permissionModeConfigPath(dir)}.lock`, fn, {
|
|
@@ -56894,7 +57420,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
56894
57420
|
// src/lib/version-check.ts
|
|
56895
57421
|
init_config_dir();
|
|
56896
57422
|
init_fs();
|
|
56897
|
-
import
|
|
57423
|
+
import path152 from "path";
|
|
56898
57424
|
var REGISTRY_URL = "https://registry.npmjs.org/@mrciphersmith%2Fkeryx/latest";
|
|
56899
57425
|
var FIXED_INSTALL_COMMAND = "npm install -g @mrciphersmith/keryx@latest";
|
|
56900
57426
|
var RESPONSE_BODY_LIMIT_BYTES = 64 * 1024;
|
|
@@ -57096,7 +57622,7 @@ async function checkVersion(options) {
|
|
|
57096
57622
|
const now = options.now ?? Date.now;
|
|
57097
57623
|
const timestamp = now();
|
|
57098
57624
|
const configDir = ensureKeryxConfigDir(options.cacheDir);
|
|
57099
|
-
const cacheFile =
|
|
57625
|
+
const cacheFile = path152.join(configDir, "version-check.json");
|
|
57100
57626
|
const cache = parseCache(cacheFile);
|
|
57101
57627
|
if (cache?.latestVersion !== undefined && cache.successAt !== undefined && timestamp - cache.successAt >= 0 && timestamp - cache.successAt < SUCCESS_CACHE_TTL_MS) {
|
|
57102
57628
|
return resultFor(options.currentVersion, current, cache.latestVersion, "cache");
|
|
@@ -57214,7 +57740,7 @@ function wrappedLineCount(text, width) {
|
|
|
57214
57740
|
return total;
|
|
57215
57741
|
}
|
|
57216
57742
|
function prefixFilter(commands, query) {
|
|
57217
|
-
const q = query.
|
|
57743
|
+
const q = query.toLowerCase();
|
|
57218
57744
|
if (!q.startsWith("/")) {
|
|
57219
57745
|
return [];
|
|
57220
57746
|
}
|
|
@@ -57632,6 +58158,17 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
57632
58158
|
key.stopPropagation();
|
|
57633
58159
|
return;
|
|
57634
58160
|
}
|
|
58161
|
+
if (key.name === "tab") {
|
|
58162
|
+
const opt = menu.getSelectedOption();
|
|
58163
|
+
if (opt !== null) {
|
|
58164
|
+
input2.value = `${opt.name} `;
|
|
58165
|
+
}
|
|
58166
|
+
hideMenu();
|
|
58167
|
+
input2.focus();
|
|
58168
|
+
key.preventDefault();
|
|
58169
|
+
key.stopPropagation();
|
|
58170
|
+
return;
|
|
58171
|
+
}
|
|
57635
58172
|
if (key.name === "backspace") {
|
|
57636
58173
|
input2.value = input2.value.slice(0, -1);
|
|
57637
58174
|
refilter();
|
|
@@ -65137,9 +65674,9 @@ Shell:
|
|
|
65137
65674
|
|
|
65138
65675
|
// src/commands/modules.ts
|
|
65139
65676
|
init_fs();
|
|
65140
|
-
import { readFile as
|
|
65677
|
+
import { readFile as readFile79 } from "fs/promises";
|
|
65141
65678
|
import { stdin } from "process";
|
|
65142
|
-
import
|
|
65679
|
+
import path153 from "path";
|
|
65143
65680
|
var MODULES = [
|
|
65144
65681
|
{ name: "gdgraph", flag: "--no-gdgraph", desc: "code graph, symbols, affected context", defaultEnabled: true },
|
|
65145
65682
|
{ name: "gdctx", flag: "--no-gdctx", desc: "token-aware command/read output", defaultEnabled: true },
|
|
@@ -65185,8 +65722,8 @@ async function modulesCommand(args2 = []) {
|
|
|
65185
65722
|
return;
|
|
65186
65723
|
}
|
|
65187
65724
|
const wantsJson = args2.includes("--json") && (sub === undefined || sub === "status" || sub === "list" || sub === "--json");
|
|
65188
|
-
const metaprojectRoot =
|
|
65189
|
-
const manifestPath =
|
|
65725
|
+
const metaprojectRoot = path153.join(process.cwd(), ".metaproject");
|
|
65726
|
+
const manifestPath = path153.join(metaprojectRoot, "metaproject.json");
|
|
65190
65727
|
if (!await pathExists(manifestPath)) {
|
|
65191
65728
|
if (wantsJson) {
|
|
65192
65729
|
console.log(JSON.stringify({ schemaVersion: 1, error: "not-initialized", modules: [] }, null, 2));
|
|
@@ -65199,7 +65736,7 @@ async function modulesCommand(args2 = []) {
|
|
|
65199
65736
|
}
|
|
65200
65737
|
let manifest = {};
|
|
65201
65738
|
try {
|
|
65202
|
-
manifest = JSON.parse(await
|
|
65739
|
+
manifest = JSON.parse(await readFile79(manifestPath, "utf8"));
|
|
65203
65740
|
} catch {}
|
|
65204
65741
|
const enabled = new Set(MODULES.filter((module) => manifest.modules?.[module.name]?.enabled === true).map((module) => module.name));
|
|
65205
65742
|
if (wantsJson) {
|
|
@@ -65305,13 +65842,13 @@ import { randomUUID as randomUUID29 } from "crypto";
|
|
|
65305
65842
|
// src/lib/serve-config.ts
|
|
65306
65843
|
init_config_dir();
|
|
65307
65844
|
import { existsSync as existsSync27 } from "fs";
|
|
65308
|
-
import
|
|
65845
|
+
import path154 from "path";
|
|
65309
65846
|
var SERVE_CONFIG_SCHEMA_VERSION = "1.0.0";
|
|
65310
65847
|
var DEFAULT_SERVE_BIND_ADDRESS = "127.0.0.1";
|
|
65311
65848
|
var DEFAULT_SERVE_PORT = 7377;
|
|
65312
65849
|
var DEFAULT_SERVE_PROFILE = "remote-restricted";
|
|
65313
65850
|
function serveConfigPath(dir) {
|
|
65314
|
-
return
|
|
65851
|
+
return path154.join(keryxConfigDir(dir), "serve.json");
|
|
65315
65852
|
}
|
|
65316
65853
|
function parseIpv4(value) {
|
|
65317
65854
|
const parts = value.split(".");
|
|
@@ -65639,9 +66176,9 @@ import {
|
|
|
65639
66176
|
unlinkSync as unlinkSync3,
|
|
65640
66177
|
writeFileSync as writeFileSync8
|
|
65641
66178
|
} from "fs";
|
|
65642
|
-
import
|
|
66179
|
+
import path155 from "path";
|
|
65643
66180
|
function serveCredentialPath(dir) {
|
|
65644
|
-
return
|
|
66181
|
+
return path155.join(keryxConfigDir(dir), "serve-credentials.json");
|
|
65645
66182
|
}
|
|
65646
66183
|
function constantTimeEqual(a, b) {
|
|
65647
66184
|
const width = Math.max(a.length, b.length);
|
|
@@ -65875,22 +66412,22 @@ class AuthFailureThrottle {
|
|
|
65875
66412
|
init_config_dir();
|
|
65876
66413
|
import { createHash as createHash34 } from "crypto";
|
|
65877
66414
|
import { existsSync as existsSync29, readdirSync as readdirSync2, rmSync as rmSync2 } from "fs";
|
|
65878
|
-
import
|
|
66415
|
+
import path156 from "path";
|
|
65879
66416
|
var MAX_TURN_EVENTS = 1e4;
|
|
65880
66417
|
function turnsRoot(dir) {
|
|
65881
|
-
return
|
|
66418
|
+
return path156.join(keryxConfigDir(dir), "turns");
|
|
65882
66419
|
}
|
|
65883
66420
|
function turnDir(turnId, dir) {
|
|
65884
|
-
return
|
|
66421
|
+
return path156.join(turnsRoot(dir), turnId);
|
|
65885
66422
|
}
|
|
65886
66423
|
function keyPath(project, idempotencyKey, dir) {
|
|
65887
66424
|
const projectBytes = Buffer.byteLength(project, "utf8");
|
|
65888
66425
|
const digest2 = createHash34("sha256").update(`${projectBytes}:${project}\x00${idempotencyKey}`, "utf8").digest("hex");
|
|
65889
|
-
return
|
|
66426
|
+
return path156.join(turnsRoot(dir), "keys", `${digest2}.json`);
|
|
65890
66427
|
}
|
|
65891
66428
|
function legacyKeyPath(idempotencyKey, dir) {
|
|
65892
66429
|
const digest2 = createHash34("sha256").update(idempotencyKey, "utf8").digest("hex");
|
|
65893
|
-
return
|
|
66430
|
+
return path156.join(turnsRoot(dir), "keys", `${digest2}.json`);
|
|
65894
66431
|
}
|
|
65895
66432
|
function adoptLegacyClaim(project, idempotencyKey, dir) {
|
|
65896
66433
|
const legacy = legacyKeyPath(idempotencyKey, dir);
|
|
@@ -65954,7 +66491,7 @@ function ensureTurnDir(turnId, dir) {
|
|
|
65954
66491
|
}
|
|
65955
66492
|
function createTurnRecord(record, dir) {
|
|
65956
66493
|
ensureTurnDir(record.turnId, dir);
|
|
65957
|
-
writeOwnerOnlyFile(
|
|
66494
|
+
writeOwnerOnlyFile(path156.join(turnDir(record.turnId, dir), "turn.json"), `${JSON.stringify(record, null, 2)}
|
|
65958
66495
|
`);
|
|
65959
66496
|
}
|
|
65960
66497
|
function appendTurnEvent(event, dir, opts) {
|
|
@@ -65963,12 +66500,12 @@ function appendTurnEvent(event, dir, opts) {
|
|
|
65963
66500
|
}
|
|
65964
66501
|
const line = JSON.stringify(event);
|
|
65965
66502
|
try {
|
|
65966
|
-
appendOwnerOnlyLine(
|
|
66503
|
+
appendOwnerOnlyLine(path156.join(turnDir(event.turnId, dir), "events.jsonl"), line);
|
|
65967
66504
|
} catch (error2) {
|
|
65968
66505
|
if (error2?.code !== "ENOENT") {
|
|
65969
66506
|
throw error2;
|
|
65970
66507
|
}
|
|
65971
|
-
appendOwnerOnlyLine(
|
|
66508
|
+
appendOwnerOnlyLine(path156.join(ensureTurnDir(event.turnId, dir), "events.jsonl"), line);
|
|
65972
66509
|
}
|
|
65973
66510
|
return true;
|
|
65974
66511
|
}
|
|
@@ -65976,7 +66513,7 @@ function readTurnEvents(turnId, after = -1, dir) {
|
|
|
65976
66513
|
if (!isTurnId(turnId)) {
|
|
65977
66514
|
return { ok: false, reason: "not-a-turn-id" };
|
|
65978
66515
|
}
|
|
65979
|
-
const read = readTurnFile(
|
|
66516
|
+
const read = readTurnFile(path156.join(turnDir(turnId, dir), "events.jsonl"));
|
|
65980
66517
|
if (!read.ok) {
|
|
65981
66518
|
if (isDefiniteAbsence2(read.reason)) {
|
|
65982
66519
|
return { ok: true, value: [] };
|
|
@@ -66004,7 +66541,7 @@ function readTurnRecord(turnId, dir) {
|
|
|
66004
66541
|
if (!isTurnId(turnId)) {
|
|
66005
66542
|
return { ok: false, reason: "not-a-turn-id" };
|
|
66006
66543
|
}
|
|
66007
|
-
const read = readTurnFile(
|
|
66544
|
+
const read = readTurnFile(path156.join(turnDir(turnId, dir), "turn.json"));
|
|
66008
66545
|
if (!read.ok) {
|
|
66009
66546
|
return { ok: false, reason: read.reason };
|
|
66010
66547
|
}
|
|
@@ -66023,7 +66560,7 @@ function finishTurn(turnId, result, dir) {
|
|
|
66023
66560
|
if (!record.ok) {
|
|
66024
66561
|
return false;
|
|
66025
66562
|
}
|
|
66026
|
-
writeOwnerOnlyFile(
|
|
66563
|
+
writeOwnerOnlyFile(path156.join(turnDir(turnId, dir), "turn.json"), `${JSON.stringify({ ...record.value, result }, null, 2)}
|
|
66027
66564
|
`);
|
|
66028
66565
|
return true;
|
|
66029
66566
|
}
|
|
@@ -66069,7 +66606,7 @@ function releaseIdempotencyKey(project, idempotencyKey, turnId, dir) {
|
|
|
66069
66606
|
|
|
66070
66607
|
// src/lib/serve-turn.ts
|
|
66071
66608
|
import { randomUUID as randomUUID28 } from "crypto";
|
|
66072
|
-
import
|
|
66609
|
+
import path157 from "path";
|
|
66073
66610
|
init_service();
|
|
66074
66611
|
var REMOTE_ORIGIN = "remote:http";
|
|
66075
66612
|
var MAX_PROMPT_CHARS = 32000;
|
|
@@ -66138,9 +66675,9 @@ function isUuid(value) {
|
|
|
66138
66675
|
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(value);
|
|
66139
66676
|
}
|
|
66140
66677
|
function resolveProject(declared, dir) {
|
|
66141
|
-
const wanted =
|
|
66678
|
+
const wanted = path157.resolve(declared);
|
|
66142
66679
|
for (const entry of listProjects(dir, () => {})) {
|
|
66143
|
-
if (
|
|
66680
|
+
if (path157.resolve(entry.path) === wanted) {
|
|
66144
66681
|
return { ok: true, project: entry.path };
|
|
66145
66682
|
}
|
|
66146
66683
|
}
|
|
@@ -67173,9 +67710,9 @@ function printHelp17() {
|
|
|
67173
67710
|
|
|
67174
67711
|
// src/commands/update.ts
|
|
67175
67712
|
import { spawn as spawn5 } from "child_process";
|
|
67176
|
-
import { chmod as chmod4, mkdir as
|
|
67713
|
+
import { chmod as chmod4, mkdir as mkdir56, readFile as readFile80, readdir as readdir27, writeFile as writeFile49 } from "fs/promises";
|
|
67177
67714
|
import { access as access4, constants as constants2, existsSync as existsSync30 } from "fs";
|
|
67178
|
-
import
|
|
67715
|
+
import path158 from "path";
|
|
67179
67716
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
67180
67717
|
init_config();
|
|
67181
67718
|
init_config2();
|
|
@@ -67191,8 +67728,8 @@ async function updateCommand(args2 = []) {
|
|
|
67191
67728
|
return;
|
|
67192
67729
|
}
|
|
67193
67730
|
const projectRoot = process.cwd();
|
|
67194
|
-
const metaprojectRoot =
|
|
67195
|
-
banner("keryx update", `Refreshing the .metaproject workspace in ${
|
|
67731
|
+
const metaprojectRoot = path158.join(projectRoot, ".metaproject");
|
|
67732
|
+
banner("keryx update", `Refreshing the .metaproject workspace in ${path158.basename(projectRoot)}/`);
|
|
67196
67733
|
if (!await pathExists(metaprojectRoot)) {
|
|
67197
67734
|
console.log(` ${style.red(symbols.cross)} Metaproject is not initialized.`);
|
|
67198
67735
|
console.log(` ${style.cyan(symbols.arrow)} Run ${style.cyan("keryx init")} first.`);
|
|
@@ -67238,12 +67775,12 @@ async function updateCommand(args2 = []) {
|
|
|
67238
67775
|
nextSteps(steps);
|
|
67239
67776
|
}
|
|
67240
67777
|
async function refreshServiceFiles(projectRoot, options) {
|
|
67241
|
-
const metaprojectRoot =
|
|
67778
|
+
const metaprojectRoot = path158.join(projectRoot, ".metaproject");
|
|
67242
67779
|
const manifestState = await readManifest5(metaprojectRoot);
|
|
67243
67780
|
const manifest = manifestState.manifest;
|
|
67244
67781
|
const recoveredManifest = !manifestState.exists || !manifestState.valid;
|
|
67245
67782
|
if (manifestState.migrated) {
|
|
67246
|
-
await writeFile49(
|
|
67783
|
+
await writeFile49(path158.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
67247
67784
|
`, "utf8");
|
|
67248
67785
|
}
|
|
67249
67786
|
const enableGdgraph = moduleEnabled2(manifest, "gdgraph");
|
|
@@ -67280,11 +67817,11 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67280
67817
|
enableSecurity,
|
|
67281
67818
|
enableSac
|
|
67282
67819
|
});
|
|
67283
|
-
await writeTextIfChanged4(
|
|
67284
|
-
await writeTextIfChanged4(
|
|
67285
|
-
await writeTextIfChanged4(
|
|
67286
|
-
await writeTextIfChanged4(
|
|
67287
|
-
await writeTextIfChanged4(
|
|
67820
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "README.md"), renderMetaprojectCoreReadme());
|
|
67821
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "hooks", "README.md"), renderHooksReadme());
|
|
67822
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "rules", "README.md"), renderProjectRulesReadme());
|
|
67823
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "project-rules", "README.md"), renderProjectRulesSkillReadme({ sources: ruleSources }));
|
|
67824
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "index.md"), renderIndexMarkdown({
|
|
67288
67825
|
enableGdgraph,
|
|
67289
67826
|
enableGdctx,
|
|
67290
67827
|
enableGdwiki,
|
|
@@ -67297,7 +67834,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67297
67834
|
ruleSources,
|
|
67298
67835
|
hasDistilledEntrypoints: await hasDistilledEntrypoints(metaprojectRoot)
|
|
67299
67836
|
}));
|
|
67300
|
-
await writeTextIfChanged4(
|
|
67837
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "keryx-dashboard.html"), renderMetaprojectDashboardHtml({
|
|
67301
67838
|
enableGdgraph,
|
|
67302
67839
|
enableGdctx,
|
|
67303
67840
|
enableGdwiki,
|
|
@@ -67309,7 +67846,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67309
67846
|
enableSecurity,
|
|
67310
67847
|
data: dashboardData
|
|
67311
67848
|
}));
|
|
67312
|
-
await writeTextIfMissing4(
|
|
67849
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "README.md"), renderMetaprojectReadme({
|
|
67313
67850
|
enableGdgraph,
|
|
67314
67851
|
enableGdctx,
|
|
67315
67852
|
enableGdwiki,
|
|
@@ -67322,31 +67859,31 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67322
67859
|
}));
|
|
67323
67860
|
if (enableGdgraph) {
|
|
67324
67861
|
await installGdgraphCoreScripts2(metaprojectRoot);
|
|
67325
|
-
await writeTextIfChanged4(
|
|
67326
|
-
await writeTextIfChanged4(
|
|
67327
|
-
await writeTextIfChanged4(
|
|
67862
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "gdgraph.md"), renderGdgraphManifest());
|
|
67863
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "gdgraph", "README.md"), renderGdgraphCoreReadme());
|
|
67864
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "gdgraph", "SKILL.md"), renderGdgraphSkillReadme());
|
|
67328
67865
|
await seedAssetsLock(metaprojectRoot);
|
|
67329
67866
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
67330
67867
|
await installManagedHook2(projectRoot, "post-commit", "gdgraph-post-commit", renderGdgraphPostCommitHook());
|
|
67331
67868
|
}
|
|
67332
67869
|
}
|
|
67333
67870
|
if (enableGdctx) {
|
|
67334
|
-
await writeTextIfMissing4(
|
|
67335
|
-
await writeTextIfChanged4(
|
|
67336
|
-
await writeTextIfChanged4(
|
|
67337
|
-
await writeTextIfChanged4(
|
|
67871
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "gdctx.config.json"), renderGdctxConfig());
|
|
67872
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "gdctx.md"), renderGdctxManifest());
|
|
67873
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "gdctx", "README.md"), renderGdctxCoreReadme());
|
|
67874
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "gdctx", "SKILL.md"), renderGdctxSkillReadme());
|
|
67338
67875
|
}
|
|
67339
67876
|
if (enableGdwiki) {
|
|
67340
|
-
await writeTextIfMissing4(
|
|
67341
|
-
await writeTextIfChanged4(
|
|
67342
|
-
await writeTextIfChanged4(
|
|
67877
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "wiki", "templates", "page.md"), renderWikiPageTemplate());
|
|
67878
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "gdwiki.md"), renderGdwikiManifest());
|
|
67879
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "gdwiki", "SKILL.md"), renderGdwikiSkillReadme());
|
|
67343
67880
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
67344
67881
|
await installManagedHook2(projectRoot, "post-commit", "gdwiki-post-commit", renderGdwikiPostCommitHook());
|
|
67345
67882
|
}
|
|
67346
67883
|
}
|
|
67347
67884
|
if (enableSac) {
|
|
67348
|
-
await writeTextIfMissing4(
|
|
67349
|
-
await writeTextIfChanged4(
|
|
67885
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "modules", "sac.md"), renderSacManifest());
|
|
67886
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "sac", "SKILL.md"), renderSacSkillReadme());
|
|
67350
67887
|
}
|
|
67351
67888
|
if (enableGdskills) {
|
|
67352
67889
|
await installGdskills(metaprojectRoot, gdskillsProfile, { createDataDirs: false });
|
|
@@ -67355,25 +67892,25 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67355
67892
|
}
|
|
67356
67893
|
}
|
|
67357
67894
|
if (enableHealth) {
|
|
67358
|
-
await writeTextIfMissing4(
|
|
67359
|
-
await writeTextIfChanged4(
|
|
67360
|
-
await writeTextIfChanged4(
|
|
67361
|
-
await writeTextIfChanged4(
|
|
67895
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "health.config.json"), renderHealthConfig());
|
|
67896
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "health.md"), renderHealthManifest());
|
|
67897
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "health", "README.md"), renderHealthCoreReadme());
|
|
67898
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "health", "SKILL.md"), renderHealthSkillReadme());
|
|
67362
67899
|
if (manifest.modules?.health?.hooks?.gitPostCommit) {
|
|
67363
67900
|
await installManagedHook2(projectRoot, "post-commit", "health-post-commit", renderHealthPostCommitHook());
|
|
67364
67901
|
}
|
|
67365
67902
|
}
|
|
67366
67903
|
if (enableTesting) {
|
|
67367
|
-
await writeTextIfMissing4(
|
|
67904
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "testing.config.json"), renderTestingConfig({
|
|
67368
67905
|
postCommitRefresh: Boolean(manifest.modules?.testing?.hooks?.gitPostCommit),
|
|
67369
67906
|
prePushGate: Boolean(manifest.modules?.testing?.hooks?.prePush)
|
|
67370
67907
|
}));
|
|
67371
|
-
await writeTextIfChanged4(
|
|
67372
|
-
await writeTextIfChanged4(
|
|
67373
|
-
await writeTextIfChanged4(
|
|
67908
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "testing.md"), renderTestingManifest());
|
|
67909
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "testing", "README.md"), renderTestingCoreReadme());
|
|
67910
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "testing", "SKILL.md"), renderTestingSkillReadme());
|
|
67374
67911
|
if (enableGdwiki) {
|
|
67375
|
-
await writeTextIfMissing4(
|
|
67376
|
-
await writeTextIfMissing4(
|
|
67912
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "wiki", "testing", "README.md"), renderTestingWikiReadme());
|
|
67913
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "wiki", "testing", "conventions.md"), renderTestingWikiConventions());
|
|
67377
67914
|
}
|
|
67378
67915
|
if (manifest.modules?.testing?.hooks?.gitPostCommit) {
|
|
67379
67916
|
await installManagedHook2(projectRoot, "post-commit", "testing-post-commit", renderTestingPostCommitHook());
|
|
@@ -67386,24 +67923,24 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67386
67923
|
await installManagedHook2(projectRoot, "post-commit", "metaproject-dashboard-post-commit", renderMetaprojectDashboardPostCommitHook());
|
|
67387
67924
|
}
|
|
67388
67925
|
if (enableMemory) {
|
|
67389
|
-
await writeTextIfMissing4(
|
|
67390
|
-
await writeTextIfMissing4(
|
|
67391
|
-
await writeTextIfChanged4(
|
|
67392
|
-
await writeTextIfChanged4(
|
|
67393
|
-
await writeTextIfChanged4(
|
|
67926
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "memory.config.json"), renderMemoryConfig());
|
|
67927
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "memory", "templates", "entry.md"), renderMemoryEntryTemplate());
|
|
67928
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "memory.md"), renderMemoryManifest());
|
|
67929
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "memory", "README.md"), renderMemoryCoreReadme());
|
|
67930
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "memory", "SKILL.md"), renderMemorySkillReadme());
|
|
67394
67931
|
}
|
|
67395
67932
|
if (enableTasks) {
|
|
67396
|
-
await writeTextIfChanged4(
|
|
67397
|
-
await writeTextIfChanged4(
|
|
67398
|
-
await writeTextIfChanged4(
|
|
67399
|
-
await writeTextIfChanged4(
|
|
67400
|
-
await writeTextIfChanged4(
|
|
67401
|
-
await writeTextIfChanged4(
|
|
67933
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "flows", "README.md"), renderFlowsReadme());
|
|
67934
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "tasks.md"), renderTasksManifest());
|
|
67935
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "flow", "SKILL.md"), renderFlowSkillRouter());
|
|
67936
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "flow", "init.md"), renderFlowInitSkill());
|
|
67937
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "flow", "manage.md"), renderFlowManageSkill());
|
|
67938
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "skills", "flow", "complete.md"), renderFlowCompleteSkill());
|
|
67402
67939
|
}
|
|
67403
67940
|
if (enableSecurity) {
|
|
67404
|
-
await writeTextIfMissing4(
|
|
67405
|
-
await writeTextIfChanged4(
|
|
67406
|
-
await writeTextIfChanged4(
|
|
67941
|
+
await writeTextIfMissing4(path158.join(metaprojectRoot, "security.config.json"), renderSecurityConfig());
|
|
67942
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "modules", "security.md"), renderSecurityManifest());
|
|
67943
|
+
await writeTextIfChanged4(path158.join(metaprojectRoot, "core", "security", "README.md"), renderSecurityCoreReadme());
|
|
67407
67944
|
if (manifest.modules?.security?.hooks?.prePush) {
|
|
67408
67945
|
await installManagedHook2(projectRoot, "pre-push", "security-pre-push", renderSecurityPrePushHook());
|
|
67409
67946
|
}
|
|
@@ -67454,13 +67991,13 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
67454
67991
|
};
|
|
67455
67992
|
}
|
|
67456
67993
|
async function buildDashboard(projectRoot = process.cwd()) {
|
|
67457
|
-
const metaprojectRoot =
|
|
67994
|
+
const metaprojectRoot = path158.join(projectRoot, ".metaproject");
|
|
67458
67995
|
if (!await pathExists(metaprojectRoot)) {
|
|
67459
67996
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
67460
67997
|
}
|
|
67461
67998
|
const manifest = (await readManifest5(metaprojectRoot)).manifest;
|
|
67462
67999
|
const data = await collectDashboardData(metaprojectRoot);
|
|
67463
|
-
const dashboardPath =
|
|
68000
|
+
const dashboardPath = path158.join(metaprojectRoot, "keryx-dashboard.html");
|
|
67464
68001
|
await writeTextIfChanged4(dashboardPath, renderMetaprojectDashboardHtml({
|
|
67465
68002
|
enableGdgraph: moduleEnabled2(manifest, "gdgraph"),
|
|
67466
68003
|
enableGdctx: moduleEnabled2(manifest, "gdctx"),
|
|
@@ -67480,11 +68017,11 @@ async function shouldInstallDashboardPostCommitHook(projectRoot, manifest) {
|
|
|
67480
68017
|
if (Object.values(modules).some((module) => Boolean(module.hooks?.gitPostCommit))) {
|
|
67481
68018
|
return true;
|
|
67482
68019
|
}
|
|
67483
|
-
const hookPath =
|
|
68020
|
+
const hookPath = path158.join(projectRoot, ".git", "hooks", "post-commit");
|
|
67484
68021
|
if (!await pathExists(hookPath)) {
|
|
67485
68022
|
return false;
|
|
67486
68023
|
}
|
|
67487
|
-
return (await
|
|
68024
|
+
return (await readFile80(hookPath, "utf8")).includes("# keryx:");
|
|
67488
68025
|
}
|
|
67489
68026
|
async function collectDashboardData(metaprojectRoot) {
|
|
67490
68027
|
const data = {};
|
|
@@ -67500,11 +68037,11 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
67500
68037
|
if (testing) {
|
|
67501
68038
|
data.testing = testing;
|
|
67502
68039
|
}
|
|
67503
|
-
const wiki = await collectMarkdownPages(
|
|
68040
|
+
const wiki = await collectMarkdownPages(path158.join(metaprojectRoot, "wiki"), "wiki");
|
|
67504
68041
|
if (wiki.length > 0) {
|
|
67505
68042
|
data.wiki = { pages: wiki };
|
|
67506
68043
|
}
|
|
67507
|
-
const memory = await collectMarkdownPages(
|
|
68044
|
+
const memory = await collectMarkdownPages(path158.join(metaprojectRoot, "memory"), "memory");
|
|
67508
68045
|
if (memory.length > 0) {
|
|
67509
68046
|
data.memory = { entries: memory };
|
|
67510
68047
|
}
|
|
@@ -67519,29 +68056,29 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
67519
68056
|
return data;
|
|
67520
68057
|
}
|
|
67521
68058
|
async function collectTasksDashboardData(metaprojectRoot) {
|
|
67522
|
-
const flowsRoot2 =
|
|
68059
|
+
const flowsRoot2 = path158.join(metaprojectRoot, "flows");
|
|
67523
68060
|
if (!await pathExists(flowsRoot2)) {
|
|
67524
68061
|
return null;
|
|
67525
68062
|
}
|
|
67526
68063
|
let dirEntries;
|
|
67527
68064
|
try {
|
|
67528
|
-
dirEntries = (await
|
|
68065
|
+
dirEntries = (await readdir27(flowsRoot2, { withFileTypes: true })).filter((entry) => entry.isDirectory() && /^\d{3}-/.test(entry.name)).map((entry) => entry.name).sort();
|
|
67529
68066
|
} catch {
|
|
67530
68067
|
return null;
|
|
67531
68068
|
}
|
|
67532
68069
|
const flows = [];
|
|
67533
68070
|
for (const dir of dirEntries) {
|
|
67534
|
-
const flowPath =
|
|
68071
|
+
const flowPath = path158.join(flowsRoot2, dir, "flow.json");
|
|
67535
68072
|
if (!await pathExists(flowPath)) {
|
|
67536
68073
|
continue;
|
|
67537
68074
|
}
|
|
67538
68075
|
try {
|
|
67539
|
-
const flow = JSON.parse(await
|
|
68076
|
+
const flow = JSON.parse(await readFile80(flowPath, "utf8"));
|
|
67540
68077
|
const tasks = Array.isArray(flow.tasks) ? flow.tasks : [];
|
|
67541
68078
|
let acTotal = 0;
|
|
67542
|
-
const acPath2 =
|
|
68079
|
+
const acPath2 = path158.join(flowsRoot2, dir, "acceptance-criteria.md");
|
|
67543
68080
|
if (await pathExists(acPath2)) {
|
|
67544
|
-
const acContent = await
|
|
68081
|
+
const acContent = await readFile80(acPath2, "utf8");
|
|
67545
68082
|
acTotal = (acContent.match(/^- AC\d+:/gm) ?? []).length;
|
|
67546
68083
|
}
|
|
67547
68084
|
flows.push({
|
|
@@ -67593,11 +68130,11 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
67593
68130
|
"data/testing/context.md"
|
|
67594
68131
|
];
|
|
67595
68132
|
for (const href of staticHrefs) {
|
|
67596
|
-
const filePath =
|
|
68133
|
+
const filePath = path158.join(metaprojectRoot, ...href.split("/"));
|
|
67597
68134
|
if (!await pathExists(filePath)) {
|
|
67598
68135
|
continue;
|
|
67599
68136
|
}
|
|
67600
|
-
const content = await
|
|
68137
|
+
const content = await readFile80(filePath, "utf8");
|
|
67601
68138
|
docs[href] = content.length > 40000 ? `${content.slice(0, 40000)}
|
|
67602
68139
|
|
|
67603
68140
|
\u2026truncated\u2026` : content;
|
|
@@ -67610,11 +68147,11 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
67610
68147
|
return docs;
|
|
67611
68148
|
}
|
|
67612
68149
|
async function collectHealthDashboardData(metaprojectRoot) {
|
|
67613
|
-
const reportPath2 =
|
|
68150
|
+
const reportPath2 = path158.join(metaprojectRoot, "data", "health", "artifacts", "latest.json");
|
|
67614
68151
|
if (!await pathExists(reportPath2)) {
|
|
67615
68152
|
return;
|
|
67616
68153
|
}
|
|
67617
|
-
const report = JSON.parse(await
|
|
68154
|
+
const report = JSON.parse(await readFile80(reportPath2, "utf8"));
|
|
67618
68155
|
const metrics = Array.isArray(report.metrics) ? report.metrics : [];
|
|
67619
68156
|
const findings = Array.isArray(report.findings) ? report.findings : [];
|
|
67620
68157
|
const project = metrics.find((metric) => metric.key === "project") ?? {};
|
|
@@ -67719,8 +68256,8 @@ function metricToScope(metric) {
|
|
|
67719
68256
|
};
|
|
67720
68257
|
}
|
|
67721
68258
|
async function collectGraphDashboardData(metaprojectRoot) {
|
|
67722
|
-
const nodesPath =
|
|
67723
|
-
const edgesPath =
|
|
68259
|
+
const nodesPath = path158.join(metaprojectRoot, "data", "gdgraph", "storage", "nodes.jsonl");
|
|
68260
|
+
const edgesPath = path158.join(metaprojectRoot, "data", "gdgraph", "storage", "edges.jsonl");
|
|
67724
68261
|
if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
|
|
67725
68262
|
return;
|
|
67726
68263
|
}
|
|
@@ -67728,7 +68265,7 @@ async function collectGraphDashboardData(metaprojectRoot) {
|
|
|
67728
68265
|
let nodes = 0;
|
|
67729
68266
|
let files = 0;
|
|
67730
68267
|
let assets = 0;
|
|
67731
|
-
for (const node of parseJsonl2(await
|
|
68268
|
+
for (const node of parseJsonl2(await readFile80(nodesPath, "utf8"))) {
|
|
67732
68269
|
nodes += 1;
|
|
67733
68270
|
if (node.kind === "asset") {
|
|
67734
68271
|
assets += 1;
|
|
@@ -67744,7 +68281,7 @@ async function collectGraphDashboardData(metaprojectRoot) {
|
|
|
67744
68281
|
let imports = 0;
|
|
67745
68282
|
let assetEdges = 0;
|
|
67746
68283
|
let unresolved = 0;
|
|
67747
|
-
for (const edge of parseJsonl2(await
|
|
68284
|
+
for (const edge of parseJsonl2(await readFile80(edgesPath, "utf8"))) {
|
|
67748
68285
|
edges += 1;
|
|
67749
68286
|
if (edge.kind === "imports") {
|
|
67750
68287
|
imports += 1;
|
|
@@ -67771,10 +68308,10 @@ async function collectGraphDashboardData(metaprojectRoot) {
|
|
|
67771
68308
|
};
|
|
67772
68309
|
}
|
|
67773
68310
|
async function collectTestingDashboardData(metaprojectRoot) {
|
|
67774
|
-
const reportPath2 =
|
|
67775
|
-
const contextPath =
|
|
68311
|
+
const reportPath2 = path158.join(metaprojectRoot, "data", "testing", "artifacts", "latest.json");
|
|
68312
|
+
const contextPath = path158.join(metaprojectRoot, "data", "testing", "context.md");
|
|
67776
68313
|
if (await pathExists(reportPath2)) {
|
|
67777
|
-
const report = JSON.parse(await
|
|
68314
|
+
const report = JSON.parse(await readFile80(reportPath2, "utf8"));
|
|
67778
68315
|
const totalTests = numberOrUndefined(report.total);
|
|
67779
68316
|
const failedTests = Array.isArray(report.failures) ? report.failures.length : numberOrUndefined(report.failed);
|
|
67780
68317
|
return {
|
|
@@ -67801,11 +68338,11 @@ async function collectMarkdownPages(root, hrefPrefix) {
|
|
|
67801
68338
|
const files = await listMarkdownFiles(root);
|
|
67802
68339
|
const pages = [];
|
|
67803
68340
|
for (const filePath of files.slice(0, 40)) {
|
|
67804
|
-
const relativePath =
|
|
68341
|
+
const relativePath = path158.relative(root, filePath).split(path158.sep).join("/");
|
|
67805
68342
|
if (relativePath === "index.md" || relativePath.startsWith("templates/")) {
|
|
67806
68343
|
continue;
|
|
67807
68344
|
}
|
|
67808
|
-
const content = await
|
|
68345
|
+
const content = await readFile80(filePath, "utf8");
|
|
67809
68346
|
const embedded = content.length > 24000 ? `${content.slice(0, 24000)}
|
|
67810
68347
|
|
|
67811
68348
|
\u2026truncated\u2026` : content;
|
|
@@ -67819,10 +68356,10 @@ async function collectMarkdownPages(root, hrefPrefix) {
|
|
|
67819
68356
|
return pages;
|
|
67820
68357
|
}
|
|
67821
68358
|
async function listMarkdownFiles(root) {
|
|
67822
|
-
const entries = await
|
|
68359
|
+
const entries = await readdir27(root, { withFileTypes: true });
|
|
67823
68360
|
const files = [];
|
|
67824
68361
|
for (const entry of entries) {
|
|
67825
|
-
const fullPath =
|
|
68362
|
+
const fullPath = path158.join(root, entry.name);
|
|
67826
68363
|
if (entry.isDirectory()) {
|
|
67827
68364
|
files.push(...await listMarkdownFiles(fullPath));
|
|
67828
68365
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -67870,7 +68407,7 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
67870
68407
|
const manifest = {
|
|
67871
68408
|
schemaVersion: 1,
|
|
67872
68409
|
standardVersion: STANDARD_VERSION,
|
|
67873
|
-
name: `${
|
|
68410
|
+
name: `${path158.basename(path158.dirname(metaprojectRoot))}-metaproject`,
|
|
67874
68411
|
createdBy: "keryx",
|
|
67875
68412
|
profiles: computeProfiles(enabledModuleKeys2),
|
|
67876
68413
|
paths: {
|
|
@@ -67971,17 +68508,17 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
67971
68508
|
metaproject: ".metaproject/index.md"
|
|
67972
68509
|
}
|
|
67973
68510
|
};
|
|
67974
|
-
await writeFile49(
|
|
68511
|
+
await writeFile49(path158.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
67975
68512
|
`, "utf8");
|
|
67976
68513
|
}
|
|
67977
68514
|
async function enableTasksInManifest(metaprojectRoot) {
|
|
67978
|
-
const manifestPath =
|
|
68515
|
+
const manifestPath = path158.join(metaprojectRoot, "metaproject.json");
|
|
67979
68516
|
if (!await pathExists(manifestPath)) {
|
|
67980
68517
|
return;
|
|
67981
68518
|
}
|
|
67982
68519
|
let raw;
|
|
67983
68520
|
try {
|
|
67984
|
-
raw = JSON.parse(await
|
|
68521
|
+
raw = JSON.parse(await readFile80(manifestPath, "utf8"));
|
|
67985
68522
|
} catch {
|
|
67986
68523
|
return;
|
|
67987
68524
|
}
|
|
@@ -67998,13 +68535,13 @@ async function enableTasksInManifest(metaprojectRoot) {
|
|
|
67998
68535
|
`, "utf8");
|
|
67999
68536
|
}
|
|
68000
68537
|
async function updateManifestAgentEntrypoints(metaprojectRoot, ruleSources) {
|
|
68001
|
-
const manifestPath =
|
|
68538
|
+
const manifestPath = path158.join(metaprojectRoot, "metaproject.json");
|
|
68002
68539
|
if (!await pathExists(manifestPath)) {
|
|
68003
68540
|
return;
|
|
68004
68541
|
}
|
|
68005
68542
|
let raw;
|
|
68006
68543
|
try {
|
|
68007
|
-
raw = JSON.parse(await
|
|
68544
|
+
raw = JSON.parse(await readFile80(manifestPath, "utf8"));
|
|
68008
68545
|
} catch {
|
|
68009
68546
|
return;
|
|
68010
68547
|
}
|
|
@@ -68034,86 +68571,86 @@ async function updateRuntime(projectRoot) {
|
|
|
68034
68571
|
}
|
|
68035
68572
|
}
|
|
68036
68573
|
async function findRuntimeRoot(projectRoot) {
|
|
68037
|
-
const projectRuntime =
|
|
68038
|
-
if (await pathExists(
|
|
68574
|
+
const projectRuntime = path158.join(projectRoot, ".metaproject", "runtime", "keryx");
|
|
68575
|
+
if (await pathExists(path158.join(projectRuntime, ".git"))) {
|
|
68039
68576
|
return projectRuntime;
|
|
68040
68577
|
}
|
|
68041
68578
|
const home = process.env.HOME;
|
|
68042
68579
|
if (!home) {
|
|
68043
68580
|
return null;
|
|
68044
68581
|
}
|
|
68045
|
-
const globalRuntime =
|
|
68046
|
-
if (await pathExists(
|
|
68582
|
+
const globalRuntime = path158.join(home, ".keryx", "keryx");
|
|
68583
|
+
if (await pathExists(path158.join(globalRuntime, ".git"))) {
|
|
68047
68584
|
return globalRuntime;
|
|
68048
68585
|
}
|
|
68049
68586
|
return null;
|
|
68050
68587
|
}
|
|
68051
68588
|
async function createServiceDirs(metaprojectRoot, modules) {
|
|
68052
68589
|
const dirs = [
|
|
68053
|
-
|
|
68054
|
-
|
|
68055
|
-
|
|
68056
|
-
|
|
68057
|
-
|
|
68590
|
+
path158.join(metaprojectRoot, "core"),
|
|
68591
|
+
path158.join(metaprojectRoot, "hooks", "post-update.d"),
|
|
68592
|
+
path158.join(metaprojectRoot, "modules"),
|
|
68593
|
+
path158.join(metaprojectRoot, "rules"),
|
|
68594
|
+
path158.join(metaprojectRoot, "skills", "project-rules"),
|
|
68058
68595
|
...modules.enableGdgraph ? [
|
|
68059
|
-
|
|
68060
|
-
|
|
68596
|
+
path158.join(metaprojectRoot, "core", "gdgraph"),
|
|
68597
|
+
path158.join(metaprojectRoot, "skills", "gdgraph")
|
|
68061
68598
|
] : [],
|
|
68062
68599
|
...modules.enableGdctx ? [
|
|
68063
|
-
|
|
68064
|
-
|
|
68600
|
+
path158.join(metaprojectRoot, "core", "gdctx"),
|
|
68601
|
+
path158.join(metaprojectRoot, "skills", "gdctx")
|
|
68065
68602
|
] : [],
|
|
68066
68603
|
...modules.enableGdwiki ? [
|
|
68067
|
-
|
|
68068
|
-
|
|
68604
|
+
path158.join(metaprojectRoot, "skills", "gdwiki"),
|
|
68605
|
+
path158.join(metaprojectRoot, "wiki", "templates")
|
|
68069
68606
|
] : [],
|
|
68070
68607
|
...modules.enableHealth ? [
|
|
68071
|
-
|
|
68072
|
-
|
|
68608
|
+
path158.join(metaprojectRoot, "core", "health"),
|
|
68609
|
+
path158.join(metaprojectRoot, "skills", "health")
|
|
68073
68610
|
] : [],
|
|
68074
68611
|
...modules.enableTesting ? [
|
|
68075
|
-
|
|
68076
|
-
|
|
68612
|
+
path158.join(metaprojectRoot, "core", "testing"),
|
|
68613
|
+
path158.join(metaprojectRoot, "skills", "testing")
|
|
68077
68614
|
] : [],
|
|
68078
68615
|
...modules.enableMemory ? [
|
|
68079
|
-
|
|
68080
|
-
|
|
68081
|
-
|
|
68616
|
+
path158.join(metaprojectRoot, "core", "memory"),
|
|
68617
|
+
path158.join(metaprojectRoot, "skills", "memory"),
|
|
68618
|
+
path158.join(metaprojectRoot, "memory", "templates")
|
|
68082
68619
|
] : [],
|
|
68083
68620
|
...modules.enableTasks ? [
|
|
68084
|
-
|
|
68085
|
-
|
|
68621
|
+
path158.join(metaprojectRoot, "flows"),
|
|
68622
|
+
path158.join(metaprojectRoot, "skills", "flow")
|
|
68086
68623
|
] : [],
|
|
68087
68624
|
...modules.enableSecurity ? [
|
|
68088
|
-
|
|
68625
|
+
path158.join(metaprojectRoot, "core", "security")
|
|
68089
68626
|
] : [],
|
|
68090
68627
|
...modules.enableSac ? [
|
|
68091
|
-
|
|
68628
|
+
path158.join(metaprojectRoot, "skills", "sac")
|
|
68092
68629
|
] : []
|
|
68093
68630
|
];
|
|
68094
|
-
await Promise.all(dirs.map((dir) =>
|
|
68631
|
+
await Promise.all(dirs.map((dir) => mkdir56(dir, { recursive: true })));
|
|
68095
68632
|
}
|
|
68096
68633
|
async function installGdgraphCoreScripts2(metaprojectRoot) {
|
|
68097
|
-
const gdgraphCoreRoot =
|
|
68098
|
-
await
|
|
68634
|
+
const gdgraphCoreRoot = path158.join(metaprojectRoot, "core", "gdgraph");
|
|
68635
|
+
await mkdir56(gdgraphCoreRoot, { recursive: true });
|
|
68099
68636
|
for (const file of GDGRAPH_CORE_SOURCES) {
|
|
68100
|
-
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`),
|
|
68637
|
+
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`), path158.join(gdgraphCoreRoot, file));
|
|
68101
68638
|
}
|
|
68102
|
-
await writeTextIfChanged4(
|
|
68639
|
+
await writeTextIfChanged4(path158.join(gdgraphCoreRoot, "cli.ts"), renderGdgraphCoreCli());
|
|
68103
68640
|
}
|
|
68104
68641
|
async function installManagedHook2(projectRoot, hookName, blockId, content) {
|
|
68105
68642
|
const hooksRoot = await resolveGitHooksRoot(projectRoot);
|
|
68106
68643
|
if (!hooksRoot) {
|
|
68107
68644
|
return;
|
|
68108
68645
|
}
|
|
68109
|
-
await
|
|
68110
|
-
const hookPath =
|
|
68646
|
+
await mkdir56(hooksRoot, { recursive: true });
|
|
68647
|
+
const hookPath = path158.join(hooksRoot, hookName);
|
|
68111
68648
|
const blockStart = `# keryx:${blockId}:begin`;
|
|
68112
68649
|
const blockEnd = `# keryx:${blockId}:end`;
|
|
68113
68650
|
const managedBlock = `${blockStart}
|
|
68114
68651
|
${content.trim()}
|
|
68115
68652
|
${blockEnd}`;
|
|
68116
|
-
const existing = await pathExists(hookPath) ? await
|
|
68653
|
+
const existing = await pathExists(hookPath) ? await readFile80(hookPath, "utf8") : `#!/usr/bin/env sh
|
|
68117
68654
|
`;
|
|
68118
68655
|
const blockPattern = new RegExp(`${escapeRegExp6(blockStart)}[\\s\\S]*?${escapeRegExp6(blockEnd)}`);
|
|
68119
68656
|
const next = blockPattern.test(existing) ? existing.replace(blockPattern, managedBlock) : `${existing.trimEnd()}
|
|
@@ -68128,11 +68665,11 @@ async function removeManagedHook2(projectRoot, hookName, blockId) {
|
|
|
68128
68665
|
if (!hooksRoot) {
|
|
68129
68666
|
return;
|
|
68130
68667
|
}
|
|
68131
|
-
const hookPath =
|
|
68668
|
+
const hookPath = path158.join(hooksRoot, hookName);
|
|
68132
68669
|
if (!await pathExists(hookPath)) {
|
|
68133
68670
|
return;
|
|
68134
68671
|
}
|
|
68135
|
-
const existing = await
|
|
68672
|
+
const existing = await readFile80(hookPath, "utf8");
|
|
68136
68673
|
const blockStart = `# keryx:${blockId}:begin`;
|
|
68137
68674
|
const blockEnd = `# keryx:${blockId}:end`;
|
|
68138
68675
|
const blockPattern = new RegExp(`\\n*${escapeRegExp6(blockStart)}[\\s\\S]*?${escapeRegExp6(blockEnd)}\\n*`);
|
|
@@ -68150,11 +68687,11 @@ async function prePushHasSecurityBlock2(projectRoot) {
|
|
|
68150
68687
|
if (!hooksRoot) {
|
|
68151
68688
|
return false;
|
|
68152
68689
|
}
|
|
68153
|
-
const hookPath =
|
|
68690
|
+
const hookPath = path158.join(hooksRoot, "pre-push");
|
|
68154
68691
|
if (!await pathExists(hookPath)) {
|
|
68155
68692
|
return false;
|
|
68156
68693
|
}
|
|
68157
|
-
const hook = await
|
|
68694
|
+
const hook = await readFile80(hookPath, "utf8");
|
|
68158
68695
|
return hook.includes("# keryx:security-pre-push:begin");
|
|
68159
68696
|
}
|
|
68160
68697
|
async function agentSettingsHasSecuritySentinel2(projectRoot) {
|
|
@@ -68162,10 +68699,10 @@ async function agentSettingsHasSecuritySentinel2(projectRoot) {
|
|
|
68162
68699
|
if (!await pathExists(file)) {
|
|
68163
68700
|
return false;
|
|
68164
68701
|
}
|
|
68165
|
-
return (await
|
|
68702
|
+
return (await readFile80(file, "utf8")).includes(AGENT_HOOKS_SENTINEL);
|
|
68166
68703
|
}
|
|
68167
68704
|
async function readManifest5(metaprojectRoot) {
|
|
68168
|
-
const manifestPath =
|
|
68705
|
+
const manifestPath = path158.join(metaprojectRoot, "metaproject.json");
|
|
68169
68706
|
if (!await pathExists(manifestPath)) {
|
|
68170
68707
|
return {
|
|
68171
68708
|
exists: false,
|
|
@@ -68175,7 +68712,7 @@ async function readManifest5(metaprojectRoot) {
|
|
|
68175
68712
|
};
|
|
68176
68713
|
}
|
|
68177
68714
|
try {
|
|
68178
|
-
const manifest = JSON.parse(await
|
|
68715
|
+
const manifest = JSON.parse(await readFile80(manifestPath, "utf8"));
|
|
68179
68716
|
const normalized = normalizeManifest(manifest);
|
|
68180
68717
|
return {
|
|
68181
68718
|
exists: true,
|
|
@@ -68234,7 +68771,7 @@ async function inferManifestFromExistingMetaproject(metaprojectRoot) {
|
|
|
68234
68771
|
}
|
|
68235
68772
|
async function anyPathExists(root, candidates) {
|
|
68236
68773
|
for (const candidate of candidates) {
|
|
68237
|
-
if (await pathExists(
|
|
68774
|
+
if (await pathExists(path158.join(root, candidate))) {
|
|
68238
68775
|
return true;
|
|
68239
68776
|
}
|
|
68240
68777
|
}
|
|
@@ -68255,13 +68792,13 @@ function parseUpdateArgs(args2) {
|
|
|
68255
68792
|
};
|
|
68256
68793
|
}
|
|
68257
68794
|
async function runPostUpdateHooks(projectRoot) {
|
|
68258
|
-
const hooksDir =
|
|
68795
|
+
const hooksDir = path158.join(projectRoot, ".metaproject", "hooks", "post-update.d");
|
|
68259
68796
|
if (!await pathExists(hooksDir)) {
|
|
68260
68797
|
return;
|
|
68261
68798
|
}
|
|
68262
|
-
const entries = (await
|
|
68799
|
+
const entries = (await readdir27(hooksDir)).sort();
|
|
68263
68800
|
for (const entry of entries) {
|
|
68264
|
-
const hookPath =
|
|
68801
|
+
const hookPath = path158.join(hooksDir, entry);
|
|
68265
68802
|
try {
|
|
68266
68803
|
await accessExecutable(hookPath);
|
|
68267
68804
|
} catch {
|
|
@@ -68299,25 +68836,25 @@ async function run(command, args2, cwd) {
|
|
|
68299
68836
|
});
|
|
68300
68837
|
}
|
|
68301
68838
|
async function writeTextIfChanged4(filePath, content) {
|
|
68302
|
-
if (await pathExists(filePath) && await
|
|
68839
|
+
if (await pathExists(filePath) && await readFile80(filePath, "utf8") === content) {
|
|
68303
68840
|
return;
|
|
68304
68841
|
}
|
|
68305
|
-
await
|
|
68842
|
+
await mkdir56(path158.dirname(filePath), { recursive: true });
|
|
68306
68843
|
await writeFile49(filePath, content, "utf8");
|
|
68307
68844
|
}
|
|
68308
68845
|
async function writeTextIfMissing4(filePath, content) {
|
|
68309
68846
|
if (await pathExists(filePath)) {
|
|
68310
68847
|
return;
|
|
68311
68848
|
}
|
|
68312
|
-
await
|
|
68849
|
+
await mkdir56(path158.dirname(filePath), { recursive: true });
|
|
68313
68850
|
await writeFile49(filePath, content, "utf8");
|
|
68314
68851
|
}
|
|
68315
68852
|
async function copyFileIfChanged2(from, to) {
|
|
68316
|
-
const next = await
|
|
68317
|
-
if (await pathExists(to) && await
|
|
68853
|
+
const next = await readFile80(from, "utf8");
|
|
68854
|
+
if (await pathExists(to) && await readFile80(to, "utf8") === next) {
|
|
68318
68855
|
return;
|
|
68319
68856
|
}
|
|
68320
|
-
await
|
|
68857
|
+
await mkdir56(path158.dirname(to), { recursive: true });
|
|
68321
68858
|
await writeFile49(to, next, "utf8");
|
|
68322
68859
|
}
|
|
68323
68860
|
function runtimeSourcePath2(relativePath) {
|
|
@@ -68326,7 +68863,7 @@ function runtimeSourcePath2(relativePath) {
|
|
|
68326
68863
|
return directPath;
|
|
68327
68864
|
}
|
|
68328
68865
|
if (relativePath.startsWith("../")) {
|
|
68329
|
-
const packagedSourcePath =
|
|
68866
|
+
const packagedSourcePath = path158.join(path158.dirname(fileURLToPath7(import.meta.url)), "..", "src", relativePath.slice(3));
|
|
68330
68867
|
if (existsSync30(packagedSourcePath)) {
|
|
68331
68868
|
return packagedSourcePath;
|
|
68332
68869
|
}
|
|
@@ -68358,7 +68895,7 @@ function printHelp18() {
|
|
|
68358
68895
|
|
|
68359
68896
|
// src/commands/dashboard.ts
|
|
68360
68897
|
import { spawn as spawn6 } from "child_process";
|
|
68361
|
-
import
|
|
68898
|
+
import path159 from "path";
|
|
68362
68899
|
init_args();
|
|
68363
68900
|
async function dashboardCommand(args2 = []) {
|
|
68364
68901
|
const options = parseOptions(args2);
|
|
@@ -68369,7 +68906,7 @@ async function dashboardCommand(args2 = []) {
|
|
|
68369
68906
|
}
|
|
68370
68907
|
if (subcommand === "build") {
|
|
68371
68908
|
const result = await buildDashboard();
|
|
68372
|
-
const rel =
|
|
68909
|
+
const rel = path159.relative(process.cwd(), result.path);
|
|
68373
68910
|
console.log(` ${style.green(symbols.ok)} Dashboard built ${style.cyan(symbols.arrow)} ${style.cyan(rel)}`);
|
|
68374
68911
|
note(`Open it: keryx dashboard open`);
|
|
68375
68912
|
return;
|
|
@@ -68377,7 +68914,7 @@ async function dashboardCommand(args2 = []) {
|
|
|
68377
68914
|
if (subcommand === "open") {
|
|
68378
68915
|
const result = await buildDashboard();
|
|
68379
68916
|
await openFile(result.path);
|
|
68380
|
-
const rel =
|
|
68917
|
+
const rel = path159.relative(process.cwd(), result.path);
|
|
68381
68918
|
console.log(` ${style.green(symbols.ok)} Opened ${style.cyan(rel)}`);
|
|
68382
68919
|
return;
|
|
68383
68920
|
}
|
|
@@ -68424,9 +68961,9 @@ function printHelp19() {
|
|
|
68424
68961
|
import { readFileSync as readFileSync10 } from "fs";
|
|
68425
68962
|
|
|
68426
68963
|
// src/agents/bootstrap.ts
|
|
68427
|
-
import { mkdir as
|
|
68964
|
+
import { mkdir as mkdir57, readFile as readFile81, writeFile as writeFile50 } from "fs/promises";
|
|
68428
68965
|
import { homedir as homedir7 } from "os";
|
|
68429
|
-
import
|
|
68966
|
+
import path160 from "path";
|
|
68430
68967
|
init_fs();
|
|
68431
68968
|
var AGENT_BOOTSTRAP_START = "<!-- keryx:global-bootstrap -->";
|
|
68432
68969
|
var AGENT_BOOTSTRAP_END = "<!-- /keryx:global-bootstrap -->";
|
|
@@ -68436,35 +68973,35 @@ var AGENT_BOOTSTRAP_RUNTIMES = [
|
|
|
68436
68973
|
aliases: ["claude-code"],
|
|
68437
68974
|
label: "Claude Code",
|
|
68438
68975
|
fileName: "CLAUDE.md",
|
|
68439
|
-
filePath: (homeRoot) =>
|
|
68976
|
+
filePath: (homeRoot) => path160.join(homeRoot, ".claude", "CLAUDE.md")
|
|
68440
68977
|
},
|
|
68441
68978
|
{
|
|
68442
68979
|
id: "opencode",
|
|
68443
68980
|
aliases: ["open-code"],
|
|
68444
68981
|
label: "OpenCode",
|
|
68445
68982
|
fileName: "AGENTS.md",
|
|
68446
|
-
filePath: (homeRoot) =>
|
|
68983
|
+
filePath: (homeRoot) => path160.join(homeRoot, ".config", "opencode", "AGENTS.md")
|
|
68447
68984
|
},
|
|
68448
68985
|
{
|
|
68449
68986
|
id: "zcode",
|
|
68450
68987
|
aliases: ["zed", "zed-code"],
|
|
68451
68988
|
label: "ZCode",
|
|
68452
68989
|
fileName: "AGENTS.md",
|
|
68453
|
-
filePath: (homeRoot) =>
|
|
68990
|
+
filePath: (homeRoot) => path160.join(homeRoot, ".zcode", "AGENTS.md")
|
|
68454
68991
|
},
|
|
68455
68992
|
{
|
|
68456
68993
|
id: "codex",
|
|
68457
68994
|
aliases: [],
|
|
68458
68995
|
label: "Codex",
|
|
68459
68996
|
fileName: "AGENTS.md",
|
|
68460
|
-
filePath: (homeRoot) =>
|
|
68997
|
+
filePath: (homeRoot) => path160.join(homeRoot, ".codex", "AGENTS.md")
|
|
68461
68998
|
},
|
|
68462
68999
|
{
|
|
68463
69000
|
id: "antigravity",
|
|
68464
69001
|
aliases: ["antigravuty", "antigravity-code"],
|
|
68465
69002
|
label: "Antigravity",
|
|
68466
69003
|
fileName: "AGENTS.md",
|
|
68467
|
-
filePath: (homeRoot) =>
|
|
69004
|
+
filePath: (homeRoot) => path160.join(homeRoot, ".config", "antigravity", "AGENTS.md")
|
|
68468
69005
|
}
|
|
68469
69006
|
];
|
|
68470
69007
|
function agentBootstrapRuntimeIds() {
|
|
@@ -68497,7 +69034,7 @@ function resolveAgentBootstrapRuntimes(ids) {
|
|
|
68497
69034
|
async function agentBootstrapStatus(runtime, homeRoot = homedir7()) {
|
|
68498
69035
|
const filePath = runtime.filePath(homeRoot);
|
|
68499
69036
|
const exists2 = await pathExists(filePath);
|
|
68500
|
-
const content = exists2 ? await
|
|
69037
|
+
const content = exists2 ? await readFile81(filePath, "utf8") : "";
|
|
68501
69038
|
const expected = renderAgentBootstrapBlock(runtime.fileName).trim();
|
|
68502
69039
|
const installed = content.includes(AGENT_BOOTSTRAP_START);
|
|
68503
69040
|
const current = installed && extractManagedBlock(content)?.trim() === expected;
|
|
@@ -68507,12 +69044,12 @@ async function installAgentBootstrap(runtime, options = {}) {
|
|
|
68507
69044
|
const homeRoot = options.homeRoot ?? homedir7();
|
|
68508
69045
|
const filePath = runtime.filePath(homeRoot);
|
|
68509
69046
|
const exists2 = await pathExists(filePath);
|
|
68510
|
-
const current = exists2 ? await
|
|
69047
|
+
const current = exists2 ? await readFile81(filePath, "utf8") : "";
|
|
68511
69048
|
const next = upsertManagedBlock(current || defaultAgentFile(runtime), renderAgentBootstrapBlock(runtime.fileName));
|
|
68512
69049
|
const dryRun = options.dryRun === true;
|
|
68513
69050
|
const wrote = next !== current;
|
|
68514
69051
|
if (wrote && !dryRun) {
|
|
68515
|
-
await
|
|
69052
|
+
await mkdir57(path160.dirname(filePath), { recursive: true });
|
|
68516
69053
|
await writeFile50(filePath, next, "utf8");
|
|
68517
69054
|
}
|
|
68518
69055
|
const status = dryRun ? statusFromContent(runtime, filePath, exists2, next) : await agentBootstrapStatus(runtime, homeRoot);
|
|
@@ -68522,7 +69059,7 @@ async function uninstallAgentBootstrap(runtime, options = {}) {
|
|
|
68522
69059
|
const homeRoot = options.homeRoot ?? homedir7();
|
|
68523
69060
|
const filePath = runtime.filePath(homeRoot);
|
|
68524
69061
|
const exists2 = await pathExists(filePath);
|
|
68525
|
-
const current = exists2 ? await
|
|
69062
|
+
const current = exists2 ? await readFile81(filePath, "utf8") : "";
|
|
68526
69063
|
const next = removeManagedBlock(current);
|
|
68527
69064
|
const dryRun = options.dryRun === true;
|
|
68528
69065
|
const removed = next !== current;
|
|
@@ -69048,8 +69585,8 @@ function printBootstrapHelp() {
|
|
|
69048
69585
|
|
|
69049
69586
|
// src/commands/metrics.ts
|
|
69050
69587
|
init_args();
|
|
69051
|
-
import { readFile as
|
|
69052
|
-
import
|
|
69588
|
+
import { readFile as readFile82 } from "fs/promises";
|
|
69589
|
+
import path162 from "path";
|
|
69053
69590
|
|
|
69054
69591
|
// src/metrics/benchmark.ts
|
|
69055
69592
|
var RELIABILITIES2 = new Set(["exact", "estimated", "unknown"]);
|
|
@@ -69827,8 +70364,8 @@ function buildContainmentManifest(inputs, options = {}) {
|
|
|
69827
70364
|
}
|
|
69828
70365
|
|
|
69829
70366
|
// src/metrics/oracle-runner.ts
|
|
69830
|
-
import { mkdir as
|
|
69831
|
-
import
|
|
70367
|
+
import { mkdir as mkdir58, writeFile as writeFile51 } from "fs/promises";
|
|
70368
|
+
import path161 from "path";
|
|
69832
70369
|
|
|
69833
70370
|
// src/metrics/ir.ts
|
|
69834
70371
|
function toIdSet(ids) {
|
|
@@ -70270,9 +70807,9 @@ function buildEvidenceBundle(input2, options = {}) {
|
|
|
70270
70807
|
async function persistEvidenceBundle(outDir, bundle, ladder = "metastore") {
|
|
70271
70808
|
const safeTarget = bundle.target.replace(/[^A-Za-z0-9._/-]/g, "_");
|
|
70272
70809
|
const safeCase = bundle.caseId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
70273
|
-
const dir =
|
|
70274
|
-
await
|
|
70275
|
-
const write = (name, value) => writeFile51(
|
|
70810
|
+
const dir = path161.join(outDir, "bench", ladder, safeTarget, safeCase, bundle.variant, String(bundle.seed));
|
|
70811
|
+
await mkdir58(dir, { recursive: true });
|
|
70812
|
+
const write = (name, value) => writeFile51(path161.join(dir, name), `${JSON.stringify(value, null, 2)}
|
|
70276
70813
|
`, "utf8");
|
|
70277
70814
|
await Promise.all([
|
|
70278
70815
|
write("inputs.json", bundle.inputs),
|
|
@@ -70312,7 +70849,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70312
70849
|
console.log("# metrics status");
|
|
70313
70850
|
console.log("");
|
|
70314
70851
|
console.log(`root: ${root}`);
|
|
70315
|
-
console.log(`enabled: ${await Bun.file(
|
|
70852
|
+
console.log(`enabled: ${await Bun.file(path162.join(projectRoot, ".metaproject", "metaproject.json")).exists() ? "yes" : "no"}`);
|
|
70316
70853
|
const latest2 = await readLatestPointer(root);
|
|
70317
70854
|
console.log(`latest: ${latest2.status}`);
|
|
70318
70855
|
return;
|
|
@@ -70324,7 +70861,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70324
70861
|
process.exitCode = 1;
|
|
70325
70862
|
return;
|
|
70326
70863
|
}
|
|
70327
|
-
const record2 = JSON.parse(await
|
|
70864
|
+
const record2 = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70328
70865
|
const result = validateRunRecord(record2);
|
|
70329
70866
|
console.log(result.valid ? "valid: yes" : "valid: no");
|
|
70330
70867
|
for (const error2 of result.errors)
|
|
@@ -70349,13 +70886,13 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70349
70886
|
process.exitCode = 1;
|
|
70350
70887
|
return;
|
|
70351
70888
|
}
|
|
70352
|
-
const file =
|
|
70889
|
+
const file = path162.join(metricsRoot(projectRoot), "runs", `${runId}.json`);
|
|
70353
70890
|
if (!await Bun.file(file).exists()) {
|
|
70354
70891
|
console.error(`Run not found: ${runId}`);
|
|
70355
70892
|
process.exitCode = 1;
|
|
70356
70893
|
return;
|
|
70357
70894
|
}
|
|
70358
|
-
console.log(await
|
|
70895
|
+
console.log(await readFile82(file, "utf8"));
|
|
70359
70896
|
return;
|
|
70360
70897
|
}
|
|
70361
70898
|
if (subcommand === "compare") {
|
|
@@ -70366,8 +70903,8 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70366
70903
|
process.exitCode = 1;
|
|
70367
70904
|
return;
|
|
70368
70905
|
}
|
|
70369
|
-
const a = JSON.parse(await
|
|
70370
|
-
const b = JSON.parse(await
|
|
70906
|
+
const a = JSON.parse(await readFile82(path162.join(metricsRoot(projectRoot), "runs", `${runA}.json`), "utf8"));
|
|
70907
|
+
const b = JSON.parse(await readFile82(path162.join(metricsRoot(projectRoot), "runs", `${runB}.json`), "utf8"));
|
|
70371
70908
|
const comparison = compareExecutionRuns(a, b);
|
|
70372
70909
|
console.log(stableJson(comparison));
|
|
70373
70910
|
return;
|
|
@@ -70401,8 +70938,8 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70401
70938
|
return;
|
|
70402
70939
|
}
|
|
70403
70940
|
const template = createPairedBenchmarkTemplate(taskIds);
|
|
70404
|
-
await Bun.write(
|
|
70405
|
-
console.log(`manifest: ${
|
|
70941
|
+
await Bun.write(path162.resolve(projectRoot, out), stableJson(template));
|
|
70942
|
+
console.log(`manifest: ${path162.relative(projectRoot, path162.resolve(projectRoot, out))}`);
|
|
70406
70943
|
return;
|
|
70407
70944
|
}
|
|
70408
70945
|
if (subcommand === "benchmark" && args2[1] === "run") {
|
|
@@ -70416,7 +70953,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70416
70953
|
process.exitCode = 1;
|
|
70417
70954
|
return;
|
|
70418
70955
|
}
|
|
70419
|
-
const raw = JSON.parse(await
|
|
70956
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70420
70957
|
const input2 = Array.isArray(raw) ? raw : raw.runs ?? [];
|
|
70421
70958
|
const result = validatePairedBenchmark(input2);
|
|
70422
70959
|
console.log(stableJson(result));
|
|
@@ -70428,7 +70965,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
70428
70965
|
process.exitCode = 1;
|
|
70429
70966
|
}
|
|
70430
70967
|
async function loadAffectedSets(projectRoot, file) {
|
|
70431
|
-
const raw = JSON.parse(await
|
|
70968
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70432
70969
|
const map = new Map;
|
|
70433
70970
|
for (const entry of raw.targets ?? []) {
|
|
70434
70971
|
if (typeof entry.target === "string")
|
|
@@ -70499,7 +71036,7 @@ async function runHarnessLayer(projectRoot, args2, ladder) {
|
|
|
70499
71036
|
let tasks;
|
|
70500
71037
|
let model;
|
|
70501
71038
|
try {
|
|
70502
|
-
const raw = JSON.parse(await
|
|
71039
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, resultsPath), "utf8"));
|
|
70503
71040
|
tasks = raw.tasks ?? [];
|
|
70504
71041
|
model = raw.model;
|
|
70505
71042
|
} catch (error2) {
|
|
@@ -70530,7 +71067,7 @@ async function runSafetyCompletionHonestyLayer(projectRoot, args2, ladder) {
|
|
|
70530
71067
|
let cases;
|
|
70531
71068
|
let model;
|
|
70532
71069
|
try {
|
|
70533
|
-
const raw = JSON.parse(await
|
|
71070
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, resultsPath), "utf8"));
|
|
70534
71071
|
cases = raw.cases ?? [];
|
|
70535
71072
|
model = raw.model;
|
|
70536
71073
|
} catch (error2) {
|
|
@@ -70555,7 +71092,7 @@ async function runSafetyFalsePremiseLayer(projectRoot, args2, ladder) {
|
|
|
70555
71092
|
let cases;
|
|
70556
71093
|
let model;
|
|
70557
71094
|
try {
|
|
70558
|
-
const raw = JSON.parse(await
|
|
71095
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, resultsPath), "utf8"));
|
|
70559
71096
|
cases = raw.cases ?? [];
|
|
70560
71097
|
model = raw.model;
|
|
70561
71098
|
} catch (error2) {
|
|
@@ -70580,7 +71117,7 @@ async function runSafetyContainmentLayer(projectRoot, args2, ladder, caseClass)
|
|
|
70580
71117
|
let cases;
|
|
70581
71118
|
let model;
|
|
70582
71119
|
try {
|
|
70583
|
-
const raw = JSON.parse(await
|
|
71120
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, resultsPath), "utf8"));
|
|
70584
71121
|
cases = raw.cases ?? [];
|
|
70585
71122
|
model = raw.model;
|
|
70586
71123
|
} catch (error2) {
|
|
@@ -70642,12 +71179,12 @@ async function runGdgraphLayer(projectRoot, args2, ladder) {
|
|
|
70642
71179
|
}
|
|
70643
71180
|
const manifests = buildOracleManifestsByGold(inputs, { ladder });
|
|
70644
71181
|
if (outDir) {
|
|
70645
|
-
const resolvedOut =
|
|
71182
|
+
const resolvedOut = path162.resolve(projectRoot, outDir);
|
|
70646
71183
|
for (const input2 of inputs) {
|
|
70647
71184
|
for (const named of input2.golds) {
|
|
70648
71185
|
const bundle = buildEvidenceBundle({ target: input2.target, system: input2.system, gold: named.gold }, { ladder, goldReference: goldPathFor(named.kind), timestamp: new Date().toISOString() });
|
|
70649
|
-
const dir = await persistEvidenceBundle(
|
|
70650
|
-
console.error(`bundle[${named.kind}]: ${
|
|
71186
|
+
const dir = await persistEvidenceBundle(path162.join(resolvedOut, named.kind), bundle, ladder);
|
|
71187
|
+
console.error(`bundle[${named.kind}]: ${path162.relative(projectRoot, dir)}`);
|
|
70651
71188
|
}
|
|
70652
71189
|
}
|
|
70653
71190
|
}
|
|
@@ -70671,7 +71208,7 @@ async function runGdgraphLayer(projectRoot, args2, ladder) {
|
|
|
70671
71208
|
return allValid;
|
|
70672
71209
|
}
|
|
70673
71210
|
async function loadCoverageMap2(projectRoot, file) {
|
|
70674
|
-
const raw = JSON.parse(await
|
|
71211
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70675
71212
|
return raw.coverageMap ?? {};
|
|
70676
71213
|
}
|
|
70677
71214
|
async function runTestingLayer(projectRoot, args2, ladder) {
|
|
@@ -70708,7 +71245,7 @@ async function runTestingLayer(projectRoot, args2, ladder) {
|
|
|
70708
71245
|
return result.valid;
|
|
70709
71246
|
}
|
|
70710
71247
|
async function loadMemoryGoldK(projectRoot, file) {
|
|
70711
|
-
const raw = JSON.parse(await
|
|
71248
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70712
71249
|
return typeof raw.k === "number" && raw.k > 0 ? raw.k : 3;
|
|
70713
71250
|
}
|
|
70714
71251
|
async function runMemoryLayer(projectRoot, args2, ladder) {
|
|
@@ -70745,11 +71282,11 @@ async function runMemoryLayer(projectRoot, args2, ladder) {
|
|
|
70745
71282
|
return result.valid;
|
|
70746
71283
|
}
|
|
70747
71284
|
async function loadWikiGoldK(projectRoot, file) {
|
|
70748
|
-
const raw = JSON.parse(await
|
|
71285
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70749
71286
|
return typeof raw.k === "number" && raw.k > 0 ? raw.k : 5;
|
|
70750
71287
|
}
|
|
70751
71288
|
async function loadWikiGroundedness(projectRoot, file) {
|
|
70752
|
-
const raw = JSON.parse(await
|
|
71289
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70753
71290
|
const map = new Map;
|
|
70754
71291
|
for (const entry of raw.targets ?? []) {
|
|
70755
71292
|
if (typeof entry.target !== "string" || !Array.isArray(entry.scores) || entry.scores.length !== 3)
|
|
@@ -70805,7 +71342,7 @@ async function runWikiLayer(projectRoot, args2, ladder) {
|
|
|
70805
71342
|
return result.valid;
|
|
70806
71343
|
}
|
|
70807
71344
|
async function loadGdctxFacts(projectRoot, file) {
|
|
70808
|
-
const raw = JSON.parse(await
|
|
71345
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, file), "utf8"));
|
|
70809
71346
|
const inputs = [];
|
|
70810
71347
|
for (const entry of raw.inputs ?? []) {
|
|
70811
71348
|
if (typeof entry.input === "string") {
|
|
@@ -70843,7 +71380,7 @@ async function collect(projectRoot, args2) {
|
|
|
70843
71380
|
process.exitCode = 1;
|
|
70844
71381
|
return;
|
|
70845
71382
|
}
|
|
70846
|
-
const raw = JSON.parse(await
|
|
71383
|
+
const raw = JSON.parse(await readFile82(path162.resolve(projectRoot, eventFile), "utf8"));
|
|
70847
71384
|
const events2 = Array.isArray(raw) ? raw : raw.events;
|
|
70848
71385
|
const startedAt = optionValue(args2, "--started-at") ?? events2[0]?.timestamp_utc ?? new Date().toISOString();
|
|
70849
71386
|
const finishedAt = optionValue(args2, "--finished-at") ?? events2.at(-1)?.timestamp_utc ?? startedAt;
|
|
@@ -70859,11 +71396,11 @@ async function collect(projectRoot, args2) {
|
|
|
70859
71396
|
parentRunId: optionValue(args2, "--parent-run-id") ?? null
|
|
70860
71397
|
});
|
|
70861
71398
|
const result = await writeRunArtifacts(metricsRoot(projectRoot), record2, { cwd: projectRoot });
|
|
70862
|
-
console.log(`json: ${
|
|
70863
|
-
console.log(`markdown: ${
|
|
71399
|
+
console.log(`json: ${path162.relative(projectRoot, result.jsonPath)}`);
|
|
71400
|
+
console.log(`markdown: ${path162.relative(projectRoot, result.markdownPath)}`);
|
|
70864
71401
|
}
|
|
70865
71402
|
function metricsRoot(projectRoot) {
|
|
70866
|
-
return
|
|
71403
|
+
return path162.join(projectRoot, ".metaproject", "data", "metrics");
|
|
70867
71404
|
}
|
|
70868
71405
|
function printMetricsHelp() {
|
|
70869
71406
|
console.log(`keryx metrics
|