@kody-ade/kody-engine 0.4.300 → 0.4.302

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 +62 -10
  2. package/package.json +1 -1
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.300",
18
+ version: "0.4.302",
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",
@@ -10963,7 +10963,7 @@ var init_deriveQaScopeFromIssue = __esm({
10963
10963
  "src/scripts/deriveQaScopeFromIssue.ts"() {
10964
10964
  "use strict";
10965
10965
  init_issue();
10966
- TITLE_PATTERN = /^QA(?:\s+\w+)?:\s*(.+?)(?:\s*\(#\d+\))?\s*$/i;
10966
+ TITLE_PATTERN = /^QA:\s*(.+?)(?:\s*\(#\d+\))?\s*$/i;
10967
10967
  deriveQaScopeFromIssue = async (ctx) => {
10968
10968
  if (typeof ctx.args.scope === "string" && ctx.args.scope.trim().length > 0) {
10969
10969
  return;
@@ -10983,7 +10983,8 @@ var init_deriveQaScopeFromIssue = __esm({
10983
10983
  }
10984
10984
  if (!title) return;
10985
10985
  const m = title.match(TITLE_PATTERN);
10986
- const scope = (m?.[1] ?? title).trim();
10986
+ if (!m) return;
10987
+ const scope = (m[1] ?? "").trim();
10987
10988
  if (!scope) return;
10988
10989
  ctx.args.scope = scope;
10989
10990
  process.stdout.write(`\u2192 qa-engineer: derived scope from tracking issue #${issueNumber} title: "${scope}"
@@ -20302,6 +20303,13 @@ function autoDispatch(opts) {
20302
20303
  const afterTag = extractAfterTag(body);
20303
20304
  const firstTokenRaw = extractSubcommand(afterTag);
20304
20305
  const firstToken = firstTokenRaw && POLITE_WORDS.has(firstTokenRaw) ? null : firstTokenRaw;
20306
+ if (isBotAuthor && firstToken) {
20307
+ process.stderr.write(
20308
+ `[kody] dispatch: rejecting bot self-dispatch comment (author=${authorLogin || authorType}, firstToken=${firstToken})
20309
+ `
20310
+ );
20311
+ return null;
20312
+ }
20305
20313
  const aliases = opts?.config?.aliases ?? BUILTIN_ALIASES;
20306
20314
  const aliased = firstToken ? aliases[firstToken] ?? firstToken : null;
20307
20315
  let route = null;
@@ -20382,13 +20390,6 @@ function autoDispatchTyped(opts) {
20382
20390
  if (!hasKodyMention(rawBody)) {
20383
20391
  return { kind: "silent", reason: "comment does not mention @kody" };
20384
20392
  }
20385
- if (authorLogin === "kody-bot" || authorType === "Bot") {
20386
- return { kind: "silent", reason: `bot-authored comment (${authorLogin || authorType})` };
20387
- }
20388
- if (!associationAllowed(event, opts?.config)) {
20389
- const assoc = String(comment?.author_association ?? "").toUpperCase() || "<none>";
20390
- return { kind: "silent", reason: `commenter association '${assoc}' not in access.allowedAssociations` };
20391
- }
20392
20393
  const targetNum = Number(issue?.number ?? 0);
20393
20394
  const isPr = !!issue?.pull_request;
20394
20395
  if (!targetNum) {
@@ -20396,6 +20397,23 @@ function autoDispatchTyped(opts) {
20396
20397
  }
20397
20398
  const afterTag = extractAfterTag(rawBody.toLowerCase());
20398
20399
  const tokenRaw = extractSubcommand(afterTag) ?? "";
20400
+ if ((authorLogin === "kody-bot" || authorType === "Bot") && tokenRaw && !POLITE_WORDS.has(tokenRaw)) {
20401
+ return {
20402
+ kind: "rejected",
20403
+ reason: "bot_self_dispatch",
20404
+ token: tokenRaw,
20405
+ target: targetNum,
20406
+ isPr,
20407
+ author: authorLogin || authorType
20408
+ };
20409
+ }
20410
+ if (authorLogin === "kody-bot" || authorType === "Bot") {
20411
+ return { kind: "silent", reason: `bot-authored comment (${authorLogin || authorType})` };
20412
+ }
20413
+ if (!associationAllowed(event, opts?.config)) {
20414
+ const assoc = String(comment?.author_association ?? "").toUpperCase() || "<none>";
20415
+ return { kind: "silent", reason: `commenter association '${assoc}' not in access.allowedAssociations` };
20416
+ }
20399
20417
  if (!tokenRaw || POLITE_WORDS.has(tokenRaw)) {
20400
20418
  return {
20401
20419
  kind: "silent",
@@ -20553,6 +20571,7 @@ function coerceBare(spec, value) {
20553
20571
  init_gha();
20554
20572
  init_issue();
20555
20573
  init_job();
20574
+ init_lifecycleLabels();
20556
20575
  init_registry();
20557
20576
 
20558
20577
  // src/run-request.ts
@@ -20618,6 +20637,11 @@ function readRunRequestFromEnv(env = process.env) {
20618
20637
  // src/kody-cli.ts
20619
20638
  init_runtimePaths();
20620
20639
  init_stateWorkspace();
20640
+ var FAILED_DISPATCH_LABEL = {
20641
+ label: "kody:failed",
20642
+ color: "e11d21",
20643
+ description: "Kody failed or rejected the run"
20644
+ };
20621
20645
  var CI_HELP = `kody ci \u2014 minimal-YAML autonomous engineer (CI preflight + run)
20622
20646
 
20623
20647
  Usage:
@@ -20889,6 +20913,7 @@ ${tail}
20889
20913
  postIssueComment(issueNumber, body, cwd);
20890
20914
  } catch {
20891
20915
  }
20916
+ setKodyLabel(issueNumber, FAILED_DISPATCH_LABEL, cwd);
20892
20917
  }
20893
20918
  function shouldPostRunFailureTail(exitCode) {
20894
20919
  return exitCode !== 0 && exitCode !== 1 && exitCode !== 2 && exitCode !== 3;
@@ -21045,6 +21070,33 @@ async function runCi(argv) {
21045
21070
  }
21046
21071
  if (!args.issueNumber && !autoFallback && process.env.GITHUB_EVENT_NAME) {
21047
21072
  const outcome = autoDispatchTyped({ config: earlyConfig });
21073
+ if (outcome.kind === "rejected") {
21074
+ try {
21075
+ unpackAllSecrets();
21076
+ await resolveAuthToken();
21077
+ } catch {
21078
+ }
21079
+ const body = [
21080
+ `\u26A0\uFE0F kody rejected this trigger: bot-authored \`@kody ${outcome.token}\` comments cannot dispatch work.`,
21081
+ "",
21082
+ "Use workflow_dispatch or runExecutableChain for engine-owned continuation instead."
21083
+ ].join("\n");
21084
+ try {
21085
+ if (outcome.isPr) postPrReviewComment(outcome.target, body, cwd);
21086
+ else postIssueComment(outcome.target, body, cwd);
21087
+ } catch (err) {
21088
+ process.stderr.write(
21089
+ `[kody] dispatch: failed to post rejected-trigger feedback: ${err instanceof Error ? err.message : String(err)}
21090
+ `
21091
+ );
21092
+ }
21093
+ setKodyLabel(outcome.target, FAILED_DISPATCH_LABEL, cwd);
21094
+ process.stderr.write(
21095
+ `[kody] dispatch: rejected bot self-dispatch by ${outcome.author} on #${outcome.target} (${outcome.token})
21096
+ `
21097
+ );
21098
+ return 64;
21099
+ }
21048
21100
  if (outcome.kind === "unrecognized") {
21049
21101
  try {
21050
21102
  unpackAllSecrets();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.300",
3
+ "version": "0.4.302",
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",