@mrciphersmith/keryx 0.2.74 → 0.2.75
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 +84 -11
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16448,7 +16448,13 @@ function writeJsonl(file, history, ts) {
|
|
|
16448
16448
|
function redactHistory(history) {
|
|
16449
16449
|
return history.map((message) => ({
|
|
16450
16450
|
...message,
|
|
16451
|
-
content: redactSensitiveText(message.content)
|
|
16451
|
+
content: redactSensitiveText(message.content),
|
|
16452
|
+
...message.toolCalls === undefined ? {} : {
|
|
16453
|
+
toolCalls: message.toolCalls.map((call) => ({
|
|
16454
|
+
...call,
|
|
16455
|
+
arguments: redactSensitiveText(call.arguments)
|
|
16456
|
+
}))
|
|
16457
|
+
}
|
|
16452
16458
|
}));
|
|
16453
16459
|
}
|
|
16454
16460
|
function readJsonl2(file) {
|
|
@@ -17613,6 +17619,9 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
17613
17619
|
if (!await pathExists(metaprojectRoot)) {
|
|
17614
17620
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
17615
17621
|
}
|
|
17622
|
+
if (!isRoutableSkillTarget(options.target)) {
|
|
17623
|
+
throw new Error(`keryx skills create: target ${JSON.stringify(options.target)} reads as prose, not a routing key. ` + 'A target is what `keryx skills route` matches against \u2014 a concept ("auth flow"), a symbol (`IResultDqReport`), ' + "or a path (`src/dq/DqScoreCard.tsx`). A sentence matches nothing and verifies as permanently stale.");
|
|
17624
|
+
}
|
|
17616
17625
|
const moduleName = slugify3(options.module ?? inferModule(options.target));
|
|
17617
17626
|
const skillName = slugify3(options.name ?? inferSkillName(options.target));
|
|
17618
17627
|
const format = options.format ?? "auto";
|
|
@@ -18605,6 +18614,23 @@ function authorityFor(manifest, subject) {
|
|
|
18605
18614
|
function normalizeProposalLifecycleResult(value) {
|
|
18606
18615
|
return JSON.parse(JSON.stringify(value));
|
|
18607
18616
|
}
|
|
18617
|
+
async function readProposalSecurityGate(cwd, workspaceId, proposalId) {
|
|
18618
|
+
const file = path86.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
|
|
18619
|
+
let parsed;
|
|
18620
|
+
try {
|
|
18621
|
+
parsed = JSON.parse(await readFile44(file, "utf8"));
|
|
18622
|
+
} catch {
|
|
18623
|
+
return;
|
|
18624
|
+
}
|
|
18625
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
18626
|
+
return;
|
|
18627
|
+
const record = parsed;
|
|
18628
|
+
const gate = record.security?.gate;
|
|
18629
|
+
if (gate !== "pass" && gate !== "needs-approval")
|
|
18630
|
+
return;
|
|
18631
|
+
const evidenceRefs = Array.isArray(record.evidence) ? record.evidence.map((entry) => typeof entry === "object" && entry !== null ? entry.uri : undefined).filter((uri) => typeof uri === "string") : [];
|
|
18632
|
+
return { gate, evidenceRefs };
|
|
18633
|
+
}
|
|
18608
18634
|
var ProposalLifecycleError;
|
|
18609
18635
|
var init_proposal_lifecycle = __esm(() => {
|
|
18610
18636
|
init_fs();
|
|
@@ -18788,13 +18814,16 @@ async function digestLedgerPrefix(handle, byteLength) {
|
|
|
18788
18814
|
return digest2;
|
|
18789
18815
|
const buffer = Buffer.alloc(Math.min(ledgerDigestChunkBytes, byteLength));
|
|
18790
18816
|
let position = 0;
|
|
18791
|
-
|
|
18817
|
+
const maxChunks = Math.ceil(byteLength / buffer.length);
|
|
18818
|
+
for (let chunk = 0;chunk < maxChunks && position < byteLength; chunk += 1) {
|
|
18792
18819
|
const result = await handle.read(buffer, 0, Math.min(buffer.length, byteLength - position), position);
|
|
18793
18820
|
if (result.bytesRead === 0)
|
|
18794
18821
|
return;
|
|
18795
18822
|
digest2.update(buffer.subarray(0, result.bytesRead));
|
|
18796
18823
|
position += result.bytesRead;
|
|
18797
18824
|
}
|
|
18825
|
+
if (position < byteLength)
|
|
18826
|
+
return;
|
|
18798
18827
|
return digest2;
|
|
18799
18828
|
}
|
|
18800
18829
|
function parseCheckpoint(value) {
|
|
@@ -33530,6 +33559,28 @@ async function validateValue(value, schema, valuePath, errors, rootSchema, schem
|
|
|
33530
33559
|
message: `Expected array length >= ${schema.minItems}`
|
|
33531
33560
|
});
|
|
33532
33561
|
}
|
|
33562
|
+
if (Array.isArray(value) && schema.maxItems !== undefined && value.length > schema.maxItems) {
|
|
33563
|
+
errors.push({
|
|
33564
|
+
path: valuePath,
|
|
33565
|
+
message: `Expected array length <= ${schema.maxItems}`
|
|
33566
|
+
});
|
|
33567
|
+
}
|
|
33568
|
+
if (typeof value === "number" && schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum) {
|
|
33569
|
+
errors.push({
|
|
33570
|
+
path: valuePath,
|
|
33571
|
+
message: `Expected number > ${schema.exclusiveMinimum}`
|
|
33572
|
+
});
|
|
33573
|
+
}
|
|
33574
|
+
if (schema.not !== undefined) {
|
|
33575
|
+
const negated = [];
|
|
33576
|
+
await validateValue(value, schema.not, valuePath, negated, rootSchema, schemaCache);
|
|
33577
|
+
if (negated.length === 0) {
|
|
33578
|
+
errors.push({
|
|
33579
|
+
path: valuePath,
|
|
33580
|
+
message: "Expected value NOT to match the prohibited subschema"
|
|
33581
|
+
});
|
|
33582
|
+
}
|
|
33583
|
+
}
|
|
33533
33584
|
if (typeof value === "string") {
|
|
33534
33585
|
if (schema.minLength !== undefined && value.length < schema.minLength) {
|
|
33535
33586
|
errors.push({
|
|
@@ -40350,7 +40401,7 @@ ${renderUntrackedFiles(untracked, config)}
|
|
|
40350
40401
|
` : ""}
|
|
40351
40402
|
## Risk Hints
|
|
40352
40403
|
|
|
40353
|
-
${renderRiskHints(risky, shape)}
|
|
40404
|
+
${renderRiskHints(risky, shape, shape.files)}
|
|
40354
40405
|
|
|
40355
40406
|
## Hunks
|
|
40356
40407
|
|
|
@@ -40723,13 +40774,19 @@ function renderDiffCounts(file) {
|
|
|
40723
40774
|
}
|
|
40724
40775
|
return file.changed !== undefined ? `: ~${file.changed} changed` : "";
|
|
40725
40776
|
}
|
|
40726
|
-
function renderRiskHints(risky, shape) {
|
|
40777
|
+
function renderRiskHints(risky, shape, files) {
|
|
40727
40778
|
const hints = risky.map((file) => `- ${file.path}`);
|
|
40728
40779
|
if (shape.pathsAbbreviated) {
|
|
40729
40780
|
hints.push("- (paths are abbreviated by `--stat`; risk matching is unreliable \u2014 re-run with `--numstat` or `--name-only` to check)");
|
|
40730
40781
|
}
|
|
40731
40782
|
if (hints.length === 0) {
|
|
40732
|
-
|
|
40783
|
+
if (shape.mode === "unenumerable") {
|
|
40784
|
+
return "- unknown: no file list in this output shape";
|
|
40785
|
+
}
|
|
40786
|
+
if (files.length === 0 && (shape.reportedFileCount ?? 0) > 0) {
|
|
40787
|
+
return `- unknown: ${shape.reportedFileCount} file(s) changed but this output shape lists no per-file rows \u2014 nothing was checked. Re-run with \`--numstat\` or \`--name-only\`.`;
|
|
40788
|
+
}
|
|
40789
|
+
return "- none";
|
|
40733
40790
|
}
|
|
40734
40791
|
return hints.join(`
|
|
40735
40792
|
`);
|
|
@@ -49574,8 +49631,11 @@ init_project_skills();
|
|
|
49574
49631
|
import { readFile as readFile72, readdir as readdir24 } from "fs/promises";
|
|
49575
49632
|
import path135 from "path";
|
|
49576
49633
|
var PROJECT_REVIEWER_MODULE = "review";
|
|
49634
|
+
function escapeRegexLiteral(literal) {
|
|
49635
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
49636
|
+
}
|
|
49577
49637
|
function metadataLine(content, label) {
|
|
49578
|
-
const match = content.match(new RegExp(`^${label
|
|
49638
|
+
const match = content.match(new RegExp(`^${escapeRegexLiteral(label)}:\\s*(.+)$`, "m"));
|
|
49579
49639
|
return match?.[1]?.trim();
|
|
49580
49640
|
}
|
|
49581
49641
|
async function skillDirs(root) {
|
|
@@ -63322,7 +63382,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
63322
63382
|
// package.json
|
|
63323
63383
|
var package_default = {
|
|
63324
63384
|
name: "@mrciphersmith/keryx",
|
|
63325
|
-
version: "0.2.
|
|
63385
|
+
version: "0.2.75",
|
|
63326
63386
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
63327
63387
|
private: false,
|
|
63328
63388
|
publishConfig: {
|
|
@@ -82895,13 +82955,26 @@ async function workspaceCommand(args2) {
|
|
|
82895
82955
|
return;
|
|
82896
82956
|
}
|
|
82897
82957
|
if (subcommand === "confirm-review") {
|
|
82898
|
-
rejectUnknownOptions(args2.slice(3), new Set);
|
|
82958
|
+
rejectUnknownOptions(args2.slice(3), new Set(["--acknowledge-security"]));
|
|
82899
82959
|
const workspaceId = args2[1];
|
|
82900
82960
|
const proposalId = args2[2];
|
|
82901
82961
|
if (!workspaceId || !proposalId)
|
|
82902
|
-
throw new Error("Usage: keryx workspace confirm-review <workspace-id> <proposal-id>");
|
|
82903
|
-
const
|
|
82904
|
-
|
|
82962
|
+
throw new Error("Usage: keryx workspace confirm-review <workspace-id> <proposal-id> [--acknowledge-security]");
|
|
82963
|
+
const security = await readProposalSecurityGate(process.cwd(), workspaceId, proposalId);
|
|
82964
|
+
if (!security)
|
|
82965
|
+
throw new Error(`keryx workspace confirm-review: cannot read proposal ${proposalId} in workspace ${workspaceId} \u2014 refusing to mint a token for a proposal whose security gate is unknown`);
|
|
82966
|
+
const acknowledgeSecurity = booleanFlag(args2, "--acknowledge-security");
|
|
82967
|
+
if (security.gate === "needs-approval" && !acknowledgeSecurity) {
|
|
82968
|
+
throw new Error([
|
|
82969
|
+
`keryx workspace confirm-review: proposal ${proposalId} is gated \`needs-approval\` \u2014 its evidence tripped the security scan.`,
|
|
82970
|
+
...security.evidenceRefs.length > 0 ? [`Evidence: ${security.evidenceRefs.join(", ")}`] : [],
|
|
82971
|
+
"Read the evidence, then re-run with --acknowledge-security to state that you have.",
|
|
82972
|
+
"Accepting without reading it is the thing this gate exists to prevent."
|
|
82973
|
+
].join(`
|
|
82974
|
+
`));
|
|
82975
|
+
}
|
|
82976
|
+
const { token, expiresAt } = await mintConfirmToken(process.cwd(), workspaceId, proposalId, { securityAcknowledged: security.gate === "needs-approval" && acknowledgeSecurity });
|
|
82977
|
+
console.log(JSON.stringify({ token, expiresAt, securityGate: security.gate, securityAcknowledged: security.gate === "needs-approval" && acknowledgeSecurity }, null, 2));
|
|
82905
82978
|
return;
|
|
82906
82979
|
}
|
|
82907
82980
|
if (subcommand === "review") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.75",
|
|
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": {
|