@feng0531/dsh-code-review 0.23.0 → 0.23.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,15 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.23.2
4
+
5
+ - .m使用已有快照前8KiB首个非空行提示区分Objective-C/MATLAB,.mm与Swift专用生命周期缺陷指引,不新读取。
6
+ - 主输入按新侧/删除旧侧识别,复核复用主输入指引不增调用;258测试通过,识别非语义证明。
7
+
8
+ ## 0.23.1
9
+
10
+ - 模板/IaC/协议schema按已捕获路径附缺陷检查:实际上下文转义、权限/破坏性资源变化、wire/client兼容/授权迁移风险。
11
+ - 指引不证明执行/应用/约束,不增加读取/调用,不加风格审核;256测试通过。
12
+
3
13
  ## 0.23.0
4
14
 
5
15
  - 补Java/Go/Python/Rust/Kotlin/PHP缺陷检查及依赖清单/GitHub Actions专用风险指引;仅已捕获路径选择,不新读取/调用,不风格审核。
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 当前状态
6
6
 
7
- 当前代码版本为 0.23.0
7
+ 当前代码版本为 0.23.2
8
8
 
9
9
  单提交审查直接读取原始commit头的父节点,不受浅克隆遍历边界影响;缺失父树明确失败且不自动fetch,不能把非根提交当空旧侧。
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feng0531/dsh-code-review",
3
- "version": "0.23.0",
3
+ "version": "0.23.2",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
@@ -1,6 +1,9 @@
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
+ 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
+ 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
+ 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.'],
4
7
  java: ['Check checked/unchecked exception exits, try-with-resources ownership and suppressed failures.', 'Check null/unboxing, equality/hash contracts and mutable keys; confirm the actual consumer contract.', 'Check synchronization/volatile publication, executor shutdown, interruption propagation and transaction rollback.'],
5
8
  go: ['Check error handling including typed-nil interfaces, deferred cleanup and panic paths.', 'Check goroutine/channel ownership, cancellation, close/send races and synchronization before shared-state teardown.', 'Check slice backing-array aliasing, map races and integer/bounds contracts with concrete callers.'],
6
9
  python: ['Check exception paths, context manager cleanup, iterator exhaustion and mutable default/shared state.', 'Check async task exception observation, cancellation and blocking operations on the event loop.', 'Check untrusted serialization, subprocess/SQL interpolation and authorization boundaries against actual input flows.'],
@@ -12,11 +15,15 @@ const checklists = {
12
15
  javascript: ['Check null/undefined contract changes, promise rejection handling and missing await or cleanup on failure.', 'Check event/timer/listener lifecycle, closure state, cancellation races and concurrent updates.', 'Check untrusted input at injection/authentication boundaries; do not report style or infer TypeScript runtime checks.'],
13
16
  configuration: ['Check changed configuration keys against consumer/schema evidence, type/unit/default mismatches and compatibility.', 'Check exposed secrets, privilege expansion and unsafe interpolation only with concrete supported evidence.']
14
17
  };
15
- export function defectGuidance(filePath) {
18
+ export function defectGuidance(filePath, sourceText = '') {
16
19
  const lower = filePath.toLowerCase();
17
- const specialized = /\.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;
20
+ const first = typeof sourceText === 'string' ? sourceText.slice(0,8192).split('\n').map(s=>s.trim()).find(Boolean) ?? '' : '';
21
+ 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);
18
23
  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');
19
24
  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
+ 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);
26
+ const purposeChecks = purpose === 'template' ? ['Check escaping for the actual HTML/attribute/URL/script context, untrusted raw output and template execution boundaries.', 'Check missing/null variables and changed conditional branches against captured callers; do not invent engine defaults.'] : purpose === 'infrastructure' ? ['Check privilege/network exposure, secret/state handling and untrusted interpolation against actual provider semantics.', 'Check replacement/deletion, dependency order and changed defaults for concrete data loss or service disruption; configuration is not an applied plan.'] : purpose === 'protocol-schema' ? ['Check field identifier reuse, removed/renamed fields, type/nullability/default changes and wire/client compatibility against actual consumers.', 'Check resolver authorization, data exposure, migration constraints and referential integrity using captured implementation evidence; schema alone does not prove enforcement.'] : [];
20
27
  const typeChecks = fileType === 'github-workflow' ? ['Check event trust boundaries, token permissions and fork/PR-controlled inputs before privileged commands or secret exposure.', 'Check expression interpolation into shell commands, checkout/ref provenance, artifact/cache trust and required job dependency gates.'] : fileType === 'dependency-manifest' ? ['Check changed dependency versions/features against consumers, lock/resolution evidence and runtime compatibility; do not invent a vulnerability from a package name.', 'Check executable install/build hooks, publish/export entry points and platform constraints for concrete changed behavior.'] : [];
21
- return { version:2, language, ...(fileType ? {fileType} : {}), checks:[...common,...(checklists[language] ?? []),...typeChecks], notice:'Guidance is not evidence, a semantic parser, a style rule or permission to read outside the snapshot.' };
28
+ return { version:4, language, ...(sniffed ? {selection:'bounded-first-nonblank-line-hint'} : {}), ...(purpose ? {fileType:purpose} : {}), checks:[...common,...(checklists[language] ?? []),...typeChecks,...purposeChecks], notice:'Guidance is not evidence, a semantic parser, a style rule or permission to read outside the snapshot.' };
22
29
  }
@@ -12,7 +12,7 @@ import { initialInputBudget } from './input-budget.mjs';
12
12
  // Pure preparation over already captured data. No model calls or new reads.
13
13
  export function preparePrimaryInput(input, file, { instructions, scope, grouping, maxInputBytes }) {
14
14
  const changes = changeMap(file.left.text, file.right.text);
15
- const base = { defectGuidance: defectGuidance(file.path), snapshotId: input.id, file, changes, context: input.context ?? [], rules: input.rules ?? [] };
15
+ const base = { defectGuidance: defectGuidance(file.path, file.rightExists === false ? file.left.text : file.right.text), snapshotId: input.id, file, changes, context: input.context ?? [], rules: input.rules ?? [] };
16
16
  const contextRelations = inferContextRelations(input, file);
17
17
  if (contextRelations.length) {
18
18
  base.contextRelations = contextRelations;
@@ -13,8 +13,9 @@ export async function verificationLoop(model, request, candidates, scope, option
13
13
  if (!Array.isArray(candidates) || candidates.length > 50) throw new Error('Invalid candidates');
14
14
  if (!candidates.length) return [];
15
15
  const ids = candidates.map((_, i) => 'c' + (i + 1));
16
- const rules = request.input ? (JSON.parse(request.input).rules ?? []) : [];
17
- const input = JSON.stringify({ defectGuidance: [...new Set(candidates.map(f => scope.catalog().find(s => s.fileId === f.fileId)?.path).filter(Boolean))].map(defectGuidance), rules, candidates: candidates.map((finding, i) => ({ candidateId: ids[i], finding })) });
16
+ const envelope = request.input ? JSON.parse(request.input) : {};
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
19
  const receipts = createEvidenceReceipts(scope.read);
19
20
  const retrievalScope = { ...scope, read: receipts.read };
20
21
  const response = await retrievalLoop(model, { ...request, input, instructions: VERIFICATION_INSTRUCTIONS }, retrievalScope, options);