@kody-ade/kody-engine 0.4.356 → 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 +403 -796
- 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);
|
|
@@ -2757,17 +2757,12 @@ function readDispatchTargetKind(repoSlug, issueNumber) {
|
|
|
2757
2757
|
}
|
|
2758
2758
|
}
|
|
2759
2759
|
function isDispatchGated(capability, mode) {
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
return
|
|
2763
|
-
}
|
|
2764
|
-
function trustRefusal(capabilitySlug) {
|
|
2765
|
-
return `Not dispatched: capability \`${capabilitySlug ?? "?"}\` is in ASK mode (not trusted for autonomy). Do NOT retry the dispatch. Instead notify the operator (use recommend_to_operator, or rely on the tracking issue that already @-mentions them), then submit_state. To let this capability act on its own, grant it Auto on the dashboard Trust page.`;
|
|
2760
|
+
void capability;
|
|
2761
|
+
void mode;
|
|
2762
|
+
return false;
|
|
2766
2763
|
}
|
|
2767
2764
|
function assertCmsWriteAllowed(opts) {
|
|
2768
|
-
|
|
2769
|
-
return trustRefusal(opts.capabilitySlug);
|
|
2770
|
-
}
|
|
2765
|
+
void opts;
|
|
2771
2766
|
return null;
|
|
2772
2767
|
}
|
|
2773
2768
|
function capabilityToolDefinitions(opts) {
|
|
@@ -2796,9 +2791,6 @@ function capabilityToolDefinitions(opts) {
|
|
|
2796
2791
|
},
|
|
2797
2792
|
handler: async (args) => {
|
|
2798
2793
|
const pr = Number(args.pr);
|
|
2799
|
-
if (isDispatchGated(verb, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2800
|
-
return { content: [{ type: "text", text: trustRefusal(opts.capabilitySlug) }] };
|
|
2801
|
-
}
|
|
2802
2794
|
const result = dispatchVerb(workflowFile, opts.repoSlug, verb, pr);
|
|
2803
2795
|
const text = result.ok ? `Dispatched \`${verb}\` on PR #${pr}. The repair runs in its own workflow_dispatch \u2014 wait for the next tick to see the new headSha.` : `Dispatch failed for \`${verb}\` on PR #${pr}: ${result.error}`;
|
|
2804
2796
|
return { content: [{ type: "text", text }] };
|
|
@@ -2818,7 +2810,7 @@ function capabilityToolDefinitions(opts) {
|
|
|
2818
2810
|
);
|
|
2819
2811
|
const recommendTool = {
|
|
2820
2812
|
name: "recommend_to_operator",
|
|
2821
|
-
description: "Post ONE comment on a PR with the operator @-mention prepended. Use this when
|
|
2813
|
+
description: "Post ONE comment on a PR with the operator @-mention prepended. Use this when the operator should confirm or review something via the dashboard inbox. The mention handle is substituted from kody.config.json `github.operators` \u2014 do not type it yourself.",
|
|
2822
2814
|
inputSchema: {
|
|
2823
2815
|
pr: z3.number().int().positive().describe("PR number to comment on."),
|
|
2824
2816
|
body: z3.string().min(1).describe("Comment body (markdown). Do not include the operator mention \u2014 the engine prepends it.")
|
|
@@ -2921,9 +2913,6 @@ function capabilityToolDefinitions(opts) {
|
|
|
2921
2913
|
if (!Number.isFinite(issue) || issue <= 0) {
|
|
2922
2914
|
return { content: [{ type: "text", text: "Start failed: `issue` is required and must be a positive number." }] };
|
|
2923
2915
|
}
|
|
2924
|
-
if (isDispatchGated(name, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2925
|
-
return { content: [{ type: "text", text: trustRefusal(opts.capabilitySlug) }] };
|
|
2926
|
-
}
|
|
2927
2916
|
const result = startCapability(workflowFile, name, issue, opts.repoSlug);
|
|
2928
2917
|
const text = result.ok ? `Started capability \`${name}\` on #${issue} via workflow_dispatch.` : `Start failed for capability \`${name}\` on #${issue}: ${result.error}`;
|
|
2929
2918
|
return { content: [{ type: "text", text }] };
|
|
@@ -2965,7 +2954,7 @@ function buildCapabilityMcpServer(opts) {
|
|
|
2965
2954
|
});
|
|
2966
2955
|
return { server };
|
|
2967
2956
|
}
|
|
2968
|
-
var FAIL_CONCLUSIONS, RUNNING_STATUSES, THREAD_BODY_MAX, CHECK_FAIL_CONCLUSIONS, DEFAULT_IGNORE_CHECKS, trackMarker, commentMarker,
|
|
2957
|
+
var FAIL_CONCLUSIONS, RUNNING_STATUSES, THREAD_BODY_MAX, CHECK_FAIL_CONCLUSIONS, DEFAULT_IGNORE_CHECKS, trackMarker, commentMarker, CAPABILITY_MCP_TOOL_NAMES;
|
|
2969
2958
|
var init_capabilityMcp = __esm({
|
|
2970
2959
|
"src/capabilityMcp.ts"() {
|
|
2971
2960
|
"use strict";
|
|
@@ -2980,7 +2969,6 @@ var init_capabilityMcp = __esm({
|
|
|
2980
2969
|
DEFAULT_IGNORE_CHECKS = ["run", "kody", "capability-tick", "agent-ask", "chat"];
|
|
2981
2970
|
trackMarker = (key) => `<!-- kody-track:${key} -->`;
|
|
2982
2971
|
commentMarker = (key) => `<!-- kody-track-comment:${key} -->`;
|
|
2983
|
-
GATE_EXEMPT_CAPABILITIES = /* @__PURE__ */ new Set(["qa-engineer", "ui-review"]);
|
|
2984
2972
|
CAPABILITY_MCP_TOOL_NAMES = [
|
|
2985
2973
|
"list_prs_to_repair",
|
|
2986
2974
|
"sync_pr",
|
|
@@ -3586,8 +3574,8 @@ function stripFrontmatter(raw) {
|
|
|
3586
3574
|
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
3587
3575
|
return (match ? match[1] : raw).trim();
|
|
3588
3576
|
}
|
|
3589
|
-
function loadAgentIdentity(cwd,
|
|
3590
|
-
const trimmed =
|
|
3577
|
+
function loadAgentIdentity(cwd, slug, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3578
|
+
const trimmed = slug.trim();
|
|
3591
3579
|
if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
|
|
3592
3580
|
const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
|
|
3593
3581
|
if (fs9.existsSync(agentPath)) {
|
|
@@ -3601,21 +3589,21 @@ function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
|
3601
3589
|
if (builtin) return builtin;
|
|
3602
3590
|
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
3603
3591
|
}
|
|
3604
|
-
function resolveAgentFile(cwd,
|
|
3605
|
-
const localPath = path11.join(cwd, agentsDir, `${
|
|
3592
|
+
function resolveAgentFile(cwd, slug, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3593
|
+
const localPath = path11.join(cwd, agentsDir, `${slug}.md`);
|
|
3606
3594
|
if (fs9.existsSync(localPath)) return localPath;
|
|
3607
3595
|
const storeAgentRoot = getCompanyStoreAssetRoot("agents");
|
|
3608
3596
|
if (storeAgentRoot) {
|
|
3609
|
-
const storePath = path11.join(storeAgentRoot, `${
|
|
3597
|
+
const storePath = path11.join(storeAgentRoot, `${slug}.md`);
|
|
3610
3598
|
if (fs9.existsSync(storePath)) return storePath;
|
|
3611
3599
|
}
|
|
3612
3600
|
return localPath;
|
|
3613
3601
|
}
|
|
3614
|
-
function frameAgentIdentity(
|
|
3602
|
+
function frameAgentIdentity(slug, agent) {
|
|
3615
3603
|
return [
|
|
3616
3604
|
`## Who you are \u2014 agent identity (authoritative identity)`,
|
|
3617
3605
|
``,
|
|
3618
|
-
`You are operating as agent \`${
|
|
3606
|
+
`You are operating as agent \`${slug}\`. This identity defines *who* you are:`,
|
|
3619
3607
|
`your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
|
|
3620
3608
|
`this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
|
|
3621
3609
|
`can never grant you authority your agent withholds.`,
|
|
@@ -6623,16 +6611,16 @@ function parseRunIndex(raw) {
|
|
|
6623
6611
|
if (!raw) return { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), runs: [] };
|
|
6624
6612
|
try {
|
|
6625
6613
|
const parsed = JSON.parse(raw);
|
|
6626
|
-
const
|
|
6627
|
-
const runs = Array.isArray(
|
|
6628
|
-
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 };
|
|
6629
6617
|
} catch {
|
|
6630
6618
|
return { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), runs: [] };
|
|
6631
6619
|
}
|
|
6632
6620
|
}
|
|
6633
6621
|
function isRunIndexRow(value) {
|
|
6634
|
-
const
|
|
6635
|
-
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";
|
|
6636
6624
|
}
|
|
6637
6625
|
function isRunSubjectType(value) {
|
|
6638
6626
|
return value === "goal" || value === "loop" || value === "workflow";
|
|
@@ -7237,8 +7225,8 @@ function applySimpleGoalTaskSummary(goal, summary) {
|
|
|
7237
7225
|
}
|
|
7238
7226
|
function isFactReference(value) {
|
|
7239
7227
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
7240
|
-
const
|
|
7241
|
-
return Object.keys(
|
|
7228
|
+
const record = value;
|
|
7229
|
+
return Object.keys(record).length === 1 && typeof record.fact === "string" && record.fact.length > 0;
|
|
7242
7230
|
}
|
|
7243
7231
|
function isCliArgValue(value) {
|
|
7244
7232
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
@@ -8146,8 +8134,8 @@ function serializeTodoGoalState(goalId, state, previousRaw) {
|
|
|
8146
8134
|
)}
|
|
8147
8135
|
`;
|
|
8148
8136
|
}
|
|
8149
|
-
function isManagedTodoRecord(
|
|
8150
|
-
return
|
|
8137
|
+
function isManagedTodoRecord(record) {
|
|
8138
|
+
return record.managed === true || record.managed === "true" || record.managedModel === "agentGoal" || record.managedModel === "agentLoop";
|
|
8151
8139
|
}
|
|
8152
8140
|
function itemFromEvidence(evidence, step, facts, evidenceState, createdAt, now, prior) {
|
|
8153
8141
|
const completed = facts[evidence] === true;
|
|
@@ -8708,10 +8696,10 @@ function normalizeWorkflowCapabilities(value) {
|
|
|
8708
8696
|
const capabilities = [];
|
|
8709
8697
|
for (const item of value) {
|
|
8710
8698
|
if (typeof item !== "string") continue;
|
|
8711
|
-
const
|
|
8712
|
-
if (!CAPABILITY_ID_PATTERN.test(
|
|
8713
|
-
seen.add(
|
|
8714
|
-
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);
|
|
8715
8703
|
}
|
|
8716
8704
|
return capabilities;
|
|
8717
8705
|
}
|
|
@@ -8841,8 +8829,8 @@ function isStateUnchanged(prev, next) {
|
|
|
8841
8829
|
if (prev.done !== next.done) return false;
|
|
8842
8830
|
return JSON.stringify(prev.data) === JSON.stringify(next.data);
|
|
8843
8831
|
}
|
|
8844
|
-
function stateFilePath(jobsDir,
|
|
8845
|
-
return `${jobsDir.replace(/\/+$/, "")}/${
|
|
8832
|
+
function stateFilePath(jobsDir, slug) {
|
|
8833
|
+
return `${jobsDir.replace(/\/+$/, "")}/${slug}/state.json`;
|
|
8846
8834
|
}
|
|
8847
8835
|
function slugFromStateFilePath(filePath) {
|
|
8848
8836
|
if (/\/state\.json$/i.test(filePath)) {
|
|
@@ -8884,8 +8872,8 @@ var init_contentsApiBackend = __esm({
|
|
|
8884
8872
|
this.jobsDir = stateRepoJobsDir(opts.jobsDir);
|
|
8885
8873
|
this.cwd = opts.cwd;
|
|
8886
8874
|
}
|
|
8887
|
-
load(
|
|
8888
|
-
const filePath = stateFilePath(this.jobsDir,
|
|
8875
|
+
load(slug) {
|
|
8876
|
+
const filePath = stateFilePath(this.jobsDir, slug);
|
|
8889
8877
|
const loaded = readStateText(this.config, this.cwd, filePath);
|
|
8890
8878
|
if (!loaded) {
|
|
8891
8879
|
return { path: filePath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
@@ -8905,20 +8893,20 @@ var init_contentsApiBackend = __esm({
|
|
|
8905
8893
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
8906
8894
|
return false;
|
|
8907
8895
|
}
|
|
8908
|
-
const
|
|
8896
|
+
const slug = slugFromStateFilePath(loaded.path);
|
|
8909
8897
|
const body = `${JSON.stringify(next, null, 2)}
|
|
8910
8898
|
`;
|
|
8911
|
-
const message = `chore(jobs): update state for ${
|
|
8899
|
+
const message = `chore(jobs): update state for ${slug} (rev ${next.rev})`;
|
|
8912
8900
|
const sha = typeof loaded.handle === "string" ? loaded.handle : void 0;
|
|
8913
8901
|
try {
|
|
8914
8902
|
writeStateText(this.config, this.cwd, loaded.path, body, message, sha);
|
|
8915
8903
|
} catch (err) {
|
|
8916
8904
|
if (!isShaConflict(err)) throw err;
|
|
8917
|
-
const current = this.load(
|
|
8905
|
+
const current = this.load(slug);
|
|
8918
8906
|
if (!current.created && isStateUnchanged(current.state, next)) return false;
|
|
8919
8907
|
const currentSha = typeof current.handle === "string" ? current.handle : void 0;
|
|
8920
8908
|
process.stderr.write(
|
|
8921
|
-
`[kody] jobState: concurrent write detected for ${
|
|
8909
|
+
`[kody] jobState: concurrent write detected for ${slug}; reloaded SHA and retrying (last-write-wins)
|
|
8922
8910
|
`
|
|
8923
8911
|
);
|
|
8924
8912
|
writeStateText(this.config, this.cwd, loaded.path, body, message, currentSha);
|
|
@@ -9045,8 +9033,8 @@ var init_localFileBackend = __esm({
|
|
|
9045
9033
|
`);
|
|
9046
9034
|
}
|
|
9047
9035
|
}
|
|
9048
|
-
load(
|
|
9049
|
-
const relPath = stateFilePath(this.jobsDir,
|
|
9036
|
+
load(slug) {
|
|
9037
|
+
const relPath = stateFilePath(this.jobsDir, slug);
|
|
9050
9038
|
const absPath = path27.join(this.cwd, relPath);
|
|
9051
9039
|
if (!fs29.existsSync(absPath)) {
|
|
9052
9040
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
@@ -9178,18 +9166,18 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9178
9166
|
const blockers = [];
|
|
9179
9167
|
const explicitCapabilityTarget = opts.goal.loopTarget?.type === "capability" ? opts.goal.loopTarget.id.trim() : "";
|
|
9180
9168
|
const capabilitySlugs = explicitCapabilityTarget ? [explicitCapabilityTarget] : opts.goal.capabilities;
|
|
9181
|
-
for (const
|
|
9182
|
-
const capability2 = resolveCapabilityFolder(
|
|
9169
|
+
for (const slug of capabilitySlugs) {
|
|
9170
|
+
const capability2 = resolveCapabilityFolder(slug, jobsRoot);
|
|
9183
9171
|
const status = await describeCapabilitySchedule(
|
|
9184
9172
|
capability2,
|
|
9185
|
-
|
|
9173
|
+
slug,
|
|
9186
9174
|
backend,
|
|
9187
|
-
opts.previousScheduleState?.capabilities[
|
|
9175
|
+
opts.previousScheduleState?.capabilities[slug]
|
|
9188
9176
|
);
|
|
9189
|
-
statuses[
|
|
9190
|
-
if (status.state === "blocked") blockers.push(`${
|
|
9177
|
+
statuses[slug] = status;
|
|
9178
|
+
if (status.state === "blocked") blockers.push(`${slug}: ${status.reason}`);
|
|
9191
9179
|
}
|
|
9192
|
-
const due = capabilitySlugs.map((
|
|
9180
|
+
const due = capabilitySlugs.map((slug) => statuses[slug]).filter((status) => status?.state === "due").sort(compareOldestLastFired)[0];
|
|
9193
9181
|
if (!due) {
|
|
9194
9182
|
const reason = blockers.length > 0 ? "no runnable capability; blocked capabilities need attention" : "no runnable capability";
|
|
9195
9183
|
const kind = blockers.length > 0 ? "blocked" : "idle";
|
|
@@ -9238,18 +9226,18 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9238
9226
|
}
|
|
9239
9227
|
};
|
|
9240
9228
|
}
|
|
9241
|
-
async function describeCapabilitySchedule(capability,
|
|
9242
|
-
if (!capability) return { slug
|
|
9229
|
+
async function describeCapabilitySchedule(capability, slug, backend, previous) {
|
|
9230
|
+
if (!capability) return { slug, state: "blocked", reason: "capability folder missing" };
|
|
9243
9231
|
const { config } = capability;
|
|
9244
9232
|
if (config.disabled === true) {
|
|
9245
|
-
return { slug
|
|
9233
|
+
return { slug, title: capability.title, state: "disabled", reason: "disabled" };
|
|
9246
9234
|
}
|
|
9247
9235
|
if (!config.agent || config.agent.trim().length === 0) {
|
|
9248
|
-
return { slug
|
|
9236
|
+
return { slug, title: capability.title, state: "blocked", reason: "no agent assigned" };
|
|
9249
9237
|
}
|
|
9250
9238
|
if (config.implementations && config.implementations.length > 1) {
|
|
9251
9239
|
return {
|
|
9252
|
-
slug
|
|
9240
|
+
slug,
|
|
9253
9241
|
title: capability.title,
|
|
9254
9242
|
state: "blocked",
|
|
9255
9243
|
reason: "multi-implementation capability needs task-jobs route"
|
|
@@ -9258,20 +9246,20 @@ async function describeCapabilitySchedule(capability, slug2, backend, previous)
|
|
|
9258
9246
|
let lastFiredAt = validIso(previous?.lastFiredAt) ? previous?.lastFiredAt : void 0;
|
|
9259
9247
|
try {
|
|
9260
9248
|
if (!lastFiredAt) {
|
|
9261
|
-
const loaded = await backend.load(
|
|
9249
|
+
const loaded = await backend.load(slug);
|
|
9262
9250
|
const raw = loaded.state.data?.lastFiredAt;
|
|
9263
9251
|
if (typeof raw === "string" && validIso(raw)) lastFiredAt = raw;
|
|
9264
9252
|
}
|
|
9265
9253
|
} catch {
|
|
9266
9254
|
return {
|
|
9267
|
-
slug
|
|
9255
|
+
slug,
|
|
9268
9256
|
title: capability.title,
|
|
9269
9257
|
state: "due",
|
|
9270
9258
|
reason: "state unreadable; ready for loop tick"
|
|
9271
9259
|
};
|
|
9272
9260
|
}
|
|
9273
9261
|
return {
|
|
9274
|
-
slug
|
|
9262
|
+
slug,
|
|
9275
9263
|
title: capability.title,
|
|
9276
9264
|
state: "due",
|
|
9277
9265
|
reason: "ready for loop tick",
|
|
@@ -9369,8 +9357,9 @@ function scalarFacts(facts) {
|
|
|
9369
9357
|
}
|
|
9370
9358
|
function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options = {}) {
|
|
9371
9359
|
if (ctx.data.jobForce === true) return null;
|
|
9372
|
-
const
|
|
9373
|
-
|
|
9360
|
+
const selfKind = managedModelKind(goal);
|
|
9361
|
+
const selfMode = selfKind === "Goal" ? firstTrustOverride(ctx, subjectCandidates("goal", goalId, goalState)) : null;
|
|
9362
|
+
if (selfKind === "Goal" && (selfMode === "ask" || selfMode !== "auto" && goal.runWithoutApproval !== true)) {
|
|
9374
9363
|
return `Run without approval is off for ${managedModelKind(goal)} ${goalId}`;
|
|
9375
9364
|
}
|
|
9376
9365
|
if (dispatch2.workflow) {
|
|
@@ -9384,8 +9373,9 @@ function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options =
|
|
|
9384
9373
|
if (targetGoal && targetGoal !== goalId && options.checkTargets !== false) {
|
|
9385
9374
|
const target = fetchGoalState(ctx.config, targetGoal, ctx.cwd);
|
|
9386
9375
|
const targetManaged = target ? managedGoalFromState(expandManagedGoalState(target)) : null;
|
|
9387
|
-
const
|
|
9388
|
-
|
|
9376
|
+
const targetIsGoal = targetManaged ? managedModelKind(targetManaged) === "Goal" : false;
|
|
9377
|
+
const targetMode = targetManaged && targetIsGoal ? firstTrustOverride(ctx, subjectCandidates("goal", targetGoal, target)) : null;
|
|
9378
|
+
if (targetIsGoal && (targetMode === "ask" || targetMode !== "auto" && targetManaged && targetManaged.runWithoutApproval !== true)) {
|
|
9389
9379
|
return `Run without approval is off for goal ${targetGoal}`;
|
|
9390
9380
|
}
|
|
9391
9381
|
}
|
|
@@ -9406,20 +9396,17 @@ function scheduleWaitDecision(previousScheduleState, plannedDecision, reason) {
|
|
|
9406
9396
|
}
|
|
9407
9397
|
function unmarkPlannedCapabilityDispatch(scheduleState, at) {
|
|
9408
9398
|
return Object.fromEntries(
|
|
9409
|
-
Object.entries(scheduleState.capabilities).map(([
|
|
9410
|
-
if (status.lastFiredAt !== at) return [
|
|
9399
|
+
Object.entries(scheduleState.capabilities).map(([slug, status]) => {
|
|
9400
|
+
if (status.lastFiredAt !== at) return [slug, status];
|
|
9411
9401
|
const rest = { ...status };
|
|
9412
9402
|
delete rest.lastFiredAt;
|
|
9413
|
-
return [
|
|
9403
|
+
return [slug, rest];
|
|
9414
9404
|
})
|
|
9415
9405
|
);
|
|
9416
9406
|
}
|
|
9417
9407
|
function managedModelKind(goal) {
|
|
9418
9408
|
return goal.loopTarget || goal.schedule ? "Loop" : "Goal";
|
|
9419
9409
|
}
|
|
9420
|
-
function managedModelSubjectKind(goal) {
|
|
9421
|
-
return managedModelKind(goal) === "Loop" ? "loop" : "goal";
|
|
9422
|
-
}
|
|
9423
9410
|
function subjectCandidates(kind, id, state) {
|
|
9424
9411
|
const ids = /* @__PURE__ */ new Set();
|
|
9425
9412
|
ids.add(id);
|
|
@@ -9588,8 +9575,8 @@ function routeNeedsIssueFact(goal) {
|
|
|
9588
9575
|
return goal.route.some(
|
|
9589
9576
|
(step) => Object.values(step.args ?? {}).some((value) => {
|
|
9590
9577
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9591
|
-
const
|
|
9592
|
-
return Object.keys(
|
|
9578
|
+
const record = value;
|
|
9579
|
+
return Object.keys(record).length === 1 && record.fact === "issue";
|
|
9593
9580
|
})
|
|
9594
9581
|
);
|
|
9595
9582
|
}
|
|
@@ -9598,8 +9585,8 @@ function workflowNeedsIssueFact(goal) {
|
|
|
9598
9585
|
}
|
|
9599
9586
|
function isIssueFactReference(value) {
|
|
9600
9587
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9601
|
-
const
|
|
9602
|
-
return Object.keys(
|
|
9588
|
+
const record = value;
|
|
9589
|
+
return Object.keys(record).length === 1 && record.fact === "issue";
|
|
9603
9590
|
}
|
|
9604
9591
|
function normalizeIssueNumber(value) {
|
|
9605
9592
|
if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
|
|
@@ -9940,9 +9927,9 @@ function resolveTrigger(force) {
|
|
|
9940
9927
|
if (force || event === "issue_comment" || event === "workflow_dispatch") return "manual";
|
|
9941
9928
|
return "event";
|
|
9942
9929
|
}
|
|
9943
|
-
function appendLine(ctx,
|
|
9944
|
-
const filePath = `activity/${
|
|
9945
|
-
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}`);
|
|
9946
9933
|
}
|
|
9947
9934
|
var appendCompanyActivity;
|
|
9948
9935
|
var init_appendCompanyActivity = __esm({
|
|
@@ -9958,7 +9945,7 @@ var init_appendCompanyActivity = __esm({
|
|
|
9958
9945
|
const agent = ctx.data.agentSlug || null;
|
|
9959
9946
|
const agentTitle = ctx.data.agentTitle || null;
|
|
9960
9947
|
const force = ctx.args?.force === true;
|
|
9961
|
-
const
|
|
9948
|
+
const record = {
|
|
9962
9949
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9963
9950
|
action: `Ran capability: ${capabilityTitle ?? capability}`,
|
|
9964
9951
|
capability,
|
|
@@ -9972,7 +9959,7 @@ var init_appendCompanyActivity = __esm({
|
|
|
9972
9959
|
durationMs: agentResult?.durationMs ?? null,
|
|
9973
9960
|
runUrl: getRunUrl() || null
|
|
9974
9961
|
};
|
|
9975
|
-
appendLine(ctx,
|
|
9962
|
+
appendLine(ctx, record);
|
|
9976
9963
|
} catch (err) {
|
|
9977
9964
|
process.stderr.write(
|
|
9978
9965
|
`[activity] company-activity append failed: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -9983,494 +9970,6 @@ var init_appendCompanyActivity = __esm({
|
|
|
9983
9970
|
}
|
|
9984
9971
|
});
|
|
9985
9972
|
|
|
9986
|
-
// src/agencyArchitectDecision.ts
|
|
9987
|
-
function parseAgencyArchitectDecisionText(finalText) {
|
|
9988
|
-
const raw = extractDecisionJson(finalText);
|
|
9989
|
-
const parsed = JSON.parse(raw);
|
|
9990
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9991
|
-
throw new Error("agency-architect decision must be JSON object");
|
|
9992
|
-
}
|
|
9993
|
-
const input = parsed;
|
|
9994
|
-
const actions = Array.isArray(input.actions) ? input.actions.map(parseAction) : [];
|
|
9995
|
-
return {
|
|
9996
|
-
summary: typeof input.summary === "string" ? input.summary.trim() : "",
|
|
9997
|
-
actions
|
|
9998
|
-
};
|
|
9999
|
-
}
|
|
10000
|
-
function buildManagedGoalState(action) {
|
|
10001
|
-
const at = nowIso();
|
|
10002
|
-
return {
|
|
10003
|
-
state: "active",
|
|
10004
|
-
createdAt: at,
|
|
10005
|
-
updatedAt: at,
|
|
10006
|
-
extra: {
|
|
10007
|
-
type: action.goalType ?? "release",
|
|
10008
|
-
destination: { outcome: action.outcome, evidence: action.evidence },
|
|
10009
|
-
capabilities: action.capabilities,
|
|
10010
|
-
route: action.route,
|
|
10011
|
-
facts: action.facts ?? {},
|
|
10012
|
-
blockers: [],
|
|
10013
|
-
createdByIntent: action.intentId,
|
|
10014
|
-
manager: "cto"
|
|
10015
|
-
}
|
|
10016
|
-
};
|
|
10017
|
-
}
|
|
10018
|
-
function buildAgentLoopState(action) {
|
|
10019
|
-
const at = nowIso();
|
|
10020
|
-
return {
|
|
10021
|
-
state: "active",
|
|
10022
|
-
createdAt: at,
|
|
10023
|
-
updatedAt: at,
|
|
10024
|
-
extra: {
|
|
10025
|
-
type: "agentLoop",
|
|
10026
|
-
scheduleMode: "agentLoop",
|
|
10027
|
-
schedule: action.every,
|
|
10028
|
-
destination: { outcome: action.outcome, evidence: [] },
|
|
10029
|
-
capabilities: action.capabilities,
|
|
10030
|
-
route: [],
|
|
10031
|
-
facts: {},
|
|
10032
|
-
blockers: [],
|
|
10033
|
-
createdByIntent: action.intentId,
|
|
10034
|
-
manager: "cto"
|
|
10035
|
-
}
|
|
10036
|
-
};
|
|
10037
|
-
}
|
|
10038
|
-
function extractDecisionJson(finalText) {
|
|
10039
|
-
const fence = finalText.match(/```(?:kody-agency-architect-decision|json)\s*([\s\S]*?)```/i);
|
|
10040
|
-
if (fence?.[1]) return fence[1].trim();
|
|
10041
|
-
const line = finalText.match(/KODY_AGENCY_ARCHITECT_DECISION=(\{[\s\S]*\})/);
|
|
10042
|
-
if (line?.[1]) return line[1].trim();
|
|
10043
|
-
throw new Error("missing kody-agency-architect-decision JSON");
|
|
10044
|
-
}
|
|
10045
|
-
function parseAction(value) {
|
|
10046
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10047
|
-
throw new Error("agency-architect action must be object");
|
|
10048
|
-
}
|
|
10049
|
-
const input = value;
|
|
10050
|
-
const kind = input.kind;
|
|
10051
|
-
if (kind === "createManagedGoal") return parseCreateManagedGoal(input);
|
|
10052
|
-
if (kind === "createAgentLoop") return parseCreateAgentLoop(input);
|
|
10053
|
-
if (kind === "setGoalLifecycle") return parseSetGoalLifecycle(input);
|
|
10054
|
-
if (kind === "updateIntentPortfolio") return parseUpdateIntentPortfolio(input);
|
|
10055
|
-
if (kind === "note") return parseNote(input);
|
|
10056
|
-
throw new Error(`unsupported agency-architect action kind: ${String(kind)}`);
|
|
10057
|
-
}
|
|
10058
|
-
function parseCreateManagedGoal(input) {
|
|
10059
|
-
const route = Array.isArray(input.route) ? input.route.map(parseRouteStep) : [];
|
|
10060
|
-
if (route.length === 0) throw new Error("createManagedGoal requires route");
|
|
10061
|
-
const evidence = stringArray3(input.evidence);
|
|
10062
|
-
if (evidence.length === 0) throw new Error("createManagedGoal requires evidence");
|
|
10063
|
-
return {
|
|
10064
|
-
kind: "createManagedGoal",
|
|
10065
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10066
|
-
id: slug(input.id, "id"),
|
|
10067
|
-
outcome: requiredString(input.outcome, "outcome"),
|
|
10068
|
-
goalType: typeof input.goalType === "string" && input.goalType.trim() ? input.goalType.trim() : void 0,
|
|
10069
|
-
evidence,
|
|
10070
|
-
capabilities: nonEmptyStringArray(input.capabilities, "capabilities"),
|
|
10071
|
-
route,
|
|
10072
|
-
facts: record(input.facts) ?? {},
|
|
10073
|
-
reason: requiredString(input.reason, "reason")
|
|
10074
|
-
};
|
|
10075
|
-
}
|
|
10076
|
-
function parseCreateAgentLoop(input) {
|
|
10077
|
-
return {
|
|
10078
|
-
kind: "createAgentLoop",
|
|
10079
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10080
|
-
id: slug(input.id, "id"),
|
|
10081
|
-
outcome: requiredString(input.outcome, "outcome"),
|
|
10082
|
-
every: oneOf(input.every, ["manual", "1h", "1d", "7d", "30d"], "1d"),
|
|
10083
|
-
capabilities: nonEmptyStringArray(input.capabilities, "capabilities"),
|
|
10084
|
-
reason: requiredString(input.reason, "reason")
|
|
10085
|
-
};
|
|
10086
|
-
}
|
|
10087
|
-
function parseSetGoalLifecycle(input) {
|
|
10088
|
-
return {
|
|
10089
|
-
kind: "setGoalLifecycle",
|
|
10090
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10091
|
-
id: slug(input.id, "id"),
|
|
10092
|
-
state: oneOf(input.state, ["active", "closed", "abandoned"], "active"),
|
|
10093
|
-
reason: requiredString(input.reason, "reason")
|
|
10094
|
-
};
|
|
10095
|
-
}
|
|
10096
|
-
function parseUpdateIntentPortfolio(input) {
|
|
10097
|
-
return {
|
|
10098
|
-
kind: "updateIntentPortfolio",
|
|
10099
|
-
intentId: slug(input.intentId, "intentId"),
|
|
10100
|
-
goals: stringArray3(input.goals).filter(isSlug),
|
|
10101
|
-
loops: stringArray3(input.loops).filter(isSlug),
|
|
10102
|
-
capabilities: stringArray3(input.capabilities).filter(isSlug),
|
|
10103
|
-
reason: requiredString(input.reason, "reason")
|
|
10104
|
-
};
|
|
10105
|
-
}
|
|
10106
|
-
function parseNote(input) {
|
|
10107
|
-
return {
|
|
10108
|
-
kind: "note",
|
|
10109
|
-
intentId: typeof input.intentId === "string" && isSlug(input.intentId) ? input.intentId : void 0,
|
|
10110
|
-
message: requiredString(input.message ?? input.content, "message")
|
|
10111
|
-
};
|
|
10112
|
-
}
|
|
10113
|
-
function parseRouteStep(value) {
|
|
10114
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("route step must be object");
|
|
10115
|
-
const input = value;
|
|
10116
|
-
return {
|
|
10117
|
-
stage: requiredString(input.stage, "route.stage"),
|
|
10118
|
-
evidence: requiredString(input.evidence, "route.evidence"),
|
|
10119
|
-
capability: slug(input.capability, "route.capability"),
|
|
10120
|
-
...typeof input.implementation === "string" && input.implementation.trim() ? { implementation: input.implementation.trim() } : {},
|
|
10121
|
-
...record(input.args) ? { args: record(input.args) } : {}
|
|
10122
|
-
};
|
|
10123
|
-
}
|
|
10124
|
-
function slug(value, field) {
|
|
10125
|
-
const text = requiredString(value, field);
|
|
10126
|
-
if (!isSlug(text)) throw new Error(`${field} must be lowercase slug`);
|
|
10127
|
-
return text;
|
|
10128
|
-
}
|
|
10129
|
-
function isSlug(value) {
|
|
10130
|
-
return SLUG_RE.test(value);
|
|
10131
|
-
}
|
|
10132
|
-
function requiredString(value, field) {
|
|
10133
|
-
if (typeof value !== "string" || !value.trim()) throw new Error(`${field} is required`);
|
|
10134
|
-
return value.trim();
|
|
10135
|
-
}
|
|
10136
|
-
function stringArray3(value) {
|
|
10137
|
-
if (!Array.isArray(value)) return [];
|
|
10138
|
-
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
10139
|
-
}
|
|
10140
|
-
function nonEmptyStringArray(value, field) {
|
|
10141
|
-
const values = stringArray3(value);
|
|
10142
|
-
if (values.length === 0) throw new Error(`${field} must not be empty`);
|
|
10143
|
-
return values;
|
|
10144
|
-
}
|
|
10145
|
-
function record(value) {
|
|
10146
|
-
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : null;
|
|
10147
|
-
}
|
|
10148
|
-
function oneOf(value, allowed, fallback) {
|
|
10149
|
-
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
10150
|
-
}
|
|
10151
|
-
var SLUG_RE;
|
|
10152
|
-
var init_agencyArchitectDecision = __esm({
|
|
10153
|
-
"src/agencyArchitectDecision.ts"() {
|
|
10154
|
-
"use strict";
|
|
10155
|
-
init_state2();
|
|
10156
|
-
SLUG_RE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
10157
|
-
}
|
|
10158
|
-
});
|
|
10159
|
-
|
|
10160
|
-
// src/companyIntent.ts
|
|
10161
|
-
function isCompanyIntentId(value) {
|
|
10162
|
-
return SLUG_RE2.test(value);
|
|
10163
|
-
}
|
|
10164
|
-
function companyIntentPath(id) {
|
|
10165
|
-
assertIntentId(id);
|
|
10166
|
-
return `intents/${id}/intent.json`;
|
|
10167
|
-
}
|
|
10168
|
-
function normalizeCompanyIntent(path51, raw) {
|
|
10169
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
10170
|
-
throw new Error(`${path51}: intent must be JSON object`);
|
|
10171
|
-
}
|
|
10172
|
-
const input = raw;
|
|
10173
|
-
const id = stringField4(input.id);
|
|
10174
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${path51}: invalid intent id`);
|
|
10175
|
-
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
10176
|
-
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
10177
|
-
const description = stringField4(input.description);
|
|
10178
|
-
return {
|
|
10179
|
-
version: 1,
|
|
10180
|
-
id,
|
|
10181
|
-
status: oneOf2(input.status, ["active", "paused", "archived"], "active"),
|
|
10182
|
-
for: stringField4(input.for),
|
|
10183
|
-
...description ? { description } : {},
|
|
10184
|
-
priority: numberField(input.priority, 100),
|
|
10185
|
-
posture: oneOf2(
|
|
10186
|
-
input.posture,
|
|
10187
|
-
["confidence", "speed", "stability-recovery", "maintenance", "balanced"],
|
|
10188
|
-
"balanced"
|
|
10189
|
-
),
|
|
10190
|
-
scope: {
|
|
10191
|
-
repos: stringArray4(recordField3(input.scope)?.repos),
|
|
10192
|
-
areas: stringArray4(recordField3(input.scope)?.areas)
|
|
10193
|
-
},
|
|
10194
|
-
principles: stringArray4(input.principles),
|
|
10195
|
-
metrics: stringArray4(input.metrics),
|
|
10196
|
-
policy: {
|
|
10197
|
-
release: normalizeReleasePolicy(recordField3(recordField3(input.policy)?.release)),
|
|
10198
|
-
automation: normalizeAutomationPolicy(recordField3(recordField3(input.policy)?.automation))
|
|
10199
|
-
},
|
|
10200
|
-
portfolio: {
|
|
10201
|
-
goals: stringArray4(recordField3(input.portfolio)?.goals).filter(isCompanyIntentId),
|
|
10202
|
-
loops: stringArray4(recordField3(input.portfolio)?.loops).filter(isCompanyIntentId),
|
|
10203
|
-
capabilities: stringArray4(recordField3(input.portfolio)?.capabilities).filter(isCompanyIntentId)
|
|
10204
|
-
},
|
|
10205
|
-
manager: normalizeManager(recordField3(input.manager)),
|
|
10206
|
-
createdAt,
|
|
10207
|
-
updatedAt
|
|
10208
|
-
};
|
|
10209
|
-
}
|
|
10210
|
-
function listCompanyIntents(config, cwd) {
|
|
10211
|
-
const entries = listStateDirectory(config, cwd, "intents");
|
|
10212
|
-
const records = [];
|
|
10213
|
-
for (const entry of entries) {
|
|
10214
|
-
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
10215
|
-
const path51 = companyIntentPath(entry.name);
|
|
10216
|
-
const file = readStateText(config, cwd, path51);
|
|
10217
|
-
if (!file) continue;
|
|
10218
|
-
records.push({
|
|
10219
|
-
id: entry.name,
|
|
10220
|
-
path: file.path,
|
|
10221
|
-
intent: normalizeCompanyIntent(file.path, JSON.parse(file.content))
|
|
10222
|
-
});
|
|
10223
|
-
}
|
|
10224
|
-
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
10225
|
-
}
|
|
10226
|
-
function readCompanyIntent(config, cwd, id) {
|
|
10227
|
-
const path51 = companyIntentPath(id);
|
|
10228
|
-
const file = readStateText(config, cwd, path51);
|
|
10229
|
-
if (!file) return null;
|
|
10230
|
-
return { id, path: file.path, intent: normalizeCompanyIntent(file.path, JSON.parse(file.content)) };
|
|
10231
|
-
}
|
|
10232
|
-
function writeCompanyIntent(config, cwd, intent, message = `chore(intents): update ${intent.id}`) {
|
|
10233
|
-
upsertStateText(config, cwd, companyIntentPath(intent.id), `${JSON.stringify(intent, null, 2)}
|
|
10234
|
-
`, message);
|
|
10235
|
-
}
|
|
10236
|
-
function appendCompanyIntentDecision(config, cwd, intentId, entry) {
|
|
10237
|
-
assertIntentId(intentId);
|
|
10238
|
-
appendStateLine(
|
|
10239
|
-
config,
|
|
10240
|
-
cwd,
|
|
10241
|
-
`intents/${intentId}/decisions.jsonl`,
|
|
10242
|
-
JSON.stringify(entry),
|
|
10243
|
-
`chore(intents): log ${intentId} decision`
|
|
10244
|
-
);
|
|
10245
|
-
}
|
|
10246
|
-
function listCompanyPortfolio(config, cwd) {
|
|
10247
|
-
const goals = [];
|
|
10248
|
-
for (const id of listGoalStateIds(config, cwd)) {
|
|
10249
|
-
if (!isCompanyIntentId(id)) continue;
|
|
10250
|
-
const state = fetchGoalState(config, id, cwd);
|
|
10251
|
-
if (!state) continue;
|
|
10252
|
-
const destination = recordField3(state.extra.destination);
|
|
10253
|
-
goals.push({
|
|
10254
|
-
id,
|
|
10255
|
-
state: state.state,
|
|
10256
|
-
type: stringField4(state.extra.type) || void 0,
|
|
10257
|
-
outcome: stringField4(destination?.outcome) || void 0,
|
|
10258
|
-
capabilities: stringArray4(state.extra.capabilities),
|
|
10259
|
-
isLoop: state.extra.scheduleMode === "agentLoop" || state.extra.type === "agentLoop",
|
|
10260
|
-
updatedAt: state.updatedAt
|
|
10261
|
-
});
|
|
10262
|
-
}
|
|
10263
|
-
return { goals: goals.sort((a, b) => a.id.localeCompare(b.id)) };
|
|
10264
|
-
}
|
|
10265
|
-
function writeCompanyGoalState(config, cwd, id, state, message) {
|
|
10266
|
-
assertIntentId(id);
|
|
10267
|
-
putGoalState(config, id, state, message, cwd);
|
|
10268
|
-
}
|
|
10269
|
-
function assertIntentId(id) {
|
|
10270
|
-
if (!isCompanyIntentId(id)) throw new Error(`invalid intent/portfolio id: ${id}`);
|
|
10271
|
-
}
|
|
10272
|
-
function stringField4(value) {
|
|
10273
|
-
return typeof value === "string" ? value.trim() : "";
|
|
10274
|
-
}
|
|
10275
|
-
function numberField(value, fallback) {
|
|
10276
|
-
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
10277
|
-
}
|
|
10278
|
-
function recordField3(value) {
|
|
10279
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
10280
|
-
}
|
|
10281
|
-
function stringArray4(value) {
|
|
10282
|
-
if (!Array.isArray(value)) return [];
|
|
10283
|
-
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
10284
|
-
}
|
|
10285
|
-
function oneOf2(value, allowed, fallback) {
|
|
10286
|
-
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
10287
|
-
}
|
|
10288
|
-
function normalizeReleasePolicy(raw) {
|
|
10289
|
-
if (!raw) return void 0;
|
|
10290
|
-
return {
|
|
10291
|
-
cadence: oneOf2(raw.cadence, ["manual", "1d", "1w"], "manual"),
|
|
10292
|
-
qaDepth: oneOf2(raw.qaDepth, ["light", "standard", "strict"], "standard"),
|
|
10293
|
-
blockerLevel: oneOf2(raw.blockerLevel, ["low", "standard", "strict"], "standard"),
|
|
10294
|
-
approval: oneOf2(
|
|
10295
|
-
raw.approval,
|
|
10296
|
-
["none", "before-production", "before-risky-actions"],
|
|
10297
|
-
"before-risky-actions"
|
|
10298
|
-
)
|
|
10299
|
-
};
|
|
10300
|
-
}
|
|
10301
|
-
function normalizeAutomationPolicy(raw) {
|
|
10302
|
-
return {
|
|
10303
|
-
authority: "full-auto",
|
|
10304
|
-
maxConcurrentGoals: Math.max(1, Math.floor(numberField(raw?.maxConcurrentGoals, 1))),
|
|
10305
|
-
maxDailyActions: Math.max(1, Math.floor(numberField(raw?.maxDailyActions, 6))),
|
|
10306
|
-
requiresHumanFor: stringArray4(raw?.requiresHumanFor)
|
|
10307
|
-
};
|
|
10308
|
-
}
|
|
10309
|
-
function normalizeManager(raw) {
|
|
10310
|
-
return {
|
|
10311
|
-
agent: "cto",
|
|
10312
|
-
loop: "agency-architect-loop",
|
|
10313
|
-
capability: "agency-architect",
|
|
10314
|
-
reviewEvery: oneOf2(raw?.reviewEvery, ["1d", "1w"], "1d"),
|
|
10315
|
-
...typeof raw?.lastReviewedAt === "string" ? { lastReviewedAt: raw.lastReviewedAt } : {}
|
|
10316
|
-
};
|
|
10317
|
-
}
|
|
10318
|
-
var SLUG_RE2;
|
|
10319
|
-
var init_companyIntent = __esm({
|
|
10320
|
-
"src/companyIntent.ts"() {
|
|
10321
|
-
"use strict";
|
|
10322
|
-
init_state2();
|
|
10323
|
-
init_stateStore();
|
|
10324
|
-
init_stateRepo();
|
|
10325
|
-
SLUG_RE2 = /^[a-z][a-z0-9-]{0,63}$/;
|
|
10326
|
-
}
|
|
10327
|
-
});
|
|
10328
|
-
|
|
10329
|
-
// src/scripts/applyAgencyArchitectDecision.ts
|
|
10330
|
-
function applyAction(config, cwd, action) {
|
|
10331
|
-
if (action.kind === "createManagedGoal") {
|
|
10332
|
-
const existing = fetchGoalState(config, action.id, cwd);
|
|
10333
|
-
if (existing) return applied(action, false, "goal already exists");
|
|
10334
|
-
writeCompanyGoalState(
|
|
10335
|
-
config,
|
|
10336
|
-
cwd,
|
|
10337
|
-
action.id,
|
|
10338
|
-
buildManagedGoalState(action),
|
|
10339
|
-
`chore(goals): create ${action.id} from intent ${action.intentId}`
|
|
10340
|
-
);
|
|
10341
|
-
return applied(action, true, action.reason, action.id);
|
|
10342
|
-
}
|
|
10343
|
-
if (action.kind === "createAgentLoop") {
|
|
10344
|
-
const existing = fetchGoalState(config, action.id, cwd);
|
|
10345
|
-
if (existing) return applied(action, false, "loop already exists");
|
|
10346
|
-
writeCompanyGoalState(
|
|
10347
|
-
config,
|
|
10348
|
-
cwd,
|
|
10349
|
-
action.id,
|
|
10350
|
-
buildAgentLoopState(action),
|
|
10351
|
-
`chore(goals): create loop ${action.id} from intent ${action.intentId}`
|
|
10352
|
-
);
|
|
10353
|
-
return applied(action, true, action.reason, action.id);
|
|
10354
|
-
}
|
|
10355
|
-
if (action.kind === "setGoalLifecycle") {
|
|
10356
|
-
const state = fetchGoalState(config, action.id, cwd);
|
|
10357
|
-
if (!state) return applied(action, false, "goal/loop missing", action.id);
|
|
10358
|
-
const before = state.state;
|
|
10359
|
-
if (before === action.state) return applied(action, false, "state already set", action.id);
|
|
10360
|
-
const next = {
|
|
10361
|
-
...state,
|
|
10362
|
-
state: action.state,
|
|
10363
|
-
updatedAt: nowIso(),
|
|
10364
|
-
extra: {
|
|
10365
|
-
...state.extra,
|
|
10366
|
-
lifecycleChangedByIntent: action.intentId,
|
|
10367
|
-
lifecycleChangeReason: action.reason
|
|
10368
|
-
}
|
|
10369
|
-
};
|
|
10370
|
-
writeCompanyGoalState(
|
|
10371
|
-
config,
|
|
10372
|
-
cwd,
|
|
10373
|
-
action.id,
|
|
10374
|
-
next,
|
|
10375
|
-
`chore(goals): ${action.state} ${action.id} from intent ${action.intentId}`
|
|
10376
|
-
);
|
|
10377
|
-
return applied(action, true, action.reason, action.id);
|
|
10378
|
-
}
|
|
10379
|
-
if (action.kind === "updateIntentPortfolio") {
|
|
10380
|
-
const record2 = readCompanyIntent(config, cwd, action.intentId);
|
|
10381
|
-
if (!record2) return applied(action, false, "intent missing");
|
|
10382
|
-
const intent = {
|
|
10383
|
-
...record2.intent,
|
|
10384
|
-
portfolio: {
|
|
10385
|
-
goals: mergeUnique(record2.intent.portfolio.goals, action.goals ?? []),
|
|
10386
|
-
loops: mergeUnique(record2.intent.portfolio.loops, action.loops ?? []),
|
|
10387
|
-
capabilities: mergeUnique(record2.intent.portfolio.capabilities, action.capabilities ?? [])
|
|
10388
|
-
},
|
|
10389
|
-
updatedAt: nowIso()
|
|
10390
|
-
};
|
|
10391
|
-
writeCompanyIntent(config, cwd, intent, `chore(intents): update ${action.intentId} portfolio`);
|
|
10392
|
-
return applied(action, true, action.reason);
|
|
10393
|
-
}
|
|
10394
|
-
if (action.kind === "note") {
|
|
10395
|
-
return {
|
|
10396
|
-
kind: action.kind,
|
|
10397
|
-
intentId: action.intentId,
|
|
10398
|
-
changed: false,
|
|
10399
|
-
reason: action.message
|
|
10400
|
-
};
|
|
10401
|
-
}
|
|
10402
|
-
return { kind: "unknown", changed: false, reason: "unsupported action" };
|
|
10403
|
-
}
|
|
10404
|
-
function applied(action, changed, reason, resource) {
|
|
10405
|
-
return {
|
|
10406
|
-
kind: action.kind,
|
|
10407
|
-
intentId: "intentId" in action ? action.intentId : void 0,
|
|
10408
|
-
resource,
|
|
10409
|
-
changed,
|
|
10410
|
-
reason
|
|
10411
|
-
};
|
|
10412
|
-
}
|
|
10413
|
-
function mergeUnique(left, right) {
|
|
10414
|
-
return [.../* @__PURE__ */ new Set([...left, ...right])].sort();
|
|
10415
|
-
}
|
|
10416
|
-
function logAppliedAgencyArchitectActions(config, cwd, appliedActions) {
|
|
10417
|
-
const at = nowIso();
|
|
10418
|
-
for (const action of appliedActions) {
|
|
10419
|
-
if (!action.intentId) continue;
|
|
10420
|
-
appendCompanyIntentDecision(config, cwd, action.intentId, {
|
|
10421
|
-
at,
|
|
10422
|
-
agent: "cto",
|
|
10423
|
-
intentId: action.intentId,
|
|
10424
|
-
action: action.kind,
|
|
10425
|
-
reason: action.reason,
|
|
10426
|
-
after: { changed: action.changed },
|
|
10427
|
-
resources: action.resource ? [action.resource] : []
|
|
10428
|
-
});
|
|
10429
|
-
}
|
|
10430
|
-
}
|
|
10431
|
-
var applyAgencyArchitectDecision;
|
|
10432
|
-
var init_applyAgencyArchitectDecision = __esm({
|
|
10433
|
-
"src/scripts/applyAgencyArchitectDecision.ts"() {
|
|
10434
|
-
"use strict";
|
|
10435
|
-
init_agencyArchitectDecision();
|
|
10436
|
-
init_companyIntent();
|
|
10437
|
-
init_state2();
|
|
10438
|
-
init_stateStore();
|
|
10439
|
-
applyAgencyArchitectDecision = async (ctx) => {
|
|
10440
|
-
const decision = ctx.data.agencyArchitectDecision;
|
|
10441
|
-
if (!decision || !Array.isArray(decision.actions)) return;
|
|
10442
|
-
if (ctx.output.exitCode !== 0) return;
|
|
10443
|
-
const applied2 = [];
|
|
10444
|
-
for (const action of decision.actions) {
|
|
10445
|
-
applied2.push(applyAction(ctx.config, ctx.cwd, action));
|
|
10446
|
-
}
|
|
10447
|
-
ctx.data.agencyArchitectApplied = applied2;
|
|
10448
|
-
ctx.data.agencyArchitectApplySummary = `agency-architect applied ${applied2.filter((item) => item.changed).length}/${applied2.length} action(s)`;
|
|
10449
|
-
};
|
|
10450
|
-
}
|
|
10451
|
-
});
|
|
10452
|
-
|
|
10453
|
-
// src/scripts/appendCompanyIntentDecision.ts
|
|
10454
|
-
var appendCompanyIntentDecision2;
|
|
10455
|
-
var init_appendCompanyIntentDecision = __esm({
|
|
10456
|
-
"src/scripts/appendCompanyIntentDecision.ts"() {
|
|
10457
|
-
"use strict";
|
|
10458
|
-
init_applyAgencyArchitectDecision();
|
|
10459
|
-
appendCompanyIntentDecision2 = async (ctx) => {
|
|
10460
|
-
const applied2 = ctx.data.agencyArchitectApplied;
|
|
10461
|
-
if (!applied2 || applied2.length === 0) return;
|
|
10462
|
-
try {
|
|
10463
|
-
logAppliedAgencyArchitectActions(ctx.config, ctx.cwd, applied2);
|
|
10464
|
-
} catch (err) {
|
|
10465
|
-
process.stderr.write(
|
|
10466
|
-
`[agency-architect] failed append intent decision log: ${err instanceof Error ? err.message : String(err)}
|
|
10467
|
-
`
|
|
10468
|
-
);
|
|
10469
|
-
}
|
|
10470
|
-
};
|
|
10471
|
-
}
|
|
10472
|
-
});
|
|
10473
|
-
|
|
10474
9973
|
// src/capabilityEvidence.ts
|
|
10475
9974
|
function capabilityReportToEvidence(report) {
|
|
10476
9975
|
if (report.target.type !== "goal") return null;
|
|
@@ -10641,7 +10140,7 @@ function retryAfterSecondsFor(route, evidence) {
|
|
|
10641
10140
|
const step = route.find(
|
|
10642
10141
|
(item) => !!item && typeof item === "object" && !Array.isArray(item) && item.evidence === evidence
|
|
10643
10142
|
);
|
|
10644
|
-
const policy = step &&
|
|
10143
|
+
const policy = step && recordField3(step.onFailure);
|
|
10645
10144
|
const retryAfter = typeof policy?.retryAfterSeconds === "number" ? policy.retryAfterSeconds : void 0;
|
|
10646
10145
|
return retryAfter !== void 0 && retryAfter >= 0 ? Math.floor(retryAfter) : void 0;
|
|
10647
10146
|
}
|
|
@@ -10690,7 +10189,7 @@ function parseStringArray3(raw) {
|
|
|
10690
10189
|
}
|
|
10691
10190
|
return out;
|
|
10692
10191
|
}
|
|
10693
|
-
function
|
|
10192
|
+
function recordField3(value) {
|
|
10694
10193
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
10695
10194
|
}
|
|
10696
10195
|
var CONTROL_FACT_KEYS3;
|
|
@@ -10747,7 +10246,7 @@ function capabilityEvidenceOutput(evidence) {
|
|
|
10747
10246
|
function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
10748
10247
|
const outputs = evidenceItems.map(capabilityEvidenceOutput);
|
|
10749
10248
|
const latestOutput = outputs.at(-1);
|
|
10750
|
-
const facts =
|
|
10249
|
+
const facts = recordField4(snapshot, "facts") ?? recordField4(state.extra, "facts") ?? {};
|
|
10751
10250
|
const blockers = uniqueStrings2([
|
|
10752
10251
|
...stringArrayField(snapshot, "blockers"),
|
|
10753
10252
|
...stringArrayField(latestEvent, "blockers"),
|
|
@@ -10766,12 +10265,12 @@ function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
|
10766
10265
|
"",
|
|
10767
10266
|
"## Status",
|
|
10768
10267
|
`- State: ${state.state}`,
|
|
10769
|
-
`- Stage: ${
|
|
10268
|
+
`- Stage: ${stringField4(snapshot, "stage") ?? stringField4(state.extra, "stage") ?? "unknown"}`,
|
|
10770
10269
|
`- Next step: ${nextStepFromEvent(state, snapshot, latestOutput, latestEvent)}`,
|
|
10771
10270
|
`- Updated: ${state.updatedAt ?? state.createdAt ?? state.startedAt ?? "unknown"}`,
|
|
10772
10271
|
"",
|
|
10773
10272
|
"## Decision",
|
|
10774
|
-
`- Event: ${
|
|
10273
|
+
`- Event: ${stringField4(latestEvent, "event") ?? "unknown"}`,
|
|
10775
10274
|
`- Reason: ${decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers)}`,
|
|
10776
10275
|
`- Required evidence: ${listOrNone(stringArrayField(snapshot, "requiredEvidence"))}`,
|
|
10777
10276
|
`- Satisfied evidence: ${listOrNone(stringArrayField(snapshot, "satisfiedEvidence"))}`,
|
|
@@ -10799,9 +10298,9 @@ function capabilityEvidenceMarkdown(outputs) {
|
|
|
10799
10298
|
function decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers) {
|
|
10800
10299
|
if (state.state === "done") return "destination evidence satisfied";
|
|
10801
10300
|
if (blockers.length > 0) return blockers[0] ?? "blocked";
|
|
10802
|
-
const eventReason =
|
|
10301
|
+
const eventReason = stringField4(latestEvent, "reason") ?? stringField4(recordField4(latestEvent, "decision"), "reason");
|
|
10803
10302
|
if (eventReason) return eventReason;
|
|
10804
|
-
const summary =
|
|
10303
|
+
const summary = stringField4(latestOutput, "summary");
|
|
10805
10304
|
if (summary) return summary;
|
|
10806
10305
|
if (missingEvidence.length > 0) return `waiting for ${missingEvidence[0]}`;
|
|
10807
10306
|
return "waiting for more evidence";
|
|
@@ -10809,33 +10308,33 @@ function decisionReason(state, latestEvent, latestOutput, missingEvidence, block
|
|
|
10809
10308
|
function evidenceOutputMarkdown(index, output) {
|
|
10810
10309
|
return [
|
|
10811
10310
|
`### Output ${index}`,
|
|
10812
|
-
`- Status: ${
|
|
10813
|
-
`- Summary: ${
|
|
10311
|
+
`- Status: ${stringField4(output, "status") ?? "unknown"}`,
|
|
10312
|
+
`- Summary: ${stringField4(output, "summary") ?? "no summary"}`,
|
|
10814
10313
|
`- Sources: ${listOrNone(stringArrayField(output, "sources"))}`,
|
|
10815
|
-
`- Evidence values: ${inlineJson(
|
|
10314
|
+
`- Evidence values: ${inlineJson(recordField4(output, "evidence") ?? {})}`,
|
|
10816
10315
|
`- Missing evidence: ${listOrNone(stringArrayField(output, "missingEvidence"))}`,
|
|
10817
10316
|
`- Blockers: ${listOrNone(stringArrayField(output, "blockers"))}`,
|
|
10818
10317
|
""
|
|
10819
10318
|
];
|
|
10820
10319
|
}
|
|
10821
10320
|
function dispatchContextMarkdown(latestEvent) {
|
|
10822
|
-
const context =
|
|
10321
|
+
const context = recordField4(latestEvent, "dispatchContext");
|
|
10823
10322
|
if (!context) return ["- none"];
|
|
10824
|
-
const githubActor =
|
|
10825
|
-
const githubActorRole =
|
|
10826
|
-
const target = dispatchTargetLabel(
|
|
10323
|
+
const githubActor = stringField4(context, "githubActor");
|
|
10324
|
+
const githubActorRole = stringField4(context, "githubActorRole");
|
|
10325
|
+
const target = dispatchTargetLabel(recordField4(context, "target"));
|
|
10827
10326
|
return [
|
|
10828
|
-
`- Triggered by: ${
|
|
10829
|
-
`- Mode: ${
|
|
10327
|
+
`- Triggered by: ${stringField4(context, "triggeredBy") ?? "unknown"}`,
|
|
10328
|
+
`- Mode: ${stringField4(context, "dispatchMode") ?? "unknown"}`,
|
|
10830
10329
|
`- GitHub actor: ${githubActor ? `${githubActor}${githubActorRole ? ` (${githubActorRole})` : ""}` : "none"}`,
|
|
10831
|
-
`- Decided by: ${
|
|
10832
|
-
`- Dispatched by: ${
|
|
10330
|
+
`- Decided by: ${stringField4(context, "decidedBy") ?? "unknown"}`,
|
|
10331
|
+
`- Dispatched by: ${stringField4(context, "dispatchedBy") ?? "unknown"}`,
|
|
10833
10332
|
`- Target: ${target ?? "none"}`
|
|
10834
10333
|
];
|
|
10835
10334
|
}
|
|
10836
10335
|
function dispatchTargetLabel(target) {
|
|
10837
|
-
const type =
|
|
10838
|
-
const id =
|
|
10336
|
+
const type = stringField4(target, "type");
|
|
10337
|
+
const id = stringField4(target, "id");
|
|
10839
10338
|
if (type && id) return `${type} ${id}`;
|
|
10840
10339
|
return id ?? type;
|
|
10841
10340
|
}
|
|
@@ -10858,27 +10357,27 @@ function listOrNone(values) {
|
|
|
10858
10357
|
function uniqueStrings2(values) {
|
|
10859
10358
|
return [...new Set(values)].sort();
|
|
10860
10359
|
}
|
|
10861
|
-
function
|
|
10862
|
-
const value =
|
|
10360
|
+
function stringField4(record, key) {
|
|
10361
|
+
const value = record?.[key];
|
|
10863
10362
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
10864
10363
|
}
|
|
10865
|
-
function
|
|
10866
|
-
const value =
|
|
10364
|
+
function recordField4(record, key) {
|
|
10365
|
+
const value = record?.[key];
|
|
10867
10366
|
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : void 0;
|
|
10868
10367
|
}
|
|
10869
|
-
function stringArrayField(
|
|
10870
|
-
const value =
|
|
10368
|
+
function stringArrayField(record, key) {
|
|
10369
|
+
const value = record?.[key];
|
|
10871
10370
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
10872
10371
|
}
|
|
10873
|
-
function artifactArrayField(
|
|
10874
|
-
const value =
|
|
10372
|
+
function artifactArrayField(record, key) {
|
|
10373
|
+
const value = record?.[key];
|
|
10875
10374
|
if (!Array.isArray(value)) return [];
|
|
10876
10375
|
return value.filter(isArtifact);
|
|
10877
10376
|
}
|
|
10878
10377
|
function isArtifact(value) {
|
|
10879
10378
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
10880
|
-
const
|
|
10881
|
-
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");
|
|
10882
10381
|
}
|
|
10883
10382
|
function uniqueArtifacts2(artifacts) {
|
|
10884
10383
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10895,7 +10394,7 @@ ${artifact.path ?? ""}`;
|
|
|
10895
10394
|
}
|
|
10896
10395
|
function nextStepFromEvent(state, goalAfter, capabilityOutput, latestEvent) {
|
|
10897
10396
|
if (state.state === "done") return "done";
|
|
10898
|
-
const decisionKind =
|
|
10397
|
+
const decisionKind = stringField4(recordField4(latestEvent, "decision"), "kind") ?? stringField4(latestEvent, "status");
|
|
10899
10398
|
if (decisionKind === "done") return "done";
|
|
10900
10399
|
if (decisionKind === "dispatch") return "dispatch";
|
|
10901
10400
|
if (decisionKind === "blocked" || decisionKind === "reject-evidence") return "block";
|
|
@@ -11149,8 +10648,8 @@ function nextStepFromEvidence2(goalAfter, capabilityOutput) {
|
|
|
11149
10648
|
if (missingEvidence.length > 0 && status !== "noop") return "dispatch";
|
|
11150
10649
|
return "wait";
|
|
11151
10650
|
}
|
|
11152
|
-
function stringArrayField2(
|
|
11153
|
-
const value =
|
|
10651
|
+
function stringArrayField2(record, key) {
|
|
10652
|
+
const value = record?.[key];
|
|
11154
10653
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
11155
10654
|
}
|
|
11156
10655
|
function describeMessage(goalId, evidenceItems) {
|
|
@@ -12552,7 +12051,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12552
12051
|
const content = fs33.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
12553
12052
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
12554
12053
|
if (!slugMatch) continue;
|
|
12555
|
-
const
|
|
12054
|
+
const slug = slugMatch[1];
|
|
12556
12055
|
const name = file.replace(/\.(ts|tsx)$/, "");
|
|
12557
12056
|
const fields = [];
|
|
12558
12057
|
const fieldMatches = content.matchAll(/name:\s*['"]([a-zA-Z_][a-zA-Z0-9_]*)['"]/g);
|
|
@@ -12562,7 +12061,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12562
12061
|
const hasAdmin = /components:\s*\{/.test(content) || /Field:\s*['"]/.test(content) || /Cell:\s*['"]/.test(content) || /views:\s*\{/.test(content);
|
|
12563
12062
|
out.push({
|
|
12564
12063
|
name,
|
|
12565
|
-
slug
|
|
12064
|
+
slug,
|
|
12566
12065
|
filePath: path32.relative(cwd, filePath),
|
|
12567
12066
|
fields: fields.slice(0, 20),
|
|
12568
12067
|
hasAdmin
|
|
@@ -13671,8 +13170,8 @@ function git3(args, cwd) {
|
|
|
13671
13170
|
}).trim();
|
|
13672
13171
|
}
|
|
13673
13172
|
function deriveBranchName(issueNumber, title) {
|
|
13674
|
-
const
|
|
13675
|
-
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`;
|
|
13676
13175
|
}
|
|
13677
13176
|
function getCurrentBranch(cwd) {
|
|
13678
13177
|
return git3(["branch", "--show-current"], cwd);
|
|
@@ -14366,7 +13865,7 @@ function stripDirective(body) {
|
|
|
14366
13865
|
}
|
|
14367
13866
|
return lines.slice(start).join("\n").trim();
|
|
14368
13867
|
}
|
|
14369
|
-
function parseAgentFile(raw,
|
|
13868
|
+
function parseAgentFile(raw, slug) {
|
|
14370
13869
|
const stripped = stripLeadingFrontmatter(raw);
|
|
14371
13870
|
const trimmed = stripped.trim();
|
|
14372
13871
|
const firstLine2 = trimmed.split("\n", 1)[0] ?? "";
|
|
@@ -14375,14 +13874,14 @@ function parseAgentFile(raw, slug2) {
|
|
|
14375
13874
|
const rest = trimmed.slice(firstLine2.length).replace(/^\n+/, "");
|
|
14376
13875
|
return { title: h1[1].trim(), body: rest };
|
|
14377
13876
|
}
|
|
14378
|
-
return { title: humanizeSlug2(
|
|
13877
|
+
return { title: humanizeSlug2(slug), body: trimmed };
|
|
14379
13878
|
}
|
|
14380
13879
|
function stripLeadingFrontmatter(raw) {
|
|
14381
13880
|
const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/.exec(raw);
|
|
14382
13881
|
return match ? raw.slice(match[0].length) : raw;
|
|
14383
13882
|
}
|
|
14384
|
-
function humanizeSlug2(
|
|
14385
|
-
return
|
|
13883
|
+
function humanizeSlug2(slug) {
|
|
13884
|
+
return slug.split(/[-_]+/).filter((s) => s.length > 0).map((s) => s[0].toUpperCase() + s.slice(1)).join(" ");
|
|
14386
13885
|
}
|
|
14387
13886
|
var loadAgentAdhoc;
|
|
14388
13887
|
var init_loadAgentAdhoc = __esm({
|
|
@@ -14425,14 +13924,14 @@ var init_loadCapabilityState = __esm({
|
|
|
14425
13924
|
CAPABILITY_TOOL_PALETTE = new Set(CAPABILITY_MCP_TOOL_NAMES);
|
|
14426
13925
|
loadCapabilityState = async (ctx, profile, args) => {
|
|
14427
13926
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
14428
|
-
const
|
|
13927
|
+
const slug = profile.name;
|
|
14429
13928
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
14430
13929
|
if (backend.hydrate) await backend.hydrate();
|
|
14431
|
-
const loaded = await backend.load(
|
|
14432
|
-
ctx.data.jobSlug =
|
|
13930
|
+
const loaded = await backend.load(slug);
|
|
13931
|
+
ctx.data.jobSlug = slug;
|
|
14433
13932
|
ctx.data.jobState = loaded;
|
|
14434
13933
|
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
14435
|
-
ctx.data.capabilitySlug =
|
|
13934
|
+
ctx.data.capabilitySlug = slug;
|
|
14436
13935
|
ctx.data.capabilityTitle = profile.describe;
|
|
14437
13936
|
ctx.data.implementationSlug = profile.implementation ?? profile.name;
|
|
14438
13937
|
ctx.data.agentSlug = profile.agent ?? "";
|
|
@@ -14445,7 +13944,7 @@ var init_loadCapabilityState = __esm({
|
|
|
14445
13944
|
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE.has(name));
|
|
14446
13945
|
if (unknown.length > 0) {
|
|
14447
13946
|
throw new Error(
|
|
14448
|
-
`loadCapabilityState: capability '${
|
|
13947
|
+
`loadCapabilityState: capability '${slug}' declared capabilityTools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
14449
13948
|
);
|
|
14450
13949
|
}
|
|
14451
13950
|
const mode = profile.capabilityToolMode ?? "lock";
|
|
@@ -14465,6 +13964,141 @@ var init_loadCapabilityState = __esm({
|
|
|
14465
13964
|
}
|
|
14466
13965
|
});
|
|
14467
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
|
+
|
|
14468
14102
|
// src/scripts/loadCompanyIntents.ts
|
|
14469
14103
|
var loadCompanyIntents;
|
|
14470
14104
|
var init_loadCompanyIntents = __esm({
|
|
@@ -14473,11 +14107,11 @@ var init_loadCompanyIntents = __esm({
|
|
|
14473
14107
|
init_companyIntent();
|
|
14474
14108
|
loadCompanyIntents = async (ctx) => {
|
|
14475
14109
|
const intents = listCompanyIntents(ctx.config, ctx.cwd);
|
|
14476
|
-
const active = intents.filter((
|
|
14110
|
+
const active = intents.filter((record) => record.intent.status === "active");
|
|
14477
14111
|
ctx.data.companyIntents = intents;
|
|
14478
14112
|
ctx.data.companyActiveIntents = active;
|
|
14479
14113
|
ctx.data.companyIntentsJson = JSON.stringify(
|
|
14480
|
-
active.map((
|
|
14114
|
+
active.map((record) => record.intent),
|
|
14481
14115
|
null,
|
|
14482
14116
|
2
|
|
14483
14117
|
);
|
|
@@ -14645,7 +14279,7 @@ var init_loadIssueStateComment = __esm({
|
|
|
14645
14279
|
// src/scripts/loadJobFromFile.ts
|
|
14646
14280
|
import * as fs37 from "fs";
|
|
14647
14281
|
import * as path35 from "path";
|
|
14648
|
-
function parseJobFile(raw,
|
|
14282
|
+
function parseJobFile(raw, slug) {
|
|
14649
14283
|
let stripped = raw;
|
|
14650
14284
|
if (stripped.startsWith("---\n")) {
|
|
14651
14285
|
const end = stripped.indexOf("\n---\n", 4);
|
|
@@ -14660,10 +14294,10 @@ function parseJobFile(raw, slug2) {
|
|
|
14660
14294
|
const rest = trimmed.slice(firstLine2.length).replace(/^\n+/, "");
|
|
14661
14295
|
return { title: h1[1].trim(), body: rest };
|
|
14662
14296
|
}
|
|
14663
|
-
return { title: humanizeSlug3(
|
|
14297
|
+
return { title: humanizeSlug3(slug), body: trimmed };
|
|
14664
14298
|
}
|
|
14665
|
-
function humanizeSlug3(
|
|
14666
|
-
return
|
|
14299
|
+
function humanizeSlug3(slug) {
|
|
14300
|
+
return slug.split(/[-_]+/).filter((s) => s.length > 0).map((s) => s[0].toUpperCase() + s.slice(1)).join(" ");
|
|
14667
14301
|
}
|
|
14668
14302
|
var CAPABILITY_TOOL_PALETTE2, loadJobFromFile;
|
|
14669
14303
|
var init_loadJobFromFile = __esm({
|
|
@@ -14678,13 +14312,13 @@ var init_loadJobFromFile = __esm({
|
|
|
14678
14312
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
14679
14313
|
const agentsDir = String(args?.agentsDir ?? ".kody/agents");
|
|
14680
14314
|
const slugArg = String(args?.slugArg ?? "job");
|
|
14681
|
-
const
|
|
14682
|
-
if (!
|
|
14315
|
+
const slug = String(ctx.args[slugArg] ?? "").trim();
|
|
14316
|
+
if (!slug) {
|
|
14683
14317
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
14684
14318
|
}
|
|
14685
|
-
const capability = resolveCapabilityFolder(
|
|
14319
|
+
const capability = resolveCapabilityFolder(slug, path35.join(ctx.cwd, jobsDir));
|
|
14686
14320
|
if (!capability) {
|
|
14687
|
-
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)}`);
|
|
14688
14322
|
}
|
|
14689
14323
|
const { title, body, config } = capability;
|
|
14690
14324
|
const mentions = (config.mentions ?? []).map((login) => `@${login}`).join(" ");
|
|
@@ -14695,7 +14329,7 @@ var init_loadJobFromFile = __esm({
|
|
|
14695
14329
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14696
14330
|
if (!fs37.existsSync(agentPath)) {
|
|
14697
14331
|
throw new Error(
|
|
14698
|
-
`loadJobFromFile: capability '${
|
|
14332
|
+
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
14699
14333
|
);
|
|
14700
14334
|
}
|
|
14701
14335
|
const agentRaw = fs37.readFileSync(agentPath, "utf-8");
|
|
@@ -14704,17 +14338,17 @@ var init_loadJobFromFile = __esm({
|
|
|
14704
14338
|
agentIdentity = parsed.body;
|
|
14705
14339
|
}
|
|
14706
14340
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
14707
|
-
const loaded = await backend.load(
|
|
14708
|
-
ctx.data.jobSlug =
|
|
14341
|
+
const loaded = await backend.load(slug);
|
|
14342
|
+
ctx.data.jobSlug = slug;
|
|
14709
14343
|
ctx.data.jobTitle = title;
|
|
14710
|
-
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);
|
|
14711
14345
|
ctx.data.jobState = loaded;
|
|
14712
14346
|
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
14713
14347
|
ctx.data.agentSlug = agentSlug;
|
|
14714
14348
|
ctx.data.agentTitle = agentTitle;
|
|
14715
14349
|
ctx.data.agentIdentity = agentIdentity;
|
|
14716
14350
|
ctx.data.mentions = mentions;
|
|
14717
|
-
ctx.data.capabilitySlug =
|
|
14351
|
+
ctx.data.capabilitySlug = slug;
|
|
14718
14352
|
ctx.data.capabilityTitle = title;
|
|
14719
14353
|
ctx.data.agentSlug = agentSlug;
|
|
14720
14354
|
ctx.data.agentTitle = agentTitle;
|
|
@@ -14725,7 +14359,7 @@ var init_loadJobFromFile = __esm({
|
|
|
14725
14359
|
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE2.has(name));
|
|
14726
14360
|
if (unknown.length > 0) {
|
|
14727
14361
|
throw new Error(
|
|
14728
|
-
`loadJobFromFile: capability '${
|
|
14362
|
+
`loadJobFromFile: capability '${slug}' declared tools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
14729
14363
|
);
|
|
14730
14364
|
}
|
|
14731
14365
|
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
@@ -15679,8 +15313,8 @@ function parseAgentFactoryBundle(raw) {
|
|
|
15679
15313
|
};
|
|
15680
15314
|
}
|
|
15681
15315
|
function buildStatePrBranchName(sourceLabel, issueNumber, title, now = Date.now()) {
|
|
15682
|
-
const
|
|
15683
|
-
const suffix =
|
|
15316
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48).replace(/-+$/g, "");
|
|
15317
|
+
const suffix = slug ? `-${slug}` : "";
|
|
15684
15318
|
return `${sourceLabel}/issue-${issueNumber}-${now.toString(36)}${suffix}`;
|
|
15685
15319
|
}
|
|
15686
15320
|
function normalizeBundleFiles(ctx, bundle) {
|
|
@@ -16009,41 +15643,8 @@ QA_REPORT_POSTED=${created.url} (verdict: ${verdict})
|
|
|
16009
15643
|
}
|
|
16010
15644
|
});
|
|
16011
15645
|
|
|
16012
|
-
// src/scripts/parseAgencyArchitectDecision.ts
|
|
16013
|
-
function makeAction2(type, payload) {
|
|
16014
|
-
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16015
|
-
}
|
|
16016
|
-
var parseAgencyArchitectDecision;
|
|
16017
|
-
var init_parseAgencyArchitectDecision = __esm({
|
|
16018
|
-
"src/scripts/parseAgencyArchitectDecision.ts"() {
|
|
16019
|
-
"use strict";
|
|
16020
|
-
init_agencyArchitectDecision();
|
|
16021
|
-
parseAgencyArchitectDecision = async (ctx, _profile, agentResult) => {
|
|
16022
|
-
if (!agentResult) {
|
|
16023
|
-
ctx.data.agencyArchitectDecision = { summary: "", actions: [] };
|
|
16024
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_NOT_RUN", { reason: "no agent result" });
|
|
16025
|
-
return;
|
|
16026
|
-
}
|
|
16027
|
-
try {
|
|
16028
|
-
const decision = parseAgencyArchitectDecisionText(agentResult.finalText);
|
|
16029
|
-
ctx.data.agencyArchitectDecision = decision;
|
|
16030
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_DECIDED", {
|
|
16031
|
-
summary: decision.summary,
|
|
16032
|
-
actionCount: decision.actions.length
|
|
16033
|
-
});
|
|
16034
|
-
} catch (err) {
|
|
16035
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
16036
|
-
ctx.data.agencyArchitectDecisionError = reason;
|
|
16037
|
-
ctx.data.action = makeAction2("AGENCY_ARCHITECT_FAILED", { reason });
|
|
16038
|
-
ctx.output.exitCode = 1;
|
|
16039
|
-
ctx.output.reason = reason;
|
|
16040
|
-
}
|
|
16041
|
-
};
|
|
16042
|
-
}
|
|
16043
|
-
});
|
|
16044
|
-
|
|
16045
15646
|
// src/scripts/parseAgentResult.ts
|
|
16046
|
-
function
|
|
15647
|
+
function makeAction2(type, payload) {
|
|
16047
15648
|
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16048
15649
|
}
|
|
16049
15650
|
var parseAgentResult2;
|
|
@@ -16054,7 +15655,7 @@ var init_parseAgentResult = __esm({
|
|
|
16054
15655
|
parseAgentResult2 = async (ctx, profile, agentResult) => {
|
|
16055
15656
|
if (!agentResult) {
|
|
16056
15657
|
ctx.data.agentDone = false;
|
|
16057
|
-
ctx.data.action =
|
|
15658
|
+
ctx.data.action = makeAction2("AGENT_NOT_RUN", { reason: "no agent result" });
|
|
16058
15659
|
return;
|
|
16059
15660
|
}
|
|
16060
15661
|
const parsed = parseAgentResult(agentResult.finalText);
|
|
@@ -16071,13 +15672,13 @@ var init_parseAgentResult = __esm({
|
|
|
16071
15672
|
ctx.data.agentError = agentResult.error;
|
|
16072
15673
|
const modeSeg = (ctx.args.mode ?? profile.name).replace(/-/g, "_").toUpperCase();
|
|
16073
15674
|
if (parsed.done) {
|
|
16074
|
-
ctx.data.action =
|
|
15675
|
+
ctx.data.action = makeAction2(`${modeSeg}_COMPLETED`, {
|
|
16075
15676
|
commitMessage: parsed.commitMessage
|
|
16076
15677
|
});
|
|
16077
15678
|
} else {
|
|
16078
15679
|
const isGenericNoOutput = parsed.failureReason === "agent produced no final message";
|
|
16079
15680
|
const reason = isGenericNoOutput && agentResult.error ? `agent SDK error: ${agentResult.error}` : parsed.failureReason || agentResult.error || "unknown failure";
|
|
16080
|
-
ctx.data.action =
|
|
15681
|
+
ctx.data.action = makeAction2(`${modeSeg}_FAILED`, { reason });
|
|
16081
15682
|
}
|
|
16082
15683
|
};
|
|
16083
15684
|
}
|
|
@@ -16848,7 +16449,7 @@ function tryAuditComment(issueNumber, body, cwd) {
|
|
|
16848
16449
|
} catch {
|
|
16849
16450
|
}
|
|
16850
16451
|
}
|
|
16851
|
-
function
|
|
16452
|
+
function makeAction3(type, payload) {
|
|
16852
16453
|
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16853
16454
|
}
|
|
16854
16455
|
function failedAction4(reason) {
|
|
@@ -16885,7 +16486,7 @@ var init_recordClassification = __esm({
|
|
|
16885
16486
|
ctx.output.reason = "classify: no decision";
|
|
16886
16487
|
return;
|
|
16887
16488
|
}
|
|
16888
|
-
ctx.data.action =
|
|
16489
|
+
ctx.data.action = makeAction3(`CLASSIFIED_AS_${classification.toUpperCase()}`, {
|
|
16889
16490
|
classification,
|
|
16890
16491
|
reason: reason ?? "",
|
|
16891
16492
|
source: ctx.data.classificationSource ?? "agent"
|
|
@@ -18217,16 +17818,16 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18217
17818
|
const slugArg = String(args?.slugArg ?? "capability");
|
|
18218
17819
|
const fenceLabel = String(args?.fenceLabel ?? "kody-job-next-state");
|
|
18219
17820
|
const shell = String(args?.shell ?? "tick.sh");
|
|
18220
|
-
const
|
|
18221
|
-
if (!
|
|
17821
|
+
const slug = String(args?.slug ?? ctx.args[slugArg] ?? ctx.args.capability ?? "").trim();
|
|
17822
|
+
if (!slug) {
|
|
18222
17823
|
ctx.output.exitCode = 99;
|
|
18223
17824
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
18224
17825
|
return;
|
|
18225
17826
|
}
|
|
18226
|
-
const capability = resolveCapabilityFolder(
|
|
17827
|
+
const capability = resolveCapabilityFolder(slug, path41.join(ctx.cwd, jobsDir));
|
|
18227
17828
|
if (!capability) {
|
|
18228
17829
|
ctx.output.exitCode = 99;
|
|
18229
|
-
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)`;
|
|
18230
17831
|
return;
|
|
18231
17832
|
}
|
|
18232
17833
|
const shellPath = path41.join(profile.dir, shell);
|
|
@@ -18238,14 +17839,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18238
17839
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
18239
17840
|
let loaded;
|
|
18240
17841
|
try {
|
|
18241
|
-
loaded = await backend.load(
|
|
17842
|
+
loaded = await backend.load(slug);
|
|
18242
17843
|
} catch (err) {
|
|
18243
17844
|
ctx.output.exitCode = 99;
|
|
18244
17845
|
ctx.output.reason = `runScheduledImplementationTick: state load failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
18245
17846
|
return;
|
|
18246
17847
|
}
|
|
18247
|
-
ctx.data.jobSlug =
|
|
18248
|
-
ctx.data.capabilitySlug =
|
|
17848
|
+
ctx.data.jobSlug = slug;
|
|
17849
|
+
ctx.data.capabilitySlug = slug;
|
|
18249
17850
|
ctx.data.implementationSlug = profile.name;
|
|
18250
17851
|
ctx.data.jobState = loaded;
|
|
18251
17852
|
runTickShellAndParse({
|
|
@@ -18275,22 +17876,22 @@ var init_runTickScript = __esm({
|
|
|
18275
17876
|
const jobsDir = String(args?.jobsDir ?? ".kody/capabilities");
|
|
18276
17877
|
const slugArg = String(args?.slugArg ?? "job");
|
|
18277
17878
|
const fenceLabel = String(args?.fenceLabel ?? "kody-job-next-state");
|
|
18278
|
-
const
|
|
18279
|
-
if (!
|
|
17879
|
+
const slug = String(ctx.args[slugArg] ?? "").trim();
|
|
17880
|
+
if (!slug) {
|
|
18280
17881
|
ctx.output.exitCode = 99;
|
|
18281
17882
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
18282
17883
|
return;
|
|
18283
17884
|
}
|
|
18284
|
-
const capability = readCapabilityFolder(path42.join(ctx.cwd, jobsDir),
|
|
17885
|
+
const capability = readCapabilityFolder(path42.join(ctx.cwd, jobsDir), slug);
|
|
18285
17886
|
if (!capability) {
|
|
18286
17887
|
ctx.output.exitCode = 99;
|
|
18287
|
-
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)}`;
|
|
18288
17889
|
return;
|
|
18289
17890
|
}
|
|
18290
17891
|
const tickScript = capability.config.tickScript;
|
|
18291
17892
|
if (!tickScript) {
|
|
18292
17893
|
ctx.output.exitCode = 99;
|
|
18293
|
-
ctx.output.reason = `runTickScript: capability ${
|
|
17894
|
+
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
18294
17895
|
return;
|
|
18295
17896
|
}
|
|
18296
17897
|
const scriptPath = path42.isAbsolute(tickScript) ? tickScript : path42.join(ctx.cwd, tickScript);
|
|
@@ -18302,13 +17903,13 @@ var init_runTickScript = __esm({
|
|
|
18302
17903
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
18303
17904
|
let loaded;
|
|
18304
17905
|
try {
|
|
18305
|
-
loaded = await backend.load(
|
|
17906
|
+
loaded = await backend.load(slug);
|
|
18306
17907
|
} catch (err) {
|
|
18307
17908
|
ctx.output.exitCode = 99;
|
|
18308
17909
|
ctx.output.reason = `runTickScript: state load failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
18309
17910
|
return;
|
|
18310
17911
|
}
|
|
18311
|
-
ctx.data.jobSlug =
|
|
17912
|
+
ctx.data.jobSlug = slug;
|
|
18312
17913
|
ctx.data.jobState = loaded;
|
|
18313
17914
|
runTickShellAndParse({
|
|
18314
17915
|
ctx,
|
|
@@ -18580,7 +18181,7 @@ function validateModelBundle(bundle, producer) {
|
|
|
18580
18181
|
const failures = [];
|
|
18581
18182
|
const expectedKind = CREATOR_KIND[producer];
|
|
18582
18183
|
if (producer === FACTORY_PRODUCER) {
|
|
18583
|
-
const contracts =
|
|
18184
|
+
const contracts = stringArray4(bundle.modelCreatorContractsUsed);
|
|
18584
18185
|
for (const contract of CREATOR_CONTRACTS) {
|
|
18585
18186
|
if (!contracts.includes(contract)) failures.push(`modelCreatorContractsUsed missing ${contract}`);
|
|
18586
18187
|
}
|
|
@@ -18607,36 +18208,36 @@ function validateOneModel(rawModel, files, label, strictSingleModel, failures, e
|
|
|
18607
18208
|
if (!isModelKind(kind)) failures.push(`${label}.kind must be agent, capability, goal, agentLoop, or workflow`);
|
|
18608
18209
|
if (expectedKind && kind !== expectedKind && producer)
|
|
18609
18210
|
failures.push(`${producer} must output model.kind ${expectedKind}`);
|
|
18610
|
-
const
|
|
18611
|
-
if (!
|
|
18211
|
+
const slug = stringField6(model.slug);
|
|
18212
|
+
if (!isSlug(slug)) failures.push(`${label}.slug must be a lowercase slug`);
|
|
18612
18213
|
if (isModelKind(kind)) {
|
|
18613
|
-
const docsUsed =
|
|
18214
|
+
const docsUsed = stringArray4(model.docsUsed);
|
|
18614
18215
|
for (const doc of REQUIRED_DOCS[kind]) {
|
|
18615
18216
|
if (!docsUsed.includes(doc)) failures.push(`${label} docsUsed missing ${doc}`);
|
|
18616
18217
|
}
|
|
18617
|
-
validateFilesForKind(kind,
|
|
18618
|
-
validateModelShape(kind, model, files,
|
|
18218
|
+
validateFilesForKind(kind, slug, files, strictSingleModel, failures);
|
|
18219
|
+
validateModelShape(kind, model, files, slug, failures);
|
|
18619
18220
|
}
|
|
18620
18221
|
}
|
|
18621
|
-
function validateFilesForKind(kind,
|
|
18222
|
+
function validateFilesForKind(kind, slug, files, strictSingleModel, failures) {
|
|
18622
18223
|
const paths = files.map((file) => normalizeBundlePath(file.path));
|
|
18623
18224
|
if (paths.some((filePath) => filePath === "implementations" || filePath.startsWith("implementations/"))) {
|
|
18624
18225
|
failures.push("files must not use obsolete implementation storage");
|
|
18625
18226
|
}
|
|
18626
18227
|
if (kind === "agent") {
|
|
18627
|
-
requirePath(paths, `agents/${
|
|
18228
|
+
requirePath(paths, `agents/${slug}.md`, "agent file", failures);
|
|
18628
18229
|
if (strictSingleModel) rejectOtherRoots(paths, ["agents/"], "agent", failures);
|
|
18629
18230
|
}
|
|
18630
18231
|
if (kind === "capability") {
|
|
18631
|
-
requirePath(paths, `capabilities/${
|
|
18632
|
-
requirePath(paths, `capabilities/${
|
|
18633
|
-
if (strictSingleModel) rejectOtherRoots(paths, [`capabilities/${
|
|
18634
|
-
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);
|
|
18635
18236
|
if (profile) {
|
|
18636
18237
|
const profileSlug = stringField6(profile.slug);
|
|
18637
18238
|
const profileName = stringField6(profile.name);
|
|
18638
|
-
if (profileSlug && profileSlug !==
|
|
18639
|
-
if (!profileSlug && profileName && profileName !==
|
|
18239
|
+
if (profileSlug && profileSlug !== slug) failures.push("capability profile slug must match model.slug");
|
|
18240
|
+
if (!profileSlug && profileName && profileName !== slug) {
|
|
18640
18241
|
failures.push("capability profile name must match model.slug when slug is absent");
|
|
18641
18242
|
}
|
|
18642
18243
|
if (profile.agent !== void 0)
|
|
@@ -18647,8 +18248,8 @@ function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
|
|
|
18647
18248
|
}
|
|
18648
18249
|
}
|
|
18649
18250
|
if (kind === "goal") {
|
|
18650
|
-
requirePath(paths, `goals/templates/${
|
|
18651
|
-
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);
|
|
18652
18253
|
}
|
|
18653
18254
|
if (kind === "agentLoop") {
|
|
18654
18255
|
if (!paths.some((filePath) => filePath.endsWith("/state.json")))
|
|
@@ -18656,8 +18257,8 @@ function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
|
|
|
18656
18257
|
if (strictSingleModel) rejectOtherRoots(paths, ["goals/", "loops/", "capabilities/"], "agentLoop", failures);
|
|
18657
18258
|
}
|
|
18658
18259
|
if (kind === "workflow") {
|
|
18659
|
-
requirePath(paths, `capabilities/${
|
|
18660
|
-
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);
|
|
18661
18262
|
if (profile) {
|
|
18662
18263
|
if (profile.capabilityKind !== void 0) {
|
|
18663
18264
|
failures.push("workflow profile must not declare capabilityKind");
|
|
@@ -18676,8 +18277,8 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18676
18277
|
if (!model || typeof model !== "object" || Array.isArray(model)) continue;
|
|
18677
18278
|
const input = model;
|
|
18678
18279
|
const kind = stringField6(input.kind);
|
|
18679
|
-
const
|
|
18680
|
-
if (isModelKind(kind) &&
|
|
18280
|
+
const slug = stringField6(input.slug);
|
|
18281
|
+
if (isModelKind(kind) && isSlug(slug)) available.set(`${kind}:${slug}`, kind);
|
|
18681
18282
|
}
|
|
18682
18283
|
for (const model of models) {
|
|
18683
18284
|
if (!model || typeof model !== "object" || Array.isArray(model)) continue;
|
|
@@ -18691,7 +18292,7 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18691
18292
|
}
|
|
18692
18293
|
}
|
|
18693
18294
|
if (kind === "workflow") {
|
|
18694
|
-
for (const capability of
|
|
18295
|
+
for (const capability of stringArray4(input.steps)) {
|
|
18695
18296
|
if (!available.has(`capability:${capability}`)) {
|
|
18696
18297
|
failures.push(`workflow ${stringField6(input.slug)} references missing capability ${capability}`);
|
|
18697
18298
|
}
|
|
@@ -18721,10 +18322,10 @@ function validateFactoryAssembly(models, failures) {
|
|
|
18721
18322
|
}
|
|
18722
18323
|
}
|
|
18723
18324
|
}
|
|
18724
|
-
function validateModelShape(kind, model, files,
|
|
18325
|
+
function validateModelShape(kind, model, files, slug, failures) {
|
|
18725
18326
|
if (kind === "agent") {
|
|
18726
|
-
const agentFile = textFile(files, `agents/${
|
|
18727
|
-
if (!
|
|
18327
|
+
const agentFile = textFile(files, `agents/${slug}.md`);
|
|
18328
|
+
if (!stringArray4(model.owns).includes("identity") && !containsWord(agentFile, "identity")) {
|
|
18728
18329
|
failures.push("agent owns must include identity");
|
|
18729
18330
|
}
|
|
18730
18331
|
requireStringArrayIncludes(model.doesNotOwn, "tasks", "agent doesNotOwn", failures);
|
|
@@ -18741,7 +18342,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18741
18342
|
requireStringArrayIncludes(model.doesNotOwn, "goal progress", "capability doesNotOwn", failures);
|
|
18742
18343
|
}
|
|
18743
18344
|
if (kind === "goal") {
|
|
18744
|
-
const goalState = parseJsonContent(textFile(files, `goals/templates/${
|
|
18345
|
+
const goalState = parseJsonContent(textFile(files, `goals/templates/${slug}/state.json`));
|
|
18745
18346
|
if (!stringField6(model.outcome) && !stringField6(goalState?.outcome))
|
|
18746
18347
|
failures.push("goal model must declare outcome");
|
|
18747
18348
|
if (evidenceRefs(model).length === 0 && evidenceRefs(goalState).length === 0) {
|
|
@@ -18753,7 +18354,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18753
18354
|
}
|
|
18754
18355
|
if (kind === "agentLoop") {
|
|
18755
18356
|
if (!stringField6(model.cadence)) failures.push("agentLoop model must declare cadence");
|
|
18756
|
-
const loopState = parseJsonContent(firstStateFile(files,
|
|
18357
|
+
const loopState = parseJsonContent(firstStateFile(files, slug));
|
|
18757
18358
|
const hasTarget = Boolean(wakeTarget(model)) || Boolean(stringField6(model.target)) || Boolean(wakeTarget(loopState)) || Boolean(stringField6(loopState?.target)) || Boolean(loopTargetString(loopState));
|
|
18758
18359
|
if (!hasTarget) {
|
|
18759
18360
|
failures.push("agentLoop model must declare wakeTarget object");
|
|
@@ -18767,7 +18368,7 @@ function validateModelShape(kind, model, files, slug2, failures) {
|
|
|
18767
18368
|
}
|
|
18768
18369
|
}
|
|
18769
18370
|
function capabilityRefs(value) {
|
|
18770
|
-
return [...
|
|
18371
|
+
return [...stringArray4(value?.capabilities), ...stringArray4(value?.allowedCapabilities)];
|
|
18771
18372
|
}
|
|
18772
18373
|
function evidenceRefs(value) {
|
|
18773
18374
|
if (!value) return [];
|
|
@@ -18780,8 +18381,8 @@ function wakeTarget(value) {
|
|
|
18780
18381
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
18781
18382
|
const target = raw;
|
|
18782
18383
|
const type = stringField6(target.type);
|
|
18783
|
-
const
|
|
18784
|
-
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 };
|
|
18785
18386
|
return null;
|
|
18786
18387
|
}
|
|
18787
18388
|
function loopTargetString(value) {
|
|
@@ -18792,8 +18393,8 @@ function loopTargetString(value) {
|
|
|
18792
18393
|
function textFile(files, wantedPath) {
|
|
18793
18394
|
return files.find((item) => normalizeBundlePath(item.path) === wantedPath)?.content ?? "";
|
|
18794
18395
|
}
|
|
18795
|
-
function firstStateFile(files,
|
|
18796
|
-
const normalizedSlug = `${
|
|
18396
|
+
function firstStateFile(files, slug) {
|
|
18397
|
+
const normalizedSlug = `${slug}/state.json`;
|
|
18797
18398
|
return files.find((item) => normalizeBundlePath(item.path).endsWith(normalizedSlug))?.content ?? "";
|
|
18798
18399
|
}
|
|
18799
18400
|
function parseJsonContent(content) {
|
|
@@ -18839,7 +18440,7 @@ function normalizeBundlePath(filePath) {
|
|
|
18839
18440
|
function stringField6(value) {
|
|
18840
18441
|
return typeof value === "string" ? value.trim() : "";
|
|
18841
18442
|
}
|
|
18842
|
-
function
|
|
18443
|
+
function stringArray4(value) {
|
|
18843
18444
|
if (!Array.isArray(value)) return [];
|
|
18844
18445
|
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
18845
18446
|
}
|
|
@@ -18850,9 +18451,9 @@ function arrayObjects(value) {
|
|
|
18850
18451
|
);
|
|
18851
18452
|
}
|
|
18852
18453
|
function requireStringArrayIncludes(value, expected, label, failures) {
|
|
18853
|
-
if (!
|
|
18454
|
+
if (!stringArray4(value).includes(expected)) failures.push(`${label} must include ${expected}`);
|
|
18854
18455
|
}
|
|
18855
|
-
function
|
|
18456
|
+
function isSlug(value) {
|
|
18856
18457
|
return /^[a-z][a-z0-9-]{0,63}$/.test(value);
|
|
18857
18458
|
}
|
|
18858
18459
|
function isModelKind(value) {
|
|
@@ -19585,8 +19186,6 @@ var init_scripts = __esm({
|
|
|
19585
19186
|
init_advanceFlow();
|
|
19586
19187
|
init_advanceManagedGoal();
|
|
19587
19188
|
init_appendCompanyActivity();
|
|
19588
|
-
init_appendCompanyIntentDecision();
|
|
19589
|
-
init_applyAgencyArchitectDecision();
|
|
19590
19189
|
init_applyCapabilityReports();
|
|
19591
19190
|
init_buildSyntheticPlugin();
|
|
19592
19191
|
init_checkCoverageWithRetry();
|
|
@@ -19634,7 +19233,6 @@ var init_scripts = __esm({
|
|
|
19634
19233
|
init_notifyTerminal();
|
|
19635
19234
|
init_openAgentFactoryStatePr();
|
|
19636
19235
|
init_openQaIssue();
|
|
19637
|
-
init_parseAgencyArchitectDecision();
|
|
19638
19236
|
init_parseAgentResult();
|
|
19639
19237
|
init_parseIssueStateFromAgentResult();
|
|
19640
19238
|
init_parseJobStateFromAgentResult();
|
|
@@ -19732,7 +19330,6 @@ var init_scripts = __esm({
|
|
|
19732
19330
|
};
|
|
19733
19331
|
postflightScripts = {
|
|
19734
19332
|
parseAgentResult: parseAgentResult2,
|
|
19735
|
-
parseAgencyArchitectDecision,
|
|
19736
19333
|
parseIssueStateFromAgentResult,
|
|
19737
19334
|
parseJobStateFromAgentResult,
|
|
19738
19335
|
parseReproOutput,
|
|
@@ -19740,8 +19337,6 @@ var init_scripts = __esm({
|
|
|
19740
19337
|
writeIssueStateComment,
|
|
19741
19338
|
writeJobStateFile,
|
|
19742
19339
|
appendCompanyActivity,
|
|
19743
|
-
appendCompanyIntentDecision: appendCompanyIntentDecision2,
|
|
19744
|
-
applyAgencyArchitectDecision,
|
|
19745
19340
|
requireFeedbackActions,
|
|
19746
19341
|
requirePlanDeviations,
|
|
19747
19342
|
verify,
|
|
@@ -19903,6 +19498,7 @@ var init_stateWorkspace = __esm({
|
|
|
19903
19498
|
];
|
|
19904
19499
|
FILE_MAPPINGS = [
|
|
19905
19500
|
{ statePath: "instructions.md", localPath: path43.join(".kody", "instructions.md") },
|
|
19501
|
+
{ statePath: "system-prompt.md", localPath: path43.join(".kody", "system-prompt.md") },
|
|
19906
19502
|
{ statePath: "variables.json", localPath: path43.join(".kody", "variables.json") },
|
|
19907
19503
|
{ statePath: "secrets.enc", localPath: path43.join(".kody", "secrets.enc") }
|
|
19908
19504
|
];
|
|
@@ -21276,14 +20872,14 @@ function filterCliArgsForStep(action, raw) {
|
|
|
21276
20872
|
function composeStepWhy(parentWhy, step) {
|
|
21277
20873
|
return [parentWhy?.trim(), step.reason ? `Workflow step: ${step.reason}` : ""].filter((part) => Boolean(part)).join("\n\n");
|
|
21278
20874
|
}
|
|
21279
|
-
function loadCapabilityContext(
|
|
21280
|
-
if (!
|
|
21281
|
-
return resolveCapabilityFolder(
|
|
20875
|
+
function loadCapabilityContext(slug, cwd) {
|
|
20876
|
+
if (!slug) return null;
|
|
20877
|
+
return resolveCapabilityFolder(slug, path45.join(cwd, ".kody", "capabilities"));
|
|
21282
20878
|
}
|
|
21283
|
-
function loadWorkflowContext(
|
|
21284
|
-
if (!
|
|
21285
|
-
const workflow = readWorkflowDefinition(base.config, base.cwd,
|
|
21286
|
-
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;
|
|
21287
20883
|
}
|
|
21288
20884
|
function mintInstantJob(dispatch2, opts) {
|
|
21289
20885
|
return {
|
|
@@ -21795,7 +21391,7 @@ async function runChatTurn(opts) {
|
|
|
21795
21391
|
return { exitCode: 64, error };
|
|
21796
21392
|
}
|
|
21797
21393
|
const { turns: promptTurns, imagePaths } = prepareAttachments(turns, opts.cwd, opts.sessionId);
|
|
21798
|
-
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);
|
|
21799
21395
|
const agentIdentityBlock = readAgentIdentityBlock(opts.cwd, opts.agentIdentity);
|
|
21800
21396
|
const catalog = buildImplementationCatalog();
|
|
21801
21397
|
const taskArtifactsPaths = prepareTaskArtifactsDir(opts.cwd, opts.sessionId);
|
|
@@ -21943,10 +21539,10 @@ async function runChatTurn(opts) {
|
|
|
21943
21539
|
return { exitCode: 0, reply };
|
|
21944
21540
|
}
|
|
21945
21541
|
function readAgentIdentityBlock(cwd, agentIdentity) {
|
|
21946
|
-
const
|
|
21947
|
-
if (!
|
|
21948
|
-
const body = agentIdentity?.body?.trim() || loadAgentIdentity(cwd,
|
|
21949
|
-
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);
|
|
21950
21546
|
}
|
|
21951
21547
|
async function runOpenAIChatTurn(args) {
|
|
21952
21548
|
const { opts, turns, systemPrompt, sessionFile } = args;
|
|
@@ -22088,6 +21684,17 @@ _\u2026 (context truncated; use the state repo context files for the full text)_
|
|
|
22088
21684
|
}
|
|
22089
21685
|
var INSTRUCTIONS_REL = ".kody/instructions.md";
|
|
22090
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
|
+
}
|
|
22091
21698
|
function readInstructionsBlock(cwd) {
|
|
22092
21699
|
const instructionsPath = path16.join(cwd, INSTRUCTIONS_REL);
|
|
22093
21700
|
let raw;
|
|
@@ -23639,11 +23246,11 @@ function agentIdentityField(body) {
|
|
|
23639
23246
|
if (typeof body !== "object" || body === null || !("agentIdentity" in body)) return void 0;
|
|
23640
23247
|
const value = body.agentIdentity;
|
|
23641
23248
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
23642
|
-
const
|
|
23643
|
-
const
|
|
23644
|
-
const bodyText = typeof
|
|
23645
|
-
if (!
|
|
23646
|
-
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 };
|
|
23647
23254
|
}
|
|
23648
23255
|
function sendJson(res, status, body) {
|
|
23649
23256
|
res.writeHead(status, { "content-type": "application/json" });
|