@feng0531/dsh-code-review 0.29.2 → 0.30.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.30.0
4
+
5
+ - Git自动直接上下文改512字面候选index探针,不枚举全tracked;普通tracked有效性及同probe竞态重核保持。
6
+ - 累计metadata1MiB/每probe64KiB、目录扩张拒绝;11000大树auto及指纹相关性回归,283测试通过。SVN索引未改。
7
+
3
8
  ## 0.29.2
4
9
 
5
10
  - Git工作副本基线捕获不再全HEAD枚举,仅可审查变更基线路径literal非递归lookup,改名使用oldPath,删除/子模块边界不变。
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  ## 当前状态
6
6
 
7
- 当前代码版本为 0.29.2
7
+ 当前代码版本为 0.30.0
8
+
9
+ Git自动直接依赖上下文仅查询从已捕获源码导出的最多512路径索引探针,不列整个tracked树;累计索引1MiB并在结束核对同探针指纹。SVN沿用原索引限额,此项不冒充SVN等价。
8
10
 
9
11
  凭据路径硬排除:.env及其后缀(.env.example/.env.sample/.env.template例外)、.ssh目录、SSH私钥及.netrc/_netrc/.npmrc/.pypirc/.dockercfg,大小写无关;显式选择不可绕过,上下文/规则同样拒绝。仅路径策略,不保证普通文件无秘密。
10
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feng0531/dsh-code-review",
3
- "version": "0.29.2",
3
+ "version": "0.30.0",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
package/src/snapshot.mjs CHANGED
@@ -39,9 +39,10 @@ export async function captureSnapshot(cwd, options = {}) {
39
39
  if (!Array.isArray(rulePaths) || rulePaths.some(name => contextPaths.includes(name))) throw new Error('Rule paths must be separate from context paths');
40
40
  const rules = await captureProjectRules(snapshot.root, rulePaths, { signal: options.signal, files: snapshot.files });
41
41
  const context = [];
42
- let autoContext, index;
42
+ let autoContext, index, indexOptions = options;
43
43
  if (options.autoContext === true) {
44
- index = await (type === 'git' ? gitContextIndex : svnContextIndex)(snapshot.root, options);
44
+ if(type==='git'){const probes=new Set();contextCandidates(snapshot.files,[],{onProbe:paths=>{for(const p of paths)probes.add(p);if(probes.size>512)throw new Error('Git context lookup limit exceeded');}});indexOptions={...options,probePaths:[...probes]};}
45
+ index = await (type === 'git' ? gitContextIndex : svnContextIndex)(snapshot.root, indexOptions);
45
46
  const plan = contextCandidates(snapshot.files, index.paths);
46
47
  autoContext = { ...plan, candidates: plan.candidates.filter(c => !contextPaths.includes(c.path) && !rulePaths.includes(c.path)), capturedPaths: [] };
47
48
  for (const candidate of autoContext.candidates) {
@@ -63,7 +64,7 @@ export async function captureSnapshot(cwd, options = {}) {
63
64
  // Re-capture verifies both selected sides while collecting explicit context.
64
65
  if ((await capture(cwd, options)).id !== snapshot.id) throw new Error('Snapshot changed while collecting context');
65
66
  for (const item of context) if ((await readLocal(snapshot.root, item.path, options)).hash !== item.hash) throw new Error('Context changed during capture');
66
- if (index && (await (type === 'git' ? gitContextIndex : svnContextIndex)(snapshot.root, options)).fingerprint !== index.fingerprint) throw new Error('Tracked context index changed during capture');
67
+ if (index && (await (type === 'git' ? gitContextIndex : svnContextIndex)(snapshot.root, indexOptions)).fingerprint !== index.fingerprint) throw new Error('Tracked context index changed during capture');
67
68
  const verifiedRules = await captureProjectRules(snapshot.root, rulePaths, { signal: options.signal, files: snapshot.files });
68
69
  if (JSON.stringify(verifiedRules) !== JSON.stringify(rules)) throw new Error('Rules changed during capture');
69
70
  const result = { ...snapshot, context, ...(autoContext ? { autoContext } : {}), ...(rules.length ? { rules } : {}) };
@@ -13,7 +13,12 @@ export async function svnContextIndex(root, options = {}) {
13
13
  }
14
14
  // Index metadata only; never invokes network, diff drivers or source reads.
15
15
  export async function gitContextIndex(root, options = {}) {
16
- const bytes = await checked('git', ['--no-optional-locks','-c','core.fsmonitor=false','-c','core.untrackedCache=false','ls-files','--stage','-z'], {...options,cwd:root,maxBytes:1024*1024});
16
+ let bytes;
17
+ if(options.probePaths !== undefined){
18
+ if(!Array.isArray(options.probePaths)||options.probePaths.length>512||new Set(options.probePaths).size!==options.probePaths.length)throw new Error('Invalid Git context probes');
19
+ const chunks=[];let totalBytes=0;for(const name of [...options.probePaths].sort()){relativePath(name);const chunk=await checked('git',['--no-optional-locks','--literal-pathspecs','-c','core.fsmonitor=false','-c','core.untrackedCache=false','ls-files','--stage','-z','--',name],{...options,cwd:root,maxBytes:64*1024});const records=new TextDecoder('utf-8',{fatal:true}).decode(chunk).split('\0').filter(Boolean);for(const record of records)if(record.slice(record.indexOf('\t')+1)!==name)throw new Error('Git context probe expanded beyond literal path');totalBytes+=chunk.length;if(totalBytes>1024*1024)throw new Error('Tracked context index limit exceeded');chunks.push(chunk);}
20
+ bytes=Buffer.concat(chunks);if(bytes.length>1024*1024)throw new Error('Tracked context index limit exceeded');
21
+ }else bytes = await checked('git', ['--no-optional-locks','-c','core.fsmonitor=false','-c','core.untrackedCache=false','ls-files','--stage','-z'], {...options,cwd:root,maxBytes:1024*1024});
17
22
  const records = new TextDecoder('utf-8',{fatal:true}).decode(bytes).split('\0').filter(Boolean);
18
23
  if(records.length>10000)throw new Error('Tracked context index limit exceeded');
19
24
  const entries=new Map();