@kody-ade/kody-engine 0.4.454 → 0.4.456

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.454",
18
+ version: "0.4.456",
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",
@@ -1770,6 +1770,7 @@ function parseWorkflowStep(value) {
1770
1770
  const evidence = stringField(raw.evidence);
1771
1771
  const reason = stringField(raw.reason);
1772
1772
  const target = stringField(raw.target);
1773
+ const delivery = stringField(raw.delivery);
1773
1774
  const targetFact = stringField(raw.targetFact ?? raw.target_fact);
1774
1775
  const hasInput = Object.hasOwn(raw, "input");
1775
1776
  const next = parseWorkflowTransitions(raw.next);
@@ -1781,6 +1782,7 @@ function parseWorkflowStep(value) {
1781
1782
  ...action && isSafeSlug(action) ? { action } : {},
1782
1783
  ...evidence ? { evidence } : {},
1783
1784
  ...target === "issue" || target === "pr" ? { target } : {},
1785
+ ...delivery === "pull-request" ? { delivery } : {},
1784
1786
  ...targetFact ? { targetFact } : {},
1785
1787
  ...reason ? { reason } : {},
1786
1788
  ...next ? { next } : {},
@@ -4212,6 +4214,24 @@ var init_agencyBoundaryEval = __esm({
4212
4214
  }
4213
4215
  });
4214
4216
 
4217
+ // src/capabilityDelivery.ts
4218
+ function capabilityDeliveryTarget(input) {
4219
+ if (!input || typeof input !== "object" || Array.isArray(input)) return null;
4220
+ const value = input;
4221
+ const issue2 = positiveInteger(value.issue);
4222
+ const pr = positiveInteger(value.pr);
4223
+ if (issue2 === null === (pr === null)) return null;
4224
+ return issue2 === null ? { kind: "pr", number: pr } : { kind: "issue", number: issue2 };
4225
+ }
4226
+ function positiveInteger(value) {
4227
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
4228
+ }
4229
+ var init_capabilityDelivery = __esm({
4230
+ "src/capabilityDelivery.ts"() {
4231
+ "use strict";
4232
+ }
4233
+ });
4234
+
4215
4235
  // src/agency/capability-contract-validation.ts
4216
4236
  import Ajv from "ajv";
4217
4237
  function validateCapabilityContractValue(boundary, schema, value) {
@@ -4350,7 +4370,7 @@ function parseGoalEvidenceProgress(value) {
4350
4370
  ...stringField2(raw.reason) ? { reason: stringField2(raw.reason) } : {},
4351
4371
  ...stringField2(raw.nextAction) ? { nextAction: stringField2(raw.nextAction) } : {},
4352
4372
  ...stringField2(raw.nextRetryAt) ? { nextRetryAt: stringField2(raw.nextRetryAt) } : {},
4353
- ...positiveInteger(raw.issue) ? { issue: positiveInteger(raw.issue) } : {},
4373
+ ...positiveInteger2(raw.issue) ? { issue: positiveInteger2(raw.issue) } : {},
4354
4374
  ...stringField2(raw.updatedAt) ? { updatedAt: stringField2(raw.updatedAt) } : {}
4355
4375
  };
4356
4376
  }
@@ -4366,7 +4386,7 @@ function definedProgressFields(update) {
4366
4386
  function stringField2(value) {
4367
4387
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
4368
4388
  }
4369
- function positiveInteger(value) {
4389
+ function positiveInteger2(value) {
4370
4390
  if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
4371
4391
  return void 0;
4372
4392
  }
@@ -8904,6 +8924,14 @@ function validateWorkflow(value, options = {}) {
8904
8924
  }
8905
8925
  }
8906
8926
  validateDataMatch(step.runWhen, `${base}.runWhen`, issues);
8927
+ if (step.delivery !== void 0 && step.delivery !== "pull-request") {
8928
+ issue(
8929
+ issues,
8930
+ "invalid_delivery",
8931
+ `${base}.delivery`,
8932
+ "workflow step delivery must be pull-request"
8933
+ );
8934
+ }
8907
8935
  if (step.input !== void 0 && !isJsonValue(step.input)) {
8908
8936
  issue(issues, "invalid_input", `${base}.input`, "workflow step input must be one JSON value");
8909
8937
  }
@@ -8919,6 +8947,7 @@ function validateWorkflow(value, options = {}) {
8919
8947
  issue(issues, "missing_start_step", "startAt", `workflow startAt references missing step ${startAt ?? "<none>"}`);
8920
8948
  }
8921
8949
  const adjacency = /* @__PURE__ */ new Map();
8950
+ const explicitEndSources = /* @__PURE__ */ new Set();
8922
8951
  steps.forEach((step, index) => {
8923
8952
  if (!step) return;
8924
8953
  const id = text(step.id);
@@ -8987,6 +9016,7 @@ function validateWorkflow(value, options = {}) {
8987
9016
  return;
8988
9017
  }
8989
9018
  if (target === "$end") {
9019
+ explicitEndSources.add(id);
8990
9020
  return;
8991
9021
  }
8992
9022
  if (!seen.has(target)) {
@@ -9041,7 +9071,7 @@ function validateWorkflow(value, options = {}) {
9041
9071
  ids.forEach((id, index) => {
9042
9072
  if (!reachable.has(id)) issue(issues, "unreachable_step", `steps[${index}]`, `workflow step ${id} is unreachable`);
9043
9073
  });
9044
- if (![...reachable].some((id) => (adjacency.get(id) ?? []).length === 0)) {
9074
+ if (![...reachable].some((id) => (adjacency.get(id) ?? []).length === 0 || explicitEndSources.has(id))) {
9045
9075
  issue(issues, "missing_terminal_step", "steps", "workflow has no reachable final step");
9046
9076
  }
9047
9077
  }
@@ -9116,6 +9146,7 @@ var init_workflowValidation = __esm({
9116
9146
  "action",
9117
9147
  "evidence",
9118
9148
  "target",
9149
+ "delivery",
9119
9150
  "targetFact",
9120
9151
  "reason",
9121
9152
  "next",
@@ -15502,6 +15533,7 @@ var init_loadSimpleCapability = __esm({
15502
15533
  const toolFiles = listFiles(toolRoot);
15503
15534
  const skillFiles = listFiles(skillRoot);
15504
15535
  const input = parseInput(ctx.args.input);
15536
+ const delivery = ctx.data.jobDelivery === "pull-request";
15505
15537
  ctx.data.jobCapability = slug;
15506
15538
  ctx.data.capabilityInput = input;
15507
15539
  ctx.data.capabilityEnvironment = capabilityEnvironment(input);
@@ -15514,7 +15546,21 @@ var init_loadSimpleCapability = __esm({
15514
15546
  JSON.stringify(input ?? null, null, 2),
15515
15547
  "```",
15516
15548
  "",
15517
- "Return one JSON value.",
15549
+ ...delivery ? [
15550
+ "## Delivery",
15551
+ "",
15552
+ "The wrapper owns git commits, pushes, and pull requests. Do not run git or gh write commands.",
15553
+ "Finish with exactly this structure:",
15554
+ "",
15555
+ "DONE",
15556
+ "PLAN_DEVIATIONS: none",
15557
+ "COMMIT_MSG: <conventional commit message>",
15558
+ "PR_SUMMARY:",
15559
+ "- <what changed>",
15560
+ "```json",
15561
+ '{"summary":"<result>","status":"changed"}',
15562
+ "```"
15563
+ ] : ["Return one JSON value."],
15518
15564
  ...skillFiles.length ? [
15519
15565
  "",
15520
15566
  "## Skills",
@@ -17924,6 +17970,208 @@ var init_prepareBrowserAuth = __esm({
17924
17970
  }
17925
17971
  });
17926
17972
 
17973
+ // src/scripts/runFlow.ts
17974
+ function tryPost(issueNumber, body, cwd) {
17975
+ try {
17976
+ postIssueComment(issueNumber, body, cwd);
17977
+ } catch {
17978
+ }
17979
+ }
17980
+ function resolveBaseOverride(value) {
17981
+ if (!value) return null;
17982
+ if (value.length > 200) return null;
17983
+ if (value.includes("..")) return null;
17984
+ if (!/^[a-z0-9][a-z0-9/._-]*$/.test(value)) return null;
17985
+ return value;
17986
+ }
17987
+ var runFlow;
17988
+ var init_runFlow = __esm({
17989
+ "src/scripts/runFlow.ts"() {
17990
+ "use strict";
17991
+ init_branch();
17992
+ init_gha();
17993
+ init_issue();
17994
+ runFlow = async (ctx) => {
17995
+ const issueNumber = ctx.args.issue;
17996
+ const issue2 = getIssue(issueNumber, ctx.cwd);
17997
+ const cfgCtx = ctx.config.issueContext ?? {};
17998
+ const commentsFormatted = formatIssueComments(
17999
+ issue2.comments,
18000
+ cfgCtx.commentLimit ?? DEFAULT_COMMENT_LIMIT,
18001
+ cfgCtx.commentMaxBytes ?? DEFAULT_COMMENT_MAX_BYTES
18002
+ );
18003
+ ctx.data.issue = { ...issue2, commentsFormatted };
18004
+ if (issue2.isPullRequest) {
18005
+ ctx.data.commentTargetType = "pr";
18006
+ ctx.data.commentTargetNumber = issueNumber;
18007
+ ctx.skipAgent = true;
18008
+ ctx.output.exitCode = 1;
18009
+ ctx.output.reason = `run target #${issueNumber} is a pull request; dispatch a PR action or the source issue instead`;
18010
+ return;
18011
+ }
18012
+ ctx.data.commentTargetType = "issue";
18013
+ ctx.data.commentTargetNumber = issueNumber;
18014
+ const argBase = resolveBaseOverride(ctx.args.base);
18015
+ const baseRaw = ctx.args.base;
18016
+ if (baseRaw && !argBase) {
18017
+ process.stderr.write(`[kody runFlow] ignoring --base "${baseRaw}" (must match kody-task or goal-branch pattern)
18018
+ `);
18019
+ }
18020
+ const base = argBase;
18021
+ if (base) {
18022
+ ctx.data.baseBranch = base;
18023
+ process.stderr.write(`[kody runFlow] resolved base branch: ${base} (from --base)
18024
+ `);
18025
+ }
18026
+ const branchInfo = ensureFeatureBranch(
18027
+ issueNumber,
18028
+ issue2.title,
18029
+ ctx.config.git.defaultBranch,
18030
+ ctx.cwd,
18031
+ base ?? void 0
18032
+ );
18033
+ ctx.data.branch = branchInfo.branch;
18034
+ const runUrl = getRunUrl();
18035
+ const startMsg = runUrl ? `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\`, run ${runUrl}` : `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\``;
18036
+ tryPost(issueNumber, startMsg, ctx.cwd);
18037
+ };
18038
+ }
18039
+ });
18040
+
18041
+ // src/scripts/syncFlow.ts
18042
+ import { execFileSync as execFileSync16 } from "child_process";
18043
+ function restoreDone(prNumber, cwd) {
18044
+ try {
18045
+ setKodyLabel(prNumber, DONE2, cwd);
18046
+ } catch {
18047
+ }
18048
+ }
18049
+ function bail2(ctx, prNumber, reason) {
18050
+ ctx.skipAgent = true;
18051
+ ctx.output.exitCode = 1;
18052
+ ctx.output.reason = reason;
18053
+ const runUrl = getRunUrl();
18054
+ const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
18055
+ tryPostPr3(prNumber, `\u274C kody sync could not complete${runSuffix}: ${reason}`, ctx.cwd);
18056
+ }
18057
+ function revParseHead(cwd) {
18058
+ try {
18059
+ return execFileSync16("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
18060
+ } catch {
18061
+ return "";
18062
+ }
18063
+ }
18064
+ function pushBranch(branch, cwd) {
18065
+ const result = pushWithRetry({ cwd: cwd ?? process.cwd(), branch, setUpstream: true });
18066
+ if (!result.ok) {
18067
+ throw new Error(result.reason);
18068
+ }
18069
+ }
18070
+ function tryPostPr3(prNumber, body, cwd) {
18071
+ try {
18072
+ postPrReviewComment(prNumber, body, cwd);
18073
+ } catch {
18074
+ }
18075
+ }
18076
+ var DONE2, syncFlow;
18077
+ var init_syncFlow = __esm({
18078
+ "src/scripts/syncFlow.ts"() {
18079
+ "use strict";
18080
+ init_branch();
18081
+ init_gha();
18082
+ init_issue();
18083
+ init_lifecycleLabels();
18084
+ init_pushWithRetry();
18085
+ DONE2 = {
18086
+ label: "kody:done",
18087
+ color: "0e8a16",
18088
+ description: "kody: PR ready for human review/merge"
18089
+ };
18090
+ syncFlow = async (ctx, _profile, args) => {
18091
+ const announceOnSuccess = Boolean(args?.announceOnSuccess);
18092
+ const prNumber = ctx.args.pr;
18093
+ const pr = getPr(prNumber, ctx.cwd);
18094
+ if (pr.state !== "OPEN") {
18095
+ bail2(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
18096
+ return;
18097
+ }
18098
+ ctx.data.pr = pr;
18099
+ if (announceOnSuccess) {
18100
+ ctx.data.commentTargetType = "pr";
18101
+ ctx.data.commentTargetNumber = prNumber;
18102
+ }
18103
+ checkoutPrBranch(prNumber, ctx.cwd);
18104
+ ctx.data.branch = getCurrentBranch(ctx.cwd);
18105
+ const baseBranch = pr.baseRefName || ctx.config.git.defaultBranch;
18106
+ ctx.data.baseBranch = baseBranch;
18107
+ const headBefore = revParseHead(ctx.cwd);
18108
+ const mergeStatus = mergeBase(baseBranch, ctx.cwd);
18109
+ if (mergeStatus === "error") {
18110
+ bail2(ctx, prNumber, `failed to merge origin/${baseBranch} (non-conflict error); see runner log`);
18111
+ return;
18112
+ }
18113
+ if (mergeStatus === "conflict") {
18114
+ bail2(
18115
+ ctx,
18116
+ prNumber,
18117
+ `merge from origin/${baseBranch} produced conflicts \u2014 run \`@kody resolve\` to let kody resolve them`
18118
+ );
18119
+ return;
18120
+ }
18121
+ const headAfter = revParseHead(ctx.cwd);
18122
+ if (headAfter === headBefore) {
18123
+ ctx.data.syncResult = "noop";
18124
+ if (announceOnSuccess) {
18125
+ ctx.output.exitCode = 0;
18126
+ ctx.output.reason = `already up to date with origin/${baseBranch}`;
18127
+ restoreDone(prNumber, ctx.cwd);
18128
+ }
18129
+ return;
18130
+ }
18131
+ try {
18132
+ pushBranch(ctx.data.branch, ctx.cwd);
18133
+ } catch (err) {
18134
+ const msg = err instanceof Error ? err.message : String(err);
18135
+ bail2(ctx, prNumber, `merge succeeded but push failed: ${msg}`);
18136
+ return;
18137
+ }
18138
+ ctx.data.syncResult = "merged";
18139
+ if (announceOnSuccess) {
18140
+ ctx.output.exitCode = 0;
18141
+ ctx.output.reason = `merged origin/${baseBranch} into ${ctx.data.branch}`;
18142
+ restoreDone(prNumber, ctx.cwd);
18143
+ }
18144
+ };
18145
+ }
18146
+ });
18147
+
18148
+ // src/scripts/prepareCapabilityDelivery.ts
18149
+ var prepareCapabilityDelivery;
18150
+ var init_prepareCapabilityDelivery = __esm({
18151
+ "src/scripts/prepareCapabilityDelivery.ts"() {
18152
+ "use strict";
18153
+ init_capabilityDelivery();
18154
+ init_runFlow();
18155
+ init_syncFlow();
18156
+ prepareCapabilityDelivery = async (ctx, profile) => {
18157
+ const target = capabilityDeliveryTarget(ctx.data.capabilityInput);
18158
+ if (!target) {
18159
+ throw new Error(
18160
+ "pull-request delivery requires exactly one positive issue or pr input"
18161
+ );
18162
+ }
18163
+ ctx.args[target.kind] = target.number;
18164
+ if (target.kind === "issue") {
18165
+ await runFlow(ctx, profile);
18166
+ return;
18167
+ }
18168
+ ctx.data.commentTargetType = "pr";
18169
+ ctx.data.commentTargetNumber = target.number;
18170
+ await syncFlow(ctx, profile);
18171
+ };
18172
+ }
18173
+ });
18174
+
17927
18175
  // src/scripts/promoteQaGoal.ts
17928
18176
  var REPORT_JSON_OPEN2, promoteQaGoal;
17929
18177
  var init_promoteQaGoal = __esm({
@@ -18079,7 +18327,7 @@ var init_publishReport = __esm({
18079
18327
  });
18080
18328
 
18081
18329
  // src/scripts/recordClassification.ts
18082
- import { execFileSync as execFileSync16 } from "child_process";
18330
+ import { execFileSync as execFileSync17 } from "child_process";
18083
18331
  function parseClassification(prSummary) {
18084
18332
  if (!prSummary) return null;
18085
18333
  const classMatch = prSummary.match(/classification:\s*(feature|bug|spec|chore)\b/i);
@@ -18091,7 +18339,7 @@ function parseClassification(prSummary) {
18091
18339
  }
18092
18340
  function tryAuditComment(issueNumber, body, cwd) {
18093
18341
  try {
18094
- execFileSync16("gh", ["issue", "comment", String(issueNumber), "--body", body], {
18342
+ execFileSync17("gh", ["issue", "comment", String(issueNumber), "--body", body], {
18095
18343
  cwd,
18096
18344
  timeout: API_TIMEOUT_MS5,
18097
18345
  stdio: ["ignore", "pipe", "pipe"]
@@ -18311,7 +18559,7 @@ var init_resolveArtifacts = __esm({
18311
18559
  });
18312
18560
 
18313
18561
  // src/scripts/resolveFlow.ts
18314
- import { execFileSync as execFileSync17 } from "child_process";
18562
+ import { execFileSync as execFileSync18 } from "child_process";
18315
18563
  function buildPreferBlock(prefer, baseBranch) {
18316
18564
  if (prefer !== "ours" && prefer !== "theirs") return "";
18317
18565
  const keepSide = prefer === "ours" ? "HEAD (this PR branch)" : `origin/${baseBranch} (base branch)`;
@@ -18331,7 +18579,7 @@ function buildPreferBlock(prefer, baseBranch) {
18331
18579
  }
18332
18580
  function getConflictedFiles(cwd) {
18333
18581
  try {
18334
- const out = execFileSync17("git", ["diff", "--name-only", "--diff-filter=U"], {
18582
+ const out = execFileSync18("git", ["diff", "--name-only", "--diff-filter=U"], {
18335
18583
  encoding: "utf-8",
18336
18584
  cwd,
18337
18585
  env: { ...process.env, HUSKY: "0" }
@@ -18346,7 +18594,7 @@ function getConflictMarkersPreview(files, cwd, maxBytes = CONFLICT_DIFF_MAX_BYTE
18346
18594
  let total = 0;
18347
18595
  for (const f of files) {
18348
18596
  try {
18349
- const content = execFileSync17("cat", [f], { encoding: "utf-8", cwd }).toString();
18597
+ const content = execFileSync18("cat", [f], { encoding: "utf-8", cwd }).toString();
18350
18598
  const snippet = `### ${f}
18351
18599
 
18352
18600
  \`\`\`
@@ -18361,7 +18609,7 @@ ${content.slice(0, 6e3)}
18361
18609
  }
18362
18610
  return chunks.join("\n");
18363
18611
  }
18364
- function tryPostPr3(prNumber, body, cwd) {
18612
+ function tryPostPr4(prNumber, body, cwd) {
18365
18613
  try {
18366
18614
  postPrReviewComment(prNumber, body, cwd);
18367
18615
  } catch {
@@ -18370,12 +18618,12 @@ function tryPostPr3(prNumber, body, cwd) {
18370
18618
  function pushEmptyCommit(branch, cwd) {
18371
18619
  const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
18372
18620
  try {
18373
- execFileSync17(
18621
+ execFileSync18(
18374
18622
  "git",
18375
18623
  ["commit", "--allow-empty", "-m", "chore: kody resolve refresh \u2014 empty commit to recompute mergeable status"],
18376
18624
  { cwd, env, stdio: ["ignore", "pipe", "pipe"] }
18377
18625
  );
18378
- execFileSync17("git", ["push", "-u", "origin", branch], {
18626
+ execFileSync18("git", ["push", "-u", "origin", branch], {
18379
18627
  cwd,
18380
18628
  env,
18381
18629
  stdio: ["ignore", "pipe", "pipe"]
@@ -18413,14 +18661,14 @@ var init_resolveFlow = __esm({
18413
18661
  ctx.output.exitCode = 0;
18414
18662
  ctx.output.reason = `PR #${prNumber} is mergeable (no conflicts) \u2014 nothing to resolve`;
18415
18663
  ctx.skipAgent = true;
18416
- tryPostPr3(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18664
+ tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18417
18665
  return;
18418
18666
  }
18419
18667
  if (ghStatus.status === "BLOCKED") {
18420
18668
  ctx.output.exitCode = 0;
18421
18669
  ctx.output.reason = `PR #${prNumber} is mergeable but blocked by checks/reviews (mergeStateStatus=${ghStatus.mergeStateStatus}) \u2014 nothing for resolve to do`;
18422
18670
  ctx.skipAgent = true;
18423
- tryPostPr3(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18671
+ tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18424
18672
  return;
18425
18673
  }
18426
18674
  checkoutPrBranch(prNumber, ctx.cwd);
@@ -18432,20 +18680,20 @@ var init_resolveFlow = __esm({
18432
18680
  ctx.output.exitCode = 0;
18433
18681
  ctx.output.reason = pushed ? `local merge clean despite GitHub reporting CONFLICTING \u2014 pushed empty commit to force re-evaluation` : `local merge clean despite GitHub reporting CONFLICTING \u2014 couldn't refresh GitHub cache (push failed)`;
18434
18682
  ctx.skipAgent = true;
18435
- tryPostPr3(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18683
+ tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18436
18684
  return;
18437
18685
  }
18438
18686
  ctx.output.exitCode = 0;
18439
18687
  ctx.output.reason = `already up to date with origin/${baseBranch} \u2014 nothing to resolve`;
18440
18688
  ctx.skipAgent = true;
18441
- tryPostPr3(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18689
+ tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
18442
18690
  return;
18443
18691
  }
18444
18692
  if (mergeStatus === "error") {
18445
18693
  ctx.output.exitCode = 99;
18446
18694
  ctx.output.reason = `failed to merge origin/${baseBranch} (non-conflict error); see runner log`;
18447
18695
  ctx.skipAgent = true;
18448
- tryPostPr3(prNumber, `\u26A0\uFE0F kody resolve FAILED: ${ctx.output.reason}`, ctx.cwd);
18696
+ tryPostPr4(prNumber, `\u26A0\uFE0F kody resolve FAILED: ${ctx.output.reason}`, ctx.cwd);
18449
18697
  return;
18450
18698
  }
18451
18699
  const conflictedFiles = getConflictedFiles(ctx.cwd);
@@ -18460,7 +18708,7 @@ var init_resolveFlow = __esm({
18460
18708
  ctx.data.preferBlock = buildPreferBlock(ctx.args.prefer, baseBranch);
18461
18709
  const runUrl = getRunUrl();
18462
18710
  const runSuffix = runUrl ? `, run ${runUrl}` : "";
18463
- tryPostPr3(
18711
+ tryPostPr4(
18464
18712
  prNumber,
18465
18713
  `\u2699\uFE0F kody resolve started on \`${ctx.data.branch}\`${runSuffix} \u2014 ${conflictedFiles.length} conflicted file(s)`,
18466
18714
  ctx.cwd
@@ -18561,10 +18809,10 @@ var init_resolvePreviewUrl = __esm({
18561
18809
  });
18562
18810
 
18563
18811
  // src/scripts/resolveQaUrl.ts
18564
- import { execFileSync as execFileSync18 } from "child_process";
18812
+ import { execFileSync as execFileSync19 } from "child_process";
18565
18813
  function ghQuery(args, cwd) {
18566
18814
  try {
18567
- const out = execFileSync18("gh", args, {
18815
+ const out = execFileSync19("gh", args, {
18568
18816
  cwd,
18569
18817
  stdio: ["ignore", "pipe", "pipe"],
18570
18818
  encoding: "utf-8",
@@ -18641,7 +18889,7 @@ var init_resolveQaUrl = __esm({
18641
18889
  });
18642
18890
 
18643
18891
  // src/scripts/revertFlow.ts
18644
- import { execFileSync as execFileSync19 } from "child_process";
18892
+ import { execFileSync as execFileSync20 } from "child_process";
18645
18893
  function buildCommitMessage(resolved) {
18646
18894
  if (resolved.length === 1) {
18647
18895
  const { full, subject } = resolved[0];
@@ -18654,7 +18902,7 @@ function buildPrSummary(resolved) {
18654
18902
  return resolved.map((r) => `- Reverted \`${r.full.slice(0, 7)}\`${r.subject ? ` \u2014 ${r.subject}` : ""}`).join("\n");
18655
18903
  }
18656
18904
  function git4(args, cwd) {
18657
- return execFileSync19("git", args, {
18905
+ return execFileSync20("git", args, {
18658
18906
  encoding: "utf-8",
18659
18907
  timeout: 3e4,
18660
18908
  cwd,
@@ -18664,7 +18912,7 @@ function git4(args, cwd) {
18664
18912
  }
18665
18913
  function isAncestorOfHead(sha, cwd) {
18666
18914
  try {
18667
- execFileSync19("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
18915
+ execFileSync20("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
18668
18916
  cwd,
18669
18917
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
18670
18918
  stdio: ["ignore", "ignore", "ignore"]
@@ -18674,7 +18922,7 @@ function isAncestorOfHead(sha, cwd) {
18674
18922
  return false;
18675
18923
  }
18676
18924
  }
18677
- function tryPostPr4(prNumber, body, cwd) {
18925
+ function tryPostPr5(prNumber, body, cwd) {
18678
18926
  try {
18679
18927
  postPrReviewComment(prNumber, body, cwd);
18680
18928
  } catch (err) {
@@ -18710,7 +18958,7 @@ var init_revertFlow = __esm({
18710
18958
  ctx.output.exitCode = 64;
18711
18959
  ctx.output.reason = "no commit SHAs provided \u2014 usage: @kody revert <sha> [<sha> \u2026]";
18712
18960
  ctx.skipAgent = true;
18713
- tryPostPr4(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18961
+ tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18714
18962
  return;
18715
18963
  }
18716
18964
  const requested = shasArg.split(/\s+/).filter((s) => s.length > 0);
@@ -18719,7 +18967,7 @@ var init_revertFlow = __esm({
18719
18967
  ctx.output.exitCode = 64;
18720
18968
  ctx.output.reason = `not valid SHA-shaped tokens: ${bad.join(", ")}`;
18721
18969
  ctx.skipAgent = true;
18722
- tryPostPr4(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18970
+ tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18723
18971
  return;
18724
18972
  }
18725
18973
  const resolved = [];
@@ -18747,7 +18995,7 @@ var init_revertFlow = __esm({
18747
18995
  ctx.output.exitCode = 64;
18748
18996
  ctx.output.reason = `commit(s) not found in this PR branch: ${unreachable.join(", ")}`;
18749
18997
  ctx.skipAgent = true;
18750
- tryPostPr4(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18998
+ tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
18751
18999
  return;
18752
19000
  }
18753
19001
  ctx.args.shas = resolved.map((r) => r.full).join(" ");
@@ -18757,13 +19005,13 @@ var init_revertFlow = __esm({
18757
19005
  const runUrl = getRunUrl();
18758
19006
  const runSuffix = runUrl ? `, run ${runUrl}` : "";
18759
19007
  const shaList = resolved.map((r) => `\`${r.full.slice(0, 7)}\``).join(", ");
18760
- tryPostPr4(prNumber, `\u2699\uFE0F kody revert started on \`${ctx.data.branch}\`${runSuffix} \u2014 reverting ${shaList}`, ctx.cwd);
19008
+ tryPostPr5(prNumber, `\u2699\uFE0F kody revert started on \`${ctx.data.branch}\`${runSuffix} \u2014 reverting ${shaList}`, ctx.cwd);
18761
19009
  };
18762
19010
  }
18763
19011
  });
18764
19012
 
18765
19013
  // src/scripts/reviewFlow.ts
18766
- function tryPostPr5(prNumber, body, cwd) {
19014
+ function tryPostPr6(prNumber, body, cwd) {
18767
19015
  try {
18768
19016
  postPrReviewComment(prNumber, body, cwd);
18769
19017
  } catch {
@@ -18793,75 +19041,7 @@ var init_reviewFlow = __esm({
18793
19041
  ctx.data.prDiff = getPrDiff(prNumber, ctx.cwd);
18794
19042
  const runUrl = getRunUrl();
18795
19043
  const runSuffix = runUrl ? `, run ${runUrl}` : "";
18796
- tryPostPr5(prNumber, `\u{1F440} kody review started on PR #${prNumber}${runSuffix}`, ctx.cwd);
18797
- };
18798
- }
18799
- });
18800
-
18801
- // src/scripts/runFlow.ts
18802
- function tryPost(issueNumber, body, cwd) {
18803
- try {
18804
- postIssueComment(issueNumber, body, cwd);
18805
- } catch {
18806
- }
18807
- }
18808
- function resolveBaseOverride(value) {
18809
- if (!value) return null;
18810
- if (value.length > 200) return null;
18811
- if (value.includes("..")) return null;
18812
- if (!/^[a-z0-9][a-z0-9/._-]*$/.test(value)) return null;
18813
- return value;
18814
- }
18815
- var runFlow;
18816
- var init_runFlow = __esm({
18817
- "src/scripts/runFlow.ts"() {
18818
- "use strict";
18819
- init_branch();
18820
- init_gha();
18821
- init_issue();
18822
- runFlow = async (ctx) => {
18823
- const issueNumber = ctx.args.issue;
18824
- const issue2 = getIssue(issueNumber, ctx.cwd);
18825
- const cfgCtx = ctx.config.issueContext ?? {};
18826
- const commentsFormatted = formatIssueComments(
18827
- issue2.comments,
18828
- cfgCtx.commentLimit ?? DEFAULT_COMMENT_LIMIT,
18829
- cfgCtx.commentMaxBytes ?? DEFAULT_COMMENT_MAX_BYTES
18830
- );
18831
- ctx.data.issue = { ...issue2, commentsFormatted };
18832
- if (issue2.isPullRequest) {
18833
- ctx.data.commentTargetType = "pr";
18834
- ctx.data.commentTargetNumber = issueNumber;
18835
- ctx.skipAgent = true;
18836
- ctx.output.exitCode = 1;
18837
- ctx.output.reason = `run target #${issueNumber} is a pull request; dispatch a PR action or the source issue instead`;
18838
- return;
18839
- }
18840
- ctx.data.commentTargetType = "issue";
18841
- ctx.data.commentTargetNumber = issueNumber;
18842
- const argBase = resolveBaseOverride(ctx.args.base);
18843
- const baseRaw = ctx.args.base;
18844
- if (baseRaw && !argBase) {
18845
- process.stderr.write(`[kody runFlow] ignoring --base "${baseRaw}" (must match kody-task or goal-branch pattern)
18846
- `);
18847
- }
18848
- const base = argBase;
18849
- if (base) {
18850
- ctx.data.baseBranch = base;
18851
- process.stderr.write(`[kody runFlow] resolved base branch: ${base} (from --base)
18852
- `);
18853
- }
18854
- const branchInfo = ensureFeatureBranch(
18855
- issueNumber,
18856
- issue2.title,
18857
- ctx.config.git.defaultBranch,
18858
- ctx.cwd,
18859
- base ?? void 0
18860
- );
18861
- ctx.data.branch = branchInfo.branch;
18862
- const runUrl = getRunUrl();
18863
- const startMsg = runUrl ? `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\`, run ${runUrl}` : `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\``;
18864
- tryPost(issueNumber, startMsg, ctx.cwd);
19044
+ tryPostPr6(prNumber, `\u{1F440} kody review started on PR #${prNumber}${runSuffix}`, ctx.cwd);
18865
19045
  };
18866
19046
  }
18867
19047
  });
@@ -19631,7 +19811,7 @@ var init_skipAgent = __esm({
19631
19811
  });
19632
19812
 
19633
19813
  // src/scripts/stageMergeConflicts.ts
19634
- import { execFileSync as execFileSync20 } from "child_process";
19814
+ import { execFileSync as execFileSync21 } from "child_process";
19635
19815
  var stageMergeConflicts;
19636
19816
  var init_stageMergeConflicts = __esm({
19637
19817
  "src/scripts/stageMergeConflicts.ts"() {
@@ -19639,7 +19819,7 @@ var init_stageMergeConflicts = __esm({
19639
19819
  stageMergeConflicts = async (ctx) => {
19640
19820
  if (ctx.data.agentDone === false) return;
19641
19821
  try {
19642
- execFileSync20("git", ["add", "-A"], {
19822
+ execFileSync21("git", ["add", "-A"], {
19643
19823
  cwd: ctx.cwd,
19644
19824
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
19645
19825
  stdio: "pipe"
@@ -19692,113 +19872,6 @@ var init_startFlow = __esm({
19692
19872
  }
19693
19873
  });
19694
19874
 
19695
- // src/scripts/syncFlow.ts
19696
- import { execFileSync as execFileSync21 } from "child_process";
19697
- function restoreDone(prNumber, cwd) {
19698
- try {
19699
- setKodyLabel(prNumber, DONE2, cwd);
19700
- } catch {
19701
- }
19702
- }
19703
- function bail2(ctx, prNumber, reason) {
19704
- ctx.skipAgent = true;
19705
- ctx.output.exitCode = 1;
19706
- ctx.output.reason = reason;
19707
- const runUrl = getRunUrl();
19708
- const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
19709
- tryPostPr6(prNumber, `\u274C kody sync could not complete${runSuffix}: ${reason}`, ctx.cwd);
19710
- }
19711
- function revParseHead(cwd) {
19712
- try {
19713
- return execFileSync21("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
19714
- } catch {
19715
- return "";
19716
- }
19717
- }
19718
- function pushBranch(branch, cwd) {
19719
- const result = pushWithRetry({ cwd: cwd ?? process.cwd(), branch, setUpstream: true });
19720
- if (!result.ok) {
19721
- throw new Error(result.reason);
19722
- }
19723
- }
19724
- function tryPostPr6(prNumber, body, cwd) {
19725
- try {
19726
- postPrReviewComment(prNumber, body, cwd);
19727
- } catch {
19728
- }
19729
- }
19730
- var DONE2, syncFlow;
19731
- var init_syncFlow = __esm({
19732
- "src/scripts/syncFlow.ts"() {
19733
- "use strict";
19734
- init_branch();
19735
- init_gha();
19736
- init_issue();
19737
- init_lifecycleLabels();
19738
- init_pushWithRetry();
19739
- DONE2 = {
19740
- label: "kody:done",
19741
- color: "0e8a16",
19742
- description: "kody: PR ready for human review/merge"
19743
- };
19744
- syncFlow = async (ctx, _profile, args) => {
19745
- const announceOnSuccess = Boolean(args?.announceOnSuccess);
19746
- const prNumber = ctx.args.pr;
19747
- const pr = getPr(prNumber, ctx.cwd);
19748
- if (pr.state !== "OPEN") {
19749
- bail2(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
19750
- return;
19751
- }
19752
- ctx.data.pr = pr;
19753
- if (announceOnSuccess) {
19754
- ctx.data.commentTargetType = "pr";
19755
- ctx.data.commentTargetNumber = prNumber;
19756
- }
19757
- checkoutPrBranch(prNumber, ctx.cwd);
19758
- ctx.data.branch = getCurrentBranch(ctx.cwd);
19759
- const baseBranch = pr.baseRefName || ctx.config.git.defaultBranch;
19760
- ctx.data.baseBranch = baseBranch;
19761
- const headBefore = revParseHead(ctx.cwd);
19762
- const mergeStatus = mergeBase(baseBranch, ctx.cwd);
19763
- if (mergeStatus === "error") {
19764
- bail2(ctx, prNumber, `failed to merge origin/${baseBranch} (non-conflict error); see runner log`);
19765
- return;
19766
- }
19767
- if (mergeStatus === "conflict") {
19768
- bail2(
19769
- ctx,
19770
- prNumber,
19771
- `merge from origin/${baseBranch} produced conflicts \u2014 run \`@kody resolve\` to let kody resolve them`
19772
- );
19773
- return;
19774
- }
19775
- const headAfter = revParseHead(ctx.cwd);
19776
- if (headAfter === headBefore) {
19777
- ctx.data.syncResult = "noop";
19778
- if (announceOnSuccess) {
19779
- ctx.output.exitCode = 0;
19780
- ctx.output.reason = `already up to date with origin/${baseBranch}`;
19781
- restoreDone(prNumber, ctx.cwd);
19782
- }
19783
- return;
19784
- }
19785
- try {
19786
- pushBranch(ctx.data.branch, ctx.cwd);
19787
- } catch (err) {
19788
- const msg = err instanceof Error ? err.message : String(err);
19789
- bail2(ctx, prNumber, `merge succeeded but push failed: ${msg}`);
19790
- return;
19791
- }
19792
- ctx.data.syncResult = "merged";
19793
- if (announceOnSuccess) {
19794
- ctx.output.exitCode = 0;
19795
- ctx.output.reason = `merged origin/${baseBranch} into ${ctx.data.branch}`;
19796
- restoreDone(prNumber, ctx.cwd);
19797
- }
19798
- };
19799
- }
19800
- });
19801
-
19802
19875
  // src/scripts/validateAgencyModelProposal.ts
19803
19876
  import * as path46 from "path";
19804
19877
  function validateModelBundle(bundle, expectedKind, options = {}) {
@@ -20880,6 +20953,7 @@ var init_scripts = __esm({
20880
20953
  init_postResearchComment();
20881
20954
  init_postReviewResult();
20882
20955
  init_prepareBrowserAuth();
20956
+ init_prepareCapabilityDelivery();
20883
20957
  init_promoteQaGoal();
20884
20958
  init_publishReport();
20885
20959
  init_recordClassification();
@@ -20941,6 +21015,7 @@ var init_scripts = __esm({
20941
21015
  loadPriorArt,
20942
21016
  loadQaContext,
20943
21017
  prepareBrowserAuth,
21018
+ prepareCapabilityDelivery,
20944
21019
  buildSyntheticPlugin,
20945
21020
  resolveArtifacts,
20946
21021
  discoverQaContext,
@@ -22301,6 +22376,9 @@ function validateJob(input) {
22301
22376
  if (j.cliArgs !== void 0 && (typeof j.cliArgs !== "object" || j.cliArgs === null)) {
22302
22377
  throw new InvalidJobError("job.cliArgs must be an object when present");
22303
22378
  }
22379
+ if (j.delivery !== void 0 && j.delivery !== "pull-request") {
22380
+ throw new InvalidJobError(`job.delivery must be "pull-request" (got ${String(j.delivery)})`);
22381
+ }
22304
22382
  return {
22305
22383
  action: typeof j.action === "string" ? j.action : void 0,
22306
22384
  implementation: typeof j.implementation === "string" ? j.implementation : void 0,
@@ -22310,6 +22388,7 @@ function validateJob(input) {
22310
22388
  agent: typeof j.agent === "string" ? j.agent : void 0,
22311
22389
  schedule: typeof j.schedule === "string" ? j.schedule : void 0,
22312
22390
  target: typeof j.target === "number" ? j.target : void 0,
22391
+ delivery: j.delivery === "pull-request" ? j.delivery : void 0,
22313
22392
  cliArgs: j.cliArgs ?? {},
22314
22393
  workflowFacts: j.workflowFacts && typeof j.workflowFacts === "object" && !Array.isArray(j.workflowFacts) ? j.workflowFacts : void 0,
22315
22394
  workflowState: parseWorkflowRunState(j.workflowState) ?? void 0,
@@ -22362,7 +22441,7 @@ async function runJob(job, base) {
22362
22441
  }
22363
22442
  const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
22364
22443
  const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
22365
- const capabilitySelectedImplementation = resolvedCapability?.implementation ?? capabilityContext?.config.implementation ?? capabilityContext?.config.implementations?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
22444
+ const capabilitySelectedImplementation = valid.delivery === "pull-request" && resolvedCapability?.implementation === "capability-run" ? "capability-delivery" : resolvedCapability?.implementation ?? capabilityContext?.config.implementation ?? capabilityContext?.config.implementations?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
22366
22445
  const profileName = explicitImplementation ?? capabilitySelectedImplementation;
22367
22446
  if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedImplementation, base)) {
22368
22447
  const workflowCapability = capabilityContext ?? workflowContext;
@@ -22452,6 +22531,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
22452
22531
  preloadedData.jobKey = stableJobKey(valid);
22453
22532
  preloadedData.jobFlavor = valid.flavor;
22454
22533
  if (valid.target !== void 0) preloadedData.jobTarget = valid.target;
22534
+ if (valid.delivery !== void 0) preloadedData.jobDelivery = valid.delivery;
22455
22535
  if (valid.action !== void 0 && valid.action.length > 0) preloadedData.jobAction = valid.action;
22456
22536
  if (capabilityIdentity !== void 0 && capabilityIdentity.length > 0)
22457
22537
  preloadedData.jobCapability = capabilityIdentity;
@@ -22491,11 +22571,13 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
22491
22571
  };
22492
22572
  const shouldApplyResolvedCapabilityArgs = valid.implementation === void 0 && resolvedCapability && profileName === resolvedCapability.implementation;
22493
22573
  input.cliArgs = shouldApplyResolvedCapabilityArgs ? { ...resolvedCapability.cliArgs, ...input.cliArgs } : input.cliArgs;
22494
- if (profileName === "capability-run" && capabilityIdentity) {
22574
+ if ((profileName === "capability-run" || profileName === "capability-delivery") && capabilityIdentity) {
22495
22575
  const capabilityInput = Object.keys(valid.cliArgs).length > 0 ? genericInputFromArgs(valid.cliArgs) : void 0;
22576
+ const deliveryTarget = profileName === "capability-delivery" && capabilityInput && typeof capabilityInput === "object" ? capabilityDeliveryArgs(capabilityInput) : {};
22496
22577
  input.cliArgs = {
22497
22578
  capability: capabilityIdentity,
22498
- ...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {}
22579
+ ...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {},
22580
+ ...deliveryTarget
22499
22581
  };
22500
22582
  }
22501
22583
  const run = base.chain === false ? runImplementation : runImplementationChain;
@@ -22852,6 +22934,7 @@ function workflowStepToJob(step, parent, chainData, cwd) {
22852
22934
  ...parent.agent ? { agent: parent.agent } : {},
22853
22935
  ...parent.schedule ? { schedule: parent.schedule } : {},
22854
22936
  ...typeof target === "number" ? { target } : {},
22937
+ ...step.delivery ? { delivery: step.delivery } : {},
22855
22938
  cliArgs,
22856
22939
  ...step.evidence ? { evidence: step.evidence } : parent.evidence ? { evidence: parent.evidence } : {},
22857
22940
  flavor: parent.flavor,
@@ -22861,6 +22944,10 @@ function workflowStepToJob(step, parent, chainData, cwd) {
22861
22944
  ...parent.resultTarget ? { resultTarget: parent.resultTarget } : {}
22862
22945
  };
22863
22946
  }
22947
+ function capabilityDeliveryArgs(input) {
22948
+ const target = capabilityDeliveryTarget(input);
22949
+ return target ? { [target.kind]: target.number } : {};
22950
+ }
22864
22951
  function usesGenericCapabilityInput(action, cwd) {
22865
22952
  const inputs = getCapabilityActionInputs(action, hydratedCapabilitiesRoot(cwd));
22866
22953
  return Boolean(inputs?.length === 1 && inputs[0]?.name === "input" && inputs[0]?.flag === "--input");
@@ -23025,6 +23112,7 @@ var init_job = __esm({
23025
23112
  "src/job.ts"() {
23026
23113
  "use strict";
23027
23114
  init_agencyBoundaryEval();
23115
+ init_capabilityDelivery();
23028
23116
  init_capabilityFolders();
23029
23117
  init_definition_paths();
23030
23118
  init_executor();
@@ -569,6 +569,8 @@ export interface Job {
569
569
  schedule?: string
570
570
  /** The issue/PR number this job acts on, when applicable. */
571
571
  target?: number
572
+ /** Workflow-owned delivery policy applied by a generic runtime adapter. */
573
+ delivery?: "pull-request"
572
574
  /** Args passed through to the implementation (mirrors DispatchResult.cliArgs). */
573
575
  cliArgs: Record<string, unknown>
574
576
  /** Internal workflow resume context. Not passed to capability CLI args. */
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "capability-delivery",
3
+ "internal": true,
4
+ "role": "primitive",
5
+ "kind": "oneshot",
6
+ "inputs": [
7
+ {
8
+ "name": "capability",
9
+ "flag": "--capability",
10
+ "type": "string",
11
+ "required": true,
12
+ "describe": "Capability folder slug."
13
+ },
14
+ {
15
+ "name": "input",
16
+ "flag": "--input",
17
+ "type": "string",
18
+ "required": false,
19
+ "describe": "The capability's one JSON input."
20
+ },
21
+ {
22
+ "name": "issue",
23
+ "flag": "--issue",
24
+ "type": "int",
25
+ "required": false,
26
+ "describe": "Issue receiving a new pull request."
27
+ },
28
+ {
29
+ "name": "pr",
30
+ "flag": "--pr",
31
+ "type": "int",
32
+ "required": false,
33
+ "describe": "Existing pull request receiving changes."
34
+ }
35
+ ],
36
+ "claudeCode": {
37
+ "model": "inherit",
38
+ "permissionMode": "acceptEdits",
39
+ "maxTurns": 60,
40
+ "maxThinkingTokens": null,
41
+ "systemPromptAppend": null,
42
+ "enableVerifyTool": true,
43
+ "verifyAttempts": 4,
44
+ "tools": [
45
+ "Read",
46
+ "Write",
47
+ "Edit",
48
+ "Bash",
49
+ "Grep",
50
+ "Glob",
51
+ "mcp__kody-verify"
52
+ ],
53
+ "hooks": ["block-git"],
54
+ "skills": [],
55
+ "commands": [],
56
+ "subagents": [],
57
+ "plugins": [],
58
+ "mcpServers": []
59
+ },
60
+ "cliTools": [],
61
+ "lifecycle": "pr-branch",
62
+ "lifecycleConfig": {
63
+ "label": {
64
+ "name": "kody:working",
65
+ "color": "fbca04",
66
+ "description": "kody: delivering capability work"
67
+ },
68
+ "context": "task",
69
+ "sync": false,
70
+ "advance": false,
71
+ "mirrorState": false,
72
+ "finalize": false
73
+ },
74
+ "scripts": {
75
+ "preflight": [
76
+ { "script": "loadSimpleCapability" },
77
+ { "script": "prepareCapabilityDelivery" }
78
+ ],
79
+ "postflight": [
80
+ { "script": "parseSimpleCapabilityOutput" }
81
+ ]
82
+ },
83
+ "inputArtifacts": [],
84
+ "outputArtifacts": []
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.454",
3
+ "version": "0.4.456",
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",