@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/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": 131,
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 readdir20, readFile as readFile64 } from "fs/promises";
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 readdir19 } from "fs/promises";
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 readdir19(dir)).filter((name) => name.endsWith(".md"));
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 stat16 } from "fs/promises";
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 stat16(absoluteTarget);
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 readdir20(proposalsDir)).filter((name) => name.endsWith(".json"));
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 readdir21, readFile as readFile66 } from "fs/promises";
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 readdir21(externalSlatesDir(cwd));
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: "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)."
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, and the deviations with their reasons."
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: "Drive this session from a Telegram topic: send lines, get replies, answer approvals. Off by default; [name|off|status]."
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.68",
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",
@@ -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
- ## Question Bank by Goal Type
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
- ### For implementation goals
93
- - What is the expected input/output?
94
- - What are the edge cases that must be handled?
95
- - What is the performance/scale requirement?
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
- ### For review goals
99
- - What specific concerns should the review focus on?
100
- - What is the acceptance criteria?
99
+ ## Question Bank by Goal Type
101
100
 
102
- ### For architecture/design goals
103
- - What are the hard constraints (performance, compat, timeline)?
104
- - What are you most worried about?
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