@kody-ade/kody-engine 0.4.292 → 0.4.294

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/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.292",
18
+ version: "0.4.294",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -45,8 +45,9 @@ var init_package = __esm({
45
45
  lint: "biome check",
46
46
  "lint:fix": "biome check --write",
47
47
  format: "biome format --write",
48
+ "verify:package": "node scripts/verify-package-tarball.cjs",
48
49
  "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
49
- prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build"
50
+ prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
50
51
  },
51
52
  dependencies: {
52
53
  "@actions/cache": "^6.0.0",
@@ -2306,6 +2307,7 @@ function listFolderCapabilityActions(root, source) {
2306
2307
  if (capability.config.internal === true || capability.config.public === false) continue;
2307
2308
  const action = capability.config.action ?? slug2;
2308
2309
  const { executable, cliArgs } = resolveCapabilityExecution(capability);
2310
+ if (hasUnresolvedExplicitImplementation(capability, executable)) continue;
2309
2311
  out.push({
2310
2312
  action,
2311
2313
  capability: slug2,
@@ -2319,6 +2321,14 @@ function listFolderCapabilityActions(root, source) {
2319
2321
  }
2320
2322
  return out.sort((a, b) => a.action.localeCompare(b.action));
2321
2323
  }
2324
+ function hasUnresolvedExplicitImplementation(capability, executable) {
2325
+ const config = capability.config;
2326
+ const hasExplicitImplementation = Boolean(config.implementation || config.executable) || (config.implementations?.length ?? 0) > 0 || (config.executables?.length ?? 0) > 0;
2327
+ if (!hasExplicitImplementation) return false;
2328
+ if (config.workflow?.steps.length) return false;
2329
+ if (config.role && PUBLIC_EXECUTABLE_ROLES.has(config.role)) return false;
2330
+ return resolveExecutable(executable) === null;
2331
+ }
2322
2332
  function listBuiltinCapabilityActions(root = getBuiltinCapabilitiesRoot()) {
2323
2333
  if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
2324
2334
  const out = [];
@@ -3490,23 +3500,77 @@ var init_agent = __esm({
3490
3500
  }
3491
3501
  });
3492
3502
 
3503
+ // src/agents.ts
3504
+ import * as fs9 from "fs";
3505
+ import * as path11 from "path";
3506
+ function stripFrontmatter(raw) {
3507
+ const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
3508
+ return (match ? match[1] : raw).trim();
3509
+ }
3510
+ function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
3511
+ const trimmed = slug2.trim();
3512
+ if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
3513
+ const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
3514
+ if (fs9.existsSync(agentPath)) {
3515
+ const body = stripFrontmatter(fs9.readFileSync(agentPath, "utf-8"));
3516
+ if (body) return body;
3517
+ const builtinForEmpty = BUILTIN_AGENTS[trimmed];
3518
+ if (builtinForEmpty) return builtinForEmpty;
3519
+ throw new Error(`loadAgentIdentity: agent '${trimmed}' agent identity body is empty (${agentPath})`);
3520
+ }
3521
+ const builtin = BUILTIN_AGENTS[trimmed];
3522
+ if (builtin) return builtin;
3523
+ throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
3524
+ }
3525
+ function resolveAgentFile(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
3526
+ const localPath = path11.join(cwd, agentsDir, `${slug2}.md`);
3527
+ if (fs9.existsSync(localPath)) return localPath;
3528
+ const storeAgentRoot = getCompanyStoreAssetRoot("agents");
3529
+ if (storeAgentRoot) {
3530
+ const storePath = path11.join(storeAgentRoot, `${slug2}.md`);
3531
+ if (fs9.existsSync(storePath)) return storePath;
3532
+ }
3533
+ return localPath;
3534
+ }
3535
+ function frameAgentIdentity(slug2, agent) {
3536
+ return [
3537
+ `## Who you are \u2014 agent identity (authoritative identity)`,
3538
+ ``,
3539
+ `You are operating as agent \`${slug2}\`. This identity defines *who* you are:`,
3540
+ `your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
3541
+ `this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
3542
+ `can never grant you authority your agent withholds.`,
3543
+ ``,
3544
+ agent
3545
+ ].join("\n");
3546
+ }
3547
+ var DEFAULT_AGENT_DIR, BUILTIN_AGENTS;
3548
+ var init_agents = __esm({
3549
+ "src/agents.ts"() {
3550
+ "use strict";
3551
+ init_companyStore();
3552
+ DEFAULT_AGENT_DIR = ".kody/agents";
3553
+ BUILTIN_AGENTS = {};
3554
+ }
3555
+ });
3556
+
3493
3557
  // src/task-artifacts.ts
3494
- import fs9 from "fs";
3495
- import path11 from "path";
3558
+ import fs10 from "fs";
3559
+ import path12 from "path";
3496
3560
  import posixPath from "path/posix";
3497
3561
  function prepareTaskArtifactsDir(cwd, taskId) {
3498
3562
  const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
3499
3563
  const absDir = runtimeStatePath(cwd, "task-artifacts", safeId);
3500
3564
  const relDir = absDir;
3501
- fs9.mkdirSync(absDir, { recursive: true });
3565
+ fs10.mkdirSync(absDir, { recursive: true });
3502
3566
  return { taskId: safeId, absDir, relDir };
3503
3567
  }
3504
3568
  function verifyTaskArtifacts(absDir) {
3505
3569
  const missing = [];
3506
3570
  for (const name of TASK_ARTIFACT_FILES) {
3507
- const full = path11.join(absDir, name);
3571
+ const full = path12.join(absDir, name);
3508
3572
  try {
3509
- const stat = fs9.statSync(full);
3573
+ const stat = fs10.statSync(full);
3510
3574
  if (!stat.isFile() || stat.size === 0) missing.push(name);
3511
3575
  } catch {
3512
3576
  missing.push(name);
@@ -3519,11 +3583,11 @@ function taskArtifactStatePath(taskId, file) {
3519
3583
  }
3520
3584
  function persistTaskArtifactsToState(config, cwd, artifacts) {
3521
3585
  for (const file of TASK_ARTIFACT_FILES) {
3522
- const full = path11.join(artifacts.absDir, file);
3523
- if (!fs9.existsSync(full)) continue;
3524
- const stat = fs9.statSync(full);
3586
+ const full = path12.join(artifacts.absDir, file);
3587
+ if (!fs10.existsSync(full)) continue;
3588
+ const stat = fs10.statSync(full);
3525
3589
  if (!stat.isFile() || stat.size === 0) continue;
3526
- const content = fs9.readFileSync(full, "utf-8");
3590
+ const content = fs10.readFileSync(full, "utf-8");
3527
3591
  upsertStateText(
3528
3592
  config,
3529
3593
  cwd,
@@ -3603,7 +3667,7 @@ var init_task_artifacts = __esm({
3603
3667
 
3604
3668
  // src/gha.ts
3605
3669
  import { execFileSync as execFileSync3 } from "child_process";
3606
- import * as fs15 from "fs";
3670
+ import * as fs16 from "fs";
3607
3671
  function getRunUrl() {
3608
3672
  const server = process.env.GITHUB_SERVER_URL;
3609
3673
  const repo = process.env.GITHUB_REPOSITORY;
@@ -3614,10 +3678,10 @@ function getRunUrl() {
3614
3678
  function reactToTriggerComment(cwd) {
3615
3679
  if (process.env.GITHUB_EVENT_NAME !== "issue_comment") return;
3616
3680
  const eventPath = process.env.GITHUB_EVENT_PATH;
3617
- if (!eventPath || !fs15.existsSync(eventPath)) return;
3681
+ if (!eventPath || !fs16.existsSync(eventPath)) return;
3618
3682
  let event = null;
3619
3683
  try {
3620
- event = JSON.parse(fs15.readFileSync(eventPath, "utf-8"));
3684
+ event = JSON.parse(fs16.readFileSync(eventPath, "utf-8"));
3621
3685
  } catch {
3622
3686
  return;
3623
3687
  }
@@ -3668,60 +3732,6 @@ var init_gha = __esm({
3668
3732
  }
3669
3733
  });
3670
3734
 
3671
- // src/agents.ts
3672
- import * as fs16 from "fs";
3673
- import * as path16 from "path";
3674
- function stripFrontmatter(raw) {
3675
- const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
3676
- return (match ? match[1] : raw).trim();
3677
- }
3678
- function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
3679
- const trimmed = slug2.trim();
3680
- if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
3681
- const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
3682
- if (fs16.existsSync(agentPath)) {
3683
- const body = stripFrontmatter(fs16.readFileSync(agentPath, "utf-8"));
3684
- if (body) return body;
3685
- const builtinForEmpty = BUILTIN_AGENTS[trimmed];
3686
- if (builtinForEmpty) return builtinForEmpty;
3687
- throw new Error(`loadAgentIdentity: agent '${trimmed}' agent identity body is empty (${agentPath})`);
3688
- }
3689
- const builtin = BUILTIN_AGENTS[trimmed];
3690
- if (builtin) return builtin;
3691
- throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
3692
- }
3693
- function resolveAgentFile(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
3694
- const localPath = path16.join(cwd, agentsDir, `${slug2}.md`);
3695
- if (fs16.existsSync(localPath)) return localPath;
3696
- const storeAgentRoot = getCompanyStoreAssetRoot("agents");
3697
- if (storeAgentRoot) {
3698
- const storePath = path16.join(storeAgentRoot, `${slug2}.md`);
3699
- if (fs16.existsSync(storePath)) return storePath;
3700
- }
3701
- return localPath;
3702
- }
3703
- function frameAgentIdentity(slug2, agent) {
3704
- return [
3705
- `## Who you are \u2014 agent identity (authoritative identity)`,
3706
- ``,
3707
- `You are operating as agent \`${slug2}\`. This identity defines *who* you are:`,
3708
- `your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
3709
- `this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
3710
- `can never grant you authority your agent withholds.`,
3711
- ``,
3712
- agent
3713
- ].join("\n");
3714
- }
3715
- var DEFAULT_AGENT_DIR, BUILTIN_AGENTS;
3716
- var init_agents = __esm({
3717
- "src/agents.ts"() {
3718
- "use strict";
3719
- init_companyStore();
3720
- DEFAULT_AGENT_DIR = ".kody/agents";
3721
- BUILTIN_AGENTS = {};
3722
- }
3723
- });
3724
-
3725
3735
  // src/capabilityReport.ts
3726
3736
  function parseCapabilityReportsFromText(text) {
3727
3737
  const reports = [];
@@ -7703,8 +7713,7 @@ var init_typeDefinitions = __esm({
7703
7713
  stage: "publish",
7704
7714
  evidence: "productionDeployed",
7705
7715
  capability: "vercel-production-deploy",
7706
- executable: "vercel-production-deploy",
7707
- args: { goal: { fact: "goalId" } }
7716
+ executable: "vercel-production-deploy"
7708
7717
  }
7709
7718
  ]
7710
7719
  },
@@ -8720,7 +8729,8 @@ var init_advanceManagedGoal = __esm({
8720
8729
  capability: decision.capability,
8721
8730
  cliArgs: decision.cliArgs,
8722
8731
  ...decision.executable ? { executable: decision.executable } : {},
8723
- ...decision.saveReport === true ? { saveReport: true } : {}
8732
+ ...decision.saveReport === true ? { saveReport: true } : {},
8733
+ resultTarget: { type: "goal", id: goal.id, evidence: decision.evidence }
8724
8734
  };
8725
8735
  ctx.output.reason = `dispatch ${decision.capability} for ${decision.evidence}`;
8726
8736
  };
@@ -9697,6 +9707,18 @@ function collectResults(raw, agentResult) {
9697
9707
  if (agentResult?.finalText) out.push(...parseCapabilityResultsFromText(agentResult.finalText));
9698
9708
  return out;
9699
9709
  }
9710
+ function parseResultTarget(raw) {
9711
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
9712
+ const target = raw;
9713
+ if (target.type !== "goal") return null;
9714
+ if (typeof target.id !== "string" || target.id.trim().length === 0) return null;
9715
+ const evidence = typeof target.evidence === "string" && target.evidence.trim().length > 0 ? target.evidence.trim() : void 0;
9716
+ return {
9717
+ type: "goal",
9718
+ id: target.id.trim(),
9719
+ ...evidence ? { evidence } : {}
9720
+ };
9721
+ }
9700
9722
  function collectGoalCapabilityEvidence(reports, results, fallbackGoalId, explicitEvidence) {
9701
9723
  const items = [];
9702
9724
  for (const report of reports) {
@@ -9790,8 +9812,9 @@ var init_applyCapabilityReports = __esm({
9790
9812
  applyCapabilityReports = async (ctx, _profile, agentResult) => {
9791
9813
  const reports = collectReports(ctx.data.capabilityReports, agentResult);
9792
9814
  const results = collectResults(ctx.data.capabilityResults ?? ctx.data.dutyResults, agentResult);
9793
- const resultGoalId = typeof ctx.args.goal === "string" && ctx.args.goal.length > 0 ? ctx.args.goal : null;
9794
- const explicitEvidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
9815
+ const resultTarget = parseResultTarget(ctx.data.capabilityResultTarget);
9816
+ const resultGoalId = resultTarget?.id ?? (typeof ctx.args.goal === "string" && ctx.args.goal.length > 0 ? ctx.args.goal : null);
9817
+ const explicitEvidence = resultTarget?.evidence ?? (typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0);
9795
9818
  const evidenceItems = collectGoalCapabilityEvidence(reports, results, resultGoalId, explicitEvidence);
9796
9819
  if (evidenceItems.length === 0) return;
9797
9820
  const evidenceByGoal = groupGoalEvidence(evidenceItems);
@@ -18402,7 +18425,8 @@ function handoffToJob(handoff) {
18402
18425
  executable: handoff.executable,
18403
18426
  cliArgs: handoff.cliArgs,
18404
18427
  flavor: "instant",
18405
- saveReport: handoff.saveReport === true
18428
+ saveReport: handoff.saveReport === true,
18429
+ resultTarget: handoff.resultTarget
18406
18430
  };
18407
18431
  }
18408
18432
  function clearStampedLifecycleLabels(profile, ctx) {
@@ -18817,7 +18841,20 @@ function validateJob(input) {
18817
18841
  cliArgs: j.cliArgs ?? {},
18818
18842
  flavor: j.flavor,
18819
18843
  force: j.force === true,
18820
- saveReport: j.saveReport === true
18844
+ saveReport: j.saveReport === true,
18845
+ resultTarget: parseCapabilityResultTarget(j.resultTarget)
18846
+ };
18847
+ }
18848
+ function parseCapabilityResultTarget(raw) {
18849
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
18850
+ const target = raw;
18851
+ if (target.type !== "goal") return void 0;
18852
+ if (typeof target.id !== "string" || target.id.trim().length === 0) return void 0;
18853
+ const evidence = typeof target.evidence === "string" && target.evidence.trim().length > 0 ? target.evidence.trim() : void 0;
18854
+ return {
18855
+ type: "goal",
18856
+ id: target.id.trim(),
18857
+ ...evidence ? { evidence } : {}
18821
18858
  };
18822
18859
  }
18823
18860
  async function runJob(job, base) {
@@ -18877,6 +18914,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
18877
18914
  preloadedData.jobExecutable = profileName;
18878
18915
  if (valid.schedule !== void 0 && valid.schedule.length > 0) preloadedData.jobSchedule = valid.schedule;
18879
18916
  if (valid.saveReport === true) preloadedData.jobSaveReport = true;
18917
+ if (valid.resultTarget) preloadedData.capabilityResultTarget = valid.resultTarget;
18880
18918
  if (capabilityContext) {
18881
18919
  preloadedData.capabilitySlug = capabilityContext.slug;
18882
18920
  preloadedData.capabilityTitle = capabilityContext.title;
@@ -19241,16 +19279,17 @@ import * as path47 from "path";
19241
19279
 
19242
19280
  // src/chat/loop.ts
19243
19281
  init_agent();
19282
+ init_agents();
19244
19283
  init_config();
19245
19284
  init_registry();
19246
19285
  init_task_artifacts();
19247
- import * as fs13 from "fs";
19248
- import * as path15 from "path";
19286
+ import * as fs14 from "fs";
19287
+ import * as path16 from "path";
19249
19288
 
19250
19289
  // src/chat/attachments.ts
19251
19290
  init_runtimePaths();
19252
- import * as fs10 from "fs";
19253
- import * as path12 from "path";
19291
+ import * as fs11 from "fs";
19292
+ import * as path13 from "path";
19254
19293
  var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
19255
19294
  var EXT_BY_MIME = {
19256
19295
  "image/png": "png",
@@ -19283,11 +19322,11 @@ function prepareAttachments(turns, cwd, sessionId) {
19283
19322
  if (!isImage) return `[File: ${name}]`;
19284
19323
  try {
19285
19324
  if (!dirEnsured) {
19286
- fs10.mkdirSync(dir, { recursive: true });
19325
+ fs11.mkdirSync(dir, { recursive: true });
19287
19326
  dirEnsured = true;
19288
19327
  }
19289
- const filePath = path12.join(dir, `${imageCounter}.${extFor(mime)}`);
19290
- fs10.writeFileSync(filePath, Buffer.from(data, "base64"));
19328
+ const filePath = path13.join(dir, `${imageCounter}.${extFor(mime)}`);
19329
+ fs11.writeFileSync(filePath, Buffer.from(data, "base64"));
19291
19330
  imageCounter += 1;
19292
19331
  imagePaths.push(filePath);
19293
19332
  return `[Image "${name}" is attached \u2014 saved to ${filePath}. Use the Read tool on that exact path to view it.]`;
@@ -19303,11 +19342,11 @@ function prepareAttachments(turns, cwd, sessionId) {
19303
19342
  }
19304
19343
 
19305
19344
  // src/chat/events.ts
19306
- import * as fs11 from "fs";
19307
- import * as path13 from "path";
19345
+ import * as fs12 from "fs";
19346
+ import * as path14 from "path";
19308
19347
  import posixPath2 from "path/posix";
19309
19348
  function eventsFilePath(cwd, sessionId) {
19310
- return path13.join(cwd, ".kody", "events", `${sessionId}.jsonl`);
19349
+ return path14.join(cwd, ".kody", "events", `${sessionId}.jsonl`);
19311
19350
  }
19312
19351
  function eventsStatePath(sessionId) {
19313
19352
  return posixPath2.join("events", `${sessionId}.jsonl`);
@@ -19318,8 +19357,8 @@ var FileSink = class {
19318
19357
  }
19319
19358
  file;
19320
19359
  async emit(event) {
19321
- fs11.mkdirSync(path13.dirname(this.file), { recursive: true });
19322
- fs11.appendFileSync(this.file, `${JSON.stringify(event)}
19360
+ fs12.mkdirSync(path14.dirname(this.file), { recursive: true });
19361
+ fs12.appendFileSync(this.file, `${JSON.stringify(event)}
19323
19362
  `);
19324
19363
  }
19325
19364
  };
@@ -19373,18 +19412,18 @@ function makeRunId(sessionId, suffix) {
19373
19412
  }
19374
19413
 
19375
19414
  // src/chat/session.ts
19376
- import * as fs12 from "fs";
19377
- import * as path14 from "path";
19415
+ import * as fs13 from "fs";
19416
+ import * as path15 from "path";
19378
19417
  import posixPath3 from "path/posix";
19379
19418
  function sessionFilePath(cwd, sessionId) {
19380
- return path14.join(cwd, ".kody", "sessions", `${sessionId}.jsonl`);
19419
+ return path15.join(cwd, ".kody", "sessions", `${sessionId}.jsonl`);
19381
19420
  }
19382
19421
  function sessionStatePath(sessionId) {
19383
19422
  return posixPath3.join("sessions", `${sessionId}.jsonl`);
19384
19423
  }
19385
19424
  function readMeta(file) {
19386
- if (!fs12.existsSync(file)) return null;
19387
- const raw = fs12.readFileSync(file, "utf-8");
19425
+ if (!fs13.existsSync(file)) return null;
19426
+ const raw = fs13.readFileSync(file, "utf-8");
19388
19427
  const firstLine2 = raw.split("\n", 1)[0]?.trim();
19389
19428
  if (!firstLine2) return null;
19390
19429
  try {
@@ -19397,8 +19436,8 @@ function readMeta(file) {
19397
19436
  }
19398
19437
  }
19399
19438
  function readSession(file) {
19400
- if (!fs12.existsSync(file)) return [];
19401
- const raw = fs12.readFileSync(file, "utf-8").trim();
19439
+ if (!fs13.existsSync(file)) return [];
19440
+ const raw = fs13.readFileSync(file, "utf-8").trim();
19402
19441
  if (!raw) return [];
19403
19442
  const turns = [];
19404
19443
  for (const line of raw.split("\n")) {
@@ -19414,14 +19453,14 @@ function readSession(file) {
19414
19453
  return turns;
19415
19454
  }
19416
19455
  function appendTurn(file, turn) {
19417
- fs12.mkdirSync(path14.dirname(file), { recursive: true });
19456
+ fs13.mkdirSync(path15.dirname(file), { recursive: true });
19418
19457
  const line = JSON.stringify({
19419
19458
  role: turn.role,
19420
19459
  content: turn.content,
19421
19460
  timestamp: turn.timestamp,
19422
19461
  toolCalls: turn.toolCalls ?? []
19423
19462
  });
19424
- fs12.appendFileSync(file, `${line}
19463
+ fs13.appendFileSync(file, `${line}
19425
19464
  `);
19426
19465
  }
19427
19466
  function seedInitialMessage(file, message) {
@@ -19556,7 +19595,7 @@ function buildExecutableCatalog() {
19556
19595
  const entries = [];
19557
19596
  for (const { name, profilePath } of discovered) {
19558
19597
  try {
19559
- const raw = JSON.parse(fs13.readFileSync(profilePath, "utf-8"));
19598
+ const raw = JSON.parse(fs14.readFileSync(profilePath, "utf-8"));
19560
19599
  const describe = typeof raw.describe === "string" ? raw.describe : "";
19561
19600
  const firstSentence = describe.split(/(?<=[.!?])\s+/, 1)[0] ?? "";
19562
19601
  entries.push({ name, describe: firstSentence.trim() });
@@ -19593,6 +19632,7 @@ async function runChatTurn(opts) {
19593
19632
  }
19594
19633
  const { turns: promptTurns, imagePaths } = prepareAttachments(turns, opts.cwd, opts.sessionId);
19595
19634
  const basePrompt = opts.systemPrompt ?? (opts.model.protocol === "openai" ? OPENAI_CHAT_SYSTEM_PROMPT : CHAT_SYSTEM_PROMPT);
19635
+ const agentIdentityBlock = readAgentIdentityBlock(opts.cwd, opts.agentIdentity);
19596
19636
  const catalog = buildExecutableCatalog();
19597
19637
  const taskArtifactsPaths = prepareTaskArtifactsDir(opts.cwd, opts.sessionId);
19598
19638
  const artifactAddendum = taskArtifactsPromptAddendum({
@@ -19603,7 +19643,8 @@ async function runChatTurn(opts) {
19603
19643
  const contextBlock = readContextBlock(opts.cwd);
19604
19644
  const memoryBlock = readMemoryIndexBlock(opts.cwd);
19605
19645
  const instructionsBlock = readInstructionsBlock(opts.cwd);
19606
- const crossRepoBlock = opts.reposRoot ? CROSS_REPO_PROMPT : null;
19646
+ const fetchRepoEnabled = Boolean(opts.enableFetchRepoTool && opts.reposRoot);
19647
+ const crossRepoBlock = fetchRepoEnabled ? CROSS_REPO_PROMPT : null;
19607
19648
  const dashboardCmsEnabled = Boolean(opts.cmsDashboardUrl && opts.cmsRepoSlug && opts.cmsToken);
19608
19649
  const dashboardCmsBlock = dashboardCmsEnabled ? DASHBOARD_CMS_PROMPT : null;
19609
19650
  const imageBlock = imagePaths.length > 0 ? [
@@ -19616,6 +19657,7 @@ async function runChatTurn(opts) {
19616
19657
  ].join("\n") : null;
19617
19658
  const systemPrompt = [
19618
19659
  basePrompt,
19660
+ agentIdentityBlock,
19619
19661
  contextBlock,
19620
19662
  memoryBlock,
19621
19663
  instructionsBlock,
@@ -19644,14 +19686,14 @@ async function runChatTurn(opts) {
19644
19686
  quiet: opts.quiet,
19645
19687
  additionalDirectories: [
19646
19688
  taskArtifactsPaths.absDir,
19647
- ...Array.from(new Set(imagePaths.map((p2) => path15.dirname(p2))))
19689
+ ...Array.from(new Set(imagePaths.map((p2) => path16.dirname(p2))))
19648
19690
  ],
19649
19691
  systemPromptAppend: systemPrompt,
19650
19692
  ...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
19651
- // Let the agent clone + work on OTHER repos mid-conversation (a
19652
- // repo-less Brain serves many). Enabled whenever we know where repos
19653
- // live; grants read access to that root via additionalDirectories.
19654
- ...opts.reposRoot ? {
19693
+ // Cross-repo work is opt-in. Repo Brain's default path remains focused
19694
+ // on the selected repo even though the server stores clones under
19695
+ // reposRoot.
19696
+ ...fetchRepoEnabled ? {
19655
19697
  enableFetchRepoTool: true,
19656
19698
  reposRoot: opts.reposRoot,
19657
19699
  repoToken: opts.repoToken
@@ -19736,6 +19778,12 @@ async function runChatTurn(opts) {
19736
19778
  }
19737
19779
  return { exitCode: 0, reply };
19738
19780
  }
19781
+ function readAgentIdentityBlock(cwd, agentIdentity) {
19782
+ const slug2 = agentIdentity?.slug?.trim();
19783
+ if (!slug2) return null;
19784
+ const body = agentIdentity?.body?.trim() || loadAgentIdentity(cwd, slug2);
19785
+ return frameAgentIdentity(slug2, body);
19786
+ }
19739
19787
  async function runOpenAIChatTurn(args) {
19740
19788
  const { opts, turns, systemPrompt, sessionFile } = args;
19741
19789
  const doFetch = opts.fetchImpl ?? fetch;
@@ -19821,10 +19869,10 @@ async function emit(sink, type, sessionId, suffix, payload) {
19821
19869
  var MEMORY_INDEX_REL = ".kody/memory/INDEX.md";
19822
19870
  var MAX_INDEX_BYTES = 8e3;
19823
19871
  function readMemoryIndexBlock(cwd) {
19824
- const indexPath = path15.join(cwd, MEMORY_INDEX_REL);
19872
+ const indexPath = path16.join(cwd, MEMORY_INDEX_REL);
19825
19873
  let raw;
19826
19874
  try {
19827
- raw = fs13.readFileSync(indexPath, "utf-8");
19875
+ raw = fs14.readFileSync(indexPath, "utf-8");
19828
19876
  } catch {
19829
19877
  return "";
19830
19878
  }
@@ -19844,17 +19892,17 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
19844
19892
  var CONTEXT_DIR_REL = ".kody/context";
19845
19893
  var MAX_CONTEXT_BYTES = 12e3;
19846
19894
  function readContextBlock(cwd) {
19847
- const dir = path15.join(cwd, CONTEXT_DIR_REL);
19895
+ const dir = path16.join(cwd, CONTEXT_DIR_REL);
19848
19896
  let files;
19849
19897
  try {
19850
- files = fs13.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
19898
+ files = fs14.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
19851
19899
  } catch {
19852
19900
  return "";
19853
19901
  }
19854
19902
  const sections = [];
19855
19903
  for (const file of files) {
19856
19904
  try {
19857
- const content = fs13.readFileSync(path15.join(dir, file), "utf-8").trim();
19905
+ const content = fs14.readFileSync(path16.join(dir, file), "utf-8").trim();
19858
19906
  if (content) sections.push(`### ${file.replace(/\.md$/, "")}
19859
19907
 
19860
19908
  ${content}`);
@@ -19877,10 +19925,10 @@ _\u2026 (context truncated; use the state repo context files for the full text)_
19877
19925
  var INSTRUCTIONS_REL = ".kody/instructions.md";
19878
19926
  var MAX_INSTRUCTIONS_BYTES = 8e3;
19879
19927
  function readInstructionsBlock(cwd) {
19880
- const instructionsPath = path15.join(cwd, INSTRUCTIONS_REL);
19928
+ const instructionsPath = path16.join(cwd, INSTRUCTIONS_REL);
19881
19929
  let raw;
19882
19930
  try {
19883
- raw = fs13.readFileSync(instructionsPath, "utf-8");
19931
+ raw = fs14.readFileSync(instructionsPath, "utf-8");
19884
19932
  } catch {
19885
19933
  return "";
19886
19934
  }
@@ -19981,7 +20029,7 @@ init_config();
19981
20029
 
19982
20030
  // src/dispatch.ts
19983
20031
  init_config();
19984
- import * as fs14 from "fs";
20032
+ import * as fs15 from "fs";
19985
20033
 
19986
20034
  // src/cron-match.ts
19987
20035
  var FIELD_BOUNDS = [
@@ -20083,10 +20131,10 @@ function autoDispatch(opts) {
20083
20131
  }
20084
20132
  const eventName = process.env.GITHUB_EVENT_NAME;
20085
20133
  const eventPath = process.env.GITHUB_EVENT_PATH;
20086
- if (!eventName || !eventPath || !fs14.existsSync(eventPath)) return null;
20134
+ if (!eventName || !eventPath || !fs15.existsSync(eventPath)) return null;
20087
20135
  let event = {};
20088
20136
  try {
20089
- event = JSON.parse(fs14.readFileSync(eventPath, "utf-8"));
20137
+ event = JSON.parse(fs15.readFileSync(eventPath, "utf-8"));
20090
20138
  } catch {
20091
20139
  return null;
20092
20140
  }
@@ -20197,7 +20245,7 @@ function autoDispatchTyped(opts) {
20197
20245
  if (legacy) return { kind: "route", ...legacy };
20198
20246
  const eventName = process.env.GITHUB_EVENT_NAME;
20199
20247
  const eventPath = process.env.GITHUB_EVENT_PATH;
20200
- if (!eventName || !eventPath || !fs14.existsSync(eventPath)) {
20248
+ if (!eventName || !eventPath || !fs15.existsSync(eventPath)) {
20201
20249
  return { kind: "silent", reason: "no GHA event context" };
20202
20250
  }
20203
20251
  if (eventName !== "issue_comment") {
@@ -20205,7 +20253,7 @@ function autoDispatchTyped(opts) {
20205
20253
  }
20206
20254
  let event = {};
20207
20255
  try {
20208
- event = JSON.parse(fs14.readFileSync(eventPath, "utf-8"));
20256
+ event = JSON.parse(fs15.readFileSync(eventPath, "utf-8"));
20209
20257
  } catch {
20210
20258
  return { kind: "silent", reason: "GHA event payload unreadable" };
20211
20259
  }
@@ -20249,7 +20297,7 @@ function dispatchScheduledWatches(opts) {
20249
20297
  for (const exe of listExecutables()) {
20250
20298
  let raw;
20251
20299
  try {
20252
- raw = fs14.readFileSync(exe.profilePath, "utf-8");
20300
+ raw = fs15.readFileSync(exe.profilePath, "utf-8");
20253
20301
  } catch {
20254
20302
  continue;
20255
20303
  }
@@ -21332,6 +21380,19 @@ function strField(body, key) {
21332
21380
  }
21333
21381
  return void 0;
21334
21382
  }
21383
+ function boolField(body, key) {
21384
+ return typeof body === "object" && body !== null && body[key] === true;
21385
+ }
21386
+ function agentIdentityField(body) {
21387
+ if (typeof body !== "object" || body === null || !("agentIdentity" in body)) return void 0;
21388
+ const value = body.agentIdentity;
21389
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
21390
+ const record2 = value;
21391
+ const slug2 = typeof record2.slug === "string" ? record2.slug.trim() : "";
21392
+ const bodyText = typeof record2.body === "string" ? record2.body.trim() : "";
21393
+ if (!slug2 || !bodyText) return void 0;
21394
+ return { slug: slug2, body: bodyText };
21395
+ }
21335
21396
  function sendJson(res, status, body) {
21336
21397
  res.writeHead(status, { "content-type": "application/json" });
21337
21398
  res.end(JSON.stringify(body));
@@ -21466,6 +21527,8 @@ async function handleChatTurn(req, res, chatId, opts) {
21466
21527
  const dashboardUrl = strField(body, "dashboardUrl");
21467
21528
  const storeRepoUrl = strField(body, "storeRepoUrl");
21468
21529
  const storeRef = strField(body, "storeRef");
21530
+ const allowCrossRepo = boolField(body, "allowCrossRepo");
21531
+ const agentIdentity = agentIdentityField(body);
21469
21532
  let agentCwd;
21470
21533
  try {
21471
21534
  agentCwd = await ensureRepoCwd({
@@ -21540,9 +21603,12 @@ async function handleChatTurn(req, res, chatId, opts) {
21540
21603
  model: opts.model,
21541
21604
  litellmUrl: opts.litellmUrl,
21542
21605
  sink,
21543
- // Let the agent clone + work on OTHER repos via the fetch_repo tool.
21544
21606
  reposRoot: opts.reposRoot,
21607
+ // Repo Brain is selected-repo focused by default. Higher-level
21608
+ // coordinator flows can opt into fetch_repo explicitly.
21609
+ ...allowCrossRepo ? { enableFetchRepoTool: true } : {},
21545
21610
  repoToken,
21611
+ ...agentIdentity ? { agentIdentity } : {},
21546
21612
  ...dashboardUrl && repo && stateToken ? {
21547
21613
  cmsDashboardUrl: dashboardUrl,
21548
21614
  cmsRepoSlug: repo,
@@ -21812,7 +21878,9 @@ async function proxyToBrainServe(args) {
21812
21878
  ...args.body.repoToken ? { repoToken: args.body.repoToken } : {},
21813
21879
  ...args.body.dashboardUrl ? { dashboardUrl: args.body.dashboardUrl } : {},
21814
21880
  ...args.body.storeRepoUrl ? { storeRepoUrl: args.body.storeRepoUrl } : {},
21815
- ...args.body.storeRef ? { storeRef: args.body.storeRef } : {}
21881
+ ...args.body.storeRef ? { storeRef: args.body.storeRef } : {},
21882
+ ...args.body.allowCrossRepo === true ? { allowCrossRepo: true } : {},
21883
+ ...args.body.agentIdentity ? { agentIdentity: args.body.agentIdentity } : {}
21816
21884
  })
21817
21885
  });
21818
21886
  if (!upstream.ok || !upstream.body) {
@@ -394,6 +394,12 @@ export interface OutputContract {
394
394
  }
395
395
  }
396
396
 
397
+ export interface CapabilityResultTarget {
398
+ type: "goal"
399
+ id: string
400
+ evidence?: string
401
+ }
402
+
397
403
  // ────────────────────────────────────────────────────────────────────────────
398
404
  // Run-time context passed to every script.
399
405
  // ────────────────────────────────────────────────────────────────────────────
@@ -429,6 +435,7 @@ export interface Context {
429
435
  executable?: string
430
436
  cliArgs: Record<string, unknown>
431
437
  saveReport?: boolean
438
+ resultTarget?: CapabilityResultTarget
432
439
  }
433
440
  /** In-process hand-off to a full Job, preserving job identity in task state. */
434
441
  nextJob?: Job
@@ -440,6 +447,7 @@ export interface Context {
440
447
  executable?: string
441
448
  cliArgs: Record<string, unknown>
442
449
  saveReport?: boolean
450
+ resultTarget?: CapabilityResultTarget
443
451
  }
444
452
  }
445
453
  /**
@@ -512,4 +520,6 @@ export interface Job {
512
520
  force?: boolean
513
521
  /** Ask the owning goal/loop to write a report run after its persisted decision. */
514
522
  saveReport?: boolean
523
+ /** Internal parent context used by postflights to attach neutral capability output. */
524
+ resultTarget?: CapabilityResultTarget
515
525
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.292",
3
+ "version": "0.4.294",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -54,6 +54,7 @@
54
54
  "lint": "biome check",
55
55
  "lint:fix": "biome check --write",
56
56
  "format": "biome format --write",
57
+ "verify:package": "node scripts/verify-package-tarball.cjs",
57
58
  "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
58
59
  }
59
60
  }