@zephyrdeng/pi-review 0.6.2 → 0.7.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 (163) hide show
  1. package/README.md +126 -14
  2. package/README.zh-CN.md +79 -4
  3. package/dist/args.d.ts +8 -0
  4. package/dist/args.d.ts.map +1 -1
  5. package/dist/args.js +167 -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 +125 -0
  10. package/dist/args.test.js.map +1 -0
  11. package/dist/child-process.d.ts +3 -0
  12. package/dist/child-process.d.ts.map +1 -1
  13. package/dist/child-process.js +26 -0
  14. package/dist/child-process.js.map +1 -1
  15. package/dist/child-process.test.js +13 -0
  16. package/dist/child-process.test.js.map +1 -1
  17. package/dist/cli-exit.test.d.ts +2 -0
  18. package/dist/cli-exit.test.d.ts.map +1 -0
  19. package/dist/cli-exit.test.js +84 -0
  20. package/dist/cli-exit.test.js.map +1 -0
  21. package/dist/cli.js +16 -2
  22. package/dist/cli.js.map +1 -1
  23. package/dist/config.d.ts +1 -0
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +1 -0
  26. package/dist/config.js.map +1 -1
  27. package/dist/extensions/review.d.ts +2 -0
  28. package/dist/extensions/review.js +22 -0
  29. package/dist/extensions/rv-prompts.d.ts +19 -0
  30. package/dist/extensions/rv-prompts.js +132 -0
  31. package/dist/index.d.ts +22 -7
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +15 -6
  34. package/dist/index.js.map +1 -1
  35. package/dist/json-events.d.ts +71 -0
  36. package/dist/json-events.d.ts.map +1 -1
  37. package/dist/json-events.js +250 -0
  38. package/dist/json-events.js.map +1 -1
  39. package/dist/json-events.test.js +217 -1
  40. package/dist/json-events.test.js.map +1 -1
  41. package/dist/loop.d.ts +36 -0
  42. package/dist/loop.d.ts.map +1 -0
  43. package/dist/loop.js +73 -0
  44. package/dist/loop.js.map +1 -0
  45. package/dist/loop.test.d.ts +2 -0
  46. package/dist/loop.test.d.ts.map +1 -0
  47. package/dist/loop.test.js +83 -0
  48. package/dist/loop.test.js.map +1 -0
  49. package/dist/matcher.d.ts +74 -0
  50. package/dist/matcher.d.ts.map +1 -0
  51. package/dist/matcher.js +202 -0
  52. package/dist/matcher.js.map +1 -0
  53. package/dist/matcher.test.d.ts +2 -0
  54. package/dist/matcher.test.d.ts.map +1 -0
  55. package/dist/matcher.test.js +161 -0
  56. package/dist/matcher.test.js.map +1 -0
  57. package/dist/meta-footer.d.ts +15 -1
  58. package/dist/meta-footer.d.ts.map +1 -1
  59. package/dist/meta-footer.js +108 -0
  60. package/dist/meta-footer.js.map +1 -1
  61. package/dist/meta-footer.test.js +43 -1
  62. package/dist/meta-footer.test.js.map +1 -1
  63. package/dist/panel-aggregate.d.ts +18 -0
  64. package/dist/panel-aggregate.d.ts.map +1 -0
  65. package/dist/panel-aggregate.js +247 -0
  66. package/dist/panel-aggregate.js.map +1 -0
  67. package/dist/panel-aggregate.test.d.ts +2 -0
  68. package/dist/panel-aggregate.test.d.ts.map +1 -0
  69. package/dist/panel-aggregate.test.js +461 -0
  70. package/dist/panel-aggregate.test.js.map +1 -0
  71. package/dist/panel-cancellation.test.d.ts +2 -0
  72. package/dist/panel-cancellation.test.d.ts.map +1 -0
  73. package/dist/panel-cancellation.test.js +24 -0
  74. package/dist/panel-cancellation.test.js.map +1 -0
  75. package/dist/panel-cli.test.d.ts +2 -0
  76. package/dist/panel-cli.test.d.ts.map +1 -0
  77. package/dist/panel-cli.test.js +239 -0
  78. package/dist/panel-cli.test.js.map +1 -0
  79. package/dist/panel-config.d.ts +19 -0
  80. package/dist/panel-config.d.ts.map +1 -0
  81. package/dist/panel-config.js +115 -0
  82. package/dist/panel-config.js.map +1 -0
  83. package/dist/panel-config.test.d.ts +2 -0
  84. package/dist/panel-config.test.d.ts.map +1 -0
  85. package/dist/panel-config.test.js +94 -0
  86. package/dist/panel-config.test.js.map +1 -0
  87. package/dist/panel-loop.test.d.ts +2 -0
  88. package/dist/panel-loop.test.d.ts.map +1 -0
  89. package/dist/panel-loop.test.js +118 -0
  90. package/dist/panel-loop.test.js.map +1 -0
  91. package/dist/panel-tools.test.d.ts +2 -0
  92. package/dist/panel-tools.test.d.ts.map +1 -0
  93. package/dist/panel-tools.test.js +12 -0
  94. package/dist/panel-tools.test.js.map +1 -0
  95. package/dist/panel-usage.d.ts +6 -0
  96. package/dist/panel-usage.d.ts.map +1 -0
  97. package/dist/panel-usage.js +21 -0
  98. package/dist/panel-usage.js.map +1 -0
  99. package/dist/panel-view.d.ts +41 -0
  100. package/dist/panel-view.d.ts.map +1 -0
  101. package/dist/panel-view.js +90 -0
  102. package/dist/panel-view.js.map +1 -0
  103. package/dist/panel-view.test.d.ts +2 -0
  104. package/dist/panel-view.test.d.ts.map +1 -0
  105. package/dist/panel-view.test.js +45 -0
  106. package/dist/panel-view.test.js.map +1 -0
  107. package/dist/panel.d.ts +20 -0
  108. package/dist/panel.d.ts.map +1 -0
  109. package/dist/panel.js +393 -0
  110. package/dist/panel.js.map +1 -0
  111. package/dist/presets.d.ts +2 -1
  112. package/dist/presets.d.ts.map +1 -1
  113. package/dist/presets.js +10 -0
  114. package/dist/presets.js.map +1 -1
  115. package/dist/prompt.d.ts +14 -1
  116. package/dist/prompt.d.ts.map +1 -1
  117. package/dist/prompt.js +61 -15
  118. package/dist/prompt.js.map +1 -1
  119. package/dist/prompt.test.d.ts +2 -0
  120. package/dist/prompt.test.d.ts.map +1 -0
  121. package/dist/prompt.test.js +37 -0
  122. package/dist/prompt.test.js.map +1 -0
  123. package/dist/review-events.d.ts +70 -0
  124. package/dist/review-events.d.ts.map +1 -0
  125. package/dist/review-events.js +52 -0
  126. package/dist/review-events.js.map +1 -0
  127. package/dist/review-events.test.d.ts +2 -0
  128. package/dist/review-events.test.d.ts.map +1 -0
  129. package/dist/review-events.test.js +47 -0
  130. package/dist/review-events.test.js.map +1 -0
  131. package/dist/review-result.d.ts +5 -0
  132. package/dist/review-result.d.ts.map +1 -0
  133. package/dist/review-result.js +98 -0
  134. package/dist/review-result.js.map +1 -0
  135. package/dist/review-result.test.d.ts +2 -0
  136. package/dist/review-result.test.d.ts.map +1 -0
  137. package/dist/review-result.test.js +196 -0
  138. package/dist/review-result.test.js.map +1 -0
  139. package/dist/review.d.ts +10 -4
  140. package/dist/review.d.ts.map +1 -1
  141. package/dist/review.js +82 -20
  142. package/dist/review.js.map +1 -1
  143. package/dist/review.meta.test.js +2 -2
  144. package/dist/review.meta.test.js.map +1 -1
  145. package/dist/skill-protocol.test.d.ts +2 -0
  146. package/dist/skill-protocol.test.d.ts.map +1 -0
  147. package/dist/skill-protocol.test.js +35 -0
  148. package/dist/skill-protocol.test.js.map +1 -0
  149. package/dist/types.d.ts +151 -5
  150. package/dist/types.d.ts.map +1 -1
  151. package/dist/types.js +13 -0
  152. package/dist/types.js.map +1 -1
  153. package/extensions/panel-tool.test.ts +30 -0
  154. package/extensions/panel-tool.ts +169 -0
  155. package/extensions/review.ts +3 -1
  156. package/extensions/rv-prompts.test.ts +8 -1
  157. package/extensions/rv-prompts.ts +6 -4
  158. package/package.json +14 -5
  159. package/resources/panel-presets.json +21 -0
  160. package/resources/review-presets.json +2 -2
  161. package/resources/system-prompt.md +11 -1
  162. package/skills/pi-review/SKILL.md +93 -15
  163. package/skills/pi-review/references/codex-tools.md +19 -6
@@ -0,0 +1,118 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { formatLoopSummary, runReviewLoop } from "./loop.js";
4
+ function cluster(summary, opts = {}) {
5
+ const support = opts.support ?? 1;
6
+ return {
7
+ id: "C1",
8
+ summary,
9
+ confirmed: opts.confirmed ?? false,
10
+ supportCount: support,
11
+ actionableSupportCount: opts.actionableSupport ?? support,
12
+ supportingReviewerIds: opts.reviewers ?? ["r1"],
13
+ sourceFindingIds: ["r1#F1"],
14
+ };
15
+ }
16
+ function panelMeta(status, opts = {}) {
17
+ const confirmed = opts.confirmed ?? [];
18
+ const advisories = opts.advisories ?? [];
19
+ const verdict = status === "clean" ? "approve" : status === "has_findings" ? "request_changes" : status === "needs_human" ? "needs_clarification" : "blocked";
20
+ return {
21
+ strategy: "panel",
22
+ reviewMode: "code",
23
+ verdict,
24
+ verdictSource: "parsed",
25
+ status,
26
+ findings: confirmed.map((c) => ({ id: c.id, summary: c.summary, actionable: true })),
27
+ actionableCount: confirmed.length,
28
+ durationMs: opts.durationMs ?? 100,
29
+ model: null,
30
+ configuredReviewers: opts.configured ?? 3,
31
+ successfulReviewers: opts.successful ?? opts.configured ?? 3,
32
+ consensusPolicy: (opts.policy ?? "quorum"),
33
+ consensusThreshold: opts.threshold ?? 2,
34
+ panelHealth: (opts.health ?? (status === "blocked" ? "blocked" : status === "needs_human" ? "needs_human" : "healthy")),
35
+ confirmedClusters: confirmed,
36
+ advisories,
37
+ reviewers: [],
38
+ adjudicationUsed: false,
39
+ };
40
+ }
41
+ const confirmedFinding = [cluster("Off-by-one", { confirmed: true, support: 2, actionableSupport: 2, reviewers: ["r1", "r2"] })];
42
+ test("panel loop stops after a clean first panel", async () => {
43
+ let calls = 0;
44
+ const result = await runReviewLoop(3, async () => {
45
+ calls += 1;
46
+ return { meta: panelMeta("clean"), exitCode: 0 };
47
+ });
48
+ assert.equal(calls, 1);
49
+ assert.equal(result.stopReason, "clean");
50
+ assert.equal(result.exitCode, 0);
51
+ assert.equal(result.rounds[0].panel?.confirmedCount, 0);
52
+ });
53
+ test("panel loop stops when a later panel becomes clean", async () => {
54
+ const sequence = [
55
+ { meta: panelMeta("has_findings", { confirmed: confirmedFinding }), exitCode: 1 },
56
+ { meta: panelMeta("clean"), exitCode: 0 },
57
+ ];
58
+ const result = await runReviewLoop(3, async (i) => sequence[i - 1]);
59
+ assert.equal(result.stopReason, "clean");
60
+ assert.deepEqual(result.rounds.map((r) => r.status), ["has_findings", "clean"]);
61
+ assert.equal(result.rounds[0].panel?.confirmedCount, 1);
62
+ assert.equal(result.rounds[1].panel?.confirmedCount, 0);
63
+ });
64
+ test("panel loop exhausts the budget while confirmed findings remain", async () => {
65
+ let calls = 0;
66
+ const result = await runReviewLoop(2, async () => {
67
+ calls += 1;
68
+ return { meta: panelMeta("has_findings", { confirmed: confirmedFinding }), exitCode: 1 };
69
+ });
70
+ assert.equal(calls, 2);
71
+ assert.equal(result.stopReason, "budget_exhausted");
72
+ assert.equal(result.exitCode, 1);
73
+ });
74
+ test("panel loop escalates blocked and needs-human panels immediately", async () => {
75
+ for (const scenario of [
76
+ { status: "blocked", exit: 4, health: "blocked" },
77
+ { status: "needs_human", exit: 3, health: "needs_human" },
78
+ ]) {
79
+ let calls = 0;
80
+ const result = await runReviewLoop(3, async () => {
81
+ calls += 1;
82
+ return { meta: panelMeta(scenario.status, { health: scenario.health }), exitCode: scenario.exit };
83
+ });
84
+ assert.equal(calls, 1);
85
+ assert.equal(result.stopReason, scenario.status);
86
+ assert.equal(result.exitCode, scenario.exit);
87
+ }
88
+ });
89
+ test("panel loop execution count: reviewer runs scale with executed rounds and early stop reduces runs", async () => {
90
+ const reviewerCount = 3;
91
+ let calls = 0;
92
+ await runReviewLoop(5, async () => {
93
+ calls += 1;
94
+ return { meta: panelMeta("clean"), exitCode: 0 };
95
+ });
96
+ assert.equal(calls, 1);
97
+ assert.equal(calls * reviewerCount, reviewerCount);
98
+ let budgetCalls = 0;
99
+ await runReviewLoop(2, async () => {
100
+ budgetCalls += 1;
101
+ return { meta: panelMeta("has_findings", { confirmed: confirmedFinding, configured: reviewerCount }), exitCode: 1 };
102
+ });
103
+ assert.equal(budgetCalls, 2);
104
+ assert.equal(budgetCalls * reviewerCount, 6);
105
+ });
106
+ test("panel loop summary reports per-round support and consensus details", async () => {
107
+ const sequence = [
108
+ { meta: panelMeta("has_findings", { confirmed: confirmedFinding, advisories: [cluster("Typo")], configured: 3, successful: 3, policy: "quorum", threshold: 2, health: "healthy", durationMs: 1200 }), exitCode: 1 },
109
+ { meta: panelMeta("clean", { configured: 3, successful: 3, policy: "quorum", threshold: 2, durationMs: 800 }), exitCode: 0 },
110
+ ];
111
+ const result = await runReviewLoop(3, async (i) => sequence[i - 1]);
112
+ const summary = formatLoopSummary(result);
113
+ assert.match(summary, /pi-review loop/);
114
+ assert.match(summary, /Round 1.*panel 3\/3.*1 confirmed \/ 1 advisory.*quorum≥2.*HEALTHY/);
115
+ assert.match(summary, /Round 2.*panel 3\/3.*0 confirmed \/ 0 advisory/);
116
+ assert.match(summary, /Stop.*clean/);
117
+ });
118
+ //# sourceMappingURL=panel-loop.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-loop.test.js","sourceRoot":"","sources":["../src/panel-loop.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=panel-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-tools.test.d.ts","sourceRoot":"","sources":["../src/panel-tools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { PANEL_READ_ONLY_TOOLS, resolvePanelReviewerTools } from "./panel.js";
4
+ test("panel reviewers default to the hard read-only allowlist", () => {
5
+ assert.equal(resolvePanelReviewerTools(undefined), PANEL_READ_ONLY_TOOLS.join(","));
6
+ });
7
+ test("panel reviewers reject shell and mutation-capable tools at the boundary", () => {
8
+ for (const tool of ["bash", "edit", "write", "apply_patch"]) {
9
+ assert.throws(() => resolvePanelReviewerTools(`read,${tool}`), /panel reviewers only allow/);
10
+ }
11
+ });
12
+ //# sourceMappingURL=panel-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-tools.test.js","sourceRoot":"","sources":["../src/panel-tools.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE9E,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACnE,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yEAAyE,EAAE,GAAG,EAAE;IACnF,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { TokenUsage } from "./types.js";
2
+ /**
3
+ * Combine final usage from independent reviewer sessions.
4
+ */
5
+ export declare function sumPanelUsage(usages: (TokenUsage | undefined)[]): TokenUsage | undefined;
6
+ //# sourceMappingURL=panel-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-usage.d.ts","sourceRoot":"","sources":["../src/panel-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,GAAG,UAAU,GAAG,SAAS,CAcxF"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Combine final usage from independent reviewer sessions.
3
+ */
4
+ export function sumPanelUsage(usages) {
5
+ const present = usages.filter((usage) => Boolean(usage));
6
+ if (present.length === 0)
7
+ return undefined;
8
+ const total = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 0 };
9
+ for (const usage of present) {
10
+ total.input += usage.input;
11
+ total.cacheRead += usage.cacheRead;
12
+ total.cacheWrite += usage.cacheWrite;
13
+ total.output += usage.output;
14
+ total.reasoning += usage.reasoning;
15
+ total.totalTokens += usage.totalTokens;
16
+ if (typeof usage.costTotal === "number")
17
+ total.costTotal = (total.costTotal ?? 0) + usage.costTotal;
18
+ }
19
+ return total;
20
+ }
21
+ //# sourceMappingURL=panel-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-usage.js","sourceRoot":"","sources":["../src/panel-usage.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAkC;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAuB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,KAAK,GAAe,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAC7G,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC;QAC3B,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACnC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC;QACrC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QAC7B,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACnC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC;QACvC,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;YAAE,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;IACtG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { PanelReviewMeta, ReviewerSubmission, TokenUsage } from "./types.js";
2
+ import type { ReviewEvent, ReviewerIdentity } from "./review-events.js";
3
+ export type ReviewerViewStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
4
+ export type PanelPhase = "idle" | "running" | "aggregating" | "completed";
5
+ export interface PanelReviewerView extends ReviewerIdentity {
6
+ status: ReviewerViewStatus;
7
+ activeTool?: string;
8
+ activityAt?: number;
9
+ startedAt?: number;
10
+ completedAt?: number;
11
+ turns: number;
12
+ usage?: TokenUsage;
13
+ recentActivity: string[];
14
+ submission?: ReviewerSubmission;
15
+ error?: string;
16
+ }
17
+ export interface PanelViewState {
18
+ runId?: string;
19
+ lastSeq: number;
20
+ target?: string;
21
+ mode?: string;
22
+ panelPreset?: string;
23
+ startedAt?: number;
24
+ completedAt?: number;
25
+ phase: PanelPhase;
26
+ reviewers: Record<string, PanelReviewerView>;
27
+ aggregate: {
28
+ total: number;
29
+ queued: number;
30
+ running: number;
31
+ completed: number;
32
+ failed: number;
33
+ cancelled: number;
34
+ usage?: TokenUsage;
35
+ };
36
+ meta?: PanelReviewMeta;
37
+ }
38
+ export declare function createPanelViewState(): PanelViewState;
39
+ /** Unknown, duplicate, out-of-order, and other-run events leave state intact. */
40
+ export declare function reducePanelEvent(state: PanelViewState, event: ReviewEvent): PanelViewState;
41
+ //# sourceMappingURL=panel-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-view.d.ts","sourceRoot":"","sources":["../src/panel-view.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGxE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAC7F,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAE1E,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC7C,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC;IACxI,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAID,wBAAgB,oBAAoB,IAAI,cAAc,CAOrD;AA2BD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,cAAc,CAsD1F"}
@@ -0,0 +1,90 @@
1
+ // Pure state reducer shared by the Pi renderer and future event consumers.
2
+ import { sumPanelUsage } from "./panel-usage.js";
3
+ const ACTIVITY_LIMIT = 8;
4
+ export function createPanelViewState() {
5
+ return {
6
+ lastSeq: 0,
7
+ phase: "idle",
8
+ reviewers: {},
9
+ aggregate: { total: 0, queued: 0, running: 0, completed: 0, failed: 0, cancelled: 0 },
10
+ };
11
+ }
12
+ function addActivity(reviewer, activity) {
13
+ return { ...reviewer, recentActivity: [...reviewer.recentActivity, activity].slice(-ACTIVITY_LIMIT) };
14
+ }
15
+ function fallbackReviewer(reviewerId) {
16
+ return { reviewerId, role: reviewerId, model: null, status: "queued", turns: 0, recentActivity: [] };
17
+ }
18
+ function withAggregate(state) {
19
+ const statuses = Object.values(state.reviewers).map((reviewer) => reviewer.status);
20
+ const usage = sumPanelUsage(Object.values(state.reviewers).map((reviewer) => reviewer.usage));
21
+ return {
22
+ ...state,
23
+ aggregate: {
24
+ total: statuses.length,
25
+ queued: statuses.filter((status) => status === "queued").length,
26
+ running: statuses.filter((status) => status === "running").length,
27
+ completed: statuses.filter((status) => status === "completed").length,
28
+ failed: statuses.filter((status) => status === "failed").length,
29
+ cancelled: statuses.filter((status) => status === "cancelled").length,
30
+ ...(usage ? { usage } : {}),
31
+ },
32
+ };
33
+ }
34
+ /** Unknown, duplicate, out-of-order, and other-run events leave state intact. */
35
+ export function reducePanelEvent(state, event) {
36
+ const knownTypes = new Set([
37
+ "panel.started", "reviewer.queued", "reviewer.started", "reviewer.turn.started", "reviewer.tool.started", "reviewer.tool.finished", "reviewer.text.delta", "reviewer.usage", "reviewer.completed", "reviewer.failed", "reviewer.cancelled", "aggregation.started", "panel.completed",
38
+ ]);
39
+ if (!knownTypes.has(event.type) || event.seq <= state.lastSeq || (state.runId && event.runId !== state.runId))
40
+ return state;
41
+ let next = { ...state, runId: event.runId, lastSeq: event.seq };
42
+ if (event.type === "panel.started") {
43
+ const reviewers = Object.fromEntries(event.reviewers.map((identity) => [identity.reviewerId, { ...identity, status: "queued", turns: 0, recentActivity: [] }]));
44
+ return withAggregate({ ...next, target: event.target, mode: event.mode, ...(event.panelPreset ? { panelPreset: event.panelPreset } : {}), startedAt: event.at, phase: "running", reviewers });
45
+ }
46
+ if (event.type === "aggregation.started")
47
+ return withAggregate({ ...next, phase: "aggregating" });
48
+ if (event.type === "panel.completed") {
49
+ const completed = withAggregate({ ...next, phase: "completed", completedAt: event.at, meta: event.meta });
50
+ return { ...completed, aggregate: { ...completed.aggregate, ...(event.meta.usage ? { usage: event.meta.usage } : {}) } };
51
+ }
52
+ const reviewerId = event.reviewerId;
53
+ const previous = state.reviewers[reviewerId] ?? fallbackReviewer(reviewerId);
54
+ let reviewer = previous;
55
+ switch (event.type) {
56
+ case "reviewer.queued":
57
+ reviewer = { ...previous, status: "queued", activityAt: event.at };
58
+ break;
59
+ case "reviewer.started":
60
+ reviewer = addActivity({ ...previous, status: "running", startedAt: event.at, activityAt: event.at }, "review started");
61
+ break;
62
+ case "reviewer.turn.started":
63
+ reviewer = addActivity({ ...previous, status: "running", turns: event.turn, activityAt: event.at }, `turn ${event.turn}`);
64
+ break;
65
+ case "reviewer.tool.started":
66
+ reviewer = addActivity({ ...previous, status: "running", activeTool: event.tool, activityAt: event.at }, `tool ${event.tool}${event.summary ? `: ${event.summary}` : ""}`);
67
+ break;
68
+ case "reviewer.tool.finished":
69
+ reviewer = addActivity({ ...previous, status: "running", activeTool: undefined, activityAt: event.at }, `tool ${event.tool} finished${event.summary ? `: ${event.summary}` : ""}`);
70
+ break;
71
+ case "reviewer.text.delta":
72
+ reviewer = addActivity({ ...previous, status: "running", activityAt: event.at }, event.text);
73
+ break;
74
+ case "reviewer.usage":
75
+ reviewer = { ...previous, usage: event.usage, activityAt: event.at };
76
+ break;
77
+ case "reviewer.completed":
78
+ reviewer = addActivity({ ...previous, status: "completed", activeTool: undefined, completedAt: event.at, activityAt: event.at, usage: event.submission.usage ?? previous.usage, submission: event.submission }, "review completed");
79
+ break;
80
+ case "reviewer.failed":
81
+ reviewer = addActivity({ ...previous, status: "failed", activeTool: undefined, completedAt: event.at, activityAt: event.at, error: event.message }, event.message);
82
+ break;
83
+ case "reviewer.cancelled":
84
+ reviewer = addActivity({ ...previous, status: "cancelled", activeTool: undefined, completedAt: event.at, activityAt: event.at, ...(event.message ? { error: event.message } : {}) }, event.message ?? "review cancelled");
85
+ break;
86
+ }
87
+ next = { ...next, reviewers: { ...state.reviewers, [reviewerId]: reviewer } };
88
+ return withAggregate(next);
89
+ }
90
+ //# sourceMappingURL=panel-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-view.js","sourceRoot":"","sources":["../src/panel-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=panel-view.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-view.test.d.ts","sourceRoot":"","sources":["../src/panel-view.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { createPanelViewState, reducePanelEvent } from "./panel-view.js";
4
+ function event(type, seq, payload) {
5
+ return { v: 1, runId: "run-1", seq, at: 1000 + seq, type, ...payload };
6
+ }
7
+ test("panel reducer produces the same final state during live delivery and replay", () => {
8
+ const events = [
9
+ event("panel.started", 1, { target: "@src", mode: "code", reviewers: [{ reviewerId: "security", role: "Security", model: "openai/gpt", thinking: "high" }] }),
10
+ event("reviewer.queued", 2, { reviewerId: "security" }),
11
+ event("reviewer.started", 3, { reviewerId: "security" }),
12
+ event("reviewer.tool.started", 4, { reviewerId: "security", tool: "read", summary: "src/panel.ts" }),
13
+ event("reviewer.usage", 5, { reviewerId: "security", usage: { input: 10, output: 4, cacheRead: 0, cacheWrite: 0, reasoning: 2, totalTokens: 14 } }),
14
+ event("reviewer.completed", 6, { reviewerId: "security", submission: { reviewerId: "security", role: "Security", model: "openai/gpt", durationMs: 20, result: { status: "clean", verdict: "approve", verdictSource: "parsed", findings: [], actionableCount: 0 } } }),
15
+ event("aggregation.started", 7, {}),
16
+ ];
17
+ const live = events.reduce(reducePanelEvent, createPanelViewState());
18
+ const replay = events.reduce(reducePanelEvent, createPanelViewState());
19
+ assert.deepEqual(replay, live);
20
+ assert.equal(live.reviewers.security?.status, "completed");
21
+ assert.equal(live.reviewers.security?.activeTool, undefined);
22
+ assert.equal(live.aggregate.completed, 1);
23
+ assert.equal(live.phase, "aggregating");
24
+ });
25
+ test("terminal panel usage reuses the CLI aggregation semantics", () => {
26
+ const now = Date.now();
27
+ let state = reducePanelEvent(createPanelViewState(), {
28
+ v: 1, runId: "run-usage", seq: 1, at: now, type: "panel.started", target: "@src", mode: "code",
29
+ reviewers: [{ reviewerId: "r1", role: "one", model: null }, { reviewerId: "r2", role: "two", model: null }],
30
+ });
31
+ state = reducePanelEvent(state, { v: 1, runId: "run-usage", seq: 2, at: now, type: "reviewer.usage", reviewerId: "r1", usage: { input: 100, output: 10, cacheRead: 20, cacheWrite: 0, reasoning: 5, totalTokens: 110 } });
32
+ state = reducePanelEvent(state, { v: 1, runId: "run-usage", seq: 3, at: now, type: "reviewer.usage", reviewerId: "r2", usage: { input: 80, output: 30, cacheRead: 10, cacheWrite: 0, reasoning: 7, totalTokens: 110 } });
33
+ assert.deepEqual(state.aggregate.usage, { input: 180, output: 40, cacheRead: 30, cacheWrite: 0, reasoning: 12, totalTokens: 220 });
34
+ });
35
+ test("panel reducer ignores duplicates, unknown events, and out-of-order delivery", () => {
36
+ const started = event("panel.started", 1, { target: "@src", mode: "code", reviewers: [] });
37
+ const state = reducePanelEvent(createPanelViewState(), started);
38
+ const duplicate = reducePanelEvent(state, started);
39
+ const unknown = reducePanelEvent(duplicate, { v: 1, runId: "run-1", seq: 2, at: 1002, type: "future.event" });
40
+ const later = reducePanelEvent(unknown, event("aggregation.started", 3, {}));
41
+ const outOfOrder = reducePanelEvent(later, event("aggregation.started", 2, {}));
42
+ assert.equal(outOfOrder.lastSeq, 3);
43
+ assert.equal(outOfOrder.phase, "aggregating");
44
+ });
45
+ //# sourceMappingURL=panel-view.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-view.test.js","sourceRoot":"","sources":["../src/panel-view.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ParsedArgs, PanelReviewMeta } from "./types.js";
2
+ export { PANEL_READ_ONLY_TOOLS } from "./types.js";
3
+ import { type ReviewEventListener } from "./review-events.js";
4
+ /** Emit the aggregate panel footer (ASCII + JSON) like a single review. */
5
+ export declare function emitPanelFooter(meta: PanelReviewMeta): void;
6
+ /** Resolve reviewer tools through the hard allowlist; rejected requests cannot silently widen access. */
7
+ export declare function resolvePanelReviewerTools(tools: string | string[] | undefined): string;
8
+ export interface PanelRunOptions {
9
+ onEvent?: ReviewEventListener;
10
+ signal?: AbortSignal;
11
+ emitFooter?: boolean;
12
+ }
13
+ /** Run one complete panel evaluation and return the aggregate result (no exit). */
14
+ export declare function runPanelReviewOnce(parsed: ParsedArgs, stdinText?: string, options?: PanelRunOptions): Promise<{
15
+ meta: PanelReviewMeta;
16
+ exitCode: number;
17
+ }>;
18
+ /** CLI-compatible panel review entrypoint. */
19
+ export declare function runPanelReview(parsed: ParsedArgs): Promise<never>;
20
+ //# sourceMappingURL=panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EAIhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAgBnD,OAAO,EAAiG,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE7J,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAa3D;AAWD,yGAAyG;AACzG,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAStF;AAqPD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAmBD,mFAAmF;AACnF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,UAAU,EAClB,SAAS,SAAoB,EAC7B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAuGtD;AAED,8CAA8C;AAC9C,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CASvE"}