@kody-ade/kody-engine 0.4.213-live.0 → 0.4.213-live.2
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.213-live.
|
|
18
|
+
version: "0.4.213-live.2",
|
|
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",
|
|
@@ -3149,7 +3149,7 @@ function nextPendingTaskJob(state, ids) {
|
|
|
3149
3149
|
const keys = ids && ids.length > 0 ? ids : Object.keys(jobs);
|
|
3150
3150
|
for (const key of keys) {
|
|
3151
3151
|
const job = jobs[key];
|
|
3152
|
-
if (job
|
|
3152
|
+
if (job && job.status !== "succeeded") return job;
|
|
3153
3153
|
}
|
|
3154
3154
|
return null;
|
|
3155
3155
|
}
|
|
@@ -4776,6 +4776,7 @@ var init_saveTaskState = __esm({
|
|
|
4776
4776
|
if (ctx.output.prUrl) next.core.prUrl = ctx.output.prUrl;
|
|
4777
4777
|
if (typeof ctx.data.runUrl === "string") next.core.runUrl = ctx.data.runUrl;
|
|
4778
4778
|
writeTaskState(target, number, next, ctx.cwd);
|
|
4779
|
+
ctx.data.taskState = next;
|
|
4779
4780
|
ctx.data.taskStateRendered = renderStateComment(next);
|
|
4780
4781
|
};
|
|
4781
4782
|
}
|
|
@@ -7072,9 +7073,9 @@ __export(job_exports, {
|
|
|
7072
7073
|
validateJob: () => validateJob
|
|
7073
7074
|
});
|
|
7074
7075
|
function newJobId(flavor) {
|
|
7075
|
-
const runId = process.env.GITHUB_RUN_ID;
|
|
7076
|
-
if (runId) return `gh-${runId}-${process.env.GITHUB_RUN_ATTEMPT ?? "1"}`;
|
|
7077
7076
|
localJobSeq += 1;
|
|
7077
|
+
const runId = process.env.GITHUB_RUN_ID;
|
|
7078
|
+
if (runId) return `gh-${runId}-${process.env.GITHUB_RUN_ATTEMPT ?? "1"}-${localJobSeq}`;
|
|
7078
7079
|
return `${flavor}-${Date.now()}-${localJobSeq}`;
|
|
7079
7080
|
}
|
|
7080
7081
|
function validateJob(input) {
|
|
@@ -7109,7 +7110,7 @@ async function runJob(job, base) {
|
|
|
7109
7110
|
if (!profileName) {
|
|
7110
7111
|
throw new InvalidJobError("job resolves to no executable or duty");
|
|
7111
7112
|
}
|
|
7112
|
-
const preloadedData = {};
|
|
7113
|
+
const preloadedData = { ...base.preloadedData ?? {} };
|
|
7113
7114
|
preloadedData.jobId = newJobId(valid.flavor);
|
|
7114
7115
|
preloadedData.jobKey = stableJobKey(valid);
|
|
7115
7116
|
preloadedData.jobFlavor = valid.flavor;
|
|
@@ -8025,7 +8026,7 @@ var init_dispatchNextTaskJob = __esm({
|
|
|
8025
8026
|
"use strict";
|
|
8026
8027
|
init_jobIdentity();
|
|
8027
8028
|
init_state();
|
|
8028
|
-
dispatchNextTaskJob = async (ctx) => {
|
|
8029
|
+
dispatchNextTaskJob = async (ctx, profile) => {
|
|
8029
8030
|
const state = ctx.data.taskState ?? emptyState();
|
|
8030
8031
|
const ids = Array.isArray(ctx.data.plannedTaskJobIds) ? ctx.data.plannedTaskJobIds.filter((id) => typeof id === "string") : void 0;
|
|
8031
8032
|
const next = nextPendingTaskJob(state, ids);
|
|
@@ -8037,6 +8038,9 @@ var init_dispatchNextTaskJob = __esm({
|
|
|
8037
8038
|
}
|
|
8038
8039
|
const plannedJobs = Array.isArray(ctx.data.plannedTaskJobs) ? ctx.data.plannedTaskJobs.filter(isJob) : [];
|
|
8039
8040
|
ctx.output.nextJob = plannedJobs.find((job) => stableJobKey(job) === next.id) ?? taskJobToJob(next, ctx.args.issue);
|
|
8041
|
+
if (typeof ctx.args.issue === "number") {
|
|
8042
|
+
ctx.output.afterNextJob = { executable: profile.name, cliArgs: { issue: ctx.args.issue } };
|
|
8043
|
+
}
|
|
8040
8044
|
};
|
|
8041
8045
|
}
|
|
8042
8046
|
});
|
|
@@ -8345,6 +8349,35 @@ var init_ensurePr = __esm({
|
|
|
8345
8349
|
}
|
|
8346
8350
|
});
|
|
8347
8351
|
|
|
8352
|
+
// src/scripts/failOnceTaskJob.ts
|
|
8353
|
+
var failOnceTaskJob;
|
|
8354
|
+
var init_failOnceTaskJob = __esm({
|
|
8355
|
+
"src/scripts/failOnceTaskJob.ts"() {
|
|
8356
|
+
"use strict";
|
|
8357
|
+
init_jobIdentity();
|
|
8358
|
+
failOnceTaskJob = async (ctx, profile) => {
|
|
8359
|
+
ctx.skipAgent = true;
|
|
8360
|
+
const issue = typeof ctx.args.issue === "number" ? ctx.args.issue : void 0;
|
|
8361
|
+
const fallbackJob = {
|
|
8362
|
+
executable: profile.name,
|
|
8363
|
+
flavor: "instant",
|
|
8364
|
+
...typeof issue === "number" ? { target: issue, cliArgs: { issue } } : { cliArgs: {} }
|
|
8365
|
+
};
|
|
8366
|
+
const jobKey = typeof ctx.data.jobKey === "string" ? ctx.data.jobKey : stableJobKey(fallbackJob);
|
|
8367
|
+
const state = ctx.data.taskState;
|
|
8368
|
+
const runs = state?.jobs?.[jobKey]?.runs ?? [];
|
|
8369
|
+
const hasFailedBefore = runs.some((run) => run.status === "failed");
|
|
8370
|
+
if (!hasFailedBefore) {
|
|
8371
|
+
ctx.output.exitCode = 1;
|
|
8372
|
+
ctx.output.reason = "intentional first-attempt failure for task job live test";
|
|
8373
|
+
return;
|
|
8374
|
+
}
|
|
8375
|
+
ctx.output.exitCode = 0;
|
|
8376
|
+
ctx.output.reason = "task job live test succeeded after prior failure";
|
|
8377
|
+
};
|
|
8378
|
+
}
|
|
8379
|
+
});
|
|
8380
|
+
|
|
8348
8381
|
// src/scripts/finalizeGoal.ts
|
|
8349
8382
|
function prIssueNumbers(pr) {
|
|
8350
8383
|
const nums = new Set(extractClosesIssues(pr.body));
|
|
@@ -13412,6 +13445,7 @@ var init_scripts = __esm({
|
|
|
13412
13445
|
init_dispatchNextTask();
|
|
13413
13446
|
init_dispatchNextTaskJob();
|
|
13414
13447
|
init_ensurePr();
|
|
13448
|
+
init_failOnceTaskJob();
|
|
13415
13449
|
init_finalizeGoal();
|
|
13416
13450
|
init_finalizeTerminal();
|
|
13417
13451
|
init_finishFlow();
|
|
@@ -13569,6 +13603,7 @@ var init_scripts = __esm({
|
|
|
13569
13603
|
notifyTerminal,
|
|
13570
13604
|
openQaIssue,
|
|
13571
13605
|
createQaGoal,
|
|
13606
|
+
failOnceTaskJob,
|
|
13572
13607
|
recordOutcome,
|
|
13573
13608
|
mergeReleasePr,
|
|
13574
13609
|
waitForCi,
|
|
@@ -14088,7 +14123,9 @@ async function runExecutable(profileName, input) {
|
|
|
14088
14123
|
prUrl: ctx.output.prUrl,
|
|
14089
14124
|
reason: ctx.output.reason,
|
|
14090
14125
|
nextDispatch: ctx.output.nextDispatch,
|
|
14091
|
-
nextJob: ctx.output.nextJob
|
|
14126
|
+
nextJob: ctx.output.nextJob,
|
|
14127
|
+
afterNextJob: ctx.output.afterNextJob,
|
|
14128
|
+
taskState: ctx.data.taskState
|
|
14092
14129
|
});
|
|
14093
14130
|
} finally {
|
|
14094
14131
|
clearStampedLifecycleLabels(profile, ctx);
|
|
@@ -14110,27 +14147,61 @@ async function runExecutable(profileName, input) {
|
|
|
14110
14147
|
}
|
|
14111
14148
|
async function runExecutableChain(profileName, input) {
|
|
14112
14149
|
let result = await runExecutable(profileName, input);
|
|
14150
|
+
let chainData = {
|
|
14151
|
+
...input.preloadedData ?? {},
|
|
14152
|
+
...result.taskState ? { taskState: result.taskState } : {}
|
|
14153
|
+
};
|
|
14113
14154
|
for (let hops = 1; (result.nextDispatch || result.nextJob) && hops <= MAX_CHAIN_HOPS; hops++) {
|
|
14114
14155
|
if (result.nextJob) {
|
|
14115
14156
|
const next2 = result.nextJob;
|
|
14157
|
+
const after = result.afterNextJob;
|
|
14116
14158
|
const label = next2.executable ?? next2.duty ?? "unknown";
|
|
14117
14159
|
process.stdout.write(`\u2192 kody: in-process job hand-off \u2192 ${label} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
14118
14160
|
|
|
14119
14161
|
`);
|
|
14120
14162
|
const { runJob: runJob2 } = await Promise.resolve().then(() => (init_job(), job_exports));
|
|
14121
|
-
|
|
14163
|
+
const childResult = await runJob2(next2, {
|
|
14122
14164
|
cwd: input.cwd,
|
|
14123
14165
|
config: input.config,
|
|
14124
14166
|
verbose: input.verbose,
|
|
14125
|
-
quiet: input.quiet
|
|
14167
|
+
quiet: input.quiet,
|
|
14168
|
+
preloadedData: chainData
|
|
14126
14169
|
});
|
|
14170
|
+
if (after && childResult.exitCode === 0 && !childResult.nextDispatch && !childResult.nextJob && !childResult.afterNextJob) {
|
|
14171
|
+
chainData = {
|
|
14172
|
+
...chainData,
|
|
14173
|
+
...childResult.taskState ? { taskState: childResult.taskState } : {}
|
|
14174
|
+
};
|
|
14175
|
+
process.stdout.write(`\u2192 kody: in-process return \u2192 ${after.executable} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
14176
|
+
|
|
14177
|
+
`);
|
|
14178
|
+
result = await runExecutable(after.executable, {
|
|
14179
|
+
...input,
|
|
14180
|
+
cliArgs: after.cliArgs,
|
|
14181
|
+
preloadedData: chainData
|
|
14182
|
+
});
|
|
14183
|
+
chainData = {
|
|
14184
|
+
...chainData,
|
|
14185
|
+
...result.taskState ? { taskState: result.taskState } : {}
|
|
14186
|
+
};
|
|
14187
|
+
} else {
|
|
14188
|
+
result = childResult;
|
|
14189
|
+
chainData = {
|
|
14190
|
+
...chainData,
|
|
14191
|
+
...result.taskState ? { taskState: result.taskState } : {}
|
|
14192
|
+
};
|
|
14193
|
+
}
|
|
14127
14194
|
continue;
|
|
14128
14195
|
}
|
|
14129
14196
|
const next = result.nextDispatch;
|
|
14130
14197
|
process.stdout.write(`\u2192 kody: in-process hand-off \u2192 ${next.executable} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
14131
14198
|
|
|
14132
14199
|
`);
|
|
14133
|
-
result = await runExecutable(next.executable, { ...input, cliArgs: next.cliArgs });
|
|
14200
|
+
result = await runExecutable(next.executable, { ...input, cliArgs: next.cliArgs, preloadedData: chainData });
|
|
14201
|
+
chainData = {
|
|
14202
|
+
...chainData,
|
|
14203
|
+
...result.taskState ? { taskState: result.taskState } : {}
|
|
14204
|
+
};
|
|
14134
14205
|
}
|
|
14135
14206
|
if (result.nextDispatch || result.nextJob) {
|
|
14136
14207
|
const pending = result.nextDispatch?.executable ?? result.nextJob?.executable ?? result.nextJob?.duty ?? "unknown";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "task-job-fail-once",
|
|
3
|
+
"role": "utility",
|
|
4
|
+
"describe": "Live-test executable that fails the first planned job attempt and succeeds on rerun.",
|
|
5
|
+
"kind": "oneshot",
|
|
6
|
+
"inputs": [
|
|
7
|
+
{
|
|
8
|
+
"name": "issue",
|
|
9
|
+
"flag": "--issue",
|
|
10
|
+
"type": "int",
|
|
11
|
+
"required": true,
|
|
12
|
+
"describe": "GitHub issue number that owns the task state."
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"claudeCode": {
|
|
16
|
+
"model": "inherit",
|
|
17
|
+
"permissionMode": "default",
|
|
18
|
+
"maxTurns": 0,
|
|
19
|
+
"maxThinkingTokens": null,
|
|
20
|
+
"systemPromptAppend": null,
|
|
21
|
+
"tools": [],
|
|
22
|
+
"hooks": [],
|
|
23
|
+
"skills": [],
|
|
24
|
+
"commands": [],
|
|
25
|
+
"subagents": [],
|
|
26
|
+
"plugins": [],
|
|
27
|
+
"mcpServers": []
|
|
28
|
+
},
|
|
29
|
+
"cliTools": [],
|
|
30
|
+
"inputArtifacts": [],
|
|
31
|
+
"outputArtifacts": [],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"preflight": [
|
|
34
|
+
{ "script": "loadIssueContext" },
|
|
35
|
+
{ "script": "loadTaskState" },
|
|
36
|
+
{ "script": "skipAgent" }
|
|
37
|
+
],
|
|
38
|
+
"postflight": [
|
|
39
|
+
{ "script": "failOnceTaskJob" },
|
|
40
|
+
{ "script": "recordOutcome" },
|
|
41
|
+
{ "script": "saveTaskState" }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This executable is script-only.
|
|
@@ -413,6 +413,8 @@ export interface Context {
|
|
|
413
413
|
nextDispatch?: { executable: string; cliArgs: Record<string, unknown> }
|
|
414
414
|
/** In-process hand-off to a full Job, preserving job identity in task state. */
|
|
415
415
|
nextJob?: Job
|
|
416
|
+
/** Where to return after nextJob succeeds. Used by task-jobs to keep draining pending work. */
|
|
417
|
+
afterNextJob?: { executable: string; cliArgs: Record<string, unknown> }
|
|
416
418
|
}
|
|
417
419
|
/**
|
|
418
420
|
* If a preflight script sets this to true, the executor skips the agent
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.213-live.
|
|
3
|
+
"version": "0.4.213-live.2",
|
|
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",
|