@cjhyy/code-shell-arena 0.8.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 (102) hide show
  1. package/README.md +46 -0
  2. package/dist/arena.d.ts +45 -0
  3. package/dist/arena.js +362 -0
  4. package/dist/capability.d.ts +43 -0
  5. package/dist/capability.js +453 -0
  6. package/dist/context/context-tools.d.ts +16 -0
  7. package/dist/context/context-tools.js +272 -0
  8. package/dist/context/within-root.d.ts +7 -0
  9. package/dist/context/within-root.js +15 -0
  10. package/dist/detect-mode.d.ts +20 -0
  11. package/dist/detect-mode.js +78 -0
  12. package/dist/digest-builder.d.ts +25 -0
  13. package/dist/digest-builder.js +120 -0
  14. package/dist/index.d.ts +25 -0
  15. package/dist/index.js +23 -0
  16. package/dist/index.runtime.d.ts +13 -0
  17. package/dist/index.runtime.js +11 -0
  18. package/dist/iterate/convergence.d.ts +25 -0
  19. package/dist/iterate/convergence.js +103 -0
  20. package/dist/iterate/formats/index.d.ts +22 -0
  21. package/dist/iterate/formats/index.js +283 -0
  22. package/dist/iterate/index.d.ts +11 -0
  23. package/dist/iterate/index.js +9 -0
  24. package/dist/iterate/iterative-arena.d.ts +31 -0
  25. package/dist/iterate/iterative-arena.js +252 -0
  26. package/dist/iterate/parse.d.ts +42 -0
  27. package/dist/iterate/parse.js +123 -0
  28. package/dist/iterate/phases/argue.d.ts +22 -0
  29. package/dist/iterate/phases/argue.js +165 -0
  30. package/dist/iterate/phases/revise.d.ts +16 -0
  31. package/dist/iterate/phases/revise.js +62 -0
  32. package/dist/iterate/phases/tournament.d.ts +34 -0
  33. package/dist/iterate/phases/tournament.js +113 -0
  34. package/dist/iterate/tools/web-tools.d.ts +13 -0
  35. package/dist/iterate/tools/web-tools.js +54 -0
  36. package/dist/iterate/types.d.ts +152 -0
  37. package/dist/iterate/types.js +8 -0
  38. package/dist/ledger.d.ts +47 -0
  39. package/dist/ledger.js +159 -0
  40. package/dist/lenses/architecture.d.ts +5 -0
  41. package/dist/lenses/architecture.js +22 -0
  42. package/dist/lenses/engineering.d.ts +5 -0
  43. package/dist/lenses/engineering.js +22 -0
  44. package/dist/lenses/general.d.ts +5 -0
  45. package/dist/lenses/general.js +20 -0
  46. package/dist/lenses/index.d.ts +16 -0
  47. package/dist/lenses/index.js +47 -0
  48. package/dist/lenses/product.d.ts +5 -0
  49. package/dist/lenses/product.js +22 -0
  50. package/dist/model-presets.d.ts +23 -0
  51. package/dist/model-presets.js +44 -0
  52. package/dist/phases/adjudication.d.ts +25 -0
  53. package/dist/phases/adjudication.js +142 -0
  54. package/dist/phases/build-consensus.d.ts +30 -0
  55. package/dist/phases/build-consensus.js +85 -0
  56. package/dist/phases/claim-registry.d.ts +26 -0
  57. package/dist/phases/claim-registry.js +60 -0
  58. package/dist/phases/cross-review.d.ts +47 -0
  59. package/dist/phases/cross-review.js +224 -0
  60. package/dist/phases/debate-rounds.d.ts +28 -0
  61. package/dist/phases/debate-rounds.js +161 -0
  62. package/dist/phases/participant-research.d.ts +39 -0
  63. package/dist/phases/participant-research.js +322 -0
  64. package/dist/phases/planning-detail-expansion.d.ts +39 -0
  65. package/dist/phases/planning-detail-expansion.js +120 -0
  66. package/dist/planner.d.ts +28 -0
  67. package/dist/planner.js +312 -0
  68. package/dist/providers/docs.d.ts +7 -0
  69. package/dist/providers/docs.js +111 -0
  70. package/dist/providers/git.d.ts +8 -0
  71. package/dist/providers/git.js +174 -0
  72. package/dist/providers/index.d.ts +32 -0
  73. package/dist/providers/index.js +132 -0
  74. package/dist/providers/none.d.ts +7 -0
  75. package/dist/providers/none.js +11 -0
  76. package/dist/providers/repo.d.ts +7 -0
  77. package/dist/providers/repo.js +258 -0
  78. package/dist/render/session.d.ts +17 -0
  79. package/dist/render/session.js +190 -0
  80. package/dist/render/terminal.d.ts +34 -0
  81. package/dist/render/terminal.js +286 -0
  82. package/dist/strategies/discussion.d.ts +25 -0
  83. package/dist/strategies/discussion.js +143 -0
  84. package/dist/strategies/index.d.ts +15 -0
  85. package/dist/strategies/index.js +28 -0
  86. package/dist/strategies/language-wrapper.d.ts +17 -0
  87. package/dist/strategies/language-wrapper.js +102 -0
  88. package/dist/strategies/lens-wrapper.d.ts +16 -0
  89. package/dist/strategies/lens-wrapper.js +236 -0
  90. package/dist/strategies/planning.d.ts +30 -0
  91. package/dist/strategies/planning.js +225 -0
  92. package/dist/strategies/review.d.ts +26 -0
  93. package/dist/strategies/review.js +168 -0
  94. package/dist/strategies/utils.d.ts +36 -0
  95. package/dist/strategies/utils.js +603 -0
  96. package/dist/tools/selector.d.ts +17 -0
  97. package/dist/tools/selector.js +61 -0
  98. package/dist/transitions.d.ts +53 -0
  99. package/dist/transitions.js +97 -0
  100. package/dist/types.d.ts +518 -0
  101. package/dist/types.js +27 -0
  102. package/package.json +45 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Review strategy — structured code review with findings.
3
+ *
4
+ * V2: produces ArenaFinding[] (strength/improvement/risk/question)
5
+ * instead of free-text opinions.
6
+ */
7
+ import { formatBaseContext, formatReports, formatFindingReviews, formatClaimsForReview, formatDebateHistory, formatClaimSummaryForConsensus, formatDigestForPrompt, parseReport, parseReviews, parseConsensus, parseChallenges, parseDebateTurn, parseAdjudication, } from "./utils.js";
8
+ export class ReviewStrategy {
9
+ // ─── Research Phase ──────────────────────────────────────────
10
+ researchSystemPrompt(name) {
11
+ return (`You are ${name}, a reviewer in a multi-model review arena.\n\n` +
12
+ `You may have access to read-only tools to fetch additional context. ` +
13
+ `The base context is intentionally lean — use tools to inspect details as needed.\n\n` +
14
+ `IMPORTANT RULES:\n` +
15
+ `- Limit yourself to AT MOST 3 tool rounds. Do NOT exhaustively read every file.\n` +
16
+ `- Focus on the HIGHEST-IMPACT findings. Quality over quantity.\n` +
17
+ `- Output as many findings as the topic warrants — typically 5-15 for a non-trivial subject. ` +
18
+ `Each <summary> should be 80+ words with concrete evidence and rationale, not a one-liner. ` +
19
+ `Rank by confidence.\n` +
20
+ `- Prioritize: risks > improvements > questions. Strengths are optional.\n\n` +
21
+ `When ready, respond ONLY with the following XML structure (no markdown fences, no commentary outside the root element):\n\n` +
22
+ `<report>\n` +
23
+ ` <contextSummary>brief summary of what you investigated</contextSummary>\n` +
24
+ ` <findings>\n` +
25
+ ` <finding id="unique-id" kind="risk|improvement|question|strength" severity="high|medium|low" confidence="0.0-1.0">\n` +
26
+ ` <title>short title</title>\n` +
27
+ ` <summary>detailed explanation, 80+ words, citing specific files/lines</summary>\n` +
28
+ ` <evidence type="file|diff|grep|git|doc" ref="path">what it shows</evidence>\n` +
29
+ ` <evidence type="file" ref="another/path">…</evidence>\n` +
30
+ ` <affectedFiles>\n` +
31
+ ` <file>src/foo.ts</file>\n` +
32
+ ` <file>src/bar.ts</file>\n` +
33
+ ` </affectedFiles>\n` +
34
+ ` <suggestedChange>optional concrete fix</suggestedChange>\n` +
35
+ ` </finding>\n` +
36
+ ` <!-- repeat <finding> blocks as needed -->\n` +
37
+ ` </findings>\n` +
38
+ `</report>\n\n` +
39
+ `XML is preferred over JSON because thinking-mode models produce more reliable output here. Do not wrap the XML in code fences. Do not include text outside <report>…</report>.`);
40
+ }
41
+ researchUserPrompt(topic, baseContext) {
42
+ return (`## Review Topic\n${topic}\n\n` +
43
+ `${formatBaseContext(baseContext)}\n\n` +
44
+ `Use tools to read specific files from the diff. Then output 3-6 highest-confidence findings as a single <report> XML element.`);
45
+ }
46
+ parseResearchResponse(participant, text) {
47
+ return parseReport(participant, text);
48
+ }
49
+ // ─── Cross Review Phase ──────────────────────────────────────
50
+ crossReviewSystemPrompt(reviewerName) {
51
+ return (`You are ${reviewerName}, reviewing other participants' review findings.\n\n` +
52
+ `For each finding, provide a verdict:\n` +
53
+ `- "agree": you confirm this finding\n` +
54
+ `- "refine": mostly agree but with refinements\n` +
55
+ `- "disagree": you believe this finding is incorrect\n` +
56
+ `- "needs_evidence": the finding lacks sufficient evidence\n\n` +
57
+ `Focus on HIGH VALUE findings: high severity, high risk, or conflicting conclusions.\n` +
58
+ `You don't need to review every single finding — prioritize the important ones.\n\n` +
59
+ `Respond ONLY with a JSON array (no markdown fences):\n` +
60
+ `[{"findingId": "...", "verdict": "agree|refine|disagree|needs_evidence", "reason": "...", "extraEvidence": ["optional"]}]`);
61
+ }
62
+ crossReviewUserPrompt(topic, myReport, otherReports) {
63
+ return (`## Topic: ${topic}\n\n` +
64
+ `## Your Findings\n${formatReports([myReport])}\n\n` +
65
+ `## Other Reviewers' Findings\n${formatReports(otherReports)}\n\n` +
66
+ `Review the other participants' findings. Focus on high-priority items.`);
67
+ }
68
+ parseCrossReviewResponse(reviewer, text) {
69
+ return parseReviews(reviewer, text);
70
+ }
71
+ // ─── Consensus Phase ─────────────────────────────────────────
72
+ consensusSystemPrompt() {
73
+ return (`You are a neutral moderator synthesizing a multi-model review into a structured consensus.\n\n` +
74
+ `You MUST faithfully reflect the aggregated findings and peer reviews. ` +
75
+ `Do NOT add new conclusions that have no source in the findings.\n\n` +
76
+ `IMPORTANT: Start with a "subjectSummary" — a factual overview of WHAT is being reviewed ` +
77
+ `(scope, key areas, high-level description). This comes BEFORE any judgment.\n\n` +
78
+ `Respond ONLY with JSON (no markdown fences):\n` +
79
+ `{\n` +
80
+ ` "summary": "one-paragraph overall assessment",\n` +
81
+ ` "subjectSummary": "factual overview of what is being reviewed — scope, key areas, subject description",\n` +
82
+ ` "strengths": [{"title": "...", "summary": "...", "support": ["participant names"], "challenge": [], "confidence": 0.0-1.0, "evidenceRefs": ["finding IDs"]}],\n` +
83
+ ` "improvements": [same structure],\n` +
84
+ ` "risks": [same structure],\n` +
85
+ ` "openQuestions": [same structure],\n` +
86
+ ` "nextActions": [{"title": "...", "priority": "high|medium|low", "rationale": "...", "relatedFindings": ["finding IDs"]}]\n` +
87
+ `}`);
88
+ }
89
+ consensusUserPrompt(topic, reports, reviews) {
90
+ return (`## Topic\n${topic}\n\n` +
91
+ `## Participant Reports\n${formatReports(reports)}\n\n` +
92
+ `## Peer Reviews\n${formatFindingReviews(reviews)}\n\n` +
93
+ `Synthesize a structured consensus. Group findings by category, note agreement/disagreement, and propose next actions.`);
94
+ }
95
+ parseConsensusResponse(text) {
96
+ return parseConsensus(text);
97
+ }
98
+ preferredFindingKinds() {
99
+ return ["strength", "improvement", "risk", "question"];
100
+ }
101
+ // ─── V2: Verification Review ────────────────────────────────────
102
+ verificationReviewUserPrompt(topic, myReport, claimsToReview, digest) {
103
+ return (`## Topic: ${topic}\n\n` +
104
+ `## Your Findings\n${formatReports([myReport])}\n\n` +
105
+ `## Claims to Verify\n${formatClaimsForReview(claimsToReview)}\n\n` +
106
+ `## Evidence Digest\n${formatDigestForPrompt(digest)}\n\n` +
107
+ `Verify each claim against the evidence. For claims lacking evidence, you may request specific checks.\n` +
108
+ `Respond ONLY with a JSON array:\n` +
109
+ `[{"claimId": "...", "verdict": "agree|refine|disagree|needs_evidence", "reason": "...", ` +
110
+ `"supportingEvidenceRefs": ["optional"], "requestedChecks": [{"description": "what to check", "priority": "high|medium|low"}]}]`);
111
+ }
112
+ parseVerificationReviewResponse(reviewer, text) {
113
+ return parseChallenges(reviewer, text);
114
+ }
115
+ // ─── V2: Debate ─────────────────────────────────────────────────
116
+ debateTurnUserPrompt(topic, claim, priorTurns, digest) {
117
+ return (`## Topic: ${topic}\n\n` +
118
+ `## Contested Claim\n` +
119
+ `[${claim.claimId}] ${claim.finding.title}\n${claim.finding.summary}\n` +
120
+ `Evidence: ${claim.evidenceRefs.join(", ") || "none"}\n\n` +
121
+ `## Prior Debate\n${formatDebateHistory(priorTurns)}\n\n` +
122
+ `## Evidence Digest\n${formatDigestForPrompt(digest)}\n\n` +
123
+ `State your position on this claim. Build on prior turns: cite specific evidence, ` +
124
+ `acknowledge counter-arguments, and explain your reasoning in 150-300 words. ` +
125
+ `Brevity here means missed nuance — depth wins.\n` +
126
+ `Respond ONLY with JSON:\n` +
127
+ `{"stance": "support|oppose|narrow|uncertain", "summary": "your argument", "newEvidenceRefs": ["optional"]}`);
128
+ }
129
+ parseDebateTurnResponse(participant, text) {
130
+ return parseDebateTurn(participant, text);
131
+ }
132
+ // ─── V2: Adjudication ──────────────────────────────────────────
133
+ adjudicationUserPrompt(topic, claim, debateRounds, digest) {
134
+ const debateSummary = debateRounds.length > 0
135
+ ? debateRounds.map((r) => `Round ${r.round}:\n${formatDebateHistory(r.participants)}\n${r.resolved ? "→ Resolved" : "→ Unresolved"}`).join("\n\n")
136
+ : "No debate rounds occurred.";
137
+ return (`## Topic: ${topic}\n\n` +
138
+ `## Claim Under Adjudication\n` +
139
+ `[${claim.claimId}] ${claim.finding.title}\n${claim.finding.summary}\n` +
140
+ `Owner: ${claim.owner} | Status: ${claim.status}\n` +
141
+ `Evidence: ${claim.evidenceRefs.join(", ") || "none"}\n\n` +
142
+ `## Challenges\n` +
143
+ claim.challenges.map((c) => `[${c.reviewer}] ${c.verdict}: ${c.reason}`).join("\n") + "\n\n" +
144
+ `## Debate\n${debateSummary}\n\n` +
145
+ `## Evidence Digest\n${formatDigestForPrompt(digest)}\n\n` +
146
+ `As moderator, you MUST issue a verdict — "unresolved" is reserved ONLY for the rare case where the debate produced genuinely irreconcilable interpretations of the same evidence. Default to deciding.\n\n` +
147
+ `Decision rule:\n` +
148
+ `- "accepted": claim is correct as stated AND has direct evidence (file/line refs).\n` +
149
+ `- "accepted_with_revision": core insight is correct but the challenge surfaced a real refinement (scope/severity/wording). Issue a corrected finalSummary.\n` +
150
+ `- "rejected": the challenger demonstrated the claim is factually wrong or already addressed in the code under review.\n` +
151
+ `- "unresolved": ONLY when no amount of further evidence could break the tie — e.g., taste-level disagreement on design philosophy. Using this on a verifiable code claim is a failure of adjudication.\n\n` +
152
+ `Respond ONLY with JSON:\n` +
153
+ `{"outcome": "accepted|accepted_with_revision|rejected|unresolved", "rationale": "...", ` +
154
+ `"finalSummary": "revised claim summary if needed", "supportingEvidenceRefs": ["..."]}`);
155
+ }
156
+ parseAdjudicationResponse(text) {
157
+ return parseAdjudication("", text);
158
+ }
159
+ // ─── V2: Claim-Aware Consensus ─────────────────────────────────
160
+ claimAwareConsensusUserPrompt(topic, reports, reviews, claimSummary) {
161
+ return (`## Topic\n${topic}\n\n` +
162
+ `## Claim Verification Status\n${formatClaimSummaryForConsensus(claimSummary)}\n\n` +
163
+ `## Participant Reports\n${formatReports(reports)}\n\n` +
164
+ `## Peer Reviews\n${formatFindingReviews(reviews)}\n\n` +
165
+ `Synthesize a structured consensus. Verified claims should appear as high-confidence items. ` +
166
+ `Unresolved claims should appear as open questions. Rejected claims should be excluded or noted as dismissed.`);
167
+ }
168
+ }
@@ -0,0 +1,36 @@
1
+ /** Shared utilities for arena strategy implementations. */
2
+ import type { ArenaBaseContext, FindingReview, ParticipantReport, ArenaConsensus, ArenaRoadmapPhaseDetail, ClaimRecord, ClaimChallenge, ClaimAdjudication, ClaimStatusSummary, DebateTurn, RoundResearchDigest } from "../types.js";
3
+ export { extractJSON, extractJSONArray } from "@cjhyy/code-shell-core/extension";
4
+ /** Format base context into a readable text block for LLM prompts */
5
+ export declare function formatBaseContext(ctx: ArenaBaseContext): string;
6
+ /** Format participant reports for cross-review or consensus prompts */
7
+ export declare function formatReports(reports: ParticipantReport[]): string;
8
+ /** Format finding reviews for consensus prompts */
9
+ export declare function formatFindingReviews(reviews: FindingReview[]): string;
10
+ /**
11
+ * Parse a ParticipantReport. The research prompt now asks for an
12
+ * XML <report> element because thinking-mode models (DeepSeek V4)
13
+ * produced malformed JSON often enough to derail the loop. We try
14
+ * XML first, then JSON, then a free-text salvage.
15
+ */
16
+ export declare function parseReport(participant: string, text: string): ParticipantReport;
17
+ /** Parse FindingReview[] from LLM JSON output */
18
+ export declare function parseReviews(reviewer: string, text: string): FindingReview[];
19
+ /** Parse ArenaConsensus from LLM JSON output */
20
+ export declare function parseConsensus(text: string): ArenaConsensus;
21
+ /** Format claims for verification-review prompts */
22
+ export declare function formatClaimsForReview(claims: ClaimRecord[]): string;
23
+ /** Format debate history for debate turn prompts */
24
+ export declare function formatDebateHistory(turns: DebateTurn[]): string;
25
+ /** Format claim status summary for consensus prompts */
26
+ export declare function formatClaimSummaryForConsensus(summary: ClaimStatusSummary): string;
27
+ /** Format a digest text block for inclusion in prompts */
28
+ export declare function formatDigestForPrompt(digest: RoundResearchDigest): string;
29
+ /** Parse ClaimChallenge[] from LLM JSON output */
30
+ export declare function parseChallenges(reviewer: string, text: string): ClaimChallenge[];
31
+ /** Parse a DebateTurn from LLM JSON output */
32
+ export declare function parseDebateTurn(participant: string, text: string): DebateTurn;
33
+ /** Parse a ClaimAdjudication from LLM JSON output */
34
+ export declare function parseAdjudication(claimId: string, text: string): ClaimAdjudication;
35
+ /** Parse an ArenaRoadmapPhaseDetail from LLM JSON output */
36
+ export declare function parseDetailExpansion(text: string): ArenaRoadmapPhaseDetail;