@feng0531/dsh-code-review 0.16.1 → 0.18.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 +12 -0
- package/README.md +9 -9
- package/cordis.patch.yml +1 -2
- package/index.mjs +5 -10
- package/package.json +1 -1
- package/src/defect-guidance.mjs +13 -0
- package/src/primary-input.mjs +2 -1
- package/src/verification-loop.mjs +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# 变更记录
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
- 原创C++/C#/JS-TS/配置缺陷指引按文件类型进入主输入和候选复核,计入输入预算,不新增读取调用或权限,不把清单当证据。
|
|
6
|
+
- 持续源码对齐计划记录七项及验收,七项不当作完整清单;单批发布不结束总体目标。
|
|
7
|
+
- 全量233项通过,真实模型质量未测。
|
|
8
|
+
|
|
9
|
+
## 0.17.0
|
|
10
|
+
|
|
11
|
+
- 按用户选择的DSH工具权限执行,注册入口不再重复approval.request,不再要求allowModelSending开关;仅依赖tools/llm。
|
|
12
|
+
- 保留preview确认、不可变快照、范围只读、证据校验及调用读取生命周期预算;不把never当自动批准,不改宿主策略。
|
|
13
|
+
- 真实ToolRuntime离线入口回归:未确认0调用,正常执行0额外审批、当前Agent路由及源码不变;不是GUI权限策略或真实模型质量证明。
|
|
14
|
+
|
|
3
15
|
## 0.16.1
|
|
4
16
|
|
|
5
17
|
- 宿主effectivePolicy为never时明确解释自动拒绝与完整文件权限不等于外发批准;保留宿主请求与唯一allowed-once授权,不修改策略。
|
package/README.md
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
## 当前状态
|
|
6
6
|
|
|
7
|
-
当前代码版本为 0.
|
|
7
|
+
当前代码版本为 0.18.0,包含有界覆盖预检、显式项目规则及候选证据与反证复核;发布状态以 npm 和 GitHub Release 为准。已通过真实临时 Git/SVN 仓库测试,以及隔离进程中的真实 DSH ToolRuntime 注册验证。当前开发会话的实际预览已返回0.6.0的plan/rules字段,空变更预览与默认关闭外发已验证;已进行经宿主审批的六次小规模真实试跑,累计12次模型调用;四组合成正负例与历史修复对照符合预期,历史引入方向检出候选但引用复核未完成(partial)。不是独立盲测或整体质量证明。详情见 [试跑结果](evaluation/PILOT-RESULTS.md)。
|
|
8
8
|
|
|
9
9
|
## 工作区下多个子仓库(0.11.0)
|
|
10
10
|
|
|
11
|
-
当会话目录不是仓库而其子目录含Git/SVN仓库时,预览可指定 `repositoryPath`,例如会话位于工作区根时传 `{ "repositoryPath": "c3animation" }
|
|
11
|
+
当会话目录不是仓库而其子目录含Git/SVN仓库时,预览可指定 `repositoryPath`,例如会话位于工作区根时传 `{ "repositoryPath": "c3animation" }`。该参数必须是工作区相对路径(正斜杠),指向明确仓库根;不能使用绝对路径、上级路径或链接目录。文件、上下文、规则路径仍相对此次选定仓库。多个子仓库分别预览和执行,不混用快照;execute只接收previewId,不能另改目标。省略参数保持原行为。使用此参数需宿主安装0.11.0或更新版本;仓库发布不会自动更新当前宿主。
|
|
12
12
|
|
|
13
13
|
## 完整文件权限与审批策略
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
0.17.0起注册工具沿用DSH正常工具执行权限,不再主动调用approval.request,不要求额外allowModelSending开关。宿主工具权限控制入口调用;完整权限下不再因插件重复审批而失败。不修改宿主策略,不把never解释为allowed-once。
|
|
16
16
|
|
|
17
17
|
## C++关联与审批诊断(0.16.0)
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
主输入提供每侧最多20条零参独立调用原位置,含 `worker.join()`、`debugger->Close()`、`Allocator::Shutdown()` 等语法导航;标记未解析,不证明宏展开、重载选择、动态分派或执行顺序,也不表示全部调用覆盖。其他源码须批准范围内read获取。线程退出/调试器关闭/分配器生命周期合成缺陷与safe反例仅验证明确抽象契约及离线证据协议,不是编译或真实模型质量成绩。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
0.16.x的独立外发审批已在0.17.0移除;仍保留预览确认及快照/范围/只读校验。未执行或失败仍不是审核通过。
|
|
24
24
|
|
|
25
25
|
## C#显式上下文位置线索(0.15.0)
|
|
26
26
|
|
|
@@ -60,19 +60,19 @@
|
|
|
60
60
|
|
|
61
61
|
预览返回 `plan`:逐文件初始输入字节、关联回退状态和 `ready`/`input-blocked`/`excluded`/`blocked`。预检包括提示词、检索目录、规则及上下文,不外发模型。`minimumCalls` 仅是ready主文件所需初始请求(含窗口批次)的下限,不是费用估算或可完成承诺;检索、复核会增加调用。200文件全ready仍可能被100次全局调用额度截断。
|
|
62
62
|
|
|
63
|
-
执行报告的 `files`/`coverage` 才是实际覆盖;关联上下文发送不等于作为主文件审查。`initialInputBytes` 仅在进入预检的文件上存在。`followup.suggestedPaths`
|
|
63
|
+
执行报告的 `files`/`coverage` 才是实际覆盖;关联上下文发送不等于作为主文件审查。`initialInputBytes` 仅在进入预检的文件上存在。`followup.suggestedPaths` 列出未完成项(包括初审完成但复核未完成),不自动续审,也不代表阻断原因已解决。再次执行需新预览并由宿主允许工具执行,并显式重选规则/上下文。空建议不代表没有限制或代码正确。
|
|
64
64
|
|
|
65
65
|
不抬高200文件/4MiB快照及单文件捕获硬限。完整输入超限且检索已批准时,精确hunk可作为保留原始行号的局部窗口,最多20批;只在全部窗口可容纳时启用,单hunk不内部拆分、受限diff不伪造窗口。上下文/规则仍占额度。批次共享每文件超时及全局调用/检索限制,窗口完成账本不代表全文正确,不支持跨审批自动恢复。
|
|
66
66
|
|
|
67
67
|
## 环境
|
|
68
68
|
|
|
69
69
|
- Node.js 22+,Git,SVN(测试还需要 svnadmin)。
|
|
70
|
-
- DSH 提供 tools、llm
|
|
70
|
+
- DSH 提供 tools、llm 服务;当前已核对宿主 API,尚未承诺稳定跨版本兼容。
|
|
71
71
|
- Windows SVN 必须支持 UTF-8 路径;CI 对临时 SVN 工具设置 UTF-8 manifest,不修改用户安装的 SVN。
|
|
72
72
|
|
|
73
73
|
## 安装
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
通过DSH插件管理器安装启用;0.17.0不需要allowModelSending配置。执行权限遵循宿主工具策略,历史开关不再决定注册工具执行。
|
|
76
76
|
|
|
77
77
|
```sh
|
|
78
78
|
dsh plugin add https://github.com/f-e-n-g-0531/dsh-code-review.git
|
|
@@ -82,12 +82,12 @@ dsh plugin add https://github.com/f-e-n-g-0531/dsh-code-review.git
|
|
|
82
82
|
|
|
83
83
|
## 使用流程
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
插件入口由DSH加载器装载;执行将预览快照发送给当前Agent模型,由宿主正常工具权限控制,不重复请求独立审批。
|
|
86
86
|
|
|
87
87
|
1. 在目标仓库的活跃 Agent 会话中调用 `code_review_preview`。
|
|
88
88
|
2. 可用 `selectedPaths` 精确选择变更文件;未跟踪文件必须显式选入。`contextPaths` 提供仓库相对路径的额外上下文。
|
|
89
89
|
3. 展示预览中的仓库范围、文件、排除原因及模型提供方。调用 `code_review_execute`,传入 `previewId` 和 `confirmed: true`。
|
|
90
|
-
4.
|
|
90
|
+
4. DSH 正常工具权限机制决定是否调用执行入口;插件不另发审批请求,不读取never当作授权。执行会把预览快照发送至当前Agent模型,confirmed仅确认预览,不修改宿主权限。
|
|
91
91
|
5. 返回 `json`(结构化报告字符串)及 `markdown`(中文报告)。文件、模型或目录变化时需重新预览。
|
|
92
92
|
|
|
93
93
|
默认在发现的仓库根目录审查,而不是仅当前子目录;预览会显示实际根目录。发送内容包括可审查文件的两侧完整文本、属性和显式上下文,可能包含敏感信息。选择前请检查范围,不要把密钥文件作为上下文。
|
package/cordis.patch.yml
CHANGED
package/index.mjs
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { requestModelApproval } from './src/model-approval.mjs';
|
|
2
1
|
import { createReviewService } from './src/service.mjs';
|
|
3
2
|
export const name = 'dsh-code-review';
|
|
4
|
-
export const inject = ['tools', 'llm'
|
|
3
|
+
export const inject = ['tools', 'llm'];
|
|
5
4
|
|
|
6
5
|
export function apply(ctx, config = {}) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
agent: exec.agent, toolName: 'code_review_execute', signal: exec.signal,
|
|
11
|
-
reason: '只读代码审查将发送代码给 ' + route.provider + '/' + route.model + '。仓库:' + snapshot.root + ';快照:' + snapshot.id + ';文件:' + JSON.stringify(snapshot.files.filter(f => f.eligibility === 'reviewable').map(f => f.path)) + ';上下文:' + JSON.stringify(snapshot.context.map(c => c.path)) + ';项目规则(全文将发送):' + JSON.stringify((snapshot.rules ?? []).map(({ path, hash }) => ({ path, hash }))),
|
|
12
|
-
}),
|
|
13
|
-
});
|
|
6
|
+
// This entry runs only when the host invokes the registered tool.
|
|
7
|
+
// Host tool policy owns permission; do not request a second approval here.
|
|
8
|
+
const service = createReviewService(ctx.llm, { allowModelSending: true, authorize: async () => true });
|
|
14
9
|
const output = {
|
|
15
10
|
schema: { type: 'object', additionalProperties: false, properties: { json: { type: 'string' }, markdown: { type: 'string' } }, required: ['json', 'markdown'] },
|
|
16
11
|
render: (_args, value) => [{ type: 'text', text: value.markdown || value.json }],
|
|
@@ -22,7 +17,7 @@ export function apply(ctx, config = {}) {
|
|
|
22
17
|
async execute(args, exec) { const preview = await service.preview(args, exec); return { json: JSON.stringify(preview), markdown: '' }; },
|
|
23
18
|
});
|
|
24
19
|
ctx.tools.register({
|
|
25
|
-
name: 'code_review_execute', description: 'Execute a previewed read-only code review using the current DSH model.
|
|
20
|
+
name: 'code_review_execute', description: 'Execute a previewed read-only code review using the current DSH model. Sends the approved snapshot to the current Agent model under DSH tool execution policy; no separate plugin approval prompt. Never modifies the reviewed repository.',
|
|
26
21
|
parameters: { type: 'object', additionalProperties: false, properties: { previewId: { type: 'string' }, confirmed: { type: 'boolean' } }, required: ['previewId', 'confirmed'] },
|
|
27
22
|
output,
|
|
28
23
|
async execute(args, exec) { const result = await service.execute(args, exec); return { json: JSON.stringify(result.report), markdown: result.markdown }; },
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Original defect checklists, not executable rules or proof of a defect.
|
|
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
|
+
const checklists = {
|
|
4
|
+
cpp: ['Check ownership, dangling references, double release and allocator/object lifetime across all exits.', 'Check stop publication, synchronization, join completion and remaining users before teardown; source order alone is not a happens-before proof.', 'Check exception/early-return resource cleanup, iterator invalidation, bounds, integer conversion and undefined behavior.', 'Do not assume macro expansion, overload binding, build flags or virtual dispatch targets without evidence.'],
|
|
5
|
+
csharp: ['Check IDisposable/async disposal, cancellation propagation and completion before releasing shared state.', 'Check nullability and actual runtime guards, event subscription lifetime, deferred enumeration and captured mutable state.', 'Check async exception observation, synchronization and thread-affinity; do not assume await establishes unrelated ordering.'],
|
|
6
|
+
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.'],
|
|
7
|
+
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.']
|
|
8
|
+
};
|
|
9
|
+
export function defectGuidance(filePath) {
|
|
10
|
+
const lower = filePath.toLowerCase();
|
|
11
|
+
const language = /\.(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';
|
|
12
|
+
return { version:1, language, checks:[...common,...(checklists[language] ?? [])], notice:'Guidance is not evidence, a semantic parser, a style rule or permission to read outside the snapshot.' };
|
|
13
|
+
}
|
package/src/primary-input.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { defectGuidance } from './defect-guidance.mjs';
|
|
1
2
|
import { cppCallSites } from './cpp-call-sites.mjs';
|
|
2
3
|
import { inferCsharpContext } from './csharp-context.mjs';
|
|
3
4
|
import { inferImportRelations } from './import-relations.mjs';
|
|
@@ -11,7 +12,7 @@ import { initialInputBudget } from './input-budget.mjs';
|
|
|
11
12
|
// Pure preparation over already captured data. No model calls or new reads.
|
|
12
13
|
export function preparePrimaryInput(input, file, { instructions, scope, grouping, maxInputBytes }) {
|
|
13
14
|
const changes = changeMap(file.left.text, file.right.text);
|
|
14
|
-
const base = { snapshotId: input.id, file, changes, context: input.context ?? [], rules: input.rules ?? [] };
|
|
15
|
+
const base = { defectGuidance: defectGuidance(file.path), snapshotId: input.id, file, changes, context: input.context ?? [], rules: input.rules ?? [] };
|
|
15
16
|
const contextRelations = inferContextRelations(input, file);
|
|
16
17
|
if (contextRelations.length) {
|
|
17
18
|
base.contextRelations = contextRelations;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { defectGuidance } from './defect-guidance.mjs';
|
|
1
2
|
import { createEvidenceReceipts } from './evidence-receipts.mjs';
|
|
2
3
|
import { retrievalLoop } from './retrieval-loop.mjs';
|
|
3
4
|
import { validateCandidateVerification } from './candidate-verification.mjs';
|
|
@@ -13,7 +14,7 @@ export async function verificationLoop(model, request, candidates, scope, option
|
|
|
13
14
|
if (!candidates.length) return [];
|
|
14
15
|
const ids = candidates.map((_, i) => 'c' + (i + 1));
|
|
15
16
|
const rules = request.input ? (JSON.parse(request.input).rules ?? []) : [];
|
|
16
|
-
const input = JSON.stringify({ rules, candidates: candidates.map((finding, i) => ({ candidateId: ids[i], finding })) });
|
|
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 })) });
|
|
17
18
|
const receipts = createEvidenceReceipts(scope.read);
|
|
18
19
|
const retrievalScope = { ...scope, read: receipts.read };
|
|
19
20
|
const response = await retrievalLoop(model, { ...request, input, instructions: VERIFICATION_INSTRUCTIONS }, retrievalScope, options);
|