@mrciphersmith/keryx 0.3.68 → 0.3.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/README.md +25 -8
- package/dist/cli.js +13128 -4770
- package/dist/core.js +92 -14
- package/package.json +2 -2
- 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();
|
|
@@ -24113,6 +24149,7 @@ __export(exports_service2, {
|
|
|
24113
24149
|
acCheckCachePath: () => acCheckCachePath,
|
|
24114
24150
|
acCriterionKnown: () => acCriterionKnown,
|
|
24115
24151
|
acPath: () => acPath,
|
|
24152
|
+
appendJournal: () => appendJournal,
|
|
24116
24153
|
assertAcIntact: () => assertAcIntact,
|
|
24117
24154
|
baseBranchCondition: () => baseBranchCondition,
|
|
24118
24155
|
batchAcCheckItems: () => batchAcCheckItems,
|
|
@@ -24131,6 +24168,7 @@ __export(exports_service2, {
|
|
|
24131
24168
|
fencedLines: () => fencedLines,
|
|
24132
24169
|
flowDeliveryStatementFrom: () => flowDeliveryStatementFrom,
|
|
24133
24170
|
flowStatementFrom: () => flowStatementFrom,
|
|
24171
|
+
flowsRoot: () => flowsRoot,
|
|
24134
24172
|
hashDiff: () => hashDiff,
|
|
24135
24173
|
intentNoteForNewFlow: () => intentNoteForNewFlow,
|
|
24136
24174
|
isFrozen: () => isFrozen,
|
|
@@ -28951,7 +28989,8 @@ __export(exports_service5, {
|
|
|
28951
28989
|
UnknownGraphTargetError: () => UnknownGraphTargetError,
|
|
28952
28990
|
buildAffectedReport: () => buildAffectedReport,
|
|
28953
28991
|
checkGraphStaleness: () => checkGraphStaleness,
|
|
28954
|
-
createGdgraphService: () => createGdgraphService
|
|
28992
|
+
createGdgraphService: () => createGdgraphService,
|
|
28993
|
+
estimateTokens: () => estimateTokens2
|
|
28955
28994
|
});
|
|
28956
28995
|
|
|
28957
28996
|
// src/gdgraph/build.ts
|
|
@@ -37391,7 +37430,7 @@ function normalizeFwkResult(result) {
|
|
|
37391
37430
|
// src/sac/proposal-lifecycle.ts
|
|
37392
37431
|
init_fs();
|
|
37393
37432
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "crypto";
|
|
37394
|
-
import { appendFile as appendFile8, mkdir as mkdir35, readdir as
|
|
37433
|
+
import { appendFile as appendFile8, mkdir as mkdir35, readdir as readdir21, readFile as readFile64 } from "fs/promises";
|
|
37395
37434
|
import path121 from "path";
|
|
37396
37435
|
|
|
37397
37436
|
// src/sac/trusted-wrap-up.ts
|
|
@@ -37541,7 +37580,7 @@ function sessionDir(projectPath, sessionId, dataDir) {
|
|
|
37541
37580
|
// src/session/slate.ts
|
|
37542
37581
|
init_fs();
|
|
37543
37582
|
init_assembly();
|
|
37544
|
-
import { mkdir as mkdir33, readFile as readFile56, rm as rm7 } from "fs/promises";
|
|
37583
|
+
import { mkdir as mkdir33, readFile as readFile56, readdir as readdir19, rm as rm7, stat as stat16 } from "fs/promises";
|
|
37545
37584
|
import path113 from "path";
|
|
37546
37585
|
init_redact();
|
|
37547
37586
|
var SLATE_SEED_KINDS = [
|
|
@@ -37766,6 +37805,9 @@ function readJsonl2(file) {
|
|
|
37766
37805
|
...o.isError === true ? { isError: true } : {},
|
|
37767
37806
|
...typeof o.spillPath === "string" && o.spillPath.length > 0 ? { spillPath: o.spillPath } : {},
|
|
37768
37807
|
...o.collapsed === true ? { collapsed: true } : {},
|
|
37808
|
+
...typeof o.trailStep === "number" && Number.isInteger(o.trailStep) && o.trailStep > 0 ? { trailStep: o.trailStep } : {},
|
|
37809
|
+
...o.packed === true ? { packed: true } : {},
|
|
37810
|
+
...o.slateFrame === true ? { slateFrame: true } : {},
|
|
37769
37811
|
...typeof o.ts === "string" && o.ts.length > 0 ? { ts: o.ts } : {},
|
|
37770
37812
|
...reasoning !== undefined ? { reasoning } : {}
|
|
37771
37813
|
});
|
|
@@ -38136,7 +38178,7 @@ async function consumeConfirmToken(cwd, workspaceId, proposalId, idempotencyKey,
|
|
|
38136
38178
|
init_dedup();
|
|
38137
38179
|
init_store();
|
|
38138
38180
|
init_config();
|
|
38139
|
-
import { readFile as readFile59, readdir as
|
|
38181
|
+
import { readFile as readFile59, readdir as readdir20 } from "fs/promises";
|
|
38140
38182
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
38141
38183
|
import path118 from "path";
|
|
38142
38184
|
|
|
@@ -38369,7 +38411,7 @@ async function collectWikiDecisionEntries(cwd) {
|
|
|
38369
38411
|
const dir = path118.join(cwd, ".metaproject", "wiki", "decisions");
|
|
38370
38412
|
let files;
|
|
38371
38413
|
try {
|
|
38372
|
-
files = (await
|
|
38414
|
+
files = (await readdir20(dir)).filter((name) => name.endsWith(".md"));
|
|
38373
38415
|
} catch {
|
|
38374
38416
|
return [];
|
|
38375
38417
|
}
|
|
@@ -38720,7 +38762,7 @@ init_json();
|
|
|
38720
38762
|
init_guard();
|
|
38721
38763
|
import { createHash as createHash29 } from "crypto";
|
|
38722
38764
|
import { homedir as homedir2 } from "os";
|
|
38723
|
-
import { readFile as readFile62, stat as
|
|
38765
|
+
import { readFile as readFile62, stat as stat17 } from "fs/promises";
|
|
38724
38766
|
import path120 from "path";
|
|
38725
38767
|
var VERSION = "0.1.0";
|
|
38726
38768
|
var PROJECT_SKILLS_DIR = ".metaproject/project-skills";
|
|
@@ -38897,7 +38939,7 @@ async function classifyTarget(absoluteTarget, targetExists) {
|
|
|
38897
38939
|
if (!targetExists) {
|
|
38898
38940
|
return "symbol-or-concept";
|
|
38899
38941
|
}
|
|
38900
|
-
const stats = await
|
|
38942
|
+
const stats = await stat17(absoluteTarget);
|
|
38901
38943
|
return stats.isDirectory() ? "directory" : "file";
|
|
38902
38944
|
}
|
|
38903
38945
|
async function existingRelativePaths(projectRoot, candidates) {
|
|
@@ -39420,7 +39462,7 @@ class ProposalLifecycleService {
|
|
|
39420
39462
|
const proposalsDir = path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
|
|
39421
39463
|
let entries;
|
|
39422
39464
|
try {
|
|
39423
|
-
entries = (await
|
|
39465
|
+
entries = (await readdir21(proposalsDir)).filter((name) => name.endsWith(".json"));
|
|
39424
39466
|
} catch (error) {
|
|
39425
39467
|
if (isNotFound(error))
|
|
39426
39468
|
return [];
|
|
@@ -39930,7 +39972,7 @@ function normalizeCollaborationResult(value) {
|
|
|
39930
39972
|
}
|
|
39931
39973
|
// src/session/external-slate.ts
|
|
39932
39974
|
init_fs();
|
|
39933
|
-
import { mkdir as mkdir38, readdir as
|
|
39975
|
+
import { mkdir as mkdir38, readdir as readdir22, readFile as readFile66 } from "fs/promises";
|
|
39934
39976
|
import path124 from "path";
|
|
39935
39977
|
|
|
39936
39978
|
// src/sac/machine-wrap-up.ts
|
|
@@ -40398,7 +40440,7 @@ async function writeExternalSlate(cwd, externalSessionId, update) {
|
|
|
40398
40440
|
}
|
|
40399
40441
|
async function listExternalSlateIds(cwd) {
|
|
40400
40442
|
try {
|
|
40401
|
-
const entries = await
|
|
40443
|
+
const entries = await readdir22(externalSlatesDir(cwd));
|
|
40402
40444
|
return entries.filter((name) => name.endsWith(".json")).map((name) => name.slice(0, -".json".length));
|
|
40403
40445
|
} catch (error) {
|
|
40404
40446
|
if (isNotFound(error))
|
|
@@ -41133,6 +41175,18 @@ var HELP_GROUPS = [
|
|
|
41133
41175
|
group: "Working in keryx shell",
|
|
41134
41176
|
summary: "Compact model context \u2014 /compact [focus] (archive kept)."
|
|
41135
41177
|
},
|
|
41178
|
+
{
|
|
41179
|
+
kind: "slash",
|
|
41180
|
+
name: "/trail",
|
|
41181
|
+
group: "Working in keryx shell",
|
|
41182
|
+
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]."
|
|
41183
|
+
},
|
|
41184
|
+
{
|
|
41185
|
+
kind: "slash",
|
|
41186
|
+
name: "/notes",
|
|
41187
|
+
group: "Working in keryx shell",
|
|
41188
|
+
summary: "The notes the model keeps for itself (the facts that survive older rounds) \u2014 /notes [key]."
|
|
41189
|
+
},
|
|
41136
41190
|
{
|
|
41137
41191
|
kind: "slash",
|
|
41138
41192
|
name: "/rewind",
|
|
@@ -41345,7 +41399,19 @@ var HELP_GROUPS = [
|
|
|
41345
41399
|
kind: "cli",
|
|
41346
41400
|
name: "decisions",
|
|
41347
41401
|
group: "Automation",
|
|
41348
|
-
summary:
|
|
41402
|
+
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.`
|
|
41403
|
+
},
|
|
41404
|
+
{
|
|
41405
|
+
kind: "cli",
|
|
41406
|
+
name: "intake",
|
|
41407
|
+
group: "Automation",
|
|
41408
|
+
summary: "GitHub work intake: tickets, review requests, failed CI, PR comments and board movement as cards in Telegram; status, pause, poll by hand, and a usefulness report."
|
|
41409
|
+
},
|
|
41410
|
+
{
|
|
41411
|
+
kind: "cli",
|
|
41412
|
+
name: "research",
|
|
41413
|
+
group: "Automation",
|
|
41414
|
+
summary: "Part 1 materials: sync refreshes the -latest counts, the text-free decisions export and the status page next to the catalog; no commit, only when the content changed."
|
|
41349
41415
|
},
|
|
41350
41416
|
{
|
|
41351
41417
|
kind: "cli",
|
|
@@ -41411,7 +41477,7 @@ var HELP_GROUPS = [
|
|
|
41411
41477
|
kind: "slash",
|
|
41412
41478
|
name: "/decisions",
|
|
41413
41479
|
group: "Automation",
|
|
41414
|
-
summary: "Recommendation journal report: match share by mode and stage,
|
|
41480
|
+
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
41481
|
},
|
|
41416
41482
|
{
|
|
41417
41483
|
kind: "slash",
|
|
@@ -41429,7 +41495,13 @@ var HELP_GROUPS = [
|
|
|
41429
41495
|
kind: "slash",
|
|
41430
41496
|
name: "/remote-control",
|
|
41431
41497
|
group: "Automation",
|
|
41432
|
-
summary:
|
|
41498
|
+
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].'
|
|
41499
|
+
},
|
|
41500
|
+
{
|
|
41501
|
+
kind: "slash",
|
|
41502
|
+
name: "/history",
|
|
41503
|
+
group: "Automation",
|
|
41504
|
+
summary: "Post the last messages of this session to the Telegram topic, oldest first. [N], 1 to 20; 10 by default."
|
|
41433
41505
|
},
|
|
41434
41506
|
{
|
|
41435
41507
|
kind: "slash",
|
|
@@ -41437,6 +41509,12 @@ var HELP_GROUPS = [
|
|
|
41437
41509
|
group: "Automation",
|
|
41438
41510
|
summary: "Connect, test or disconnect Telegram for this machine: bot token, one-time code, group. [status]."
|
|
41439
41511
|
},
|
|
41512
|
+
{
|
|
41513
|
+
kind: "slash",
|
|
41514
|
+
name: "/intake",
|
|
41515
|
+
group: "Automation",
|
|
41516
|
+
summary: "GitHub work intake: cards that wait for your decision (take, decline, later), pause or resume the poll, poll by hand. [status|list|pause|resume|poll]."
|
|
41517
|
+
},
|
|
41440
41518
|
{
|
|
41441
41519
|
kind: "slash",
|
|
41442
41520
|
name: "/rendering",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.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": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"test:client:terminal": "bun test src/tui/ src/commands/shell",
|
|
50
50
|
"test:client:streaming": "bun test src/harness/provider/",
|
|
51
51
|
"test:client:cancel-resume": "bun test src/harness/run/ src/harness/resume/ src/harness/session/ src/session/ src/bus/ src/rewind/ src/remote/ src/docs/ src/commands/sessions",
|
|
52
|
-
"test:client:runtime": "bun test src/harness/ src/mcp-client/ src/mcp-servers/ src/agents/ src/commands/agent src/commands/harness src/commands/providers src/scheduler/",
|
|
52
|
+
"test:client:runtime": "bun test src/harness/ src/mcp-client/ src/mcp-servers/ src/agents/ src/commands/agent src/commands/harness src/commands/providers src/scheduler/ src/intake/",
|
|
53
53
|
"test:client": "bun run test:client:terminal && bun run test:client:streaming && bun run test:client:cancel-resume && bun run test:client:runtime",
|
|
54
54
|
"check": "bun run lint && bun run typecheck && bun run typecheck:scripts && bun test",
|
|
55
55
|
"check:core": "bun run lint && bun run typecheck && bun run typecheck:scripts && bun run test:core",
|
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
|
|