@kody-ade/kody-engine 0.4.302 → 0.4.304
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 +94 -2
- 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.304",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -10438,6 +10438,14 @@ var init_composePrompt = __esm({
|
|
|
10438
10438
|
|
|
10439
10439
|
// src/scripts/postReviewResult.ts
|
|
10440
10440
|
function inferVerdictFromReviewText(body) {
|
|
10441
|
+
const structuredVerdict = body.match(/"verdict"\s*:\s*"(pass|concerns|fail|partial)"/i);
|
|
10442
|
+
if (structuredVerdict) {
|
|
10443
|
+
const value = structuredVerdict[1].toUpperCase();
|
|
10444
|
+
return value === "PARTIAL" ? "CONCERNS" : value;
|
|
10445
|
+
}
|
|
10446
|
+
if (/\bpartial\b/i.test(body) && /\b(finding|gap|unverified|unverifiable|blocker|issue)s?\b/i.test(body)) {
|
|
10447
|
+
return "CONCERNS";
|
|
10448
|
+
}
|
|
10441
10449
|
if (/\b(blocking|blocker|must fix|should not merge|regression|breaks|security risk)\b/i.test(body)) return "FAIL";
|
|
10442
10450
|
if (/\b(actionable item|suggestions?|worth clarifying|worth checking|minor note|non-blocking|deserves a comment)\b/i.test(
|
|
10443
10451
|
body
|
|
@@ -10565,6 +10573,8 @@ function buildGoalName(scope, verdict) {
|
|
|
10565
10573
|
function splitReport(text) {
|
|
10566
10574
|
const open = text.indexOf(REPORT_JSON_OPEN);
|
|
10567
10575
|
if (open < 0) {
|
|
10576
|
+
const fallback = parseFallbackFindingsJson(text);
|
|
10577
|
+
if (fallback) return fallback;
|
|
10568
10578
|
return { markdown: text.trim(), data: null, jsonError: "no JSON block marker" };
|
|
10569
10579
|
}
|
|
10570
10580
|
const closeRel = text.slice(open + REPORT_JSON_OPEN.length).indexOf(REPORT_JSON_CLOSE);
|
|
@@ -10590,6 +10600,74 @@ function splitReport(text) {
|
|
|
10590
10600
|
const markdown = text.slice(0, open).trim();
|
|
10591
10601
|
return { markdown, data: parsed, jsonError: parseError };
|
|
10592
10602
|
}
|
|
10603
|
+
function parseFallbackFindingsJson(text) {
|
|
10604
|
+
const fences = [...text.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/gi)];
|
|
10605
|
+
for (let i = fences.length - 1; i >= 0; i--) {
|
|
10606
|
+
const match = fences[i];
|
|
10607
|
+
const raw = match[1]?.trim();
|
|
10608
|
+
if (!raw || !/"findings"\s*:/.test(raw)) continue;
|
|
10609
|
+
try {
|
|
10610
|
+
const parsed = JSON.parse(raw);
|
|
10611
|
+
if (!parsed || !Array.isArray(parsed.findings)) {
|
|
10612
|
+
return { markdown: removeFence(text, match).trim(), data: null, jsonError: "fallback JSON missing 'findings' array" };
|
|
10613
|
+
}
|
|
10614
|
+
return {
|
|
10615
|
+
markdown: removeFence(text, match).trim(),
|
|
10616
|
+
data: { findings: parsed.findings.map((f, idx) => normalizeFallbackFinding(f, idx)) }
|
|
10617
|
+
};
|
|
10618
|
+
} catch (err) {
|
|
10619
|
+
return {
|
|
10620
|
+
markdown: removeFence(text, match).trim(),
|
|
10621
|
+
data: null,
|
|
10622
|
+
jsonError: err instanceof Error ? err.message : String(err)
|
|
10623
|
+
};
|
|
10624
|
+
}
|
|
10625
|
+
}
|
|
10626
|
+
return null;
|
|
10627
|
+
}
|
|
10628
|
+
function removeFence(text, match) {
|
|
10629
|
+
const start = match.index ?? -1;
|
|
10630
|
+
if (start < 0) return text;
|
|
10631
|
+
return `${text.slice(0, start)}${text.slice(start + match[0].length)}`;
|
|
10632
|
+
}
|
|
10633
|
+
function normalizeFallbackFinding(raw, idx) {
|
|
10634
|
+
const finding = raw && typeof raw === "object" ? raw : {};
|
|
10635
|
+
const title = firstString(finding.title, finding.summary, finding.issue, finding.name) || `QA finding ${idx + 1}`;
|
|
10636
|
+
const route = firstString(finding.route, finding.url, finding.path);
|
|
10637
|
+
const expected = firstString(finding.expected) || "Expected behavior described in QA report.";
|
|
10638
|
+
const actual = firstString(finding.actual, finding.summary, finding.observed) || "Observed behavior described in QA report.";
|
|
10639
|
+
return {
|
|
10640
|
+
severity: normalizeSeverity(firstString(finding.severity, finding.priority)),
|
|
10641
|
+
title,
|
|
10642
|
+
...route ? { route } : {},
|
|
10643
|
+
steps: firstString(finding.steps, finding.repro, finding.reproduction) || "See QA report.",
|
|
10644
|
+
expected,
|
|
10645
|
+
actual,
|
|
10646
|
+
evidence: evidenceString(finding.evidence)
|
|
10647
|
+
};
|
|
10648
|
+
}
|
|
10649
|
+
function firstString(...values) {
|
|
10650
|
+
for (const value of values) {
|
|
10651
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
10652
|
+
}
|
|
10653
|
+
return "";
|
|
10654
|
+
}
|
|
10655
|
+
function evidenceString(value) {
|
|
10656
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
10657
|
+
if (Array.isArray(value)) {
|
|
10658
|
+
const parts = value.filter((v) => typeof v === "string" && v.trim().length > 0).map((v) => v.trim());
|
|
10659
|
+
return parts.length > 0 ? parts.join(", ") : void 0;
|
|
10660
|
+
}
|
|
10661
|
+
return void 0;
|
|
10662
|
+
}
|
|
10663
|
+
function normalizeSeverity(value) {
|
|
10664
|
+
const v = value.trim().toUpperCase();
|
|
10665
|
+
if (v === "P0" || v === "CRITICAL") return "P0";
|
|
10666
|
+
if (v === "P1" || v === "HIGH" || v === "BLOCKER") return "P1";
|
|
10667
|
+
if (v === "P2" || v === "MEDIUM") return "P2";
|
|
10668
|
+
if (v === "P3" || v === "LOW" || v === "POLISH") return "P3";
|
|
10669
|
+
return "P2";
|
|
10670
|
+
}
|
|
10593
10671
|
function loadManifest(cwd) {
|
|
10594
10672
|
let issuesJson;
|
|
10595
10673
|
try {
|
|
@@ -10891,7 +10969,7 @@ QA_GOAL_TARGETED=(no manifest issue) (id: ${goalId}, verdict: ${verdict})
|
|
|
10891
10969
|
});
|
|
10892
10970
|
ctx.output.exitCode = verdict === "FAIL" ? 1 : 0;
|
|
10893
10971
|
}
|
|
10894
|
-
var MANIFEST_LABEL, MANIFEST_TITLE, MANIFEST_START, MANIFEST_END, FINDING_LABEL, REPORT_JSON_OPEN, REPORT_JSON_CLOSE, SEVERITY_COLORS, createQaGoal;
|
|
10972
|
+
var MANIFEST_LABEL, MANIFEST_TITLE, MANIFEST_START, MANIFEST_END, FINDING_LABEL, QA_REPORT_LABEL, REPORT_JSON_OPEN, REPORT_JSON_CLOSE, SEVERITY_COLORS, createQaGoal;
|
|
10895
10973
|
var init_createQaGoal = __esm({
|
|
10896
10974
|
"src/scripts/createQaGoal.ts"() {
|
|
10897
10975
|
"use strict";
|
|
@@ -10904,6 +10982,7 @@ var init_createQaGoal = __esm({
|
|
|
10904
10982
|
MANIFEST_START = "<!-- kody-goals-start -->";
|
|
10905
10983
|
MANIFEST_END = "<!-- kody-goals-end -->";
|
|
10906
10984
|
FINDING_LABEL = "kody:qa-finding";
|
|
10985
|
+
QA_REPORT_LABEL = "kody:qa-report";
|
|
10907
10986
|
REPORT_JSON_OPEN = "<!-- KODY_QA_REPORT_JSON";
|
|
10908
10987
|
REPORT_JSON_CLOSE = "-->";
|
|
10909
10988
|
SEVERITY_COLORS = {
|
|
@@ -10943,6 +11022,11 @@ var init_createQaGoal = __esm({
|
|
|
10943
11022
|
ctx.data.action = failedAction2(ctx.output.reason);
|
|
10944
11023
|
return;
|
|
10945
11024
|
}
|
|
11025
|
+
try {
|
|
11026
|
+
ensureLabel(QA_REPORT_LABEL, "8b5cf6", "kody: QA report", ctx.cwd);
|
|
11027
|
+
gh(["issue", "edit", String(existingIssue), "--add-label", QA_REPORT_LABEL], { cwd: ctx.cwd });
|
|
11028
|
+
} catch {
|
|
11029
|
+
}
|
|
10946
11030
|
process.stdout.write(
|
|
10947
11031
|
`
|
|
10948
11032
|
QA_REPORT_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.github.repo}/issues/${existingIssue} (verdict: ${verdict})
|
|
@@ -14085,6 +14169,13 @@ function ensureLabel2(cwd) {
|
|
|
14085
14169
|
return false;
|
|
14086
14170
|
}
|
|
14087
14171
|
}
|
|
14172
|
+
function markIssueWithReportLabel(issue, cwd) {
|
|
14173
|
+
if (!ensureLabel2(cwd)) return;
|
|
14174
|
+
try {
|
|
14175
|
+
gh(["issue", "edit", String(issue), "--add-label", QA_LABEL], { cwd });
|
|
14176
|
+
} catch {
|
|
14177
|
+
}
|
|
14178
|
+
}
|
|
14088
14179
|
function createQaIssue(title, body, hasLabel, cwd) {
|
|
14089
14180
|
const args = ["issue", "create", "--title", title, "--body-file", "-"];
|
|
14090
14181
|
if (hasLabel) args.push("--label", QA_LABEL);
|
|
@@ -14126,6 +14217,7 @@ var init_openQaIssue = __esm({
|
|
|
14126
14217
|
if (typeof existingIssue === "number" && Number.isFinite(existingIssue) && existingIssue > 0) {
|
|
14127
14218
|
try {
|
|
14128
14219
|
postIssueComment(existingIssue, reportBody, ctx.cwd);
|
|
14220
|
+
markIssueWithReportLabel(existingIssue, ctx.cwd);
|
|
14129
14221
|
} catch (err) {
|
|
14130
14222
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14131
14223
|
ctx.output.exitCode = 4;
|
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.304",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|