@mrciphersmith/keryx 0.3.89 → 0.3.91
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
CHANGED
|
@@ -21105,7 +21105,7 @@ var package_default;
|
|
|
21105
21105
|
var init_package = __esm(() => {
|
|
21106
21106
|
package_default = {
|
|
21107
21107
|
name: "@mrciphersmith/keryx",
|
|
21108
|
-
version: "0.3.
|
|
21108
|
+
version: "0.3.91",
|
|
21109
21109
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
21110
21110
|
private: false,
|
|
21111
21111
|
publishConfig: {
|
|
@@ -98346,7 +98346,7 @@ var init_registry3 = __esm(() => {
|
|
|
98346
98346
|
// src/harness/tool/builtin/spawn-subagent-tool.ts
|
|
98347
98347
|
import { createHash as createHash64, randomUUID as randomUUID26 } from "crypto";
|
|
98348
98348
|
import { execFile as execFile7 } from "child_process";
|
|
98349
|
-
import { lstat as lstat15, mkdtemp as mkdtemp2, readFile as readFile108, realpath as realpath19, rm as rm15, stat as stat27 } from "fs/promises";
|
|
98349
|
+
import { lstat as lstat15, mkdir as mkdir56, mkdtemp as mkdtemp2, readFile as readFile108, realpath as realpath19, rm as rm15, stat as stat27, writeFile as writeFile36 } from "fs/promises";
|
|
98350
98350
|
import { tmpdir as tmpdir6 } from "os";
|
|
98351
98351
|
import path222 from "path";
|
|
98352
98352
|
import { promisify as promisify5 } from "util";
|
|
@@ -98413,6 +98413,57 @@ ${blocks.join(`
|
|
|
98413
98413
|
|
|
98414
98414
|
`)}` };
|
|
98415
98415
|
}
|
|
98416
|
+
async function resolveSaveResultPath(root, target) {
|
|
98417
|
+
if (target === undefined)
|
|
98418
|
+
return { ok: true, abs: undefined };
|
|
98419
|
+
if (typeof target !== "string" || target.trim() === "") {
|
|
98420
|
+
return { ok: false, reason: "spawn_subagent save_result_to must be a non-empty project-relative path" };
|
|
98421
|
+
}
|
|
98422
|
+
const abs = confineToRoot(root, target);
|
|
98423
|
+
if (abs === null)
|
|
98424
|
+
return { ok: false, reason: `spawn_subagent save_result_to path escapes the project root: ${target}` };
|
|
98425
|
+
if (CONTEXT_FILE_DENYLIST.test(path222.relative(root, abs).split(path222.sep).join("/"))) {
|
|
98426
|
+
return { ok: false, reason: `spawn_subagent save_result_to refuses a credential or VCS-internal path: ${target}` };
|
|
98427
|
+
}
|
|
98428
|
+
try {
|
|
98429
|
+
const realRoot = await realpath19(root);
|
|
98430
|
+
let probe = abs;
|
|
98431
|
+
for (;; ) {
|
|
98432
|
+
try {
|
|
98433
|
+
const real = await realpath19(probe);
|
|
98434
|
+
const rel = path222.relative(realRoot, real);
|
|
98435
|
+
if (rel.startsWith("..") || path222.isAbsolute(rel)) {
|
|
98436
|
+
return { ok: false, reason: `spawn_subagent save_result_to resolves outside the project root: ${target}` };
|
|
98437
|
+
}
|
|
98438
|
+
if (probe === abs && !(await stat27(abs)).isFile()) {
|
|
98439
|
+
return { ok: false, reason: `spawn_subagent save_result_to is not a regular file: ${target}` };
|
|
98440
|
+
}
|
|
98441
|
+
break;
|
|
98442
|
+
} catch (err) {
|
|
98443
|
+
if (err.code !== "ENOENT")
|
|
98444
|
+
throw err;
|
|
98445
|
+
const parent = path222.dirname(probe);
|
|
98446
|
+
if (parent === probe)
|
|
98447
|
+
throw err;
|
|
98448
|
+
probe = parent;
|
|
98449
|
+
}
|
|
98450
|
+
}
|
|
98451
|
+
} catch {
|
|
98452
|
+
return { ok: false, reason: `spawn_subagent save_result_to cannot be used: ${target}` };
|
|
98453
|
+
}
|
|
98454
|
+
return { ok: true, abs };
|
|
98455
|
+
}
|
|
98456
|
+
async function saveChildResult(abs, text) {
|
|
98457
|
+
try {
|
|
98458
|
+
await mkdir56(path222.dirname(abs), { recursive: true });
|
|
98459
|
+
await writeFile36(abs, text.endsWith(`
|
|
98460
|
+
`) ? text : `${text}
|
|
98461
|
+
`, "utf8");
|
|
98462
|
+
return;
|
|
98463
|
+
} catch (err) {
|
|
98464
|
+
return err.message;
|
|
98465
|
+
}
|
|
98466
|
+
}
|
|
98416
98467
|
function resolveSubagentMaxToolCalls(env = process.env) {
|
|
98417
98468
|
const n = parseIntEnvVar(env, ENV_SUBAGENT_MAX_TOOL_CALLS);
|
|
98418
98469
|
return n === undefined || n <= 0 ? undefined : n;
|
|
@@ -98618,7 +98669,7 @@ function createSpawnSubagentTool(deps) {
|
|
|
98618
98669
|
return {
|
|
98619
98670
|
definition: {
|
|
98620
98671
|
name: "spawn_subagent",
|
|
98621
|
-
description: "Spawn a bounded subagent to work on a focused subtask in parallel-safe isolation " + "(MAE multi-agent). Use for independent investigations, reviews, or research while " + "you continue the main plan. Input: { task: string, mode?: 'read_only'|'general', " + "label?: string, max_tool_calls?: integer, max_rounds?: integer, context_files?: string[] }. " + "max_tool_calls is ADVISORY: it never stops the child, it only sets when the child is warned " + "(from 80% of it) to return its result; a hard tool-call cap exists only when the operator " + `configures ${ENV_SUBAGENT_MAX_TOOL_CALLS}. max_rounds limits model rounds (default 40, capped ` + "at 200). A child that hits its round budget or the operator's call cap gets one final round to " + "submit a partial result, and the output's first line is then 'status: BudgetExhausted (...)'. " + "External runtimes cannot accept these limits. " + "Default mode is read_only (no shell). " + "Returns the child's summary. Prefer one clear task per spawn; do not spawn for " + "trivial questions (answer yourself). Optionally accepts a 'model_tier' " + "(light|standard|deep) to size the child's model against your own, and a 'runtime' " + "block to delegate the child to an external vendor coding CLI instead of running it " + "in-process. Optional 'cwd' runs the child's tools against a different directory than " + "yours (e.g. a review worktree checked out at a PR head) \u2014 accepted only when it is your " + "own project root, a descendant of it, or one of its git worktrees; a relative path " + "resolves against your own cwd. Not supported for external (runtime.kind='external') children.",
|
|
98672
|
+
description: "Spawn a bounded subagent to work on a focused subtask in parallel-safe isolation " + "(MAE multi-agent). Use for independent investigations, reviews, or research while " + "you continue the main plan. Input: { task: string, mode?: 'read_only'|'general', " + "label?: string, max_tool_calls?: integer, max_rounds?: integer, context_files?: string[], save_result_to?: string }. " + "max_tool_calls is ADVISORY: it never stops the child, it only sets when the child is warned " + "(from 80% of it) to return its result; a hard tool-call cap exists only when the operator " + `configures ${ENV_SUBAGENT_MAX_TOOL_CALLS}. max_rounds limits model rounds (default 40, capped ` + "at 200). A child that hits its round budget or the operator's call cap gets one final round to " + "submit a partial result, and the output's first line is then 'status: BudgetExhausted (...)'. " + "External runtimes cannot accept these limits. " + "Default mode is read_only (no shell). " + "Returns the child's summary. Prefer one clear task per spawn; do not spawn for " + "trivial questions (answer yourself). Optionally accepts a 'model_tier' " + "(light|standard|deep) to size the child's model against your own, and a 'runtime' " + "block to delegate the child to an external vendor coding CLI instead of running it " + "in-process. Optional 'cwd' runs the child's tools against a different directory than " + "yours (e.g. a review worktree checked out at a PR head) \u2014 accepted only when it is your " + "own project root, a descendant of it, or one of its git worktrees; a relative path " + "resolves against your own cwd. Not supported for external (runtime.kind='external') children.",
|
|
98622
98673
|
inputSchema: {
|
|
98623
98674
|
type: "object",
|
|
98624
98675
|
properties: {
|
|
@@ -98640,6 +98691,10 @@ function createSpawnSubagentTool(deps) {
|
|
|
98640
98691
|
items: { type: "string" },
|
|
98641
98692
|
description: "Project-relative files (e.g. review slices) the host copies into the child's task, so " + "you do not paste them yourself. Resolved against your own project root (not 'cwd'); native " + "children only; credential files (.env*, keys) are refused. Up to 40 files and 400000 bytes in total."
|
|
98642
98693
|
},
|
|
98694
|
+
save_result_to: {
|
|
98695
|
+
type: "string",
|
|
98696
|
+
description: "Project-relative file the host writes the child's complete final text to when it ends, " + "so the result survives your own context (e.g. .metaproject/data/review/raw/<reviewer>.txt). " + "Native children only; credential and VCS paths are refused."
|
|
98697
|
+
},
|
|
98643
98698
|
max_rounds: {
|
|
98644
98699
|
type: "integer",
|
|
98645
98700
|
minimum: 1,
|
|
@@ -98718,6 +98773,17 @@ function createSpawnSubagentTool(deps) {
|
|
|
98718
98773
|
if (!attached.ok) {
|
|
98719
98774
|
return { status: "Error", output: attached.reason, isError: true };
|
|
98720
98775
|
}
|
|
98776
|
+
if (input.save_result_to !== undefined && isExternalRuntimeRequest) {
|
|
98777
|
+
return {
|
|
98778
|
+
status: "Error",
|
|
98779
|
+
output: "spawn_subagent save_result_to is not supported for external (runtime.kind='external') children.",
|
|
98780
|
+
isError: true
|
|
98781
|
+
};
|
|
98782
|
+
}
|
|
98783
|
+
const saveTarget = await resolveSaveResultPath(deps.cwd, input.save_result_to);
|
|
98784
|
+
if (!saveTarget.ok) {
|
|
98785
|
+
return { status: "Error", output: saveTarget.reason, isError: true };
|
|
98786
|
+
}
|
|
98721
98787
|
const task = taskText;
|
|
98722
98788
|
const labelRaw = typeof input.label === "string" ? input.label.trim() : "";
|
|
98723
98789
|
childSeq += 1;
|
|
@@ -99191,9 +99257,11 @@ ${boundSummary(foldedPartial)}` : ""),
|
|
|
99191
99257
|
` + `MAE reservation: rounds\u2264${maxRounds} ` + (configuredMaxToolCalls === undefined ? "" : `calls\u2264${configuredMaxToolCalls} `) + (advisoryToolCalls === undefined ? "" : `calls~${advisoryToolCalls}(advisory) `) + `runtime\u2264${spawned.reservation.maxRuntimeMs}ms children=${ledger.childCount}
|
|
99192
99258
|
` + (tierRecord === undefined ? "" : `${tierRecord}
|
|
99193
99259
|
`);
|
|
99260
|
+
const saveNote = saveTarget.abs === undefined ? "" : `
|
|
99261
|
+
[full result ${await saveChildResult(saveTarget.abs, raw) === undefined ? "saved to" : "could NOT be saved to"} ${String(input.save_result_to)}]`;
|
|
99194
99262
|
if (status === "Completed") {
|
|
99195
99263
|
return { status, isError, output: `${header}--- summary ---
|
|
99196
|
-
${boundSummary(folded.text)}` };
|
|
99264
|
+
${boundSummary(folded.text)}${saveNote}` };
|
|
99197
99265
|
}
|
|
99198
99266
|
const statusLine = formatStoppedStatusLine(status, turnResult);
|
|
99199
99267
|
const submitted = turnResult?.submittedResult;
|
|
@@ -99208,7 +99276,7 @@ ${raw}`).text;
|
|
|
99208
99276
|
status,
|
|
99209
99277
|
isError,
|
|
99210
99278
|
output: `${statusLine}
|
|
99211
|
-
${header}${boundedResult}`,
|
|
99279
|
+
${header}${boundedResult}${saveNote}`,
|
|
99212
99280
|
partial: boundedResult
|
|
99213
99281
|
};
|
|
99214
99282
|
} catch (cause) {
|
|
@@ -100926,7 +100994,7 @@ var init_dispatch2 = __esm(() => {
|
|
|
100926
100994
|
|
|
100927
100995
|
// src/harness/external/acp-fs.ts
|
|
100928
100996
|
import { constants as constants2, realpathSync as realpathSync15, statSync as statSync12 } from "fs";
|
|
100929
|
-
import { mkdir as
|
|
100997
|
+
import { mkdir as mkdir57, open as open10, readFile as readFile109 } from "fs/promises";
|
|
100930
100998
|
import path225 from "path";
|
|
100931
100999
|
function refusedMethodError(method, reason) {
|
|
100932
101000
|
return new AcpError(JSON_RPC_ERROR_CODES.methodNotFound, `${method} refused: ${reason}`, { reason });
|
|
@@ -100985,7 +101053,7 @@ async function writeTextFileInWorktree(worktree, target, content, requested, hoo
|
|
|
100985
101053
|
}
|
|
100986
101054
|
await hooks.beforeWrite?.();
|
|
100987
101055
|
const parent = path225.dirname(target);
|
|
100988
|
-
await
|
|
101056
|
+
await mkdir57(parent, { recursive: true });
|
|
100989
101057
|
const rootReal = realpathSync15(worktree);
|
|
100990
101058
|
const parentReal = realpathSync15(parent);
|
|
100991
101059
|
const rel = path225.relative(rootReal, parentReal);
|
|
@@ -103087,7 +103155,7 @@ var init_codec2 = __esm(() => {
|
|
|
103087
103155
|
});
|
|
103088
103156
|
|
|
103089
103157
|
// src/harness/external/runtime.ts
|
|
103090
|
-
import { mkdtemp as mkdtemp4, rm as rm17, writeFile as
|
|
103158
|
+
import { mkdtemp as mkdtemp4, rm as rm17, writeFile as writeFile37 } from "fs/promises";
|
|
103091
103159
|
import { tmpdir as tmpdir8 } from "os";
|
|
103092
103160
|
import path227 from "path";
|
|
103093
103161
|
function refuse2(status, output) {
|
|
@@ -103100,7 +103168,7 @@ async function prepareResultSchema() {
|
|
|
103100
103168
|
const schemaText = JSON.stringify(schema, null, 2);
|
|
103101
103169
|
schemaDir = await mkdtemp4(path227.join(tmpdir8(), "keryx-external-result-schema-"));
|
|
103102
103170
|
const schemaPath = path227.join(schemaDir, "subagent-result.schema.json");
|
|
103103
|
-
await
|
|
103171
|
+
await writeFile37(schemaPath, schemaText, "utf8");
|
|
103104
103172
|
return { ok: true, schema, schemaText, schemaPath, schemaDir };
|
|
103105
103173
|
} catch (error) {
|
|
103106
103174
|
if (schemaDir !== undefined) {
|
|
@@ -103209,7 +103277,7 @@ async function runExternalChild(input, deps) {
|
|
|
103209
103277
|
if (codexStrict) {
|
|
103210
103278
|
resultSchemaPathForCodec = path227.join(schemaDir, STRICT_SCHEMA_FILE);
|
|
103211
103279
|
try {
|
|
103212
|
-
await
|
|
103280
|
+
await writeFile37(resultSchemaPathForCodec, JSON.stringify(toStrictOutputSchema(bundledResultSchema)), "utf8");
|
|
103213
103281
|
} catch (error) {
|
|
103214
103282
|
await rm17(schemaDir, { recursive: true, force: true }).catch(() => {
|
|
103215
103283
|
return;
|
|
@@ -103475,7 +103543,7 @@ var init_runtime2 = __esm(() => {
|
|
|
103475
103543
|
// src/harness/run-external-factory.ts
|
|
103476
103544
|
import { randomUUID as randomUUID27 } from "crypto";
|
|
103477
103545
|
import { execFile as execFile10 } from "child_process";
|
|
103478
|
-
import { mkdir as
|
|
103546
|
+
import { mkdir as mkdir58 } from "fs/promises";
|
|
103479
103547
|
import { tmpdir as tmpdir9 } from "os";
|
|
103480
103548
|
import path228 from "path";
|
|
103481
103549
|
import { promisify as promisify8 } from "util";
|
|
@@ -103505,7 +103573,7 @@ async function defaultWorkingDiff(cwd) {
|
|
|
103505
103573
|
function ensuringParentDir(port, worktreesDir) {
|
|
103506
103574
|
return {
|
|
103507
103575
|
async create(worktreeId) {
|
|
103508
|
-
await
|
|
103576
|
+
await mkdir58(worktreesDir, { recursive: true });
|
|
103509
103577
|
return port.create(worktreeId);
|
|
103510
103578
|
},
|
|
103511
103579
|
remove: (worktreeId) => port.remove(worktreeId),
|
|
@@ -117740,7 +117808,7 @@ var init_repair = __esm(() => {
|
|
|
117740
117808
|
});
|
|
117741
117809
|
|
|
117742
117810
|
// src/review/managed.ts
|
|
117743
|
-
import { mkdir as
|
|
117811
|
+
import { mkdir as mkdir59, readFile as readFile121, readdir as readdir39, realpath as realpath20, rm as rm18, stat as stat29 } from "fs/promises";
|
|
117744
117812
|
import path252 from "path";
|
|
117745
117813
|
function reviewsRoot(cwd) {
|
|
117746
117814
|
return path252.join(cwd, ".metaproject", "reviews");
|
|
@@ -117876,7 +117944,7 @@ async function createManagedReviewPackage(input) {
|
|
|
117876
117944
|
if (contractErrors.length > 0) {
|
|
117877
117945
|
throw new Error(`Refusing to record findings that do not satisfy review-finding.schema.json: ${contractErrors.map((error) => `${error.path} ${error.message}`).join("; ")}`);
|
|
117878
117946
|
}
|
|
117879
|
-
await
|
|
117947
|
+
await mkdir59(packageDir, { recursive: true });
|
|
117880
117948
|
await writeFileAtomic(path252.join(packageDir, "research.json"), `${JSON.stringify(input.research ?? PENDING_RESEARCH, null, 2)}
|
|
117881
117949
|
`);
|
|
117882
117950
|
await writeFileAtomic(path252.join(packageDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
@@ -118152,7 +118220,13 @@ async function readReport(input) {
|
|
|
118152
118220
|
return input.reportText;
|
|
118153
118221
|
}
|
|
118154
118222
|
if (input.reportPath) {
|
|
118155
|
-
|
|
118223
|
+
try {
|
|
118224
|
+
return await readFile121(path252.resolve(input.cwd, input.reportPath), "utf8");
|
|
118225
|
+
} catch (error) {
|
|
118226
|
+
const code = error.code;
|
|
118227
|
+
if (input.mode === "ingest" || code !== "ENOENT" && code !== "EISDIR")
|
|
118228
|
+
throw error;
|
|
118229
|
+
}
|
|
118156
118230
|
}
|
|
118157
118231
|
if (input.mode === "ingest") {
|
|
118158
118232
|
throw new Error("ingest requires --report or reportText");
|
|
@@ -125399,7 +125473,7 @@ var init_aggregate = __esm(() => {
|
|
|
125399
125473
|
});
|
|
125400
125474
|
|
|
125401
125475
|
// src/governance/report.ts
|
|
125402
|
-
import { mkdir as
|
|
125476
|
+
import { mkdir as mkdir60 } from "fs/promises";
|
|
125403
125477
|
import path261 from "path";
|
|
125404
125478
|
function governanceDataRoot(cwd) {
|
|
125405
125479
|
return path261.join(cwd, ".metaproject", "data", "governance");
|
|
@@ -125585,7 +125659,7 @@ function renderTriggerSpendLine(spend) {
|
|
|
125585
125659
|
}
|
|
125586
125660
|
async function writeGovernanceArtifacts(cwd, report) {
|
|
125587
125661
|
const { markdown, json } = artifactPaths(cwd);
|
|
125588
|
-
await
|
|
125662
|
+
await mkdir60(path261.dirname(markdown), { recursive: true });
|
|
125589
125663
|
await writeFileAtomic(markdown, renderGovernanceMarkdown(report));
|
|
125590
125664
|
await writeFileAtomic(json, `${JSON.stringify(report, null, 2)}
|
|
125591
125665
|
`);
|
|
@@ -128773,7 +128847,7 @@ var init_granted_json_ids = __esm(() => {
|
|
|
128773
128847
|
// src/commands/trigger-agent-task.ts
|
|
128774
128848
|
import { execFile as execFile11 } from "child_process";
|
|
128775
128849
|
import { randomUUID as randomUUID35 } from "crypto";
|
|
128776
|
-
import { mkdtemp as mkdtemp5, mkdir as
|
|
128850
|
+
import { mkdtemp as mkdtemp5, mkdir as mkdir61, readdir as readdir42, rm as rm19, writeFile as writeFile38 } from "fs/promises";
|
|
128777
128851
|
import { homedir as homedir12, tmpdir as tmpdir11 } from "os";
|
|
128778
128852
|
import path268 from "path";
|
|
128779
128853
|
function scrubGrantedOutput(text, env, secrets = [], json = false) {
|
|
@@ -128944,9 +129018,9 @@ async function runLocked(projectRoot, entry, action, deps, runId, now) {
|
|
|
128944
129018
|
const workdir = path268.join(scratch, "work");
|
|
128945
129019
|
const scratchHome = path268.join(scratch, "home");
|
|
128946
129020
|
const grantedCwd = path268.join(scratch, "granted-cwd");
|
|
128947
|
-
await
|
|
128948
|
-
await
|
|
128949
|
-
await
|
|
129021
|
+
await mkdir61(workdir, { recursive: true });
|
|
129022
|
+
await mkdir61(scratchHome, { recursive: true });
|
|
129023
|
+
await mkdir61(grantedCwd, { recursive: true, mode: 448 });
|
|
128950
129024
|
const cleanup = async () => {
|
|
128951
129025
|
await rm19(scratch, { recursive: true, force: true }).catch(() => {});
|
|
128952
129026
|
};
|
|
@@ -129114,9 +129188,9 @@ async function runLocked(projectRoot, entry, action, deps, runId, now) {
|
|
|
129114
129188
|
try {
|
|
129115
129189
|
await ensureTriggerDataIgnored(projectRoot);
|
|
129116
129190
|
const dir = path268.join(triggerReportsDir(projectRoot), entry.name);
|
|
129117
|
-
await
|
|
129191
|
+
await mkdir61(dir, { recursive: true });
|
|
129118
129192
|
const file = path268.join(dir, `${runId}.md`);
|
|
129119
|
-
await
|
|
129193
|
+
await writeFile38(file, renderReport3({ entry, action, runId, at: now().toISOString(), outcome, why, cost, grantedCalls, denials, sandboxNote, summary, networkDecisions }), "utf8");
|
|
129120
129194
|
await pruneReports(dir, action.report.keep);
|
|
129121
129195
|
reportPath = path268.relative(projectRoot, file);
|
|
129122
129196
|
} catch (error) {
|
|
@@ -129663,18 +129737,18 @@ var init_types10 = __esm(() => {
|
|
|
129663
129737
|
|
|
129664
129738
|
// src/intake/store.ts
|
|
129665
129739
|
import { createHash as createHash70 } from "crypto";
|
|
129666
|
-
import { appendFile as appendFile14, mkdir as
|
|
129740
|
+
import { appendFile as appendFile14, mkdir as mkdir62, readFile as readFile128, writeFile as writeFile39 } from "fs/promises";
|
|
129667
129741
|
import path272 from "path";
|
|
129668
129742
|
async function ensureIntakeDataIgnored(root) {
|
|
129669
129743
|
const dir = intakeDataDir(root);
|
|
129670
|
-
await
|
|
129744
|
+
await mkdir62(dir, { recursive: true });
|
|
129671
129745
|
const file = path272.join(dir, ".gitignore");
|
|
129672
129746
|
try {
|
|
129673
129747
|
await readFile128(file, "utf8");
|
|
129674
129748
|
} catch (error) {
|
|
129675
129749
|
if (!isNotFound(error))
|
|
129676
129750
|
throw error;
|
|
129677
|
-
await
|
|
129751
|
+
await writeFile39(file, `# Work intake: the card registry, the ledger and the poll state. Never committed.
|
|
129678
129752
|
*
|
|
129679
129753
|
!.gitignore
|
|
129680
129754
|
`, "utf8");
|
|
@@ -130815,7 +130889,7 @@ var init_events = __esm(() => {
|
|
|
130815
130889
|
|
|
130816
130890
|
// src/intake/poll.ts
|
|
130817
130891
|
import { randomUUID as randomUUID36 } from "crypto";
|
|
130818
|
-
import { mkdir as
|
|
130892
|
+
import { mkdir as mkdir63, mkdtemp as mkdtemp6, rm as rm21, writeFile as writeFile40 } from "fs/promises";
|
|
130819
130893
|
import path275 from "path";
|
|
130820
130894
|
function intakePollDue(config, state, now) {
|
|
130821
130895
|
if (!config.enabled || state.paused || config.repos.length === 0)
|
|
@@ -130924,7 +130998,7 @@ async function pollLocked(root, config, deps, runId, now) {
|
|
|
130924
130998
|
try {
|
|
130925
130999
|
if (scratch !== undefined) {
|
|
130926
131000
|
const cwd = path275.join(scratch, "granted-cwd");
|
|
130927
|
-
await
|
|
131001
|
+
await mkdir63(cwd, { recursive: true, mode: 448 });
|
|
130928
131002
|
const gh = await verifyGh(root, env);
|
|
130929
131003
|
if (!gh.ok)
|
|
130930
131004
|
failures.push({ source: "gh", detail: `refusing to run: ${gh.reason}` });
|
|
@@ -131113,9 +131187,9 @@ async function writeReport2(root, r) {
|
|
|
131113
131187
|
try {
|
|
131114
131188
|
await ensureIntakeDataIgnored(root);
|
|
131115
131189
|
const dir = intakeReportsDir(root);
|
|
131116
|
-
await
|
|
131190
|
+
await mkdir63(dir, { recursive: true });
|
|
131117
131191
|
const file = path275.join(dir, `${r.runId}.md`);
|
|
131118
|
-
await
|
|
131192
|
+
await writeFile40(file, scrubGrantedOutput(lines.join(`
|
|
131119
131193
|
`), r.env), "utf8");
|
|
131120
131194
|
await pruneReports(dir, REPORTS_KEEP);
|
|
131121
131195
|
return path275.relative(root, file);
|
|
@@ -132412,7 +132486,7 @@ var init_decisions_surface = __esm(() => {
|
|
|
132412
132486
|
});
|
|
132413
132487
|
|
|
132414
132488
|
// src/scheduler/research-sync-job.ts
|
|
132415
|
-
import { mkdir as
|
|
132489
|
+
import { mkdir as mkdir64, readFile as readFile131, readdir as readdir44, rm as rm22, writeFile as writeFile41 } from "fs/promises";
|
|
132416
132490
|
import path276 from "path";
|
|
132417
132491
|
function researchSyncDataDir(projectRoot) {
|
|
132418
132492
|
return path276.join(projectRoot, ".metaproject", "data", "research-sync");
|
|
@@ -132451,14 +132525,14 @@ async function writeFired2(projectRoot, state) {
|
|
|
132451
132525
|
}
|
|
132452
132526
|
async function ensureIgnored(projectRoot) {
|
|
132453
132527
|
const dir = researchSyncDataDir(projectRoot);
|
|
132454
|
-
await
|
|
132528
|
+
await mkdir64(dir, { recursive: true });
|
|
132455
132529
|
const file = path276.join(dir, ".gitignore");
|
|
132456
132530
|
try {
|
|
132457
132531
|
await readFile131(file, "utf8");
|
|
132458
132532
|
} catch (error) {
|
|
132459
132533
|
if (!isNotFound(error))
|
|
132460
132534
|
throw error;
|
|
132461
|
-
await
|
|
132535
|
+
await writeFile41(file, `# Daily research sync: the entry and the day it last ran. Never staged.
|
|
132462
132536
|
*
|
|
132463
132537
|
!.gitignore
|
|
132464
132538
|
`, "utf8");
|
|
@@ -132490,7 +132564,7 @@ async function claimFiles(projectRoot) {
|
|
|
132490
132564
|
}
|
|
132491
132565
|
async function claimDay(projectRoot, day, at) {
|
|
132492
132566
|
try {
|
|
132493
|
-
await
|
|
132567
|
+
await writeFile41(researchSyncClaimPath(projectRoot, day), `${JSON.stringify({ pid: process.pid, claimedAt: at.toISOString() })}
|
|
132494
132568
|
`, { flag: "wx" });
|
|
132495
132569
|
} catch (error) {
|
|
132496
132570
|
if (error.code === "EEXIST")
|
|
@@ -132688,7 +132762,7 @@ var STATUS_TITLE = "# \u0422\u0435\u043A\u0443\u0449\u0435\u0435 \u0441\u043E\u0
|
|
|
132688
132762
|
|
|
132689
132763
|
// src/commands/research-sync.ts
|
|
132690
132764
|
import { execFile as execFile12 } from "child_process";
|
|
132691
|
-
import { mkdir as
|
|
132765
|
+
import { mkdir as mkdir65, mkdtemp as mkdtemp7, readFile as readFile132, rename as rename12, rm as rm23, writeFile as writeFile42 } from "fs/promises";
|
|
132692
132766
|
import { tmpdir as tmpdir12 } from "os";
|
|
132693
132767
|
import path277 from "path";
|
|
132694
132768
|
import { promisify as promisify9 } from "util";
|
|
@@ -132723,7 +132797,7 @@ async function runCounts(root) {
|
|
|
132723
132797
|
const gitDir = (await tool("git", ["rev-parse", "--absolute-git-dir"], { cwd: root }, "git rev-parse")).trim();
|
|
132724
132798
|
const archive = path277.join(work, "flows.tar");
|
|
132725
132799
|
const tree = path277.join(work, "tree");
|
|
132726
|
-
await
|
|
132800
|
+
await mkdir65(tree);
|
|
132727
132801
|
await tool("git", ["archive", "--format=tar", `--output=${archive}`, "HEAD", ".metaproject/flows"], { cwd: root }, "git archive");
|
|
132728
132802
|
await tool("tar", ["-xf", archive, "-C", tree], { cwd: work }, "tar extract");
|
|
132729
132803
|
const python = process.platform === "win32" ? "python" : "python3";
|
|
@@ -132755,7 +132829,7 @@ function withoutTime(counts) {
|
|
|
132755
132829
|
async function writeAtomic(file, content) {
|
|
132756
132830
|
const temp = `${file}.tmp-${process.pid}`;
|
|
132757
132831
|
try {
|
|
132758
|
-
await
|
|
132832
|
+
await writeFile42(temp, content, "utf8");
|
|
132759
132833
|
await rename12(temp, file);
|
|
132760
132834
|
} catch (error) {
|
|
132761
132835
|
await rm23(temp, { force: true });
|
|
@@ -132808,7 +132882,7 @@ async function recordFailure(root, runAt, reason) {
|
|
|
132808
132882
|
await writeIfChanged(file, text);
|
|
132809
132883
|
}
|
|
132810
132884
|
async function runResearchSync(input) {
|
|
132811
|
-
const deps = { now: () => new Date, runCounts, headHash, writeStaged: (file, content) =>
|
|
132885
|
+
const deps = { now: () => new Date, runCounts, headHash, writeStaged: (file, content) => writeFile42(file, content, "utf8"), renameStaged: rename12, ...input };
|
|
132812
132886
|
const { root } = deps;
|
|
132813
132887
|
const runAt = deps.now();
|
|
132814
132888
|
let computed;
|
|
@@ -132855,7 +132929,7 @@ async function runResearchSync(input) {
|
|
|
132855
132929
|
if (item.previous === null)
|
|
132856
132930
|
await rm23(item.file, { force: true });
|
|
132857
132931
|
else
|
|
132858
|
-
await
|
|
132932
|
+
await writeFile42(item.file, item.previous, "utf8");
|
|
132859
132933
|
} catch {}
|
|
132860
132934
|
}
|
|
132861
132935
|
changed.length = 0;
|
|
@@ -146613,7 +146687,7 @@ var init_jev_edit_guard_inspector = __esm(() => {
|
|
|
146613
146687
|
// src/review/jev-edit-guard-log.ts
|
|
146614
146688
|
import { appendFile as appendFile16, readFile as readFile154 } from "fs/promises";
|
|
146615
146689
|
import path296 from "path";
|
|
146616
|
-
import { mkdir as
|
|
146690
|
+
import { mkdir as mkdir66 } from "fs/promises";
|
|
146617
146691
|
function isEditGuardLogStatus(value) {
|
|
146618
146692
|
return typeof value === "string" && EDIT_GUARD_LOG_STATUSES.includes(value);
|
|
146619
146693
|
}
|
|
@@ -146667,7 +146741,7 @@ async function readEditGuardLogRecords(cwd) {
|
|
|
146667
146741
|
}
|
|
146668
146742
|
async function appendEditGuardLog(cwd, record) {
|
|
146669
146743
|
const file = path296.join(cwd, EDIT_GUARD_LOG_PATH);
|
|
146670
|
-
await
|
|
146744
|
+
await mkdir66(path296.dirname(file), { recursive: true });
|
|
146671
146745
|
await appendFile16(file, `${JSON.stringify(record)}
|
|
146672
146746
|
`, { mode: 384 });
|
|
146673
146747
|
}
|
|
@@ -155309,7 +155383,7 @@ var init_execution_plan_panel = __esm(() => {
|
|
|
155309
155383
|
});
|
|
155310
155384
|
|
|
155311
155385
|
// src/assets/pull.ts
|
|
155312
|
-
import { mkdir as
|
|
155386
|
+
import { mkdir as mkdir67, writeFile as writeFile43 } from "fs/promises";
|
|
155313
155387
|
import path301 from "path";
|
|
155314
155388
|
async function pullAsset(id, lock, options = {}) {
|
|
155315
155389
|
const entry = lock.assets[id];
|
|
@@ -155328,8 +155402,8 @@ async function pullAsset(id, lock, options = {}) {
|
|
|
155328
155402
|
}
|
|
155329
155403
|
const destDir = options.destDir ?? assetCacheDir();
|
|
155330
155404
|
const destPath = path301.join(destDir, id);
|
|
155331
|
-
await
|
|
155332
|
-
await
|
|
155405
|
+
await mkdir67(destDir, { recursive: true });
|
|
155406
|
+
await writeFile43(destPath, bytes);
|
|
155333
155407
|
return { path: destPath, sha256: actual, verified: true };
|
|
155334
155408
|
}
|
|
155335
155409
|
var defaultFetcher = async (url) => {
|
|
@@ -156269,7 +156343,7 @@ var init_diff = __esm(() => {
|
|
|
156269
156343
|
});
|
|
156270
156344
|
|
|
156271
156345
|
// src/sync/hooks.ts
|
|
156272
|
-
import { chmod as chmod11, mkdir as
|
|
156346
|
+
import { chmod as chmod11, mkdir as mkdir68, readFile as readFile157, writeFile as writeFile44 } from "fs/promises";
|
|
156273
156347
|
import path303 from "path";
|
|
156274
156348
|
function escapeRegExp8(value) {
|
|
156275
156349
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -156292,7 +156366,7 @@ async function writeManagedHook(projectRoot, hookName) {
|
|
|
156292
156366
|
if (!hooksRoot) {
|
|
156293
156367
|
return false;
|
|
156294
156368
|
}
|
|
156295
|
-
await
|
|
156369
|
+
await mkdir68(hooksRoot, { recursive: true });
|
|
156296
156370
|
const hookPath = path303.join(hooksRoot, hookName);
|
|
156297
156371
|
const start = `# keryx:${BLOCK_ID}:begin`;
|
|
156298
156372
|
const end = `# keryx:${BLOCK_ID}:end`;
|
|
@@ -156306,7 +156380,7 @@ ${end}`;
|
|
|
156306
156380
|
|
|
156307
156381
|
${block}
|
|
156308
156382
|
`;
|
|
156309
|
-
await
|
|
156383
|
+
await writeFile44(hookPath, next, "utf8");
|
|
156310
156384
|
await chmod11(hookPath, 493);
|
|
156311
156385
|
return true;
|
|
156312
156386
|
}
|
|
@@ -156326,7 +156400,7 @@ async function stripManagedHook(projectRoot, hookName) {
|
|
|
156326
156400
|
if (!pattern.test(existing)) {
|
|
156327
156401
|
return false;
|
|
156328
156402
|
}
|
|
156329
|
-
await
|
|
156403
|
+
await writeFile44(hookPath, `${existing.replace(pattern, `
|
|
156330
156404
|
`).trimEnd()}
|
|
156331
156405
|
`, "utf8");
|
|
156332
156406
|
return true;
|
|
@@ -157612,7 +157686,7 @@ var init_digest_summary = __esm(() => {
|
|
|
157612
157686
|
|
|
157613
157687
|
// src/scheduler/digest-run.ts
|
|
157614
157688
|
import { randomUUID as randomUUID41 } from "crypto";
|
|
157615
|
-
import { mkdir as
|
|
157689
|
+
import { mkdir as mkdir69, mkdtemp as mkdtemp10, rm as rm26, writeFile as writeFile45 } from "fs/promises";
|
|
157616
157690
|
import path305 from "path";
|
|
157617
157691
|
function scrubDigestReportLocator(locator, env) {
|
|
157618
157692
|
const scrubbed = scrubGrantedOutput(locator, env);
|
|
@@ -157684,7 +157758,7 @@ async function runLocked2(projectRoot, entry, action, deps, runId, now) {
|
|
|
157684
157758
|
}
|
|
157685
157759
|
const scratch = await mkdtemp10(path305.join(parent.dir, `${entry.name.replace(/[^A-Za-z0-9._-]/g, "-")}-`));
|
|
157686
157760
|
const grantedCwd = path305.join(scratch, "granted-cwd");
|
|
157687
|
-
await
|
|
157761
|
+
await mkdir69(grantedCwd, { recursive: true, mode: 448 });
|
|
157688
157762
|
const limits = startLimits({ maxSeconds: dispatch.maxSeconds, memoryLimitMb: digest.memoryLimitMb }, { ...deps.armTimeout !== undefined ? { armTimeout: deps.armTimeout } : {}, ...deps.limits ?? {} });
|
|
157689
157763
|
let crashed;
|
|
157690
157764
|
let collected = { items: [], failures: [], failedSources: new Set, truncatedSources: new Set, raw: [], calls: [], stopped: false };
|
|
@@ -157771,9 +157845,9 @@ async function runLocked2(projectRoot, entry, action, deps, runId, now) {
|
|
|
157771
157845
|
try {
|
|
157772
157846
|
await ensureTriggerDataIgnored(projectRoot);
|
|
157773
157847
|
const dir = path305.join(triggerReportsDir(projectRoot), entry.name);
|
|
157774
|
-
await
|
|
157848
|
+
await mkdir69(dir, { recursive: true });
|
|
157775
157849
|
const file = path305.join(dir, `${runId}.md`);
|
|
157776
|
-
await
|
|
157850
|
+
await writeFile45(file, renderDigestReport({
|
|
157777
157851
|
entry,
|
|
157778
157852
|
runId,
|
|
157779
157853
|
at: startedAt.toISOString(),
|
|
@@ -174232,7 +174306,7 @@ var init_sweep = __esm(() => {
|
|
|
174232
174306
|
});
|
|
174233
174307
|
|
|
174234
174308
|
// src/retention/auto-sweep.ts
|
|
174235
|
-
import { mkdir as
|
|
174309
|
+
import { mkdir as mkdir70, readFile as readFile167, rm as rm27, stat as stat35, writeFile as writeFile46 } from "fs/promises";
|
|
174236
174310
|
import { randomUUID as randomUUID43 } from "crypto";
|
|
174237
174311
|
import path322 from "path";
|
|
174238
174312
|
function autoSweepStampPath(cwd) {
|
|
@@ -174285,7 +174359,7 @@ async function acquireClaim(claimPath, staleMs) {
|
|
|
174285
174359
|
const nonce = `${process.pid}:${randomUUID43()}`;
|
|
174286
174360
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
174287
174361
|
try {
|
|
174288
|
-
await
|
|
174362
|
+
await writeFile46(claimPath, nonce, { flag: "wx", mode: 384 });
|
|
174289
174363
|
return {
|
|
174290
174364
|
release: async () => {
|
|
174291
174365
|
try {
|
|
@@ -174328,7 +174402,7 @@ async function maybeAutoSweepGdctx(cwd, options = {}) {
|
|
|
174328
174402
|
}
|
|
174329
174403
|
const stamp = autoSweepStampPath(cwd);
|
|
174330
174404
|
try {
|
|
174331
|
-
await
|
|
174405
|
+
await mkdir70(path322.dirname(stamp), { recursive: true });
|
|
174332
174406
|
} catch {
|
|
174333
174407
|
return { ran: false, reason: "stamp-unwritable" };
|
|
174334
174408
|
}
|
|
@@ -174341,7 +174415,7 @@ async function maybeAutoSweepGdctx(cwd, options = {}) {
|
|
|
174341
174415
|
return { ran: false, reason: "throttled" };
|
|
174342
174416
|
}
|
|
174343
174417
|
try {
|
|
174344
|
-
await
|
|
174418
|
+
await writeFile46(stamp, `${JSON.stringify({ startedAtMs: now, completedAtMs: null }, null, 2)}
|
|
174345
174419
|
`, "utf8");
|
|
174346
174420
|
} catch {
|
|
174347
174421
|
return { ran: false, reason: "stamp-unwritable" };
|
|
@@ -174351,7 +174425,7 @@ async function maybeAutoSweepGdctx(cwd, options = {}) {
|
|
|
174351
174425
|
now
|
|
174352
174426
|
});
|
|
174353
174427
|
const completedAtMs = options.now ?? Date.now();
|
|
174354
|
-
await
|
|
174428
|
+
await writeFile46(stamp, `${JSON.stringify({ startedAtMs: now, completedAtMs, lastRunAtMs: completedAtMs }, null, 2)}
|
|
174355
174429
|
`, "utf8").catch(() => {
|
|
174356
174430
|
return;
|
|
174357
174431
|
});
|
|
@@ -174371,7 +174445,7 @@ var init_auto_sweep = __esm(() => {
|
|
|
174371
174445
|
|
|
174372
174446
|
// src/ctx/artifact-id.ts
|
|
174373
174447
|
import { randomBytes as randomBytes14 } from "crypto";
|
|
174374
|
-
import { mkdir as
|
|
174448
|
+
import { mkdir as mkdir71, readFile as readFile168, rm as rm28, writeFile as writeFile47 } from "fs/promises";
|
|
174375
174449
|
import path323 from "path";
|
|
174376
174450
|
function pinnedClock() {
|
|
174377
174451
|
const pin = process.env.KERYX_CTX_CLOCK_PIN_MS;
|
|
@@ -174397,7 +174471,7 @@ function isAlreadyExists(error) {
|
|
|
174397
174471
|
}
|
|
174398
174472
|
async function claim(file) {
|
|
174399
174473
|
try {
|
|
174400
|
-
await
|
|
174474
|
+
await writeFile47(file, "", { encoding: "utf8", flag: "wx" });
|
|
174401
174475
|
return true;
|
|
174402
174476
|
} catch (error) {
|
|
174403
174477
|
if (isAlreadyExists(error)) {
|
|
@@ -174410,8 +174484,8 @@ async function reserveArtifact(options) {
|
|
|
174410
174484
|
const now = options.now ?? pinnedClock() ?? (() => new Date);
|
|
174411
174485
|
const token = options.token ?? defaultToken;
|
|
174412
174486
|
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
174413
|
-
await
|
|
174414
|
-
await
|
|
174487
|
+
await mkdir71(options.rawDir, { recursive: true });
|
|
174488
|
+
await mkdir71(options.artifactsDir, { recursive: true });
|
|
174415
174489
|
for (let attempt = 0;attempt < maxAttempts; attempt += 1) {
|
|
174416
174490
|
const id = artifactIdCandidate(options.kind, now(), token());
|
|
174417
174491
|
const rawPath = path323.join(options.rawDir, `${id}.log`);
|
|
@@ -174584,7 +174658,7 @@ var init_structured = __esm(() => {
|
|
|
174584
174658
|
});
|
|
174585
174659
|
|
|
174586
174660
|
// src/commands/ctx.ts
|
|
174587
|
-
import { readFile as readFile169, writeFile as
|
|
174661
|
+
import { readFile as readFile169, writeFile as writeFile48 } from "fs/promises";
|
|
174588
174662
|
import path324 from "path";
|
|
174589
174663
|
function structuredBudgetBytes(config) {
|
|
174590
174664
|
return (config.compactHeadLines + config.compactTailLines) * 40;
|
|
@@ -175023,8 +175097,8 @@ async function writeArtifact({
|
|
|
175023
175097
|
${JSON.stringify(artifact, null, 2)}
|
|
175024
175098
|
\`\`\`
|
|
175025
175099
|
`;
|
|
175026
|
-
await
|
|
175027
|
-
await
|
|
175100
|
+
await writeFile48(rawPath, raw, "utf8");
|
|
175101
|
+
await writeFile48(summaryPath, summaryWithMeta, "utf8");
|
|
175028
175102
|
await writeFileAtomic(latestRawPath, raw);
|
|
175029
175103
|
await writeFileAtomic(latestSummaryPath, summaryWithMeta);
|
|
175030
175104
|
await maybeAutoSweepGdctx(projectRoot).catch(() => {
|
|
@@ -175920,7 +175994,7 @@ function readLiteral(source, start, quote) {
|
|
|
175920
175994
|
}
|
|
175921
175995
|
|
|
175922
175996
|
// src/wiki/freshness/queue.ts
|
|
175923
|
-
import { readFile as readFile170, rename as rename13, stat as stat36, unlink as unlink3, writeFile as
|
|
175997
|
+
import { readFile as readFile170, rename as rename13, stat as stat36, unlink as unlink3, writeFile as writeFile49 } from "fs/promises";
|
|
175924
175998
|
import path325 from "path";
|
|
175925
175999
|
function queuePath(cwd) {
|
|
175926
176000
|
return path325.join(cwd, ".metaproject", "data", "wiki", QUEUE_FILE);
|
|
@@ -176504,7 +176578,7 @@ var init_report6 = __esm(() => {
|
|
|
176504
176578
|
});
|
|
176505
176579
|
|
|
176506
176580
|
// src/wiki/freshness/run.ts
|
|
176507
|
-
import { mkdir as
|
|
176581
|
+
import { mkdir as mkdir72, readFile as readFile172, writeFile as writeFile50 } from "fs/promises";
|
|
176508
176582
|
import path326 from "path";
|
|
176509
176583
|
function freshnessDir(cwd) {
|
|
176510
176584
|
return path326.join(cwd, ".metaproject", "data", "wiki", "freshness");
|
|
@@ -176550,10 +176624,10 @@ async function runFreshness(input) {
|
|
|
176550
176624
|
}
|
|
176551
176625
|
async function persist(cwd, report) {
|
|
176552
176626
|
const dir = freshnessDir(cwd);
|
|
176553
|
-
await
|
|
176554
|
-
await
|
|
176627
|
+
await mkdir72(dir, { recursive: true });
|
|
176628
|
+
await writeFile50(path326.join(dir, "latest.json"), `${JSON.stringify(report, null, 2)}
|
|
176555
176629
|
`, "utf8");
|
|
176556
|
-
await
|
|
176630
|
+
await writeFile50(path326.join(dir, "latest.md"), renderMarkdown2(report), "utf8");
|
|
176557
176631
|
}
|
|
176558
176632
|
async function collectChanges(cwd, git, fromRev) {
|
|
176559
176633
|
const status = await git(cwd, ["diff", "--name-status", "-M", fromRev, "HEAD"]);
|
|
@@ -180546,7 +180620,7 @@ var init_manifest4 = __esm(() => {
|
|
|
180546
180620
|
});
|
|
180547
180621
|
|
|
180548
180622
|
// src/gdskills/sync.ts
|
|
180549
|
-
import { copyFile as copyFile3, mkdir as
|
|
180623
|
+
import { copyFile as copyFile3, mkdir as mkdir73, readdir as readdir55, writeFile as writeFile51 } from "fs/promises";
|
|
180550
180624
|
import path340 from "path";
|
|
180551
180625
|
function isGlobalSyncRuntime(runtime) {
|
|
180552
180626
|
return Object.hasOwn(GLOBAL_SKILL_SYNC_TARGETS, runtime);
|
|
@@ -180617,12 +180691,12 @@ async function syncRuntimeSkillsToRoot(projectRoot, options) {
|
|
|
180617
180691
|
const manifestPath = path340.join(targetRoot, "keryx-sync-manifest.json");
|
|
180618
180692
|
const syncedSkills = skillDirs.map((skillDir) => path340.basename(skillDir)).sort();
|
|
180619
180693
|
if (!options.dryRun) {
|
|
180620
|
-
await
|
|
180694
|
+
await mkdir73(targetRoot, { recursive: true });
|
|
180621
180695
|
for (const skillDir of skillDirs) {
|
|
180622
180696
|
const targetSkillDir = path340.join(targetRoot, path340.basename(skillDir));
|
|
180623
180697
|
await copyDirectory(skillDir, targetSkillDir);
|
|
180624
180698
|
}
|
|
180625
|
-
await
|
|
180699
|
+
await writeFile51(manifestPath, `${JSON.stringify({
|
|
180626
180700
|
schemaVersion: 1,
|
|
180627
180701
|
runtime: options.runtime,
|
|
180628
180702
|
sourceRoot: toPosix(path340.relative(projectRoot, sourceRoot)),
|
|
@@ -180687,7 +180761,7 @@ async function plannedSyncFiles(projectRoot, skillDirs, sourceRoot, targetRoot)
|
|
|
180687
180761
|
async function copyDirectory(sourceDir, targetDir) {
|
|
180688
180762
|
for (const filePath of await listFiles3(sourceDir)) {
|
|
180689
180763
|
const targetPath = path340.join(targetDir, path340.relative(sourceDir, filePath));
|
|
180690
|
-
await
|
|
180764
|
+
await mkdir73(path340.dirname(targetPath), { recursive: true });
|
|
180691
180765
|
await copyFile3(filePath, targetPath);
|
|
180692
180766
|
}
|
|
180693
180767
|
}
|
|
@@ -182830,7 +182904,7 @@ var init_remove_skill = __esm(() => {
|
|
|
182830
182904
|
});
|
|
182831
182905
|
|
|
182832
182906
|
// src/gdskills/verify.ts
|
|
182833
|
-
import { mkdir as
|
|
182907
|
+
import { mkdir as mkdir74, readFile as readFile181, writeFile as writeFile52 } from "fs/promises";
|
|
182834
182908
|
import path345 from "path";
|
|
182835
182909
|
async function verifyProjectSkill(projectRoot, options) {
|
|
182836
182910
|
const metaprojectRoot = path345.join(projectRoot, ".metaproject");
|
|
@@ -182876,11 +182950,11 @@ async function verifyProjectSkill(projectRoot, options) {
|
|
|
182876
182950
|
dryRun: options.dryRun === true
|
|
182877
182951
|
};
|
|
182878
182952
|
if (!options.dryRun) {
|
|
182879
|
-
await
|
|
182880
|
-
await
|
|
182953
|
+
await mkdir74(path345.dirname(reportPath), { recursive: true });
|
|
182954
|
+
await writeFile52(reportPath, `${JSON.stringify(report, null, 2)}
|
|
182881
182955
|
`, "utf8");
|
|
182882
|
-
await
|
|
182883
|
-
await
|
|
182956
|
+
await writeFile52(path345.join(resolved.packageRoot, "verification.md"), renderVerificationMarkdown(report), "utf8");
|
|
182957
|
+
await writeFile52(skillMdPath, updateLastVerified(skillMd, verifiedAt), "utf8");
|
|
182884
182958
|
}
|
|
182885
182959
|
return report;
|
|
182886
182960
|
}
|
|
@@ -185586,7 +185660,7 @@ var init_plans = __esm(() => {
|
|
|
185586
185660
|
});
|
|
185587
185661
|
|
|
185588
185662
|
// src/job/store.ts
|
|
185589
|
-
import { appendFile as appendFile17, mkdir as
|
|
185663
|
+
import { appendFile as appendFile17, mkdir as mkdir75, readFile as readFile184, readdir as readdir61 } from "fs/promises";
|
|
185590
185664
|
import path348 from "path";
|
|
185591
185665
|
function jobsRoot(cwd) {
|
|
185592
185666
|
return path348.join(cwd, ".metaproject", "jobs");
|
|
@@ -185631,7 +185705,7 @@ async function writeJob(cwd, name, state) {
|
|
|
185631
185705
|
`));
|
|
185632
185706
|
}
|
|
185633
185707
|
const file = jobStatePath(cwd, name);
|
|
185634
|
-
await
|
|
185708
|
+
await mkdir75(path348.dirname(file), { recursive: true });
|
|
185635
185709
|
await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
|
|
185636
185710
|
`);
|
|
185637
185711
|
}
|
|
@@ -185670,7 +185744,7 @@ var init_store10 = __esm(() => {
|
|
|
185670
185744
|
});
|
|
185671
185745
|
|
|
185672
185746
|
// src/job/service.ts
|
|
185673
|
-
import { copyFile as copyFile4, mkdir as
|
|
185747
|
+
import { copyFile as copyFile4, mkdir as mkdir76 } from "fs/promises";
|
|
185674
185748
|
import path349 from "path";
|
|
185675
185749
|
function createJobService(deps) {
|
|
185676
185750
|
const now = () => deps.now().toISOString();
|
|
@@ -185713,7 +185787,7 @@ function createJobService(deps) {
|
|
|
185713
185787
|
if (await pathExists(absolute)) {
|
|
185714
185788
|
throw new Error(`Job package already exists: .metaproject/jobs/${name}. ` + `Run: keryx job status ${name}`);
|
|
185715
185789
|
}
|
|
185716
|
-
await
|
|
185790
|
+
await mkdir76(absolute, { recursive: true });
|
|
185717
185791
|
const createdAt = now();
|
|
185718
185792
|
const state = {
|
|
185719
185793
|
phase: "PLAN",
|
|
@@ -187383,7 +187457,7 @@ var init_retry_plan = __esm(() => {
|
|
|
187383
187457
|
|
|
187384
187458
|
// src/commands/review-slice.ts
|
|
187385
187459
|
import { existsSync as existsSync58, readFileSync as readFileSync28, statSync as statSync20 } from "fs";
|
|
187386
|
-
import { mkdir as
|
|
187460
|
+
import { mkdir as mkdir77, readFile as readFile188, readdir as readdir63, rm as rm29 } from "fs/promises";
|
|
187387
187461
|
import path351 from "path";
|
|
187388
187462
|
function wantsHelp2(args) {
|
|
187389
187463
|
return args.includes("--help") || args.includes("-h");
|
|
@@ -187441,7 +187515,7 @@ Attempts are remembered in ${RETRY_STATE_NAME} beside the manifest (--state to m
|
|
|
187441
187515
|
`);
|
|
187442
187516
|
}
|
|
187443
187517
|
async function writeSliceFiles(dir, slices) {
|
|
187444
|
-
await
|
|
187518
|
+
await mkdir77(dir, { recursive: true });
|
|
187445
187519
|
for (const slice of slices) {
|
|
187446
187520
|
await writeFileAtomic(path351.join(dir, slice.path), slice.text);
|
|
187447
187521
|
}
|
|
@@ -187460,7 +187534,7 @@ async function runSlice(args, deps) {
|
|
|
187460
187534
|
const outDir = path351.resolve(optionValue(args, "--out") ?? DEFAULT_SLICE_DIR);
|
|
187461
187535
|
const diff = diffFile !== undefined ? await deps.readDiffSource(diffFile) : await deps.gitDiff(ref, contextLines);
|
|
187462
187536
|
const { manifest, slices } = buildSlices(sliceSourceFromDiff(diff, { contextLines }), { maxBytes });
|
|
187463
|
-
await
|
|
187537
|
+
await mkdir77(outDir, { recursive: true });
|
|
187464
187538
|
for (const entry of await readdir63(outDir)) {
|
|
187465
187539
|
if (/^slice-\d+\.diff$/.test(entry)) {
|
|
187466
187540
|
await rm29(path351.join(outDir, entry), { force: true });
|
|
@@ -188935,7 +189009,7 @@ var init_floor = __esm(() => {
|
|
|
188935
189009
|
});
|
|
188936
189010
|
|
|
188937
189011
|
// src/commands/review.ts
|
|
188938
|
-
import { mkdir as
|
|
189012
|
+
import { mkdir as mkdir78, readdir as readdir64, readFile as readFile192 } from "fs/promises";
|
|
188939
189013
|
import path356, { join as join11 } from "path";
|
|
188940
189014
|
function reviewerList(args) {
|
|
188941
189015
|
return (optionValue(args, "--reviewers") ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
@@ -190245,7 +190319,7 @@ async function runLearn(args) {
|
|
|
190245
190319
|
const sourcePath = learningSourcePath(cwd, config.repo, number);
|
|
190246
190320
|
const recordPath = learningRecordPath(cwd, config.repo, number);
|
|
190247
190321
|
const relativeSourcePath = toPosix(path356.relative(cwd, sourcePath));
|
|
190248
|
-
await
|
|
190322
|
+
await mkdir78(path356.dirname(sourcePath), { recursive: true });
|
|
190249
190323
|
await writeFileAtomic(sourcePath, renderLearningSource(selection));
|
|
190250
190324
|
await writeFileAtomic(recordPath, renderLearningRecord({
|
|
190251
190325
|
repo: config.repo,
|
|
@@ -191876,7 +191950,7 @@ function classifyBaselineStatuses(baseline, pr) {
|
|
|
191876
191950
|
}
|
|
191877
191951
|
|
|
191878
191952
|
// src/commands/standard.ts
|
|
191879
|
-
import { mkdir as
|
|
191953
|
+
import { mkdir as mkdir79, writeFile as writeFile53 } from "fs/promises";
|
|
191880
191954
|
import path359 from "path";
|
|
191881
191955
|
async function standardCommand(args = [], projectRoot = process.cwd()) {
|
|
191882
191956
|
const subcommand = args[0];
|
|
@@ -191987,8 +192061,8 @@ async function handleEmit(projectRoot, args) {
|
|
|
191987
192061
|
if (args.includes("--stdout")) {
|
|
191988
192062
|
process.stdout.write(result.content);
|
|
191989
192063
|
} else {
|
|
191990
|
-
await
|
|
191991
|
-
await
|
|
192064
|
+
await mkdir79(path359.dirname(result.path), { recursive: true });
|
|
192065
|
+
await writeFile53(result.path, result.content, "utf8");
|
|
191992
192066
|
heading("keryx standard emit llms");
|
|
191993
192067
|
if (problems.length === 0) {
|
|
191994
192068
|
console.log(` ${style.green(symbols.ok)} wrote ${path359.relative(projectRoot, result.path)} (valid llms.txt)`);
|
|
@@ -194732,7 +194806,7 @@ var init_security_impact_evidence = __esm(() => {
|
|
|
194732
194806
|
});
|
|
194733
194807
|
|
|
194734
194808
|
// src/commands/security.ts
|
|
194735
|
-
import { mkdir as
|
|
194809
|
+
import { mkdir as mkdir80, readdir as readdir66, readFile as readFile195, writeFile as writeFile54 } from "fs/promises";
|
|
194736
194810
|
import path363 from "path";
|
|
194737
194811
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
194738
194812
|
async function securityCommand(args = [], cwd = process.cwd()) {
|
|
@@ -195015,8 +195089,8 @@ async function handleScanMcp(cwd, args) {
|
|
|
195015
195089
|
const { manifest } = extractManifestAndBaseline(read.value, {});
|
|
195016
195090
|
const baseline = { schemaVersion: 1, tools: buildMcpBaseline(manifest) };
|
|
195017
195091
|
const outPath = mcpBaselinePath(cwd);
|
|
195018
|
-
await
|
|
195019
|
-
await
|
|
195092
|
+
await mkdir80(path363.dirname(outPath), { recursive: true });
|
|
195093
|
+
await writeFile54(outPath, `${JSON.stringify(baseline, null, 2)}
|
|
195020
195094
|
`, "utf8");
|
|
195021
195095
|
if (asJson) {
|
|
195022
195096
|
console.log(JSON.stringify({ pinned: Object.keys(baseline.tools).length, path: outPath }, null, 2));
|
|
@@ -195138,7 +195212,7 @@ async function handleRedact(cwd, args) {
|
|
|
195138
195212
|
source
|
|
195139
195213
|
});
|
|
195140
195214
|
if (out) {
|
|
195141
|
-
await
|
|
195215
|
+
await writeFile54(out, redacted, "utf8");
|
|
195142
195216
|
heading("keryx security redact");
|
|
195143
195217
|
console.log(` ${style.green(symbols.ok)} redacted ${findings.length} span(s) \u2192 ${out}`);
|
|
195144
195218
|
} else {
|
|
@@ -196399,7 +196473,7 @@ var init_metaproject_tools2 = __esm(() => {
|
|
|
196399
196473
|
});
|
|
196400
196474
|
|
|
196401
196475
|
// src/mcp/tools.ts
|
|
196402
|
-
import { readFile as readFile196, realpath as realpath24, writeFile as
|
|
196476
|
+
import { readFile as readFile196, realpath as realpath24, writeFile as writeFile55 } from "fs/promises";
|
|
196403
196477
|
import path365 from "path";
|
|
196404
196478
|
import { randomUUID as randomUUID44 } from "crypto";
|
|
196405
196479
|
function sacWorkspaceService(cwd) {
|
|
@@ -196545,7 +196619,7 @@ function buildToolRegistry() {
|
|
|
196545
196619
|
const wrapUp = await wrapUpAuthority.issue({ actor, source: "session", sourceRef: sessionEvidenceRef(workspaceId, session.id) });
|
|
196546
196620
|
const proposal = await service.create({ request: undefined, requestCorrelationId, workspaceId, id: `proposal-${randomUUID44().replace(/-/g, "").slice(0, 16)}`, proposalRevision, kind, wrapUp });
|
|
196547
196621
|
if (note)
|
|
196548
|
-
await
|
|
196622
|
+
await writeFile55(proposalNotePath(cwd, workspaceId, proposal.id), note, "utf8");
|
|
196549
196623
|
return normalizeProposalLifecycleResult(proposal);
|
|
196550
196624
|
}
|
|
196551
196625
|
},
|
|
@@ -213287,7 +213361,7 @@ var PROBE_TIMEOUT_MS = 1e4;
|
|
|
213287
213361
|
|
|
213288
213362
|
// src/commands/agents-external.ts
|
|
213289
213363
|
import { randomUUID as randomUUID56 } from "crypto";
|
|
213290
|
-
import { mkdir as
|
|
213364
|
+
import { mkdir as mkdir81 } from "fs/promises";
|
|
213291
213365
|
import { tmpdir as tmpdir16 } from "os";
|
|
213292
213366
|
import path386 from "path";
|
|
213293
213367
|
import { createInterface as createInterface4 } from "readline";
|
|
@@ -213560,7 +213634,7 @@ async function runCommand4(args, deps, log) {
|
|
|
213560
213634
|
const worktreesDir = path386.join(tmpdir16(), "keryx-external-worktrees");
|
|
213561
213635
|
const worktree = seams.worktree ?? createGitWorktreePort({ repoRoot: cwd, worktreesDir });
|
|
213562
213636
|
if (seams.worktree === undefined)
|
|
213563
|
-
await
|
|
213637
|
+
await mkdir81(worktreesDir, { recursive: true });
|
|
213564
213638
|
const detect = seams.detect === null ? undefined : seams.detect ?? createVersionProbe();
|
|
213565
213639
|
const runInput = {
|
|
213566
213640
|
runtime: {
|
|
@@ -215535,7 +215609,7 @@ function factPreservation(rawFacts, compactFacts) {
|
|
|
215535
215609
|
}
|
|
215536
215610
|
|
|
215537
215611
|
// src/metrics/oracle-runner.ts
|
|
215538
|
-
import { mkdir as
|
|
215612
|
+
import { mkdir as mkdir82, writeFile as writeFile56 } from "fs/promises";
|
|
215539
215613
|
import path388 from "path";
|
|
215540
215614
|
function oracleTaskId(target) {
|
|
215541
215615
|
return `metastore:gdgraph-affected:${target}`;
|
|
@@ -215858,8 +215932,8 @@ async function persistEvidenceBundle(outDir, bundle, ladder = "metastore") {
|
|
|
215858
215932
|
const safeTarget = bundle.target.replace(/[^A-Za-z0-9._/-]/g, "_");
|
|
215859
215933
|
const safeCase = bundle.caseId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
215860
215934
|
const dir = path388.join(outDir, "bench", ladder, safeTarget, safeCase, bundle.variant, String(bundle.seed));
|
|
215861
|
-
await
|
|
215862
|
-
const write = (name, value) =>
|
|
215935
|
+
await mkdir82(dir, { recursive: true });
|
|
215936
|
+
const write = (name, value) => writeFile56(path388.join(dir, name), `${JSON.stringify(value, null, 2)}
|
|
215863
215937
|
`, "utf8");
|
|
215864
215938
|
await Promise.all([
|
|
215865
215939
|
write("inputs.json", bundle.inputs),
|
|
@@ -216583,7 +216657,7 @@ function formatFwkExplain(result) {
|
|
|
216583
216657
|
|
|
216584
216658
|
// src/commands/workspace.ts
|
|
216585
216659
|
import { randomUUID as randomUUID57 } from "crypto";
|
|
216586
|
-
import { writeFile as
|
|
216660
|
+
import { writeFile as writeFile57 } from "fs/promises";
|
|
216587
216661
|
function service8() {
|
|
216588
216662
|
return new WorkspaceService({
|
|
216589
216663
|
workspaceRoot: process.cwd(),
|
|
@@ -216724,7 +216798,7 @@ async function workspaceCommand(args) {
|
|
|
216724
216798
|
const wrapUp = await wrapUpAuthority.issue({ actor, source: "session", sourceRef: sessionEvidenceRef(workspaceId, session.id) });
|
|
216725
216799
|
const proposal = await service.create({ request: undefined, requestCorrelationId, workspaceId, id: proposalId, proposalRevision, kind, wrapUp });
|
|
216726
216800
|
if (persistedNote)
|
|
216727
|
-
await
|
|
216801
|
+
await writeFile57(notePath, persistedNote, "utf8");
|
|
216728
216802
|
console.log(JSON.stringify(normalizeProposalLifecycleResult(proposal), null, 2));
|
|
216729
216803
|
return;
|
|
216730
216804
|
}
|
|
@@ -221044,7 +221118,7 @@ var init_learned_pattern_schema = __esm(() => {
|
|
|
221044
221118
|
|
|
221045
221119
|
// src/bundle/export.ts
|
|
221046
221120
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
221047
|
-
import { mkdir as
|
|
221121
|
+
import { mkdir as mkdir83, readdir as readdir71, readFile as readFile205, writeFile as writeFile58, lstat as lstat24 } from "fs/promises";
|
|
221048
221122
|
import { existsSync as existsSync62 } from "fs";
|
|
221049
221123
|
import path395 from "path";
|
|
221050
221124
|
function globToRegExp5(glob) {
|
|
@@ -221279,12 +221353,12 @@ async function outDirIsEmpty(out) {
|
|
|
221279
221353
|
}
|
|
221280
221354
|
}
|
|
221281
221355
|
async function writeDirectoryBundle(out, manifestBytes, files) {
|
|
221282
|
-
await
|
|
221283
|
-
await
|
|
221356
|
+
await mkdir83(out, { recursive: true });
|
|
221357
|
+
await writeFile58(path395.join(out, "bundle.json"), manifestBytes);
|
|
221284
221358
|
for (const [rel, bytes] of files) {
|
|
221285
221359
|
const abs = path395.join(out, ...rel.split("/"));
|
|
221286
|
-
await
|
|
221287
|
-
await
|
|
221360
|
+
await mkdir83(path395.dirname(abs), { recursive: true });
|
|
221361
|
+
await writeFile58(abs, bytes);
|
|
221288
221362
|
}
|
|
221289
221363
|
}
|
|
221290
221364
|
async function exportBundle(opts) {
|
|
@@ -221417,8 +221491,8 @@ async function exportBundle(opts) {
|
|
|
221417
221491
|
const archive = buildBundleArchive(files, manifestBytes);
|
|
221418
221492
|
if (!archive.ok)
|
|
221419
221493
|
return { ok: false, refusals: [archive.refusal] };
|
|
221420
|
-
await
|
|
221421
|
-
await
|
|
221494
|
+
await mkdir83(path395.dirname(opts.out), { recursive: true });
|
|
221495
|
+
await writeFile58(opts.out, archive.value);
|
|
221422
221496
|
} else {
|
|
221423
221497
|
if (existsSync62(opts.out) && !await outDirIsEmpty(opts.out)) {
|
|
221424
221498
|
return { ok: false, refusals: [{ reason: BUNDLE_REFUSAL.notABundle, message: `${opts.out} already exists and is not empty` }] };
|
|
@@ -221601,7 +221675,7 @@ var init_applied_state = __esm(() => {
|
|
|
221601
221675
|
});
|
|
221602
221676
|
|
|
221603
221677
|
// src/lib/private-dir.ts
|
|
221604
|
-
import { lstat as lstat25, mkdir as
|
|
221678
|
+
import { lstat as lstat25, mkdir as mkdir84, open as open11, readFile as readFile207 } from "fs/promises";
|
|
221605
221679
|
import path397 from "path";
|
|
221606
221680
|
async function checkPrivateDirGitignore(dir, root) {
|
|
221607
221681
|
if (root !== undefined) {
|
|
@@ -221691,7 +221765,7 @@ async function ensurePrivateDirGitignore(dir, root) {
|
|
|
221691
221765
|
return check;
|
|
221692
221766
|
}
|
|
221693
221767
|
const gitignorePath = path397.join(dir, ".gitignore");
|
|
221694
|
-
await
|
|
221768
|
+
await mkdir84(dir, { recursive: true });
|
|
221695
221769
|
try {
|
|
221696
221770
|
const handle = await open11(gitignorePath, "wx");
|
|
221697
221771
|
try {
|
|
@@ -222106,7 +222180,7 @@ var init_plan2 = __esm(() => {
|
|
|
222106
222180
|
});
|
|
222107
222181
|
|
|
222108
222182
|
// src/bundle/audit.ts
|
|
222109
|
-
import { mkdtemp as mkdtemp11, mkdir as
|
|
222183
|
+
import { mkdtemp as mkdtemp11, mkdir as mkdir85, rm as rm30, writeFile as writeFile59 } from "fs/promises";
|
|
222110
222184
|
import { tmpdir as tmpdir17 } from "os";
|
|
222111
222185
|
import path398 from "path";
|
|
222112
222186
|
function entriesToStage(plan) {
|
|
@@ -222123,8 +222197,8 @@ async function auditBundlePlan(plan, opts = {}) {
|
|
|
222123
222197
|
try {
|
|
222124
222198
|
for (const entry of toStage) {
|
|
222125
222199
|
const abs = path398.join(stagingDir, ...entry.path.split("/"));
|
|
222126
|
-
await
|
|
222127
|
-
await
|
|
222200
|
+
await mkdir85(path398.dirname(abs), { recursive: true });
|
|
222201
|
+
await writeFile59(abs, entry.bytes);
|
|
222128
222202
|
}
|
|
222129
222203
|
} catch (err) {
|
|
222130
222204
|
return {
|
|
@@ -222157,7 +222231,7 @@ var init_audit = __esm(() => {
|
|
|
222157
222231
|
});
|
|
222158
222232
|
|
|
222159
222233
|
// src/bundle/apply.ts
|
|
222160
|
-
import { mkdir as
|
|
222234
|
+
import { mkdir as mkdir86, rmdir as rmdir2, stat as stat42 } from "fs/promises";
|
|
222161
222235
|
import path399 from "path";
|
|
222162
222236
|
function writableEntries(plan) {
|
|
222163
222237
|
return plan.entries.filter((e) => e.bucket === "new" || e.bucket === "update" || e.bucket === "conflict" && e.forced);
|
|
@@ -222326,7 +222400,7 @@ async function mkdirRecordingCreated(dir) {
|
|
|
222326
222400
|
}
|
|
222327
222401
|
}
|
|
222328
222402
|
if (missing.length > 0) {
|
|
222329
|
-
await
|
|
222403
|
+
await mkdir86(dir, { recursive: true });
|
|
222330
222404
|
}
|
|
222331
222405
|
return missing;
|
|
222332
222406
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.91",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -85,7 +85,7 @@ A reviewer on this host cannot open a path: its file tool reads inside its worki
|
|
|
85
85
|
1. **Slice first.** `keryx review slice --ref <base> --out <dir>` after `keryx review scope`. It writes `slice-NN.diff` files of at most 150000 bytes each and a `manifest.json`; ledgers (csv, lockfiles, snapshots, generated files) are listed under `omissions` with a reason — list them in the report as not reviewed, never as clean.
|
|
86
86
|
2. **Slices travel by `context_files`.** Write the slices under the project (the default `--out`, `.metaproject/data/review/slices`, already is) and pass each reviewer its slice paths in `spawn_subagent`'s `context_files`: the host copies the text into that reviewer's task, so you never paste or retype a slice. Put the `slices` ids in its reviewer-input. A dispatch that names a git range but no slice and no `context_files` leaves the reviewer with nothing to read — that is `BLOCKED`, not a review.
|
|
87
87
|
3. **Check before dispatch.** `keryx review dispatch-check --payload <file> --manifest <dir>/manifest.json` for the wave; exit 1 means a payload names no slice, is over the ceiling, or breaks `reviewer-input.schema.json`. Fix it; do not dispatch around it.
|
|
88
|
-
4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. Give each reviewer `max_rounds` of at least 40 (the default); a reviewer that spends its rounds reading the skill and the schema returns nothing. **Incomplete means retry once, then Not run.** On `INCOMPLETE` or `BLOCKED`, `keryx review retry-plan --manifest <dir>/manifest.json --result <result.json>` decides: it cuts the assigned slices in half and names the one retry, and after that prints the `- **Not run:** …` line to paste into the report. An unfinished reviewer is never counted as a clean pass.
|
|
88
|
+
4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. Give each reviewer `max_rounds` of at least 40 (the default); a reviewer that spends its rounds reading the skill and the schema returns nothing. **Incomplete means retry once, then Not run.** On `INCOMPLETE` or `BLOCKED`, `keryx review retry-plan --manifest <dir>/manifest.json --result <result.json>` decides: it cuts the assigned slices in half and names the one retry, and after that prints the `- **Not run:** …` line to paste into the report. An unfinished reviewer is never counted as a clean pass. **Persist every result.** Pass each reviewer `save_result_to: .metaproject/data/review/raw/<reviewer>.txt`: the host writes its full final text there, so `review complete` has raw evidence even after the transcript is cut. Build `research.json` from those files — the ledger fields from the detail file plus one more key, `dispatch: {version:1, selected:[names], unresolvedRules:[], runs:[{reviewer, executionId:<its sub:… id>, status:"complete", scopeComplete:true, rawEvidence:<saved path>, ruleEvidence:[<rule paths>], executionRequired:false, executionReason:<why>}]}` — and ingest once with `--research`, into the package `review start` created. A refused `review complete` names what is missing: fix that with a command and run it again; it is never `blocked`. `--head` wants a SHA (`git rev-parse HEAD`), not `HEAD`.
|
|
89
89
|
5. **Never print a scope or a slice.** The tool output of one call is cut at about 20 KB and `keryx review scope` of a large PR prints hundreds of KB. Run it as `keryx review scope --ref <base> --json > .metaproject/data/review/scope.json` and read the counts from the file (`keryx ctx read`, or `jq`); take `<base>` from `git symbolic-ref refs/remotes/origin/HEAD`, not a guessed `origin/main`. Create `.metaproject/data/review/` first (`mkdir -p`) — a missing directory is a command to run, not a blocker. **Machine artifacts by direct write.** Save slices, payloads and results by redirection or `keryx ctx run --raw -- <command>`; the summarized form of `keryx ctx run` drops the bytes a later step parses.
|
|
90
90
|
|
|
91
91
|
## Control
|