clud-bug 0.6.34 → 0.7.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/bin/clud-bug.js +10 -1353
- package/data/canonical-v1.json +37 -0
- package/dist/cli/agents-md.d.ts +16 -0
- package/dist/cli/agents-md.d.ts.map +1 -0
- package/dist/cli/agents-md.js +226 -0
- package/dist/cli/agents-md.js.map +1 -0
- package/dist/cli/audit.d.ts +13 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +90 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/branch-protection.d.ts +57 -0
- package/dist/cli/branch-protection.d.ts.map +1 -0
- package/dist/cli/branch-protection.js +118 -0
- package/dist/cli/branch-protection.js.map +1 -0
- package/dist/cli/configure-github.d.ts +58 -0
- package/dist/cli/configure-github.d.ts.map +1 -0
- package/dist/cli/configure-github.js +242 -0
- package/dist/cli/configure-github.js.map +1 -0
- package/dist/cli/edit-workflow.d.ts +18 -0
- package/dist/cli/edit-workflow.d.ts.map +1 -0
- package/dist/cli/edit-workflow.js +43 -0
- package/dist/cli/edit-workflow.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +2067 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/skill-usage.d.ts +109 -0
- package/dist/cli/skill-usage.d.ts.map +1 -0
- package/dist/cli/skill-usage.js +380 -0
- package/dist/cli/skill-usage.js.map +1 -0
- package/dist/cli/skills.d.ts +56 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +292 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/update.d.ts +29 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +205 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/usage.d.ts +142 -0
- package/dist/cli/usage.d.ts.map +1 -0
- package/dist/cli/usage.js +348 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/core/audit.d.ts +8 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +47 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/auto-resolve.d.ts +235 -0
- package/dist/core/auto-resolve.d.ts.map +1 -0
- package/dist/core/auto-resolve.js +293 -0
- package/dist/core/auto-resolve.js.map +1 -0
- package/dist/core/configure-github.d.ts +179 -0
- package/dist/core/configure-github.d.ts.map +1 -0
- package/dist/core/configure-github.js +289 -0
- package/dist/core/configure-github.js.map +1 -0
- package/dist/core/detect.d.ts +77 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +262 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/diff-findings.d.ts +96 -0
- package/dist/core/diff-findings.d.ts.map +1 -0
- package/dist/core/diff-findings.js +261 -0
- package/dist/core/diff-findings.js.map +1 -0
- package/dist/core/formal-review.d.ts +79 -0
- package/dist/core/formal-review.d.ts.map +1 -0
- package/dist/core/formal-review.js +71 -0
- package/dist/core/formal-review.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +66 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/inline-threads.d.ts +160 -0
- package/dist/core/inline-threads.d.ts.map +1 -0
- package/dist/core/inline-threads.js +369 -0
- package/dist/core/inline-threads.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +164 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +419 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/prompts.d.ts +9 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +401 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/render-review.d.ts +6 -0
- package/dist/core/render-review.d.ts.map +1 -0
- package/dist/core/render-review.js +219 -0
- package/dist/core/render-review.js.map +1 -0
- package/dist/core/render.d.ts +13 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +62 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/resolve-verifier.d.ts +46 -0
- package/dist/core/resolve-verifier.d.ts.map +1 -0
- package/dist/core/resolve-verifier.js +187 -0
- package/dist/core/resolve-verifier.js.map +1 -0
- package/dist/core/review-schema-zod.d.ts +240 -0
- package/dist/core/review-schema-zod.d.ts.map +1 -0
- package/dist/core/review-schema-zod.js +218 -0
- package/dist/core/review-schema-zod.js.map +1 -0
- package/dist/core/review-schema.d.ts +42 -0
- package/dist/core/review-schema.d.ts.map +1 -0
- package/dist/core/review-schema.js +156 -0
- package/dist/core/review-schema.js.map +1 -0
- package/dist/core/review-writeback.d.ts +193 -0
- package/dist/core/review-writeback.d.ts.map +1 -0
- package/dist/core/review-writeback.js +364 -0
- package/dist/core/review-writeback.js.map +1 -0
- package/dist/core/skills.d.ts +147 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +726 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/package.json +37 -5
- package/{lib/agents-md.js → src/cli/agents-md.ts} +25 -14
- package/{lib/audit.js → src/cli/audit.ts} +37 -44
- package/{lib/branch-protection.js → src/cli/branch-protection.ts} +75 -11
- package/src/cli/configure-github.ts +329 -0
- package/{lib/edit-workflow.js → src/cli/edit-workflow.ts} +32 -11
- package/src/cli/index.ts +107 -0
- package/src/cli/main.ts +2204 -0
- package/{lib/skill-usage.js → src/cli/skill-usage.ts} +168 -94
- package/src/cli/skills.ts +386 -0
- package/{lib/update.js → src/cli/update.ts} +87 -27
- package/{lib/usage.js → src/cli/usage.ts} +167 -76
- package/src/core/audit.ts +53 -0
- package/src/core/auto-resolve.ts +488 -0
- package/src/core/configure-github.ts +497 -0
- package/{lib/detect.js → src/core/detect.ts} +100 -47
- package/src/core/diff-findings.ts +323 -0
- package/src/core/formal-review.ts +168 -0
- package/src/core/index.ts +250 -0
- package/src/core/inline-threads.ts +471 -0
- package/src/core/prompt-builder.ts +561 -0
- package/{lib/prompts.js → src/core/prompts.ts} +16 -2
- package/{lib/render-review.js → src/core/render-review.ts} +57 -25
- package/{lib/render.js → src/core/render.ts} +37 -17
- package/src/core/resolve-verifier.ts +228 -0
- package/src/core/review-schema-zod.ts +262 -0
- package/{lib/review-schema.js → src/core/review-schema.ts} +68 -5
- package/src/core/review-writeback.ts +565 -0
- package/{lib/skills.js → src/core/skills.ts} +456 -342
- package/src/core/version.ts +3 -0
- package/templates/clud-bug-review.md.tmpl +115 -0
- package/templates/workflow-py.yml.tmpl +80 -3
- package/templates/workflow-ts.yml.tmpl +80 -3
- package/templates/workflow.yml.tmpl +175 -8
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Zod-typed review schema for the AI-Gateway-shape consumer (clud-bug-app).
|
|
2
|
+
//
|
|
3
|
+
// The CLI runtime in `./review-schema.ts` ships a plain JSON-Schema object
|
|
4
|
+
// because that's what the Agent SDK validator expects on the
|
|
5
|
+
// `--json-schema '<JSON>'` argument. The App's runtime instead funnels the
|
|
6
|
+
// model output through the Vercel AI SDK, which derives a JSON Schema from
|
|
7
|
+
// a Zod schema. Both consumers need to agree on the WIRE shape — separate
|
|
8
|
+
// `critical_findings[] / minor_findings[] / preexisting_findings[]` arrays
|
|
9
|
+
// per SPEC §1.8.1 — but each builds its validator from a different source.
|
|
10
|
+
//
|
|
11
|
+
// This module ports the App's Zod schemas + flat-shape helpers into core
|
|
12
|
+
// so a future drift between the App's Zod and the CLI's JSON-Schema lives
|
|
13
|
+
// in one repo. The equivalence test (test/review-schema-zod.test.js)
|
|
14
|
+
// asserts the two schemas describe the same wire shape (required fields,
|
|
15
|
+
// finding-item shape) for every release.
|
|
16
|
+
//
|
|
17
|
+
// Ported from clud-bug-app/lib/review-schema.ts (commit shipped 2026-06-08).
|
|
18
|
+
// The pure helpers (`flattenFindings`, `unflattenFindings`,
|
|
19
|
+
// `deriveSummaryCounts`, `deriveSkillsReferenced`, `buildReviewFromFindings`)
|
|
20
|
+
// are byte-equivalent to the App's helpers — see test for the equivalence
|
|
21
|
+
// fixtures.
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
// Severity buckets per SPEC §1.8.1. Only used by the internal `Finding`
|
|
24
|
+
// type — the wire `findingItemSchema` does NOT carry severity.
|
|
25
|
+
export const severityValues = ['critical', 'minor', 'preexisting'];
|
|
26
|
+
export const severitySchema = z.enum(severityValues);
|
|
27
|
+
// Status header at the top of the review file.
|
|
28
|
+
export const statusHeaderValues = [
|
|
29
|
+
'critical findings',
|
|
30
|
+
'clean',
|
|
31
|
+
'bare',
|
|
32
|
+
];
|
|
33
|
+
export const statusHeaderSchema = z.enum(statusHeaderValues);
|
|
34
|
+
export const summaryCountsSchema = z.object({
|
|
35
|
+
critical: z.number().int().min(0),
|
|
36
|
+
minor: z.number().int().min(0),
|
|
37
|
+
preexisting: z.number().int().min(0),
|
|
38
|
+
resolved_from_prior: z.number().int().min(0),
|
|
39
|
+
still_open: z.number().int().min(0),
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Wire-shape finding item — NO severity field (mirrors the CLI's
|
|
43
|
+
* `FINDING_ITEM` JSON Schema in `./review-schema.ts`). Severity is implicit
|
|
44
|
+
* in which array the item lives in (`critical_findings`/`minor_findings`/
|
|
45
|
+
* `preexisting_findings`).
|
|
46
|
+
*/
|
|
47
|
+
export const findingItemSchema = z.object({
|
|
48
|
+
skill: z.string().min(1),
|
|
49
|
+
file: z.string().optional(),
|
|
50
|
+
line: z.number().int().min(1).optional(),
|
|
51
|
+
summary: z.string().min(1),
|
|
52
|
+
reasoning: z.string().optional(),
|
|
53
|
+
});
|
|
54
|
+
/** Per-skill scan report — one entry per loaded skill (even silent ones). */
|
|
55
|
+
export const perSkillScanItemSchema = z.object({
|
|
56
|
+
skill: z.string(),
|
|
57
|
+
outcome: z.string(),
|
|
58
|
+
});
|
|
59
|
+
/** Dedicated-section block for `review_mode: dedicated` skills. */
|
|
60
|
+
export const dedicatedSectionSchema = z.object({
|
|
61
|
+
section_name: z.string(),
|
|
62
|
+
skill: z.string(),
|
|
63
|
+
findings: z.array(findingItemSchema),
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Full review payload — wire shape. The model produces this; the App
|
|
67
|
+
* orchestrator immediately flattens to the internal `Finding[]` shape via
|
|
68
|
+
* `flattenFindings()` for multi-pass + aggregator work, then unflattens
|
|
69
|
+
* back via `unflattenFindings()` before writeback.
|
|
70
|
+
*/
|
|
71
|
+
export const reviewSchema = z.object({
|
|
72
|
+
status_header: statusHeaderSchema,
|
|
73
|
+
summary_counts: summaryCountsSchema,
|
|
74
|
+
per_skill_scan: z.array(perSkillScanItemSchema),
|
|
75
|
+
critical_findings: z.array(findingItemSchema),
|
|
76
|
+
minor_findings: z.array(findingItemSchema),
|
|
77
|
+
preexisting_findings: z.array(findingItemSchema),
|
|
78
|
+
dedicated_sections: z.array(dedicatedSectionSchema).optional(),
|
|
79
|
+
diagnostics: z.array(z.string()).optional(),
|
|
80
|
+
skills_referenced: z.array(z.string()),
|
|
81
|
+
last_reviewed_sha: z.string(),
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Zod schema describing the internal Finding shape (for tests + cross-check
|
|
85
|
+
* Pass 2 independentFindings). The wire equivalent is `findingItemSchema`
|
|
86
|
+
* which does NOT have severity.
|
|
87
|
+
*/
|
|
88
|
+
export const findingSchema = findingItemSchema.extend({
|
|
89
|
+
severity: severitySchema,
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* Flatten wire-shape `Review.critical_findings / minor_findings /
|
|
93
|
+
* preexisting_findings` into a single `Finding[]` with severity tagged.
|
|
94
|
+
* Preserves ordering: criticals first, then minors, then preexistings.
|
|
95
|
+
*/
|
|
96
|
+
export function flattenFindings(review) {
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const f of review.critical_findings)
|
|
99
|
+
out.push({ ...f, severity: 'critical' });
|
|
100
|
+
for (const f of review.minor_findings)
|
|
101
|
+
out.push({ ...f, severity: 'minor' });
|
|
102
|
+
for (const f of review.preexisting_findings)
|
|
103
|
+
out.push({ ...f, severity: 'preexisting' });
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Inverse of `flattenFindings`: split a flat `Finding[]` back into the
|
|
108
|
+
* three wire-shape arrays. Used at writeback time after multi-pass
|
|
109
|
+
* aggregation has produced the final flat list.
|
|
110
|
+
*/
|
|
111
|
+
export function unflattenFindings(findings) {
|
|
112
|
+
const stripSeverity = (f) => {
|
|
113
|
+
const { severity: _s, ...rest } = f;
|
|
114
|
+
return rest;
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
critical_findings: findings.filter((f) => f.severity === 'critical').map(stripSeverity),
|
|
118
|
+
minor_findings: findings.filter((f) => f.severity === 'minor').map(stripSeverity),
|
|
119
|
+
preexisting_findings: findings.filter((f) => f.severity === 'preexisting').map(stripSeverity),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Derive `summary_counts` from a flat `Finding[]` list. Canonical
|
|
124
|
+
* source-of-truth used by the orchestrator after flattening, to
|
|
125
|
+
* overwrite the model's potentially-drifted counts.
|
|
126
|
+
*/
|
|
127
|
+
export function deriveSummaryCounts(findings) {
|
|
128
|
+
return {
|
|
129
|
+
critical: findings.filter((f) => f.severity === 'critical').length,
|
|
130
|
+
minor: findings.filter((f) => f.severity === 'minor').length,
|
|
131
|
+
preexisting: findings.filter((f) => f.severity === 'preexisting').length,
|
|
132
|
+
resolved_from_prior: 0,
|
|
133
|
+
still_open: 0,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Derive `skills_referenced` from a flat `Finding[]` list, preserving
|
|
138
|
+
* citation order (first appearance wins) and deduplicating.
|
|
139
|
+
*/
|
|
140
|
+
export function deriveSkillsReferenced(findings) {
|
|
141
|
+
const seen = new Set();
|
|
142
|
+
const out = [];
|
|
143
|
+
for (const f of findings) {
|
|
144
|
+
if (seen.has(f.skill))
|
|
145
|
+
continue;
|
|
146
|
+
seen.add(f.skill);
|
|
147
|
+
out.push(f.skill);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Test helper: build a wire-shape `Review` from a flat `Finding[]` list.
|
|
153
|
+
* Tests historically built reviews with a flat `findings: [...]` field; the
|
|
154
|
+
* wire shape (separate severity arrays + per_skill_scan + last_reviewed_sha
|
|
155
|
+
* required) is more verbose. This helper keeps fixtures short — pass a
|
|
156
|
+
* flat list, get back a valid wire-shape Review with derived counts and
|
|
157
|
+
* skills.
|
|
158
|
+
*
|
|
159
|
+
* Production code should NOT use this; it constructs reviews from AI output
|
|
160
|
+
* directly. This is purely for test ergonomics.
|
|
161
|
+
*/
|
|
162
|
+
export function buildReviewFromFindings(opts) {
|
|
163
|
+
const split = unflattenFindings(opts.findings);
|
|
164
|
+
// Default status_header is derived from severity, NOT just emptiness.
|
|
165
|
+
// The App's original buildReviewFromFindings defaulted to
|
|
166
|
+
// 'critical findings' for ANY non-empty list, including minor-only and
|
|
167
|
+
// preexisting-only inputs. That was a bug (caught by clud-bug-review
|
|
168
|
+
// on PR #158): a review with only minor findings should be 'clean', not
|
|
169
|
+
// 'critical findings'. Fixed here on port to core.
|
|
170
|
+
//
|
|
171
|
+
// Callers that need the old behavior can pass `status_header` explicitly.
|
|
172
|
+
// Callers that want SPEC §1.8.1 semantics (the default) get the correct
|
|
173
|
+
// bucket: criticals present → 'critical findings'; else → 'clean'.
|
|
174
|
+
const hasCritical = opts.findings.some((f) => f.severity === 'critical');
|
|
175
|
+
const defaultStatus = hasCritical ? 'critical findings' : 'clean';
|
|
176
|
+
return {
|
|
177
|
+
status_header: opts.status_header ?? defaultStatus,
|
|
178
|
+
summary_counts: deriveSummaryCounts(opts.findings),
|
|
179
|
+
skills_referenced: deriveSkillsReferenced(opts.findings),
|
|
180
|
+
per_skill_scan: opts.per_skill_scan ?? [],
|
|
181
|
+
critical_findings: split.critical_findings,
|
|
182
|
+
minor_findings: split.minor_findings,
|
|
183
|
+
preexisting_findings: split.preexisting_findings,
|
|
184
|
+
...(opts.dedicated_sections !== undefined
|
|
185
|
+
? { dedicated_sections: opts.dedicated_sections }
|
|
186
|
+
: {}),
|
|
187
|
+
...(opts.diagnostics !== undefined ? { diagnostics: opts.diagnostics } : {}),
|
|
188
|
+
last_reviewed_sha: opts.last_reviewed_sha ?? '',
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// D.2.5 — cross-check pass schema
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
/**
|
|
195
|
+
* Per-finding verdict from a cross-check pass. The pass2 model echoes
|
|
196
|
+
* back Pass 1's findings by 0-indexed `pass1Index` + `agreed`/`disagreed`
|
|
197
|
+
* + rationale. The aggregator stitches these into
|
|
198
|
+
* `MultiPassReview.findings[].attributions`.
|
|
199
|
+
*
|
|
200
|
+
* Cross-check Pass 2 operates on a flat finding list (its own
|
|
201
|
+
* representation), so its independentFindings carry severity — uses the
|
|
202
|
+
* legacy `findingSchema` shape.
|
|
203
|
+
*/
|
|
204
|
+
export const crossCheckVerdictSchema = z.object({
|
|
205
|
+
pass1Index: z.number().int().min(0),
|
|
206
|
+
verdict: z.enum(['agreed', 'disagreed']),
|
|
207
|
+
rationale: z.string().optional(),
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* Full cross-check response. Pass 2 outputs verdicts on Pass-1 findings
|
|
211
|
+
* plus its own independent finds (in the internal `findingSchema` shape
|
|
212
|
+
* with severity, since cross-check works on already-flattened lists).
|
|
213
|
+
*/
|
|
214
|
+
export const crossCheckSchema = z.object({
|
|
215
|
+
verdicts: z.array(crossCheckVerdictSchema),
|
|
216
|
+
independentFindings: z.array(findingSchema),
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=review-schema-zod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-schema-zod.js","sourceRoot":"","sources":["../../src/core/review-schema-zod.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,2EAA2E;AAC3E,6DAA6D;AAC7D,2EAA2E;AAC3E,2EAA2E;AAC3E,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AACrE,yEAAyE;AACzE,yCAAyC;AACzC,EAAE;AACF,6EAA6E;AAC7E,4DAA4D;AAC5D,8EAA8E;AAC9E,0EAA0E;AAC1E,YAAY;AAEZ,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wEAAwE;AACxE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,CAAU,CAAC;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAGrD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB;IACnB,OAAO;IACP,MAAM;CACE,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;AAG7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACpC,CAAC,CAAC;AAGH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAGH,mEAAmE;AACnE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;CACrC,CAAC,CAAC;AAGH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,aAAa,EAAE,kBAAkB;IACjC,cAAc,EAAE,mBAAmB;IACnC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IAC/C,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAC7C,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAC1C,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAChD,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,QAAQ,EAAE;IAC9D,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3C,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACtC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;CAC9B,CAAC,CAAC;AAeH;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC;IACpD,QAAQ,EAAE,cAAc;CACzB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,iBAAiB;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IACnF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,cAAc;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7E,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,oBAAoB;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;IACzF,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAmB;IAKnD,MAAM,aAAa,GAAG,CAAC,CAAU,EAAe,EAAE;QAChD,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,OAAO;QACL,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;QACvF,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;QACjF,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;KAC9F,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAmB;IACrD,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;QAClE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;QAC5D,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,MAAM;QACxE,mBAAmB,EAAE,CAAC;QACtB,UAAU,EAAE,CAAC;KACd,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAmB;IACxD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,SAAS;QAChC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAOvC;IACC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/C,sEAAsE;IACtE,0DAA0D;IAC1D,uEAAuE;IACvE,qEAAqE;IACrE,wEAAwE;IACxE,mDAAmD;IACnD,EAAE;IACF,0EAA0E;IAC1E,wEAAwE;IACxE,mEAAmE;IACnE,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC;IAClE,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,aAAa;QAClD,cAAc,EAAE,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAClD,iBAAiB,EAAE,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC;QACxD,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,EAAE;QACzC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,SAAS;YACvC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,EAAE;KAChD,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC;IAC1C,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;CAC5C,CAAC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type JSONSchemaObject = Record<string, unknown>;
|
|
2
|
+
export declare const REVIEW_SCHEMA: JSONSchemaObject;
|
|
3
|
+
export declare function serializedReviewSchema(): string;
|
|
4
|
+
export type FindingSeverity = 'critical' | 'minor' | 'preexisting';
|
|
5
|
+
export interface ReviewFinding {
|
|
6
|
+
skill: string;
|
|
7
|
+
summary: string;
|
|
8
|
+
file?: string;
|
|
9
|
+
line?: number;
|
|
10
|
+
reasoning?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface PerSkillScanItem {
|
|
13
|
+
skill: string;
|
|
14
|
+
outcome: string;
|
|
15
|
+
}
|
|
16
|
+
export interface DedicatedSection {
|
|
17
|
+
section_name: string;
|
|
18
|
+
skill: string;
|
|
19
|
+
findings: ReviewFinding[];
|
|
20
|
+
}
|
|
21
|
+
export interface ReviewSummaryCounts {
|
|
22
|
+
critical: number;
|
|
23
|
+
minor: number;
|
|
24
|
+
preexisting: number;
|
|
25
|
+
resolved_from_prior: number;
|
|
26
|
+
still_open: number;
|
|
27
|
+
}
|
|
28
|
+
export type ReviewStatusHeader = 'critical findings' | 'clean' | 'bare';
|
|
29
|
+
export interface ReviewData {
|
|
30
|
+
status_header: ReviewStatusHeader | string;
|
|
31
|
+
summary_counts: ReviewSummaryCounts;
|
|
32
|
+
per_skill_scan: PerSkillScanItem[];
|
|
33
|
+
critical_findings: ReviewFinding[];
|
|
34
|
+
minor_findings: ReviewFinding[];
|
|
35
|
+
preexisting_findings: ReviewFinding[];
|
|
36
|
+
skills_referenced: string[];
|
|
37
|
+
last_reviewed_sha: string;
|
|
38
|
+
dedicated_sections?: DedicatedSection[];
|
|
39
|
+
diagnostics?: string[];
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=review-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-schema.d.ts","sourceRoot":"","sources":["../../src/core/review-schema.ts"],"names":[],"mappings":"AAqCA,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA4ChD,eAAO,MAAM,aAAa,EAAE,gBAgF3B,CAAC;AAMF,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAUD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,OAAO,GAAG,MAAM,CAAC;AAExE,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,kBAAkB,GAAG,MAAM,CAAC;IAC3C,cAAc,EAAE,mBAAmB,CAAC;IACpC,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,iBAAiB,EAAE,aAAa,EAAE,CAAC;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,oBAAoB,EAAE,aAAa,EAAE,CAAC;IACtC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// JSON Schema for clud-bug review structured output (0.0.O / v0.6.22).
|
|
2
|
+
//
|
|
3
|
+
// Passed to claude-code-action via `claude_args: --json-schema '<JSON>'`.
|
|
4
|
+
// The Agent SDK validates the LLM's emitted JSON against this schema and
|
|
5
|
+
// re-prompts on mismatch (internal retry; not a clud-bug-level loop).
|
|
6
|
+
//
|
|
7
|
+
// Schema design choices:
|
|
8
|
+
// - Flat top-level — composite-action outputs are a single string, so we
|
|
9
|
+
// fromJSON() once and pluck fields. No deep nesting that would force
|
|
10
|
+
// extra path traversal in the post-step shell.
|
|
11
|
+
// - Word/char caps in `description:` — the SDK doc names these as the
|
|
12
|
+
// primary lever for keeping output cheap. They're advisory (the SDK
|
|
13
|
+
// does not enforce numeric caps; the LLM treats them as instruction).
|
|
14
|
+
// 0.0.X already lives in the prompt, so the schema description here is
|
|
15
|
+
// a complementary belt-and-suspenders signal.
|
|
16
|
+
// - Required minimum — only the fields a renderer absolutely needs to
|
|
17
|
+
// produce a valid summary comment. Counts are always required (the
|
|
18
|
+
// stats header + status block depend on them); finding arrays are
|
|
19
|
+
// required but may be empty (a clean review has 0 findings, not
|
|
20
|
+
// missing arrays).
|
|
21
|
+
// - `additionalProperties: false` on every object — schema-strict mode.
|
|
22
|
+
// Anthropic's structured-outputs doc explicitly recommends this to
|
|
23
|
+
// keep the model from inventing fields.
|
|
24
|
+
//
|
|
25
|
+
// Bumped via deliberate edit; not derived from a TypeScript type. The
|
|
26
|
+
// rendering side (./render-review.ts) treats unknown fields permissively
|
|
27
|
+
// — schema and renderer can drift up to one minor version safely.
|
|
28
|
+
const FINDING_ITEM = {
|
|
29
|
+
type: 'object',
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
properties: {
|
|
32
|
+
skill: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
description: 'The skill name in brackets, e.g. "critical-issues-only". Must match a loaded skill or "(none)".',
|
|
35
|
+
},
|
|
36
|
+
file: {
|
|
37
|
+
type: 'string',
|
|
38
|
+
description: 'Path of the affected file relative to repo root. Optional when the finding is cross-cutting.',
|
|
39
|
+
},
|
|
40
|
+
line: {
|
|
41
|
+
type: 'integer',
|
|
42
|
+
minimum: 1,
|
|
43
|
+
description: 'Line number in the affected file. Required when `file` is set.',
|
|
44
|
+
},
|
|
45
|
+
summary: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'One sentence stating the claim. Max ~20 words; no trailing period (the renderer adds one).',
|
|
48
|
+
},
|
|
49
|
+
reasoning: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Evidence anchor + suggested fix. Max ~80 words. Rendered inside <details> block; can be omitted for self-evident findings.',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
required: ['skill', 'summary'],
|
|
55
|
+
};
|
|
56
|
+
const PER_SKILL_SCAN_ITEM = {
|
|
57
|
+
type: 'object',
|
|
58
|
+
additionalProperties: false,
|
|
59
|
+
properties: {
|
|
60
|
+
skill: { type: 'string' },
|
|
61
|
+
outcome: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
description: 'One sentence describing what the skill found. Max ~15 words. Examples: "scanned all paths. 2 critical findings below.", "0 findings.", "not applicable to this diff."',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ['skill', 'outcome'],
|
|
67
|
+
};
|
|
68
|
+
export const REVIEW_SCHEMA = {
|
|
69
|
+
type: 'object',
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
properties: {
|
|
72
|
+
status_header: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
enum: ['critical findings', 'clean', 'bare'],
|
|
75
|
+
description: 'Strict-mode opt-in repos: `critical findings` when ANY 🔴 finding exists, otherwise `clean`. Non-strict-mode repos (the default): emit `bare` — the renderer produces a `## 🐛 Clud Bug review` H2 with no suffix, matching the v0.6.21- behaviour. Check .claude/skills/.clud-bug.json for `strictMode: true` to pick critical/clean vs bare.',
|
|
76
|
+
},
|
|
77
|
+
summary_counts: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
additionalProperties: false,
|
|
80
|
+
properties: {
|
|
81
|
+
critical: { type: 'integer', minimum: 0 },
|
|
82
|
+
minor: { type: 'integer', minimum: 0 },
|
|
83
|
+
preexisting: { type: 'integer', minimum: 0 },
|
|
84
|
+
resolved_from_prior: { type: 'integer', minimum: 0 },
|
|
85
|
+
still_open: { type: 'integer', minimum: 0 },
|
|
86
|
+
},
|
|
87
|
+
required: ['critical', 'minor', 'preexisting', 'resolved_from_prior', 'still_open'],
|
|
88
|
+
},
|
|
89
|
+
per_skill_scan: {
|
|
90
|
+
type: 'array',
|
|
91
|
+
description: 'One entry per LOADED skill — even silent ones. Empty when no skills are installed.',
|
|
92
|
+
items: PER_SKILL_SCAN_ITEM,
|
|
93
|
+
},
|
|
94
|
+
critical_findings: {
|
|
95
|
+
type: 'array',
|
|
96
|
+
description: 'NEW 🔴 findings (bugs, security, perf, missing test coverage). May be empty.',
|
|
97
|
+
items: FINDING_ITEM,
|
|
98
|
+
},
|
|
99
|
+
minor_findings: {
|
|
100
|
+
type: 'array',
|
|
101
|
+
description: 'NEW 🟡 findings (nits, style, observations). May be empty.',
|
|
102
|
+
items: FINDING_ITEM,
|
|
103
|
+
},
|
|
104
|
+
preexisting_findings: {
|
|
105
|
+
type: 'array',
|
|
106
|
+
description: 'NEW 🟣 findings (issues that pre-date this PR). May be empty.',
|
|
107
|
+
items: FINDING_ITEM,
|
|
108
|
+
},
|
|
109
|
+
dedicated_sections: {
|
|
110
|
+
type: 'array',
|
|
111
|
+
description: 'Per-dedicated-mode-skill section blocks. Each item carries the section header text and its findings.',
|
|
112
|
+
items: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
additionalProperties: false,
|
|
115
|
+
properties: {
|
|
116
|
+
section_name: { type: 'string', description: 'Human-readable section title, e.g. "Brand voice".' },
|
|
117
|
+
skill: { type: 'string', description: 'The dedicated skill name.' },
|
|
118
|
+
findings: { type: 'array', items: FINDING_ITEM },
|
|
119
|
+
},
|
|
120
|
+
required: ['section_name', 'skill', 'findings'],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
diagnostics: {
|
|
124
|
+
type: 'array',
|
|
125
|
+
description: '0.0.T tee-hint diagnostics. One line per `head -c` cap that fired during fetch. Empty when no truncation occurred.',
|
|
126
|
+
items: { type: 'string' },
|
|
127
|
+
},
|
|
128
|
+
skills_referenced: {
|
|
129
|
+
type: 'array',
|
|
130
|
+
description: 'Names of every skill cited in any finding. Empty list (or ["(none)"]) when no skill applied.',
|
|
131
|
+
items: { type: 'string' },
|
|
132
|
+
},
|
|
133
|
+
last_reviewed_sha: {
|
|
134
|
+
type: 'string',
|
|
135
|
+
description: 'The HEAD SHA at review time, used by the incremental-diff handshake. Set to the literal value of the workflow env var $HEAD_SHA.',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
required: [
|
|
139
|
+
'status_header',
|
|
140
|
+
'summary_counts',
|
|
141
|
+
'per_skill_scan',
|
|
142
|
+
'critical_findings',
|
|
143
|
+
'minor_findings',
|
|
144
|
+
'preexisting_findings',
|
|
145
|
+
'skills_referenced',
|
|
146
|
+
'last_reviewed_sha',
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
// Serialize the schema for inclusion in workflow templates as the
|
|
150
|
+
// `--json-schema '<JSON>'` argument. Single-line (the workflow YAML uses
|
|
151
|
+
// the pipe block; single-quoted JSON inside that needs to stay flat to
|
|
152
|
+
// avoid YAML parser surprises with embedded newlines).
|
|
153
|
+
export function serializedReviewSchema() {
|
|
154
|
+
return JSON.stringify(REVIEW_SCHEMA);
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=review-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-schema.js","sourceRoot":"","sources":["../../src/core/review-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { type Finding, type Review } from './review-schema-zod.js';
|
|
2
|
+
/** Protocol version this implementation emits. */
|
|
3
|
+
export declare const PROTOCOL_VERSION = "0.1.0";
|
|
4
|
+
/** "Written by" tag for the App writeback (SPEC §6.1). */
|
|
5
|
+
export declare const WRITTEN_BY = "clud-bug[bot]";
|
|
6
|
+
export declare const SEVERITY_EMOJI: {
|
|
7
|
+
readonly critical: "🔴";
|
|
8
|
+
readonly minor: "🟡";
|
|
9
|
+
readonly preexisting: "🟣";
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* One parsed finding suitable for the SPEC §1.8.1 Resolved / Still-open
|
|
13
|
+
* blocks. Mirrors `ParsedFinding` from `./diff-findings.ts`; declared
|
|
14
|
+
* here as a structural interface (not re-imported) so callers without
|
|
15
|
+
* `diff-findings` in scope can still construct the input.
|
|
16
|
+
*/
|
|
17
|
+
export interface RenderedFindingRef {
|
|
18
|
+
file: string;
|
|
19
|
+
line: number;
|
|
20
|
+
severity: 'critical' | 'minor' | 'preexisting';
|
|
21
|
+
skillName: string;
|
|
22
|
+
summary: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* SPEC §6.7.3 cache telemetry — per-invocation token counts from the
|
|
26
|
+
* Anthropic-family `usage` block. When present, the renderer emits a
|
|
27
|
+
* `<!-- cache: ... -->` HTML comment immediately below the
|
|
28
|
+
* `<!-- review-sha: ... -->` metadata line so downstream cost analysis
|
|
29
|
+
* tooling can audit cache behaviour from the committed doc-file.
|
|
30
|
+
*/
|
|
31
|
+
export interface CacheStats {
|
|
32
|
+
/** `cache_read_input_tokens` from the Anthropic usage block. */
|
|
33
|
+
cachedInputTokens: number;
|
|
34
|
+
/** `cache_creation_input_tokens` from the Anthropic usage block. */
|
|
35
|
+
cacheCreationInputTokens: number;
|
|
36
|
+
}
|
|
37
|
+
export interface RenderReviewFileInput {
|
|
38
|
+
review: Review;
|
|
39
|
+
prNumber: number;
|
|
40
|
+
/** 40-char head SHA. Pinned to `<!-- review-sha: ... -->`. */
|
|
41
|
+
headSha: string;
|
|
42
|
+
/** GitHub PR URL — appended verbatim to the trailing rule. */
|
|
43
|
+
prUrl: string;
|
|
44
|
+
/**
|
|
45
|
+
* Findings present in the prior `docs/reviews/PR-<n>.md` that are NOT
|
|
46
|
+
* present in this round's `review`. When non-empty, emits the SPEC
|
|
47
|
+
* §1.8.1 `**Resolved this round:**` block AFTER the severity buckets
|
|
48
|
+
* and BEFORE the trailing `---` separator. Omitted entirely when
|
|
49
|
+
* empty/undefined (SPEC §1.8.1: blocks MUST be omitted when empty).
|
|
50
|
+
*
|
|
51
|
+
* Produced by `diffFindings()` from `./diff-findings.ts`.
|
|
52
|
+
*/
|
|
53
|
+
resolvedFindings?: RenderedFindingRef[];
|
|
54
|
+
/**
|
|
55
|
+
* Findings present in BOTH the prior `docs/reviews/PR-<n>.md` AND
|
|
56
|
+
* this round's `review` — the persistent ones. When non-empty, emits
|
|
57
|
+
* the SPEC §1.8.1 `**Still open:**` block AFTER `**Resolved this
|
|
58
|
+
* round:**` and before the trailing `---` separator. Omitted entirely
|
|
59
|
+
* when empty/undefined.
|
|
60
|
+
*
|
|
61
|
+
* Produced by `diffFindings()` from `./diff-findings.ts`.
|
|
62
|
+
*/
|
|
63
|
+
stillOpenFindings?: RenderedFindingRef[];
|
|
64
|
+
/**
|
|
65
|
+
* SPEC §6.7.3 cache telemetry. When present, emits a
|
|
66
|
+
* `<!-- cache: <read> read · <created> created -->` HTML comment
|
|
67
|
+
* immediately below the `<!-- review-sha: ... -->` metadata line.
|
|
68
|
+
* Omitted entirely when undefined (this comment is OPTIONAL per the
|
|
69
|
+
* SPEC, but SHOULD be implemented for cost-analysis tooling).
|
|
70
|
+
*/
|
|
71
|
+
cacheStats?: CacheStats;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Renders the review object to the SPEC §1.8.1 markdown template.
|
|
75
|
+
*
|
|
76
|
+
* Pure: no I/O, no time-of-day, no provider info — fixture-stable.
|
|
77
|
+
*
|
|
78
|
+
* NB: This produces the doc-file shape (`# clud-bug review — PR #N` H1).
|
|
79
|
+
* The CLI's `renderReview` produces the PR-comment shape (`## 🐛 Clud Bug
|
|
80
|
+
* review` H2). Both are valid review outputs; SPEC §6.2 says they share
|
|
81
|
+
* the underlying finding data but differ in container.
|
|
82
|
+
*/
|
|
83
|
+
export declare function renderReviewFile(input: RenderReviewFileInput): string;
|
|
84
|
+
/**
|
|
85
|
+
* Provenance label for a single finding's attribution from one pass.
|
|
86
|
+
* Mirrors the App's `PassSource` discriminator.
|
|
87
|
+
*
|
|
88
|
+
* `mode === 'cross-check'`:
|
|
89
|
+
* - 'first' → finding raised by Pass 1
|
|
90
|
+
* - 'agreed' → later pass agreed
|
|
91
|
+
* - 'disagreed' → later pass disagreed
|
|
92
|
+
* - 'independent' → later pass surfaced this finding independently
|
|
93
|
+
*
|
|
94
|
+
* `mode === 'consensus'`:
|
|
95
|
+
* - 'first' → finding tuple unique to Pass 1
|
|
96
|
+
* - 'independent' → finding tuple unique to Pass N (N > 1)
|
|
97
|
+
* - 'agreed' → finding tuple appeared in 2+ passes (consensus)
|
|
98
|
+
*/
|
|
99
|
+
export type PassSource = 'first' | 'agreed' | 'disagreed' | 'independent';
|
|
100
|
+
export interface PassAttribution {
|
|
101
|
+
/** 1-indexed pass number — matches the spec's "[Pass N]" label. */
|
|
102
|
+
passNumber: number;
|
|
103
|
+
/** Role display name, e.g. "Beetle". */
|
|
104
|
+
roleName: string;
|
|
105
|
+
/** Model slug for this pass — used by the renderer for the "· Sonnet 4.6" tail. */
|
|
106
|
+
model: string;
|
|
107
|
+
/** Provenance — see PassSource doc. */
|
|
108
|
+
source: PassSource;
|
|
109
|
+
/** Optional one-line note from the pass, e.g. cross-check rationale. */
|
|
110
|
+
note?: string;
|
|
111
|
+
}
|
|
112
|
+
export interface UnifiedFinding extends Finding {
|
|
113
|
+
/** One PassAttribution per pass involved with this finding. Order: by passNumber. */
|
|
114
|
+
attributions: PassAttribution[];
|
|
115
|
+
}
|
|
116
|
+
/** Effective resolution verdict the multi-pass orchestrator emits. */
|
|
117
|
+
export type MultiPassVerdict = 'request_changes' | 'review_only' | 'clean';
|
|
118
|
+
/** Effective multi-pass mode. */
|
|
119
|
+
export type ReviewPassMode = 'cross-check' | 'consensus' | 'independent';
|
|
120
|
+
export interface MultiPassReview {
|
|
121
|
+
/** Status header — derived from aggregated findings + mode resolution rules. */
|
|
122
|
+
status_header: Review['status_header'];
|
|
123
|
+
/** Summary counts, derived from the unified findings list. */
|
|
124
|
+
summary_counts: Review['summary_counts'];
|
|
125
|
+
/** Skills cited at least once across any pass. */
|
|
126
|
+
skills_referenced: string[];
|
|
127
|
+
/** Unified findings, with per-pass attribution. */
|
|
128
|
+
findings: UnifiedFinding[];
|
|
129
|
+
/** Effective mode (for the renderer's "(N passes · mode)" header line). */
|
|
130
|
+
mode: ReviewPassMode;
|
|
131
|
+
/** Number of passes that actually ran. */
|
|
132
|
+
passCount: number;
|
|
133
|
+
/** Role labels per pass, parallel to passCount. Used by the renderer. */
|
|
134
|
+
roles: Array<{
|
|
135
|
+
passNumber: number;
|
|
136
|
+
roleName: string;
|
|
137
|
+
model: string;
|
|
138
|
+
}>;
|
|
139
|
+
/** Resolution verdict — see App's multi-pass-aggregator for derivation. */
|
|
140
|
+
verdict: MultiPassVerdict;
|
|
141
|
+
}
|
|
142
|
+
export interface RenderMultiPassMarkdownInput {
|
|
143
|
+
review: MultiPassReview;
|
|
144
|
+
prNumber: number;
|
|
145
|
+
/** 40-char head SHA. Pinned to `<!-- review-sha: ... -->`. */
|
|
146
|
+
headSha: string;
|
|
147
|
+
/** GitHub PR URL — appended verbatim to the trailing rule. */
|
|
148
|
+
prUrl: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Renders a multi-pass review with per-pass attribution lines.
|
|
152
|
+
*
|
|
153
|
+
* Output layout (SPEC §1.8.5):
|
|
154
|
+
*
|
|
155
|
+
* # clud-bug review — PR #N (M passes · mode)
|
|
156
|
+
* <!-- protocol-version: ... -->
|
|
157
|
+
* <!-- written-by: clud-bug[bot] -->
|
|
158
|
+
* <!-- review-sha: ... -->
|
|
159
|
+
* <!-- passes: M -->
|
|
160
|
+
* <!-- mode: cross-check|consensus|independent -->
|
|
161
|
+
*
|
|
162
|
+
* **Summary:** ... · **Verdict:** request_changes / review_only / clean
|
|
163
|
+
*
|
|
164
|
+
* **Reviewers:**
|
|
165
|
+
* - Pass 1 — Beetle · anthropic/claude-sonnet-4.6
|
|
166
|
+
* - Pass 2 — Wasp · anthropic/claude-opus-4.7
|
|
167
|
+
*
|
|
168
|
+
* **Skills cited:** ...
|
|
169
|
+
*
|
|
170
|
+
* **Findings:**
|
|
171
|
+
*
|
|
172
|
+
* ### (red) Critical
|
|
173
|
+
* - [Pass 1 — Beetle · Sonnet 4.6] auth.ts:42 — race-conditions: Race condition
|
|
174
|
+
* Reasoning: ...
|
|
175
|
+
* [Pass 2 — Wasp · Opus 4.7]: (check) AGREED — same finding identified independently.
|
|
176
|
+
*
|
|
177
|
+
* ...
|
|
178
|
+
*
|
|
179
|
+
* ---
|
|
180
|
+
* [Link to PR](...)
|
|
181
|
+
*
|
|
182
|
+
* Pure: no I/O, no time-of-day, fixture-stable.
|
|
183
|
+
*/
|
|
184
|
+
export declare function renderMultiPassMarkdown(input: RenderMultiPassMarkdownInput): string;
|
|
185
|
+
/** SPEC §6.1 / §1.8 path. The App's Octokit writeback uses this. */
|
|
186
|
+
export declare function reviewFilePath(prNumber: number): string;
|
|
187
|
+
/**
|
|
188
|
+
* SPEC §6.1 commit message: exactly `[skip-logmind] clud-bug review: PR #<n>`.
|
|
189
|
+
* The `[skip-logmind]` prefix tells `check-decisions.yml` to ignore this
|
|
190
|
+
* commit (SPEC §6.4). The App's Octokit writeback uses this.
|
|
191
|
+
*/
|
|
192
|
+
export declare function reviewCommitMessage(prNumber: number): string;
|
|
193
|
+
//# sourceMappingURL=review-writeback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-writeback.d.ts","sourceRoot":"","sources":["../../src/core/review-writeback.ts"],"names":[],"mappings":"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"}
|