@kody-ade/kody-engine 0.2.4 → 0.2.5

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/kody2.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@kody-ade/kody-engine",
6
- version: "0.2.4",
6
+ version: "0.2.5",
7
7
  description: "kody2 \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
8
8
  license: "MIT",
9
9
  type: "module",
@@ -1898,6 +1898,55 @@ function postWith(type, n, body, cwd) {
1898
1898
  }
1899
1899
  }
1900
1900
 
1901
+ // src/scripts/postReviewResult.ts
1902
+ function detectVerdict(body) {
1903
+ const m = body.match(/##\s*Verdict\s*:\s*(PASS|CONCERNS|FAIL)\b/i);
1904
+ if (!m) return "UNKNOWN";
1905
+ return m[1].toUpperCase();
1906
+ }
1907
+ var postReviewResult = async (ctx, _profile, agentResult) => {
1908
+ const prNumber = ctx.data.commentTargetNumber;
1909
+ if (!prNumber) {
1910
+ ctx.output.exitCode = 99;
1911
+ ctx.output.reason = "review postflight: no PR number in context";
1912
+ return;
1913
+ }
1914
+ if (!agentResult || agentResult.outcome !== "completed") {
1915
+ const reason = agentResult?.error ?? "agent did not complete";
1916
+ try {
1917
+ postPrReviewComment(prNumber, `\u26A0\uFE0F kody2 review FAILED: ${truncate2(reason, 1e3)}`, ctx.cwd);
1918
+ } catch {
1919
+ }
1920
+ ctx.output.exitCode = 1;
1921
+ ctx.output.reason = reason;
1922
+ return;
1923
+ }
1924
+ const reviewBody = agentResult.finalText.trim();
1925
+ if (!reviewBody) {
1926
+ try {
1927
+ postPrReviewComment(prNumber, `\u26A0\uFE0F kody2 review FAILED: agent produced no review body`, ctx.cwd);
1928
+ } catch {
1929
+ }
1930
+ ctx.output.exitCode = 1;
1931
+ ctx.output.reason = "empty review body";
1932
+ return;
1933
+ }
1934
+ try {
1935
+ postPrReviewComment(prNumber, reviewBody, ctx.cwd);
1936
+ } catch (err) {
1937
+ const msg = err instanceof Error ? err.message : String(err);
1938
+ ctx.output.exitCode = 4;
1939
+ ctx.output.reason = `failed to post review comment: ${msg}`;
1940
+ return;
1941
+ }
1942
+ const verdict = detectVerdict(reviewBody);
1943
+ ctx.data.reviewVerdict = verdict;
1944
+ ctx.output.exitCode = verdict === "FAIL" ? 1 : 0;
1945
+ process.stdout.write(`
1946
+ REVIEW_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.github.repo}/pull/${prNumber} (verdict: ${verdict})
1947
+ `);
1948
+ };
1949
+
1901
1950
  // src/scripts/resolveFlow.ts
1902
1951
  import { execFileSync as execFileSync10 } from "child_process";
1903
1952
  var CONFLICT_DIFF_MAX_BYTES = 4e4;
@@ -1988,6 +2037,33 @@ function tryPostPr3(prNumber, body, cwd) {
1988
2037
  }
1989
2038
  }
1990
2039
 
2040
+ // src/scripts/reviewFlow.ts
2041
+ var reviewFlow = async (ctx) => {
2042
+ const prNumber = ctx.args.pr;
2043
+ const pr = getPr(prNumber, ctx.cwd);
2044
+ if (pr.state !== "OPEN") {
2045
+ ctx.output.exitCode = 1;
2046
+ ctx.output.reason = `PR #${prNumber} is not OPEN (state: ${pr.state})`;
2047
+ ctx.skipAgent = true;
2048
+ return;
2049
+ }
2050
+ ctx.data.pr = pr;
2051
+ ctx.data.commentTargetType = "pr";
2052
+ ctx.data.commentTargetNumber = prNumber;
2053
+ checkoutPrBranch(prNumber, ctx.cwd);
2054
+ ctx.data.branch = getCurrentBranch(ctx.cwd);
2055
+ ctx.data.prDiff = getPrDiff(prNumber, ctx.cwd);
2056
+ const runUrl = getRunUrl();
2057
+ const runSuffix = runUrl ? `, run ${runUrl}` : "";
2058
+ tryPostPr4(prNumber, `\u{1F440} kody2 review started on PR #${prNumber}${runSuffix}`, ctx.cwd);
2059
+ };
2060
+ function tryPostPr4(prNumber, body, cwd) {
2061
+ try {
2062
+ postPrReviewComment(prNumber, body, cwd);
2063
+ } catch {
2064
+ }
2065
+ }
2066
+
1991
2067
  // src/scripts/runFlow.ts
1992
2068
  var runFlow = async (ctx) => {
1993
2069
  const issueNumber = ctx.args.issue;
@@ -2138,6 +2214,7 @@ var preflightScripts = {
2138
2214
  fixFlow,
2139
2215
  fixCiFlow,
2140
2216
  resolveFlow,
2217
+ reviewFlow,
2141
2218
  initFlow,
2142
2219
  loadConventions,
2143
2220
  loadCoverageRules,
@@ -2150,6 +2227,7 @@ var postflightScripts = {
2150
2227
  commitAndPush: commitAndPush2,
2151
2228
  ensurePr: ensurePr2,
2152
2229
  postIssueComment: postIssueComment2,
2230
+ postReviewResult,
2153
2231
  writeRunSummary
2154
2232
  };
2155
2233
  var allScriptNames = /* @__PURE__ */ new Set([
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "review",
3
+ "describe": "Read-only structured review of an open PR. Posts one comment, never commits.",
4
+
5
+ "inputs": [
6
+ {
7
+ "name": "pr",
8
+ "flag": "--pr",
9
+ "type": "int",
10
+ "required": true,
11
+ "describe": "GitHub PR number to review."
12
+ }
13
+ ],
14
+
15
+ "claudeCode": {
16
+ "model": "inherit",
17
+ "permissionMode": "default",
18
+ "maxTurns": null,
19
+ "systemPromptAppend": null,
20
+ "tools": ["Read", "Grep", "Glob", "Bash"],
21
+ "hooks": { "PreToolUse": [], "PostToolUse": [], "Stop": [] },
22
+ "skills": [],
23
+ "commands": [],
24
+ "subagents": [],
25
+ "plugins": [],
26
+ "mcpServers": []
27
+ },
28
+
29
+ "cliTools": [],
30
+
31
+ "scripts": {
32
+ "preflight": [
33
+ { "script": "reviewFlow" },
34
+ { "script": "loadConventions" },
35
+ { "script": "composePrompt" }
36
+ ],
37
+ "postflight": [
38
+ { "script": "postReviewResult" }
39
+ ]
40
+ }
41
+ }
@@ -0,0 +1,47 @@
1
+ You are Kody, a senior code reviewer. Review PR #{{pr.number}} carefully and post ONE structured review comment. Do NOT edit any files. Do NOT run any `git` or `gh` commands. Use Read / Grep / Glob / Bash only to inspect the diff and surrounding code.
2
+
3
+ # PR #{{pr.number}}: {{pr.title}}
4
+
5
+ Base: {{pr.baseRefName}} ← Head: {{pr.headRefName}}
6
+
7
+ {{pr.body}}
8
+
9
+ {{conventionsBlock}}
10
+
11
+ # Diff
12
+
13
+ ```diff
14
+ {{prDiff}}
15
+ ```
16
+
17
+ # Required output
18
+
19
+ Your FINAL message must be a markdown-formatted review comment, **structured exactly as below** — no preamble, no DONE / COMMIT_MSG / PR_SUMMARY markers. The entire final message IS the review comment and will be posted verbatim:
20
+
21
+ ```
22
+ ## Verdict: PASS | CONCERNS | FAIL
23
+
24
+ ### Summary
25
+ <2-3 sentences: what this PR does, is the approach sound>
26
+
27
+ ### Strengths
28
+ - <bullet>
29
+ - <bullet>
30
+
31
+ ### Concerns
32
+ - <bullet, or "None" if none>
33
+
34
+ ### Suggestions
35
+ - <bullet with file:line reference where possible>
36
+
37
+ ### Bottom line
38
+ <one sentence>
39
+ ```
40
+
41
+ # Rules
42
+
43
+ - No file edits. No `git`/`gh` invocations. Read-only investigation.
44
+ - Be specific: cite file paths and line numbers. No generic advice.
45
+ - Verdict **FAIL** only for clear correctness / security / regression risks.
46
+ - Verdict **CONCERNS** for style / clarity / test-coverage gaps that shouldn't block.
47
+ - Verdict **PASS** when the PR meets spec with no blocking issues.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "kody2 — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",