@kody-ade/kody-engine 0.4.521 → 0.4.523
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 +178 -39
- 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.523",
|
|
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",
|
|
@@ -13760,9 +13760,7 @@ function dueSlot(loop, now) {
|
|
|
13760
13760
|
return `${year}-${month}-${day}T${loop.trigger.at.time}[${loop.trigger.at.timezone}]`;
|
|
13761
13761
|
}
|
|
13762
13762
|
function loopJob(loop) {
|
|
13763
|
-
const cliArgs =
|
|
13764
|
-
Object.entries(loop.input).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)])
|
|
13765
|
-
);
|
|
13763
|
+
const cliArgs = { ...loop.input };
|
|
13766
13764
|
return loop.target.kind === "workflow" ? { workflow: loop.target.id, cliArgs, flavor: "scheduled" } : { capability: loop.target.id, cliArgs, flavor: "scheduled" };
|
|
13767
13765
|
}
|
|
13768
13766
|
function repositoryTenant(config) {
|
|
@@ -17884,27 +17882,171 @@ var init_promoteQaGoal = __esm({
|
|
|
17884
17882
|
|
|
17885
17883
|
// src/scripts/publishReport.ts
|
|
17886
17884
|
function buildRuntimeReportMarkdown(input) {
|
|
17887
|
-
|
|
17888
|
-
"---",
|
|
17889
|
-
`generatedAt: ${yamlString(input.generatedAt)}`,
|
|
17890
|
-
`reportType: ${input.reportType}`,
|
|
17891
|
-
`reportTypeVersion: ${input.reportTypeVersion}`,
|
|
17892
|
-
"producer:",
|
|
17893
|
-
` model: ${input.owner}`,
|
|
17894
|
-
` capability: ${input.capability}`,
|
|
17895
|
-
...input.reviewStatus ? [`reviewStatus: ${input.reviewStatus}`] : [],
|
|
17896
|
-
...input.reviewArea ? [`reviewArea: ${input.reviewArea}`] : [],
|
|
17897
|
-
"---",
|
|
17885
|
+
const lines = [
|
|
17898
17886
|
`# ${input.title}`,
|
|
17899
17887
|
"",
|
|
17900
17888
|
input.summary,
|
|
17901
17889
|
"",
|
|
17902
|
-
"##
|
|
17903
|
-
"
|
|
17904
|
-
|
|
17905
|
-
"
|
|
17906
|
-
""
|
|
17907
|
-
|
|
17890
|
+
"## About",
|
|
17891
|
+
markdownField("Type", input.reportType),
|
|
17892
|
+
markdownField("Version", input.reportTypeVersion),
|
|
17893
|
+
markdownField("Generated", input.generatedAt),
|
|
17894
|
+
markdownField("Owner", input.owner),
|
|
17895
|
+
markdownField("Capability", input.capability),
|
|
17896
|
+
...input.reviewStatus ? [markdownField("Review status", input.reviewStatus)] : [],
|
|
17897
|
+
...input.reviewArea ? [markdownField("Review area", input.reviewArea)] : [],
|
|
17898
|
+
"",
|
|
17899
|
+
...renderReportData(input.data)
|
|
17900
|
+
];
|
|
17901
|
+
return `${lines.join("\n").trimEnd()}
|
|
17902
|
+
`;
|
|
17903
|
+
}
|
|
17904
|
+
function renderReportData(data) {
|
|
17905
|
+
const lines = [];
|
|
17906
|
+
const workflow = recordField4(data.workflow);
|
|
17907
|
+
const finding = recordField4(data.finding);
|
|
17908
|
+
const observation = recordField4(data.observation);
|
|
17909
|
+
const learning = recordField4(data.learning);
|
|
17910
|
+
if (workflow) lines.push(...renderWorkflow(workflow));
|
|
17911
|
+
if (finding) lines.push(...renderFinding(finding));
|
|
17912
|
+
if (observation) lines.push(...renderObservation(observation));
|
|
17913
|
+
if (learning) lines.push(...renderLearning(learning));
|
|
17914
|
+
const rest = omitKeys(data, ["workflow", "finding", "observation", "learning"]);
|
|
17915
|
+
if (Object.keys(rest).length > 0) {
|
|
17916
|
+
lines.push("## Results", ...renderObjectFields(rest, 3), "");
|
|
17917
|
+
}
|
|
17918
|
+
return lines;
|
|
17919
|
+
}
|
|
17920
|
+
function renderWorkflow(workflow) {
|
|
17921
|
+
const lines = ["## Run"];
|
|
17922
|
+
pushField(lines, "Status", workflow.status);
|
|
17923
|
+
pushField(lines, "Blocker", workflow.blocker);
|
|
17924
|
+
const completed = stringArray3(workflow.completedStepIds);
|
|
17925
|
+
if (completed.length > 0) {
|
|
17926
|
+
lines.push("", "## Completed checks", ...completed.map((step) => `- ${humanize(step)}`));
|
|
17927
|
+
}
|
|
17928
|
+
const facts = recordField4(workflow.facts) ?? {};
|
|
17929
|
+
const finding = recordField4(facts.finding);
|
|
17930
|
+
const observation = recordField4(facts.observation);
|
|
17931
|
+
if (finding) lines.push("", ...renderFinding(finding));
|
|
17932
|
+
if (observation) lines.push("", ...renderObservation(observation));
|
|
17933
|
+
const remainingFacts = omitKeys(facts, ["finding", "observation"]);
|
|
17934
|
+
if (Object.keys(remainingFacts).length > 0) {
|
|
17935
|
+
lines.push("", "## Results", ...renderObjectFields(remainingFacts, 3));
|
|
17936
|
+
}
|
|
17937
|
+
const artifacts = Array.isArray(workflow.artifacts) ? workflow.artifacts : [];
|
|
17938
|
+
const evidence = renderEvidence(artifacts);
|
|
17939
|
+
if (evidence.length > 0) lines.push("", "## Evidence", ...evidence);
|
|
17940
|
+
lines.push("");
|
|
17941
|
+
return lines;
|
|
17942
|
+
}
|
|
17943
|
+
function renderFinding(finding) {
|
|
17944
|
+
const lines = ["## Finding"];
|
|
17945
|
+
for (const [label, key] of [
|
|
17946
|
+
["ID", "id"],
|
|
17947
|
+
["Status", "status"],
|
|
17948
|
+
["Severity", "severity"],
|
|
17949
|
+
["Observer", "observerId"],
|
|
17950
|
+
["Subject", "subject"],
|
|
17951
|
+
["Expected", "expectation"],
|
|
17952
|
+
["Actual", "actual"],
|
|
17953
|
+
["Observation ID", "observationId"],
|
|
17954
|
+
["Observed", "observedAt"],
|
|
17955
|
+
["Operator activity", "operatorActivityAt"]
|
|
17956
|
+
]) {
|
|
17957
|
+
pushField(lines, label, finding[key]);
|
|
17958
|
+
}
|
|
17959
|
+
lines.push("");
|
|
17960
|
+
return lines;
|
|
17961
|
+
}
|
|
17962
|
+
function renderObservation(observation) {
|
|
17963
|
+
const lines = ["## Observation"];
|
|
17964
|
+
for (const [label, key] of [
|
|
17965
|
+
["ID", "id"],
|
|
17966
|
+
["Status", "status"],
|
|
17967
|
+
["Summary", "summary"],
|
|
17968
|
+
["Observer", "observerId"],
|
|
17969
|
+
["Capability", "capability"],
|
|
17970
|
+
["Subject", "subject"],
|
|
17971
|
+
["Observed", "observedAt"]
|
|
17972
|
+
]) {
|
|
17973
|
+
pushField(lines, label, observation[key]);
|
|
17974
|
+
}
|
|
17975
|
+
const evidence = renderEvidence(Array.isArray(observation.evidence) ? observation.evidence : []);
|
|
17976
|
+
if (evidence.length > 0) lines.push("", "### Evidence", ...evidence);
|
|
17977
|
+
lines.push("");
|
|
17978
|
+
return lines;
|
|
17979
|
+
}
|
|
17980
|
+
function renderLearning(learning) {
|
|
17981
|
+
const lines = ["## Learning"];
|
|
17982
|
+
for (const [label, key] of [
|
|
17983
|
+
["ID", "id"],
|
|
17984
|
+
["Finding ID", "findingId"],
|
|
17985
|
+
["Summary", "summary"],
|
|
17986
|
+
["Change", "change"],
|
|
17987
|
+
["Evidence", "evidence"]
|
|
17988
|
+
]) {
|
|
17989
|
+
pushField(lines, label, learning[key]);
|
|
17990
|
+
}
|
|
17991
|
+
lines.push("");
|
|
17992
|
+
return lines;
|
|
17993
|
+
}
|
|
17994
|
+
function renderObjectFields(value, headingLevel) {
|
|
17995
|
+
const lines = [];
|
|
17996
|
+
for (const [key, item] of Object.entries(value)) {
|
|
17997
|
+
const label = humanize(key);
|
|
17998
|
+
if (isScalar(item)) {
|
|
17999
|
+
lines.push(markdownField(label, item));
|
|
18000
|
+
continue;
|
|
18001
|
+
}
|
|
18002
|
+
if (Array.isArray(item)) {
|
|
18003
|
+
if (item.length === 0) continue;
|
|
18004
|
+
lines.push(`${"#".repeat(Math.min(headingLevel, 6))} ${label}`);
|
|
18005
|
+
for (const entry of item) {
|
|
18006
|
+
if (isScalar(entry)) lines.push(`- ${markdownValue(entry)}`);
|
|
18007
|
+
else if (recordField4(entry)) lines.push(...renderObjectFields(recordField4(entry), headingLevel + 1));
|
|
18008
|
+
}
|
|
18009
|
+
continue;
|
|
18010
|
+
}
|
|
18011
|
+
const record2 = recordField4(item);
|
|
18012
|
+
if (!record2 || Object.keys(record2).length === 0) continue;
|
|
18013
|
+
lines.push(`${"#".repeat(Math.min(headingLevel, 6))} ${label}`, ...renderObjectFields(record2, headingLevel + 1));
|
|
18014
|
+
}
|
|
18015
|
+
return lines;
|
|
18016
|
+
}
|
|
18017
|
+
function renderEvidence(items) {
|
|
18018
|
+
return items.flatMap((item) => {
|
|
18019
|
+
const record2 = recordField4(item);
|
|
18020
|
+
if (!record2) return [];
|
|
18021
|
+
const label = stringValue5(record2.label) ?? stringValue5(record2.kind) ?? "Evidence";
|
|
18022
|
+
const url = stringValue5(record2.url);
|
|
18023
|
+
const status = stringValue5(record2.status);
|
|
18024
|
+
const suffix = status ? ` \u2014 ${humanize(status)}` : "";
|
|
18025
|
+
return [`- ${url ? `[${label}](${url})` : label}${suffix}`];
|
|
18026
|
+
});
|
|
18027
|
+
}
|
|
18028
|
+
function omitKeys(value, keys) {
|
|
18029
|
+
const omitted = new Set(keys);
|
|
18030
|
+
return Object.fromEntries(Object.entries(value).filter(([key]) => !omitted.has(key)));
|
|
18031
|
+
}
|
|
18032
|
+
function stringArray3(value) {
|
|
18033
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
18034
|
+
}
|
|
18035
|
+
function isScalar(value) {
|
|
18036
|
+
return value === null || value === void 0 || ["string", "number", "boolean"].includes(typeof value);
|
|
18037
|
+
}
|
|
18038
|
+
function pushField(lines, label, value) {
|
|
18039
|
+
if (isScalar(value) && value !== void 0 && value !== null && value !== "") {
|
|
18040
|
+
lines.push(markdownField(label, value));
|
|
18041
|
+
}
|
|
18042
|
+
}
|
|
18043
|
+
function markdownField(label, value) {
|
|
18044
|
+
return `- **${label}:** ${markdownValue(value)}`;
|
|
18045
|
+
}
|
|
18046
|
+
function markdownValue(value) {
|
|
18047
|
+
if (value === null || value === void 0) return "None";
|
|
18048
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
18049
|
+
return String(value).replace(/\r?\n/g, " ").trim();
|
|
17908
18050
|
}
|
|
17909
18051
|
async function publishWorkflowReport(input) {
|
|
17910
18052
|
const slug = input.publication.slug;
|
|
@@ -17986,10 +18128,7 @@ function stringValue5(value) {
|
|
|
17986
18128
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17987
18129
|
}
|
|
17988
18130
|
function humanize(value) {
|
|
17989
|
-
return value.split(/[-_]+/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
17990
|
-
}
|
|
17991
|
-
function yamlString(value) {
|
|
17992
|
-
return JSON.stringify(value);
|
|
18131
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[-_]+/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
17993
18132
|
}
|
|
17994
18133
|
var SAFE_SLUG, publishReport;
|
|
17995
18134
|
var init_publishReport = __esm({
|
|
@@ -19705,7 +19844,7 @@ function validateOneModel(rawModel, files, label, strictSingleModel, failures, e
|
|
|
19705
19844
|
const slug = stringField5(model.slug);
|
|
19706
19845
|
if (!isSlug(slug)) failures.push(`${label}.slug must be a lowercase slug`);
|
|
19707
19846
|
if (isModelKind(kind)) {
|
|
19708
|
-
const docsUsed =
|
|
19847
|
+
const docsUsed = stringArray4(model.docsUsed);
|
|
19709
19848
|
for (const doc of REQUIRED_DOCS[kind]) {
|
|
19710
19849
|
if (!docsUsed.includes(doc)) failures.push(`${label} docsUsed missing ${doc}`);
|
|
19711
19850
|
}
|
|
@@ -19803,12 +19942,12 @@ function validateModelShape(kind, model, files, slug, failures) {
|
|
|
19803
19942
|
if (!isFiniteNumber(intent?.priority)) failures.push("intent file must declare numeric priority");
|
|
19804
19943
|
if (!hasScope(model.scope)) failures.push("intent model scope must include a repo or area");
|
|
19805
19944
|
if (!hasScope(intent?.scope)) failures.push("intent file scope must include a repo or area");
|
|
19806
|
-
if (
|
|
19807
|
-
if (
|
|
19808
|
-
if (
|
|
19945
|
+
if (stringArray4(model.principles).length === 0) failures.push("intent model principles must be non-empty");
|
|
19946
|
+
if (stringArray4(intent?.principles).length === 0) failures.push("intent file principles must be non-empty");
|
|
19947
|
+
if (stringArray4(model.successMeasures).length === 0) {
|
|
19809
19948
|
failures.push("intent model successMeasures must be non-empty");
|
|
19810
19949
|
}
|
|
19811
|
-
if (
|
|
19950
|
+
if (stringArray4(intent?.metrics).length === 0) failures.push("intent file metrics must be non-empty");
|
|
19812
19951
|
if (!recordField5(model.policy)) failures.push("intent model must declare policy");
|
|
19813
19952
|
if (!recordField5(intent?.policy)) failures.push("intent file must declare policy");
|
|
19814
19953
|
if (stringField5(model.status) !== "paused" || stringField5(intent?.status) !== "paused") {
|
|
@@ -19823,10 +19962,10 @@ function validateModelShape(kind, model, files, slug, failures) {
|
|
|
19823
19962
|
const operation = parseJsonFile(files, `operations/${slug}/operation.json`, failures);
|
|
19824
19963
|
if (!stringField5(model.responsibility)) failures.push("operation model must declare responsibility");
|
|
19825
19964
|
if (!stringField5(operation?.responsibility)) failures.push("operation file must declare responsibility");
|
|
19826
|
-
if (
|
|
19827
|
-
if (
|
|
19828
|
-
if (
|
|
19829
|
-
if (
|
|
19965
|
+
if (stringArray4(model.intentIds).length === 0) failures.push("operation model intentIds must be non-empty");
|
|
19966
|
+
if (stringArray4(operation?.intentIds).length === 0) failures.push("operation file intentIds must be non-empty");
|
|
19967
|
+
if (stringArray4(model.doesNotOwn).length === 0) failures.push("operation model doesNotOwn must be non-empty");
|
|
19968
|
+
if (stringArray4(operation?.doesNotOwn).length === 0) failures.push("operation file doesNotOwn must be non-empty");
|
|
19830
19969
|
if (stringField5(model.status) !== "proposed" || stringField5(operation?.status) !== "proposed") {
|
|
19831
19970
|
failures.push("operation proposal status must be proposed");
|
|
19832
19971
|
}
|
|
@@ -19835,7 +19974,7 @@ function validateModelShape(kind, model, files, slug, failures) {
|
|
|
19835
19974
|
}
|
|
19836
19975
|
if (kind === "agent") {
|
|
19837
19976
|
const agentFile = textFile(files, `agents/${slug}.md`);
|
|
19838
|
-
if (!
|
|
19977
|
+
if (!stringArray4(model.owns).includes("identity") && !containsWord(agentFile, "identity")) {
|
|
19839
19978
|
failures.push("agent owns must include identity");
|
|
19840
19979
|
}
|
|
19841
19980
|
requireStringArrayIncludes(model.doesNotOwn, "tasks", "agent doesNotOwn", failures);
|
|
@@ -19878,7 +20017,7 @@ function validateModelShape(kind, model, files, slug, failures) {
|
|
|
19878
20017
|
}
|
|
19879
20018
|
}
|
|
19880
20019
|
function capabilityRefs(value) {
|
|
19881
|
-
return [...
|
|
20020
|
+
return [...stringArray4(value?.capabilities), ...stringArray4(value?.allowedCapabilities)];
|
|
19882
20021
|
}
|
|
19883
20022
|
function evidenceRefs(value) {
|
|
19884
20023
|
if (!value) return [];
|
|
@@ -19950,7 +20089,7 @@ function normalizeBundlePath(filePath) {
|
|
|
19950
20089
|
function stringField5(value) {
|
|
19951
20090
|
return typeof value === "string" ? value.trim() : "";
|
|
19952
20091
|
}
|
|
19953
|
-
function
|
|
20092
|
+
function stringArray4(value) {
|
|
19954
20093
|
if (!Array.isArray(value)) return [];
|
|
19955
20094
|
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
19956
20095
|
}
|
|
@@ -19962,10 +20101,10 @@ function isFiniteNumber(value) {
|
|
|
19962
20101
|
}
|
|
19963
20102
|
function hasScope(value) {
|
|
19964
20103
|
const scope = recordField5(value);
|
|
19965
|
-
return
|
|
20104
|
+
return stringArray4(scope?.repos).length > 0 || stringArray4(scope?.areas).length > 0;
|
|
19966
20105
|
}
|
|
19967
20106
|
function requireStringArrayIncludes(value, expected, label, failures) {
|
|
19968
|
-
if (!
|
|
20107
|
+
if (!stringArray4(value).includes(expected)) failures.push(`${label} must include ${expected}`);
|
|
19969
20108
|
}
|
|
19970
20109
|
function isSlug(value) {
|
|
19971
20110
|
return /^[a-z][a-z0-9-]{0,63}$/.test(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.523",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|