@kody-ade/kody-engine 0.4.172 → 0.4.173

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 +59 -2
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -531,7 +531,22 @@ function getIssue(issueNumber, cwd) {
531
531
  function stripKodyMentions(body) {
532
532
  return body.replace(/(@)(kody)/gi, "$1\u200B$2");
533
533
  }
534
+ function detectBotDispatchShape(body) {
535
+ const trimmed = body.replace(/^\s+/, "");
536
+ const m = trimmed.match(/^@kody\s+([a-z][a-z0-9-]*)\b/i);
537
+ return m ? m[1].toLowerCase() : null;
538
+ }
539
+ function isRunningAsBot() {
540
+ if (process.env.GITHUB_ACTIONS !== "true") return false;
541
+ const actor = (process.env.GITHUB_ACTOR ?? "").toLowerCase();
542
+ if (actor.endsWith("[bot]") || actor === "kody-bot" || actor === "kodyade") return true;
543
+ return !!process.env.KODY_APP_ID;
544
+ }
534
545
  function postIssueComment(issueNumber, body, cwd) {
546
+ if (isRunningAsBot()) {
547
+ const slug = detectBotDispatchShape(body);
548
+ if (slug) throw new BotDispatchCommentError(slug);
549
+ }
535
550
  try {
536
551
  gh(["issue", "comment", String(issueNumber), "--body-file", "-"], { input: stripKodyMentions(body), cwd });
537
552
  } catch (err) {
@@ -629,6 +644,10 @@ function getPrLatestReviewBody(prNumber, cwd) {
629
644
  return pr.body;
630
645
  }
631
646
  function postPrReviewComment(prNumber, body, cwd) {
647
+ if (isRunningAsBot()) {
648
+ const slug = detectBotDispatchShape(body);
649
+ if (slug) throw new BotDispatchCommentError(slug);
650
+ }
632
651
  try {
633
652
  gh(["pr", "comment", String(prNumber), "--body-file", "-"], { input: stripKodyMentions(body), cwd });
634
653
  } catch (err) {
@@ -638,11 +657,19 @@ function postPrReviewComment(prNumber, body, cwd) {
638
657
  );
639
658
  }
640
659
  }
641
- var API_TIMEOUT_MS, DEFAULT_COMMENT_LIMIT, DEFAULT_COMMENT_MAX_BYTES, VERDICT_HEADING;
660
+ var API_TIMEOUT_MS, BotDispatchCommentError, DEFAULT_COMMENT_LIMIT, DEFAULT_COMMENT_MAX_BYTES, VERDICT_HEADING;
642
661
  var init_issue = __esm({
643
662
  "src/issue.ts"() {
644
663
  "use strict";
645
664
  API_TIMEOUT_MS = 3e4;
665
+ BotDispatchCommentError = class extends Error {
666
+ constructor(slug) {
667
+ super(
668
+ `bot self-dispatch via @kody comments is banned. Refusing to post "@kody ${slug} \u2026" \u2014 use runExecutableChain (same-run) or dispatchExecutable (cross-run) instead. See docs/duty-dispatch.md for the contract.`
669
+ );
670
+ this.name = "BotDispatchCommentError";
671
+ }
672
+ };
646
673
  DEFAULT_COMMENT_LIMIT = 12;
647
674
  DEFAULT_COMMENT_MAX_BYTES = 16e3;
648
675
  VERDICT_HEADING = /(^|\n)\s*#{1,6}\s*Verdict\s*:/i;
@@ -1061,7 +1088,7 @@ var init_loadPriorArt = __esm({
1061
1088
  // package.json
1062
1089
  var package_default = {
1063
1090
  name: "@kody-ade/kody-engine",
1064
- version: "0.4.172",
1091
+ version: "0.4.173",
1065
1092
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
1066
1093
  license: "MIT",
1067
1094
  type: "module",
@@ -6430,6 +6457,35 @@ function filterGoalTaskPrs(prs, taskIssueNumbers) {
6430
6457
  });
6431
6458
  }
6432
6459
 
6460
+ // src/scripts/deriveQaScopeFromIssue.ts
6461
+ init_issue();
6462
+ var TITLE_PATTERN = /^QA(?:\s+\w+)?:\s*(.+?)(?:\s*\(#\d+\))?\s*$/i;
6463
+ var deriveQaScopeFromIssue = async (ctx) => {
6464
+ if (typeof ctx.args.scope === "string" && ctx.args.scope.trim().length > 0) {
6465
+ return;
6466
+ }
6467
+ const issueNumber = Number(ctx.args.issue ?? 0);
6468
+ if (!Number.isFinite(issueNumber) || issueNumber <= 0) return;
6469
+ let title = "";
6470
+ try {
6471
+ const issue = getIssue(issueNumber, ctx.cwd);
6472
+ title = (issue.title ?? "").trim();
6473
+ } catch (err) {
6474
+ process.stderr.write(
6475
+ `[kody] deriveQaScopeFromIssue: could not read #${issueNumber}: ${err instanceof Error ? err.message : String(err)}
6476
+ `
6477
+ );
6478
+ return;
6479
+ }
6480
+ if (!title) return;
6481
+ const m = title.match(TITLE_PATTERN);
6482
+ const scope = (m?.[1] ?? title).trim();
6483
+ if (!scope) return;
6484
+ ctx.args.scope = scope;
6485
+ process.stdout.write(`\u2192 qa-engineer: derived scope from tracking issue #${issueNumber} title: "${scope}"
6486
+ `);
6487
+ };
6488
+
6433
6489
  // src/scripts/diagMcp.ts
6434
6490
  import { execFileSync as execFileSync10 } from "child_process";
6435
6491
  import * as fs25 from "fs";
@@ -13101,6 +13157,7 @@ var preflightScripts = {
13101
13157
  buildSyntheticPlugin,
13102
13158
  resolveArtifacts,
13103
13159
  discoverQaContext,
13160
+ deriveQaScopeFromIssue,
13104
13161
  resolvePreviewUrl,
13105
13162
  resolveQaUrl,
13106
13163
  promoteQaGoal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.172",
3
+ "version": "0.4.173",
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",