@kody-ade/kody-engine 0.4.455 → 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.
|
|
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
|
-
...
|
|
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
|
|
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
|
}
|
|
@@ -9118,6 +9146,7 @@ var init_workflowValidation = __esm({
|
|
|
9118
9146
|
"action",
|
|
9119
9147
|
"evidence",
|
|
9120
9148
|
"target",
|
|
9149
|
+
"delivery",
|
|
9121
9150
|
"targetFact",
|
|
9122
9151
|
"reason",
|
|
9123
9152
|
"next",
|
|
@@ -15504,6 +15533,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
15504
15533
|
const toolFiles = listFiles(toolRoot);
|
|
15505
15534
|
const skillFiles = listFiles(skillRoot);
|
|
15506
15535
|
const input = parseInput(ctx.args.input);
|
|
15536
|
+
const delivery = ctx.data.jobDelivery === "pull-request";
|
|
15507
15537
|
ctx.data.jobCapability = slug;
|
|
15508
15538
|
ctx.data.capabilityInput = input;
|
|
15509
15539
|
ctx.data.capabilityEnvironment = capabilityEnvironment(input);
|
|
@@ -15516,7 +15546,21 @@ var init_loadSimpleCapability = __esm({
|
|
|
15516
15546
|
JSON.stringify(input ?? null, null, 2),
|
|
15517
15547
|
"```",
|
|
15518
15548
|
"",
|
|
15519
|
-
|
|
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."],
|
|
15520
15564
|
...skillFiles.length ? [
|
|
15521
15565
|
"",
|
|
15522
15566
|
"## Skills",
|
|
@@ -17926,6 +17970,208 @@ var init_prepareBrowserAuth = __esm({
|
|
|
17926
17970
|
}
|
|
17927
17971
|
});
|
|
17928
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
|
+
|
|
17929
18175
|
// src/scripts/promoteQaGoal.ts
|
|
17930
18176
|
var REPORT_JSON_OPEN2, promoteQaGoal;
|
|
17931
18177
|
var init_promoteQaGoal = __esm({
|
|
@@ -18081,7 +18327,7 @@ var init_publishReport = __esm({
|
|
|
18081
18327
|
});
|
|
18082
18328
|
|
|
18083
18329
|
// src/scripts/recordClassification.ts
|
|
18084
|
-
import { execFileSync as
|
|
18330
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
18085
18331
|
function parseClassification(prSummary) {
|
|
18086
18332
|
if (!prSummary) return null;
|
|
18087
18333
|
const classMatch = prSummary.match(/classification:\s*(feature|bug|spec|chore)\b/i);
|
|
@@ -18093,7 +18339,7 @@ function parseClassification(prSummary) {
|
|
|
18093
18339
|
}
|
|
18094
18340
|
function tryAuditComment(issueNumber, body, cwd) {
|
|
18095
18341
|
try {
|
|
18096
|
-
|
|
18342
|
+
execFileSync17("gh", ["issue", "comment", String(issueNumber), "--body", body], {
|
|
18097
18343
|
cwd,
|
|
18098
18344
|
timeout: API_TIMEOUT_MS5,
|
|
18099
18345
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18313,7 +18559,7 @@ var init_resolveArtifacts = __esm({
|
|
|
18313
18559
|
});
|
|
18314
18560
|
|
|
18315
18561
|
// src/scripts/resolveFlow.ts
|
|
18316
|
-
import { execFileSync as
|
|
18562
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
18317
18563
|
function buildPreferBlock(prefer, baseBranch) {
|
|
18318
18564
|
if (prefer !== "ours" && prefer !== "theirs") return "";
|
|
18319
18565
|
const keepSide = prefer === "ours" ? "HEAD (this PR branch)" : `origin/${baseBranch} (base branch)`;
|
|
@@ -18333,7 +18579,7 @@ function buildPreferBlock(prefer, baseBranch) {
|
|
|
18333
18579
|
}
|
|
18334
18580
|
function getConflictedFiles(cwd) {
|
|
18335
18581
|
try {
|
|
18336
|
-
const out =
|
|
18582
|
+
const out = execFileSync18("git", ["diff", "--name-only", "--diff-filter=U"], {
|
|
18337
18583
|
encoding: "utf-8",
|
|
18338
18584
|
cwd,
|
|
18339
18585
|
env: { ...process.env, HUSKY: "0" }
|
|
@@ -18348,7 +18594,7 @@ function getConflictMarkersPreview(files, cwd, maxBytes = CONFLICT_DIFF_MAX_BYTE
|
|
|
18348
18594
|
let total = 0;
|
|
18349
18595
|
for (const f of files) {
|
|
18350
18596
|
try {
|
|
18351
|
-
const content =
|
|
18597
|
+
const content = execFileSync18("cat", [f], { encoding: "utf-8", cwd }).toString();
|
|
18352
18598
|
const snippet = `### ${f}
|
|
18353
18599
|
|
|
18354
18600
|
\`\`\`
|
|
@@ -18363,7 +18609,7 @@ ${content.slice(0, 6e3)}
|
|
|
18363
18609
|
}
|
|
18364
18610
|
return chunks.join("\n");
|
|
18365
18611
|
}
|
|
18366
|
-
function
|
|
18612
|
+
function tryPostPr4(prNumber, body, cwd) {
|
|
18367
18613
|
try {
|
|
18368
18614
|
postPrReviewComment(prNumber, body, cwd);
|
|
18369
18615
|
} catch {
|
|
@@ -18372,12 +18618,12 @@ function tryPostPr3(prNumber, body, cwd) {
|
|
|
18372
18618
|
function pushEmptyCommit(branch, cwd) {
|
|
18373
18619
|
const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
|
|
18374
18620
|
try {
|
|
18375
|
-
|
|
18621
|
+
execFileSync18(
|
|
18376
18622
|
"git",
|
|
18377
18623
|
["commit", "--allow-empty", "-m", "chore: kody resolve refresh \u2014 empty commit to recompute mergeable status"],
|
|
18378
18624
|
{ cwd, env, stdio: ["ignore", "pipe", "pipe"] }
|
|
18379
18625
|
);
|
|
18380
|
-
|
|
18626
|
+
execFileSync18("git", ["push", "-u", "origin", branch], {
|
|
18381
18627
|
cwd,
|
|
18382
18628
|
env,
|
|
18383
18629
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18415,14 +18661,14 @@ var init_resolveFlow = __esm({
|
|
|
18415
18661
|
ctx.output.exitCode = 0;
|
|
18416
18662
|
ctx.output.reason = `PR #${prNumber} is mergeable (no conflicts) \u2014 nothing to resolve`;
|
|
18417
18663
|
ctx.skipAgent = true;
|
|
18418
|
-
|
|
18664
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18419
18665
|
return;
|
|
18420
18666
|
}
|
|
18421
18667
|
if (ghStatus.status === "BLOCKED") {
|
|
18422
18668
|
ctx.output.exitCode = 0;
|
|
18423
18669
|
ctx.output.reason = `PR #${prNumber} is mergeable but blocked by checks/reviews (mergeStateStatus=${ghStatus.mergeStateStatus}) \u2014 nothing for resolve to do`;
|
|
18424
18670
|
ctx.skipAgent = true;
|
|
18425
|
-
|
|
18671
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18426
18672
|
return;
|
|
18427
18673
|
}
|
|
18428
18674
|
checkoutPrBranch(prNumber, ctx.cwd);
|
|
@@ -18434,20 +18680,20 @@ var init_resolveFlow = __esm({
|
|
|
18434
18680
|
ctx.output.exitCode = 0;
|
|
18435
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)`;
|
|
18436
18682
|
ctx.skipAgent = true;
|
|
18437
|
-
|
|
18683
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18438
18684
|
return;
|
|
18439
18685
|
}
|
|
18440
18686
|
ctx.output.exitCode = 0;
|
|
18441
18687
|
ctx.output.reason = `already up to date with origin/${baseBranch} \u2014 nothing to resolve`;
|
|
18442
18688
|
ctx.skipAgent = true;
|
|
18443
|
-
|
|
18689
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18444
18690
|
return;
|
|
18445
18691
|
}
|
|
18446
18692
|
if (mergeStatus === "error") {
|
|
18447
18693
|
ctx.output.exitCode = 99;
|
|
18448
18694
|
ctx.output.reason = `failed to merge origin/${baseBranch} (non-conflict error); see runner log`;
|
|
18449
18695
|
ctx.skipAgent = true;
|
|
18450
|
-
|
|
18696
|
+
tryPostPr4(prNumber, `\u26A0\uFE0F kody resolve FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18451
18697
|
return;
|
|
18452
18698
|
}
|
|
18453
18699
|
const conflictedFiles = getConflictedFiles(ctx.cwd);
|
|
@@ -18462,7 +18708,7 @@ var init_resolveFlow = __esm({
|
|
|
18462
18708
|
ctx.data.preferBlock = buildPreferBlock(ctx.args.prefer, baseBranch);
|
|
18463
18709
|
const runUrl = getRunUrl();
|
|
18464
18710
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18465
|
-
|
|
18711
|
+
tryPostPr4(
|
|
18466
18712
|
prNumber,
|
|
18467
18713
|
`\u2699\uFE0F kody resolve started on \`${ctx.data.branch}\`${runSuffix} \u2014 ${conflictedFiles.length} conflicted file(s)`,
|
|
18468
18714
|
ctx.cwd
|
|
@@ -18563,10 +18809,10 @@ var init_resolvePreviewUrl = __esm({
|
|
|
18563
18809
|
});
|
|
18564
18810
|
|
|
18565
18811
|
// src/scripts/resolveQaUrl.ts
|
|
18566
|
-
import { execFileSync as
|
|
18812
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
18567
18813
|
function ghQuery(args, cwd) {
|
|
18568
18814
|
try {
|
|
18569
|
-
const out =
|
|
18815
|
+
const out = execFileSync19("gh", args, {
|
|
18570
18816
|
cwd,
|
|
18571
18817
|
stdio: ["ignore", "pipe", "pipe"],
|
|
18572
18818
|
encoding: "utf-8",
|
|
@@ -18643,7 +18889,7 @@ var init_resolveQaUrl = __esm({
|
|
|
18643
18889
|
});
|
|
18644
18890
|
|
|
18645
18891
|
// src/scripts/revertFlow.ts
|
|
18646
|
-
import { execFileSync as
|
|
18892
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
18647
18893
|
function buildCommitMessage(resolved) {
|
|
18648
18894
|
if (resolved.length === 1) {
|
|
18649
18895
|
const { full, subject } = resolved[0];
|
|
@@ -18656,7 +18902,7 @@ function buildPrSummary(resolved) {
|
|
|
18656
18902
|
return resolved.map((r) => `- Reverted \`${r.full.slice(0, 7)}\`${r.subject ? ` \u2014 ${r.subject}` : ""}`).join("\n");
|
|
18657
18903
|
}
|
|
18658
18904
|
function git4(args, cwd) {
|
|
18659
|
-
return
|
|
18905
|
+
return execFileSync20("git", args, {
|
|
18660
18906
|
encoding: "utf-8",
|
|
18661
18907
|
timeout: 3e4,
|
|
18662
18908
|
cwd,
|
|
@@ -18666,7 +18912,7 @@ function git4(args, cwd) {
|
|
|
18666
18912
|
}
|
|
18667
18913
|
function isAncestorOfHead(sha, cwd) {
|
|
18668
18914
|
try {
|
|
18669
|
-
|
|
18915
|
+
execFileSync20("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
|
|
18670
18916
|
cwd,
|
|
18671
18917
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
18672
18918
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -18676,7 +18922,7 @@ function isAncestorOfHead(sha, cwd) {
|
|
|
18676
18922
|
return false;
|
|
18677
18923
|
}
|
|
18678
18924
|
}
|
|
18679
|
-
function
|
|
18925
|
+
function tryPostPr5(prNumber, body, cwd) {
|
|
18680
18926
|
try {
|
|
18681
18927
|
postPrReviewComment(prNumber, body, cwd);
|
|
18682
18928
|
} catch (err) {
|
|
@@ -18712,7 +18958,7 @@ var init_revertFlow = __esm({
|
|
|
18712
18958
|
ctx.output.exitCode = 64;
|
|
18713
18959
|
ctx.output.reason = "no commit SHAs provided \u2014 usage: @kody revert <sha> [<sha> \u2026]";
|
|
18714
18960
|
ctx.skipAgent = true;
|
|
18715
|
-
|
|
18961
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18716
18962
|
return;
|
|
18717
18963
|
}
|
|
18718
18964
|
const requested = shasArg.split(/\s+/).filter((s) => s.length > 0);
|
|
@@ -18721,7 +18967,7 @@ var init_revertFlow = __esm({
|
|
|
18721
18967
|
ctx.output.exitCode = 64;
|
|
18722
18968
|
ctx.output.reason = `not valid SHA-shaped tokens: ${bad.join(", ")}`;
|
|
18723
18969
|
ctx.skipAgent = true;
|
|
18724
|
-
|
|
18970
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18725
18971
|
return;
|
|
18726
18972
|
}
|
|
18727
18973
|
const resolved = [];
|
|
@@ -18749,7 +18995,7 @@ var init_revertFlow = __esm({
|
|
|
18749
18995
|
ctx.output.exitCode = 64;
|
|
18750
18996
|
ctx.output.reason = `commit(s) not found in this PR branch: ${unreachable.join(", ")}`;
|
|
18751
18997
|
ctx.skipAgent = true;
|
|
18752
|
-
|
|
18998
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18753
18999
|
return;
|
|
18754
19000
|
}
|
|
18755
19001
|
ctx.args.shas = resolved.map((r) => r.full).join(" ");
|
|
@@ -18759,13 +19005,13 @@ var init_revertFlow = __esm({
|
|
|
18759
19005
|
const runUrl = getRunUrl();
|
|
18760
19006
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18761
19007
|
const shaList = resolved.map((r) => `\`${r.full.slice(0, 7)}\``).join(", ");
|
|
18762
|
-
|
|
19008
|
+
tryPostPr5(prNumber, `\u2699\uFE0F kody revert started on \`${ctx.data.branch}\`${runSuffix} \u2014 reverting ${shaList}`, ctx.cwd);
|
|
18763
19009
|
};
|
|
18764
19010
|
}
|
|
18765
19011
|
});
|
|
18766
19012
|
|
|
18767
19013
|
// src/scripts/reviewFlow.ts
|
|
18768
|
-
function
|
|
19014
|
+
function tryPostPr6(prNumber, body, cwd) {
|
|
18769
19015
|
try {
|
|
18770
19016
|
postPrReviewComment(prNumber, body, cwd);
|
|
18771
19017
|
} catch {
|
|
@@ -18795,75 +19041,7 @@ var init_reviewFlow = __esm({
|
|
|
18795
19041
|
ctx.data.prDiff = getPrDiff(prNumber, ctx.cwd);
|
|
18796
19042
|
const runUrl = getRunUrl();
|
|
18797
19043
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18798
|
-
|
|
18799
|
-
};
|
|
18800
|
-
}
|
|
18801
|
-
});
|
|
18802
|
-
|
|
18803
|
-
// src/scripts/runFlow.ts
|
|
18804
|
-
function tryPost(issueNumber, body, cwd) {
|
|
18805
|
-
try {
|
|
18806
|
-
postIssueComment(issueNumber, body, cwd);
|
|
18807
|
-
} catch {
|
|
18808
|
-
}
|
|
18809
|
-
}
|
|
18810
|
-
function resolveBaseOverride(value) {
|
|
18811
|
-
if (!value) return null;
|
|
18812
|
-
if (value.length > 200) return null;
|
|
18813
|
-
if (value.includes("..")) return null;
|
|
18814
|
-
if (!/^[a-z0-9][a-z0-9/._-]*$/.test(value)) return null;
|
|
18815
|
-
return value;
|
|
18816
|
-
}
|
|
18817
|
-
var runFlow;
|
|
18818
|
-
var init_runFlow = __esm({
|
|
18819
|
-
"src/scripts/runFlow.ts"() {
|
|
18820
|
-
"use strict";
|
|
18821
|
-
init_branch();
|
|
18822
|
-
init_gha();
|
|
18823
|
-
init_issue();
|
|
18824
|
-
runFlow = async (ctx) => {
|
|
18825
|
-
const issueNumber = ctx.args.issue;
|
|
18826
|
-
const issue2 = getIssue(issueNumber, ctx.cwd);
|
|
18827
|
-
const cfgCtx = ctx.config.issueContext ?? {};
|
|
18828
|
-
const commentsFormatted = formatIssueComments(
|
|
18829
|
-
issue2.comments,
|
|
18830
|
-
cfgCtx.commentLimit ?? DEFAULT_COMMENT_LIMIT,
|
|
18831
|
-
cfgCtx.commentMaxBytes ?? DEFAULT_COMMENT_MAX_BYTES
|
|
18832
|
-
);
|
|
18833
|
-
ctx.data.issue = { ...issue2, commentsFormatted };
|
|
18834
|
-
if (issue2.isPullRequest) {
|
|
18835
|
-
ctx.data.commentTargetType = "pr";
|
|
18836
|
-
ctx.data.commentTargetNumber = issueNumber;
|
|
18837
|
-
ctx.skipAgent = true;
|
|
18838
|
-
ctx.output.exitCode = 1;
|
|
18839
|
-
ctx.output.reason = `run target #${issueNumber} is a pull request; dispatch a PR action or the source issue instead`;
|
|
18840
|
-
return;
|
|
18841
|
-
}
|
|
18842
|
-
ctx.data.commentTargetType = "issue";
|
|
18843
|
-
ctx.data.commentTargetNumber = issueNumber;
|
|
18844
|
-
const argBase = resolveBaseOverride(ctx.args.base);
|
|
18845
|
-
const baseRaw = ctx.args.base;
|
|
18846
|
-
if (baseRaw && !argBase) {
|
|
18847
|
-
process.stderr.write(`[kody runFlow] ignoring --base "${baseRaw}" (must match kody-task or goal-branch pattern)
|
|
18848
|
-
`);
|
|
18849
|
-
}
|
|
18850
|
-
const base = argBase;
|
|
18851
|
-
if (base) {
|
|
18852
|
-
ctx.data.baseBranch = base;
|
|
18853
|
-
process.stderr.write(`[kody runFlow] resolved base branch: ${base} (from --base)
|
|
18854
|
-
`);
|
|
18855
|
-
}
|
|
18856
|
-
const branchInfo = ensureFeatureBranch(
|
|
18857
|
-
issueNumber,
|
|
18858
|
-
issue2.title,
|
|
18859
|
-
ctx.config.git.defaultBranch,
|
|
18860
|
-
ctx.cwd,
|
|
18861
|
-
base ?? void 0
|
|
18862
|
-
);
|
|
18863
|
-
ctx.data.branch = branchInfo.branch;
|
|
18864
|
-
const runUrl = getRunUrl();
|
|
18865
|
-
const startMsg = runUrl ? `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\`, run ${runUrl}` : `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\``;
|
|
18866
|
-
tryPost(issueNumber, startMsg, ctx.cwd);
|
|
19044
|
+
tryPostPr6(prNumber, `\u{1F440} kody review started on PR #${prNumber}${runSuffix}`, ctx.cwd);
|
|
18867
19045
|
};
|
|
18868
19046
|
}
|
|
18869
19047
|
});
|
|
@@ -19633,7 +19811,7 @@ var init_skipAgent = __esm({
|
|
|
19633
19811
|
});
|
|
19634
19812
|
|
|
19635
19813
|
// src/scripts/stageMergeConflicts.ts
|
|
19636
|
-
import { execFileSync as
|
|
19814
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
19637
19815
|
var stageMergeConflicts;
|
|
19638
19816
|
var init_stageMergeConflicts = __esm({
|
|
19639
19817
|
"src/scripts/stageMergeConflicts.ts"() {
|
|
@@ -19641,7 +19819,7 @@ var init_stageMergeConflicts = __esm({
|
|
|
19641
19819
|
stageMergeConflicts = async (ctx) => {
|
|
19642
19820
|
if (ctx.data.agentDone === false) return;
|
|
19643
19821
|
try {
|
|
19644
|
-
|
|
19822
|
+
execFileSync21("git", ["add", "-A"], {
|
|
19645
19823
|
cwd: ctx.cwd,
|
|
19646
19824
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
19647
19825
|
stdio: "pipe"
|
|
@@ -19694,113 +19872,6 @@ var init_startFlow = __esm({
|
|
|
19694
19872
|
}
|
|
19695
19873
|
});
|
|
19696
19874
|
|
|
19697
|
-
// src/scripts/syncFlow.ts
|
|
19698
|
-
import { execFileSync as execFileSync21 } from "child_process";
|
|
19699
|
-
function restoreDone(prNumber, cwd) {
|
|
19700
|
-
try {
|
|
19701
|
-
setKodyLabel(prNumber, DONE2, cwd);
|
|
19702
|
-
} catch {
|
|
19703
|
-
}
|
|
19704
|
-
}
|
|
19705
|
-
function bail2(ctx, prNumber, reason) {
|
|
19706
|
-
ctx.skipAgent = true;
|
|
19707
|
-
ctx.output.exitCode = 1;
|
|
19708
|
-
ctx.output.reason = reason;
|
|
19709
|
-
const runUrl = getRunUrl();
|
|
19710
|
-
const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
|
|
19711
|
-
tryPostPr6(prNumber, `\u274C kody sync could not complete${runSuffix}: ${reason}`, ctx.cwd);
|
|
19712
|
-
}
|
|
19713
|
-
function revParseHead(cwd) {
|
|
19714
|
-
try {
|
|
19715
|
-
return execFileSync21("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
19716
|
-
} catch {
|
|
19717
|
-
return "";
|
|
19718
|
-
}
|
|
19719
|
-
}
|
|
19720
|
-
function pushBranch(branch, cwd) {
|
|
19721
|
-
const result = pushWithRetry({ cwd: cwd ?? process.cwd(), branch, setUpstream: true });
|
|
19722
|
-
if (!result.ok) {
|
|
19723
|
-
throw new Error(result.reason);
|
|
19724
|
-
}
|
|
19725
|
-
}
|
|
19726
|
-
function tryPostPr6(prNumber, body, cwd) {
|
|
19727
|
-
try {
|
|
19728
|
-
postPrReviewComment(prNumber, body, cwd);
|
|
19729
|
-
} catch {
|
|
19730
|
-
}
|
|
19731
|
-
}
|
|
19732
|
-
var DONE2, syncFlow;
|
|
19733
|
-
var init_syncFlow = __esm({
|
|
19734
|
-
"src/scripts/syncFlow.ts"() {
|
|
19735
|
-
"use strict";
|
|
19736
|
-
init_branch();
|
|
19737
|
-
init_gha();
|
|
19738
|
-
init_issue();
|
|
19739
|
-
init_lifecycleLabels();
|
|
19740
|
-
init_pushWithRetry();
|
|
19741
|
-
DONE2 = {
|
|
19742
|
-
label: "kody:done",
|
|
19743
|
-
color: "0e8a16",
|
|
19744
|
-
description: "kody: PR ready for human review/merge"
|
|
19745
|
-
};
|
|
19746
|
-
syncFlow = async (ctx, _profile, args) => {
|
|
19747
|
-
const announceOnSuccess = Boolean(args?.announceOnSuccess);
|
|
19748
|
-
const prNumber = ctx.args.pr;
|
|
19749
|
-
const pr = getPr(prNumber, ctx.cwd);
|
|
19750
|
-
if (pr.state !== "OPEN") {
|
|
19751
|
-
bail2(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
|
|
19752
|
-
return;
|
|
19753
|
-
}
|
|
19754
|
-
ctx.data.pr = pr;
|
|
19755
|
-
if (announceOnSuccess) {
|
|
19756
|
-
ctx.data.commentTargetType = "pr";
|
|
19757
|
-
ctx.data.commentTargetNumber = prNumber;
|
|
19758
|
-
}
|
|
19759
|
-
checkoutPrBranch(prNumber, ctx.cwd);
|
|
19760
|
-
ctx.data.branch = getCurrentBranch(ctx.cwd);
|
|
19761
|
-
const baseBranch = pr.baseRefName || ctx.config.git.defaultBranch;
|
|
19762
|
-
ctx.data.baseBranch = baseBranch;
|
|
19763
|
-
const headBefore = revParseHead(ctx.cwd);
|
|
19764
|
-
const mergeStatus = mergeBase(baseBranch, ctx.cwd);
|
|
19765
|
-
if (mergeStatus === "error") {
|
|
19766
|
-
bail2(ctx, prNumber, `failed to merge origin/${baseBranch} (non-conflict error); see runner log`);
|
|
19767
|
-
return;
|
|
19768
|
-
}
|
|
19769
|
-
if (mergeStatus === "conflict") {
|
|
19770
|
-
bail2(
|
|
19771
|
-
ctx,
|
|
19772
|
-
prNumber,
|
|
19773
|
-
`merge from origin/${baseBranch} produced conflicts \u2014 run \`@kody resolve\` to let kody resolve them`
|
|
19774
|
-
);
|
|
19775
|
-
return;
|
|
19776
|
-
}
|
|
19777
|
-
const headAfter = revParseHead(ctx.cwd);
|
|
19778
|
-
if (headAfter === headBefore) {
|
|
19779
|
-
ctx.data.syncResult = "noop";
|
|
19780
|
-
if (announceOnSuccess) {
|
|
19781
|
-
ctx.output.exitCode = 0;
|
|
19782
|
-
ctx.output.reason = `already up to date with origin/${baseBranch}`;
|
|
19783
|
-
restoreDone(prNumber, ctx.cwd);
|
|
19784
|
-
}
|
|
19785
|
-
return;
|
|
19786
|
-
}
|
|
19787
|
-
try {
|
|
19788
|
-
pushBranch(ctx.data.branch, ctx.cwd);
|
|
19789
|
-
} catch (err) {
|
|
19790
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
19791
|
-
bail2(ctx, prNumber, `merge succeeded but push failed: ${msg}`);
|
|
19792
|
-
return;
|
|
19793
|
-
}
|
|
19794
|
-
ctx.data.syncResult = "merged";
|
|
19795
|
-
if (announceOnSuccess) {
|
|
19796
|
-
ctx.output.exitCode = 0;
|
|
19797
|
-
ctx.output.reason = `merged origin/${baseBranch} into ${ctx.data.branch}`;
|
|
19798
|
-
restoreDone(prNumber, ctx.cwd);
|
|
19799
|
-
}
|
|
19800
|
-
};
|
|
19801
|
-
}
|
|
19802
|
-
});
|
|
19803
|
-
|
|
19804
19875
|
// src/scripts/validateAgencyModelProposal.ts
|
|
19805
19876
|
import * as path46 from "path";
|
|
19806
19877
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
@@ -20882,6 +20953,7 @@ var init_scripts = __esm({
|
|
|
20882
20953
|
init_postResearchComment();
|
|
20883
20954
|
init_postReviewResult();
|
|
20884
20955
|
init_prepareBrowserAuth();
|
|
20956
|
+
init_prepareCapabilityDelivery();
|
|
20885
20957
|
init_promoteQaGoal();
|
|
20886
20958
|
init_publishReport();
|
|
20887
20959
|
init_recordClassification();
|
|
@@ -20943,6 +21015,7 @@ var init_scripts = __esm({
|
|
|
20943
21015
|
loadPriorArt,
|
|
20944
21016
|
loadQaContext,
|
|
20945
21017
|
prepareBrowserAuth,
|
|
21018
|
+
prepareCapabilityDelivery,
|
|
20946
21019
|
buildSyntheticPlugin,
|
|
20947
21020
|
resolveArtifacts,
|
|
20948
21021
|
discoverQaContext,
|
|
@@ -22303,6 +22376,9 @@ function validateJob(input) {
|
|
|
22303
22376
|
if (j.cliArgs !== void 0 && (typeof j.cliArgs !== "object" || j.cliArgs === null)) {
|
|
22304
22377
|
throw new InvalidJobError("job.cliArgs must be an object when present");
|
|
22305
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
|
+
}
|
|
22306
22382
|
return {
|
|
22307
22383
|
action: typeof j.action === "string" ? j.action : void 0,
|
|
22308
22384
|
implementation: typeof j.implementation === "string" ? j.implementation : void 0,
|
|
@@ -22312,6 +22388,7 @@ function validateJob(input) {
|
|
|
22312
22388
|
agent: typeof j.agent === "string" ? j.agent : void 0,
|
|
22313
22389
|
schedule: typeof j.schedule === "string" ? j.schedule : void 0,
|
|
22314
22390
|
target: typeof j.target === "number" ? j.target : void 0,
|
|
22391
|
+
delivery: j.delivery === "pull-request" ? j.delivery : void 0,
|
|
22315
22392
|
cliArgs: j.cliArgs ?? {},
|
|
22316
22393
|
workflowFacts: j.workflowFacts && typeof j.workflowFacts === "object" && !Array.isArray(j.workflowFacts) ? j.workflowFacts : void 0,
|
|
22317
22394
|
workflowState: parseWorkflowRunState(j.workflowState) ?? void 0,
|
|
@@ -22364,7 +22441,7 @@ async function runJob(job, base) {
|
|
|
22364
22441
|
}
|
|
22365
22442
|
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
22366
22443
|
const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
|
|
22367
|
-
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);
|
|
22368
22445
|
const profileName = explicitImplementation ?? capabilitySelectedImplementation;
|
|
22369
22446
|
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedImplementation, base)) {
|
|
22370
22447
|
const workflowCapability = capabilityContext ?? workflowContext;
|
|
@@ -22454,6 +22531,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
22454
22531
|
preloadedData.jobKey = stableJobKey(valid);
|
|
22455
22532
|
preloadedData.jobFlavor = valid.flavor;
|
|
22456
22533
|
if (valid.target !== void 0) preloadedData.jobTarget = valid.target;
|
|
22534
|
+
if (valid.delivery !== void 0) preloadedData.jobDelivery = valid.delivery;
|
|
22457
22535
|
if (valid.action !== void 0 && valid.action.length > 0) preloadedData.jobAction = valid.action;
|
|
22458
22536
|
if (capabilityIdentity !== void 0 && capabilityIdentity.length > 0)
|
|
22459
22537
|
preloadedData.jobCapability = capabilityIdentity;
|
|
@@ -22493,11 +22571,13 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
22493
22571
|
};
|
|
22494
22572
|
const shouldApplyResolvedCapabilityArgs = valid.implementation === void 0 && resolvedCapability && profileName === resolvedCapability.implementation;
|
|
22495
22573
|
input.cliArgs = shouldApplyResolvedCapabilityArgs ? { ...resolvedCapability.cliArgs, ...input.cliArgs } : input.cliArgs;
|
|
22496
|
-
if (profileName === "capability-run" && capabilityIdentity) {
|
|
22574
|
+
if ((profileName === "capability-run" || profileName === "capability-delivery") && capabilityIdentity) {
|
|
22497
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) : {};
|
|
22498
22577
|
input.cliArgs = {
|
|
22499
22578
|
capability: capabilityIdentity,
|
|
22500
|
-
...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {}
|
|
22579
|
+
...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {},
|
|
22580
|
+
...deliveryTarget
|
|
22501
22581
|
};
|
|
22502
22582
|
}
|
|
22503
22583
|
const run = base.chain === false ? runImplementation : runImplementationChain;
|
|
@@ -22854,6 +22934,7 @@ function workflowStepToJob(step, parent, chainData, cwd) {
|
|
|
22854
22934
|
...parent.agent ? { agent: parent.agent } : {},
|
|
22855
22935
|
...parent.schedule ? { schedule: parent.schedule } : {},
|
|
22856
22936
|
...typeof target === "number" ? { target } : {},
|
|
22937
|
+
...step.delivery ? { delivery: step.delivery } : {},
|
|
22857
22938
|
cliArgs,
|
|
22858
22939
|
...step.evidence ? { evidence: step.evidence } : parent.evidence ? { evidence: parent.evidence } : {},
|
|
22859
22940
|
flavor: parent.flavor,
|
|
@@ -22863,6 +22944,10 @@ function workflowStepToJob(step, parent, chainData, cwd) {
|
|
|
22863
22944
|
...parent.resultTarget ? { resultTarget: parent.resultTarget } : {}
|
|
22864
22945
|
};
|
|
22865
22946
|
}
|
|
22947
|
+
function capabilityDeliveryArgs(input) {
|
|
22948
|
+
const target = capabilityDeliveryTarget(input);
|
|
22949
|
+
return target ? { [target.kind]: target.number } : {};
|
|
22950
|
+
}
|
|
22866
22951
|
function usesGenericCapabilityInput(action, cwd) {
|
|
22867
22952
|
const inputs = getCapabilityActionInputs(action, hydratedCapabilitiesRoot(cwd));
|
|
22868
22953
|
return Boolean(inputs?.length === 1 && inputs[0]?.name === "input" && inputs[0]?.flag === "--input");
|
|
@@ -23027,6 +23112,7 @@ var init_job = __esm({
|
|
|
23027
23112
|
"src/job.ts"() {
|
|
23028
23113
|
"use strict";
|
|
23029
23114
|
init_agencyBoundaryEval();
|
|
23115
|
+
init_capabilityDelivery();
|
|
23030
23116
|
init_capabilityFolders();
|
|
23031
23117
|
init_definition_paths();
|
|
23032
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.
|
|
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",
|