iterate-plugin 2.7.3 → 2.8.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.
- package/README.md +13 -0
- package/README.zh-CN.md +13 -0
- package/dist/config-loader.js +6 -1
- package/dist/evidence.js +161 -0
- package/dist/git-scope.js +101 -0
- package/dist/meta-review.js +76 -1
- package/dist/method-scope.js +173 -0
- package/dist/review-scope.js +187 -0
- package/dist/review.js +226 -18
- package/dist/skill-prompt.js +69 -29
- package/dist/tools/fix.js +12 -2
- package/dist/tools/review.js +77 -5
- package/lib/client.js +3 -14
- package/package.json +1 -1
- package/src/client/index.ts +9 -12
- package/src/config-loader.ts +6 -1
- package/src/evidence.ts +213 -0
- package/src/git-scope.ts +129 -0
- package/src/meta-review.ts +94 -1
- package/src/method-scope.ts +201 -0
- package/src/review-scope.ts +203 -0
- package/src/review.ts +313 -18
- package/src/skill-prompt.ts +69 -29
- package/src/tools/fix.ts +13 -2
- package/src/tools/review.ts +91 -5
- package/src/types.ts +6 -1
package/src/tools/review.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
2
2
|
import type { JsonValue } from '@deepseek-ai/dsh-session'
|
|
3
3
|
import { loadEffectiveConfig, resolveProjectRoot } from '../config-loader.ts'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
buildReviewPlan,
|
|
6
|
+
buildReviewReport,
|
|
7
|
+
sanitizeRounds,
|
|
8
|
+
validateRoundsSchema,
|
|
9
|
+
} from '../review.ts'
|
|
5
10
|
import { buildFinalReviewReport, metaReviewReport } from '../meta-review.ts'
|
|
11
|
+
import { evidenceToPlain, verifyFindings } from '../evidence.ts'
|
|
12
|
+
import {
|
|
13
|
+
collectScopeFiles,
|
|
14
|
+
computeCoverage,
|
|
15
|
+
coverageToDict,
|
|
16
|
+
} from '../review-scope.ts'
|
|
17
|
+
import { resolveChangedFiles } from '../git-scope.ts'
|
|
6
18
|
import type { KnownIntentional, ReviewFinding, ReviewReport, ReviewRound } from '../types.ts'
|
|
19
|
+
import type { CoverageResult } from '../review-scope.ts'
|
|
7
20
|
|
|
8
21
|
/** Default round cap when neither the arg nor config provides one. */
|
|
9
22
|
const DEFAULT_MAX_REVIEW_ROUNDS = 3
|
|
@@ -94,6 +107,21 @@ export function registerReviewTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
94
107
|
found: { type: 'boolean' },
|
|
95
108
|
plan: { type: 'json' },
|
|
96
109
|
report: { type: 'json' },
|
|
110
|
+
schemaValidation: {
|
|
111
|
+
type: 'json',
|
|
112
|
+
description:
|
|
113
|
+
'For `aggregate`: per-round schema validation results (round, valid, issues). ' +
|
|
114
|
+
'Present only when reviewer.output_schema_validation is enabled; the workflow ' +
|
|
115
|
+
'retries rounds with valid=false (≤2 times) before forwarding findings.',
|
|
116
|
+
},
|
|
117
|
+
evidence: { type: 'json' },
|
|
118
|
+
coverage: {
|
|
119
|
+
type: 'json',
|
|
120
|
+
description:
|
|
121
|
+
'For `meta-review`: prompt-informative scope coverage result ' +
|
|
122
|
+
'(assigned vs self-reported reads). Present only when ' +
|
|
123
|
+
'reviewer.coverage_validation is enabled and readFiles were supplied.',
|
|
124
|
+
},
|
|
97
125
|
finalReport: { type: 'json' },
|
|
98
126
|
error: { type: 'string' },
|
|
99
127
|
},
|
|
@@ -118,7 +146,23 @@ export function registerReviewTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
118
146
|
const maxReviewRounds = args.maxReviewRounds ?? config.max_rounds ?? DEFAULT_MAX_REVIEW_ROUNDS
|
|
119
147
|
const knownIntentional = (config.personalization as { known_intentional?: KnownIntentional[] } | undefined)
|
|
120
148
|
?.known_intentional
|
|
121
|
-
|
|
149
|
+
// changed-only scope: resolve the changed-file set against
|
|
150
|
+
// git.target_branch before building the plan so reviewers get the
|
|
151
|
+
// concrete file list (and the plan auto-falls back to full when there
|
|
152
|
+
// are no changes). git failures degrade to a full-scope plan.
|
|
153
|
+
let changedFiles: string[] | undefined
|
|
154
|
+
if (config.review?.scope === 'changed-only') {
|
|
155
|
+
const gitScope = await resolveChangedFiles(projectRoot, config.git?.target_branch ?? 'main')
|
|
156
|
+
changedFiles = gitScope.changedFiles
|
|
157
|
+
}
|
|
158
|
+
// Full-codebase review: pre-collect the source inventory so
|
|
159
|
+
// buildReviewPlan can batch it into per-chunk reviewer tasks
|
|
160
|
+
// (coverage enforcement).
|
|
161
|
+
let scopeFiles: string[] | undefined
|
|
162
|
+
if (config.review?.scope === 'full') {
|
|
163
|
+
scopeFiles = collectScopeFiles(projectRoot, { scope: 'full' })
|
|
164
|
+
}
|
|
165
|
+
const plan = buildReviewPlan({ config, mode, maxReviewRounds, knownIntentional, changedFiles, scopeFiles })
|
|
122
166
|
return { operation: 'plan', mode, found: true, plan: plan as unknown as JsonValue }
|
|
123
167
|
}
|
|
124
168
|
|
|
@@ -143,16 +187,34 @@ export function registerReviewTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
143
187
|
const maxReviewRounds = args.maxReviewRounds ?? config.max_rounds ?? DEFAULT_MAX_REVIEW_ROUNDS
|
|
144
188
|
const goal = args.goal ?? config.goal ?? ''
|
|
145
189
|
const dimensions = config.dimensions ?? []
|
|
190
|
+
|
|
191
|
+
// Output schema validation gate (reviewer.output_schema_validation,
|
|
192
|
+
// default true): validate every round's findings against the findings
|
|
193
|
+
// schema, then drop schema-invalid entries before the deterministic
|
|
194
|
+
// core so malformed reviewer output can never crash dedupe/sort or
|
|
195
|
+
// leak into fixes. The `schemaValidation` array is surfaced so the
|
|
196
|
+
// workflow can retry failing rounds (≤2 times) with a strict-JSON
|
|
197
|
+
// nudge. When disabled, non-object entries are still dropped for
|
|
198
|
+
// crash-safety.
|
|
199
|
+
const schemaEnabled = config.reviewer?.output_schema_validation !== false
|
|
200
|
+
const schemaValidation = schemaEnabled ? validateRoundsSchema(rounds) : null
|
|
201
|
+
const cleanRounds = sanitizeRounds(rounds, schemaValidation)
|
|
202
|
+
|
|
146
203
|
const report = buildReviewReport({
|
|
147
204
|
mode,
|
|
148
205
|
goal,
|
|
149
206
|
dimensions,
|
|
150
207
|
maxReviewRounds,
|
|
151
|
-
rounds,
|
|
208
|
+
rounds: cleanRounds,
|
|
152
209
|
knownIntentional: args.knownIntentional as KnownIntentional[] | undefined,
|
|
153
210
|
fixedCount: typeof args.fixedCount === 'number' ? args.fixedCount : undefined,
|
|
154
211
|
})
|
|
155
|
-
return {
|
|
212
|
+
return {
|
|
213
|
+
operation: 'aggregate',
|
|
214
|
+
mode,
|
|
215
|
+
report: report as unknown as JsonValue,
|
|
216
|
+
schemaValidation: schemaValidation as unknown as JsonValue | undefined,
|
|
217
|
+
}
|
|
156
218
|
}
|
|
157
219
|
|
|
158
220
|
if (args.operation === 'meta-review') {
|
|
@@ -165,12 +227,36 @@ export function registerReviewTool(ctx: { tools: { register: (def: ReturnType<ty
|
|
|
165
227
|
}
|
|
166
228
|
}
|
|
167
229
|
const audit = metaReviewReport(source)
|
|
168
|
-
|
|
230
|
+
// Hard code-evidence gate (default on): every finding's file/line is
|
|
231
|
+
// validated against real files on disk before folding into the final
|
|
232
|
+
// verdict. Disable via config `reviewer.evidence_validation: false`.
|
|
233
|
+
const evidenceEnabled = config.reviewer?.evidence_validation !== false
|
|
234
|
+
const findings: ReviewFinding[] = Array.isArray(source.findings) ? source.findings : []
|
|
235
|
+
const evidence = evidenceEnabled ? verifyFindings(projectRoot, findings) : null
|
|
236
|
+
// Prompt-informative coverage: compare the reviewer's self-reported
|
|
237
|
+
// reads against the assigned scope inventory (never flips the
|
|
238
|
+
// verdict). Disable via config `reviewer.coverage_validation: false`.
|
|
239
|
+
const coverageEnabled = config.reviewer?.coverage_validation !== false
|
|
240
|
+
let coverage: CoverageResult | null = null
|
|
241
|
+
if (coverageEnabled) {
|
|
242
|
+
const assigned = collectScopeFiles(projectRoot, {
|
|
243
|
+
scope: config.review?.scope === 'changed-only' ? 'changed-only' : 'full',
|
|
244
|
+
})
|
|
245
|
+
const readFiles = Array.isArray((source as unknown as { readFiles?: unknown }).readFiles)
|
|
246
|
+
? ((source as unknown as { readFiles?: unknown }).readFiles as string[])
|
|
247
|
+
: null
|
|
248
|
+
if (readFiles && readFiles.length > 0) {
|
|
249
|
+
coverage = computeCoverage(assigned, readFiles)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const finalReport = buildFinalReviewReport(source, { evidence, coverage })
|
|
169
253
|
return {
|
|
170
254
|
operation: 'meta-review',
|
|
171
255
|
mode,
|
|
172
256
|
found: true,
|
|
173
257
|
report: audit as unknown as JsonValue,
|
|
258
|
+
evidence: evidence ? (evidenceToPlain(evidence) as unknown as JsonValue) : null,
|
|
259
|
+
coverage: coverage ? (coverageToDict(coverage) as unknown as JsonValue) : null,
|
|
174
260
|
finalReport: finalReport as unknown as JsonValue,
|
|
175
261
|
}
|
|
176
262
|
}
|
package/src/types.ts
CHANGED
|
@@ -16,7 +16,12 @@ export interface IterateConfig {
|
|
|
16
16
|
command_whitelist: string[]
|
|
17
17
|
commands: Record<string, string[]>
|
|
18
18
|
}
|
|
19
|
-
reviewer: {
|
|
19
|
+
reviewer: {
|
|
20
|
+
output_schema_validation: boolean
|
|
21
|
+
evidence_validation: boolean
|
|
22
|
+
coverage_validation: boolean
|
|
23
|
+
scope_chunk_size: number
|
|
24
|
+
}
|
|
20
25
|
onboarding?: Record<string, unknown>
|
|
21
26
|
personalization?: Record<string, unknown>
|
|
22
27
|
}
|