@kody-ade/kody-engine 0.4.232 → 0.4.234
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 +229 -5
- package/dist/executables/types.ts +59 -0
- package/package.json +1 -1
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.234",
|
|
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",
|
|
@@ -3121,6 +3121,7 @@ function loadProfile(profilePath) {
|
|
|
3121
3121
|
action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
|
|
3122
3122
|
executable: execRef,
|
|
3123
3123
|
describe: typeof r.describe === "string" ? r.describe : base.describe,
|
|
3124
|
+
capabilityKind: parseCapabilityKind(profilePath, r.capabilityKind) ?? base.capabilityKind,
|
|
3124
3125
|
staff: typeof r.staff === "string" && r.staff.trim() ? r.staff.trim() : base.staff,
|
|
3125
3126
|
every: typeof r.every === "string" && r.every.trim() ? r.every.trim() : void 0,
|
|
3126
3127
|
dutyTools: parseStringArray(r.dutyTools ?? r.tools) ?? base.dutyTools,
|
|
@@ -3165,6 +3166,7 @@ function loadProfile(profilePath) {
|
|
|
3165
3166
|
action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
|
|
3166
3167
|
executable: void 0,
|
|
3167
3168
|
describe: typeof r.describe === "string" ? r.describe : "",
|
|
3169
|
+
capabilityKind: parseCapabilityKind(profilePath, r.capabilityKind),
|
|
3168
3170
|
// Optional persona to run as. Empty/blank string → undefined (no persona).
|
|
3169
3171
|
staff: typeof r.staff === "string" && r.staff.trim() ? r.staff.trim() : void 0,
|
|
3170
3172
|
// Optional recurrence cadence (scheduled duty). Blank → undefined (on-demand).
|
|
@@ -3255,6 +3257,13 @@ function requireString(p, r, key) {
|
|
|
3255
3257
|
}
|
|
3256
3258
|
return v;
|
|
3257
3259
|
}
|
|
3260
|
+
function parseCapabilityKind(p, raw) {
|
|
3261
|
+
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
3262
|
+
if (typeof raw !== "string" || !VALID_CAPABILITY_KINDS.has(raw)) {
|
|
3263
|
+
throw new ProfileError(p, `"capabilityKind" must be one of: observe | act | verify`);
|
|
3264
|
+
}
|
|
3265
|
+
return raw;
|
|
3266
|
+
}
|
|
3258
3267
|
function parseStringArray(raw) {
|
|
3259
3268
|
if (!Array.isArray(raw)) return void 0;
|
|
3260
3269
|
const values = raw.map((t) => String(t).trim()).filter(Boolean);
|
|
@@ -3331,6 +3340,17 @@ function parseCliTools(p, raw) {
|
|
|
3331
3340
|
if (!Array.isArray(raw)) throw new ProfileError(p, `"cliTools" must be an array or absent`);
|
|
3332
3341
|
const out = [];
|
|
3333
3342
|
for (const [i, item] of raw.entries()) {
|
|
3343
|
+
if (typeof item === "string" && item.trim()) {
|
|
3344
|
+
const name = item.trim();
|
|
3345
|
+
out.push({
|
|
3346
|
+
name,
|
|
3347
|
+
install: { required: false, checkCommand: `command -v ${name}` },
|
|
3348
|
+
verify: `command -v ${name}`,
|
|
3349
|
+
usage: "",
|
|
3350
|
+
allowedUses: []
|
|
3351
|
+
});
|
|
3352
|
+
continue;
|
|
3353
|
+
}
|
|
3334
3354
|
if (!item || typeof item !== "object") {
|
|
3335
3355
|
throw new ProfileError(p, `cliTools[${i}] must be an object`);
|
|
3336
3356
|
}
|
|
@@ -3490,7 +3510,7 @@ function parseScriptList(p, key, raw) {
|
|
|
3490
3510
|
}
|
|
3491
3511
|
return out;
|
|
3492
3512
|
}
|
|
3493
|
-
var VALID_INPUT_TYPES, VALID_PERMISSION_MODES, VALID_ROLES, VALID_CONTAINER_CHILD_TARGETS, VALID_PHASES, KNOWN_PROFILE_KEYS;
|
|
3513
|
+
var VALID_INPUT_TYPES, VALID_PERMISSION_MODES, VALID_ROLES, VALID_CONTAINER_CHILD_TARGETS, VALID_PHASES, VALID_CAPABILITY_KINDS, KNOWN_PROFILE_KEYS;
|
|
3494
3514
|
var init_profile = __esm({
|
|
3495
3515
|
"src/profile.ts"() {
|
|
3496
3516
|
"use strict";
|
|
@@ -3506,6 +3526,7 @@ var init_profile = __esm({
|
|
|
3506
3526
|
VALID_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
3507
3527
|
VALID_CONTAINER_CHILD_TARGETS = /* @__PURE__ */ new Set(["issue", "pr"]);
|
|
3508
3528
|
VALID_PHASES = /* @__PURE__ */ new Set(["research", "planning", "implementing", "reviewing", "shipped", "failed", "idle"]);
|
|
3529
|
+
VALID_CAPABILITY_KINDS = /* @__PURE__ */ new Set(["observe", "act", "verify"]);
|
|
3509
3530
|
KNOWN_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
3510
3531
|
"name",
|
|
3511
3532
|
"action",
|
|
@@ -3515,6 +3536,7 @@ var init_profile = __esm({
|
|
|
3515
3536
|
"dutyTools",
|
|
3516
3537
|
"tools",
|
|
3517
3538
|
"mentions",
|
|
3539
|
+
"capabilityKind",
|
|
3518
3540
|
"stage",
|
|
3519
3541
|
"readsFrom",
|
|
3520
3542
|
"writesTo",
|
|
@@ -5723,6 +5745,132 @@ var init_state2 = __esm({
|
|
|
5723
5745
|
}
|
|
5724
5746
|
});
|
|
5725
5747
|
|
|
5748
|
+
// src/goal/typeDefinitions.ts
|
|
5749
|
+
function cloneRoute(route) {
|
|
5750
|
+
return route.map((step) => ({
|
|
5751
|
+
stage: step.stage,
|
|
5752
|
+
evidence: step.evidence,
|
|
5753
|
+
duty: step.duty,
|
|
5754
|
+
...step.executable ? { executable: step.executable } : {},
|
|
5755
|
+
...step.args ? { args: structuredClone(step.args) } : {}
|
|
5756
|
+
}));
|
|
5757
|
+
}
|
|
5758
|
+
function stringArray(value) {
|
|
5759
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
|
|
5760
|
+
}
|
|
5761
|
+
function routeArray(value) {
|
|
5762
|
+
if (!Array.isArray(value)) return null;
|
|
5763
|
+
const route = [];
|
|
5764
|
+
for (const item of value) {
|
|
5765
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return null;
|
|
5766
|
+
const raw = item;
|
|
5767
|
+
if (typeof raw.stage !== "string" || typeof raw.evidence !== "string" || typeof raw.duty !== "string") return null;
|
|
5768
|
+
route.push({
|
|
5769
|
+
stage: raw.stage,
|
|
5770
|
+
evidence: raw.evidence,
|
|
5771
|
+
duty: raw.duty,
|
|
5772
|
+
executable: typeof raw.executable === "string" ? raw.executable : void 0,
|
|
5773
|
+
args: raw.args && typeof raw.args === "object" && !Array.isArray(raw.args) ? { ...raw.args } : void 0
|
|
5774
|
+
});
|
|
5775
|
+
}
|
|
5776
|
+
return route;
|
|
5777
|
+
}
|
|
5778
|
+
function managedGoalTypeDefinition(type) {
|
|
5779
|
+
return Object.prototype.hasOwnProperty.call(GOAL_TYPE_DEFINITIONS, type) ? GOAL_TYPE_DEFINITIONS[type] : null;
|
|
5780
|
+
}
|
|
5781
|
+
function expandManagedGoalState(state) {
|
|
5782
|
+
const type = typeof state.extra.type === "string" ? state.extra.type : "";
|
|
5783
|
+
const definition = managedGoalTypeDefinition(type);
|
|
5784
|
+
if (!definition) return state;
|
|
5785
|
+
const destination = state.extra.destination && typeof state.extra.destination === "object" && !Array.isArray(state.extra.destination) ? { ...state.extra.destination } : {};
|
|
5786
|
+
const outcome = typeof destination.outcome === "string" ? destination.outcome : "";
|
|
5787
|
+
const evidence = stringArray(destination.evidence);
|
|
5788
|
+
const duties = stringArray(state.extra.duties);
|
|
5789
|
+
const route = routeArray(state.extra.route);
|
|
5790
|
+
const facts = state.extra.facts && typeof state.extra.facts === "object" && !Array.isArray(state.extra.facts) ? { ...state.extra.facts } : {};
|
|
5791
|
+
const blockers = stringArray(state.extra.blockers);
|
|
5792
|
+
return {
|
|
5793
|
+
...state,
|
|
5794
|
+
extra: {
|
|
5795
|
+
...state.extra,
|
|
5796
|
+
type: definition.type,
|
|
5797
|
+
destination: {
|
|
5798
|
+
...destination,
|
|
5799
|
+
outcome,
|
|
5800
|
+
evidence: evidence && evidence.length > 0 ? evidence : [...definition.evidence]
|
|
5801
|
+
},
|
|
5802
|
+
duties: duties && duties.length > 0 ? duties : [...definition.duties],
|
|
5803
|
+
route: route && route.length > 0 ? route : cloneRoute(definition.route),
|
|
5804
|
+
facts,
|
|
5805
|
+
blockers: blockers ?? []
|
|
5806
|
+
}
|
|
5807
|
+
};
|
|
5808
|
+
}
|
|
5809
|
+
var GOAL_TYPE_DEFINITIONS;
|
|
5810
|
+
var init_typeDefinitions = __esm({
|
|
5811
|
+
"src/goal/typeDefinitions.ts"() {
|
|
5812
|
+
"use strict";
|
|
5813
|
+
GOAL_TYPE_DEFINITIONS = {
|
|
5814
|
+
improve: {
|
|
5815
|
+
type: "improve",
|
|
5816
|
+
evidence: ["planReady", "changeImplemented", "changeVerified"],
|
|
5817
|
+
duties: ["plan", "fix", "review"],
|
|
5818
|
+
route: [
|
|
5819
|
+
{ stage: "plan", evidence: "planReady", duty: "plan", executable: "plan" },
|
|
5820
|
+
{ stage: "implement", evidence: "changeImplemented", duty: "fix", executable: "fix" },
|
|
5821
|
+
{ stage: "review", evidence: "changeVerified", duty: "review", executable: "review" }
|
|
5822
|
+
]
|
|
5823
|
+
},
|
|
5824
|
+
maintain: {
|
|
5825
|
+
type: "maintain",
|
|
5826
|
+
evidence: [],
|
|
5827
|
+
duties: ["cleanup", "code-health", "docs-health", "documentation-maintenance", "memory-compaction", "repo-graph", "skills-research"],
|
|
5828
|
+
route: []
|
|
5829
|
+
},
|
|
5830
|
+
monitor: {
|
|
5831
|
+
type: "monitor",
|
|
5832
|
+
evidence: [],
|
|
5833
|
+
duties: ["health-check", "pr-health-triage", "qa-sweep"],
|
|
5834
|
+
route: []
|
|
5835
|
+
},
|
|
5836
|
+
release: {
|
|
5837
|
+
type: "release",
|
|
5838
|
+
evidence: ["releasePrExists", "mainMerged", "productionDeployed"],
|
|
5839
|
+
duties: ["release", "release-merge", "vercel-production-deploy"],
|
|
5840
|
+
route: [
|
|
5841
|
+
{
|
|
5842
|
+
stage: "release",
|
|
5843
|
+
evidence: "releasePrExists",
|
|
5844
|
+
duty: "release",
|
|
5845
|
+
executable: "release-prepare",
|
|
5846
|
+
args: { issue: { fact: "issue" }, goal: { fact: "goalId" } }
|
|
5847
|
+
},
|
|
5848
|
+
{
|
|
5849
|
+
stage: "merge",
|
|
5850
|
+
evidence: "mainMerged",
|
|
5851
|
+
duty: "release-merge",
|
|
5852
|
+
executable: "release-merge",
|
|
5853
|
+
args: { pr: { fact: "releasePr" }, issue: { fact: "issue" }, goal: { fact: "goalId" } }
|
|
5854
|
+
},
|
|
5855
|
+
{
|
|
5856
|
+
stage: "publish",
|
|
5857
|
+
evidence: "productionDeployed",
|
|
5858
|
+
duty: "vercel-production-deploy",
|
|
5859
|
+
executable: "vercel-production-deploy",
|
|
5860
|
+
args: { goal: { fact: "goalId" } }
|
|
5861
|
+
}
|
|
5862
|
+
]
|
|
5863
|
+
},
|
|
5864
|
+
checklist: {
|
|
5865
|
+
type: "checklist",
|
|
5866
|
+
evidence: ["checklistComplete"],
|
|
5867
|
+
duties: ["task-verifier"],
|
|
5868
|
+
route: [{ stage: "verify", evidence: "checklistComplete", duty: "task-verifier", executable: "task-verifier" }]
|
|
5869
|
+
}
|
|
5870
|
+
};
|
|
5871
|
+
}
|
|
5872
|
+
});
|
|
5873
|
+
|
|
5726
5874
|
// src/stateBranch.ts
|
|
5727
5875
|
function is404(err) {
|
|
5728
5876
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6335,12 +6483,64 @@ function readSimpleGoalTaskSummary(goalId, cwd) {
|
|
|
6335
6483
|
const open = issues.filter((issue) => String(issue.state ?? "").toLowerCase() === "open").length;
|
|
6336
6484
|
return { total, open };
|
|
6337
6485
|
}
|
|
6486
|
+
function ensureIssueFactIfNeeded(goal, goalId, cwd) {
|
|
6487
|
+
if (!routeNeedsIssueFact(goal)) return;
|
|
6488
|
+
const existing = normalizeIssueNumber(goal.facts.issue);
|
|
6489
|
+
if (existing !== null) {
|
|
6490
|
+
goal.facts.issue = existing;
|
|
6491
|
+
return;
|
|
6492
|
+
}
|
|
6493
|
+
goal.facts.issue = findExistingGoalIssue(goalId, cwd) ?? createGoalIssue(goal, goalId, cwd);
|
|
6494
|
+
}
|
|
6495
|
+
function routeNeedsIssueFact(goal) {
|
|
6496
|
+
return goal.route.some(
|
|
6497
|
+
(step) => Object.values(step.args ?? {}).some((value) => {
|
|
6498
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
6499
|
+
const record = value;
|
|
6500
|
+
return Object.keys(record).length === 1 && record.fact === "issue";
|
|
6501
|
+
})
|
|
6502
|
+
);
|
|
6503
|
+
}
|
|
6504
|
+
function normalizeIssueNumber(value) {
|
|
6505
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
|
|
6506
|
+
if (typeof value === "string" && /^\d+$/.test(value)) return Number(value);
|
|
6507
|
+
return null;
|
|
6508
|
+
}
|
|
6509
|
+
function goalIssueMarker(goalId) {
|
|
6510
|
+
return `<!-- kody-managed-goal: ${goalId} -->`;
|
|
6511
|
+
}
|
|
6512
|
+
function findExistingGoalIssue(goalId, cwd) {
|
|
6513
|
+
const marker = goalIssueMarker(goalId);
|
|
6514
|
+
const raw = gh(["issue", "list", "--state", "all", "--limit", "100", "--json", "number,body"], { cwd });
|
|
6515
|
+
const issues = JSON.parse(raw);
|
|
6516
|
+
const match = issues.find((issue) => typeof issue.number === "number" && issue.body?.includes(marker));
|
|
6517
|
+
return match?.number ?? null;
|
|
6518
|
+
}
|
|
6519
|
+
function createGoalIssue(goal, goalId, cwd) {
|
|
6520
|
+
const prefix = goal.type === "release" ? "Release" : "Goal";
|
|
6521
|
+
const outcome = goal.destination.outcome.trim() || goalId;
|
|
6522
|
+
const title = `${prefix}: ${outcome}`.slice(0, 120);
|
|
6523
|
+
const body = [
|
|
6524
|
+
`Managed goal: \`${goalId}\``,
|
|
6525
|
+
"",
|
|
6526
|
+
`Finish line: ${outcome}`,
|
|
6527
|
+
"",
|
|
6528
|
+
"This issue was created by Kody so goal duties that require an issue can run end to end.",
|
|
6529
|
+
"",
|
|
6530
|
+
goalIssueMarker(goalId)
|
|
6531
|
+
].join("\n");
|
|
6532
|
+
const out = gh(["issue", "create", "--title", title, "--body-file", "-"], { input: body, cwd });
|
|
6533
|
+
const match = out.match(/\/issues\/(\d+)(?:[/?#]|$)/);
|
|
6534
|
+
if (!match) throw new Error(`gh issue create returned unexpected output: ${out}`);
|
|
6535
|
+
return Number(match[1]);
|
|
6536
|
+
}
|
|
6338
6537
|
var advanceManagedGoal;
|
|
6339
6538
|
var init_advanceManagedGoal = __esm({
|
|
6340
6539
|
"src/scripts/advanceManagedGoal.ts"() {
|
|
6341
6540
|
"use strict";
|
|
6342
6541
|
init_manager();
|
|
6343
6542
|
init_state2();
|
|
6543
|
+
init_typeDefinitions();
|
|
6344
6544
|
init_issue();
|
|
6345
6545
|
init_goalDutyScheduling();
|
|
6346
6546
|
advanceManagedGoal = async (ctx) => {
|
|
@@ -6352,6 +6552,7 @@ var init_advanceManagedGoal = __esm({
|
|
|
6352
6552
|
return;
|
|
6353
6553
|
}
|
|
6354
6554
|
ctx.data.goalOriginalStateText = serializeGoalState(goal.raw);
|
|
6555
|
+
goal.raw = expandManagedGoalState(goal.raw);
|
|
6355
6556
|
const managed = managedGoalFromState(goal.raw);
|
|
6356
6557
|
if (!managed) {
|
|
6357
6558
|
ctx.output.reason = "goal has no managed-goal contract; nothing to advance";
|
|
@@ -6363,6 +6564,17 @@ var init_advanceManagedGoal = __esm({
|
|
|
6363
6564
|
if (previousGoalIdFact === void 0) delete managed.facts.goalId;
|
|
6364
6565
|
else managed.facts.goalId = previousGoalIdFact;
|
|
6365
6566
|
};
|
|
6567
|
+
try {
|
|
6568
|
+
ensureIssueFactIfNeeded(managed, goal.id, ctx.cwd);
|
|
6569
|
+
} catch (err) {
|
|
6570
|
+
const reason = `failed to prepare goal issue fact: ${err instanceof Error ? err.message : String(err)}`;
|
|
6571
|
+
managed.stage = "blocked";
|
|
6572
|
+
if (!managed.blockers.includes(reason)) managed.blockers.push(reason);
|
|
6573
|
+
restoreGoalIdFact();
|
|
6574
|
+
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
6575
|
+
ctx.output.reason = reason;
|
|
6576
|
+
return;
|
|
6577
|
+
}
|
|
6366
6578
|
if (isDutyCadenceGoal(managed, goal.raw.extra)) {
|
|
6367
6579
|
const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
|
|
6368
6580
|
const decision2 = await planGoalDutySchedule({
|
|
@@ -16554,15 +16766,23 @@ async function runCi(argv) {
|
|
|
16554
16766
|
const dispatchEventPath = process.env.GITHUB_EVENT_PATH;
|
|
16555
16767
|
let manualWorkflowDispatch = false;
|
|
16556
16768
|
let forceRunAction = null;
|
|
16769
|
+
let forceRunCliArgs = {};
|
|
16557
16770
|
if (!args.issueNumber && !autoFallback && eventName === "workflow_dispatch" && dispatchEventPath && fs42.existsSync(dispatchEventPath)) {
|
|
16558
16771
|
try {
|
|
16559
16772
|
const evt = JSON.parse(fs42.readFileSync(dispatchEventPath, "utf-8"));
|
|
16560
16773
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
16561
16774
|
const sessionInput = String(evt?.inputs?.sessionId ?? "");
|
|
16562
16775
|
const dutyInput = String(evt?.inputs?.duty ?? evt?.inputs?.executable ?? "").trim();
|
|
16776
|
+
const messageInput = String(evt?.inputs?.message ?? "").trim();
|
|
16563
16777
|
const noTarget = !sessionInput && !(Number.isFinite(issueInput) && issueInput > 0);
|
|
16564
|
-
if (noTarget && dutyInput)
|
|
16565
|
-
|
|
16778
|
+
if (noTarget && dutyInput) {
|
|
16779
|
+
forceRunAction = dutyInput;
|
|
16780
|
+
if (dutyInput === "goal-manager" && messageInput) {
|
|
16781
|
+
forceRunCliArgs = { goal: messageInput };
|
|
16782
|
+
}
|
|
16783
|
+
} else {
|
|
16784
|
+
manualWorkflowDispatch = noTarget;
|
|
16785
|
+
}
|
|
16566
16786
|
} catch {
|
|
16567
16787
|
manualWorkflowDispatch = false;
|
|
16568
16788
|
}
|
|
@@ -16575,6 +16795,10 @@ async function runCi(argv) {
|
|
|
16575
16795
|
`);
|
|
16576
16796
|
return 64;
|
|
16577
16797
|
}
|
|
16798
|
+
if (route.executable === "goal-manager" && typeof forceRunCliArgs.goal !== "string") {
|
|
16799
|
+
process.stderr.write("[kody] manual goal-manager run requires message goal id\n");
|
|
16800
|
+
return 64;
|
|
16801
|
+
}
|
|
16578
16802
|
process.stdout.write(`\u2192 kody: manual one-shot run of duty action ${route.action} (${route.duty})
|
|
16579
16803
|
|
|
16580
16804
|
`);
|
|
@@ -16611,7 +16835,7 @@ async function runCi(argv) {
|
|
|
16611
16835
|
action: route.action,
|
|
16612
16836
|
duty: route.duty,
|
|
16613
16837
|
executable: route.executable,
|
|
16614
|
-
cliArgs: route.cliArgs,
|
|
16838
|
+
cliArgs: { ...route.cliArgs, ...forceRunCliArgs },
|
|
16615
16839
|
flavor: "instant",
|
|
16616
16840
|
force: true
|
|
16617
16841
|
},
|
|
@@ -15,6 +15,8 @@ import type { Phase } from "../state.js"
|
|
|
15
15
|
// Profile shape (mirrors the JSON on disk).
|
|
16
16
|
// ────────────────────────────────────────────────────────────────────────────
|
|
17
17
|
|
|
18
|
+
export type CapabilityKind = "observe" | "act" | "verify"
|
|
19
|
+
|
|
18
20
|
export interface Profile {
|
|
19
21
|
name: string
|
|
20
22
|
/**
|
|
@@ -33,6 +35,11 @@ export interface Profile {
|
|
|
33
35
|
*/
|
|
34
36
|
staff?: string
|
|
35
37
|
describe: string
|
|
38
|
+
/**
|
|
39
|
+
* Author-facing capability promise for a duty/executable. This classifies the
|
|
40
|
+
* shape of result it should return; it does not change executor control flow.
|
|
41
|
+
*/
|
|
42
|
+
capabilityKind?: CapabilityKind
|
|
36
43
|
/**
|
|
37
44
|
* Semantic role — what this executable IS, not when it runs.
|
|
38
45
|
* - primitive: single-step agent executor (flow → agent → verify → commit → PR).
|
|
@@ -390,6 +397,58 @@ export interface OutputContract {
|
|
|
390
397
|
}
|
|
391
398
|
}
|
|
392
399
|
|
|
400
|
+
export interface CapabilityAlert {
|
|
401
|
+
level?: "info" | "warning" | "error"
|
|
402
|
+
message: string
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export interface CapabilitySuggestedAction {
|
|
406
|
+
action: string
|
|
407
|
+
args?: Record<string, unknown>
|
|
408
|
+
reason?: string
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export interface CapabilityResourceRef {
|
|
412
|
+
type: string
|
|
413
|
+
id?: string | number
|
|
414
|
+
number?: number
|
|
415
|
+
url?: string
|
|
416
|
+
name?: string
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export interface CapabilityEvidenceItem {
|
|
420
|
+
source?: string
|
|
421
|
+
message: string
|
|
422
|
+
url?: string
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export interface ObserveResult {
|
|
426
|
+
kind: "observe"
|
|
427
|
+
facts?: Record<string, unknown>
|
|
428
|
+
alerts?: CapabilityAlert[]
|
|
429
|
+
suggestedActions?: CapabilitySuggestedAction[]
|
|
430
|
+
evidence?: Record<string, unknown>
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export interface ActResult {
|
|
434
|
+
kind: "act"
|
|
435
|
+
status: "created" | "changed" | "triggered" | "skipped" | "failed"
|
|
436
|
+
changedResources?: CapabilityResourceRef[]
|
|
437
|
+
createdResources?: CapabilityResourceRef[]
|
|
438
|
+
actionResult?: Record<string, unknown>
|
|
439
|
+
evidence?: Record<string, unknown>
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export interface VerifyResult {
|
|
443
|
+
kind: "verify"
|
|
444
|
+
passed: boolean
|
|
445
|
+
evidence?: CapabilityEvidenceItem[]
|
|
446
|
+
blockers?: string[]
|
|
447
|
+
facts?: Record<string, unknown>
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export type CapabilityResult = ObserveResult | ActResult | VerifyResult
|
|
451
|
+
|
|
393
452
|
// ────────────────────────────────────────────────────────────────────────────
|
|
394
453
|
// Run-time context passed to every script.
|
|
395
454
|
// ────────────────────────────────────────────────────────────────────────────
|
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.234",
|
|
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",
|