@feng0531/dsh-code-review 0.25.3 → 0.26.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.26.1
4
+
5
+ - 跨文件生成目录附各文件专用缺陷指引,按已捕获正文选择,复核复用.m内容提示不退回路径默认。
6
+ - 不复制正文或新增读取调用;指引纳入原输入预算,271测试通过。
7
+
8
+ ## 0.26.0
9
+
10
+ - Shader/HLSL/GLSL/cginc/hlsli/compute直接字面include纳入有界自动上下文,不宏/条件展开,不编译搜索路径。
11
+ - 专用坐标空间、精度/NaN、采样/资源绑定/pass变体缺陷指引;270测试通过,不保证编译或绑定。
12
+
3
13
  ## 0.25.3
4
14
 
5
15
  - 历史C#方法语法提示按侧使用明确捕获的oldText/目标text,标记contextSide/contextVersion;缺oldText不回退新定义。
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 当前状态
6
6
 
7
- 当前代码版本为 0.25.3
7
+ 当前代码版本为 0.26.1
8
8
 
9
9
  历史捕获用diff-tree精确端点变更元数据,不前置完整枚举文件树;显式上下文/规则和直接导入依赖按字面非递归路径查询。自动依赖最多512个待查路径,仍保留200变更/20上下文/4MiB快照限制,大树小提交不因无关文件元数据超限。
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feng0531/dsh-code-review",
3
- "version": "0.25.3",
3
+ "version": "0.26.1",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
@@ -10,7 +10,7 @@ export function contextCandidates(files, trackedPaths, {maxCandidates=20,onProbe
10
10
  relativePath(f.path);if(f.eligibility!=='reviewable'||f.rightExists===false)continue;
11
11
  const text=f.right?.text;if(typeof text!=='string'||Buffer.byteLength(text)>256*1024)continue;
12
12
  if(text.includes('/*')||text.includes(String.fromCharCode(96))||text.includes('R"')||/\\\r?\n/.test(text))continue;
13
- const cpp=/\.(c|cc|cpp|cxx|h|hh|hpp|hxx)$/i.test(f.path),js=/\.(mjs|cjs|js|jsx|ts|tsx)$/i.test(f.path);
13
+ const cpp=/\.(c|cc|cpp|cxx|h|hh|hpp|hxx|shader|hlsl|glsl|cginc|hlsli|compute)$/i.test(f.path),js=/\.(mjs|cjs|js|jsx|ts|tsx)$/i.test(f.path);
14
14
  if(cpp&&/^\s*#\s*(if|ifdef|ifndef|elif|else|define|undef)\b/m.test(text))continue;
15
15
  for(const line of text.split('\n')){
16
16
  const match=cpp?/^\s*#\s*include\s*"([^"\\]+)"\s*(?:\/\/.*)?$/.exec(line):js?/^\s*(?:import\s+(?:(?:[^'";]+)\s+from\s+)?|export\s+(?:[^'";]+)\s+from\s+)(['"])([^'"\\]+)\1\s*;?\s*(?:\/\/.*)?$/.exec(line):null;
@@ -1,6 +1,7 @@
1
1
  // Original defect checklists, not executable rules or proof of a defect.
2
2
  const common = ['Only report a concrete defect with trigger, impact and changed-code evidence.', 'Check before/after behavior and counterexamples; absent context means uncertainty, not an invented contract.'];
3
3
  const checklists = {
4
+ shader: ['Check coordinate spaces, matrix/vector order, normal transforms, UV units and screen/projection conventions against captured pipeline evidence.', 'Check division/normalization and precision near zero, NaN propagation, sampling/LOD behavior and bounds for changed input domains.', 'Check resource bindings, pass/keyword variants, depth/blend state and synchronization against actual consumers; do not invent platform/compiler behavior or include search paths.'],
4
5
  objc: ['Check ARC/manual ownership, retain cycles, weak/unowned callbacks and Objective-C++ lifetime crossings against captured contracts.', 'Check observer/block cancellation and queue affinity before teardown; message to nil is not proof that required work completed.'],
5
6
  swift: ['Check optional force unwraps and unowned captures against actual object lifetime and failure paths.', 'Check actor isolation, task cancellation, continuation completion exactly once and resources surviving asynchronous work.'],
6
7
  matlab: ['Check matrix dimensions, elementwise versus matrix operations and indexing against captured input contracts.', 'Check empty/NaN values, numeric precision, resource cleanup and changed output shapes with actual consumers.'],
@@ -19,7 +20,7 @@ export function defectGuidance(filePath, sourceText = '') {
19
20
  const lower = filePath.toLowerCase();
20
21
  const first = typeof sourceText === 'string' ? sourceText.slice(0,8192).split('\n').map(s=>s.trim()).find(Boolean) ?? '' : '';
21
22
  const sniffed = lower.endsWith('.m') ? (/^(?:#(?:import|include|pragma|if|define)\b|@(?:import|interface|implementation|class|protocol)\b|\/\/|\/\*)/.test(first) ? 'objc' : 'matlab') : null;
22
- const specialized = sniffed ?? (/\.mm$/.test(lower) ? 'objc' : /\.swift$/.test(lower) ? 'swift' : null) ?? (/\.java$/.test(lower) ? 'java' : /\.go$/.test(lower) ? 'go' : /\.(py|pyi)$/.test(lower) ? 'python' : /\.rs$/.test(lower) ? 'rust' : /\.(kt|kts)$/.test(lower) ? 'kotlin' : /\.(php|phtml)$/.test(lower) ? 'php' : null);
23
+ const specialized = /\.(shader|hlsl|glsl|cginc|hlsli|compute)$/.test(lower) ? 'shader' : sniffed ?? (/\.mm$/.test(lower) ? 'objc' : /\.swift$/.test(lower) ? 'swift' : null) ?? (/\.java$/.test(lower) ? 'java' : /\.go$/.test(lower) ? 'go' : /\.(py|pyi)$/.test(lower) ? 'python' : /\.rs$/.test(lower) ? 'rust' : /\.(kt|kts)$/.test(lower) ? 'kotlin' : /\.(php|phtml)$/.test(lower) ? 'php' : null);
23
24
  const language = specialized ?? (/\.(c|cc|cpp|cxx|h|hh|hpp|hxx)$/.test(lower) ? 'cpp' : lower.endsWith('.cs') ? 'csharp' : /\.(js|jsx|mjs|cjs|ts|tsx)$/.test(lower) ? 'javascript' : /\.(json|yaml|yml|toml|ini|xml|properties)$/.test(lower) ? 'configuration' : 'generic');
24
25
  const fileType = /^\.github\/workflows\/.+\.(yaml|yml)$/.test(lower) ? 'github-workflow' : /(?:^|\/)(package\.json|cargo\.toml|pom\.xml|build\.gradle|composer\.json)$/.test(lower) ? 'dependency-manifest' : undefined;
25
26
  const purpose = fileType ?? (/\.(ftl|ftlh|ftlx|hbs|mustache|jinja2|j2|pug|astro)$/.test(lower) ? 'template' : /\.(tf|hcl|tfvars|bicep|nix)$/.test(lower) ? 'infrastructure' : /\.(proto|thrift|capnp|graphql|gql|prisma)$/.test(lower) ? 'protocol-schema' : undefined);
@@ -1,3 +1,4 @@
1
+ import { defectGuidance } from './defect-guidance.mjs';
1
2
  import { changeMap } from './change-map.mjs';
2
3
 
3
4
  // Pure navigation over one already approved snapshot. No source reads or model sends.
@@ -8,7 +9,7 @@ export function prepareInteractionInput(snapshot, group, measure) {
8
9
  if (matches.length !== 1 || matches[0].eligibility !== 'reviewable' || typeof matches[0].left?.text !== 'string' || typeof matches[0].right?.text !== 'string') throw new Error('Interaction file outside approved reviewable scope');
9
10
  const file = matches[0], changes = changeMap(file.left.text, file.right.text);
10
11
  if (changes.status !== 'changed' || changes.precision !== 'exact') return { fileId: file.id, path: file.path, unavailable: true };
11
- return { fileId: file.id, path: file.path, edits: changes.edits.map(({ id, old, new: after }) => ({ id, old, new: after })) };
12
+ return { fileId: file.id, path: file.path, defectGuidance: defectGuidance(file.path,file.rightExists===false?file.left.text:file.right.text), edits: changes.edits.map(({ id, old, new: after }) => ({ id, old, new: after })) };
12
13
  });
13
14
  if (group.fileIds.filter(id => { const file = snapshot.files.find(f => f.id === id); return file.left.text !== file.right.text; }).length < 2) return { status: 'not-applicable', fileIds: [...group.fileIds] };
14
15
  if (files.some(f => f.unavailable)) return { status: 'blocked', reason: 'exact-edit-analysis-unavailable', fileIds: [...group.fileIds] };
@@ -15,7 +15,7 @@ export async function verificationLoop(model, request, candidates, scope, option
15
15
  const ids = candidates.map((_, i) => 'c' + (i + 1));
16
16
  const envelope = request.input ? JSON.parse(request.input) : {};
17
17
  const rules = envelope.rules ?? [];
18
- const input = JSON.stringify({ defectGuidance: [...new Set(candidates.map(f => scope.catalog().find(s => s.fileId === f.fileId)?.path).filter(Boolean))].map(path => envelope.file?.path === path && envelope.defectGuidance ? envelope.defectGuidance : defectGuidance(path)), rules, candidates: candidates.map((finding, i) => ({ candidateId: ids[i], finding })) });
18
+ const input = JSON.stringify({ defectGuidance: [...new Set(candidates.map(f => scope.catalog().find(s => s.fileId === f.fileId)?.path).filter(Boolean))].map(path => envelope.file?.path === path && envelope.defectGuidance ? envelope.defectGuidance : envelope.files?.find(f=>f.path===path)?.defectGuidance ?? defectGuidance(path)), rules, candidates: candidates.map((finding, i) => ({ candidateId: ids[i], finding })) });
19
19
  const receipts = createEvidenceReceipts(scope.read);
20
20
  const retrievalScope = { ...scope, read: receipts.read };
21
21
  const response = await retrievalLoop(model, { ...request, input, instructions: VERIFICATION_INSTRUCTIONS }, retrievalScope, options);