@mrciphersmith/keryx 0.3.68 → 0.3.73
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/README.md +24 -8
- package/dist/cli.js +7418 -3090
- package/dist/core.js +72 -14
- package/package.json +1 -1
- package/src/gdgraph/service.ts +5 -0
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +11 -13
package/dist/core.js
CHANGED
|
@@ -6592,6 +6592,40 @@ var init_read_source = __esm(() => {
|
|
|
6592
6592
|
init_contained_path();
|
|
6593
6593
|
});
|
|
6594
6594
|
|
|
6595
|
+
// src/security/secret-shape.ts
|
|
6596
|
+
function isIdentifier(run) {
|
|
6597
|
+
const parts = run.match(RUN_PARTS) ?? [];
|
|
6598
|
+
if (parts.join("") !== run)
|
|
6599
|
+
return false;
|
|
6600
|
+
if (parts.filter((part) => /\d/.test(part)).length > 2)
|
|
6601
|
+
return false;
|
|
6602
|
+
return parts.every((part, index) => {
|
|
6603
|
+
if (/\d/.test(part))
|
|
6604
|
+
return part.length <= 3;
|
|
6605
|
+
if (/[-_]/.test(part))
|
|
6606
|
+
return true;
|
|
6607
|
+
return part.length >= 3 || /\d/.test(parts[index + 1] ?? "");
|
|
6608
|
+
});
|
|
6609
|
+
}
|
|
6610
|
+
function isSecretRun(run) {
|
|
6611
|
+
return /[a-z]/.test(run) && /[A-Z]/.test(run) && /\d/.test(run) && !isIdentifier(run);
|
|
6612
|
+
}
|
|
6613
|
+
function looksLikeSecret(text) {
|
|
6614
|
+
if (BOT_TOKEN_SHAPE.test(text))
|
|
6615
|
+
return true;
|
|
6616
|
+
for (const run of text.match(TOKEN_RUN) ?? []) {
|
|
6617
|
+
if (isSecretRun(run))
|
|
6618
|
+
return true;
|
|
6619
|
+
}
|
|
6620
|
+
return false;
|
|
6621
|
+
}
|
|
6622
|
+
var BOT_TOKEN_SHAPE, TOKEN_RUN, RUN_PARTS;
|
|
6623
|
+
var init_secret_shape = __esm(() => {
|
|
6624
|
+
BOT_TOKEN_SHAPE = /\d{6,}:[A-Za-z0-9_-]{30,}/;
|
|
6625
|
+
TOKEN_RUN = /[A-Za-z0-9_-]{32,}|[A-Za-z0-9+/]{40,}={0,2}/g;
|
|
6626
|
+
RUN_PARTS = /[A-Z][a-z]+|[a-z]+|[A-Z]+(?![a-z])|\d+|[-_]/g;
|
|
6627
|
+
});
|
|
6628
|
+
|
|
6595
6629
|
// src/security/credential-shape.ts
|
|
6596
6630
|
function isDeniedForMcpChild(name, value) {
|
|
6597
6631
|
if (value !== undefined && CREDENTIAL_IN_VALUE_RE.test(value))
|
|
@@ -9817,7 +9851,7 @@ var init_skill_length_ceilings = __esm(() => {
|
|
|
9817
9851
|
"planning/docpack-orchestrator": 172,
|
|
9818
9852
|
"planning/docpack-review": 92,
|
|
9819
9853
|
"planning/interview": 209,
|
|
9820
|
-
"planning/interviewer":
|
|
9854
|
+
"planning/interviewer": 129,
|
|
9821
9855
|
"planning/patterns-researcher": 254,
|
|
9822
9856
|
"planning/planner": 208,
|
|
9823
9857
|
"planning/prd-creator": 210,
|
|
@@ -15814,6 +15848,7 @@ __export(exports_service, {
|
|
|
15814
15848
|
isDeniedForMcpChild: () => isDeniedForMcpChild,
|
|
15815
15849
|
isEntropyBackendEnabled: () => isEntropyBackendEnabled,
|
|
15816
15850
|
loadSecurityConfig: () => loadSecurityConfig,
|
|
15851
|
+
looksLikeSecret: () => looksLikeSecret,
|
|
15817
15852
|
looksSecretShaped: () => looksSecretShaped,
|
|
15818
15853
|
looksSecretShapedIn: () => looksSecretShapedIn,
|
|
15819
15854
|
memoizeResolved: () => memoizeResolved,
|
|
@@ -16077,6 +16112,7 @@ var init_service2 = __esm(() => {
|
|
|
16077
16112
|
init_secrets();
|
|
16078
16113
|
init_entropy();
|
|
16079
16114
|
init_incidents();
|
|
16115
|
+
init_secret_shape();
|
|
16080
16116
|
init_entropy_gate();
|
|
16081
16117
|
init_credential_shape();
|
|
16082
16118
|
init_audit_harness();
|
|
@@ -28951,7 +28987,8 @@ __export(exports_service5, {
|
|
|
28951
28987
|
UnknownGraphTargetError: () => UnknownGraphTargetError,
|
|
28952
28988
|
buildAffectedReport: () => buildAffectedReport,
|
|
28953
28989
|
checkGraphStaleness: () => checkGraphStaleness,
|
|
28954
|
-
createGdgraphService: () => createGdgraphService
|
|
28990
|
+
createGdgraphService: () => createGdgraphService,
|
|
28991
|
+
estimateTokens: () => estimateTokens2
|
|
28955
28992
|
});
|
|
28956
28993
|
|
|
28957
28994
|
// src/gdgraph/build.ts
|
|
@@ -37391,7 +37428,7 @@ function normalizeFwkResult(result) {
|
|
|
37391
37428
|
// src/sac/proposal-lifecycle.ts
|
|
37392
37429
|
init_fs();
|
|
37393
37430
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "crypto";
|
|
37394
|
-
import { appendFile as appendFile8, mkdir as mkdir35, readdir as
|
|
37431
|
+
import { appendFile as appendFile8, mkdir as mkdir35, readdir as readdir21, readFile as readFile64 } from "fs/promises";
|
|
37395
37432
|
import path121 from "path";
|
|
37396
37433
|
|
|
37397
37434
|
// src/sac/trusted-wrap-up.ts
|
|
@@ -37541,7 +37578,7 @@ function sessionDir(projectPath, sessionId, dataDir) {
|
|
|
37541
37578
|
// src/session/slate.ts
|
|
37542
37579
|
init_fs();
|
|
37543
37580
|
init_assembly();
|
|
37544
|
-
import { mkdir as mkdir33, readFile as readFile56, rm as rm7 } from "fs/promises";
|
|
37581
|
+
import { mkdir as mkdir33, readFile as readFile56, readdir as readdir19, rm as rm7, stat as stat16 } from "fs/promises";
|
|
37545
37582
|
import path113 from "path";
|
|
37546
37583
|
init_redact();
|
|
37547
37584
|
var SLATE_SEED_KINDS = [
|
|
@@ -37766,6 +37803,9 @@ function readJsonl2(file) {
|
|
|
37766
37803
|
...o.isError === true ? { isError: true } : {},
|
|
37767
37804
|
...typeof o.spillPath === "string" && o.spillPath.length > 0 ? { spillPath: o.spillPath } : {},
|
|
37768
37805
|
...o.collapsed === true ? { collapsed: true } : {},
|
|
37806
|
+
...typeof o.trailStep === "number" && Number.isInteger(o.trailStep) && o.trailStep > 0 ? { trailStep: o.trailStep } : {},
|
|
37807
|
+
...o.packed === true ? { packed: true } : {},
|
|
37808
|
+
...o.slateFrame === true ? { slateFrame: true } : {},
|
|
37769
37809
|
...typeof o.ts === "string" && o.ts.length > 0 ? { ts: o.ts } : {},
|
|
37770
37810
|
...reasoning !== undefined ? { reasoning } : {}
|
|
37771
37811
|
});
|
|
@@ -38136,7 +38176,7 @@ async function consumeConfirmToken(cwd, workspaceId, proposalId, idempotencyKey,
|
|
|
38136
38176
|
init_dedup();
|
|
38137
38177
|
init_store();
|
|
38138
38178
|
init_config();
|
|
38139
|
-
import { readFile as readFile59, readdir as
|
|
38179
|
+
import { readFile as readFile59, readdir as readdir20 } from "fs/promises";
|
|
38140
38180
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
38141
38181
|
import path118 from "path";
|
|
38142
38182
|
|
|
@@ -38369,7 +38409,7 @@ async function collectWikiDecisionEntries(cwd) {
|
|
|
38369
38409
|
const dir = path118.join(cwd, ".metaproject", "wiki", "decisions");
|
|
38370
38410
|
let files;
|
|
38371
38411
|
try {
|
|
38372
|
-
files = (await
|
|
38412
|
+
files = (await readdir20(dir)).filter((name) => name.endsWith(".md"));
|
|
38373
38413
|
} catch {
|
|
38374
38414
|
return [];
|
|
38375
38415
|
}
|
|
@@ -38720,7 +38760,7 @@ init_json();
|
|
|
38720
38760
|
init_guard();
|
|
38721
38761
|
import { createHash as createHash29 } from "crypto";
|
|
38722
38762
|
import { homedir as homedir2 } from "os";
|
|
38723
|
-
import { readFile as readFile62, stat as
|
|
38763
|
+
import { readFile as readFile62, stat as stat17 } from "fs/promises";
|
|
38724
38764
|
import path120 from "path";
|
|
38725
38765
|
var VERSION = "0.1.0";
|
|
38726
38766
|
var PROJECT_SKILLS_DIR = ".metaproject/project-skills";
|
|
@@ -38897,7 +38937,7 @@ async function classifyTarget(absoluteTarget, targetExists) {
|
|
|
38897
38937
|
if (!targetExists) {
|
|
38898
38938
|
return "symbol-or-concept";
|
|
38899
38939
|
}
|
|
38900
|
-
const stats = await
|
|
38940
|
+
const stats = await stat17(absoluteTarget);
|
|
38901
38941
|
return stats.isDirectory() ? "directory" : "file";
|
|
38902
38942
|
}
|
|
38903
38943
|
async function existingRelativePaths(projectRoot, candidates) {
|
|
@@ -39420,7 +39460,7 @@ class ProposalLifecycleService {
|
|
|
39420
39460
|
const proposalsDir = path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
|
|
39421
39461
|
let entries;
|
|
39422
39462
|
try {
|
|
39423
|
-
entries = (await
|
|
39463
|
+
entries = (await readdir21(proposalsDir)).filter((name) => name.endsWith(".json"));
|
|
39424
39464
|
} catch (error) {
|
|
39425
39465
|
if (isNotFound(error))
|
|
39426
39466
|
return [];
|
|
@@ -39930,7 +39970,7 @@ function normalizeCollaborationResult(value) {
|
|
|
39930
39970
|
}
|
|
39931
39971
|
// src/session/external-slate.ts
|
|
39932
39972
|
init_fs();
|
|
39933
|
-
import { mkdir as mkdir38, readdir as
|
|
39973
|
+
import { mkdir as mkdir38, readdir as readdir22, readFile as readFile66 } from "fs/promises";
|
|
39934
39974
|
import path124 from "path";
|
|
39935
39975
|
|
|
39936
39976
|
// src/sac/machine-wrap-up.ts
|
|
@@ -40398,7 +40438,7 @@ async function writeExternalSlate(cwd, externalSessionId, update) {
|
|
|
40398
40438
|
}
|
|
40399
40439
|
async function listExternalSlateIds(cwd) {
|
|
40400
40440
|
try {
|
|
40401
|
-
const entries = await
|
|
40441
|
+
const entries = await readdir22(externalSlatesDir(cwd));
|
|
40402
40442
|
return entries.filter((name) => name.endsWith(".json")).map((name) => name.slice(0, -".json".length));
|
|
40403
40443
|
} catch (error) {
|
|
40404
40444
|
if (isNotFound(error))
|
|
@@ -41133,6 +41173,18 @@ var HELP_GROUPS = [
|
|
|
41133
41173
|
group: "Working in keryx shell",
|
|
41134
41174
|
summary: "Compact model context \u2014 /compact [focus] (archive kept)."
|
|
41135
41175
|
},
|
|
41176
|
+
{
|
|
41177
|
+
kind: "slash",
|
|
41178
|
+
name: "/trail",
|
|
41179
|
+
group: "Working in keryx shell",
|
|
41180
|
+
summary: "The tool calls this session recorded (what stays when older rounds leave the request) \u2014 /trail [count] [tool=NAME] [file=TEXT] [from=STEP] [to=STEP]."
|
|
41181
|
+
},
|
|
41182
|
+
{
|
|
41183
|
+
kind: "slash",
|
|
41184
|
+
name: "/notes",
|
|
41185
|
+
group: "Working in keryx shell",
|
|
41186
|
+
summary: "The notes the model keeps for itself (the facts that survive older rounds) \u2014 /notes [key]."
|
|
41187
|
+
},
|
|
41136
41188
|
{
|
|
41137
41189
|
kind: "slash",
|
|
41138
41190
|
name: "/rewind",
|
|
@@ -41345,7 +41397,7 @@ var HELP_GROUPS = [
|
|
|
41345
41397
|
kind: "cli",
|
|
41346
41398
|
name: "decisions",
|
|
41347
41399
|
group: "Automation",
|
|
41348
|
-
summary:
|
|
41400
|
+
summary: `Recommendation journal: record each agent question with options and its recommendation, the human's choice, and report how often they agree (a third are asked blind). A question also takes your own text: the last row "\u0421\u0432\u043E\u0439 \u043E\u0442\u0432\u0435\u0442\u2026" in the shell, the "\u270D \u0421\u0432\u043E\u0439 \u043E\u0442\u0432\u0435\u0442" button in Telegram, and Tab after an option adds a typed reason.`
|
|
41349
41401
|
},
|
|
41350
41402
|
{
|
|
41351
41403
|
kind: "cli",
|
|
@@ -41411,7 +41463,7 @@ var HELP_GROUPS = [
|
|
|
41411
41463
|
kind: "slash",
|
|
41412
41464
|
name: "/decisions",
|
|
41413
41465
|
group: "Automation",
|
|
41414
|
-
summary: "Recommendation journal report: match share by mode and stage,
|
|
41466
|
+
summary: "Recommendation journal report: match share by mode and stage, the deviations with their reasons, and your own answers and typed reasons in full (marked \u270D in the sidebar row)."
|
|
41415
41467
|
},
|
|
41416
41468
|
{
|
|
41417
41469
|
kind: "slash",
|
|
@@ -41429,7 +41481,13 @@ var HELP_GROUPS = [
|
|
|
41429
41481
|
kind: "slash",
|
|
41430
41482
|
name: "/remote-control",
|
|
41431
41483
|
group: "Automation",
|
|
41432
|
-
summary:
|
|
41484
|
+
summary: 'Drive this session from a Telegram topic: send lines, get replies, answer approvals and questions (an option button, or "\u270D \u0421\u0432\u043E\u0439 \u043E\u0442\u0432\u0435\u0442" and a reply with your own text). Off by default; [name|off|status].'
|
|
41485
|
+
},
|
|
41486
|
+
{
|
|
41487
|
+
kind: "slash",
|
|
41488
|
+
name: "/history",
|
|
41489
|
+
group: "Automation",
|
|
41490
|
+
summary: "Post the last messages of this session to the Telegram topic, oldest first. [N], 1 to 20; 10 by default."
|
|
41433
41491
|
},
|
|
41434
41492
|
{
|
|
41435
41493
|
kind: "slash",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.73",
|
|
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": {
|
package/src/gdgraph/service.ts
CHANGED
|
@@ -25,6 +25,11 @@ export { buildAffectedReport, type AffectedReport, type AffectedReportOptions }
|
|
|
25
25
|
// `buildAffectedReport` above already follows).
|
|
26
26
|
export { checkGraphStaleness, type StalenessCheck, type StalenessStatus } from "./staleness";
|
|
27
27
|
|
|
28
|
+
// Flow 393: the shared token estimator, re-exported so session code that sizes the
|
|
29
|
+
// slate frame goes through this facade instead of a direct edge into
|
|
30
|
+
// `gdgraph/repomap.ts`.
|
|
31
|
+
export { estimateTokens } from "./repomap";
|
|
32
|
+
|
|
28
33
|
export interface GdgraphService {
|
|
29
34
|
build(cwd: string): Promise<{ nodes: number; edges: number; summaryPath: string }>;
|
|
30
35
|
loadGraph(cwd: string): Promise<GraphData>;
|
|
@@ -87,22 +87,20 @@ blockers?: string[] — unresolved critical unknowns
|
|
|
87
87
|
- **Max 8 questions** — stop when enough context is gathered
|
|
88
88
|
- **Confirm before proceeding** — summarize gathered context, state the summary's own confidence (the weakest of the answers it rests on), and ask if correct
|
|
89
89
|
|
|
90
|
-
##
|
|
90
|
+
## Host or no host
|
|
91
|
+
|
|
92
|
+
Before the first question, check whether a host can show it: the `ask_user` tool is available in this run.
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
- What should NOT be changed (constraints)?
|
|
94
|
+
- **Host present:** ask every question through `ask_user`, one per call, with the A/B/C/D options as its options.
|
|
95
|
+
- **No host:** ask NO question, not even in plain text; nobody is there to answer it. Return `status: "NEEDS_CONTEXT"` with the `assumptions` you would have asked about (question, assumption, `confidence: "assumption"`), `ready_to_proceed: false`. The caller decides.
|
|
96
|
+
- A cancelled or empty `ask_user` answer is not an answer: record it as an assumption and stop asking.
|
|
97
|
+
- Each `ask_user` question is recorded in the recommendation journal by the tool itself (source, arm, recommendation, answer); you do not record it. `src/decisions/interviewer-path.test.ts` pins this path through the agent's real tool roster.
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
- What specific concerns should the review focus on?
|
|
100
|
-
- What is the acceptance criteria?
|
|
99
|
+
## Question Bank by Goal Type
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
- Who else is affected by this decision?
|
|
101
|
+
- **Implementation:** expected input/output, edge cases that must be handled, performance or scale requirement, what must NOT change.
|
|
102
|
+
- **Review:** which concerns the review should focus on, the acceptance criteria.
|
|
103
|
+
- **Architecture/design:** hard constraints (performance, compat, timeline), what worries you most, who else is affected.
|
|
106
104
|
|
|
107
105
|
## Red Flags
|
|
108
106
|
|