@kody-ade/kody-engine 0.4.380 → 0.4.382

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.
Files changed (2) hide show
  1. package/dist/bin/kody.js +112 -26
  2. package/package.json +24 -25
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.380",
18
+ version: "0.4.382",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -1271,13 +1271,32 @@ var init_events = __esm({
1271
1271
 
1272
1272
  // src/verify.ts
1273
1273
  import { spawn } from "child_process";
1274
+ function buildVerifyEnv(source = process.env) {
1275
+ const env = { ...source };
1276
+ const rawSecrets = env.ALL_SECRETS;
1277
+ delete env.ALL_SECRETS;
1278
+ if (rawSecrets) {
1279
+ try {
1280
+ const parsed = JSON.parse(rawSecrets);
1281
+ for (const key of Object.keys(parsed)) delete env[key];
1282
+ } catch {
1283
+ }
1284
+ }
1285
+ for (const key of Object.keys(env)) {
1286
+ if (SENSITIVE_ENV_NAME.test(key)) delete env[key];
1287
+ }
1288
+ env.HUSKY = "0";
1289
+ env.SKIP_HOOKS = "1";
1290
+ env.CI = source.CI ?? "1";
1291
+ return env;
1292
+ }
1274
1293
  function runCommand(command, cwd) {
1275
1294
  return new Promise((resolve10) => {
1276
1295
  const start = Date.now();
1277
1296
  const child = spawn(command, {
1278
1297
  cwd,
1279
1298
  shell: true,
1280
- env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" },
1299
+ env: buildVerifyEnv(),
1281
1300
  stdio: ["ignore", "pipe", "pipe"]
1282
1301
  });
1283
1302
  const buffers = [];
@@ -1369,13 +1388,14 @@ function summarizeFailure(result) {
1369
1388
  }
1370
1389
  return lines.join("\n");
1371
1390
  }
1372
- var TAIL_CHARS, COMMAND_TIMEOUT_MS, DEFAULT_TEST_RETRIES, ANSI_RE;
1391
+ var TAIL_CHARS, COMMAND_TIMEOUT_MS, DEFAULT_TEST_RETRIES, SENSITIVE_ENV_NAME, ANSI_RE;
1373
1392
  var init_verify = __esm({
1374
1393
  "src/verify.ts"() {
1375
1394
  "use strict";
1376
1395
  TAIL_CHARS = 4e3;
1377
1396
  COMMAND_TIMEOUT_MS = 10 * 60 * 1e3;
1378
1397
  DEFAULT_TEST_RETRIES = 2;
1398
+ SENSITIVE_ENV_NAME = /(?:^|_)(?:TOKEN|SECRET|PASSWORD|PASSWD|API_KEY|PRIVATE_KEY|SERVICE_KEY|MASTER_KEY|CREDENTIALS?)(?:_|$)/i;
1379
1399
  ANSI_RE = /\x1B\[[0-?]*[ -/]*[@-~]/g;
1380
1400
  }
1381
1401
  });
@@ -4290,6 +4310,7 @@ function prBranchLifecycle(profile, profilePath) {
4290
4310
  const tail = [
4291
4311
  ...verifyChain,
4292
4312
  { script: "commitAndPush" },
4313
+ { script: "requireDeliveryArtifacts" },
4293
4314
  { script: "ensurePr" },
4294
4315
  { script: "postIssueComment" },
4295
4316
  { script: "writeAgentRunSummary" },
@@ -13553,7 +13574,7 @@ var init_ensurePr = __esm({
13553
13574
  draft: isFailure,
13554
13575
  failureReason: isFailure ? failureReason : void 0,
13555
13576
  changedFiles,
13556
- agentSummary: ctx.data.prSummary,
13577
+ agentSummary: ctx.data.prSummary || ctx.data.agentFallbackSummary,
13557
13578
  baseBranch,
13558
13579
  // No fresh commit this run → don't rebuild the body of an existing PR;
13559
13580
  // it would replace the original agent summary with the empty fallback.
@@ -16285,6 +16306,7 @@ var init_parseAgentResult = __esm({
16285
16306
  return;
16286
16307
  }
16287
16308
  const parsed = parseAgentResult(agentResult.finalText);
16309
+ ctx.data.agentFinalText = agentResult.finalText;
16288
16310
  ctx.data.agentDone = parsed.done;
16289
16311
  ctx.data.commitMessage = parsed.commitMessage;
16290
16312
  ctx.data.prSummary = parsed.prSummary;
@@ -17430,6 +17452,52 @@ var init_recordOutcome = __esm({
17430
17452
  }
17431
17453
  });
17432
17454
 
17455
+ // src/scripts/requireDeliveryArtifacts.ts
17456
+ function fallbackSummary(finalText) {
17457
+ const prose = finalText.split("\n").filter(
17458
+ (line) => !/^[\s>*_#`~-]*(?:DONE\b|COMMIT_MSG\s*:|PR_SUMMARY\s*:|PLAN_DEVIATIONS\s*:|FEEDBACK_ACTIONS\s*:)/i.test(line)
17459
+ ).join("\n").trim();
17460
+ if (!prose) return "";
17461
+ if (prose.length <= FALLBACK_SUMMARY_MAX) return prose;
17462
+ return `${prose.slice(0, FALLBACK_SUMMARY_MAX - 1)}\u2026`;
17463
+ }
17464
+ var FALLBACK_SUMMARY_MAX, requireDeliveryArtifacts;
17465
+ var init_requireDeliveryArtifacts = __esm({
17466
+ "src/scripts/requireDeliveryArtifacts.ts"() {
17467
+ "use strict";
17468
+ FALLBACK_SUMMARY_MAX = 6e3;
17469
+ requireDeliveryArtifacts = async (ctx) => {
17470
+ if (ctx.data.agentDone !== true) return;
17471
+ const commitResult = ctx.data.commitResult;
17472
+ const hasCommits = ctx.data.hasCommitsAhead === true;
17473
+ if (!commitResult?.committed && !hasCommits) return;
17474
+ const commitMessage = String(ctx.data.commitMessage ?? "").trim();
17475
+ const prSummary = String(ctx.data.prSummary ?? "").trim();
17476
+ const missing = [];
17477
+ if (!commitMessage) missing.push("COMMIT_MSG");
17478
+ if (!prSummary) missing.push("PR_SUMMARY");
17479
+ if (missing.length === 0) return;
17480
+ const reason = `agent omitted required delivery artifacts: ${missing.join(", ")}`;
17481
+ ctx.data.agentDone = false;
17482
+ ctx.data.agentResultIncomplete = true;
17483
+ ctx.data.agentMissingArtifacts = missing;
17484
+ ctx.data.agentFailureReason = reason;
17485
+ if (!prSummary) {
17486
+ const fallback = fallbackSummary(String(ctx.data.agentFinalText ?? ""));
17487
+ if (fallback) ctx.data.agentFallbackSummary = fallback;
17488
+ }
17489
+ const action = ctx.data.action;
17490
+ if (action?.type.endsWith("_COMPLETED")) {
17491
+ ctx.data.action = {
17492
+ type: action.type.replace(/_COMPLETED$/, "_FAILED"),
17493
+ payload: { reason, downgradedFrom: action.type },
17494
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
17495
+ };
17496
+ }
17497
+ };
17498
+ }
17499
+ });
17500
+
17433
17501
  // src/scripts/requireFeedbackActions.ts
17434
17502
  function countActionItems(block) {
17435
17503
  if (!block.trim()) return 0;
@@ -20174,6 +20242,7 @@ var init_scripts = __esm({
20174
20242
  init_publishReport();
20175
20243
  init_recordClassification();
20176
20244
  init_recordOutcome();
20245
+ init_requireDeliveryArtifacts();
20177
20246
  init_requireFeedbackActions();
20178
20247
  init_requirePlanDeviations();
20179
20248
  init_resolveArtifacts();
@@ -20265,6 +20334,7 @@ var init_scripts = __esm({
20265
20334
  writeJobStateFile,
20266
20335
  appendCompanyActivity,
20267
20336
  requireFeedbackActions,
20337
+ requireDeliveryArtifacts,
20268
20338
  requirePlanDeviations,
20269
20339
  verify,
20270
20340
  verifyWithRetry,
@@ -22625,37 +22695,53 @@ function createJsonlStore(sessionFile) {
22625
22695
  }
22626
22696
  };
22627
22697
  }
22698
+ function normalizeTurn(turn) {
22699
+ return {
22700
+ role: turn.role,
22701
+ content: turn.content,
22702
+ timestamp: turn.timestamp,
22703
+ toolCalls: turn.toolCalls ?? []
22704
+ };
22705
+ }
22628
22706
  function createConvexStore(args) {
22629
22707
  const { client, tenantId, sessionId, sessionFile, logger } = args;
22630
22708
  let sessionUpserted = false;
22709
+ const appendToConvex = async (turn) => {
22710
+ if (!sessionUpserted) {
22711
+ try {
22712
+ const meta = readMeta(sessionFile) ?? { type: "meta", mode: "one-shot" };
22713
+ await client.mutation(anyApi.chatSessions.upsert, {
22714
+ tenantId,
22715
+ sessionId,
22716
+ meta,
22717
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
22718
+ });
22719
+ sessionUpserted = true;
22720
+ } catch (err) {
22721
+ logger.warn(`session ${sessionId}: chatSessions.upsert failed: ${err instanceof Error ? err.message : String(err)}`);
22722
+ }
22723
+ }
22724
+ await client.mutation(anyApi.chatTurns.append, { tenantId, sessionId, turn });
22725
+ };
22631
22726
  return {
22632
22727
  backend: "convex",
22633
22728
  readTurns: async () => {
22634
22729
  const docs = await client.query(anyApi.chatTurns.list, { tenantId, sessionId });
22635
- return [...docs].sort((a, b) => a.seq - b.seq).map((doc) => doc.turn).filter(isChatTurn);
22730
+ const convexTurns = [...docs].sort((a, b) => a.seq - b.seq).map((doc) => doc.turn).filter(isChatTurn);
22731
+ const localTurns = readSession(sessionFile);
22732
+ if (localTurns.length <= convexTurns.length) return convexTurns;
22733
+ const tail = localTurns.slice(convexTurns.length).map(normalizeTurn);
22734
+ logger.info(
22735
+ `session ${sessionId}: backfilling ${tail.length} local JSONL turn(s) into Convex (convex=${convexTurns.length}, local=${localTurns.length})`
22736
+ );
22737
+ for (const turn of tail) {
22738
+ await appendToConvex(turn);
22739
+ }
22740
+ return [...convexTurns, ...tail];
22636
22741
  },
22637
22742
  appendTurn: async (turn) => {
22638
- const normalized = {
22639
- role: turn.role,
22640
- content: turn.content,
22641
- timestamp: turn.timestamp,
22642
- toolCalls: turn.toolCalls ?? []
22643
- };
22644
- if (!sessionUpserted) {
22645
- try {
22646
- const meta = readMeta(sessionFile) ?? { type: "meta", mode: "one-shot" };
22647
- await client.mutation(anyApi.chatSessions.upsert, {
22648
- tenantId,
22649
- sessionId,
22650
- meta,
22651
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
22652
- });
22653
- sessionUpserted = true;
22654
- } catch (err) {
22655
- logger.warn(`session ${sessionId}: chatSessions.upsert failed: ${err instanceof Error ? err.message : String(err)}`);
22656
- }
22657
- }
22658
- await client.mutation(anyApi.chatTurns.append, { tenantId, sessionId, turn: normalized });
22743
+ const normalized = normalizeTurn(turn);
22744
+ await appendToConvex(normalized);
22659
22745
  try {
22660
22746
  appendTurn(sessionFile, normalized);
22661
22747
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.380",
3
+ "version": "0.4.382",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,28 +12,6 @@
12
12
  "templates",
13
13
  "kody.config.schema.json"
14
14
  ],
15
- "scripts": {
16
- "kody:run": "tsx bin/kody.ts",
17
- "serve": "tsx bin/kody.ts serve",
18
- "serve:vscode": "tsx bin/kody.ts serve vscode",
19
- "serve:claude": "tsx bin/kody.ts serve claude",
20
- "clean:dist": "node scripts/clean-dist.cjs",
21
- "build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
22
- "check:modularity": "tsx scripts/check-script-modularity.ts",
23
- "pretest": "pnpm check:modularity",
24
- "test": "vitest run tests/unit tests/int --coverage",
25
- "posttest": "tsx scripts/check-coverage-floor.ts",
26
- "test:smoke": "vitest run tests/smoke --no-coverage",
27
- "test:e2e": "vitest run tests/e2e --no-coverage",
28
- "test:all": "vitest run tests --no-coverage",
29
- "typecheck": "tsc --noEmit",
30
- "lint": "biome check",
31
- "lint:fix": "biome check --write",
32
- "format": "biome format --write",
33
- "verify:package": "node scripts/verify-package-tarball.cjs",
34
- "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",
35
- "prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
36
- },
37
15
  "dependencies": {
38
16
  "@actions/cache": "^6.0.0",
39
17
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
@@ -58,5 +36,26 @@
58
36
  "url": "git+https://github.com/aharonyaircohen/kody-engine.git"
59
37
  },
60
38
  "homepage": "https://github.com/aharonyaircohen/kody-engine",
61
- "bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
62
- }
39
+ "bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
40
+ "scripts": {
41
+ "kody:run": "tsx bin/kody.ts",
42
+ "serve": "tsx bin/kody.ts serve",
43
+ "serve:vscode": "tsx bin/kody.ts serve vscode",
44
+ "serve:claude": "tsx bin/kody.ts serve claude",
45
+ "clean:dist": "node scripts/clean-dist.cjs",
46
+ "build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
47
+ "check:modularity": "tsx scripts/check-script-modularity.ts",
48
+ "pretest": "pnpm check:modularity",
49
+ "test": "vitest run tests/unit tests/int --coverage",
50
+ "posttest": "tsx scripts/check-coverage-floor.ts",
51
+ "test:smoke": "vitest run tests/smoke --no-coverage",
52
+ "test:e2e": "vitest run tests/e2e --no-coverage",
53
+ "test:all": "vitest run tests --no-coverage",
54
+ "typecheck": "tsc --noEmit",
55
+ "lint": "biome check",
56
+ "lint:fix": "biome check --write",
57
+ "format": "biome format --write",
58
+ "verify:package": "node scripts/verify-package-tarball.cjs",
59
+ "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"
60
+ }
61
+ }