@kody-ade/kody-engine 0.4.357 → 0.4.359
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 +391 -771
- 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.359",
|
|
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",
|
|
@@ -289,8 +289,8 @@ function isRunningAsBot() {
|
|
|
289
289
|
}
|
|
290
290
|
function postIssueComment(issueNumber, body, cwd) {
|
|
291
291
|
if (isRunningAsBot()) {
|
|
292
|
-
const
|
|
293
|
-
if (
|
|
292
|
+
const slug = detectBotDispatchShape(body);
|
|
293
|
+
if (slug) throw new BotDispatchCommentError(slug);
|
|
294
294
|
}
|
|
295
295
|
try {
|
|
296
296
|
gh(["issue", "comment", String(issueNumber), "--body-file", "-"], {
|
|
@@ -401,8 +401,8 @@ function getPrLatestReviewBody(prNumber, cwd) {
|
|
|
401
401
|
}
|
|
402
402
|
function postPrReviewComment(prNumber, body, cwd) {
|
|
403
403
|
if (isRunningAsBot()) {
|
|
404
|
-
const
|
|
405
|
-
if (
|
|
404
|
+
const slug = detectBotDispatchShape(body);
|
|
405
|
+
if (slug) throw new BotDispatchCommentError(slug);
|
|
406
406
|
}
|
|
407
407
|
try {
|
|
408
408
|
gh(["pr", "comment", String(prNumber), "--body-file", "-"], {
|
|
@@ -426,9 +426,9 @@ var init_issue = __esm({
|
|
|
426
426
|
DEFAULT_RATE_LIMIT_BASE_DELAY_MS = 1e3;
|
|
427
427
|
DEFAULT_RATE_LIMIT_MAX_WAIT_MS = 65 * 60 * 1e3;
|
|
428
428
|
BotDispatchCommentError = class extends Error {
|
|
429
|
-
constructor(
|
|
429
|
+
constructor(slug) {
|
|
430
430
|
super(
|
|
431
|
-
`bot self-dispatch via @kody comments is banned. Refusing to post "@kody ${
|
|
431
|
+
`bot self-dispatch via @kody comments is banned. Refusing to post "@kody ${slug} \u2026" \u2014 use runImplementationChain (same-run) or dispatchImplementation (cross-run) instead. See docs/capability-dispatch.md for the contract.`
|
|
432
432
|
);
|
|
433
433
|
this.name = "BotDispatchCommentError";
|
|
434
434
|
}
|
|
@@ -458,8 +458,8 @@ function isAlreadyExists(err) {
|
|
|
458
458
|
const msg = err instanceof Error ? err.message : String(err);
|
|
459
459
|
return /HTTP 422/i.test(msg) || /Reference already exists/i.test(msg);
|
|
460
460
|
}
|
|
461
|
-
function parseStateRepoSlug(
|
|
462
|
-
const value =
|
|
461
|
+
function parseStateRepoSlug(slug, field = "stateRepo") {
|
|
462
|
+
const value = slug.trim();
|
|
463
463
|
let repoPath = value;
|
|
464
464
|
if (/^https?:\/\//i.test(value)) {
|
|
465
465
|
let parsed;
|
|
@@ -694,16 +694,16 @@ function parseModelRuntimeConfig(modelSpec, rawConfig) {
|
|
|
694
694
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
695
695
|
throw new Error("KODY_MODEL_CONFIG must be a JSON object");
|
|
696
696
|
}
|
|
697
|
-
const
|
|
698
|
-
const modelName = optionalRuntimeString(
|
|
697
|
+
const record = parsed;
|
|
698
|
+
const modelName = optionalRuntimeString(record, "modelName");
|
|
699
699
|
if (!modelName) {
|
|
700
700
|
throw new Error("KODY_MODEL_CONFIG.modelName is required");
|
|
701
701
|
}
|
|
702
|
-
const protocol = optionalRuntimeString(
|
|
703
|
-
const baseURL = optionalRuntimeString(
|
|
704
|
-
const apiKeyEnvVar = optionalRuntimeString(
|
|
705
|
-
const spec = optionalRuntimeString(
|
|
706
|
-
const provider = optionalRuntimeString(
|
|
702
|
+
const protocol = optionalRuntimeString(record, "protocol");
|
|
703
|
+
const baseURL = optionalRuntimeString(record, "baseURL");
|
|
704
|
+
const apiKeyEnvVar = optionalRuntimeString(record, "apiKeyEnvVar");
|
|
705
|
+
const spec = optionalRuntimeString(record, "spec");
|
|
706
|
+
const provider = optionalRuntimeString(record, "provider") ?? fallback.provider;
|
|
707
707
|
const out = {
|
|
708
708
|
provider,
|
|
709
709
|
model: modelName
|
|
@@ -854,11 +854,11 @@ function parseGoalActivations(raw) {
|
|
|
854
854
|
const seen = /* @__PURE__ */ new Set();
|
|
855
855
|
for (const value of raw) {
|
|
856
856
|
if (typeof value === "string") {
|
|
857
|
-
const
|
|
858
|
-
if (!
|
|
859
|
-
if (!seen.has(
|
|
860
|
-
seen.add(
|
|
861
|
-
out.push(
|
|
857
|
+
const slug = parseSlug(value, "company.activeGoals");
|
|
858
|
+
if (!slug) continue;
|
|
859
|
+
if (!seen.has(slug)) {
|
|
860
|
+
seen.add(slug);
|
|
861
|
+
out.push(slug);
|
|
862
862
|
}
|
|
863
863
|
continue;
|
|
864
864
|
}
|
|
@@ -908,20 +908,20 @@ function parseSlugArray(raw, field) {
|
|
|
908
908
|
if (!Array.isArray(raw)) throw new Error(`kody.config.json: ${field} must be an array of strings`);
|
|
909
909
|
const out = [];
|
|
910
910
|
for (const value of raw) {
|
|
911
|
-
const
|
|
912
|
-
if (!
|
|
913
|
-
out.push(
|
|
911
|
+
const slug = parseSlug(value, field);
|
|
912
|
+
if (!slug) continue;
|
|
913
|
+
out.push(slug);
|
|
914
914
|
}
|
|
915
915
|
return [...new Set(out)];
|
|
916
916
|
}
|
|
917
917
|
function parseSlug(value, field) {
|
|
918
918
|
if (typeof value !== "string") throw new Error(`kody.config.json: ${field} entries must be strings`);
|
|
919
|
-
const
|
|
920
|
-
if (!
|
|
921
|
-
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(
|
|
919
|
+
const slug = value.trim();
|
|
920
|
+
if (!slug) return "";
|
|
921
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(slug)) {
|
|
922
922
|
throw new Error(`kody.config.json: ${field} contains invalid slug "${value}"`);
|
|
923
923
|
}
|
|
924
|
-
return
|
|
924
|
+
return slug;
|
|
925
925
|
}
|
|
926
926
|
function recordValue(raw) {
|
|
927
927
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : void 0;
|
|
@@ -1876,8 +1876,8 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
1876
1876
|
function isCapabilityFolder(dir) {
|
|
1877
1877
|
return fs4.existsSync(path6.join(dir, CAPABILITY_PROFILE_FILE)) && fs4.existsSync(path6.join(dir, CAPABILITY_BODY_FILE));
|
|
1878
1878
|
}
|
|
1879
|
-
function readCapabilityFolder(root,
|
|
1880
|
-
const dir = path6.join(root,
|
|
1879
|
+
function readCapabilityFolder(root, slug) {
|
|
1880
|
+
const dir = path6.join(root, slug);
|
|
1881
1881
|
const profilePath = path6.join(dir, CAPABILITY_PROFILE_FILE);
|
|
1882
1882
|
const bodyPath = path6.join(dir, CAPABILITY_BODY_FILE);
|
|
1883
1883
|
if (!fs4.existsSync(profilePath) || !fs4.statSync(profilePath).isFile()) return null;
|
|
@@ -1885,9 +1885,9 @@ function readCapabilityFolder(root, slug2) {
|
|
|
1885
1885
|
try {
|
|
1886
1886
|
const rawProfile = JSON.parse(fs4.readFileSync(profilePath, "utf-8"));
|
|
1887
1887
|
const rawBody = fs4.readFileSync(bodyPath, "utf-8");
|
|
1888
|
-
const { title, body } = parseCapabilityBody(rawBody,
|
|
1888
|
+
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
1889
1889
|
return {
|
|
1890
|
-
slug
|
|
1890
|
+
slug,
|
|
1891
1891
|
dir,
|
|
1892
1892
|
profilePath,
|
|
1893
1893
|
bodyPath,
|
|
@@ -1934,11 +1934,11 @@ function parseCapabilityToolMode(raw) {
|
|
|
1934
1934
|
if (raw === "lock" || raw === "append") return raw;
|
|
1935
1935
|
return void 0;
|
|
1936
1936
|
}
|
|
1937
|
-
function parseCapabilityBody(raw,
|
|
1937
|
+
function parseCapabilityBody(raw, slug) {
|
|
1938
1938
|
const trimmed = raw.trim();
|
|
1939
1939
|
const firstLine2 = trimmed.split("\n", 1)[0] ?? "";
|
|
1940
1940
|
const h1 = /^#\s+(.+?)\s*$/.exec(firstLine2);
|
|
1941
|
-
const title = h1 ? h1[1].trim() : humanizeSlug(
|
|
1941
|
+
const title = h1 ? h1[1].trim() : humanizeSlug(slug);
|
|
1942
1942
|
const body = stripLeadingH1(raw);
|
|
1943
1943
|
return { title, body };
|
|
1944
1944
|
}
|
|
@@ -1952,8 +1952,8 @@ function stripLeadingH1(raw) {
|
|
|
1952
1952
|
}
|
|
1953
1953
|
return lines.slice(i).join("\n");
|
|
1954
1954
|
}
|
|
1955
|
-
function humanizeSlug(
|
|
1956
|
-
return
|
|
1955
|
+
function humanizeSlug(slug) {
|
|
1956
|
+
return slug.split(/[-_]+/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
1957
1957
|
}
|
|
1958
1958
|
function stringField(value) {
|
|
1959
1959
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
@@ -2280,10 +2280,10 @@ function resolveCapabilityAction(action, projectCapabilitiesRoot = getProjectCap
|
|
|
2280
2280
|
function hasCapabilityAction(action, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2281
2281
|
return resolveCapabilityAction(action, projectCapabilitiesRoot) !== null;
|
|
2282
2282
|
}
|
|
2283
|
-
function resolveCapabilityFolder(
|
|
2284
|
-
if (!isSafeName(
|
|
2283
|
+
function resolveCapabilityFolder(slug, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2284
|
+
if (!isSafeName(slug)) return null;
|
|
2285
2285
|
for (const root of getCapabilityRoots(projectCapabilitiesRoot)) {
|
|
2286
|
-
const capability = readCapabilityFolder(root,
|
|
2286
|
+
const capability = readCapabilityFolder(root, slug);
|
|
2287
2287
|
if (capability) return capability;
|
|
2288
2288
|
}
|
|
2289
2289
|
return null;
|
|
@@ -2339,17 +2339,17 @@ function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
|
2339
2339
|
function listFolderCapabilityActions(root, source) {
|
|
2340
2340
|
if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
|
|
2341
2341
|
const out = [];
|
|
2342
|
-
for (const
|
|
2343
|
-
if (!isSafeName(
|
|
2344
|
-
const capability = readCapabilityFolder(root,
|
|
2342
|
+
for (const slug of listCapabilityFolderSlugs(root)) {
|
|
2343
|
+
if (!isSafeName(slug)) continue;
|
|
2344
|
+
const capability = readCapabilityFolder(root, slug);
|
|
2345
2345
|
if (!capability) continue;
|
|
2346
2346
|
if (capability.config.internal === true || capability.config.public === false) continue;
|
|
2347
|
-
const action = capability.config.action ??
|
|
2347
|
+
const action = capability.config.action ?? slug;
|
|
2348
2348
|
const { implementation, cliArgs } = resolveCapabilityExecution(capability);
|
|
2349
2349
|
if (hasUnresolvedExplicitImplementation(capability, implementation)) continue;
|
|
2350
2350
|
out.push({
|
|
2351
2351
|
action,
|
|
2352
|
-
capability:
|
|
2352
|
+
capability: slug,
|
|
2353
2353
|
implementation,
|
|
2354
2354
|
cliArgs,
|
|
2355
2355
|
source,
|
|
@@ -2371,15 +2371,15 @@ function hasUnresolvedExplicitImplementation(capability, implementation) {
|
|
|
2371
2371
|
function listBuiltinCapabilityActions(root = getBuiltinCapabilitiesRoot()) {
|
|
2372
2372
|
if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
|
|
2373
2373
|
const out = [];
|
|
2374
|
-
for (const
|
|
2375
|
-
if (!isSafeName(
|
|
2376
|
-
const capability = readCapabilityFolder(root,
|
|
2374
|
+
for (const slug of listCapabilityFolderSlugs(root)) {
|
|
2375
|
+
if (!isSafeName(slug)) continue;
|
|
2376
|
+
const capability = readCapabilityFolder(root, slug);
|
|
2377
2377
|
if (!capability) continue;
|
|
2378
|
-
const action = capability.config.action ??
|
|
2379
|
-
const implementation = capability.config.implementation ??
|
|
2378
|
+
const action = capability.config.action ?? slug;
|
|
2379
|
+
const implementation = capability.config.implementation ?? slug;
|
|
2380
2380
|
out.push({
|
|
2381
2381
|
action,
|
|
2382
|
-
capability:
|
|
2382
|
+
capability: slug,
|
|
2383
2383
|
implementation,
|
|
2384
2384
|
cliArgs: {},
|
|
2385
2385
|
source: "builtin",
|
|
@@ -2553,8 +2553,8 @@ function listRepairCandidates(repoSlug) {
|
|
|
2553
2553
|
function dispatchVerb(workflowFile, repoSlug, capability, prNumber) {
|
|
2554
2554
|
return dispatchWorkflow(workflowFile, capability, prNumber, repoSlug);
|
|
2555
2555
|
}
|
|
2556
|
-
function capabilityMarker(
|
|
2557
|
-
return `<!-- kody-capability: ${
|
|
2556
|
+
function capabilityMarker(slug) {
|
|
2557
|
+
return `<!-- kody-capability: ${slug} -->`;
|
|
2558
2558
|
}
|
|
2559
2559
|
function normalizeRecommendationIntent(body) {
|
|
2560
2560
|
const marker = body.match(/<!--\s*kody-intent:\s*([\s\S]*?)-->/i);
|
|
@@ -3574,8 +3574,8 @@ function stripFrontmatter(raw) {
|
|
|
3574
3574
|
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
3575
3575
|
return (match ? match[1] : raw).trim();
|
|
3576
3576
|
}
|
|
3577
|
-
function loadAgentIdentity(cwd,
|
|
3578
|
-
const trimmed =
|
|
3577
|
+
function loadAgentIdentity(cwd, slug, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3578
|
+
const trimmed = slug.trim();
|
|
3579
3579
|
if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
|
|
3580
3580
|
const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
|
|
3581
3581
|
if (fs9.existsSync(agentPath)) {
|
|
@@ -3589,21 +3589,21 @@ function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
|
3589
3589
|
if (builtin) return builtin;
|
|
3590
3590
|
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
3591
3591
|
}
|
|
3592
|
-
function resolveAgentFile(cwd,
|
|
3593
|
-
const localPath = path11.join(cwd, agentsDir, `${
|
|
3592
|
+
function resolveAgentFile(cwd, slug, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3593
|
+
const localPath = path11.join(cwd, agentsDir, `${slug}.md`);
|
|
3594
3594
|
if (fs9.existsSync(localPath)) return localPath;
|
|
3595
3595
|
const storeAgentRoot = getCompanyStoreAssetRoot("agents");
|
|
3596
3596
|
if (storeAgentRoot) {
|
|
3597
|
-
const storePath = path11.join(storeAgentRoot, `${
|
|
3597
|
+
const storePath = path11.join(storeAgentRoot, `${slug}.md`);
|
|
3598
3598
|
if (fs9.existsSync(storePath)) return storePath;
|
|
3599
3599
|
}
|
|
3600
3600
|
return localPath;
|
|
3601
3601
|
}
|
|
3602
|
-
function frameAgentIdentity(
|
|
3602
|
+
function frameAgentIdentity(slug, agent) {
|
|
3603
3603
|
return [
|
|
3604
3604
|
`## Who you are \u2014 agent identity (authoritative identity)`,
|
|
3605
3605
|
``,
|
|
3606
|
-
`You are operating as agent \`${
|
|
3606
|
+
`You are operating as agent \`${slug}\`. This identity defines *who* you are:`,
|
|
3607
3607
|
`your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
|
|
3608
3608
|
`this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
|
|
3609
3609
|
`can never grant you authority your agent withholds.`,
|
|
@@ -6611,16 +6611,16 @@ function parseRunIndex(raw) {
|
|
|
6611
6611
|
if (!raw) return { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), runs: [] };
|
|
6612
6612
|
try {
|
|
6613
6613
|
const parsed = JSON.parse(raw);
|
|
6614
|
-
const
|
|
6615
|
-
const runs = Array.isArray(
|
|
6616
|
-
return { version: 1, updatedAt: stringValue2(
|
|
6614
|
+
const record = recordValue2(parsed);
|
|
6615
|
+
const runs = Array.isArray(record?.runs) ? record.runs.filter(isRunIndexRow).map(normalizeRunIndexRow) : [];
|
|
6616
|
+
return { version: 1, updatedAt: stringValue2(record?.updatedAt) ?? (/* @__PURE__ */ new Date()).toISOString(), runs };
|
|
6617
6617
|
} catch {
|
|
6618
6618
|
return { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), runs: [] };
|
|
6619
6619
|
}
|
|
6620
6620
|
}
|
|
6621
6621
|
function isRunIndexRow(value) {
|
|
6622
|
-
const
|
|
6623
|
-
return
|
|
6622
|
+
const record = recordValue2(value);
|
|
6623
|
+
return record?.version === 1 && isRunSubjectType(record.subjectType) && typeof record.subjectId === "string" && typeof record.id === "string" && typeof record.status === "string" && typeof record.title === "string" && typeof record.updatedAt === "string";
|
|
6624
6624
|
}
|
|
6625
6625
|
function isRunSubjectType(value) {
|
|
6626
6626
|
return value === "goal" || value === "loop" || value === "workflow";
|
|
@@ -7225,8 +7225,8 @@ function applySimpleGoalTaskSummary(goal, summary) {
|
|
|
7225
7225
|
}
|
|
7226
7226
|
function isFactReference(value) {
|
|
7227
7227
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
7228
|
-
const
|
|
7229
|
-
return Object.keys(
|
|
7228
|
+
const record = value;
|
|
7229
|
+
return Object.keys(record).length === 1 && typeof record.fact === "string" && record.fact.length > 0;
|
|
7230
7230
|
}
|
|
7231
7231
|
function isCliArgValue(value) {
|
|
7232
7232
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
@@ -8134,8 +8134,8 @@ function serializeTodoGoalState(goalId, state, previousRaw) {
|
|
|
8134
8134
|
)}
|
|
8135
8135
|
`;
|
|
8136
8136
|
}
|
|
8137
|
-
function isManagedTodoRecord(
|
|
8138
|
-
return
|
|
8137
|
+
function isManagedTodoRecord(record) {
|
|
8138
|
+
return record.managed === true || record.managed === "true" || record.managedModel === "agentGoal" || record.managedModel === "agentLoop";
|
|
8139
8139
|
}
|
|
8140
8140
|
function itemFromEvidence(evidence, step, facts, evidenceState, createdAt, now, prior) {
|
|
8141
8141
|
const completed = facts[evidence] === true;
|
|
@@ -8696,10 +8696,10 @@ function normalizeWorkflowCapabilities(value) {
|
|
|
8696
8696
|
const capabilities = [];
|
|
8697
8697
|
for (const item of value) {
|
|
8698
8698
|
if (typeof item !== "string") continue;
|
|
8699
|
-
const
|
|
8700
|
-
if (!CAPABILITY_ID_PATTERN.test(
|
|
8701
|
-
seen.add(
|
|
8702
|
-
capabilities.push(
|
|
8699
|
+
const slug = item.trim();
|
|
8700
|
+
if (!CAPABILITY_ID_PATTERN.test(slug) || seen.has(slug)) continue;
|
|
8701
|
+
seen.add(slug);
|
|
8702
|
+
capabilities.push(slug);
|
|
8703
8703
|
}
|
|
8704
8704
|
return capabilities;
|
|
8705
8705
|
}
|
|
@@ -8829,8 +8829,8 @@ function isStateUnchanged(prev, next) {
|
|
|
8829
8829
|
if (prev.done !== next.done) return false;
|
|
8830
8830
|
return JSON.stringify(prev.data) === JSON.stringify(next.data);
|
|
8831
8831
|
}
|
|
8832
|
-
function stateFilePath(jobsDir,
|
|
8833
|
-
return `${jobsDir.replace(/\/+$/, "")}/${
|
|
8832
|
+
function stateFilePath(jobsDir, slug) {
|
|
8833
|
+
return `${jobsDir.replace(/\/+$/, "")}/${slug}/state.json`;
|
|
8834
8834
|
}
|
|
8835
8835
|
function slugFromStateFilePath(filePath) {
|
|
8836
8836
|
if (/\/state\.json$/i.test(filePath)) {
|
|
@@ -8872,8 +8872,8 @@ var init_contentsApiBackend = __esm({
|
|
|
8872
8872
|
this.jobsDir = stateRepoJobsDir(opts.jobsDir);
|
|
8873
8873
|
this.cwd = opts.cwd;
|
|
8874
8874
|
}
|
|
8875
|
-
load(
|
|
8876
|
-
const filePath = stateFilePath(this.jobsDir,
|
|
8875
|
+
load(slug) {
|
|
8876
|
+
const filePath = stateFilePath(this.jobsDir, slug);
|
|
8877
8877
|
const loaded = readStateText(this.config, this.cwd, filePath);
|
|
8878
8878
|
if (!loaded) {
|
|
8879
8879
|
return { path: filePath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
@@ -8893,20 +8893,20 @@ var init_contentsApiBackend = __esm({
|
|
|
8893
8893
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
8894
8894
|
return false;
|
|
8895
8895
|
}
|
|
8896
|
-
const
|
|
8896
|
+
const slug = slugFromStateFilePath(loaded.path);
|
|
8897
8897
|
const body = `${JSON.stringify(next, null, 2)}
|
|
8898
8898
|
`;
|
|
8899
|
-
const message = `chore(jobs): update state for ${
|
|
8899
|
+
const message = `chore(jobs): update state for ${slug} (rev ${next.rev})`;
|
|
8900
8900
|
const sha = typeof loaded.handle === "string" ? loaded.handle : void 0;
|
|
8901
8901
|
try {
|
|
8902
8902
|
writeStateText(this.config, this.cwd, loaded.path, body, message, sha);
|
|
8903
8903
|
} catch (err) {
|
|
8904
8904
|
if (!isShaConflict(err)) throw err;
|
|
8905
|
-
const current = this.load(
|
|
8905
|
+
const current = this.load(slug);
|
|
8906
8906
|
if (!current.created && isStateUnchanged(current.state, next)) return false;
|
|
8907
8907
|
const currentSha = typeof current.handle === "string" ? current.handle : void 0;
|
|
8908
8908
|
process.stderr.write(
|
|
8909
|
-
`[kody] jobState: concurrent write detected for ${
|
|
8909
|
+
`[kody] jobState: concurrent write detected for ${slug}; reloaded SHA and retrying (last-write-wins)
|
|
8910
8910
|
`
|
|
8911
8911
|
);
|
|
8912
8912
|
writeStateText(this.config, this.cwd, loaded.path, body, message, currentSha);
|
|
@@ -9033,8 +9033,8 @@ var init_localFileBackend = __esm({
|
|
|
9033
9033
|
`);
|
|
9034
9034
|
}
|
|
9035
9035
|
}
|
|
9036
|
-
load(
|
|
9037
|
-
const relPath = stateFilePath(this.jobsDir,
|
|
9036
|
+
load(slug) {
|
|
9037
|
+
const relPath = stateFilePath(this.jobsDir, slug);
|
|
9038
9038
|
const absPath = path27.join(this.cwd, relPath);
|
|
9039
9039
|
if (!fs29.existsSync(absPath)) {
|
|
9040
9040
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
@@ -9166,18 +9166,18 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9166
9166
|
const blockers = [];
|
|
9167
9167
|
const explicitCapabilityTarget = opts.goal.loopTarget?.type === "capability" ? opts.goal.loopTarget.id.trim() : "";
|
|
9168
9168
|
const capabilitySlugs = explicitCapabilityTarget ? [explicitCapabilityTarget] : opts.goal.capabilities;
|
|
9169
|
-
for (const
|
|
9170
|
-
const capability2 = resolveCapabilityFolder(
|
|
9169
|
+
for (const slug of capabilitySlugs) {
|
|
9170
|
+
const capability2 = resolveCapabilityFolder(slug, jobsRoot);
|
|
9171
9171
|
const status = await describeCapabilitySchedule(
|
|
9172
9172
|
capability2,
|
|
9173
|
-
|
|
9173
|
+
slug,
|
|
9174
9174
|
backend,
|
|
9175
|
-
opts.previousScheduleState?.capabilities[
|
|
9175
|
+
opts.previousScheduleState?.capabilities[slug]
|
|
9176
9176
|
);
|
|
9177
|
-
statuses[
|
|
9178
|
-
if (status.state === "blocked") blockers.push(`${
|
|
9177
|
+
statuses[slug] = status;
|
|
9178
|
+
if (status.state === "blocked") blockers.push(`${slug}: ${status.reason}`);
|
|
9179
9179
|
}
|
|
9180
|
-
const due = capabilitySlugs.map((
|
|
9180
|
+
const due = capabilitySlugs.map((slug) => statuses[slug]).filter((status) => status?.state === "due").sort(compareOldestLastFired)[0];
|
|
9181
9181
|
if (!due) {
|
|
9182
9182
|
const reason = blockers.length > 0 ? "no runnable capability; blocked capabilities need attention" : "no runnable capability";
|
|
9183
9183
|
const kind = blockers.length > 0 ? "blocked" : "idle";
|
|
@@ -9226,18 +9226,18 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9226
9226
|
}
|
|
9227
9227
|
};
|
|
9228
9228
|
}
|
|
9229
|
-
async function describeCapabilitySchedule(capability,
|
|
9230
|
-
if (!capability) return { slug
|
|
9229
|
+
async function describeCapabilitySchedule(capability, slug, backend, previous) {
|
|
9230
|
+
if (!capability) return { slug, state: "blocked", reason: "capability folder missing" };
|
|
9231
9231
|
const { config } = capability;
|
|
9232
9232
|
if (config.disabled === true) {
|
|
9233
|
-
return { slug
|
|
9233
|
+
return { slug, title: capability.title, state: "disabled", reason: "disabled" };
|
|
9234
9234
|
}
|
|
9235
9235
|
if (!config.agent || config.agent.trim().length === 0) {
|
|
9236
|
-
return { slug
|
|
9236
|
+
return { slug, title: capability.title, state: "blocked", reason: "no agent assigned" };
|
|
9237
9237
|
}
|
|
9238
9238
|
if (config.implementations && config.implementations.length > 1) {
|
|
9239
9239
|
return {
|
|
9240
|
-
slug
|
|
9240
|
+
slug,
|
|
9241
9241
|
title: capability.title,
|
|
9242
9242
|
state: "blocked",
|
|
9243
9243
|
reason: "multi-implementation capability needs task-jobs route"
|
|
@@ -9246,20 +9246,20 @@ async function describeCapabilitySchedule(capability, slug2, backend, previous)
|
|
|
9246
9246
|
let lastFiredAt = validIso(previous?.lastFiredAt) ? previous?.lastFiredAt : void 0;
|
|
9247
9247
|
try {
|
|
9248
9248
|
if (!lastFiredAt) {
|
|
9249
|
-
const loaded = await backend.load(
|
|
9249
|
+
const loaded = await backend.load(slug);
|
|
9250
9250
|
const raw = loaded.state.data?.lastFiredAt;
|
|
9251
9251
|
if (typeof raw === "string" && validIso(raw)) lastFiredAt = raw;
|
|
9252
9252
|
}
|
|
9253
9253
|
} catch {
|
|
9254
9254
|
return {
|
|
9255
|
-
slug
|
|
9255
|
+
slug,
|
|
9256
9256
|
title: capability.title,
|
|
9257
9257
|
state: "due",
|
|
9258
9258
|
reason: "state unreadable; ready for loop tick"
|
|
9259
9259
|
};
|
|
9260
9260
|
}
|
|
9261
9261
|
return {
|
|
9262
|
-
slug
|
|
9262
|
+
slug,
|
|
9263
9263
|
title: capability.title,
|
|
9264
9264
|
state: "due",
|
|
9265
9265
|
reason: "ready for loop tick",
|
|
@@ -9396,11 +9396,11 @@ function scheduleWaitDecision(previousScheduleState, plannedDecision, reason) {
|
|
|
9396
9396
|
}
|
|
9397
9397
|
function unmarkPlannedCapabilityDispatch(scheduleState, at) {
|
|
9398
9398
|
return Object.fromEntries(
|
|
9399
|
-
Object.entries(scheduleState.capabilities).map(([
|
|
9400
|
-
if (status.lastFiredAt !== at) return [
|
|
9399
|
+
Object.entries(scheduleState.capabilities).map(([slug, status]) => {
|
|
9400
|
+
if (status.lastFiredAt !== at) return [slug, status];
|
|
9401
9401
|
const rest = { ...status };
|
|
9402
9402
|
delete rest.lastFiredAt;
|
|
9403
|
-
return [
|
|
9403
|
+
return [slug, rest];
|
|
9404
9404
|
})
|
|
9405
9405
|
);
|
|
9406
9406
|
}
|
|
@@ -9575,8 +9575,8 @@ function routeNeedsIssueFact(goal) {
|
|
|
9575
9575
|
return goal.route.some(
|
|
9576
9576
|
(step) => Object.values(step.args ?? {}).some((value) => {
|
|
9577
9577
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9578
|
-
const
|
|
9579
|
-
return Object.keys(
|
|
9578
|
+
const record = value;
|
|
9579
|
+
return Object.keys(record).length === 1 && record.fact === "issue";
|
|
9580
9580
|
})
|
|
9581
9581
|
);
|
|
9582
9582
|
}
|
|
@@ -9585,8 +9585,8 @@ function workflowNeedsIssueFact(goal) {
|
|
|
9585
9585
|
}
|
|
9586
9586
|
function isIssueFactReference(value) {
|
|
9587
9587
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9588
|
-
const
|
|
9589
|
-
return Object.keys(
|
|
9588
|
+
const record = value;
|
|
9589
|
+
return Object.keys(record).length === 1 && record.fact === "issue";
|
|
9590
9590
|
}
|
|
9591
9591
|
function normalizeIssueNumber(value) {
|
|
9592
9592
|
if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
|
|
@@ -9927,9 +9927,9 @@ function resolveTrigger(force) {
|
|
|
9927
9927
|
if (force || event === "issue_comment" || event === "workflow_dispatch") return "manual";
|
|
9928
9928
|
return "event";
|
|
9929
9929
|
}
|
|
9930
|
-
function appendLine(ctx,
|
|
9931
|
-
const filePath = `activity/${
|
|
9932
|
-
appendStateLine(ctx.config, ctx.cwd, filePath, JSON.stringify(
|
|
9930
|
+
function appendLine(ctx, record) {
|
|
9931
|
+
const filePath = `activity/${record.ts.slice(0, 10)}.jsonl`;
|
|
9932
|
+
appendStateLine(ctx.config, ctx.cwd, filePath, JSON.stringify(record), `chore(activity): ${record.action}`);
|
|
9933
9933
|
}
|
|
9934
9934
|
var appendCompanyActivity;
|
|
9935
9935
|
var init_appendCompanyActivity = __esm({
|
|
@@ -9945,7 +9945,7 @@ var init_appendCompanyActivity = __esm({
|
|
|
9945
9945
|
const agent = ctx.data.agentSlug || null;
|
|
9946
9946
|
const agentTitle = ctx.data.agentTitle || null;
|
|
9947
9947
|
const force = ctx.args?.force === true;
|
|
9948
|
-
const
|
|
9948
|
+
const record = {
|
|
9949
9949
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9950
9950
|
action: `Ran capability: ${capabilityTitle ?? capability}`,
|
|
9951
9951
|
capability,
|
|
@@ -9959,7 +9959,7 @@ var init_appendCompanyActivity = __esm({
|
|
|
9959
9959
|
durationMs: agentResult?.durationMs ?? null,
|
|
9960
9960
|
runUrl: getRunUrl() || null
|
|
9961
9961
|
};
|
|
9962
|
-
appendLine(ctx,
|
|
9962
|
+
appendLine(ctx, record);
|
|
9963
9963
|
} catch (err) {
|
|
9964
9964
|
process.stderr.write(
|
|
9965
9965
|
`[activity] company-activity append failed: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -9970,494 +9970,6 @@ var init_appendCompanyActivity = __esm({
|
|
|
9970
9970
|
}
|
|
9971
9971
|
});
|
|
9972
9972
|
|
|
9973
|
-
// src/agencyArchitectDecision.ts
|
|
9974
|
-
function parseAgencyArchitectDecisionText(finalText) {
|
|
9975
|
-
const raw = extractDecisionJson(finalText);
|
|
9976
|
-
const parsed = JSON.parse(raw);
|
|
9977
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9978
|
-
throw new Error("agency-architect decision must be JSON object");
|
|
9979
|
-
}
|
|
9980
|
-
const input = parsed;
|
|
9981
|
-
const actions = Array.isArray(input.actions) ? input.actions.map(parseAction) : [];
|
|
9982
|
-
return {
|
|
9983
|
-
summary: typeof input.summary === "string" ? input.summary.trim() : "",
|
|
9984
|
-
actions
|
|
9985
|
-
};
|
|
9986
|
-
}
|
|
9987
|
-
function buildManagedGoalState(action) {
|
|
9988
|
-
const at = nowIso();
|
|
9989
|
-
return {
|
|
9990
|
-
state: "active",
|
|
9991
|
-
createdAt: at,
|
|
9992
|
-
updatedAt: at,
|
|
9993
|
-
extra: {
|
|
9994
|
-
type: action.goalType ?? "release",
|
|
9995
|
-
destination: { outcome: action.outcome, evidence: action.evidence },
|
|
9996
|
-
capabilities: action.capabilities,
|
|
9997
|
-
route: action.route,
|
|
9998
|
-
facts: action.facts ?? {},
|
|
9999
|
-
blockers: [],
|
|
10000
|
-
createdByIntent: action.intentId,
|
|
10001
|
-
manager: "cto"
|
|
10002
|
-
}
|
|
10003
|
-
};
|
|
10004
|
-
}
|
|
10005
|
-
function buildAgentLoopState(action) {
|
|
10006
|
-
const at = nowIso();
|
|
10007
|
-
return {
|
|
10008
|
-
state: "active",
|
|
10009
|
-
createdAt: at,
|
|
10010
|
-
updatedAt: at,
|
|
10011
|
-
extra: {
|
|
10012
|
-
type: "agentLoop",
|
|
10013
|
-
scheduleMode: "agentLoop",
|
|
10014
|
-
schedule: action.every,
|
|
10015
|
-
destination: { outcome: action.outcome, evidence: [] },
|
|
10016
|
-
capabilities: action.capabilities,
|
|
10017
|
-
route: [],
|
|
10018
|
-
facts: {},
|
|
10019
|
-
blockers: [],
|
|
10020
|
-
createdByIntent: action.intentId,
|
|
10021
|
-
manager: "cto"
|
|
10022
|
-
}
|
|
10023
|
-
};
|
|
10024
|
-
}
|
|
10025
|
-
function extractDecisionJson(finalText) {
|
|
10026
|
-
const fence = finalText.match(/```(?:kody-agency-architect-decision|json)\s*([\s\S]*?)```/i);
|
|
10027
|
-
if (fence?.[1]) return fence[1].trim();
|
|
10028
|
-
const line = finalText.match(/KODY_AGENCY_ARCHITECT_DECISION=(\{[\s\S]*\})/);
|
|
10029
|
-
if (line?.[1]) return line[1].trim();
|
|
10030
|
-
throw new Error("missing kody-agency-architect-decision JSON");
|
|
10031
|
-
}
|
|
10032
|
-
function parseAction(value) {
|
|
10033
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10034
|
-
throw new Error("agency-architect action must be object");
|
|
10035
|
-
}
|
|
10036
|
-
const input = value;
|
|
10037
|
-
const kind = input.kind;
|
|
10038
|
-
if (kind === "createManagedGoal") return parseCreateManagedGoal(input);
|
|
10039
|
-
if (kind === "createAgentLoop") return parseCreateAgentLoop(input);
|
|
10040
|
-
if (kind === "setGoalLifecycle") return parseSetGoalLifecycle(input);
|
|
10041
|
-
if (kind === "updateIntentPortfolio") return parseUpdateIntentPortfolio(input);
|
|
10042
|
-
if (kind === "note") return parseNote(input);
|
|
10043
|
-
throw new Error(`unsupported agency-architect action kind: ${String(kind)}`);
|
|
10044
|
-
}
|
|
10045
|
-
function parseCreateManagedGoal(input) {
|
|
10046
|
-
const route = Array.isArray(input.route) ? input.route.map(parseRouteStep) : [];
|
|
10047
|
-
if (route.length === 0) throw new Error("createManagedGoal requires route");
|
|
10048
|
-
const evidence = stringArray3(input.evidence);
|
|
10049
|
-
if (evidence.length === 0) throw new Error("createManagedGoal requires evidence");
|
|
10050
|
-
return {
|
|
10051
|
-
kind: "createManagedGoal",
|
|
10052
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10053
|
-
id: slug(input.id, "id"),
|
|
10054
|
-
outcome: requiredString(input.outcome, "outcome"),
|
|
10055
|
-
goalType: typeof input.goalType === "string" && input.goalType.trim() ? input.goalType.trim() : void 0,
|
|
10056
|
-
evidence,
|
|
10057
|
-
capabilities: nonEmptyStringArray(input.capabilities, "capabilities"),
|
|
10058
|
-
route,
|
|
10059
|
-
facts: record(input.facts) ?? {},
|
|
10060
|
-
reason: requiredString(input.reason, "reason")
|
|
10061
|
-
};
|
|
10062
|
-
}
|
|
10063
|
-
function parseCreateAgentLoop(input) {
|
|
10064
|
-
return {
|
|
10065
|
-
kind: "createAgentLoop",
|
|
10066
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10067
|
-
id: slug(input.id, "id"),
|
|
10068
|
-
outcome: requiredString(input.outcome, "outcome"),
|
|
10069
|
-
every: oneOf(input.every, ["manual", "1h", "1d", "7d", "30d"], "1d"),
|
|
10070
|
-
capabilities: nonEmptyStringArray(input.capabilities, "capabilities"),
|
|
10071
|
-
reason: requiredString(input.reason, "reason")
|
|
10072
|
-
};
|
|
10073
|
-
}
|
|
10074
|
-
function parseSetGoalLifecycle(input) {
|
|
10075
|
-
return {
|
|
10076
|
-
kind: "setGoalLifecycle",
|
|
10077
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10078
|
-
id: slug(input.id, "id"),
|
|
10079
|
-
state: oneOf(input.state, ["active", "closed", "abandoned"], "active"),
|
|
10080
|
-
reason: requiredString(input.reason, "reason")
|
|
10081
|
-
};
|
|
10082
|
-
}
|
|
10083
|
-
function parseUpdateIntentPortfolio(input) {
|
|
10084
|
-
return {
|
|
10085
|
-
kind: "updateIntentPortfolio",
|
|
10086
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10087
|
-
goals: stringArray3(input.goals).filter(isSlug),
|
|
10088
|
-
loops: stringArray3(input.loops).filter(isSlug),
|
|
10089
|
-
capabilities: stringArray3(input.capabilities).filter(isSlug),
|
|
10090
|
-
reason: requiredString(input.reason, "reason")
|
|
10091
|
-
};
|
|
10092
|
-
}
|
|
10093
|
-
function parseNote(input) {
|
|
10094
|
-
return {
|
|
10095
|
-
kind: "note",
|
|
10096
|
-
intentId: typeof input.intentId === "string" && isSlug(input.intentId) ? input.intentId : void 0,
|
|
10097
|
-
message: requiredString(input.message ?? input.content, "message")
|
|
10098
|
-
};
|
|
10099
|
-
}
|
|
10100
|
-
function parseRouteStep(value) {
|
|
10101
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("route step must be object");
|
|
10102
|
-
const input = value;
|
|
10103
|
-
return {
|
|
10104
|
-
stage: requiredString(input.stage, "route.stage"),
|
|
10105
|
-
evidence: requiredString(input.evidence, "route.evidence"),
|
|
10106
|
-
capability: slug(input.capability, "route.capability"),
|
|
10107
|
-
...typeof input.implementation === "string" && input.implementation.trim() ? { implementation: input.implementation.trim() } : {},
|
|
10108
|
-
...record(input.args) ? { args: record(input.args) } : {}
|
|
10109
|
-
};
|
|
10110
|
-
}
|
|
10111
|
-
function slug(value, field) {
|
|
10112
|
-
const text = requiredString(value, field);
|
|
10113
|
-
if (!isSlug(text)) throw new Error(`${field} must be lowercase slug`);
|
|
10114
|
-
return text;
|
|
10115
|
-
}
|
|
10116
|
-
function isSlug(value) {
|
|
10117
|
-
return SLUG_RE.test(value);
|
|
10118
|
-
}
|
|
10119
|
-
function requiredString(value, field) {
|
|
10120
|
-
if (typeof value !== "string" || !value.trim()) throw new Error(`${field} is required`);
|
|
10121
|
-
return value.trim();
|
|
10122
|
-
}
|
|
10123
|
-
function stringArray3(value) {
|
|
10124
|
-
if (!Array.isArray(value)) return [];
|
|
10125
|
-
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
10126
|
-
}
|
|
10127
|
-
function nonEmptyStringArray(value, field) {
|
|
10128
|
-
const values = stringArray3(value);
|
|
10129
|
-
if (values.length === 0) throw new Error(`${field} must not be empty`);
|
|
10130
|
-
return values;
|
|
10131
|
-
}
|
|
10132
|
-
function record(value) {
|
|
10133
|
-
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : null;
|
|
10134
|
-
}
|
|
10135
|
-
function oneOf(value, allowed, fallback) {
|
|
10136
|
-
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
10137
|
-
}
|
|
10138
|
-
var SLUG_RE;
|
|
10139
|
-
var init_agencyArchitectDecision = __esm({
|
|
10140
|
-
"src/agencyArchitectDecision.ts"() {
|
|
10141
|
-
"use strict";
|
|
10142
|
-
init_state2();
|
|
10143
|
-
SLUG_RE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
10144
|
-
}
|
|
10145
|
-
});
|
|
10146
|
-
|
|
10147
|
-
// src/companyIntent.ts
|
|
10148
|
-
function isCompanyIntentId(value) {
|
|
10149
|
-
return SLUG_RE2.test(value);
|
|
10150
|
-
}
|
|
10151
|
-
function companyIntentPath(id) {
|
|
10152
|
-
assertIntentId(id);
|
|
10153
|
-
return `intents/${id}/intent.json`;
|
|
10154
|
-
}
|
|
10155
|
-
function normalizeCompanyIntent(path51, raw) {
|
|
10156
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
10157
|
-
throw new Error(`${path51}: intent must be JSON object`);
|
|
10158
|
-
}
|
|
10159
|
-
const input = raw;
|
|
10160
|
-
const id = stringField4(input.id);
|
|
10161
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${path51}: invalid intent id`);
|
|
10162
|
-
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
10163
|
-
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
10164
|
-
const description = stringField4(input.description);
|
|
10165
|
-
return {
|
|
10166
|
-
version: 1,
|
|
10167
|
-
id,
|
|
10168
|
-
status: oneOf2(input.status, ["active", "paused", "archived"], "active"),
|
|
10169
|
-
for: stringField4(input.for),
|
|
10170
|
-
...description ? { description } : {},
|
|
10171
|
-
priority: numberField(input.priority, 100),
|
|
10172
|
-
posture: oneOf2(
|
|
10173
|
-
input.posture,
|
|
10174
|
-
["confidence", "speed", "stability-recovery", "maintenance", "balanced"],
|
|
10175
|
-
"balanced"
|
|
10176
|
-
),
|
|
10177
|
-
scope: {
|
|
10178
|
-
repos: stringArray4(recordField3(input.scope)?.repos),
|
|
10179
|
-
areas: stringArray4(recordField3(input.scope)?.areas)
|
|
10180
|
-
},
|
|
10181
|
-
principles: stringArray4(input.principles),
|
|
10182
|
-
metrics: stringArray4(input.metrics),
|
|
10183
|
-
policy: {
|
|
10184
|
-
release: normalizeReleasePolicy(recordField3(recordField3(input.policy)?.release)),
|
|
10185
|
-
automation: normalizeAutomationPolicy(recordField3(recordField3(input.policy)?.automation))
|
|
10186
|
-
},
|
|
10187
|
-
portfolio: {
|
|
10188
|
-
goals: stringArray4(recordField3(input.portfolio)?.goals).filter(isCompanyIntentId),
|
|
10189
|
-
loops: stringArray4(recordField3(input.portfolio)?.loops).filter(isCompanyIntentId),
|
|
10190
|
-
capabilities: stringArray4(recordField3(input.portfolio)?.capabilities).filter(isCompanyIntentId)
|
|
10191
|
-
},
|
|
10192
|
-
manager: normalizeManager(recordField3(input.manager)),
|
|
10193
|
-
createdAt,
|
|
10194
|
-
updatedAt
|
|
10195
|
-
};
|
|
10196
|
-
}
|
|
10197
|
-
function listCompanyIntents(config, cwd) {
|
|
10198
|
-
const entries = listStateDirectory(config, cwd, "intents");
|
|
10199
|
-
const records = [];
|
|
10200
|
-
for (const entry of entries) {
|
|
10201
|
-
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
10202
|
-
const path51 = companyIntentPath(entry.name);
|
|
10203
|
-
const file = readStateText(config, cwd, path51);
|
|
10204
|
-
if (!file) continue;
|
|
10205
|
-
records.push({
|
|
10206
|
-
id: entry.name,
|
|
10207
|
-
path: file.path,
|
|
10208
|
-
intent: normalizeCompanyIntent(file.path, JSON.parse(file.content))
|
|
10209
|
-
});
|
|
10210
|
-
}
|
|
10211
|
-
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
10212
|
-
}
|
|
10213
|
-
function readCompanyIntent(config, cwd, id) {
|
|
10214
|
-
const path51 = companyIntentPath(id);
|
|
10215
|
-
const file = readStateText(config, cwd, path51);
|
|
10216
|
-
if (!file) return null;
|
|
10217
|
-
return { id, path: file.path, intent: normalizeCompanyIntent(file.path, JSON.parse(file.content)) };
|
|
10218
|
-
}
|
|
10219
|
-
function writeCompanyIntent(config, cwd, intent, message = `chore(intents): update ${intent.id}`) {
|
|
10220
|
-
upsertStateText(config, cwd, companyIntentPath(intent.id), `${JSON.stringify(intent, null, 2)}
|
|
10221
|
-
`, message);
|
|
10222
|
-
}
|
|
10223
|
-
function appendCompanyIntentDecision(config, cwd, intentId, entry) {
|
|
10224
|
-
assertIntentId(intentId);
|
|
10225
|
-
appendStateLine(
|
|
10226
|
-
config,
|
|
10227
|
-
cwd,
|
|
10228
|
-
`intents/${intentId}/decisions.jsonl`,
|
|
10229
|
-
JSON.stringify(entry),
|
|
10230
|
-
`chore(intents): log ${intentId} decision`
|
|
10231
|
-
);
|
|
10232
|
-
}
|
|
10233
|
-
function listCompanyPortfolio(config, cwd) {
|
|
10234
|
-
const goals = [];
|
|
10235
|
-
for (const id of listGoalStateIds(config, cwd)) {
|
|
10236
|
-
if (!isCompanyIntentId(id)) continue;
|
|
10237
|
-
const state = fetchGoalState(config, id, cwd);
|
|
10238
|
-
if (!state) continue;
|
|
10239
|
-
const destination = recordField3(state.extra.destination);
|
|
10240
|
-
goals.push({
|
|
10241
|
-
id,
|
|
10242
|
-
state: state.state,
|
|
10243
|
-
type: stringField4(state.extra.type) || void 0,
|
|
10244
|
-
outcome: stringField4(destination?.outcome) || void 0,
|
|
10245
|
-
capabilities: stringArray4(state.extra.capabilities),
|
|
10246
|
-
isLoop: state.extra.scheduleMode === "agentLoop" || state.extra.type === "agentLoop",
|
|
10247
|
-
updatedAt: state.updatedAt
|
|
10248
|
-
});
|
|
10249
|
-
}
|
|
10250
|
-
return { goals: goals.sort((a, b) => a.id.localeCompare(b.id)) };
|
|
10251
|
-
}
|
|
10252
|
-
function writeCompanyGoalState(config, cwd, id, state, message) {
|
|
10253
|
-
assertIntentId(id);
|
|
10254
|
-
putGoalState(config, id, state, message, cwd);
|
|
10255
|
-
}
|
|
10256
|
-
function assertIntentId(id) {
|
|
10257
|
-
if (!isCompanyIntentId(id)) throw new Error(`invalid intent/portfolio id: ${id}`);
|
|
10258
|
-
}
|
|
10259
|
-
function stringField4(value) {
|
|
10260
|
-
return typeof value === "string" ? value.trim() : "";
|
|
10261
|
-
}
|
|
10262
|
-
function numberField(value, fallback) {
|
|
10263
|
-
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
10264
|
-
}
|
|
10265
|
-
function recordField3(value) {
|
|
10266
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
10267
|
-
}
|
|
10268
|
-
function stringArray4(value) {
|
|
10269
|
-
if (!Array.isArray(value)) return [];
|
|
10270
|
-
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
10271
|
-
}
|
|
10272
|
-
function oneOf2(value, allowed, fallback) {
|
|
10273
|
-
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
10274
|
-
}
|
|
10275
|
-
function normalizeReleasePolicy(raw) {
|
|
10276
|
-
if (!raw) return void 0;
|
|
10277
|
-
return {
|
|
10278
|
-
cadence: oneOf2(raw.cadence, ["manual", "1d", "1w"], "manual"),
|
|
10279
|
-
qaDepth: oneOf2(raw.qaDepth, ["light", "standard", "strict"], "standard"),
|
|
10280
|
-
blockerLevel: oneOf2(raw.blockerLevel, ["low", "standard", "strict"], "standard"),
|
|
10281
|
-
approval: oneOf2(
|
|
10282
|
-
raw.approval,
|
|
10283
|
-
["none", "before-production", "before-risky-actions"],
|
|
10284
|
-
"before-risky-actions"
|
|
10285
|
-
)
|
|
10286
|
-
};
|
|
10287
|
-
}
|
|
10288
|
-
function normalizeAutomationPolicy(raw) {
|
|
10289
|
-
return {
|
|
10290
|
-
authority: "full-auto",
|
|
10291
|
-
maxConcurrentGoals: Math.max(1, Math.floor(numberField(raw?.maxConcurrentGoals, 1))),
|
|
10292
|
-
maxDailyActions: Math.max(1, Math.floor(numberField(raw?.maxDailyActions, 6))),
|
|
10293
|
-
requiresHumanFor: stringArray4(raw?.requiresHumanFor)
|
|
10294
|
-
};
|
|
10295
|
-
}
|
|
10296
|
-
function normalizeManager(raw) {
|
|
10297
|
-
return {
|
|
10298
|
-
agent: "cto",
|
|
10299
|
-
loop: "agency-architect-loop",
|
|
10300
|
-
capability: "agency-architect",
|
|
10301
|
-
reviewEvery: oneOf2(raw?.reviewEvery, ["1d", "1w"], "1d"),
|
|
10302
|
-
...typeof raw?.lastReviewedAt === "string" ? { lastReviewedAt: raw.lastReviewedAt } : {}
|
|
10303
|
-
};
|
|
10304
|
-
}
|
|
10305
|
-
var SLUG_RE2;
|
|
10306
|
-
var init_companyIntent = __esm({
|
|
10307
|
-
"src/companyIntent.ts"() {
|
|
10308
|
-
"use strict";
|
|
10309
|
-
init_state2();
|
|
10310
|
-
init_stateStore();
|
|
10311
|
-
init_stateRepo();
|
|
10312
|
-
SLUG_RE2 = /^[a-z][a-z0-9-]{0,63}$/;
|
|
10313
|
-
}
|
|
10314
|
-
});
|
|
10315
|
-
|
|
10316
|
-
// src/scripts/applyAgencyArchitectDecision.ts
|
|
10317
|
-
function applyAction(config, cwd, action) {
|
|
10318
|
-
if (action.kind === "createManagedGoal") {
|
|
10319
|
-
const existing = fetchGoalState(config, action.id, cwd);
|
|
10320
|
-
if (existing) return applied(action, false, "goal already exists");
|
|
10321
|
-
writeCompanyGoalState(
|
|
10322
|
-
config,
|
|
10323
|
-
cwd,
|
|
10324
|
-
action.id,
|
|
10325
|
-
buildManagedGoalState(action),
|
|
10326
|
-
`chore(goals): create ${action.id} from intent ${action.intentId}`
|
|
10327
|
-
);
|
|
10328
|
-
return applied(action, true, action.reason, action.id);
|
|
10329
|
-
}
|
|
10330
|
-
if (action.kind === "createAgentLoop") {
|
|
10331
|
-
const existing = fetchGoalState(config, action.id, cwd);
|
|
10332
|
-
if (existing) return applied(action, false, "loop already exists");
|
|
10333
|
-
writeCompanyGoalState(
|
|
10334
|
-
config,
|
|
10335
|
-
cwd,
|
|
10336
|
-
action.id,
|
|
10337
|
-
buildAgentLoopState(action),
|
|
10338
|
-
`chore(goals): create loop ${action.id} from intent ${action.intentId}`
|
|
10339
|
-
);
|
|
10340
|
-
return applied(action, true, action.reason, action.id);
|
|
10341
|
-
}
|
|
10342
|
-
if (action.kind === "setGoalLifecycle") {
|
|
10343
|
-
const state = fetchGoalState(config, action.id, cwd);
|
|
10344
|
-
if (!state) return applied(action, false, "goal/loop missing", action.id);
|
|
10345
|
-
const before = state.state;
|
|
10346
|
-
if (before === action.state) return applied(action, false, "state already set", action.id);
|
|
10347
|
-
const next = {
|
|
10348
|
-
...state,
|
|
10349
|
-
state: action.state,
|
|
10350
|
-
updatedAt: nowIso(),
|
|
10351
|
-
extra: {
|
|
10352
|
-
...state.extra,
|
|
10353
|
-
lifecycleChangedByIntent: action.intentId,
|
|
10354
|
-
lifecycleChangeReason: action.reason
|
|
10355
|
-
}
|
|
10356
|
-
};
|
|
10357
|
-
writeCompanyGoalState(
|
|
10358
|
-
config,
|
|
10359
|
-
cwd,
|
|
10360
|
-
action.id,
|
|
10361
|
-
next,
|
|
10362
|
-
`chore(goals): ${action.state} ${action.id} from intent ${action.intentId}`
|
|
10363
|
-
);
|
|
10364
|
-
return applied(action, true, action.reason, action.id);
|
|
10365
|
-
}
|
|
10366
|
-
if (action.kind === "updateIntentPortfolio") {
|
|
10367
|
-
const record2 = readCompanyIntent(config, cwd, action.intentId);
|
|
10368
|
-
if (!record2) return applied(action, false, "intent missing");
|
|
10369
|
-
const intent = {
|
|
10370
|
-
...record2.intent,
|
|
10371
|
-
portfolio: {
|
|
10372
|
-
goals: mergeUnique(record2.intent.portfolio.goals, action.goals ?? []),
|
|
10373
|
-
loops: mergeUnique(record2.intent.portfolio.loops, action.loops ?? []),
|
|
10374
|
-
capabilities: mergeUnique(record2.intent.portfolio.capabilities, action.capabilities ?? [])
|
|
10375
|
-
},
|
|
10376
|
-
updatedAt: nowIso()
|
|
10377
|
-
};
|
|
10378
|
-
writeCompanyIntent(config, cwd, intent, `chore(intents): update ${action.intentId} portfolio`);
|
|
10379
|
-
return applied(action, true, action.reason);
|
|
10380
|
-
}
|
|
10381
|
-
if (action.kind === "note") {
|
|
10382
|
-
return {
|
|
10383
|
-
kind: action.kind,
|
|
10384
|
-
intentId: action.intentId,
|
|
10385
|
-
changed: false,
|
|
10386
|
-
reason: action.message
|
|
10387
|
-
};
|
|
10388
|
-
}
|
|
10389
|
-
return { kind: "unknown", changed: false, reason: "unsupported action" };
|
|
10390
|
-
}
|
|
10391
|
-
function applied(action, changed, reason, resource) {
|
|
10392
|
-
return {
|
|
10393
|
-
kind: action.kind,
|
|
10394
|
-
intentId: "intentId" in action ? action.intentId : void 0,
|
|
10395
|
-
resource,
|
|
10396
|
-
changed,
|
|
10397
|
-
reason
|
|
10398
|
-
};
|
|
10399
|
-
}
|
|
10400
|
-
function mergeUnique(left, right) {
|
|
10401
|
-
return [.../* @__PURE__ */ new Set([...left, ...right])].sort();
|
|
10402
|
-
}
|
|
10403
|
-
function logAppliedAgencyArchitectActions(config, cwd, appliedActions) {
|
|
10404
|
-
const at = nowIso();
|
|
10405
|
-
for (const action of appliedActions) {
|
|
10406
|
-
if (!action.intentId) continue;
|
|
10407
|
-
appendCompanyIntentDecision(config, cwd, action.intentId, {
|
|
10408
|
-
at,
|
|
10409
|
-
agent: "cto",
|
|
10410
|
-
intentId: action.intentId,
|
|
10411
|
-
action: action.kind,
|
|
10412
|
-
reason: action.reason,
|
|
10413
|
-
after: { changed: action.changed },
|
|
10414
|
-
resources: action.resource ? [action.resource] : []
|
|
10415
|
-
});
|
|
10416
|
-
}
|
|
10417
|
-
}
|
|
10418
|
-
var applyAgencyArchitectDecision;
|
|
10419
|
-
var init_applyAgencyArchitectDecision = __esm({
|
|
10420
|
-
"src/scripts/applyAgencyArchitectDecision.ts"() {
|
|
10421
|
-
"use strict";
|
|
10422
|
-
init_agencyArchitectDecision();
|
|
10423
|
-
init_companyIntent();
|
|
10424
|
-
init_state2();
|
|
10425
|
-
init_stateStore();
|
|
10426
|
-
applyAgencyArchitectDecision = async (ctx) => {
|
|
10427
|
-
const decision = ctx.data.agencyArchitectDecision;
|
|
10428
|
-
if (!decision || !Array.isArray(decision.actions)) return;
|
|
10429
|
-
if (ctx.output.exitCode !== 0) return;
|
|
10430
|
-
const applied2 = [];
|
|
10431
|
-
for (const action of decision.actions) {
|
|
10432
|
-
applied2.push(applyAction(ctx.config, ctx.cwd, action));
|
|
10433
|
-
}
|
|
10434
|
-
ctx.data.agencyArchitectApplied = applied2;
|
|
10435
|
-
ctx.data.agencyArchitectApplySummary = `agency-architect applied ${applied2.filter((item) => item.changed).length}/${applied2.length} action(s)`;
|
|
10436
|
-
};
|
|
10437
|
-
}
|
|
10438
|
-
});
|
|
10439
|
-
|
|
10440
|
-
// src/scripts/appendCompanyIntentDecision.ts
|
|
10441
|
-
var appendCompanyIntentDecision2;
|
|
10442
|
-
var init_appendCompanyIntentDecision = __esm({
|
|
10443
|
-
"src/scripts/appendCompanyIntentDecision.ts"() {
|
|
10444
|
-
"use strict";
|
|
10445
|
-
init_applyAgencyArchitectDecision();
|
|
10446
|
-
appendCompanyIntentDecision2 = async (ctx) => {
|
|
10447
|
-
const applied2 = ctx.data.agencyArchitectApplied;
|
|
10448
|
-
if (!applied2 || applied2.length === 0) return;
|
|
10449
|
-
try {
|
|
10450
|
-
logAppliedAgencyArchitectActions(ctx.config, ctx.cwd, applied2);
|
|
10451
|
-
} catch (err) {
|
|
10452
|
-
process.stderr.write(
|
|
10453
|
-
`[agency-architect] failed append intent decision log: ${err instanceof Error ? err.message : String(err)}
|
|
10454
|
-
`
|
|
10455
|
-
);
|
|
10456
|
-
}
|
|
10457
|
-
};
|
|
10458
|
-
}
|
|
10459
|
-
});
|
|
10460
|
-
|
|
10461
9973
|
// src/capabilityEvidence.ts
|
|
10462
9974
|
function capabilityReportToEvidence(report) {
|
|
10463
9975
|
if (report.target.type !== "goal") return null;
|
|
@@ -10628,7 +10140,7 @@ function retryAfterSecondsFor(route, evidence) {
|
|
|
10628
10140
|
const step = route.find(
|
|
10629
10141
|
(item) => !!item && typeof item === "object" && !Array.isArray(item) && item.evidence === evidence
|
|
10630
10142
|
);
|
|
10631
|
-
const policy = step &&
|
|
10143
|
+
const policy = step && recordField3(step.onFailure);
|
|
10632
10144
|
const retryAfter = typeof policy?.retryAfterSeconds === "number" ? policy.retryAfterSeconds : void 0;
|
|
10633
10145
|
return retryAfter !== void 0 && retryAfter >= 0 ? Math.floor(retryAfter) : void 0;
|
|
10634
10146
|
}
|
|
@@ -10677,7 +10189,7 @@ function parseStringArray3(raw) {
|
|
|
10677
10189
|
}
|
|
10678
10190
|
return out;
|
|
10679
10191
|
}
|
|
10680
|
-
function
|
|
10192
|
+
function recordField3(value) {
|
|
10681
10193
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
10682
10194
|
}
|
|
10683
10195
|
var CONTROL_FACT_KEYS3;
|
|
@@ -10734,7 +10246,7 @@ function capabilityEvidenceOutput(evidence) {
|
|
|
10734
10246
|
function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
10735
10247
|
const outputs = evidenceItems.map(capabilityEvidenceOutput);
|
|
10736
10248
|
const latestOutput = outputs.at(-1);
|
|
10737
|
-
const facts =
|
|
10249
|
+
const facts = recordField4(snapshot, "facts") ?? recordField4(state.extra, "facts") ?? {};
|
|
10738
10250
|
const blockers = uniqueStrings2([
|
|
10739
10251
|
...stringArrayField(snapshot, "blockers"),
|
|
10740
10252
|
...stringArrayField(latestEvent, "blockers"),
|
|
@@ -10753,12 +10265,12 @@ function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
|
10753
10265
|
"",
|
|
10754
10266
|
"## Status",
|
|
10755
10267
|
`- State: ${state.state}`,
|
|
10756
|
-
`- Stage: ${
|
|
10268
|
+
`- Stage: ${stringField4(snapshot, "stage") ?? stringField4(state.extra, "stage") ?? "unknown"}`,
|
|
10757
10269
|
`- Next step: ${nextStepFromEvent(state, snapshot, latestOutput, latestEvent)}`,
|
|
10758
10270
|
`- Updated: ${state.updatedAt ?? state.createdAt ?? state.startedAt ?? "unknown"}`,
|
|
10759
10271
|
"",
|
|
10760
10272
|
"## Decision",
|
|
10761
|
-
`- Event: ${
|
|
10273
|
+
`- Event: ${stringField4(latestEvent, "event") ?? "unknown"}`,
|
|
10762
10274
|
`- Reason: ${decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers)}`,
|
|
10763
10275
|
`- Required evidence: ${listOrNone(stringArrayField(snapshot, "requiredEvidence"))}`,
|
|
10764
10276
|
`- Satisfied evidence: ${listOrNone(stringArrayField(snapshot, "satisfiedEvidence"))}`,
|
|
@@ -10786,9 +10298,9 @@ function capabilityEvidenceMarkdown(outputs) {
|
|
|
10786
10298
|
function decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers) {
|
|
10787
10299
|
if (state.state === "done") return "destination evidence satisfied";
|
|
10788
10300
|
if (blockers.length > 0) return blockers[0] ?? "blocked";
|
|
10789
|
-
const eventReason =
|
|
10301
|
+
const eventReason = stringField4(latestEvent, "reason") ?? stringField4(recordField4(latestEvent, "decision"), "reason");
|
|
10790
10302
|
if (eventReason) return eventReason;
|
|
10791
|
-
const summary =
|
|
10303
|
+
const summary = stringField4(latestOutput, "summary");
|
|
10792
10304
|
if (summary) return summary;
|
|
10793
10305
|
if (missingEvidence.length > 0) return `waiting for ${missingEvidence[0]}`;
|
|
10794
10306
|
return "waiting for more evidence";
|
|
@@ -10796,33 +10308,33 @@ function decisionReason(state, latestEvent, latestOutput, missingEvidence, block
|
|
|
10796
10308
|
function evidenceOutputMarkdown(index, output) {
|
|
10797
10309
|
return [
|
|
10798
10310
|
`### Output ${index}`,
|
|
10799
|
-
`- Status: ${
|
|
10800
|
-
`- Summary: ${
|
|
10311
|
+
`- Status: ${stringField4(output, "status") ?? "unknown"}`,
|
|
10312
|
+
`- Summary: ${stringField4(output, "summary") ?? "no summary"}`,
|
|
10801
10313
|
`- Sources: ${listOrNone(stringArrayField(output, "sources"))}`,
|
|
10802
|
-
`- Evidence values: ${inlineJson(
|
|
10314
|
+
`- Evidence values: ${inlineJson(recordField4(output, "evidence") ?? {})}`,
|
|
10803
10315
|
`- Missing evidence: ${listOrNone(stringArrayField(output, "missingEvidence"))}`,
|
|
10804
10316
|
`- Blockers: ${listOrNone(stringArrayField(output, "blockers"))}`,
|
|
10805
10317
|
""
|
|
10806
10318
|
];
|
|
10807
10319
|
}
|
|
10808
10320
|
function dispatchContextMarkdown(latestEvent) {
|
|
10809
|
-
const context =
|
|
10321
|
+
const context = recordField4(latestEvent, "dispatchContext");
|
|
10810
10322
|
if (!context) return ["- none"];
|
|
10811
|
-
const githubActor =
|
|
10812
|
-
const githubActorRole =
|
|
10813
|
-
const target = dispatchTargetLabel(
|
|
10323
|
+
const githubActor = stringField4(context, "githubActor");
|
|
10324
|
+
const githubActorRole = stringField4(context, "githubActorRole");
|
|
10325
|
+
const target = dispatchTargetLabel(recordField4(context, "target"));
|
|
10814
10326
|
return [
|
|
10815
|
-
`- Triggered by: ${
|
|
10816
|
-
`- Mode: ${
|
|
10327
|
+
`- Triggered by: ${stringField4(context, "triggeredBy") ?? "unknown"}`,
|
|
10328
|
+
`- Mode: ${stringField4(context, "dispatchMode") ?? "unknown"}`,
|
|
10817
10329
|
`- GitHub actor: ${githubActor ? `${githubActor}${githubActorRole ? ` (${githubActorRole})` : ""}` : "none"}`,
|
|
10818
|
-
`- Decided by: ${
|
|
10819
|
-
`- Dispatched by: ${
|
|
10330
|
+
`- Decided by: ${stringField4(context, "decidedBy") ?? "unknown"}`,
|
|
10331
|
+
`- Dispatched by: ${stringField4(context, "dispatchedBy") ?? "unknown"}`,
|
|
10820
10332
|
`- Target: ${target ?? "none"}`
|
|
10821
10333
|
];
|
|
10822
10334
|
}
|
|
10823
10335
|
function dispatchTargetLabel(target) {
|
|
10824
|
-
const type =
|
|
10825
|
-
const id =
|
|
10336
|
+
const type = stringField4(target, "type");
|
|
10337
|
+
const id = stringField4(target, "id");
|
|
10826
10338
|
if (type && id) return `${type} ${id}`;
|
|
10827
10339
|
return id ?? type;
|
|
10828
10340
|
}
|
|
@@ -10845,27 +10357,27 @@ function listOrNone(values) {
|
|
|
10845
10357
|
function uniqueStrings2(values) {
|
|
10846
10358
|
return [...new Set(values)].sort();
|
|
10847
10359
|
}
|
|
10848
|
-
function
|
|
10849
|
-
const value =
|
|
10360
|
+
function stringField4(record, key) {
|
|
10361
|
+
const value = record?.[key];
|
|
10850
10362
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
10851
10363
|
}
|
|
10852
|
-
function
|
|
10853
|
-
const value =
|
|
10364
|
+
function recordField4(record, key) {
|
|
10365
|
+
const value = record?.[key];
|
|
10854
10366
|
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : void 0;
|
|
10855
10367
|
}
|
|
10856
|
-
function stringArrayField(
|
|
10857
|
-
const value =
|
|
10368
|
+
function stringArrayField(record, key) {
|
|
10369
|
+
const value = record?.[key];
|
|
10858
10370
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
10859
10371
|
}
|
|
10860
|
-
function artifactArrayField(
|
|
10861
|
-
const value =
|
|
10372
|
+
function artifactArrayField(record, key) {
|
|
10373
|
+
const value = record?.[key];
|
|
10862
10374
|
if (!Array.isArray(value)) return [];
|
|
10863
10375
|
return value.filter(isArtifact);
|
|
10864
10376
|
}
|
|
10865
10377
|
function isArtifact(value) {
|
|
10866
10378
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
10867
|
-
const
|
|
10868
|
-
return typeof
|
|
10379
|
+
const record = value;
|
|
10380
|
+
return typeof record.label === "string" && (record.url === void 0 || typeof record.url === "string") && (record.path === void 0 || typeof record.path === "string");
|
|
10869
10381
|
}
|
|
10870
10382
|
function uniqueArtifacts2(artifacts) {
|
|
10871
10383
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10882,7 +10394,7 @@ ${artifact.path ?? ""}`;
|
|
|
10882
10394
|
}
|
|
10883
10395
|
function nextStepFromEvent(state, goalAfter, capabilityOutput, latestEvent) {
|
|
10884
10396
|
if (state.state === "done") return "done";
|
|
10885
|
-
const decisionKind =
|
|
10397
|
+
const decisionKind = stringField4(recordField4(latestEvent, "decision"), "kind") ?? stringField4(latestEvent, "status");
|
|
10886
10398
|
if (decisionKind === "done") return "done";
|
|
10887
10399
|
if (decisionKind === "dispatch") return "dispatch";
|
|
10888
10400
|
if (decisionKind === "blocked" || decisionKind === "reject-evidence") return "block";
|
|
@@ -11136,8 +10648,8 @@ function nextStepFromEvidence2(goalAfter, capabilityOutput) {
|
|
|
11136
10648
|
if (missingEvidence.length > 0 && status !== "noop") return "dispatch";
|
|
11137
10649
|
return "wait";
|
|
11138
10650
|
}
|
|
11139
|
-
function stringArrayField2(
|
|
11140
|
-
const value =
|
|
10651
|
+
function stringArrayField2(record, key) {
|
|
10652
|
+
const value = record?.[key];
|
|
11141
10653
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
11142
10654
|
}
|
|
11143
10655
|
function describeMessage(goalId, evidenceItems) {
|
|
@@ -12539,7 +12051,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12539
12051
|
const content = fs33.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
12540
12052
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
12541
12053
|
if (!slugMatch) continue;
|
|
12542
|
-
const
|
|
12054
|
+
const slug = slugMatch[1];
|
|
12543
12055
|
const name = file.replace(/\.(ts|tsx)$/, "");
|
|
12544
12056
|
const fields = [];
|
|
12545
12057
|
const fieldMatches = content.matchAll(/name:\s*['"]([a-zA-Z_][a-zA-Z0-9_]*)['"]/g);
|
|
@@ -12549,7 +12061,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12549
12061
|
const hasAdmin = /components:\s*\{/.test(content) || /Field:\s*['"]/.test(content) || /Cell:\s*['"]/.test(content) || /views:\s*\{/.test(content);
|
|
12550
12062
|
out.push({
|
|
12551
12063
|
name,
|
|
12552
|
-
slug
|
|
12064
|
+
slug,
|
|
12553
12065
|
filePath: path32.relative(cwd, filePath),
|
|
12554
12066
|
fields: fields.slice(0, 20),
|
|
12555
12067
|
hasAdmin
|
|
@@ -13658,8 +13170,8 @@ function git3(args, cwd) {
|
|
|
13658
13170
|
}).trim();
|
|
13659
13171
|
}
|
|
13660
13172
|
function deriveBranchName(issueNumber, title) {
|
|
13661
|
-
const
|
|
13662
|
-
return
|
|
13173
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").slice(0, 50).replace(/-$/, "");
|
|
13174
|
+
return slug ? `${issueNumber}-${slug}` : `${issueNumber}-task`;
|
|
13663
13175
|
}
|
|
13664
13176
|
function getCurrentBranch(cwd) {
|
|
13665
13177
|
return git3(["branch", "--show-current"], cwd);
|
|
@@ -14353,7 +13865,7 @@ function stripDirective(body) {
|
|
|
14353
13865
|
}
|
|
14354
13866
|
return lines.slice(start).join("\n").trim();
|
|
14355
13867
|
}
|
|
14356
|
-
function parseAgentFile(raw,
|
|
13868
|
+
function parseAgentFile(raw, slug) {
|
|
14357
13869
|
const stripped = stripLeadingFrontmatter(raw);
|
|
14358
13870
|
const trimmed = stripped.trim();
|
|
14359
13871
|
const firstLine2 = trimmed.split("\n", 1)[0] ?? "";
|
|
@@ -14362,14 +13874,14 @@ function parseAgentFile(raw, slug2) {
|
|
|
14362
13874
|
const rest = trimmed.slice(firstLine2.length).replace(/^\n+/, "");
|
|
14363
13875
|
return { title: h1[1].trim(), body: rest };
|
|
14364
13876
|
}
|
|
14365
|
-
return { title: humanizeSlug2(
|
|
13877
|
+
return { title: humanizeSlug2(slug), body: trimmed };
|
|
14366
13878
|
}
|
|
14367
13879
|
function stripLeadingFrontmatter(raw) {
|
|
14368
13880
|
const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/.exec(raw);
|
|
14369
13881
|
return match ? raw.slice(match[0].length) : raw;
|
|
14370
13882
|
}
|
|
14371
|
-
function humanizeSlug2(
|
|
14372
|
-
return
|
|
13883
|
+
function humanizeSlug2(slug) {
|
|
13884
|
+
return slug.split(/[-_]+/).filter((s) => s.length > 0).map((s) => s[0].toUpperCase() + s.slice(1)).join(" ");
|
|
14373
13885
|
}
|
|
14374
13886
|
var loadAgentAdhoc;
|
|
14375
13887
|
var init_loadAgentAdhoc = __esm({
|
|
@@ -14412,14 +13924,14 @@ var init_loadCapabilityState = __esm({
|
|
|
14412
13924
|
CAPABILITY_TOOL_PALETTE = new Set(CAPABILITY_MCP_TOOL_NAMES);
|
|
14413
13925
|
loadCapabilityState = async (ctx, profile, args) => {
|
|
14414
13926
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
14415
|
-
const
|
|
13927
|
+
const slug = profile.name;
|
|
14416
13928
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
14417
13929
|
if (backend.hydrate) await backend.hydrate();
|
|
14418
|
-
const loaded = await backend.load(
|
|
14419
|
-
ctx.data.jobSlug =
|
|
13930
|
+
const loaded = await backend.load(slug);
|
|
13931
|
+
ctx.data.jobSlug = slug;
|
|
14420
13932
|
ctx.data.jobState = loaded;
|
|
14421
13933
|
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
14422
|
-
ctx.data.capabilitySlug =
|
|
13934
|
+
ctx.data.capabilitySlug = slug;
|
|
14423
13935
|
ctx.data.capabilityTitle = profile.describe;
|
|
14424
13936
|
ctx.data.implementationSlug = profile.implementation ?? profile.name;
|
|
14425
13937
|
ctx.data.agentSlug = profile.agent ?? "";
|
|
@@ -14432,7 +13944,7 @@ var init_loadCapabilityState = __esm({
|
|
|
14432
13944
|
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE.has(name));
|
|
14433
13945
|
if (unknown.length > 0) {
|
|
14434
13946
|
throw new Error(
|
|
14435
|
-
`loadCapabilityState: capability '${
|
|
13947
|
+
`loadCapabilityState: capability '${slug}' declared capabilityTools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
14436
13948
|
);
|
|
14437
13949
|
}
|
|
14438
13950
|
const mode = profile.capabilityToolMode ?? "lock";
|
|
@@ -14452,6 +13964,141 @@ var init_loadCapabilityState = __esm({
|
|
|
14452
13964
|
}
|
|
14453
13965
|
});
|
|
14454
13966
|
|
|
13967
|
+
// src/companyIntent.ts
|
|
13968
|
+
function isCompanyIntentId(value) {
|
|
13969
|
+
return SLUG_RE.test(value);
|
|
13970
|
+
}
|
|
13971
|
+
function companyIntentPath(id) {
|
|
13972
|
+
assertIntentId(id);
|
|
13973
|
+
return `intents/${id}/intent.json`;
|
|
13974
|
+
}
|
|
13975
|
+
function normalizeCompanyIntent(path51, raw) {
|
|
13976
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
13977
|
+
throw new Error(`${path51}: intent must be JSON object`);
|
|
13978
|
+
}
|
|
13979
|
+
const input = raw;
|
|
13980
|
+
const id = stringField5(input.id);
|
|
13981
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path51}: invalid intent id`);
|
|
13982
|
+
const createdAt = stringField5(input.createdAt) || nowIso();
|
|
13983
|
+
const updatedAt = stringField5(input.updatedAt) || createdAt;
|
|
13984
|
+
const description = stringField5(input.description);
|
|
13985
|
+
return {
|
|
13986
|
+
version: 1,
|
|
13987
|
+
id,
|
|
13988
|
+
status: oneOf(input.status, ["active", "paused", "archived"], "active"),
|
|
13989
|
+
for: stringField5(input.for),
|
|
13990
|
+
...description ? { description } : {},
|
|
13991
|
+
priority: numberField(input.priority, 100),
|
|
13992
|
+
posture: oneOf(
|
|
13993
|
+
input.posture,
|
|
13994
|
+
["confidence", "speed", "stability-recovery", "maintenance", "balanced"],
|
|
13995
|
+
"balanced"
|
|
13996
|
+
),
|
|
13997
|
+
scope: {
|
|
13998
|
+
repos: stringArray3(recordField5(input.scope)?.repos),
|
|
13999
|
+
areas: stringArray3(recordField5(input.scope)?.areas)
|
|
14000
|
+
},
|
|
14001
|
+
principles: stringArray3(input.principles),
|
|
14002
|
+
metrics: stringArray3(input.metrics),
|
|
14003
|
+
policy: {
|
|
14004
|
+
release: normalizeReleasePolicy(recordField5(recordField5(input.policy)?.release)),
|
|
14005
|
+
automation: normalizeAutomationPolicy(recordField5(recordField5(input.policy)?.automation))
|
|
14006
|
+
},
|
|
14007
|
+
portfolio: {
|
|
14008
|
+
goals: stringArray3(recordField5(input.portfolio)?.goals).filter(isCompanyIntentId),
|
|
14009
|
+
loops: stringArray3(recordField5(input.portfolio)?.loops).filter(isCompanyIntentId),
|
|
14010
|
+
capabilities: stringArray3(recordField5(input.portfolio)?.capabilities).filter(isCompanyIntentId)
|
|
14011
|
+
},
|
|
14012
|
+
createdAt,
|
|
14013
|
+
updatedAt
|
|
14014
|
+
};
|
|
14015
|
+
}
|
|
14016
|
+
function listCompanyIntents(config, cwd) {
|
|
14017
|
+
const entries = listStateDirectory(config, cwd, "intents");
|
|
14018
|
+
const records = [];
|
|
14019
|
+
for (const entry of entries) {
|
|
14020
|
+
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
14021
|
+
const path51 = companyIntentPath(entry.name);
|
|
14022
|
+
const file = readStateText(config, cwd, path51);
|
|
14023
|
+
if (!file) continue;
|
|
14024
|
+
records.push({
|
|
14025
|
+
id: entry.name,
|
|
14026
|
+
path: file.path,
|
|
14027
|
+
intent: normalizeCompanyIntent(file.path, JSON.parse(file.content))
|
|
14028
|
+
});
|
|
14029
|
+
}
|
|
14030
|
+
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
14031
|
+
}
|
|
14032
|
+
function listCompanyPortfolio(config, cwd) {
|
|
14033
|
+
const goals = [];
|
|
14034
|
+
for (const id of listGoalStateIds(config, cwd)) {
|
|
14035
|
+
if (!isCompanyIntentId(id)) continue;
|
|
14036
|
+
const state = fetchGoalState(config, id, cwd);
|
|
14037
|
+
if (!state) continue;
|
|
14038
|
+
const destination = recordField5(state.extra.destination);
|
|
14039
|
+
goals.push({
|
|
14040
|
+
id,
|
|
14041
|
+
state: state.state,
|
|
14042
|
+
type: stringField5(state.extra.type) || void 0,
|
|
14043
|
+
outcome: stringField5(destination?.outcome) || void 0,
|
|
14044
|
+
capabilities: stringArray3(state.extra.capabilities),
|
|
14045
|
+
isLoop: state.extra.scheduleMode === "agentLoop" || state.extra.type === "agentLoop",
|
|
14046
|
+
updatedAt: state.updatedAt
|
|
14047
|
+
});
|
|
14048
|
+
}
|
|
14049
|
+
return { goals: goals.sort((a, b) => a.id.localeCompare(b.id)) };
|
|
14050
|
+
}
|
|
14051
|
+
function assertIntentId(id) {
|
|
14052
|
+
if (!isCompanyIntentId(id)) throw new Error(`invalid intent/portfolio id: ${id}`);
|
|
14053
|
+
}
|
|
14054
|
+
function stringField5(value) {
|
|
14055
|
+
return typeof value === "string" ? value.trim() : "";
|
|
14056
|
+
}
|
|
14057
|
+
function numberField(value, fallback) {
|
|
14058
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
14059
|
+
}
|
|
14060
|
+
function recordField5(value) {
|
|
14061
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14062
|
+
}
|
|
14063
|
+
function stringArray3(value) {
|
|
14064
|
+
if (!Array.isArray(value)) return [];
|
|
14065
|
+
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
14066
|
+
}
|
|
14067
|
+
function oneOf(value, allowed, fallback) {
|
|
14068
|
+
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
14069
|
+
}
|
|
14070
|
+
function normalizeReleasePolicy(raw) {
|
|
14071
|
+
if (!raw) return void 0;
|
|
14072
|
+
return {
|
|
14073
|
+
cadence: oneOf(raw.cadence, ["manual", "1d", "1w"], "manual"),
|
|
14074
|
+
qaDepth: oneOf(raw.qaDepth, ["light", "standard", "strict"], "standard"),
|
|
14075
|
+
blockerLevel: oneOf(raw.blockerLevel, ["low", "standard", "strict"], "standard"),
|
|
14076
|
+
approval: oneOf(
|
|
14077
|
+
raw.approval,
|
|
14078
|
+
["none", "before-production", "before-risky-actions"],
|
|
14079
|
+
"before-risky-actions"
|
|
14080
|
+
)
|
|
14081
|
+
};
|
|
14082
|
+
}
|
|
14083
|
+
function normalizeAutomationPolicy(raw) {
|
|
14084
|
+
return {
|
|
14085
|
+
authority: "full-auto",
|
|
14086
|
+
maxConcurrentGoals: Math.max(1, Math.floor(numberField(raw?.maxConcurrentGoals, 1))),
|
|
14087
|
+
maxDailyActions: Math.max(1, Math.floor(numberField(raw?.maxDailyActions, 6))),
|
|
14088
|
+
requiresHumanFor: stringArray3(raw?.requiresHumanFor)
|
|
14089
|
+
};
|
|
14090
|
+
}
|
|
14091
|
+
var SLUG_RE;
|
|
14092
|
+
var init_companyIntent = __esm({
|
|
14093
|
+
"src/companyIntent.ts"() {
|
|
14094
|
+
"use strict";
|
|
14095
|
+
init_state2();
|
|
14096
|
+
init_stateStore();
|
|
14097
|
+
init_stateRepo();
|
|
14098
|
+
SLUG_RE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
14099
|
+
}
|
|
14100
|
+
});
|
|
14101
|
+
|
|
14455
14102
|
// src/scripts/loadCompanyIntents.ts
|
|
14456
14103
|
var loadCompanyIntents;
|
|
14457
14104
|
var init_loadCompanyIntents = __esm({
|
|
@@ -14460,11 +14107,11 @@ var init_loadCompanyIntents = __esm({
|
|
|
14460
14107
|
init_companyIntent();
|
|
14461
14108
|
loadCompanyIntents = async (ctx) => {
|
|
14462
14109
|
const intents = listCompanyIntents(ctx.config, ctx.cwd);
|
|
14463
|
-
const active = intents.filter((
|
|
14110
|
+
const active = intents.filter((record) => record.intent.status === "active");
|
|
14464
14111
|
ctx.data.companyIntents = intents;
|
|
14465
14112
|
ctx.data.companyActiveIntents = active;
|
|
14466
14113
|
ctx.data.companyIntentsJson = JSON.stringify(
|
|
14467
|
-
active.map((
|
|
14114
|
+
active.map((record) => record.intent),
|
|
14468
14115
|
null,
|
|
14469
14116
|
2
|
|
14470
14117
|
);
|
|
@@ -14632,7 +14279,7 @@ var init_loadIssueStateComment = __esm({
|
|
|
14632
14279
|
// src/scripts/loadJobFromFile.ts
|
|
14633
14280
|
import * as fs37 from "fs";
|
|
14634
14281
|
import * as path35 from "path";
|
|
14635
|
-
function parseJobFile(raw,
|
|
14282
|
+
function parseJobFile(raw, slug) {
|
|
14636
14283
|
let stripped = raw;
|
|
14637
14284
|
if (stripped.startsWith("---\n")) {
|
|
14638
14285
|
const end = stripped.indexOf("\n---\n", 4);
|
|
@@ -14647,10 +14294,10 @@ function parseJobFile(raw, slug2) {
|
|
|
14647
14294
|
const rest = trimmed.slice(firstLine2.length).replace(/^\n+/, "");
|
|
14648
14295
|
return { title: h1[1].trim(), body: rest };
|
|
14649
14296
|
}
|
|
14650
|
-
return { title: humanizeSlug3(
|
|
14297
|
+
return { title: humanizeSlug3(slug), body: trimmed };
|
|
14651
14298
|
}
|
|
14652
|
-
function humanizeSlug3(
|
|
14653
|
-
return
|
|
14299
|
+
function humanizeSlug3(slug) {
|
|
14300
|
+
return slug.split(/[-_]+/).filter((s) => s.length > 0).map((s) => s[0].toUpperCase() + s.slice(1)).join(" ");
|
|
14654
14301
|
}
|
|
14655
14302
|
var CAPABILITY_TOOL_PALETTE2, loadJobFromFile;
|
|
14656
14303
|
var init_loadJobFromFile = __esm({
|
|
@@ -14665,13 +14312,13 @@ var init_loadJobFromFile = __esm({
|
|
|
14665
14312
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
14666
14313
|
const agentsDir = String(args?.agentsDir ?? ".kody/agents");
|
|
14667
14314
|
const slugArg = String(args?.slugArg ?? "job");
|
|
14668
|
-
const
|
|
14669
|
-
if (!
|
|
14315
|
+
const slug = String(ctx.args[slugArg] ?? "").trim();
|
|
14316
|
+
if (!slug) {
|
|
14670
14317
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
14671
14318
|
}
|
|
14672
|
-
const capability = resolveCapabilityFolder(
|
|
14319
|
+
const capability = resolveCapabilityFolder(slug, path35.join(ctx.cwd, jobsDir));
|
|
14673
14320
|
if (!capability) {
|
|
14674
|
-
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${path35.join(ctx.cwd, jobsDir,
|
|
14321
|
+
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${path35.join(ctx.cwd, jobsDir, slug)}`);
|
|
14675
14322
|
}
|
|
14676
14323
|
const { title, body, config } = capability;
|
|
14677
14324
|
const mentions = (config.mentions ?? []).map((login) => `@${login}`).join(" ");
|
|
@@ -14682,7 +14329,7 @@ var init_loadJobFromFile = __esm({
|
|
|
14682
14329
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14683
14330
|
if (!fs37.existsSync(agentPath)) {
|
|
14684
14331
|
throw new Error(
|
|
14685
|
-
`loadJobFromFile: capability '${
|
|
14332
|
+
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
14686
14333
|
);
|
|
14687
14334
|
}
|
|
14688
14335
|
const agentRaw = fs37.readFileSync(agentPath, "utf-8");
|
|
@@ -14691,17 +14338,17 @@ var init_loadJobFromFile = __esm({
|
|
|
14691
14338
|
agentIdentity = parsed.body;
|
|
14692
14339
|
}
|
|
14693
14340
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
14694
|
-
const loaded = await backend.load(
|
|
14695
|
-
ctx.data.jobSlug =
|
|
14341
|
+
const loaded = await backend.load(slug);
|
|
14342
|
+
ctx.data.jobSlug = slug;
|
|
14696
14343
|
ctx.data.jobTitle = title;
|
|
14697
|
-
ctx.data.jobIntent = body.replace(/\{\{\s*mentions\s*\}\}/g, mentions).replace(/\{\{\s*capability\s*\}\}/g,
|
|
14344
|
+
ctx.data.jobIntent = body.replace(/\{\{\s*mentions\s*\}\}/g, mentions).replace(/\{\{\s*capability\s*\}\}/g, slug);
|
|
14698
14345
|
ctx.data.jobState = loaded;
|
|
14699
14346
|
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
14700
14347
|
ctx.data.agentSlug = agentSlug;
|
|
14701
14348
|
ctx.data.agentTitle = agentTitle;
|
|
14702
14349
|
ctx.data.agentIdentity = agentIdentity;
|
|
14703
14350
|
ctx.data.mentions = mentions;
|
|
14704
|
-
ctx.data.capabilitySlug =
|
|
14351
|
+
ctx.data.capabilitySlug = slug;
|
|
14705
14352
|
ctx.data.capabilityTitle = title;
|
|
14706
14353
|
ctx.data.agentSlug = agentSlug;
|
|
14707
14354
|
ctx.data.agentTitle = agentTitle;
|
|
@@ -14712,7 +14359,7 @@ var init_loadJobFromFile = __esm({
|
|
|
14712
14359
|
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE2.has(name));
|
|
14713
14360
|
if (unknown.length > 0) {
|
|
14714
14361
|
throw new Error(
|
|
14715
|
-
`loadJobFromFile: capability '${
|
|
14362
|
+
`loadJobFromFile: capability '${slug}' declared tools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
14716
14363
|
);
|
|
14717
14364
|
}
|
|
14718
14365
|
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
@@ -15666,8 +15313,8 @@ function parseAgentFactoryBundle(raw) {
|
|
|
15666
15313
|
};
|
|
15667
15314
|
}
|
|
15668
15315
|
function buildStatePrBranchName(sourceLabel, issueNumber, title, now = Date.now()) {
|
|
15669
|
-
const
|
|
15670
|
-
const suffix =
|
|
15316
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48).replace(/-+$/g, "");
|
|
15317
|
+
const suffix = slug ? `-${slug}` : "";
|
|
15671
15318
|
return `${sourceLabel}/issue-${issueNumber}-${now.toString(36)}${suffix}`;
|
|
15672
15319
|
}
|
|
15673
15320
|
function normalizeBundleFiles(ctx, bundle) {
|
|
@@ -15996,41 +15643,8 @@ QA_REPORT_POSTED=${created.url} (verdict: ${verdict})
|
|
|
15996
15643
|
}
|
|
15997
15644
|
});
|
|
15998
15645
|
|
|
15999
|
-
// src/scripts/parseAgencyArchitectDecision.ts
|
|
16000
|
-
function makeAction2(type, payload) {
|
|
16001
|
-
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16002
|
-
}
|
|
16003
|
-
var parseAgencyArchitectDecision;
|
|
16004
|
-
var init_parseAgencyArchitectDecision = __esm({
|
|
16005
|
-
"src/scripts/parseAgencyArchitectDecision.ts"() {
|
|
16006
|
-
"use strict";
|
|
16007
|
-
init_agencyArchitectDecision();
|
|
16008
|
-
parseAgencyArchitectDecision = async (ctx, _profile, agentResult) => {
|
|
16009
|
-
if (!agentResult) {
|
|
16010
|
-
ctx.data.agencyArchitectDecision = { summary: "", actions: [] };
|
|
16011
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_NOT_RUN", { reason: "no agent result" });
|
|
16012
|
-
return;
|
|
16013
|
-
}
|
|
16014
|
-
try {
|
|
16015
|
-
const decision = parseAgencyArchitectDecisionText(agentResult.finalText);
|
|
16016
|
-
ctx.data.agencyArchitectDecision = decision;
|
|
16017
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_DECIDED", {
|
|
16018
|
-
summary: decision.summary,
|
|
16019
|
-
actionCount: decision.actions.length
|
|
16020
|
-
});
|
|
16021
|
-
} catch (err) {
|
|
16022
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
16023
|
-
ctx.data.agencyArchitectDecisionError = reason;
|
|
16024
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_FAILED", { reason });
|
|
16025
|
-
ctx.output.exitCode = 1;
|
|
16026
|
-
ctx.output.reason = reason;
|
|
16027
|
-
}
|
|
16028
|
-
};
|
|
16029
|
-
}
|
|
16030
|
-
});
|
|
16031
|
-
|
|
16032
15646
|
// src/scripts/parseAgentResult.ts
|
|
16033
|
-
function
|
|
15647
|
+
function makeAction2(type, payload) {
|
|
16034
15648
|
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16035
15649
|
}
|
|
16036
15650
|
var parseAgentResult2;
|
|
@@ -16041,7 +15655,7 @@ var init_parseAgentResult = __esm({
|
|
|
16041
15655
|
parseAgentResult2 = async (ctx, profile, agentResult) => {
|
|
16042
15656
|
if (!agentResult) {
|
|
16043
15657
|
ctx.data.agentDone = false;
|
|
16044
|
-
ctx.data.action =
|
|
15658
|
+
ctx.data.action = makeAction2("AGENT_NOT_RUN", { reason: "no agent result" });
|
|
16045
15659
|
return;
|
|
16046
15660
|
}
|
|
16047
15661
|
const parsed = parseAgentResult(agentResult.finalText);
|
|
@@ -16058,13 +15672,13 @@ var init_parseAgentResult = __esm({
|
|
|
16058
15672
|
ctx.data.agentError = agentResult.error;
|
|
16059
15673
|
const modeSeg = (ctx.args.mode ?? profile.name).replace(/-/g, "_").toUpperCase();
|
|
16060
15674
|
if (parsed.done) {
|
|
16061
|
-
ctx.data.action =
|
|
15675
|
+
ctx.data.action = makeAction2(`${modeSeg}_COMPLETED`, {
|
|
16062
15676
|
commitMessage: parsed.commitMessage
|
|
16063
15677
|
});
|
|
16064
15678
|
} else {
|
|
16065
15679
|
const isGenericNoOutput = parsed.failureReason === "agent produced no final message";
|
|
16066
15680
|
const reason = isGenericNoOutput && agentResult.error ? `agent SDK error: ${agentResult.error}` : parsed.failureReason || agentResult.error || "unknown failure";
|
|
16067
|
-
ctx.data.action =
|
|
15681
|
+
ctx.data.action = makeAction2(`${modeSeg}_FAILED`, { reason });
|
|
16068
15682
|
}
|
|
16069
15683
|
};
|
|
16070
15684
|
}
|
|
@@ -16835,7 +16449,7 @@ function tryAuditComment(issueNumber, body, cwd) {
|
|
|
16835
16449
|
} catch {
|
|
16836
16450
|
}
|
|
16837
16451
|
}
|
|
16838
|
-
function
|
|
16452
|
+
function makeAction3(type, payload) {
|
|
16839
16453
|
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16840
16454
|
}
|
|
16841
16455
|
function failedAction4(reason) {
|
|
@@ -16872,7 +16486,7 @@ var init_recordClassification = __esm({
|
|
|
16872
16486
|
ctx.output.reason = "classify: no decision";
|
|
16873
16487
|
return;
|
|
16874
16488
|
}
|
|
16875
|
-
ctx.data.action =
|
|
16489
|
+
ctx.data.action = makeAction3(`CLASSIFIED_AS_${classification.toUpperCase()}`, {
|
|
16876
16490
|
classification,
|
|
16877
16491
|
reason: reason ?? "",
|
|
16878
16492
|
source: ctx.data.classificationSource ?? "agent"
|
|
@@ -18204,16 +17818,16 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18204
17818
|
const slugArg = String(args?.slugArg ?? "capability");
|
|
18205
17819
|
const fenceLabel = String(args?.fenceLabel ?? "kody-job-next-state");
|
|
18206
17820
|
const shell = String(args?.shell ?? "tick.sh");
|
|
18207
|
-
const
|
|
18208
|
-
if (!
|
|
17821
|
+
const slug = String(args?.slug ?? ctx.args[slugArg] ?? ctx.args.capability ?? "").trim();
|
|
17822
|
+
if (!slug) {
|
|
18209
17823
|
ctx.output.exitCode = 99;
|
|
18210
17824
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
18211
17825
|
return;
|
|
18212
17826
|
}
|
|
18213
|
-
const capability = resolveCapabilityFolder(
|
|
17827
|
+
const capability = resolveCapabilityFolder(slug, path41.join(ctx.cwd, jobsDir));
|
|
18214
17828
|
if (!capability) {
|
|
18215
17829
|
ctx.output.exitCode = 99;
|
|
18216
|
-
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${
|
|
17830
|
+
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
18217
17831
|
return;
|
|
18218
17832
|
}
|
|
18219
17833
|
const shellPath = path41.join(profile.dir, shell);
|
|
@@ -18225,14 +17839,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18225
17839
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
18226
17840
|
let loaded;
|
|
18227
17841
|
try {
|
|
18228
|
-
loaded = await backend.load(
|
|
17842
|
+
loaded = await backend.load(slug);
|
|
18229
17843
|
} catch (err) {
|
|
18230
17844
|
ctx.output.exitCode = 99;
|
|
18231
17845
|
ctx.output.reason = `runScheduledImplementationTick: state load failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
18232
17846
|
return;
|
|
18233
17847
|
}
|
|
18234
|
-
ctx.data.jobSlug =
|
|
18235
|
-
ctx.data.capabilitySlug =
|
|
17848
|
+
ctx.data.jobSlug = slug;
|
|
17849
|
+
ctx.data.capabilitySlug = slug;
|
|
18236
17850
|
ctx.data.implementationSlug = profile.name;
|
|
18237
17851
|
ctx.data.jobState = loaded;
|
|
18238
17852
|
runTickShellAndParse({
|
|
@@ -18262,22 +17876,22 @@ var init_runTickScript = __esm({
|
|
|
18262
17876
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
18263
17877
|
const slugArg = String(args?.slugArg ?? "job");
|
|
18264
17878
|
const fenceLabel = String(args?.fenceLabel ?? "kody-job-next-state");
|
|
18265
|
-
const
|
|
18266
|
-
if (!
|
|
17879
|
+
const slug = String(ctx.args[slugArg] ?? "").trim();
|
|
17880
|
+
if (!slug) {
|
|
18267
17881
|
ctx.output.exitCode = 99;
|
|
18268
17882
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
18269
17883
|
return;
|
|
18270
17884
|
}
|
|
18271
|
-
const capability = readCapabilityFolder(path42.join(ctx.cwd, jobsDir),
|
|
17885
|
+
const capability = readCapabilityFolder(path42.join(ctx.cwd, jobsDir), slug);
|
|
18272
17886
|
if (!capability) {
|
|
18273
17887
|
ctx.output.exitCode = 99;
|
|
18274
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path42.join(ctx.cwd, jobsDir,
|
|
17888
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path42.join(ctx.cwd, jobsDir, slug)}`;
|
|
18275
17889
|
return;
|
|
18276
17890
|
}
|
|
18277
17891
|
const tickScript = capability.config.tickScript;
|
|
18278
17892
|
if (!tickScript) {
|
|
18279
17893
|
ctx.output.exitCode = 99;
|
|
18280
|
-
ctx.output.reason = `runTickScript: capability ${
|
|
17894
|
+
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
18281
17895
|
return;
|
|
18282
17896
|
}
|
|
18283
17897
|
const scriptPath = path42.isAbsolute(tickScript) ? tickScript : path42.join(ctx.cwd, tickScript);
|
|
@@ -18289,13 +17903,13 @@ var init_runTickScript = __esm({
|
|
|
18289
17903
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
18290
17904
|
let loaded;
|
|
18291
17905
|
try {
|
|
18292
|
-
loaded = await backend.load(
|
|
17906
|
+
loaded = await backend.load(slug);
|
|
18293
17907
|
} catch (err) {
|
|
18294
17908
|
ctx.output.exitCode = 99;
|
|
18295
17909
|
ctx.output.reason = `runTickScript: state load failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
18296
17910
|
return;
|
|
18297
17911
|
}
|
|
18298
|
-
ctx.data.jobSlug =
|
|
17912
|
+
ctx.data.jobSlug = slug;
|
|
18299
17913
|
ctx.data.jobState = loaded;
|
|
18300
17914
|
runTickShellAndParse({
|
|
18301
17915
|
ctx,
|
|
@@ -18567,7 +18181,7 @@ function validateModelBundle(bundle, producer) {
|
|
|
18567
18181
|
const failures = [];
|
|
18568
18182
|
const expectedKind = CREATOR_KIND[producer];
|
|
18569
18183
|
if (producer === FACTORY_PRODUCER) {
|
|
18570
|
-
const contracts =
|
|
18184
|
+
const contracts = stringArray4(bundle.modelCreatorContractsUsed);
|
|
18571
18185
|
for (const contract of CREATOR_CONTRACTS) {
|
|
18572
18186
|
if (!contracts.includes(contract)) failures.push(`modelCreatorContractsUsed missing ${contract}`);
|
|
18573
18187
|
}
|
|
@@ -18594,36 +18208,36 @@ function validateOneModel(rawModel, files, label, strictSingleModel, failures, e
|
|
|
18594
18208
|
if (!isModelKind(kind)) failures.push(`${label}.kind must be agent, capability, goal, agentLoop, or workflow`);
|
|
18595
18209
|
if (expectedKind && kind !== expectedKind && producer)
|
|
18596
18210
|
failures.push(`${producer} must output model.kind ${expectedKind}`);
|
|
18597
|
-
const
|
|
18598
|
-
if (!
|
|
18211
|
+
const slug = stringField6(model.slug);
|
|
18212
|
+
if (!isSlug(slug)) failures.push(`${label}.slug must be a lowercase slug`);
|
|
18599
18213
|
if (isModelKind(kind)) {
|
|
18600
|
-
const docsUsed =
|
|
18214
|
+
const docsUsed = stringArray4(model.docsUsed);
|
|
18601
18215
|
for (const doc of REQUIRED_DOCS[kind]) {
|
|
18602
18216
|
if (!docsUsed.includes(doc)) failures.push(`${label} docsUsed missing ${doc}`);
|
|
18603
18217
|
}
|
|
18604
|
-
validateFilesForKind(kind,
|
|
18605
|
-
validateModelShape(kind, model, files,
|
|
18218
|
+
validateFilesForKind(kind, slug, files, strictSingleModel, failures);
|
|
18219
|
+
validateModelShape(kind, model, files, slug, failures);
|
|
18606
18220
|
}
|
|
18607
18221
|
}
|
|
18608
|
-
function validateFilesForKind(kind,
|
|
18222
|
+
function validateFilesForKind(kind, slug, files, strictSingleModel, failures) {
|
|
18609
18223
|
const paths = files.map((file) => normalizeBundlePath(file.path));
|
|
18610
18224
|
if (paths.some((filePath) => filePath === "implementations" || filePath.startsWith("implementations/"))) {
|
|
18611
18225
|
failures.push("files must not use obsolete implementation storage");
|
|
18612
18226
|
}
|
|
18613
18227
|
if (kind === "agent") {
|
|
18614
|
-
requirePath(paths, `agents/${
|
|
18228
|
+
requirePath(paths, `agents/${slug}.md`, "agent file", failures);
|
|
18615
18229
|
if (strictSingleModel) rejectOtherRoots(paths, ["agents/"], "agent", failures);
|
|
18616
18230
|
}
|
|
18617
18231
|
if (kind === "capability") {
|
|
18618
|
-
requirePath(paths, `capabilities/${
|
|
18619
|
-
requirePath(paths, `capabilities/${
|
|
18620
|
-
if (strictSingleModel) rejectOtherRoots(paths, [`capabilities/${
|
|
18621
|
-
const profile = parseJsonFile(files, `capabilities/${
|
|
18232
|
+
requirePath(paths, `capabilities/${slug}/profile.json`, "capability profile", failures);
|
|
18233
|
+
requirePath(paths, `capabilities/${slug}/capability.md`, "capability body", failures);
|
|
18234
|
+
if (strictSingleModel) rejectOtherRoots(paths, [`capabilities/${slug}/`], "capability", failures);
|
|
18235
|
+
const profile = parseJsonFile(files, `capabilities/${slug}/profile.json`, failures);
|
|
18622
18236
|
if (profile) {
|
|
18623
18237
|
const profileSlug = stringField6(profile.slug);
|
|
18624
18238
|
const profileName = stringField6(profile.name);
|
|
18625
|
-
if (profileSlug && profileSlug !==
|
|
18626
|
-
if (!profileSlug && profileName && profileName !==
|
|
18239
|
+
if (profileSlug && profileSlug !== slug) failures.push("capability profile slug must match model.slug");
|
|
18240
|
+
if (!profileSlug && profileName && profileName !== slug) {
|
|
18627
18241
|
failures.push("capability profile name must match model.slug when slug is absent");
|
|
18628
18242
|
}
|
|
18629
18243
|
if (profile.agent !== void 0)
|
|
@@ -18634,8 +18248,8 @@ function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
|
|
|
18634
18248
|
}
|
|
18635
18249
|
}
|
|
18636
18250
|
if (kind === "goal") {
|
|
18637
|
-
requirePath(paths, `goals/templates/${
|
|
18638
|
-
if (strictSingleModel) rejectOtherRoots(paths, [`goals/templates/${
|
|
18251
|
+
requirePath(paths, `goals/templates/${slug}/state.json`, "goal template state", failures);
|
|
18252
|
+
if (strictSingleModel) rejectOtherRoots(paths, [`goals/templates/${slug}/`], "goal", failures);
|
|
18639
18253
|
}
|
|
18640
18254
|
if (kind === "agentLoop") {
|
|
18641
18255
|
if (!paths.some((filePath) => filePath.endsWith("/state.json")))
|
|
@@ -18643,8 +18257,8 @@ function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
|
|
|
18643
18257
|
if (strictSingleModel) rejectOtherRoots(paths, ["goals/", "loops/", "capabilities/"], "agentLoop", failures);
|
|
18644
18258
|
}
|
|
18645
18259
|
if (kind === "workflow") {
|
|
18646
|
-
requirePath(paths, `capabilities/${
|
|
18647
|
-
const profile = parseJsonFile(files, `capabilities/${
|
|
18260
|
+
requirePath(paths, `capabilities/${slug}/profile.json`, "workflow capability profile", failures);
|
|
18261
|
+
const profile = parseJsonFile(files, `capabilities/${slug}/profile.json`, failures);
|
|
18648
18262
|
if (profile) {
|
|
18649
18263
|
if (profile.capabilityKind !== void 0) {
|
|
18650
18264
|
failures.push("workflow profile must not declare capabilityKind");
|
|
@@ -18663,8 +18277,8 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18663
18277
|
if (!model || typeof model !== "object" || Array.isArray(model)) continue;
|
|
18664
18278
|
const input = model;
|
|
18665
18279
|
const kind = stringField6(input.kind);
|
|
18666
|
-
const
|
|
18667
|
-
if (isModelKind(kind) &&
|
|
18280
|
+
const slug = stringField6(input.slug);
|
|
18281
|
+
if (isModelKind(kind) && isSlug(slug)) available.set(`${kind}:${slug}`, kind);
|
|
18668
18282
|
}
|
|
18669
18283
|
for (const model of models) {
|
|
18670
18284
|
if (!model || typeof model !== "object" || Array.isArray(model)) continue;
|
|
@@ -18678,7 +18292,7 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18678
18292
|
}
|
|
18679
18293
|
}
|
|
18680
18294
|
if (kind === "workflow") {
|
|
18681
|
-
for (const capability of
|
|
18295
|
+
for (const capability of stringArray4(input.steps)) {
|
|
18682
18296
|
if (!available.has(`capability:${capability}`)) {
|
|
18683
18297
|
failures.push(`workflow ${stringField6(input.slug)} references missing capability ${capability}`);
|
|
18684
18298
|
}
|
|
@@ -18708,10 +18322,10 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18708
18322
|
}
|
|
18709
18323
|
}
|
|
18710
18324
|
}
|
|
18711
|
-
function validateModelShape(kind, model, files,
|
|
18325
|
+
function validateModelShape(kind, model, files, slug, failures) {
|
|
18712
18326
|
if (kind === "agent") {
|
|
18713
|
-
const agentFile = textFile(files, `agents/${
|
|
18714
|
-
if (!
|
|
18327
|
+
const agentFile = textFile(files, `agents/${slug}.md`);
|
|
18328
|
+
if (!stringArray4(model.owns).includes("identity") && !containsWord(agentFile, "identity")) {
|
|
18715
18329
|
failures.push("agent owns must include identity");
|
|
18716
18330
|
}
|
|
18717
18331
|
requireStringArrayIncludes(model.doesNotOwn, "tasks", "agent doesNotOwn", failures);
|
|
@@ -18728,7 +18342,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18728
18342
|
requireStringArrayIncludes(model.doesNotOwn, "goal progress", "capability doesNotOwn", failures);
|
|
18729
18343
|
}
|
|
18730
18344
|
if (kind === "goal") {
|
|
18731
|
-
const goalState = parseJsonContent(textFile(files, `goals/templates/${
|
|
18345
|
+
const goalState = parseJsonContent(textFile(files, `goals/templates/${slug}/state.json`));
|
|
18732
18346
|
if (!stringField6(model.outcome) && !stringField6(goalState?.outcome))
|
|
18733
18347
|
failures.push("goal model must declare outcome");
|
|
18734
18348
|
if (evidenceRefs(model).length === 0 && evidenceRefs(goalState).length === 0) {
|
|
@@ -18740,7 +18354,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18740
18354
|
}
|
|
18741
18355
|
if (kind === "agentLoop") {
|
|
18742
18356
|
if (!stringField6(model.cadence)) failures.push("agentLoop model must declare cadence");
|
|
18743
|
-
const loopState = parseJsonContent(firstStateFile(files,
|
|
18357
|
+
const loopState = parseJsonContent(firstStateFile(files, slug));
|
|
18744
18358
|
const hasTarget = Boolean(wakeTarget(model)) || Boolean(stringField6(model.target)) || Boolean(wakeTarget(loopState)) || Boolean(stringField6(loopState?.target)) || Boolean(loopTargetString(loopState));
|
|
18745
18359
|
if (!hasTarget) {
|
|
18746
18360
|
failures.push("agentLoop model must declare wakeTarget object");
|
|
@@ -18754,7 +18368,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18754
18368
|
}
|
|
18755
18369
|
}
|
|
18756
18370
|
function capabilityRefs(value) {
|
|
18757
|
-
return [...
|
|
18371
|
+
return [...stringArray4(value?.capabilities), ...stringArray4(value?.allowedCapabilities)];
|
|
18758
18372
|
}
|
|
18759
18373
|
function evidenceRefs(value) {
|
|
18760
18374
|
if (!value) return [];
|
|
@@ -18767,8 +18381,8 @@ function wakeTarget(value) {
|
|
|
18767
18381
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
18768
18382
|
const target = raw;
|
|
18769
18383
|
const type = stringField6(target.type);
|
|
18770
|
-
const
|
|
18771
|
-
if ((type === "goal" || type === "workflow" || type === "capability") &&
|
|
18384
|
+
const slug = stringField6(target.slug);
|
|
18385
|
+
if ((type === "goal" || type === "workflow" || type === "capability") && slug) return { kind: type, slug };
|
|
18772
18386
|
return null;
|
|
18773
18387
|
}
|
|
18774
18388
|
function loopTargetString(value) {
|
|
@@ -18779,8 +18393,8 @@ function loopTargetString(value) {
|
|
|
18779
18393
|
function textFile(files, wantedPath) {
|
|
18780
18394
|
return files.find((item) => normalizeBundlePath(item.path) === wantedPath)?.content ?? "";
|
|
18781
18395
|
}
|
|
18782
|
-
function firstStateFile(files,
|
|
18783
|
-
const normalizedSlug = `${
|
|
18396
|
+
function firstStateFile(files, slug) {
|
|
18397
|
+
const normalizedSlug = `${slug}/state.json`;
|
|
18784
18398
|
return files.find((item) => normalizeBundlePath(item.path).endsWith(normalizedSlug))?.content ?? "";
|
|
18785
18399
|
}
|
|
18786
18400
|
function parseJsonContent(content) {
|
|
@@ -18826,7 +18440,7 @@ function normalizeBundlePath(filePath) {
|
|
|
18826
18440
|
function stringField6(value) {
|
|
18827
18441
|
return typeof value === "string" ? value.trim() : "";
|
|
18828
18442
|
}
|
|
18829
|
-
function
|
|
18443
|
+
function stringArray4(value) {
|
|
18830
18444
|
if (!Array.isArray(value)) return [];
|
|
18831
18445
|
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
18832
18446
|
}
|
|
@@ -18837,9 +18451,9 @@ function arrayObjects(value) {
|
|
|
18837
18451
|
);
|
|
18838
18452
|
}
|
|
18839
18453
|
function requireStringArrayIncludes(value, expected, label, failures) {
|
|
18840
|
-
if (!
|
|
18454
|
+
if (!stringArray4(value).includes(expected)) failures.push(`${label} must include ${expected}`);
|
|
18841
18455
|
}
|
|
18842
|
-
function
|
|
18456
|
+
function isSlug(value) {
|
|
18843
18457
|
return /^[a-z][a-z0-9-]{0,63}$/.test(value);
|
|
18844
18458
|
}
|
|
18845
18459
|
function isModelKind(value) {
|
|
@@ -19572,8 +19186,6 @@ var init_scripts = __esm({
|
|
|
19572
19186
|
init_advanceFlow();
|
|
19573
19187
|
init_advanceManagedGoal();
|
|
19574
19188
|
init_appendCompanyActivity();
|
|
19575
|
-
init_appendCompanyIntentDecision();
|
|
19576
|
-
init_applyAgencyArchitectDecision();
|
|
19577
19189
|
init_applyCapabilityReports();
|
|
19578
19190
|
init_buildSyntheticPlugin();
|
|
19579
19191
|
init_checkCoverageWithRetry();
|
|
@@ -19621,7 +19233,6 @@ var init_scripts = __esm({
|
|
|
19621
19233
|
init_notifyTerminal();
|
|
19622
19234
|
init_openAgentFactoryStatePr();
|
|
19623
19235
|
init_openQaIssue();
|
|
19624
|
-
init_parseAgencyArchitectDecision();
|
|
19625
19236
|
init_parseAgentResult();
|
|
19626
19237
|
init_parseIssueStateFromAgentResult();
|
|
19627
19238
|
init_parseJobStateFromAgentResult();
|
|
@@ -19719,7 +19330,6 @@ var init_scripts = __esm({
|
|
|
19719
19330
|
};
|
|
19720
19331
|
postflightScripts = {
|
|
19721
19332
|
parseAgentResult: parseAgentResult2,
|
|
19722
|
-
parseAgencyArchitectDecision,
|
|
19723
19333
|
parseIssueStateFromAgentResult,
|
|
19724
19334
|
parseJobStateFromAgentResult,
|
|
19725
19335
|
parseReproOutput,
|
|
@@ -19727,8 +19337,6 @@ var init_scripts = __esm({
|
|
|
19727
19337
|
writeIssueStateComment,
|
|
19728
19338
|
writeJobStateFile,
|
|
19729
19339
|
appendCompanyActivity,
|
|
19730
|
-
appendCompanyIntentDecision: appendCompanyIntentDecision2,
|
|
19731
|
-
applyAgencyArchitectDecision,
|
|
19732
19340
|
requireFeedbackActions,
|
|
19733
19341
|
requirePlanDeviations,
|
|
19734
19342
|
verify,
|
|
@@ -19890,6 +19498,7 @@ var init_stateWorkspace = __esm({
|
|
|
19890
19498
|
];
|
|
19891
19499
|
FILE_MAPPINGS = [
|
|
19892
19500
|
{ statePath: "instructions.md", localPath: path43.join(".kody", "instructions.md") },
|
|
19501
|
+
{ statePath: "system-prompt.md", localPath: path43.join(".kody", "system-prompt.md") },
|
|
19893
19502
|
{ statePath: "variables.json", localPath: path43.join(".kody", "variables.json") },
|
|
19894
19503
|
{ statePath: "secrets.enc", localPath: path43.join(".kody", "secrets.enc") }
|
|
19895
19504
|
];
|
|
@@ -21263,14 +20872,14 @@ function filterCliArgsForStep(action, raw) {
|
|
|
21263
20872
|
function composeStepWhy(parentWhy, step) {
|
|
21264
20873
|
return [parentWhy?.trim(), step.reason ? `Workflow step: ${step.reason}` : ""].filter((part) => Boolean(part)).join("\n\n");
|
|
21265
20874
|
}
|
|
21266
|
-
function loadCapabilityContext(
|
|
21267
|
-
if (!
|
|
21268
|
-
return resolveCapabilityFolder(
|
|
20875
|
+
function loadCapabilityContext(slug, cwd) {
|
|
20876
|
+
if (!slug) return null;
|
|
20877
|
+
return resolveCapabilityFolder(slug, path45.join(cwd, ".kody", "capabilities"));
|
|
21269
20878
|
}
|
|
21270
|
-
function loadWorkflowContext(
|
|
21271
|
-
if (!
|
|
21272
|
-
const workflow = readWorkflowDefinition(base.config, base.cwd,
|
|
21273
|
-
return workflow ? workflowDefinitionToCapabilityFolder(
|
|
20879
|
+
function loadWorkflowContext(slug, base) {
|
|
20880
|
+
if (!slug || !base.config || !isWorkflowDefinitionId(slug)) return null;
|
|
20881
|
+
const workflow = readWorkflowDefinition(base.config, base.cwd, slug);
|
|
20882
|
+
return workflow ? workflowDefinitionToCapabilityFolder(slug, workflow) : null;
|
|
21274
20883
|
}
|
|
21275
20884
|
function mintInstantJob(dispatch2, opts) {
|
|
21276
20885
|
return {
|
|
@@ -21782,7 +21391,7 @@ async function runChatTurn(opts) {
|
|
|
21782
21391
|
return { exitCode: 64, error };
|
|
21783
21392
|
}
|
|
21784
21393
|
const { turns: promptTurns, imagePaths } = prepareAttachments(turns, opts.cwd, opts.sessionId);
|
|
21785
|
-
const basePrompt = opts.systemPrompt ?? (opts.model.protocol === "openai" ? OPENAI_CHAT_SYSTEM_PROMPT : CHAT_SYSTEM_PROMPT);
|
|
21394
|
+
const basePrompt = opts.systemPrompt ?? readSystemPromptOverride(opts.cwd) ?? (opts.model.protocol === "openai" ? OPENAI_CHAT_SYSTEM_PROMPT : CHAT_SYSTEM_PROMPT);
|
|
21786
21395
|
const agentIdentityBlock = readAgentIdentityBlock(opts.cwd, opts.agentIdentity);
|
|
21787
21396
|
const catalog = buildImplementationCatalog();
|
|
21788
21397
|
const taskArtifactsPaths = prepareTaskArtifactsDir(opts.cwd, opts.sessionId);
|
|
@@ -21930,10 +21539,10 @@ async function runChatTurn(opts) {
|
|
|
21930
21539
|
return { exitCode: 0, reply };
|
|
21931
21540
|
}
|
|
21932
21541
|
function readAgentIdentityBlock(cwd, agentIdentity) {
|
|
21933
|
-
const
|
|
21934
|
-
if (!
|
|
21935
|
-
const body = agentIdentity?.body?.trim() || loadAgentIdentity(cwd,
|
|
21936
|
-
return frameAgentIdentity(
|
|
21542
|
+
const slug = agentIdentity?.slug?.trim();
|
|
21543
|
+
if (!slug) return null;
|
|
21544
|
+
const body = agentIdentity?.body?.trim() || loadAgentIdentity(cwd, slug);
|
|
21545
|
+
return frameAgentIdentity(slug, body);
|
|
21937
21546
|
}
|
|
21938
21547
|
async function runOpenAIChatTurn(args) {
|
|
21939
21548
|
const { opts, turns, systemPrompt, sessionFile } = args;
|
|
@@ -22075,6 +21684,17 @@ _\u2026 (context truncated; use the state repo context files for the full text)_
|
|
|
22075
21684
|
}
|
|
22076
21685
|
var INSTRUCTIONS_REL = ".kody/instructions.md";
|
|
22077
21686
|
var MAX_INSTRUCTIONS_BYTES = 8e3;
|
|
21687
|
+
var SYSTEM_PROMPT_OVERRIDE_REL = ".kody/system-prompt.md";
|
|
21688
|
+
function readSystemPromptOverride(cwd) {
|
|
21689
|
+
let raw;
|
|
21690
|
+
try {
|
|
21691
|
+
raw = fs14.readFileSync(path16.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
|
|
21692
|
+
} catch {
|
|
21693
|
+
return null;
|
|
21694
|
+
}
|
|
21695
|
+
const trimmed = raw.trim();
|
|
21696
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
21697
|
+
}
|
|
22078
21698
|
function readInstructionsBlock(cwd) {
|
|
22079
21699
|
const instructionsPath = path16.join(cwd, INSTRUCTIONS_REL);
|
|
22080
21700
|
let raw;
|
|
@@ -23626,11 +23246,11 @@ function agentIdentityField(body) {
|
|
|
23626
23246
|
if (typeof body !== "object" || body === null || !("agentIdentity" in body)) return void 0;
|
|
23627
23247
|
const value = body.agentIdentity;
|
|
23628
23248
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
23629
|
-
const
|
|
23630
|
-
const
|
|
23631
|
-
const bodyText = typeof
|
|
23632
|
-
if (!
|
|
23633
|
-
return { slug
|
|
23249
|
+
const record = value;
|
|
23250
|
+
const slug = typeof record.slug === "string" ? record.slug.trim() : "";
|
|
23251
|
+
const bodyText = typeof record.body === "string" ? record.body.trim() : "";
|
|
23252
|
+
if (!slug || !bodyText) return void 0;
|
|
23253
|
+
return { slug, body: bodyText };
|
|
23634
23254
|
}
|
|
23635
23255
|
function sendJson(res, status, body) {
|
|
23636
23256
|
res.writeHead(status, { "content-type": "application/json" });
|