@kody-ade/kody-engine 0.4.637 → 0.4.639
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.639",
|
|
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
|
repository: {
|
|
@@ -181,6 +181,19 @@ var init_completionGuard = __esm({
|
|
|
181
181
|
});
|
|
182
182
|
|
|
183
183
|
// src/submitStateGuard.ts
|
|
184
|
+
function createSubmitStateActivityGuard() {
|
|
185
|
+
let hasActivity = false;
|
|
186
|
+
return {
|
|
187
|
+
recordToolUse: async (input) => {
|
|
188
|
+
if (input?.tool_name !== SUBMIT_STATE_TOOL) hasActivity = true;
|
|
189
|
+
return {};
|
|
190
|
+
},
|
|
191
|
+
requireActivity: async () => hasActivity ? {} : {
|
|
192
|
+
decision: "block",
|
|
193
|
+
reason: ACTIVITY_REQUIRED_REASON
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
184
197
|
function createPostSubmitToolGuard(getSubmitted) {
|
|
185
198
|
return async () => getSubmitted() ? {
|
|
186
199
|
decision: "block",
|
|
@@ -199,12 +212,14 @@ function createSubmitStateStopHook(getSubmitted) {
|
|
|
199
212
|
};
|
|
200
213
|
};
|
|
201
214
|
}
|
|
202
|
-
var FINAL_STATE_CHANCE_REASON, STATE_ALREADY_SUBMITTED_REASON;
|
|
215
|
+
var FINAL_STATE_CHANCE_REASON, STATE_ALREADY_SUBMITTED_REASON, ACTIVITY_REQUIRED_REASON, SUBMIT_STATE_TOOL;
|
|
203
216
|
var init_submitStateGuard = __esm({
|
|
204
217
|
"src/submitStateGuard.ts"() {
|
|
205
218
|
"use strict";
|
|
206
219
|
FINAL_STATE_CHANCE_REASON = "Before finishing, call `submit_state` exactly once with the next non-empty `cursor`, compact durable `data`, and the correct `done` value. Do not perform more work; submit only the continuation state now.";
|
|
207
220
|
STATE_ALREADY_SUBMITTED_REASON = "Continuation state is already submitted for this cycle. Do not call more tools or perform more work; return your final response now.";
|
|
221
|
+
ACTIVITY_REQUIRED_REASON = "Do not submit continuation state yet. First use a tool to observe current evidence or perform the next responsibility action for this cycle.";
|
|
222
|
+
SUBMIT_STATE_TOOL = "mcp__kody-submit__submit_state";
|
|
208
223
|
}
|
|
209
224
|
});
|
|
210
225
|
|
|
@@ -4084,46 +4099,71 @@ function capabilityToolDefinitions(opts) {
|
|
|
4084
4099
|
const reportRunId = typeof args.reportRunId === "string" ? args.reportRunId : void 0;
|
|
4085
4100
|
const evidence = typeof args.evidence === "string" ? args.evidence.trim() : "";
|
|
4086
4101
|
const backend = createStateBackendFromEnv();
|
|
4087
|
-
const existing = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4088
4102
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4089
|
-
const current = existing?.doc && typeof existing.doc === "object" && !Array.isArray(existing.doc) ? existing.doc : {};
|
|
4090
|
-
const currentItems = Array.isArray(current.items) ? current.items.filter((item) => Boolean(item && typeof item === "object" && !Array.isArray(item))) : [];
|
|
4091
|
-
const previous = currentItems.find((item) => item.id === itemId);
|
|
4092
4103
|
const completed = status === "resolved";
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4104
|
+
let lastError = new Error(`Todo ${slug}/${itemId} was not visible after reconciliation`);
|
|
4105
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
4106
|
+
try {
|
|
4107
|
+
const existing = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4108
|
+
const current = existing?.doc && typeof existing.doc === "object" && !Array.isArray(existing.doc) ? existing.doc : {};
|
|
4109
|
+
const currentItems = Array.isArray(current.items) ? current.items.filter(
|
|
4110
|
+
(item) => Boolean(item && typeof item === "object" && !Array.isArray(item))
|
|
4111
|
+
) : [];
|
|
4112
|
+
const previous = currentItems.find((item) => item.id === itemId);
|
|
4113
|
+
const previousMeta = previous?.meta && typeof previous.meta === "object" && !Array.isArray(previous.meta) ? previous.meta : {};
|
|
4114
|
+
const unchanged = Boolean(
|
|
4115
|
+
previous && previous.completed === completed && previous.title === title && String(previous.body ?? "") === evidence && previousMeta.reportSlug === reportSlug
|
|
4116
|
+
);
|
|
4117
|
+
if (unchanged) {
|
|
4118
|
+
return {
|
|
4119
|
+
content: [{ type: "text", text: JSON.stringify({ changed: false, verified: true, slug, status }) }]
|
|
4120
|
+
};
|
|
4121
|
+
}
|
|
4122
|
+
const nextItem = {
|
|
4123
|
+
id: itemId,
|
|
4124
|
+
title,
|
|
4125
|
+
body: evidence,
|
|
4126
|
+
assignee: null,
|
|
4127
|
+
completed,
|
|
4128
|
+
createdAt: typeof previous?.createdAt === "string" ? previous.createdAt : now,
|
|
4129
|
+
completedAt: completed ? now : null,
|
|
4130
|
+
meta: {
|
|
4131
|
+
...previousMeta,
|
|
4132
|
+
source: "live-agent",
|
|
4133
|
+
reportSlug,
|
|
4134
|
+
...reportRunId ? { reportRunId } : {},
|
|
4135
|
+
status
|
|
4136
|
+
}
|
|
4137
|
+
};
|
|
4138
|
+
const items = previous ? currentItems.map((item) => item.id === itemId ? nextItem : item) : [...currentItems, nextItem];
|
|
4139
|
+
const doc = {
|
|
4140
|
+
...current,
|
|
4141
|
+
version: 1,
|
|
4142
|
+
title,
|
|
4143
|
+
description,
|
|
4144
|
+
createdAt: typeof current.createdAt === "string" ? current.createdAt : now,
|
|
4145
|
+
items
|
|
4146
|
+
};
|
|
4147
|
+
await backend.saveRepoDoc(opts.repoSlug, `todo:${slug}`, doc, existing?.updatedAt);
|
|
4148
|
+
const saved = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4149
|
+
const savedItems = saved?.doc && typeof saved.doc === "object" && !Array.isArray(saved.doc) && Array.isArray(saved.doc.items) ? saved.doc.items : [];
|
|
4150
|
+
const savedItem = savedItems.find(
|
|
4151
|
+
(item) => Boolean(
|
|
4152
|
+
item && typeof item === "object" && !Array.isArray(item) && item.id === itemId
|
|
4153
|
+
)
|
|
4154
|
+
);
|
|
4155
|
+
const savedMeta = savedItem?.meta && typeof savedItem.meta === "object" && !Array.isArray(savedItem.meta) ? savedItem.meta : {};
|
|
4156
|
+
if (savedItem && savedItem.completed === completed && savedItem.title === title && String(savedItem.body ?? "") === evidence && savedMeta.reportSlug === reportSlug) {
|
|
4157
|
+
return {
|
|
4158
|
+
content: [{ type: "text", text: JSON.stringify({ changed: true, verified: true, slug, status }) }]
|
|
4159
|
+
};
|
|
4160
|
+
}
|
|
4161
|
+
lastError = new Error(`Todo ${slug}/${itemId} was not visible after reconciliation attempt ${attempt + 1}`);
|
|
4162
|
+
} catch (error) {
|
|
4163
|
+
lastError = error;
|
|
4114
4164
|
}
|
|
4115
|
-
}
|
|
4116
|
-
|
|
4117
|
-
const doc = {
|
|
4118
|
-
...current,
|
|
4119
|
-
version: 1,
|
|
4120
|
-
title,
|
|
4121
|
-
description,
|
|
4122
|
-
createdAt: typeof current.createdAt === "string" ? current.createdAt : now,
|
|
4123
|
-
items
|
|
4124
|
-
};
|
|
4125
|
-
await backend.saveRepoDoc(opts.repoSlug, `todo:${slug}`, doc, existing?.updatedAt);
|
|
4126
|
-
return { content: [{ type: "text", text: JSON.stringify({ changed: true, slug, status }) }] };
|
|
4165
|
+
}
|
|
4166
|
+
throw lastError;
|
|
4127
4167
|
}
|
|
4128
4168
|
};
|
|
4129
4169
|
const cmsTools = dashboardCmsToolDefinitions({
|
|
@@ -4171,8 +4211,8 @@ var init_capabilityMcp = __esm({
|
|
|
4171
4211
|
init_dashboardCmsMcp();
|
|
4172
4212
|
init_issue();
|
|
4173
4213
|
init_registry();
|
|
4174
|
-
init_trustPolicy();
|
|
4175
4214
|
init_state_backend();
|
|
4215
|
+
init_trustPolicy();
|
|
4176
4216
|
FAIL_CONCLUSIONS = /* @__PURE__ */ new Set(["FAILURE", "TIMED_OUT", "ACTION_REQUIRED", "STARTUP_FAILURE", "CANCELLED"]);
|
|
4177
4217
|
RUNNING_STATUSES = /* @__PURE__ */ new Set(["IN_PROGRESS", "QUEUED", "PENDING", "WAITING", "REQUESTED"]);
|
|
4178
4218
|
THREAD_BODY_MAX = 4e3;
|
|
@@ -4445,6 +4485,7 @@ async function runAgent(opts) {
|
|
|
4445
4485
|
const outputContractStopHook = opts.outputContract ? createOutputContractStopHook(opts.outputContract) : null;
|
|
4446
4486
|
const submitStateStopHook = opts.enableSubmitTool ? createSubmitStateStopHook(() => getSubmitted?.()) : null;
|
|
4447
4487
|
const postSubmitToolGuard = opts.enableSubmitTool ? createPostSubmitToolGuard(() => getSubmitted?.()) : null;
|
|
4488
|
+
const submitStateActivityGuard = opts.enableSubmitTool ? createSubmitStateActivityGuard() : null;
|
|
4448
4489
|
let finalSafeToReplay = true;
|
|
4449
4490
|
for (let attempt = 0; ; attempt++) {
|
|
4450
4491
|
let ndjsonWriteFailed = false;
|
|
@@ -4493,6 +4534,12 @@ async function runAgent(opts) {
|
|
|
4493
4534
|
hooks: [completionGuard]
|
|
4494
4535
|
}
|
|
4495
4536
|
] : [],
|
|
4537
|
+
...submitStateActivityGuard ? [
|
|
4538
|
+
{
|
|
4539
|
+
matcher: "mcp__kody-submit__submit_state",
|
|
4540
|
+
hooks: [submitStateActivityGuard.requireActivity]
|
|
4541
|
+
}
|
|
4542
|
+
] : [],
|
|
4496
4543
|
{
|
|
4497
4544
|
matcher: "Agent",
|
|
4498
4545
|
hooks: [enforceSubagentModelInheritance]
|
|
@@ -4503,6 +4550,11 @@ async function runAgent(opts) {
|
|
|
4503
4550
|
}
|
|
4504
4551
|
],
|
|
4505
4552
|
PostToolUse: [
|
|
4553
|
+
...submitStateActivityGuard ? [
|
|
4554
|
+
{
|
|
4555
|
+
hooks: [submitStateActivityGuard.recordToolUse]
|
|
4556
|
+
}
|
|
4557
|
+
] : [],
|
|
4506
4558
|
{
|
|
4507
4559
|
matcher: "Agent",
|
|
4508
4560
|
hooks: [subagentInvocationHook]
|
|
File without changes
|
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.639",
|
|
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
|
"repository": {
|
|
@@ -17,6 +17,30 @@
|
|
|
17
17
|
"docs/delivery-boundary.md",
|
|
18
18
|
"kody.config.schema.json"
|
|
19
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"kody:run": "tsx bin/kody.ts",
|
|
22
|
+
"serve": "tsx bin/kody.ts serve",
|
|
23
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
24
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
25
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
26
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
27
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
28
|
+
"pretest": "pnpm check:modularity",
|
|
29
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
30
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
31
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
32
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
33
|
+
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
34
|
+
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
35
|
+
"test:all": "vitest run tests --no-coverage",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"lint": "biome check",
|
|
38
|
+
"lint:fix": "biome check --write",
|
|
39
|
+
"format": "biome format --write",
|
|
40
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
41
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
42
|
+
"prepublishOnly": "pnpm typecheck && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
43
|
+
},
|
|
20
44
|
"dependencies": {
|
|
21
45
|
"@actions/cache": "^6.0.0",
|
|
22
46
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -39,28 +63,5 @@
|
|
|
39
63
|
"node": ">=22"
|
|
40
64
|
},
|
|
41
65
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
42
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
43
|
-
|
|
44
|
-
"kody:run": "tsx bin/kody.ts",
|
|
45
|
-
"serve": "tsx bin/kody.ts serve",
|
|
46
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
47
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
48
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
49
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
50
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
51
|
-
"pretest": "pnpm check:modularity",
|
|
52
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
53
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
54
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
55
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
56
|
-
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
57
|
-
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
58
|
-
"test:all": "vitest run tests --no-coverage",
|
|
59
|
-
"typecheck": "tsc --noEmit",
|
|
60
|
-
"lint": "biome check",
|
|
61
|
-
"lint:fix": "biome check --write",
|
|
62
|
-
"format": "biome format --write",
|
|
63
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
64
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
66
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
67
|
+
}
|