@renaiss-shipflow/cli 0.10.0 → 0.12.1

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.
Files changed (59) hide show
  1. package/dist/client.d.ts +27 -0
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +5 -0
  4. package/dist/client.js.map +1 -1
  5. package/dist/commands/config.d.ts.map +1 -1
  6. package/dist/commands/config.js +3 -1
  7. package/dist/commands/config.js.map +1 -1
  8. package/dist/commands/git-identity.d.ts +3 -0
  9. package/dist/commands/git-identity.d.ts.map +1 -0
  10. package/dist/commands/git-identity.js +77 -0
  11. package/dist/commands/git-identity.js.map +1 -0
  12. package/dist/commands/issue.d.ts.map +1 -1
  13. package/dist/commands/issue.js +49 -6
  14. package/dist/commands/issue.js.map +1 -1
  15. package/dist/commands/login.d.ts.map +1 -1
  16. package/dist/commands/login.js +16 -2
  17. package/dist/commands/login.js.map +1 -1
  18. package/dist/commands/pr.d.ts.map +1 -1
  19. package/dist/commands/pr.js +107 -3
  20. package/dist/commands/pr.js.map +1 -1
  21. package/dist/commands/stats.d.ts +7 -0
  22. package/dist/commands/stats.d.ts.map +1 -1
  23. package/dist/commands/stats.js +72 -1
  24. package/dist/commands/stats.js.map +1 -1
  25. package/dist/commands/test.d.ts +10 -0
  26. package/dist/commands/test.d.ts.map +1 -1
  27. package/dist/commands/test.js +52 -14
  28. package/dist/commands/test.js.map +1 -1
  29. package/dist/config.d.ts +7 -0
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/config.js +9 -0
  32. package/dist/config.js.map +1 -1
  33. package/dist/escalation-format.d.ts +35 -2
  34. package/dist/escalation-format.d.ts.map +1 -1
  35. package/dist/escalation-format.js +81 -4
  36. package/dist/escalation-format.js.map +1 -1
  37. package/dist/gh.d.ts +40 -1
  38. package/dist/gh.d.ts.map +1 -1
  39. package/dist/gh.js +88 -3
  40. package/dist/gh.js.map +1 -1
  41. package/dist/git-local.d.ts +4 -0
  42. package/dist/git-local.d.ts.map +1 -1
  43. package/dist/git-local.js +37 -0
  44. package/dist/git-local.js.map +1 -1
  45. package/dist/index.js +2 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/packet.d.ts +43 -3
  48. package/dist/packet.d.ts.map +1 -1
  49. package/dist/packet.js +124 -17
  50. package/dist/packet.js.map +1 -1
  51. package/dist/review-contract-data.d.ts +91 -0
  52. package/dist/review-contract-data.d.ts.map +1 -0
  53. package/dist/review-contract-data.js +111 -0
  54. package/dist/review-contract-data.js.map +1 -0
  55. package/dist/review-contract.d.ts +66 -0
  56. package/dist/review-contract.d.ts.map +1 -0
  57. package/dist/review-contract.js +139 -0
  58. package/dist/review-contract.js.map +1 -0
  59. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ // Canonical review contract shared by the loop reviewer (this CLI) — the
2
+ // single source of truth for verdict vocabulary, severity badges, finding
3
+ // rendering, and diff anchoring, mirroring the server's runner_pr_review.go so
4
+ // the two reviewers post CONSISTENTLY (epic #96). Pure + testable; no I/O.
5
+ import { REVIEW_CONTRACT } from "./review-contract-data.js";
6
+ /** The loop reviewer's verdict vocabulary — from the canonical contract
7
+ * (contracts/review-contract.json): `approve`/`comment`/`request_changes`/
8
+ * `reject`. The server's advisory vocabulary lives beside it in the contract;
9
+ * reconciling the two is a later slice of epic #96. */
10
+ export const LOOP_VERDICTS = REVIEW_CONTRACT.verdicts.loop;
11
+ /** Severity scale (highest first) + the default applied to blank severities —
12
+ * from the canonical contract, matching the server's normalisation. */
13
+ export const SEVERITIES = REVIEW_CONTRACT.severities;
14
+ export const DEFAULT_SEVERITY = REVIEW_CONTRACT.defaultSeverity;
15
+ /** Severity badge — byte-identical to the server's severityBadge(). */
16
+ export function severityBadge(severity) {
17
+ switch (severity.trim().toLowerCase()) {
18
+ case "critical": return "🔴 **critical**";
19
+ case "high": return "🟠 **high**";
20
+ case "low": return "🔵 **low**";
21
+ default: return "🟡 **medium**";
22
+ }
23
+ }
24
+ /** CodeRabbit-style fix-size tag after the badge — mirrors the server. */
25
+ export function effortTag(effort) {
26
+ switch ((effort ?? "").trim().toLowerCase()) {
27
+ case "quick": return " · ⚡ quick fix";
28
+ case "involved": return " · 🔨 involved";
29
+ default: return "";
30
+ }
31
+ }
32
+ /** Verdict header, shared by the inline review body and any fallback comment. */
33
+ export function verdictHeader(verdict) {
34
+ switch (verdict) {
35
+ case "approve": return "**✅ APPROVE — ShipFlow review**";
36
+ case "request_changes": return "**🔴 CHANGES REQUESTED — ShipFlow review**";
37
+ case "reject": return "**⛔ REJECT — ShipFlow review**";
38
+ default: return "**💬 ShipFlow review — comments**";
39
+ }
40
+ }
41
+ const REVIEW_MARKER = "<!-- shipflow:loop-review -->";
42
+ /** One finding's comment body — mirrors renderInlineFinding(): badge + effort +
43
+ * issue, why, fix, and a committable ```suggestion block when present. */
44
+ export function renderFindingBody(f) {
45
+ let b = `${severityBadge(f.severity)}${effortTag(f.effort)} ${f.issue}`;
46
+ if (f.why?.trim())
47
+ b += `\n\n${f.why.trim()}`;
48
+ if (f.fix?.trim())
49
+ b += `\n\n**Fix:** ${f.fix.trim()}`;
50
+ const sug = (f.suggestion ?? "").replace(/\n+$/, "");
51
+ const code = (f.code ?? "").replace(/\n+$/, "");
52
+ if (sug.trim())
53
+ b += `\n\`\`\`suggestion\n${sug}\n\`\`\``;
54
+ else if (code.trim())
55
+ b += `\n\`\`\`\n${code}\n\`\`\``;
56
+ return `${b}\n\n${REVIEW_MARKER}`;
57
+ }
58
+ /** Repo-relative path in one canonical shape: forward slashes, no leading
59
+ * "./". Applied to both diff keys and finding paths so `./src/x` / `src\\x`
60
+ * still anchor. NOT a filesystem realpath — diff paths aren't fs paths. */
61
+ export function normPath(p) {
62
+ return p.replace(/\\/g, "/").replace(/^\.\//, "").trim();
63
+ }
64
+ const HUNK_RE = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
65
+ const FILE_RE = /^\+\+\+ b\/(.+)$/;
66
+ /** Map of path → set of new-file line numbers that GitHub will accept a
67
+ * RIGHT-side inline comment on (context + added lines). Mirrors the server's
68
+ * annotatePatch line numbering so a bad anchor can't 422 the whole review. */
69
+ export function diffAnchors(diff) {
70
+ const out = new Map();
71
+ let path = "";
72
+ let ln = 0;
73
+ for (const raw of diff.split(/\r?\n/)) {
74
+ const fm = FILE_RE.exec(raw);
75
+ if (fm) {
76
+ path = normPath(fm[1]);
77
+ ln = 0;
78
+ continue;
79
+ }
80
+ const hm = HUNK_RE.exec(raw);
81
+ if (hm) {
82
+ ln = parseInt(hm[1], 10);
83
+ continue;
84
+ }
85
+ if (!path || ln === 0)
86
+ continue;
87
+ if (raw.startsWith("-"))
88
+ continue; // removed: no RIGHT-side line
89
+ if (raw.startsWith("+") || raw.startsWith(" ")) {
90
+ if (!out.has(path))
91
+ out.set(path, new Set());
92
+ out.get(path).add(ln);
93
+ ln++;
94
+ }
95
+ }
96
+ return out;
97
+ }
98
+ /** Partition findings into ones that anchor to a real diff line (postable
99
+ * inline) and ones that must fold into the summary body (bad line / file). */
100
+ export function splitAnchorable(findings, anchors) {
101
+ const inline = [];
102
+ const body = [];
103
+ for (const f of findings) {
104
+ if (f.line > 0 && anchors.get(normPath(f.path))?.has(f.line))
105
+ inline.push(f);
106
+ else
107
+ body.push(f);
108
+ }
109
+ return { inline, body };
110
+ }
111
+ /** Build the GitHub "create review" payload: a COMMENT-event review (ShipFlow
112
+ * reviews are advisory — approval authority stays with the label gate, so the
113
+ * event is never APPROVE/REQUEST_CHANGES; the verdict lives in the header),
114
+ * with on-diff findings as inline comments and the rest folded into the body. */
115
+ export function buildReviewPayload(opts) {
116
+ const { inline, body: unanchored } = splitAnchorable(opts.findings, opts.anchors);
117
+ const lines = [verdictHeader(opts.verdict)];
118
+ if (opts.summary.trim())
119
+ lines.push("", opts.summary.trim());
120
+ if (unanchored.length) {
121
+ lines.push("", "**Further findings (outside the annotated diff lines):**");
122
+ for (const f of unanchored) {
123
+ const anchor = f.line > 0 ? `${f.path}:${f.line}` : f.path;
124
+ const fbLines = renderFindingBody(f).split("\n\n" + REVIEW_MARKER)[0].split("\n");
125
+ lines.push(`- \`${anchor}\` — ${fbLines[0]}`);
126
+ // Indent why/fix/suggestion continuation two spaces so GitHub keeps them
127
+ // nested under the bullet instead of rendering as top-level paragraphs.
128
+ for (let i = 1; i < fbLines.length; i++)
129
+ lines.push(fbLines[i] ? ` ${fbLines[i]}` : "");
130
+ }
131
+ }
132
+ lines.push("", REVIEW_MARKER);
133
+ return {
134
+ event: "COMMENT",
135
+ body: lines.join("\n"),
136
+ comments: inline.map((f) => ({ path: f.path, line: f.line, side: "RIGHT", body: renderFindingBody(f) })),
137
+ };
138
+ }
139
+ //# sourceMappingURL=review-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-contract.js","sourceRoot":"","sources":["../src/review-contract.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@renaiss-shipflow/cli",
3
- "version": "0.10.0",
3
+ "version": "0.12.1",
4
4
  "description": "CLI tool for RenaissShipFlow - AI-powered project management automation",
5
5
  "type": "module",
6
6
  "bin": {