@zephyrdeng/pi-review 0.6.1 → 0.7.0

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 (125) hide show
  1. package/README.md +110 -13
  2. package/README.zh-CN.md +64 -3
  3. package/dist/args.d.ts +8 -0
  4. package/dist/args.d.ts.map +1 -1
  5. package/dist/args.js +147 -28
  6. package/dist/args.js.map +1 -1
  7. package/dist/args.test.d.ts +2 -0
  8. package/dist/args.test.d.ts.map +1 -0
  9. package/dist/args.test.js +115 -0
  10. package/dist/args.test.js.map +1 -0
  11. package/dist/cli-exit.test.d.ts +2 -0
  12. package/dist/cli-exit.test.d.ts.map +1 -0
  13. package/dist/cli-exit.test.js +84 -0
  14. package/dist/cli-exit.test.js.map +1 -0
  15. package/dist/cli.js +16 -2
  16. package/dist/cli.js.map +1 -1
  17. package/dist/config.d.ts +1 -0
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +1 -0
  20. package/dist/config.js.map +1 -1
  21. package/dist/extensions/review.d.ts +2 -0
  22. package/dist/extensions/review.js +22 -0
  23. package/dist/extensions/rv-prompts.d.ts +19 -0
  24. package/dist/extensions/rv-prompts.js +132 -0
  25. package/dist/index.d.ts +17 -7
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +12 -6
  28. package/dist/index.js.map +1 -1
  29. package/dist/json-events.d.ts +45 -0
  30. package/dist/json-events.d.ts.map +1 -1
  31. package/dist/json-events.js +185 -0
  32. package/dist/json-events.js.map +1 -1
  33. package/dist/json-events.test.js +64 -1
  34. package/dist/json-events.test.js.map +1 -1
  35. package/dist/loop.d.ts +36 -0
  36. package/dist/loop.d.ts.map +1 -0
  37. package/dist/loop.js +73 -0
  38. package/dist/loop.js.map +1 -0
  39. package/dist/loop.test.d.ts +2 -0
  40. package/dist/loop.test.d.ts.map +1 -0
  41. package/dist/loop.test.js +83 -0
  42. package/dist/loop.test.js.map +1 -0
  43. package/dist/matcher.d.ts +74 -0
  44. package/dist/matcher.d.ts.map +1 -0
  45. package/dist/matcher.js +202 -0
  46. package/dist/matcher.js.map +1 -0
  47. package/dist/matcher.test.d.ts +2 -0
  48. package/dist/matcher.test.d.ts.map +1 -0
  49. package/dist/matcher.test.js +161 -0
  50. package/dist/matcher.test.js.map +1 -0
  51. package/dist/meta-footer.d.ts +15 -1
  52. package/dist/meta-footer.d.ts.map +1 -1
  53. package/dist/meta-footer.js +108 -0
  54. package/dist/meta-footer.js.map +1 -1
  55. package/dist/meta-footer.test.js +43 -1
  56. package/dist/meta-footer.test.js.map +1 -1
  57. package/dist/panel-aggregate.d.ts +18 -0
  58. package/dist/panel-aggregate.d.ts.map +1 -0
  59. package/dist/panel-aggregate.js +247 -0
  60. package/dist/panel-aggregate.js.map +1 -0
  61. package/dist/panel-aggregate.test.d.ts +2 -0
  62. package/dist/panel-aggregate.test.d.ts.map +1 -0
  63. package/dist/panel-aggregate.test.js +461 -0
  64. package/dist/panel-aggregate.test.js.map +1 -0
  65. package/dist/panel-cli.test.d.ts +2 -0
  66. package/dist/panel-cli.test.d.ts.map +1 -0
  67. package/dist/panel-cli.test.js +188 -0
  68. package/dist/panel-cli.test.js.map +1 -0
  69. package/dist/panel-config.d.ts +19 -0
  70. package/dist/panel-config.d.ts.map +1 -0
  71. package/dist/panel-config.js +115 -0
  72. package/dist/panel-config.js.map +1 -0
  73. package/dist/panel-config.test.d.ts +2 -0
  74. package/dist/panel-config.test.d.ts.map +1 -0
  75. package/dist/panel-config.test.js +91 -0
  76. package/dist/panel-config.test.js.map +1 -0
  77. package/dist/panel-loop.test.d.ts +2 -0
  78. package/dist/panel-loop.test.d.ts.map +1 -0
  79. package/dist/panel-loop.test.js +118 -0
  80. package/dist/panel-loop.test.js.map +1 -0
  81. package/dist/panel.d.ts +10 -0
  82. package/dist/panel.d.ts.map +1 -0
  83. package/dist/panel.js +315 -0
  84. package/dist/panel.js.map +1 -0
  85. package/dist/presets.d.ts +2 -1
  86. package/dist/presets.d.ts.map +1 -1
  87. package/dist/presets.js +10 -0
  88. package/dist/presets.js.map +1 -1
  89. package/dist/prompt.d.ts +14 -1
  90. package/dist/prompt.d.ts.map +1 -1
  91. package/dist/prompt.js +61 -15
  92. package/dist/prompt.js.map +1 -1
  93. package/dist/prompt.test.d.ts +2 -0
  94. package/dist/prompt.test.d.ts.map +1 -0
  95. package/dist/prompt.test.js +37 -0
  96. package/dist/prompt.test.js.map +1 -0
  97. package/dist/review-result.d.ts +5 -0
  98. package/dist/review-result.d.ts.map +1 -0
  99. package/dist/review-result.js +98 -0
  100. package/dist/review-result.js.map +1 -0
  101. package/dist/review-result.test.d.ts +2 -0
  102. package/dist/review-result.test.d.ts.map +1 -0
  103. package/dist/review-result.test.js +196 -0
  104. package/dist/review-result.test.js.map +1 -0
  105. package/dist/review.d.ts +10 -4
  106. package/dist/review.d.ts.map +1 -1
  107. package/dist/review.js +82 -20
  108. package/dist/review.js.map +1 -1
  109. package/dist/review.meta.test.js +2 -2
  110. package/dist/review.meta.test.js.map +1 -1
  111. package/dist/skill-protocol.test.d.ts +2 -0
  112. package/dist/skill-protocol.test.d.ts.map +1 -0
  113. package/dist/skill-protocol.test.js +35 -0
  114. package/dist/skill-protocol.test.js.map +1 -0
  115. package/dist/types.d.ts +147 -5
  116. package/dist/types.d.ts.map +1 -1
  117. package/dist/types.js +11 -0
  118. package/dist/types.js.map +1 -1
  119. package/extensions/rv-completions.test.ts +15 -0
  120. package/extensions/rv-completions.ts +7 -1
  121. package/package.json +3 -3
  122. package/resources/panel-presets.json +21 -0
  123. package/resources/system-prompt.md +11 -1
  124. package/skills/pi-review/SKILL.md +90 -12
  125. package/skills/pi-review/references/codex-tools.md +19 -6
@@ -1,6 +1,25 @@
1
1
  // Parses pi's `--mode json` event stream. That format is owned by the pi
2
2
  // binary, not a contract pi-review guarantees, so parsing degrades
3
3
  // gracefully (never throws) when lines are malformed or events are missing.
4
+ function num(value) {
5
+ const n = Number(value);
6
+ return Number.isFinite(n) && n >= 0 ? n : 0;
7
+ }
8
+ function accumulateUsage(into, usage) {
9
+ if (!usage)
10
+ return;
11
+ // input/cacheRead are prompt-scoped maxima (reported per message, not summed);
12
+ // output is additive across assistant turns.
13
+ into.input = Math.max(into.input, num(usage.input));
14
+ into.cacheRead = Math.max(into.cacheRead, num(usage.cacheRead));
15
+ into.cacheWrite = Math.max(into.cacheWrite, num(usage.cacheWrite));
16
+ into.output += num(usage.output);
17
+ into.reasoning = Math.max(into.reasoning, num(usage.reasoning));
18
+ into.totalTokens = Math.max(into.totalTokens, num(usage.totalTokens));
19
+ if (typeof usage.cost?.total === "number") {
20
+ into.costTotal = (into.costTotal ?? 0) + usage.cost.total;
21
+ }
22
+ }
4
23
  function textFromMessage(message) {
5
24
  if (!message || !Array.isArray(message.content))
6
25
  return "";
@@ -59,4 +78,170 @@ export function extractFinalText(jsonLinesText) {
59
78
  }
60
79
  return { text };
61
80
  }
81
+ /**
82
+ * Extract token usage and the response model from a pi `--mode json` event
83
+ * stream. Usage is accumulated from assistant message/turn/agent_end events.
84
+ * Degrades gracefully (returns undefined) when usage fields are absent.
85
+ */
86
+ export function extractUsage(jsonLinesText) {
87
+ const usage = {
88
+ input: 0,
89
+ output: 0,
90
+ cacheRead: 0,
91
+ cacheWrite: 0,
92
+ reasoning: 0,
93
+ totalTokens: 0,
94
+ };
95
+ let sawAnyUsage = false;
96
+ let responseModel;
97
+ for (const line of jsonLinesText.split("\n")) {
98
+ if (!line.trim())
99
+ continue;
100
+ let event;
101
+ try {
102
+ event = JSON.parse(line);
103
+ }
104
+ catch {
105
+ continue;
106
+ }
107
+ const candidates = [];
108
+ if (event?.message?.usage)
109
+ candidates.push(event.message);
110
+ else if (event?.message?.responseModel || event?.message?.model)
111
+ candidates.push(event.message);
112
+ if (event?.type === "agent_end" && Array.isArray(event.messages)) {
113
+ for (const m of event.messages) {
114
+ if (m?.usage || m?.responseModel || m?.model)
115
+ candidates.push(m);
116
+ }
117
+ }
118
+ for (const c of candidates) {
119
+ if (c.usage) {
120
+ accumulateUsage(usage, c.usage);
121
+ sawAnyUsage = true;
122
+ }
123
+ if (c.responseModel)
124
+ responseModel = c.responseModel;
125
+ else if (c.model && !responseModel)
126
+ responseModel = c.model;
127
+ }
128
+ }
129
+ if (!sawAnyUsage)
130
+ return {};
131
+ const result = { usage };
132
+ if (responseModel)
133
+ result.responseModel = responseModel;
134
+ return result;
135
+ }
136
+ /**
137
+ * Feed one chunk of stdout from pi --mode json. Splits on newlines, buffers
138
+ * partial lines, and emits text deltas + milestone notices + usage updates.
139
+ * Returns nothing; the caller reads final usage via `streamedUsage()`.
140
+ */
141
+ export class JsonEventStream {
142
+ buffer = "";
143
+ emit;
144
+ accumulate;
145
+ sawAnyUsage = false;
146
+ responseModel;
147
+ turn = 0;
148
+ inAssistantTurn = false;
149
+ constructor(emit) {
150
+ this.emit = emit;
151
+ this.accumulate = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 0 };
152
+ }
153
+ /** Feed a raw stdout chunk (may contain partial JSON lines). */
154
+ feed(chunk) {
155
+ this.buffer += chunk;
156
+ let nl;
157
+ while ((nl = this.buffer.indexOf("\n")) >= 0) {
158
+ const line = this.buffer.slice(0, nl);
159
+ this.buffer = this.buffer.slice(nl + 1);
160
+ this.processLine(line);
161
+ }
162
+ }
163
+ /** Flush any trailing partial line (call at end of stream). */
164
+ flush() {
165
+ if (this.buffer.trim())
166
+ this.processLine(this.buffer);
167
+ this.buffer = "";
168
+ }
169
+ /** Final accumulated token usage (undefined if no usage seen). */
170
+ usage() {
171
+ if (!this.sawAnyUsage)
172
+ return {};
173
+ const result = { usage: this.accumulate };
174
+ if (this.responseModel)
175
+ result.responseModel = this.responseModel;
176
+ return result;
177
+ }
178
+ processLine(raw) {
179
+ if (!raw.trim())
180
+ return;
181
+ let event;
182
+ try {
183
+ event = JSON.parse(raw);
184
+ }
185
+ catch {
186
+ return; // unparseable lines are skipped gracefully
187
+ }
188
+ this.handle(event);
189
+ }
190
+ handle(event) {
191
+ const t = event.type;
192
+ // Accumulate usage from any message/turn/agent_end carrying it.
193
+ const usageSources = [];
194
+ if (event.message?.usage)
195
+ usageSources.push(event.message);
196
+ if (event.assistantMessageEvent?.partial?.usage)
197
+ usageSources.push(event.assistantMessageEvent.partial);
198
+ if (t === "agent_end" && Array.isArray(event.messages)) {
199
+ for (const m of event.messages) {
200
+ if (m?.usage)
201
+ usageSources.push(m);
202
+ }
203
+ }
204
+ for (const s of usageSources) {
205
+ if (s.usage) {
206
+ accumulateUsage(this.accumulate, s.usage);
207
+ this.sawAnyUsage = true;
208
+ }
209
+ if (s.responseModel)
210
+ this.responseModel = s.responseModel;
211
+ else if (s.model && !this.responseModel)
212
+ this.responseModel = s.model;
213
+ }
214
+ // Text deltas -> forward to the human-readable terminal.
215
+ if (t === "message_update" && event.assistantMessageEvent?.type === "text_delta") {
216
+ const delta = event.assistantMessageEvent.delta;
217
+ if (typeof delta === "string" && delta)
218
+ this.emit.onText(delta);
219
+ }
220
+ // Semantic milestones (B).
221
+ switch (t) {
222
+ case "agent_start":
223
+ this.emit.onMilestone("pi-review: review started\n");
224
+ break;
225
+ case "turn_start":
226
+ this.turn += 1;
227
+ this.inAssistantTurn = false;
228
+ if (this.turn > 1)
229
+ this.emit.onMilestone(`pi-review: turn ${this.turn}\n`);
230
+ break;
231
+ case "message_start":
232
+ if (event.message?.role === "assistant")
233
+ this.inAssistantTurn = true;
234
+ break;
235
+ case "tool_execution_start":
236
+ this.emit.onMilestone(`pi-review: tool ${event.toolName ?? "unknown"} started\n`);
237
+ break;
238
+ case "tool_execution_end":
239
+ this.emit.onMilestone(`pi-review: tool ${event.toolName ?? "unknown"} finished\n`);
240
+ break;
241
+ case "agent_end":
242
+ this.emit.onMilestone("pi-review: review finished\n");
243
+ break;
244
+ }
245
+ }
246
+ }
62
247
  //# sourceMappingURL=json-events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-events.js","sourceRoot":"","sources":["../src/json-events.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,mEAAmE;AACnE,4EAA4E;AAe5E,SAAS,eAAe,CAAC,OAAyC;IAChE,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3D,OAAO,OAAO,CAAC,OAAO;SACnB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;SAC3E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,OAA6B;IAChD,OAAO,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,aAAqB;IACpD,IAAI,oBAAsD,CAAC;IAC3D,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAE3B,IAAI,KAA2F,CAAC;QAChG,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,IAAI,KAAK,EAAE,OAAO,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC;YACzC,oBAAoB,GAAG,KAAK,CAAC,OAAO,CAAC;QACvC,CAAC;QAED,IAAI,KAAK,EAAE,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjE,WAAW,GAAG,IAAI,CAAC;YACnB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAClC,IAAI,OAAO,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC;oBAClC,oBAAoB,GAAG,OAAO,CAAC;oBAC/B,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,kDAAkD,EAAE,CAAC;IACjF,CAAC;IAED,IAAI,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACtC,OAAO;YACL,IAAI,EAAE,eAAe,CAAC,oBAAoB,CAAC;YAC3C,KAAK,EACH,oBAAoB,CAAC,YAAY;gBACjC,wCAAwC,oBAAoB,CAAC,UAAU,EAAE;YAC3E,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,CAAC,oBAAoB,CAAC,CAAC;IACnD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC;IAC5E,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,8EAA8E,EAAE,CAAC;IACzG,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"json-events.js","sourceRoot":"","sources":["../src/json-events.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { test } from "node:test";
3
- import { extractFinalText } from "./json-events.js";
3
+ import { extractFinalText, extractUsage, JsonEventStream } from "./json-events.js";
4
4
  function lines(...events) {
5
5
  return events.map((e) => JSON.stringify(e)).join("\n");
6
6
  }
@@ -85,4 +85,67 @@ test("extractFinalText uses the last agent_end when the child retries", () => {
85
85
  assert.equal(result.text, "final attempt");
86
86
  assert.equal(result.fatal, undefined);
87
87
  });
88
+ test("extractUsage accumulates tokens from message_end and agent_end", () => {
89
+ const input = lines({ type: "session", id: "s1" }, { type: "message_end", message: { role: "assistant", usage: { input: 44, output: 3, cacheRead: 17984, cacheWrite: 0, reasoning: 0, totalTokens: 18031, cost: { total: 0.025 } }, model: "hf:zai-org/GLM-5.2" } }, { type: "agent_end", messages: [{ role: "assistant", responseModel: "zai-org/GLM-5.2" }] });
90
+ const result = extractUsage(input);
91
+ assert.ok(result.usage);
92
+ assert.equal(result.usage.input, 44);
93
+ assert.equal(result.usage.output, 3);
94
+ assert.equal(result.usage.cacheRead, 17984);
95
+ assert.equal(result.usage.totalTokens, 18031);
96
+ assert.equal(result.usage.costTotal, 0.025);
97
+ assert.equal(result.responseModel, "zai-org/GLM-5.2");
98
+ });
99
+ test("extractUsage returns undefined when no usage events exist", () => {
100
+ const input = lines({ type: "session", id: "s1" }, { type: "agent_end", messages: [{ role: "assistant" }] });
101
+ const result = extractUsage(input);
102
+ assert.equal(result.usage, undefined);
103
+ assert.equal(result.responseModel, undefined);
104
+ });
105
+ test("extractUsage sums output across multiple assistant turns", () => {
106
+ const input = lines({ type: "message_end", message: { role: "assistant", usage: { input: 100, output: 50, totalTokens: 150 } } }, { type: "message_end", message: { role: "assistant", usage: { input: 100, output: 30, totalTokens: 130 } } });
107
+ const result = extractUsage(input);
108
+ assert.equal(result.usage.output, 80);
109
+ assert.equal(result.usage.input, 100);
110
+ });
111
+ test("JsonEventStream forwards text deltas and emits milestones", () => {
112
+ const texts = [];
113
+ const milestones = [];
114
+ const stream = new JsonEventStream({ onText: (c) => texts.push(c), onMilestone: (l) => milestones.push(l) });
115
+ const input = lines({ type: "agent_start" }, { type: "turn_start" }, { type: "message_update", assistantMessageEvent: { type: "text_delta", delta: "Hello ", partial: { role: "assistant" } } }, { type: "message_update", assistantMessageEvent: { type: "text_delta", delta: "world", partial: { role: "assistant" } } }, { type: "agent_end", messages: [{ role: "assistant", content: [{ type: "text", text: "Hello world" }], responseModel: "fake/model" }] });
116
+ stream.feed(input);
117
+ stream.flush();
118
+ assert.equal(texts.join(""), "Hello world");
119
+ assert.ok(milestones.some((m) => /review started/.test(m)));
120
+ assert.ok(milestones.some((m) => /review finished/.test(m)));
121
+ const usage = stream.usage();
122
+ assert.ok(usage.responseModel === "fake/model" || usage.responseModel === undefined);
123
+ });
124
+ test("JsonEventStream accumulates token usage from streamed events", () => {
125
+ const stream = new JsonEventStream({ onText: () => { }, onMilestone: () => { } });
126
+ stream.feed(lines({ type: "message_end", message: { role: "assistant", usage: { input: 200, output: 50, cacheRead: 100, cacheWrite: 0, reasoning: 10, totalTokens: 260 } } }));
127
+ stream.flush();
128
+ const usage = stream.usage().usage;
129
+ assert.ok(usage);
130
+ assert.equal(usage.input, 200);
131
+ assert.equal(usage.output, 50);
132
+ assert.equal(usage.cacheRead, 100);
133
+ assert.equal(usage.reasoning, 10);
134
+ });
135
+ test("JsonEventStream handles partial lines across chunks", () => {
136
+ const texts = [];
137
+ const stream = new JsonEventStream({ onText: (c) => texts.push(c), onMilestone: () => { } });
138
+ // Feed a partial line, then complete it.
139
+ stream.feed('{"type":"message_update","assistantMessageEvent":{"type":"text_delta","delta":"par');
140
+ stream.feed('tial","partial":{"role":"assistant"}}}\n');
141
+ stream.flush();
142
+ assert.equal(texts.join(""), "partial");
143
+ });
144
+ test("JsonEventStream skips unparseable lines without throwing", () => {
145
+ const stream = new JsonEventStream({ onText: () => { }, onMilestone: () => { } });
146
+ stream.feed("not json\n");
147
+ stream.feed('{"type":"message_update","assistantMessageEvent":{"type":"text_delta","delta":"ok","partial":{"role":"assistant"}}}\n');
148
+ stream.flush();
149
+ assert.equal(stream.usage().usage, undefined);
150
+ });
88
151
  //# sourceMappingURL=json-events.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-events.test.js","sourceRoot":"","sources":["../src/json-events.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"json-events.test.js","sourceRoot":"","sources":["../src/json-events.test.ts"],"names":[],"mappings":"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"}
package/dist/loop.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type { ReviewRunResult, ReviewStatus, Verdict } from "./types.js";
2
+ export type LoopStopReason = "clean" | "budget_exhausted" | "needs_human" | "blocked";
3
+ export interface LoopRoundPanelSummary {
4
+ configuredReviewers: number;
5
+ successfulReviewers: number;
6
+ confirmedCount: number;
7
+ advisoryCount: number;
8
+ consensusPolicy: string;
9
+ consensusThreshold: number;
10
+ panelHealth: string;
11
+ }
12
+ export interface LoopRoundSummary {
13
+ index: number;
14
+ status: ReviewStatus;
15
+ verdict: Verdict;
16
+ durationMs: number;
17
+ findingCount: number;
18
+ actionableCount: number;
19
+ /** Thinking level requested for this round, if any. */
20
+ thinking?: string;
21
+ /** Token usage for this round, when available. */
22
+ usage?: import("./types.js").TokenUsage;
23
+ /** Present when the round evaluated a panel. */
24
+ panel?: LoopRoundPanelSummary;
25
+ }
26
+ export interface LoopReviewResult {
27
+ rounds: LoopRoundSummary[];
28
+ finalStatus: ReviewStatus;
29
+ stopReason: LoopStopReason;
30
+ exitCode: number;
31
+ }
32
+ export type RunOneReview = (roundIndex: number) => Promise<ReviewRunResult>;
33
+ export declare function formatLoopSummary(result: LoopReviewResult): string;
34
+ /** Runs isolated review rounds through an injected single-run adapter. */
35
+ export declare function runReviewLoop(maxRounds: number, runOneReview: RunOneReview): Promise<LoopReviewResult>;
36
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA+B,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEtG,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,kBAAkB,GAAG,aAAa,GAAG,SAAS,CAAC;AAEtF,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,YAAY,EAAE,UAAU,CAAC;IACxC,gDAAgD;IAChD,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,YAAY,CAAC;IAC1B,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAM5E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAmBlE;AAED,0EAA0E;AAC1E,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAgD3B"}
package/dist/loop.js ADDED
@@ -0,0 +1,73 @@
1
+ import { formatDurationMs, formatUsage } from "./meta-footer.js";
2
+ import { reviewExitCode } from "./review-result.js";
3
+ function displayEnum(value) {
4
+ return value.replaceAll("_", " ").toUpperCase();
5
+ }
6
+ export function formatLoopSummary(result) {
7
+ const lines = ["── pi-review loop " + "─".repeat(23)];
8
+ for (const round of result.rounds) {
9
+ const tokenBit = round.usage ? ` | ${formatUsage(round.usage)}` : "";
10
+ const thinkBit = round.thinking ? ` | think:${round.thinking}` : "";
11
+ if (round.panel) {
12
+ lines.push(` Round ${round.index} ${displayEnum(round.status)} | panel ${round.panel.successfulReviewers}/${round.panel.configuredReviewers} | ${round.panel.confirmedCount} confirmed / ${round.panel.advisoryCount} advisory | ${round.panel.consensusPolicy}≥${round.panel.consensusThreshold} | ${displayEnum(round.panel.panelHealth)}${thinkBit}${tokenBit} | ${formatDurationMs(round.durationMs)}`);
13
+ }
14
+ else {
15
+ lines.push(` Round ${round.index} ${displayEnum(round.status)} | ${displayEnum(round.verdict)} | ${round.actionableCount} actionable / ${round.findingCount} total${thinkBit}${tokenBit} | ${formatDurationMs(round.durationMs)}`);
16
+ }
17
+ }
18
+ lines.push(` Stop ${result.stopReason}`);
19
+ lines.push(` Exit ${result.exitCode}`);
20
+ lines.push("─".repeat(42));
21
+ return lines.join("\n");
22
+ }
23
+ /** Runs isolated review rounds through an injected single-run adapter. */
24
+ export async function runReviewLoop(maxRounds, runOneReview) {
25
+ if (!Number.isSafeInteger(maxRounds) || maxRounds < 1) {
26
+ throw new RangeError("maxRounds must be a positive integer");
27
+ }
28
+ const rounds = [];
29
+ for (let index = 1; index <= maxRounds; index += 1) {
30
+ const run = await runOneReview(index);
31
+ const { meta } = run;
32
+ const panel = isPanelMeta(meta)
33
+ ? {
34
+ configuredReviewers: meta.configuredReviewers,
35
+ successfulReviewers: meta.successfulReviewers,
36
+ confirmedCount: meta.confirmedClusters.length,
37
+ advisoryCount: meta.advisories.length,
38
+ consensusPolicy: meta.consensusPolicy,
39
+ consensusThreshold: meta.consensusThreshold,
40
+ panelHealth: meta.panelHealth,
41
+ }
42
+ : undefined;
43
+ rounds.push({
44
+ index,
45
+ status: meta.status,
46
+ verdict: meta.verdict,
47
+ durationMs: meta.durationMs,
48
+ findingCount: meta.findings.length,
49
+ actionableCount: meta.actionableCount,
50
+ ...(meta.thinking ? { thinking: meta.thinking } : {}),
51
+ ...(meta.usage ? { usage: meta.usage } : {}),
52
+ ...(panel ? { panel } : {}),
53
+ });
54
+ if (meta.status === "clean" || meta.status === "needs_human" || meta.status === "blocked") {
55
+ return {
56
+ rounds,
57
+ finalStatus: meta.status,
58
+ stopReason: meta.status,
59
+ exitCode: reviewExitCode(meta.status),
60
+ };
61
+ }
62
+ }
63
+ return {
64
+ rounds,
65
+ finalStatus: "has_findings",
66
+ stopReason: "budget_exhausted",
67
+ exitCode: reviewExitCode("has_findings"),
68
+ };
69
+ }
70
+ function isPanelMeta(meta) {
71
+ return meta.strategy === "panel";
72
+ }
73
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=loop.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.test.d.ts","sourceRoot":"","sources":["../src/loop.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { formatLoopSummary, runReviewLoop } from "./loop.js";
4
+ function meta(status, verdict, durationMs = 100) {
5
+ return {
6
+ reviewMode: "code",
7
+ verdict,
8
+ verdictSource: "parsed",
9
+ status,
10
+ findings: status === "has_findings"
11
+ ? [{ id: "F1", summary: "Fix the gate", actionable: true }]
12
+ : [],
13
+ actionableCount: status === "has_findings" ? 1 : 0,
14
+ durationMs,
15
+ model: "provider/model",
16
+ };
17
+ }
18
+ test("loop stops after a clean first round", async () => {
19
+ let calls = 0;
20
+ const result = await runReviewLoop(3, async () => {
21
+ calls += 1;
22
+ return { meta: meta("clean", "approve"), exitCode: 0 };
23
+ });
24
+ assert.equal(calls, 1);
25
+ assert.equal(result.stopReason, "clean");
26
+ assert.equal(result.exitCode, 0);
27
+ assert.deepEqual(result.rounds.map((round) => round.index), [1]);
28
+ });
29
+ test("loop stops when a later round becomes clean", async () => {
30
+ const sequence = [
31
+ { meta: meta("has_findings", "request_changes", 120), exitCode: 1 },
32
+ { meta: meta("clean", "approve", 80), exitCode: 0 },
33
+ ];
34
+ const result = await runReviewLoop(3, async (roundIndex) => sequence[roundIndex - 1]);
35
+ assert.equal(result.stopReason, "clean");
36
+ assert.equal(result.exitCode, 0);
37
+ assert.deepEqual(result.rounds.map((round) => round.status), ["has_findings", "clean"]);
38
+ assert.deepEqual(result.rounds.map((round) => round.durationMs), [120, 80]);
39
+ });
40
+ test("loop exhausts the budget while actionable findings remain", async () => {
41
+ let calls = 0;
42
+ const result = await runReviewLoop(2, async () => {
43
+ calls += 1;
44
+ return { meta: meta("has_findings", "request_changes"), exitCode: 1 };
45
+ });
46
+ assert.equal(calls, 2);
47
+ assert.equal(result.stopReason, "budget_exhausted");
48
+ assert.equal(result.finalStatus, "has_findings");
49
+ assert.equal(result.exitCode, 1);
50
+ assert.equal(result.rounds.length, 2);
51
+ });
52
+ test("loop escalates blocked and needs-human outcomes immediately", async () => {
53
+ const scenarios = [
54
+ { status: "blocked", verdict: "blocked", exitCode: 4 },
55
+ { status: "needs_human", verdict: "needs_clarification", exitCode: 3 },
56
+ ];
57
+ for (const scenario of scenarios) {
58
+ let calls = 0;
59
+ const result = await runReviewLoop(3, async () => {
60
+ calls += 1;
61
+ return {
62
+ meta: meta(scenario.status, scenario.verdict),
63
+ exitCode: scenario.exitCode,
64
+ };
65
+ });
66
+ assert.equal(calls, 1);
67
+ assert.equal(result.stopReason, scenario.status);
68
+ assert.equal(result.exitCode, scenario.exitCode);
69
+ }
70
+ });
71
+ test("loop summary reports each round and final outcome", async () => {
72
+ const sequence = [
73
+ { meta: meta("has_findings", "request_changes", 1_200), exitCode: 1 },
74
+ { meta: meta("clean", "approve", 800), exitCode: 0 },
75
+ ];
76
+ const result = await runReviewLoop(3, async (roundIndex) => sequence[roundIndex - 1]);
77
+ const summary = formatLoopSummary(result);
78
+ assert.match(summary, /pi-review loop/);
79
+ assert.match(summary, /Round 1.*HAS FINDINGS.*REQUEST CHANGES.*1\.2s/);
80
+ assert.match(summary, /Round 2.*CLEAN.*APPROVE.*800ms/);
81
+ assert.match(summary, /Stop.*clean/);
82
+ });
83
+ //# sourceMappingURL=loop.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.test.js","sourceRoot":"","sources":["../src/loop.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { type SourceFinding } from "./types.js";
2
+ /** Result of matching a set of source findings into clusters. */
3
+ export interface MatchResult {
4
+ /**
5
+ * Each group is a list of source finding IDs that represent the same
6
+ * underlying issue. Every input source ID must appear in exactly one group.
7
+ */
8
+ groups: string[][];
9
+ /** Matcher-detected problems (invented IDs, missing IDs, malformed output). */
10
+ errors: string[];
11
+ /** True when a semantic adjudicator was actually consulted. */
12
+ adjudicationUsed: boolean;
13
+ }
14
+ /** A finding matcher clusters source findings into groups. */
15
+ export interface FindingMatcher {
16
+ match(findings: SourceFinding[]): MatchResult | Promise<MatchResult>;
17
+ }
18
+ /** Normalize a path anchor so reviewers that phrase paths slightly differently still match. */
19
+ export declare function normalizePath(value: string | undefined): string;
20
+ /** Normalize a finding summary for deterministic comparison. */
21
+ export declare function normalizeSummary(value: string | undefined): string;
22
+ /** Deterministic cluster key: shared path anchor plus normalized summary. */
23
+ export declare function deterministicKey(finding: {
24
+ path?: string;
25
+ summary: string;
26
+ }): string;
27
+ /**
28
+ * Phase-one matcher: clusters findings that share a path anchor AND a
29
+ * normalized summary. Findings with different paths never merge here; findings
30
+ * with the same path but different wording form separate clusters and become
31
+ * candidates for semantic adjudication.
32
+ */
33
+ export declare class DeterministicMatcher implements FindingMatcher {
34
+ match(findings: SourceFinding[]): MatchResult;
35
+ }
36
+ /** A candidate group sharing a path anchor but differing in wording. */
37
+ export interface AdjudicationCandidate {
38
+ anchorPath: string;
39
+ findings: SourceFinding[];
40
+ }
41
+ /** Request sent to a semantic adjudicator. */
42
+ export interface AdjudicationRequest {
43
+ candidates: AdjudicationCandidate[];
44
+ }
45
+ /** A proposed merge of source finding IDs into one cluster. */
46
+ export interface AdjudicationMerge {
47
+ sourceFindingIds: string[];
48
+ confidence: number;
49
+ }
50
+ /** Response from a semantic adjudicator. */
51
+ export interface AdjudicationResponse {
52
+ merges: AdjudicationMerge[];
53
+ errors?: string[];
54
+ }
55
+ /**
56
+ * A constrained semantic adjudicator. It receives structured findings only and
57
+ * returns proposed merges with confidence. It may not invent source IDs, drop
58
+ * source IDs, claim new evidence, or act as another reviewer.
59
+ */
60
+ export interface SemanticAdjudicator {
61
+ adjudicate(request: AdjudicationRequest): AdjudicationResponse | Promise<AdjudicationResponse>;
62
+ }
63
+ /**
64
+ * Phase-two matcher: deterministic first, then an injected adjudicator may
65
+ * merge ambiguous same-path candidates. Low-confidence matches are not merged.
66
+ * Invented or missing source IDs are reported as errors and never merged.
67
+ */
68
+ export declare class SemanticMatcher implements FindingMatcher {
69
+ private readonly adjudicator;
70
+ private readonly deterministic;
71
+ constructor(adjudicator: SemanticAdjudicator);
72
+ match(findings: SourceFinding[]): Promise<MatchResult>;
73
+ }
74
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"AAQA,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAErF,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+DAA+D;IAC/D,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACtE;AAED,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAO/D;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQlE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEpF;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,WAAW;CAoB9C;AAED,wEAAwE;AACxE,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,qBAAqB,EAAE,CAAC;CACrC;AAED,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAChG;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,cAAc;IAExC,OAAO,CAAC,QAAQ,CAAC,WAAW;IADxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;gBAC/B,WAAW,EAAE,mBAAmB;IAEvD,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;CAgI7D"}