@feng0531/dsh-code-review 0.30.0 → 0.30.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.30.2
4
+
5
+ - 对照Agent核心plan失败继续main行为,风险计划异常回退原输入主审查,不传无效假设,保留fallback原因/partial限制。
6
+ - 原调用/时间预算与取消不绕过,不重试计划;主及交互回退287测试通过。
7
+
8
+ ## 0.30.1
9
+
10
+ - 风险请求来源sourceReadCoverage记录本批生成阶段requested/read/unread;未读来源不能以无发现冒充完整核查。
11
+ - search/find与旧批次不算片段读取,报告partial限制,无新调用/权限,285测试通过。
12
+ - 完成主loop核心退出/定位/预算调度复核;agent/templates剩余核查仍待。
13
+
3
14
  ## 0.30.0
4
15
 
5
16
  - Git自动直接上下文改512字面候选index探针,不枚举全tracked;普通tracked有效性及同probe竞态重核保持。
package/README.md CHANGED
@@ -4,7 +4,11 @@
4
4
 
5
5
  ## 当前状态
6
6
 
7
- 当前代码版本为 0.30.0
7
+ 当前代码版本为 0.30.2
8
+
9
+ 风险计划失败时在原预算内回退不带计划的主审查,保留fallback原因与partial限制;不重试无效计划,取消/超时/调用耗尽仍阻断。
10
+
11
+ 风险计划sourceIds会记录本批生成读取片段/未读状态;未读产生partial覆盖限制。search/find不算读,读过片段也不证明条件已核查或缺陷成立,不自动添加调用。
8
12
 
9
13
  Git自动直接依赖上下文仅查询从已捕获源码导出的最多512路径索引探针,不列整个tracked树;累计索引1MiB并在结束核对同探针指纹。SVN沿用原索引限额,此项不冒充SVN等价。
10
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feng0531/dsh-code-review",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
package/src/review.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { correctAnchor } from './anchor-correction.mjs';
2
+ import { riskReadCoverage } from './risk-read-coverage.mjs';
2
3
  import { BUSINESS_GROUP_INSTRUCTIONS, prepareBusinessGroups, validateBusinessGroups } from './business-groups.mjs';
3
4
  import { RISK_PLAN_INSTRUCTIONS, validateRiskPlan } from './risk-plan.mjs';
4
5
  import { prepareInteractionInput } from './interaction-input.mjs';
@@ -161,6 +162,7 @@ export async function reviewSnapshot(snapshot, model, options = {}) {
161
162
  state.riskPlans ??= [];
162
163
  const entry = { status: 'pending', windowIds: batch.windowIds, ...(batch.interaction ? {groupId:batch.interaction.id,sourceMode:'file-interaction'} : {}), risks: [] };
163
164
  state.riskPlans.push(entry);
165
+ try {
164
166
  const response = await executor({ ...enclosingRequest, input: batch.payload, instructions: RISK_PLAN_INSTRUCTIONS });
165
167
  const riskFiles = batch.interaction ? JSON.parse(batch.payload).files : [{ fileId: file.id, edits: changes.edits ?? [] }];
166
168
  const risks = validateRiskPlan(response, riskFiles, scope?.catalog() ?? []);
@@ -168,6 +170,11 @@ export async function reviewSnapshot(snapshot, model, options = {}) {
168
170
  entry.status = 'completed'; entry.risks = risks;
169
171
  batchPayload = JSON.stringify({ ...JSON.parse(batch.payload), riskPlan: risks, riskPlanNotice: '未可信假设而非发现或证据;须验证及寻找反证,不增加读取权限。' });
170
172
  if (!initialInputBudget({ instructions: REVIEW_INSTRUCTIONS, input: batchPayload }, scope, maxInputBytes).fits) throw new Error('Risk-enriched review input exceeds budget');
173
+ } catch(error) {
174
+ enclosingRequest.signal.throwIfAborted();
175
+ entry.status='fallback';entry.reason=error?.message??String(error);entry.risks=[];batchPayload=batch.payload;
176
+ report.limitations.push({fileId:file.id,text:'风险计划未完成,回退原输入主审查:'+entry.reason});
177
+ }
171
178
  }
172
179
  const request = { ...enclosingRequest, input: batchPayload };
173
180
  const auditStart = state.retrievalAudit?.length ?? 0;
@@ -186,6 +193,11 @@ export async function reviewSnapshot(snapshot, model, options = {}) {
186
193
  response = decoded;
187
194
  }
188
195
  }
196
+ if (options.enableRiskPlanning === true && !batch.synthesis) {
197
+ const entry=state.riskPlans.at(-1);
198
+ entry.sourceReadCoverage=riskReadCoverage(entry.risks,(state.retrievalAudit??[]).slice(auditStart),scope?.catalog()??[],input.id);
199
+ if(entry.sourceReadCoverage.some(c=>c.unreadSourceIds.length)) report.limitations.push({fileId:file.id,text:'风险计划请求的部分来源未在本次生成阶段读取;不能视为已核查风险条件或排除问题'});
200
+ }
189
201
  const generated = batch.interaction ? validateInteractionFindings(response, input, batch.interaction, (state.retrievalAudit ?? []).slice(auditStart), scope.catalog()) : validateResponse(response, file, changes);
190
202
  if (batch.synthesis) validateSynthesisReads(generated.findings, changes, (state.retrievalAudit ?? []).slice(auditStart), scope.catalog(), file.id, input.id);
191
203
  if (!batch.interaction && state.sourceMode === 'change-windows') validateWindowFindings(generated.findings, batch.synthesis ? prepared.synthesis.windows : JSON.parse(batch.payload).windows, batch.synthesis === true);
@@ -0,0 +1,6 @@
1
+ // Read occurrence only, never complete source coverage or semantic verification.
2
+ export function riskReadCoverage(risks, audit, catalog, snapshotId){
3
+ const allowed=new Set(catalog.map(s=>s.id));
4
+ const read=new Set(audit.filter(r=>r.kind==='read'&&r.snapshotId===snapshotId&&r.stage==='retrieved-locally'&&Number.isSafeInteger(r.count)&&r.count>0&&allowed.has(r.sourceId)).map(r=>r.sourceId));
5
+ return risks.map(r=>({riskId:r.id,requestedSourceIds:[...r.sourceIds],readSourceIds:r.sourceIds.filter(id=>read.has(id)),unreadSourceIds:r.sourceIds.filter(id=>!read.has(id)),status:r.sourceIds.some(id=>!read.has(id))?'unread-sources':r.sourceIds.length?'fragments-read':'no-sources-requested',conditions:'unverified'}));
6
+ }