add-coder 0.3.19 → 0.3.20
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/README.md +7 -3
- package/dist/index.js +380 -128
- package/package.json +3 -3
- package/templates/.add-coder-src-hash.json +13 -11
- package/templates/adapters/qoder/sync-policy.json +1 -1
- package/templates/core/DEPENDENCIES.md +91 -0
- package/templates/core/scripts/mcp-server/resources/add-coder-version.ts +4 -3
- package/templates/core/scripts/mcp-server/shared/fs.ts +9 -4
- package/templates/core/scripts/mcp-server/shared/prisma.ts +10 -0
- package/templates/core/scripts/mcp-server/shared/run-command.ts +57 -0
- package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +4 -1
- package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +4 -5
- package/templates/core/scripts/mcp-server/tools/gateway/check_spec_sync.ts +4 -5
- package/templates/core/scripts/mcp-server/tools/gateway/helpers.ts +7 -0
- package/templates/core/templates/01-/346/236/266/346/236/204//343/200/212ADD/345/274/200/345/217/221/345/267/245/344/275/234/350/267/257/345/276/204/344/270/216/346/226/207/346/241/243/345/215/217/345/220/214/350/247/204/350/214/203/343/200/213.md +1 -1
- package/templates/core/vocabulary/add-governance-vocabulary.md +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-coder",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "[codein2027](https://github.com/xiaomingming92/codein2027) - A complete scaffolding for building the ADD programming paradigm, the implementation layer for AI code governance. Core principle: Audit as Infrastructure. Breaks the black-box programming process and cross-session amnesia, evolving programming paradigms into an auditable, traceable, and convergent new era. npx-ready.\n\n[codein2027](https://github.com/xiaomingming92/codein2027) 快速构建 ADD 编程范式的完整脚手架——AI 代码治理的落地方案。以「审计即基础设施」为核心,彻底打破编程过程黑盒与跨轮失忆,让编程范式进化为可审计、可追溯、可收敛的新时代。npx 即用,人人可体验。",
|
|
6
6
|
"repository": {
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
"zod": "^4.4.3"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
+
"@huggingface/transformers": "^3.8.1",
|
|
51
52
|
"@prisma/adapter-pg": "^7.0.0",
|
|
52
53
|
"@prisma/client": "^7.0.0",
|
|
53
54
|
"dotenv": "*",
|
|
54
55
|
"prisma": "^7.0.0",
|
|
55
56
|
"tsx": ">=4",
|
|
56
|
-
"vector-cosine-similarity": "^1.8.0"
|
|
57
|
-
"@huggingface/transformers": "^3.8.1"
|
|
57
|
+
"vector-cosine-similarity": "^1.8.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependenciesMeta": {
|
|
60
60
|
"@prisma/client": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_version": "0.3.
|
|
2
|
+
"_version": "0.3.20",
|
|
3
3
|
"adapters/claude/hooks/doc-format-guard.sh": "ec59ad3f",
|
|
4
4
|
"adapters/claude/hooks/lib/common.sh": "4f3e64ad",
|
|
5
5
|
"adapters/claude/hooks/lib/context-inject.sh": "cfc8c65e",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"adapters/qoder/hooks/subagent-stop.sh": "5a2c78c6",
|
|
75
75
|
"adapters/qoder/mcp.json": "b2075957",
|
|
76
76
|
"adapters/qoder/settings.json": "4bae3c9a",
|
|
77
|
-
"adapters/qoder/sync-policy.json": "
|
|
77
|
+
"adapters/qoder/sync-policy.json": "9cb6ff90",
|
|
78
78
|
"adapters/trae/hooks/doc-format-guard.sh": "9b99f253",
|
|
79
79
|
"adapters/trae/hooks/lib/common.sh": "4f3e64ad",
|
|
80
80
|
"adapters/trae/hooks/lib/context-inject.sh": "cfc8c65e",
|
|
@@ -135,6 +135,7 @@
|
|
|
135
135
|
"adapters/vscode/launch.json": "f2b79855",
|
|
136
136
|
"adapters/vscode/settings.json": "7cabd00e",
|
|
137
137
|
"adapters/vscode/tasks.json": "654d7fbd",
|
|
138
|
+
"core/DEPENDENCIES.md": "88d01954",
|
|
138
139
|
"core/agents/add-flow-guardian.md": "c3e650d2",
|
|
139
140
|
"core/docs/ADD-governance-claude-code.md": "0f582a7e",
|
|
140
141
|
"core/docs/ADD-governance-codex.md": "289e8b71",
|
|
@@ -188,7 +189,7 @@
|
|
|
188
189
|
"core/scripts/mcp-server/notifications/hitl.ts": "96eb7c5d",
|
|
189
190
|
"core/scripts/mcp-server/notifications/hook.ts": "a6cb861f",
|
|
190
191
|
"core/scripts/mcp-server/notifications/index.ts": "b6615afa",
|
|
191
|
-
"core/scripts/mcp-server/resources/add-coder-version.ts": "
|
|
192
|
+
"core/scripts/mcp-server/resources/add-coder-version.ts": "2384fa40",
|
|
192
193
|
"core/scripts/mcp-server/resources/add-state.ts": "1c1cc3a2",
|
|
193
194
|
"core/scripts/mcp-server/resources/hook-events-report.ts": "1d4b5996",
|
|
194
195
|
"core/scripts/mcp-server/resources/index.ts": "50e19629",
|
|
@@ -197,12 +198,13 @@
|
|
|
197
198
|
"core/scripts/mcp-server/sampling/review.ts": "5db7a8df",
|
|
198
199
|
"core/scripts/mcp-server/shared/dps-scoring.strategy.ts": "f1c901dc",
|
|
199
200
|
"core/scripts/mcp-server/shared/env.ts": "57f4c2f2",
|
|
200
|
-
"core/scripts/mcp-server/shared/fs.ts": "
|
|
201
|
+
"core/scripts/mcp-server/shared/fs.ts": "0e66a214",
|
|
201
202
|
"core/scripts/mcp-server/shared/hitl-interaction.strategy.ts": "7c5c26f5",
|
|
202
203
|
"core/scripts/mcp-server/shared/package.json": "e3d5a4a2",
|
|
203
|
-
"core/scripts/mcp-server/shared/prisma.ts": "
|
|
204
|
+
"core/scripts/mcp-server/shared/prisma.ts": "a9618f99",
|
|
204
205
|
"core/scripts/mcp-server/shared/project-root-strategy.ts": "1a5bdc57",
|
|
205
206
|
"core/scripts/mcp-server/shared/response.ts": "f7806b67",
|
|
207
|
+
"core/scripts/mcp-server/shared/run-command.ts": "42caf972",
|
|
206
208
|
"core/scripts/mcp-server/tasks/index.ts": "c040eb75",
|
|
207
209
|
"core/scripts/mcp-server/tasks/runner.ts": "d84bd35d",
|
|
208
210
|
"core/scripts/mcp-server/tasks/store.ts": "2fce1a92",
|
|
@@ -212,10 +214,10 @@
|
|
|
212
214
|
"core/scripts/mcp-server/tools/docs.ts": "034e473c",
|
|
213
215
|
"core/scripts/mcp-server/tools/gateway/check_add_route_completeness.ts": "b58e76ee",
|
|
214
216
|
"core/scripts/mcp-server/tools/gateway/check_add_route_status.ts": "23fbbb6b",
|
|
215
|
-
"core/scripts/mcp-server/tools/gateway/check_dps.ts": "
|
|
216
|
-
"core/scripts/mcp-server/tools/gateway/check_rahs.ts": "
|
|
217
|
-
"core/scripts/mcp-server/tools/gateway/check_spec_sync.ts": "
|
|
218
|
-
"core/scripts/mcp-server/tools/gateway/helpers.ts": "
|
|
217
|
+
"core/scripts/mcp-server/tools/gateway/check_dps.ts": "4d599b38",
|
|
218
|
+
"core/scripts/mcp-server/tools/gateway/check_rahs.ts": "4078b0f1",
|
|
219
|
+
"core/scripts/mcp-server/tools/gateway/check_spec_sync.ts": "486df441",
|
|
220
|
+
"core/scripts/mcp-server/tools/gateway/helpers.ts": "f8794a92",
|
|
219
221
|
"core/scripts/mcp-server/tools/gateway/index.ts": "559acb75",
|
|
220
222
|
"core/scripts/mcp-server/tools/gateway.backup": "65eae393",
|
|
221
223
|
"core/scripts/mcp-server/tools/hitl.ts": "f447345f",
|
|
@@ -232,7 +234,7 @@
|
|
|
232
234
|
"core/specs/add-coder-npm-package/checklist.md": "ed92032c",
|
|
233
235
|
"core/specs/add-coder-npm-package/spec.md": "c7d0f235",
|
|
234
236
|
"core/specs/add-coder-npm-package/tasks.md": "c34301e5",
|
|
235
|
-
"core/templates/01-架构/《ADD开发工作路径与文档协同规范》.md": "
|
|
237
|
+
"core/templates/01-架构/《ADD开发工作路径与文档协同规范》.md": "c7e2ac6a",
|
|
236
238
|
"core/templates/TERMINOLOGY.md": "e9f4f781",
|
|
237
239
|
"core/templates/add-route-template-heavyweight.md": "0e107ac0",
|
|
238
240
|
"core/templates/add-route-template.md": "da7022df",
|
|
@@ -274,6 +276,6 @@
|
|
|
274
276
|
"core/templates/tasks-template.md": "2b9d0d52",
|
|
275
277
|
"core/templates/tasks-template.schema.json": "fff6eb47",
|
|
276
278
|
"core/tools/README.md": "26a63460",
|
|
277
|
-
"core/vocabulary/add-governance-vocabulary.md": "
|
|
279
|
+
"core/vocabulary/add-governance-vocabulary.md": "ee9e2bd2",
|
|
278
280
|
"shared/hooks-lib/common.sh": "441eee52"
|
|
279
281
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"checks": {
|
|
5
5
|
"add_route_exists": { "enabled": true, "severity": "block" },
|
|
6
6
|
"add_route_completeness": { "enabled": true, "severity": "block" },
|
|
7
|
-
"dps": { "enabled": true, "severity": "block", "threshold":
|
|
7
|
+
"dps": { "enabled": true, "severity": "block", "threshold": 80 },
|
|
8
8
|
"rahs": { "enabled": true, "severity": "block", "threshold": 90 },
|
|
9
9
|
"tasks": { "enabled": true, "severity": "block" },
|
|
10
10
|
"checklist": { "enabled": true, "severity": "block" },
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# 模板运行时依赖清单(Template Runtime Dependencies)
|
|
2
|
+
|
|
3
|
+
> 本文件随 `sync` 同步到项目的 `.add/`(或对应 magic 目录)。**基建依赖必须在安装期解决,不要等到运行时(如 DPS 评分)才发现缺失。**
|
|
4
|
+
>
|
|
5
|
+
> 两类资源的责任边界:
|
|
6
|
+
>
|
|
7
|
+
> | 类别 | 解决时机 | 负责方 |
|
|
8
|
+
> |------|---------|--------|
|
|
9
|
+
> | **基建依赖(npm 包)** | 项目安装期 `npm i` | 本清单(DEPENDENCIES.md) |
|
|
10
|
+
> | **运行时资源(模型权重)** | 首次 DPS 调用或 `model:download` 预下载 | `check_dps` 降级提示 + CLI 下载命令 |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 一、基建依赖(必须随项目安装)
|
|
15
|
+
|
|
16
|
+
以下 npm 包是模板脚本(`.add/scripts/mcp-server/` 等)的运行时基建,缺失时对应功能**静默降级或直接报错**:
|
|
17
|
+
|
|
18
|
+
| 依赖 | 版本 | 用途 | 缺失后果 |
|
|
19
|
+
|------|------|------|---------|
|
|
20
|
+
| `@huggingface/transformers` | `^3.8.1` | DPS `check_dps` 语义延续性 embedding(`getEmbeddings` 动态 import) | **check_dps 延续性静默降级为 0**(语义分 ×0.6 丢失,不易察觉) |
|
|
21
|
+
| `vector-cosine-similarity` | `^1.8.0` | DPS 余弦相似度计算 | check_dps 直接报错 |
|
|
22
|
+
| `@modelcontextprotocol/server` | `2.0.0` | MCP 服务器运行 | MCP 工具全部不可用 |
|
|
23
|
+
| `zod` | `^4.4.3` | MCP 工具输入 schema(`zod/v4`) | MCP 注册失败 |
|
|
24
|
+
| `dotenv` | `*` | 环境变量加载 | 配置缺失、连接失败 |
|
|
25
|
+
| `@prisma/client` | `^7.0.0` | ADD-7 审计落库(`shared/prisma.ts`) | 审计不可用 |
|
|
26
|
+
| `prisma` | `^7.0.0` | Prisma CLI(generate) | 客户端生成失败 |
|
|
27
|
+
| `smol-toml` | `^1.7.0` | caijuehub TOML 转录(`npm run generate`) | 策略转录失败 |
|
|
28
|
+
| `tsx` | `>=4` | TS 脚本直接执行(sync/转录/benchmark) | 脚本不可运行 |
|
|
29
|
+
|
|
30
|
+
> 以上依赖与 add-coder 包本体 `dependencies` 对齐——**安装 add-coder 包即默认获得全部基建**(`npm i add-coder` 自动安装)。本清单服务于**未安装 add-coder 包、仅同步模板脚本**的消费项目。
|
|
31
|
+
|
|
32
|
+
### 安装命令
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 消费项目(未安装 add-coder 包本体):
|
|
36
|
+
npm i @huggingface/transformers@^3.8.1 vector-cosine-similarity@^1.8.0 \
|
|
37
|
+
@modelcontextprotocol/server@2.0.0 zod@^4.4.3 dotenv \
|
|
38
|
+
@prisma/client@^7.0.0 prisma@^7.0.0 smol-toml@^1.7.0 tsx@>=4
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 二、已知版本冲突:onnxruntime 解析错位(pnpm overrides)
|
|
44
|
+
|
|
45
|
+
**场景**:升级到新版 `@huggingface/transformers`(^3.8.x,依赖 `onnxruntime-node@1.21.0`)后,若项目同时存在 langchain 生态的 optional 依赖(其声明 `onnxruntime-node/web@1.14.0`),pnpm 会同时解析出 `onnxruntime-common@1.14.0` 与 `1.21.0` 两套——transformers 加载时拿到错位的 `common@1.14.0`,导致 embedding 初始化异常。
|
|
46
|
+
|
|
47
|
+
**症状**:`check_dps` 延续性降级为 0(embedding pipeline 初始化抛错进 catch,现象与模型未下载相同,不易区分)。
|
|
48
|
+
|
|
49
|
+
**解决**:用 pnpm overrides 将 1.14.0 强制替换为 1.21.0。
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
// package.json
|
|
53
|
+
{
|
|
54
|
+
"pnpm": {
|
|
55
|
+
"overrides": {
|
|
56
|
+
"onnxruntime-node@1.14.0": "1.21.0",
|
|
57
|
+
"onnxruntime-web@1.14.0": "1.21.0",
|
|
58
|
+
"onnxruntime-common@1.14.0": "1.21.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# pnpm-workspace.yaml(等效,pnpm 9+ 推荐)
|
|
66
|
+
packages:
|
|
67
|
+
- .
|
|
68
|
+
overrides:
|
|
69
|
+
onnxruntime-node@1.14.0: 1.21.0
|
|
70
|
+
onnxruntime-web@1.14.0: 1.21.0
|
|
71
|
+
onnxruntime-common@1.14.0: 1.21.0
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
验证:`pnpm install` 后 `pnpm list onnxruntime-node onnxruntime-common` 应只见 1.21.x,无 1.14.0。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 三、运行时资源(非基建,可延迟)
|
|
79
|
+
|
|
80
|
+
| 资源 | 获取方式 | 缺失时的行为 |
|
|
81
|
+
|------|---------|-------------|
|
|
82
|
+
| embedding 模型权重(约 90MB) | `add-coder model:download` 预下载;或首次 DPS 调用自动补下载 | check_dps 降级为纯结构分并提示下载入口(**不阻断**) |
|
|
83
|
+
|
|
84
|
+
> 基建依赖缺失 ≠ 运行时资源缺失:前者应通过安装解决(本清单),后者通过 `model:download` 解决。check_dps 的降级提示只针对后者。
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 四、新增依赖的维护规则
|
|
89
|
+
|
|
90
|
+
- 模板脚本引入新的 npm 包时,**必须同步更新本清单**(依赖 / 版本 / 用途 / 缺失后果四列)
|
|
91
|
+
- 版本号与 add-coder 根 `package.json` 保持一致(`dependencies` 是权威来源,本清单是消费项目视图)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/server"
|
|
2
2
|
import { join } from "path"
|
|
3
3
|
import { readFileSafe, PROJECT_ROOT } from "../shared/fs.js"
|
|
4
|
-
import {
|
|
4
|
+
import { runCommand } from "../shared/run-command.js"
|
|
5
5
|
|
|
6
6
|
interface PkgJson { version?: string }
|
|
7
7
|
|
|
@@ -16,8 +16,9 @@ export function registerVersionResource(server: McpServer) {
|
|
|
16
16
|
try { current = (JSON.parse(pkg) as PkgJson).version ?? "unknown" } catch { /* intentionally empty */ }
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
// win32 下 npm 为 .cmd → runCommand 自动解析(issue #10 跨端修复)
|
|
20
|
+
const result = runCommand("npm", ["view", "add-coder", "version"], { timeout: 10000 })
|
|
21
|
+
latest = result.stdout.trim() || "unknown"
|
|
21
22
|
outdated = current !== "unknown" && latest !== "unknown" && current !== latest
|
|
22
23
|
} catch { /* intentionally empty */ }
|
|
23
24
|
return { contents: [{ text: JSON.stringify({ current, latest, outdated }), uri: "add-coder://version", mimeType: "application/json" }] }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile, readdir } from "fs/promises"
|
|
2
2
|
import { join, relative } from "path"
|
|
3
3
|
import { existsSync } from "fs"
|
|
4
|
-
import {
|
|
4
|
+
import { runCommand } from "./run-command.js"
|
|
5
5
|
import { PROJECT_ROOT, MAGIC_DIR } from "./env.js"
|
|
6
6
|
import type { GuardResult } from "../types.js"
|
|
7
7
|
|
|
@@ -15,9 +15,14 @@ export async function validateDocWithGuard(filePath: string): Promise<GuardResul
|
|
|
15
15
|
const content = await readFileSafe(filePath)
|
|
16
16
|
if (!content) return { ok: false, issues: "文件无法读取" }
|
|
17
17
|
const guardInput = JSON.stringify({ tool_input: { file_path: filePath, file_content: content } })
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
try {
|
|
19
|
+
// bash 在 Windows 不存在 → runCommand 抛"命令不可用" → 显式返回 guard 失败(不再静默 null)
|
|
20
|
+
const result = runCommand("bash", [guardScript], { input: guardInput, timeout: 5000 })
|
|
21
|
+
if (result.status !== 0) return { ok: false, issues: result.stderr || "guard 执行失败" }
|
|
22
|
+
return { ok: true, issues: "" }
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return { ok: false, issues: `guard 执行失败: ${e instanceof Error ? e.message : String(e)}` }
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export async function readdirRecursive(baseDir: string): Promise<string[]> {
|
|
@@ -41,6 +41,16 @@ if (url.startsWith("postgresql://") || url.startsWith("postgres://")) {
|
|
|
41
41
|
adapter = new Pg({ connectionString: url })
|
|
42
42
|
} catch { /* optional dep */ }
|
|
43
43
|
}
|
|
44
|
+
if (url.startsWith("file:")) {
|
|
45
|
+
// SQLite 完整链路(issue #10 P1-5):DATABASE_URL 为 file: → 加载 better-sqlite3 adapter
|
|
46
|
+
try {
|
|
47
|
+
const bsql = require("@prisma/adapter-better-sqlite3") as Record<string, unknown>
|
|
48
|
+
const Bsql = bsql.PrismaBetterSQLite3 as new (opts: Record<string, unknown>) => Record<string, unknown>
|
|
49
|
+
adapter = new Bsql({ url })
|
|
50
|
+
} catch {
|
|
51
|
+
throw new Error("SQLite 模式需要安装 @prisma/adapter-better-sqlite3(npm install @prisma/adapter-better-sqlite3)")
|
|
52
|
+
}
|
|
53
|
+
}
|
|
44
54
|
|
|
45
55
|
export const prisma: Record<string, Record<string, (...a: unknown[]) => unknown>> = new PrismaClient({
|
|
46
56
|
...(adapter ? { adapter } : {}),
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Author : xiaomingming wujixmm@gmail.com
|
|
3
|
+
* Date : 2026-08-07
|
|
4
|
+
* Description : 跨平台子进程统一封装(模板版,消费项目 MCP 使用)
|
|
5
|
+
* 与 add-coder 包 src/lib/run-command.ts 语义一致:
|
|
6
|
+
* - win32 下 npm/npx/pnpm/git 为 .cmd 批处理 → 显式追加 .cmd
|
|
7
|
+
* - 命令不存在(ENOENT)→ 抛"命令不可用",不再静默 status=null
|
|
8
|
+
* - 本项目所有子进程调用 MUST 走 runCommand 单入口
|
|
9
|
+
*/
|
|
10
|
+
import { spawnSync } from "child_process"
|
|
11
|
+
|
|
12
|
+
export interface RunCommandOptions {
|
|
13
|
+
cwd?: string
|
|
14
|
+
env?: NodeJS.ProcessEnv
|
|
15
|
+
input?: string
|
|
16
|
+
timeout?: number
|
|
17
|
+
shell?: boolean
|
|
18
|
+
platform?: NodeJS.Platform
|
|
19
|
+
/** stdio 透传(如 "inherit" 实时显示;默认无 input 时 ignore/pipe/pipe 捕获) */
|
|
20
|
+
stdio?: "inherit"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RunResult {
|
|
24
|
+
status: number | null
|
|
25
|
+
stdout: string
|
|
26
|
+
stderr: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Windows 下为 .cmd 批处理的可执行族(CreateProcess 无法直接执行) */
|
|
30
|
+
const CMD_EXTENSIONS = ["npm", "npx", "pnpm", "git"]
|
|
31
|
+
|
|
32
|
+
export function runCommand(cmd: string, args: string[], opts: RunCommandOptions = {}): RunResult {
|
|
33
|
+
const platform = opts.platform ?? process.platform
|
|
34
|
+
const needsCmdExt = platform === "win32" && CMD_EXTENSIONS.includes(cmd) && !opts.shell
|
|
35
|
+
const effectiveCmd = needsCmdExt ? `${cmd}.cmd` : cmd
|
|
36
|
+
const r = spawnSync(effectiveCmd, args, {
|
|
37
|
+
cwd: opts.cwd,
|
|
38
|
+
env: opts.env,
|
|
39
|
+
input: opts.input,
|
|
40
|
+
timeout: opts.timeout,
|
|
41
|
+
encoding: "utf-8",
|
|
42
|
+
shell: opts.shell,
|
|
43
|
+
stdio: opts.stdio ?? (opts.input !== undefined ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"]),
|
|
44
|
+
})
|
|
45
|
+
if (r.error) {
|
|
46
|
+
throw new Error(`命令不可用: ${cmd}(平台: ${platform},${r.error.message})`)
|
|
47
|
+
}
|
|
48
|
+
return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** 跨平台命令存在性探测:win32 用 where / POSIX 用 which */
|
|
52
|
+
export function commandExists(cmd: string, platform?: NodeJS.Platform): boolean {
|
|
53
|
+
const p = platform ?? process.platform
|
|
54
|
+
const probe = p === "win32" ? "where" : "which"
|
|
55
|
+
const r = spawnSync(probe, [cmd], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] })
|
|
56
|
+
return !r.error && r.status === 0
|
|
57
|
+
}
|
|
@@ -169,8 +169,11 @@ export function registerCheckDps(server: ToolRegistrar) {
|
|
|
169
169
|
continuityCount++;
|
|
170
170
|
}
|
|
171
171
|
} catch {
|
|
172
|
-
// embedding 加载失败 →
|
|
172
|
+
// embedding 加载失败 → 降级纯结构分;提示预下载入口(不阻断、不报错,issue 关切:网络不通用户不卡死)
|
|
173
173
|
continuityCount = 0;
|
|
174
|
+
parts.push(
|
|
175
|
+
" ⚠️ embedding 不可用(模型未下载或网络不通):语义延续性降级为 0——可运行 `add-coder model:download` 提前预下载",
|
|
176
|
+
);
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
const structSem = mappingTotal > 0 ? (mappingMatched / mappingTotal) * 100 : 0;
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
MAGIC_DIR,
|
|
19
19
|
} from "../../shared/fs.js";
|
|
20
20
|
import { prisma } from "../../shared/prisma.js";
|
|
21
|
+
import { runCommand } from "../../shared/run-command.js";
|
|
21
22
|
|
|
22
23
|
export function registerCheckRahs(server: ToolRegistrar) {
|
|
23
24
|
server.registerTool(
|
|
@@ -51,10 +52,9 @@ export function registerCheckRahs(server: ToolRegistrar) {
|
|
|
51
52
|
specScore = 80,
|
|
52
53
|
symScore = 80;
|
|
53
54
|
try {
|
|
54
|
-
|
|
55
|
-
const tsc =
|
|
55
|
+
// win32 下 npx 为 .cmd → runCommand 自动解析(issue #10 跨端修复)
|
|
56
|
+
const tsc = runCommand("npx", ["tsc", "--noEmit"], {
|
|
56
57
|
cwd: PROJECT_ROOT,
|
|
57
|
-
encoding: "utf-8",
|
|
58
58
|
timeout: 30000,
|
|
59
59
|
});
|
|
60
60
|
typeScore =
|
|
@@ -62,8 +62,7 @@ export function registerCheckRahs(server: ToolRegistrar) {
|
|
|
62
62
|
? 100
|
|
63
63
|
: Math.max(
|
|
64
64
|
0,
|
|
65
|
-
100 -
|
|
66
|
-
(tsc.stderr || "").split("\n").filter(Boolean).length * 5,
|
|
65
|
+
100 - tsc.stderr.split("\n").filter(Boolean).length * 5,
|
|
67
66
|
);
|
|
68
67
|
} catch {}
|
|
69
68
|
try {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
PROJECT_ROOT,
|
|
19
19
|
MAGIC_DIR,
|
|
20
20
|
} from "../../shared/fs.js";
|
|
21
|
+
import { runCommand } from "../../shared/run-command.js";
|
|
21
22
|
|
|
22
23
|
export function registerCheckSpecSync(server: ToolRegistrar) {
|
|
23
24
|
server.registerTool(
|
|
@@ -72,16 +73,14 @@ export function registerCheckSpecSync(server: ToolRegistrar) {
|
|
|
72
73
|
.map((f: string) => f.replace(/`/g, ""));
|
|
73
74
|
lines.push(`附录文件: ${appendixFiles.length} 个`);
|
|
74
75
|
|
|
75
|
-
// git diff
|
|
76
|
+
// git diff 变更文件(win32 下 git 为 .cmd → runCommand 自动解析,issue #10 跨端修复)
|
|
76
77
|
let diffFiles: string[] = [];
|
|
77
78
|
try {
|
|
78
|
-
const
|
|
79
|
-
const diff = spawnSync("git", ["diff", "--name-only"], {
|
|
79
|
+
const diff = runCommand("git", ["diff", "--name-only"], {
|
|
80
80
|
cwd: PROJECT_ROOT,
|
|
81
|
-
encoding: "utf-8",
|
|
82
81
|
timeout: 5000,
|
|
83
82
|
});
|
|
84
|
-
diffFiles =
|
|
83
|
+
diffFiles = diff.stdout.trim().split("\n").filter(Boolean);
|
|
85
84
|
} catch {
|
|
86
85
|
lines.push("Git diff: 无法获取");
|
|
87
86
|
}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* @Description :
|
|
8
8
|
*/
|
|
9
9
|
import { DPS_SCORING_CONFIG as CFG } from "../../shared/dps-scoring.strategy.js";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import { join } from "path";
|
|
10
12
|
|
|
11
13
|
// ═══════════════ DPS 算法:共享辅助函数 ═══════════════
|
|
12
14
|
|
|
@@ -106,6 +108,11 @@ let _embedPipeline: { embed: (texts: string[]) => Promise<number[][]> } | null =
|
|
|
106
108
|
export async function getEmbeddings(texts: string[]): Promise<number[][]> {
|
|
107
109
|
if (!_embedPipeline) {
|
|
108
110
|
const { pipeline, env } = await import("@huggingface/transformers");
|
|
111
|
+
// 与 add-coder CLI `model:download` 预下载同源:锚定用户级缓存(HF_HUB_CACHE → HF_HOME/hub → ~/.cache/huggingface/hub)
|
|
112
|
+
// ⚠️ transformers v3 默认 cacheDir 指向包内 .cache(重装即丢)——不锚定则 CLI 预下载的模型无法复用
|
|
113
|
+
const hubCache = process.env.HF_HUB_CACHE;
|
|
114
|
+
const home = process.env.HF_HOME || join(homedir(), ".cache", "huggingface");
|
|
115
|
+
env.cacheDir = hubCache || join(home, "hub");
|
|
109
116
|
env.remoteHost = "https://hf-mirror.com";
|
|
110
117
|
env.remotePathTemplate = "{model}/resolve/{revision}/";
|
|
111
118
|
const extractor = await pipeline("feature-extraction", CFG.EMBEDDING_MODEL);
|
|
@@ -392,7 +392,7 @@ Step 8 收敛判断
|
|
|
392
392
|
|------|---------|-------------------|
|
|
393
393
|
| `check_add_route_status` | Step 3 前(前置守卫) | `"add_route_exists": { "enabled": true, "severity": "block" }` |
|
|
394
394
|
| `check_add_route_completeness` | Step 3 代码完成后自检 | `"add_route_completeness": { "enabled": true, "severity": "block" }` |
|
|
395
|
-
| `check_dps({ planKeyword })` | Step 0 末尾(进入 Step 1 前) | `"dps": { "enabled": true, "severity": "block", "threshold":
|
|
395
|
+
| `check_dps({ planKeyword })` | Step 0 末尾(进入 Step 1 前) | `"dps": { "enabled": true, "severity": "block", "threshold": 80 }` |
|
|
396
396
|
| `check_rahs({ planKeyword })` | Step 4 末尾 + Step 8 收敛 | `"rahs": { "enabled": true, "severity": "block", "threshold": 90 }` |
|
|
397
397
|
|
|
398
398
|
策略文件位于 `{{magicDir}}/sync-policy.json`,重型 add-route 模板已内置对应的 §0.8 / §4.6 闸门段落。
|