draftgo-cli 3.0.51 → 3.0.53
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 +32 -34
- package/package.json +2 -3
- package/resources/skill/SKILL.md +12 -18
- package/resources/skill/init/SKILL.md +5 -3
- package/resources/skill/manifest.json +3 -3
- package/resources/skill/references/checkout.md +3 -3
- package/resources/skill/references/frontend.md +1 -1
- package/resources/skill/references/mcp.md +1 -3
- package/src/cli.js +3 -1
- package/src/commandRegistry.js +2 -2
- package/src/commands/check.js +22 -7
- package/src/commands/clean.js +26 -0
- package/src/commands/help.js +19 -20
- package/src/commands/init.js +2 -3
- package/src/commands/task.js +9 -14
- package/src/commands/verify.js +90 -0
- package/src/commands/verifyUi.js +64 -21
- package/src/commands/verifyUiCompat.js +16 -0
- package/src/projectMap.js +20 -8
- package/src/skill.js +0 -9
- package/src/workspaceHealth.js +2 -2
- package/src/worktree/inlineScripts.js +99 -0
- package/src/worktree/status.js +1 -1
- package/src/commands/context.js +0 -27
- package/src/context/index.js +0 -662
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## Workflow 2.0
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The root DraftGo Skill loads automatically in supported AI hosts. Agents read the smallest task-specific Reference set first, then query current project state through precise MCP tools instead of generating an aggregate context bundle.
|
|
6
6
|
|
|
7
7
|
Pages, navigations, documents, and custom services are long-content resources. Custom services use `draftgo checkout custom-services <id>` and a four-file worktree (`service.go`, `go.mod`, `go.sum`, `service.json`). `commit` saves the shared cloud draft, `test` validates or executes it in the DraftGo Runner, and `publish` explicitly promotes a validated draft without interrupting the current live version. Start later work with `refresh`; it stops when local edits exist. Cloud versions are the only history, while local storage keeps only current content and one base.
|
|
8
8
|
|
|
9
|
-
Small, single-point changes do not need Task overhead. Cross-module, cross-session, or multi-Agent work uses one authoritative `.draftgo/Task/[YYYY-MM-DD]<slug>/Task.md` and `draftgo task create|add|claim|start|complete|block|reopen|accept|finish`. The file keeps the user's original request, the clarified executable requirement, expected effects, scope, checklist, decisions, blockers, and final acceptance together. Legacy `task.yaml + plan.md + items/` tasks remain readable and migrate only through an explicit `draftgo task migrate`.
|
|
9
|
+
Small, single-point changes do not need Task overhead. Cross-module, cross-session, or multi-Agent work uses one authoritative `.draftgo/Task/[YYYY-MM-DD]<slug>/Task.md` and `draftgo task create|add|claim|start|complete|block|reopen|accept|finish`. The file keeps the user's original request, the clarified executable requirement, expected effects, scope, checklist, decisions, blockers, and final acceptance together. Legacy `task.yaml + plan.md + items/` tasks remain readable and migrate only through an explicit `draftgo task migrate`. `.draftgo/tmp/` is entirely disposable; user-facing evidence belongs in registered `.draftgo/artifacts/`, and `draftgo clean` removes all tmp plus registered artifacts. UI smoke checks remain single viewport and use `--screenshot never` by default. Supply `on-failure` or `always` only for explicit strong visual verification.
|
|
10
10
|
|
|
11
11
|
面向 AI 编码工具的 DraftGo 工作台 CLI:分发 DraftGo Skill,通过 MCP 发现和操作实时资源,并为页面、导航和文档提供可校验的 `checkout` / `commit` 工作流。
|
|
12
12
|
|
|
@@ -24,9 +24,7 @@ CLI 不再依赖 Python 同步脚本,也不会创建 DraftGo 业务资源的
|
|
|
24
24
|
## 工作模型
|
|
25
25
|
|
|
26
26
|
```text
|
|
27
|
-
|
|
28
|
-
-> 复用一个 MCP 会话并行查询实时上下文
|
|
29
|
-
|
|
27
|
+
根 SKILL.md -> Agent 按任务读取最少必要的 Reference
|
|
30
28
|
AI 宿主 -> draftgo mcp serve -> DraftGo /mcp
|
|
31
29
|
|
|
|
32
30
|
+-> 结构化资源、元数据、搜索和正文片段
|
|
@@ -35,7 +33,7 @@ draftgo checkout/commit -> DraftGo 专用 HTTP 正文端点
|
|
|
35
33
|
(完整 HTML/Markdown 不经过 MCP 上下文)
|
|
36
34
|
```
|
|
37
35
|
|
|
38
|
-
-
|
|
36
|
+
- Agent 负责理解任务语义、选择 Reference,并通过精确 MCP 工具逐步定位相关资源;CLI 不生成聚合上下文包。
|
|
39
37
|
- MCP 用于项目概览、资源搜索/列表、元数据、正文片段和实时 API 调用。
|
|
40
38
|
- `pages`、`navigations` 和 `docs/articles` 的完整正文使用 `checkout` / `commit`。
|
|
41
39
|
- `db_meta`、AIHub、`system_config`、角色、用户、文档分类、自定义服务等结构化资源直接通过 MCP/API 操作,不生成本地索引。
|
|
@@ -45,20 +43,19 @@ draftgo checkout/commit -> DraftGo 专用 HTTP 正文端点
|
|
|
45
43
|
|
|
46
44
|
## Agent 阅读顺序
|
|
47
45
|
|
|
48
|
-
DraftGo Skill 不能被 MCP 替代。根 `SKILL.md` 会在 Skill
|
|
46
|
+
DraftGo Skill 不能被 MCP 替代。根 `SKILL.md` 会在 Skill 触发时自动加载;Agent 按任务路由渐进读取相关 Reference:
|
|
49
47
|
|
|
50
48
|
```text
|
|
51
49
|
已加载的 SKILL.md
|
|
52
|
-
->
|
|
53
|
-
->
|
|
54
|
-
->
|
|
50
|
+
-> 读取任务所需的最少 Reference
|
|
51
|
+
-> 用 resource_search / api_search 精确定位
|
|
52
|
+
-> 按需 describe、读取 metadata 或片段
|
|
55
53
|
-> 必要时 checkout 正文
|
|
56
54
|
```
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
当前 context JSON 使用 `schema_version: "1.1"`;`live.resources` 和 `live.api` 以带来源的 `pages` 序列保留批量原始响应,`live.data_structures` 保留 db_meta 的 registry、describe 契约及完整分页读取结果。
|
|
56
|
+
页面任务读取 `frontend.md`,按需补读 `runtime.md` / `app-api.md`;数据、自定义服务和 AIHub 任务分别读取对应 Reference。目标明确时不要全量枚举无关资源。`mcp test` 是连接诊断,不是每次资源查询的前置步骤。
|
|
60
57
|
|
|
61
|
-
|
|
58
|
+
只回答无需实时状态的本地规则问题时,不必调用 MCP。静态资源须先区分:平台内置目录由 `frontend.md` 说明,指定页面依赖经 MCP 定位、checkout 后本地搜索,服务器全量文件不能凭现有 Skill、MCP 摘要或 checkout 声称已枚举。
|
|
62
59
|
|
|
63
60
|
Skill 说明产品约束、内置能力和操作规则;MCP 说明当前远端状态;checkout 正文才能证明某个页面完整引用了哪些静态资源。汇报时应明确标注这三类证据,不能互相替代。
|
|
64
61
|
|
|
@@ -80,7 +77,7 @@ draftgo connect codex --server https://draftgo.example --token "$DRAFTGO_SAT"
|
|
|
80
77
|
|
|
81
78
|
`--server` 始终表示 DraftGo 基础地址。直接连接 MCP endpoint 时使用 `--mcp-url https://draftgo.example/mcp`;CLI 会显式保存 `mcp_url`,若未同时传 `--server`,则从标准 `/mcp` 后缀推导基础地址,避免猜测已有 base URL 的语义。
|
|
82
79
|
|
|
83
|
-
`connect` 会先验证 SAT、MCP `initialize`、`tools/list` 和关键 `tools/call`,成功后写入项目私有配置 `.draftgo/config.json`,并尝试为指定或自动检测到的宿主执行 MCP setup
|
|
80
|
+
`connect` 会先验证 SAT、MCP `initialize`、`tools/list` 和关键 `tools/call`,成功后写入项目私有配置 `.draftgo/config.json`,并尝试为指定或自动检测到的宿主执行 MCP setup。`init` / `connect` 不会预建 Task、lessons、changelog、worktree、conflicts 等运行时内容;这些文件和目录只在对应能力首次使用时按需创建。它不会 pull 页面、导航、文档或任何其他业务资源。
|
|
84
81
|
|
|
85
82
|
远端暂不可用时,只有显式传入 `--allow-offline` 才会保存配置;恢复后运行 `draftgo mcp test`。使用 `--no-mcp-setup` 可跳过宿主配置。
|
|
86
83
|
|
|
@@ -156,7 +153,8 @@ DraftGo MCP 预期提供以下工具:
|
|
|
156
153
|
## 标准工作流
|
|
157
154
|
|
|
158
155
|
```text
|
|
159
|
-
|
|
156
|
+
Agent 按任务读取相关 Reference
|
|
157
|
+
→ MCP 精确定位
|
|
160
158
|
→ Agent 自主设计并批量 checkout
|
|
161
159
|
→ 独立资源按需并行开发
|
|
162
160
|
→ 主 Agent 一次统一验证
|
|
@@ -164,13 +162,9 @@ context 一次准备信息
|
|
|
164
162
|
→ draftgo changelog add "<完成结果>"
|
|
165
163
|
```
|
|
166
164
|
|
|
167
|
-
无依赖且修改不同资源的工作可以并行;同一文件或 DraftGo 资源全程只分配给一个 Agent。开始并行实现前先确定共享 schema、接口、权限和路由。单页面、强依赖或仍共享主要资源的任务由一个 Agent 完成。主 Agent 负责
|
|
168
|
-
|
|
169
|
-
前端任务先准备上下文并按需补充 MCP 定位:
|
|
165
|
+
无依赖且修改不同资源的工作可以并行;同一文件或 DraftGo 资源全程只分配给一个 Agent。开始并行实现前先确定共享 schema、接口、权限和路由。单页面、强依赖或仍共享主要资源的任务由一个 Agent 完成。主 Agent 负责 Reference/MCP 路由、资源 owner、汇总回读、统一验证、commit 和最终 changelog。
|
|
170
166
|
|
|
171
|
-
|
|
172
|
-
draftgo context --task frontend --output json
|
|
173
|
-
```
|
|
167
|
+
前端任务先读取 `references/frontend.md`,涉及 iframe、路由、认证或全局层时补读 `runtime.md` / `app-api.md`,再通过 MCP 定位目标资源。
|
|
174
168
|
|
|
175
169
|
确定全部正文资源后批量 checkout,自主设计并按唯一 owner 编辑,最后统一验证和交付:
|
|
176
170
|
|
|
@@ -178,8 +172,7 @@ draftgo context --task frontend --output json
|
|
|
178
172
|
draftgo checkout pages 42 43
|
|
179
173
|
# 独立资源可并行编辑;同一资源只由一个 Agent 修改
|
|
180
174
|
draftgo check
|
|
181
|
-
draftgo
|
|
182
|
-
draftgo verify-ui http://localhost:5173 # UI 变更时
|
|
175
|
+
draftgo verify pages 42 --remote --url http://localhost:5173/example
|
|
183
176
|
draftgo diff pages 42
|
|
184
177
|
draftgo diff pages 43
|
|
185
178
|
draftgo commit pages 42 43
|
|
@@ -209,17 +202,17 @@ draftgo changelog add "完成文档管理系统及角色权限"
|
|
|
209
202
|
|
|
210
203
|
| 命令 | 说明 |
|
|
211
204
|
|---|---|
|
|
212
|
-
| `draftgo context --task <task> --output json` | 精确读取任务 Reference 章节,并复用一个 MCP 会话并行查询项目、资源、API 和数据结构;保留原始结果及来源。 |
|
|
213
205
|
| `draftgo map` | 并行读取 pages、navigations、docs/articles 元数据,再叠加本地 checkout 状态;`--type` 可限制一种类型。 |
|
|
214
206
|
| `draftgo checkout <pages|nav|docs> <id...>` | 下载完整正文和 base,校验 hash 后原子落盘;`--force` 可显式覆盖已修改的本地正文。 |
|
|
215
207
|
| `draftgo check` | 默认只检查本地 checkout;`--remote` 额外对比 local/base/manifest/remote 的版本和 hash。 |
|
|
208
|
+
| `draftgo verify [<type> <id...>]` | 统一执行静态检查;`--remote` 增加远端比较,`--url` 增加 iframe-aware 浏览器验证。 |
|
|
216
209
|
| `draftgo diff <pages|nav|docs> <id>` | 显示 checkout base 与当前本地正文的差异。 |
|
|
217
210
|
| `draftgo commit <pages|nav|docs> <id...>` | 本地校验后,通过专用 HTTP 上传完整正文并更新 base/manifest。 |
|
|
218
211
|
| `draftgo reconcile <pages|nav|docs> <id...>` | 仅当 local 与经校验的 remote 字节一致时,安全修复落后的 base/manifest 元数据。 |
|
|
219
212
|
| `draftgo conflicts` | 列出未解决冲突;存在冲突时返回非零。`--all` 包括已解决记录。 |
|
|
220
213
|
| `draftgo conflict show <type> <id>` | 显示冲突的 base/local/remote/worktree 路径。 |
|
|
221
214
|
| `draftgo conflict resolve <type> <id>` | 确认 worktree 已合并,把保留的 remote 设为新 base;随后重新 check、diff、commit。 |
|
|
222
|
-
| `draftgo verify-ui <url>` |
|
|
215
|
+
| `draftgo verify-ui <url>` | `verify --url <url> --ui always` 的弃用兼容入口。 |
|
|
223
216
|
|
|
224
217
|
`pages`、`page`,`nav`、`navigation`、`navigations`,以及 `docs`、`doc`、`article`、`articles`、`docs/articles` 都会规范化到三个支持的正文类型。
|
|
225
218
|
|
|
@@ -316,7 +309,7 @@ checkout 会通过 MCP 获取元数据和专用下载地址,流式写入临时
|
|
|
316
309
|
1. `draftgo conflict show <type> <id>` 定位三份材料和 worktree 文件。
|
|
317
310
|
2. 在 worktree 文件中人工或借助可靠的三方合并工具完成合并。
|
|
318
311
|
3. `draftgo conflict resolve <type> <id>` 校验 worktree,并把冲突时保存的 remote 版本设为新 base。
|
|
319
|
-
4. 重新运行 `draftgo check`、必要时 `verify
|
|
312
|
+
4. 重新运行 `draftgo check`、必要时 `draftgo verify`、`draftgo diff`,最后 `draftgo commit`。
|
|
320
313
|
|
|
321
314
|
## map 与 check 输出
|
|
322
315
|
|
|
@@ -332,7 +325,11 @@ checkout 会通过 MCP 获取元数据和专用下载地址,流式写入临时
|
|
|
332
325
|
}
|
|
333
326
|
```
|
|
334
327
|
|
|
335
|
-
`draftgo check --output json`
|
|
328
|
+
`draftgo check --output json` 返回结构化的本地、远端和工作区检查结果。它以声明的 charset(默认 UTF-8)严格解码 HTML,并在内存中检查内联 JavaScript,错误直接映射到原 HTML 行列,不生成 `.draftgo/tmp/syntax/*.js`。`--strict` 会把 warnings 也视为失败。默认 `check` 不访问远端;显式使用 `--remote` 时读取实时 metadata,并把 `committed_unrecorded` 等可恢复状态指向 `draftgo reconcile`。
|
|
329
|
+
|
|
330
|
+
`draftgo verify` 是交付前统一入口。无参数时只运行快速本地 `check`;`--remote` 才联网,`--url` 才启动浏览器。浏览器检查默认使用 `--frame auto`,同时检查顶层页面和可见 iframe,因此 `--selector` 可匹配 `iframe.srcdoc` 中的业务 DOM。`--viewport mobile|desktop|both` 控制目标视口,截图默认关闭。
|
|
331
|
+
|
|
332
|
+
`.draftgo/tmp/` 是统一临时区,CLI 和 AI 产生的可丢弃中间文件必须位于 `.draftgo/tmp/<owner>/<run-id>/`;AI 自建文件使用 `.draftgo/tmp/ai/<run-id>/`。`draftgo clean --dry-run` 会列出全部 tmp 文件和已注册 artifacts,`draftgo clean --yes` 负责回收并删除空运行目录。需要保留供用户查看的截图或报告应进入 `.draftgo/artifacts/`,而不是 tmp。
|
|
336
333
|
|
|
337
334
|
## Skill 与领域约定
|
|
338
335
|
|
|
@@ -350,8 +347,7 @@ checkout 会通过 MCP 获取元数据和专用下载地址,流式写入临时
|
|
|
350
347
|
## 常用选项
|
|
351
348
|
|
|
352
349
|
- `--project <dir>`:操作指定项目目录,默认当前目录。
|
|
353
|
-
- `--output json`:为
|
|
354
|
-
- `--task <task>`:选择 context 路由;支持 frontend、data、custom-service、aihub、content、project。
|
|
350
|
+
- `--output json`:为 map、check、checkout、commit、diff、conflicts、conflict、api 或 delete 输出 JSON。
|
|
355
351
|
- `--type <type>`:限制 `map` 查询一种正文资源类型;支持 pages、nav/navigations、docs/articles 及其别名。
|
|
356
352
|
- `--strict`:check/deploy/auto-push 将 warnings 视为失败。
|
|
357
353
|
- `--remote`:让 check 按需对比 checkout 的远端版本和 hash;默认仍为快速离线检查。
|
|
@@ -364,13 +360,15 @@ checkout 会通过 MCP 获取元数据和专用下载地址,流式写入临时
|
|
|
364
360
|
- `--mcp-url <url>`:为 connect 显式指定完整 MCP endpoint;标准 `/mcp` 可自动推导基础地址,自定义路径需同时传 `--server`。
|
|
365
361
|
- `--allow-offline` / `--no-mcp-setup`:允许 connect 在 MCP 暂不可用时保存,或跳过宿主配置。
|
|
366
362
|
- `--yes`:跳过支持该选项的交互确认。
|
|
367
|
-
- `--
|
|
368
|
-
- `--
|
|
369
|
-
- `--
|
|
370
|
-
- `--
|
|
363
|
+
- `--ui auto|always|never`:控制 verify 的浏览器验证;默认 auto,只在提供 `--url` 时运行。
|
|
364
|
+
- `--viewport mobile|desktop|both`:控制 verify 的目标视口;不传时使用 `--width/--height` 或 390x844。
|
|
365
|
+
- `--frame auto|top|all|<iframe-selector>`:控制 verify 检查哪些 frame;默认检查顶层与可见 iframe。
|
|
366
|
+
- `--resource <type:id>`:兼容入口使用;推荐直接写 `draftgo verify pages 42 --url ...`。
|
|
367
|
+
- `--browser-path <file>`:verify 显式使用浏览器可执行文件;也可设置 `DRAFTGO_BROWSER_PATH`,否则自动查找系统浏览器和 Playwright 缓存。
|
|
368
|
+
- `--token auto|never`:verify 默认读取 `.draftgo/config.json`,对与 `server` 同源的地址自动附加 `token=<SAT>`;配置无 SAT、跨源地址或 `never` 模式均不附加。
|
|
371
369
|
- `--screenshot on-failure|always|never`:控制 UI 截图。
|
|
372
370
|
- `--delivery local|preview|deploy`:控制 deploy 行为。
|
|
373
|
-
- `--timeout <ms>`:控制 connect
|
|
371
|
+
- `--timeout <ms>`:控制 connect 或 MCP test 的远端请求超时。
|
|
374
372
|
|
|
375
373
|
设置 `DRAFTGO_NO_UPDATE_CHECK=1` 可关闭 npm 版本检查,适用于离线或 CI 环境。
|
|
376
374
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "draftgo-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.53",
|
|
4
4
|
"description": "Install and manage the DraftGo skill across AI coding agents (Claude Code, Codex, Cursor, Windsurf, Antigravity, Copilot, Gemini, Kiro).",
|
|
5
5
|
"bin": {
|
|
6
6
|
"draftgo": "bin/draftgo.js"
|
|
@@ -45,9 +45,8 @@
|
|
|
45
45
|
"lint": "node scripts/check-syntax.js",
|
|
46
46
|
"validate:skill": "node scripts/validate-skill.js",
|
|
47
47
|
"verify:package": "node scripts/verify-package.js",
|
|
48
|
-
"test": "npm run lint && npm run validate:skill && npm run verify:package && npm run test:unit && npm run test:
|
|
48
|
+
"test": "npm run lint && npm run validate:skill && npm run verify:package && npm run test:unit && npm run test:workflow && npm run test:changelog && npm run test:mcp && npm run test:worktree && npm run test:migration && npm run test:local && npm run test:e2e",
|
|
49
49
|
"test:unit": "node tests/unit.js",
|
|
50
|
-
"test:context": "node tests/context.test.js",
|
|
51
50
|
"test:workflow": "node tests/workflow-upgrade.test.js",
|
|
52
51
|
"test:changelog": "node tests/changelog.test.js",
|
|
53
52
|
"test:mcp": "node tests/mcp.test.js",
|
package/resources/skill/SKILL.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: draftgo
|
|
3
|
-
description: Use this skill to inspect, develop, debug, or deliver a DraftGo application.
|
|
3
|
+
description: Use this skill to inspect, develop, debug, or deliver a DraftGo application. Read task-specific references before using live MCP discovery, use checkout/commit for complete page, navigation, document, and custom-service bodies, and write the changelog only after all verification and delivery succeed.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Workflow 2.0 authority
|
|
7
7
|
|
|
8
8
|
- Treat pages, navigations, docs/articles, and custom services as checkout resources. Never save complete MCP responses, duplicate source snapshots, temporary Go modules, SDK stubs, executables, or build directories by hand.
|
|
9
|
-
-
|
|
10
|
-
- Custom-service flow: `
|
|
9
|
+
- The root Skill loads automatically. Before acting, read the smallest relevant Reference set from the task-routing table, then use MCP only for live project evidence.
|
|
10
|
+
- Custom-service flow: read `references/custom-services.md` -> locate the service through MCP -> `checkout custom-services` -> edit four files -> `commit` cloud draft -> `test` in the server Runner -> `check --remote` -> `publish` -> `refresh`. CLI and admin UI edit the same cloud draft.
|
|
11
11
|
- Do not create Task overhead for a small, single-point change. For cross-module, cross-session, or multi-Agent work, create or resume `.draftgo/Task/[YYYY-MM-DD]<slug>/Task.md`. It is the only task state: preserve both the user's original request and the clarified executable requirement, assign one owner per item/resource, and check an item only with verification evidence. Changelog remains the final delivery record, not a task tracker.
|
|
12
|
-
- Normal
|
|
13
|
-
- CLI
|
|
12
|
+
- Normal delivery uses `draftgo verify`; add `--remote` only when remote comparison is required and `--url` only for browser evidence. UI verification is iframe-aware and defaults to one viewport with no screenshot. Only explicit visual acceptance or regression diagnosis may pass `--viewport both` or `--screenshot on-failure|always`.
|
|
13
|
+
- `.draftgo/tmp/` is entirely disposable. CLI data uses `.draftgo/tmp/<command>/<run-id>/`; AI-created scratch files use `.draftgo/tmp/ai/<run-id>/`. User-facing evidence belongs under registered `.draftgo/artifacts/`. Use `draftgo clean --dry-run` before `draftgo clean --yes`.
|
|
14
14
|
|
|
15
15
|
# DraftGo 开发助手
|
|
16
16
|
|
|
@@ -19,19 +19,13 @@ description: Use this skill to inspect, develop, debug, or deliver a DraftGo app
|
|
|
19
19
|
- 本地 Skill / Reference 提供产品约束、运行机制和实践;MCP 提供当前项目、资源、API、权限与 schema。
|
|
20
20
|
- pages、navigations、docs/articles 的完整正文只通过 `draftgo checkout`、本地 worktree 和 `draftgo commit` 处理,不放进 MCP 参数、结果、日志或聊天上下文。
|
|
21
21
|
- db_meta、AIHub、system_config、roles、users、doc_categories 和自定义服务元数据直接通过 MCP 读写,不建立本地索引。
|
|
22
|
-
-
|
|
22
|
+
- 根 Skill 会在触发时自动加载。Agent 必须先按任务读取最少必要的 Reference,再通过 MCP 获取实时项目证据;MCP 不可用时报告连接、协议或 SAT 问题,不回退到旧索引或 `pull --all`。
|
|
23
23
|
- CLI 不提供页面模板,不预设页面骨架、视觉风格、原生技术或组件库选择。Agent 根据任务、受众、现有产品语言和可用资源自主设计。
|
|
24
24
|
- 本地 Docker、MySQL、Redis、Milvus 与 `draftgo local ...` 独立于 MCP 工作流,必须保留。
|
|
25
25
|
|
|
26
26
|
## 任务路由
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
draftgo context --task <frontend|data|custom-service|aihub|content|project> --output json
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
context 会校验本地 Reference,返回逐字章节、来源、实时项目/资源/API/数据结构和 bundle 同步状态;不同步时先运行 `draftgo update`。它不会限制后续 MCP 查询。只回答本地规则或需要 context 未加载的专题时,直接补读对应 Reference:
|
|
28
|
+
根 Skill 自动加载后,Agent 根据用户任务先读取下表中最少必要的 Reference,再用 MCP 查询当前项目。不要预先读取所有 Reference,也不要在目标明确时全量枚举无关资源:
|
|
35
29
|
|
|
36
30
|
| 任务 | 专题资料与后续动作 |
|
|
37
31
|
|---|---|
|
|
@@ -50,7 +44,7 @@ context 会校验本地 Reference,返回逐字章节、来源、实时项目/
|
|
|
50
44
|
- 同一文件或 DraftGo 资源全程只能由一个 Agent 修改;其他 Agent 只读分析并回传建议。
|
|
51
45
|
- 先确定共享 schema、接口、权限和 route,再并行处理无依赖且 owner 不冲突的工作单元。
|
|
52
46
|
- 单页面、强依赖或仍共享主要资源的任务不强行并行。
|
|
53
|
-
- 主 Agent
|
|
47
|
+
- 主 Agent 负责 Reference/MCP 路由、owner 分配、汇总回读、统一验证、交付和完成日志;子 Agent 不单独写 changelog。
|
|
54
48
|
- 冲突 owner、接口依赖或验证失败会阻塞依赖项,不影响无关分支继续汇总。
|
|
55
49
|
|
|
56
50
|
## 开发与交付
|
|
@@ -59,8 +53,8 @@ context 会校验本地 Reference,返回逐字章节、来源、实时项目/
|
|
|
59
53
|
|
|
60
54
|
1. MCP 定位 pages/nav/docs 并读取 metadata。
|
|
61
55
|
2. 批量 checkout;在 `.draftgo/worktree/` 按唯一 owner 编辑。
|
|
62
|
-
3. 主 Agent
|
|
63
|
-
4. 用 `draftgo diff <type> <id>` 检查 base/local 差异,再按类型运行 `draftgo commit
|
|
56
|
+
3. 主 Agent 回读全部修改,编辑过程中统一运行一次快速 `draftgo check`。交付前运行 `draftgo verify <type> <id...>`;需要远端证据时加 `--remote`,页面布局或交互变化时加对应 `--url`。
|
|
57
|
+
4. 用 `draftgo diff <type> <id>` 检查 base/local 差异,再按类型运行 `draftgo commit ...`。commit 后需要验证远端页面时运行 `draftgo verify <type> <id> --remote --url <url>`。
|
|
64
58
|
5. 409/412 时停止自动提交,保留 base/local/remote 冲突材料;不得 force、覆盖或自动合并。
|
|
65
59
|
|
|
66
60
|
完整 manifest、流式传输、哈希和冲突规则见 `references/checkout.md`。
|
|
@@ -93,10 +87,10 @@ draftgo changelog add "<完成结果>"
|
|
|
93
87
|
| 范围 | 最低证据 |
|
|
94
88
|
|---|---|
|
|
95
89
|
| MCP 连接 | 失败时用 `draftgo mcp test` 核对 initialize、tools/list 和关键工具;输出不含 SAT |
|
|
96
|
-
| 页面、导航、文档 | checkout manifest、`draftgo check
|
|
90
|
+
| 页面、导航、文档 | checkout manifest、`draftgo check`、交付前 `draftgo verify`、diff、commit 返回版本与哈希 |
|
|
97
91
|
| 结构化资源 | search/describe 契约、call 结果与回读的权限、字段、错误和副作用 |
|
|
98
92
|
| 自定义服务 | 动态 Route describe、无副作用健康请求或目标行为结果,以及管理员调用审计 |
|
|
99
|
-
| 冲突 | `.draftgo/conflicts/` 的 base/local/remote;解决后重新 check、必要的 verify
|
|
93
|
+
| 冲突 | `.draftgo/conflicts/` 的 base/local/remote;解决后重新 check、必要的 verify 和 commit |
|
|
100
94
|
| 本地底座 | `draftgo local status`、日志和相关 local 测试 |
|
|
101
95
|
|
|
102
96
|
`draftgo deploy`、`auto-push` 和兼容 `push pages|nav|docs` 只能沿用当前 check/commit 语义,不能恢复旧的全量 push。主 Agent 最终明确区分 Skill 约束、MCP 实时状态和 checkout 正文证据。
|
|
@@ -17,10 +17,12 @@ description: Install or refresh the DraftGo skill, connect a project to a DraftG
|
|
|
17
17
|
- 已有 DraftGo 服务器:运行 draftgo connect。
|
|
18
18
|
- 需要本地 Docker 基座:运行 draftgo local setup。
|
|
19
19
|
6. 连接后运行 draftgo mcp setup(或指定目标),再运行 draftgo mcp test 验证 initialize、tools/list 和关键工具。
|
|
20
|
-
7.
|
|
20
|
+
7. 根 Skill 自动加载后,按实际任务读取最少必要的 Reference,并通过 MCP project_overview、resource_search 或 api_search 获取实时信息;需要叠加本地 checkout 状态时运行 `draftgo map`。MCP 不可用时报告原因,不回退到 pull --all。
|
|
21
21
|
|
|
22
22
|
draftgo init 只负责 Skill 安装;draftgo connect 负责保存并验证 server/SAT;draftgo mcp setup 负责宿主配置。不要混用职责。
|
|
23
23
|
|
|
24
|
+
初始化后 `.draftgo/` 只保留已经写入的 `config.json`。不要预建 Task、lessons、changelog、worktree、conflicts 或其他占位文件和目录;首次实际使用对应能力时再创建。
|
|
25
|
+
|
|
24
26
|
## SAT 与配置
|
|
25
27
|
|
|
26
28
|
- 交互式连接应使用隐藏输入;不要把 SAT 写入宿主配置、Skill 文件、命令行示例或日志。
|
|
@@ -31,9 +33,9 @@ draftgo init 只负责 Skill 安装;draftgo connect 负责保存并验证 serv
|
|
|
31
33
|
## 后续动作
|
|
32
34
|
|
|
33
35
|
- 宿主配置和诊断:draftgo mcp setup/status/test,详见 ../references/mcp.md。
|
|
34
|
-
-
|
|
36
|
+
- 开发准备:根 Skill 自动加载;按任务路由读取最少必要的 Reference,再按需直接调用 MCP。
|
|
35
37
|
- 远端资源补充定位:MCP project_overview、resource_search、resource_list。
|
|
36
|
-
- 正文编辑:自主设计并批量 checkout,不同资源按唯一 owner 并行修改,由主 Agent 统一运行 check
|
|
38
|
+
- 正文编辑:自主设计并批量 checkout,不同资源按唯一 owner 并行修改,由主 Agent 统一运行 check、交付前 verify、diff 和 commit。
|
|
37
39
|
- 结构化资源:直接使用 MCP 的 api_search、api_describe、api_call;不 checkout、不生成本地镜像。
|
|
38
40
|
- 完成日志:只有整个任务统一验证且全部 commit/MCP 交付成功后,由主 Agent 执行一次 `draftgo changelog add "<完成结果>"`;验证、冲突或交付失败时不得写入。
|
|
39
41
|
- 管理本地基座:draftgo local start|stop|logs|status;local-dev、local up/down 仍可用。
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"schema_version": "1.0",
|
|
3
3
|
"id": "draftgo",
|
|
4
4
|
"name": "DraftGo 开发助手",
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.53",
|
|
6
6
|
"entry": "SKILL.md",
|
|
7
|
-
"description": "以
|
|
7
|
+
"description": "以 Skill/reference 任务路由、MCP 实时发现、长正文 checkout/commit、统一验证和完成日志为边界的 DraftGo 工作流。",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"capabilities": [
|
|
10
10
|
"draftgo-development",
|
|
11
|
-
"
|
|
11
|
+
"reference-routing",
|
|
12
12
|
"completion-changelog",
|
|
13
13
|
"custom-service-ai-sdk",
|
|
14
14
|
"mcp-bridge",
|
|
@@ -93,12 +93,12 @@ base 已变化时必须拒绝覆盖。
|
|
|
93
93
|
## Commit 流程
|
|
94
94
|
|
|
95
95
|
1. 读取 manifest 指向的 worktree 文件,计算当前字节数和 SHA-256;未变化时返回 `unchanged`。
|
|
96
|
-
2. 按 content_type
|
|
96
|
+
2. 按 content_type 执行本地结构和内联脚本检查;页面布局或交互有变化时运行 `draftgo verify <type> <id> --url <url>`。
|
|
97
97
|
3. 通过专用 HTTP 流式上传原始文件,携带 `If-Match`、base version/revision、content_type、长度和 SHA-256。
|
|
98
98
|
4. 完整正文不得作为 MCP tool 参数发送。
|
|
99
99
|
5. 底座确认 hash 和新版本后,CLI 原子更新 `.base` 与 manifest。返回 hash 不一致时不得推进基线。
|
|
100
100
|
|
|
101
|
-
推荐编辑顺序:主 Agent
|
|
101
|
+
推荐编辑顺序:主 Agent 按任务读取相关 Reference -> MCP 精确定位 -> Agent 自主设计并批量 checkout -> 独立资源按唯一 owner 并行编辑 -> 主 Agent 汇总回读 -> 统一运行一次 `draftgo check` -> `draftgo diff` -> commit -> 页面变化时用 `draftgo verify <type> <id> --remote --url <url>` 验证远端已提交版本。遇到本地正文已经等于远端、但 base/manifest 落后时,先用 `draftgo check --remote` 确认 `committed_unrecorded`,再运行 `draftgo reconcile`;不要手改 manifest。
|
|
102
102
|
|
|
103
103
|
单个 commit 成功不自动写 changelog。只有整个任务统一验证且全部 commit/MCP 交付成功后,主 Agent 才执行一次 `draftgo changelog add "<完成结果>"`。任何检查失败、409/412 或交付失败都不得写入。
|
|
104
104
|
|
|
@@ -117,7 +117,7 @@ base 已变化时必须拒绝覆盖。
|
|
|
117
117
|
- `base` 是 checkout 时的内容;`local` 是发生冲突时的本地快照;`remote` 是重新下载并校验的当前远端内容。
|
|
118
118
|
- `conflict.json` 记录三份路径、版本、ETag 和哈希,不嵌入完整正文。
|
|
119
119
|
- Agent 或用户在 worktree local 文件中完成合并;不要手写 HTML 自动合并器,也不要改动保存的三份证据。
|
|
120
|
-
- 合并完成后运行 `draftgo check`、必要时 `draftgo verify
|
|
120
|
+
- 合并完成后运行 `draftgo check`、必要时 `draftgo verify`,再执行 `draftgo conflict resolve <type> <id>`。
|
|
121
121
|
- resolve 校验 worktree 与 remote,采用 remote 版本作为新的 base,但保留合并后的 worktree;随后运行
|
|
122
122
|
`draftgo diff` 并 `draftgo commit`。
|
|
123
123
|
|
|
@@ -68,7 +68,7 @@ version: 2.0.0
|
|
|
68
68
|
- 表格、代码和其他超宽内容应在合理边界内可访问,不能让核心操作因溢出而不可达。
|
|
69
69
|
- 弹窗和抽屉在目标视口内完整可用,长内容有明确滚动边界。
|
|
70
70
|
|
|
71
|
-
需要浏览器证据时按页面受众和现有断点运行 `draftgo verify
|
|
71
|
+
需要浏览器证据时按页面受众和现有断点运行 `draftgo verify <type> <id> --url <url>`;只有验收确实覆盖多端时加 `--viewport both`,不要机械遍历与任务无关的视口。业务 HTML 位于 iframe 时默认 `--frame auto` 会检查顶层和可见 iframe,`--selector` 可直接定位业务 DOM。
|
|
72
72
|
|
|
73
73
|
### 导航与系统页边界(强制)
|
|
74
74
|
|
|
@@ -12,7 +12,7 @@ DraftGo MCP 用于实时发现、结构化查询和普通 API 操作。完整 pa
|
|
|
12
12
|
MCP tool result 或参数传输;需要全文时使用 `draftgo checkout`,提交时使用 `draftgo commit`。MCP 返回
|
|
13
13
|
`artifact` / `omitted` 时保留该语义,不要尝试重新展开长内容。
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
不要在 CLI 或 MCP 服务端增加聚合上下文工具。自然语言任务的语义筛选由已加载根 Skill 的 Agent 完成:先读取任务路由指定的最少必要 Reference,再调用下面的精确 MCP 工具,并根据结果逐步缩小范围。
|
|
16
16
|
|
|
17
17
|
标准发现顺序:
|
|
18
18
|
|
|
@@ -75,14 +75,12 @@ describe 缺少与本次调用有关的参数、请求体、responses、permissi
|
|
|
75
75
|
## CLI
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
draftgo context --task frontend --output json
|
|
79
78
|
draftgo mcp setup [target...]
|
|
80
79
|
draftgo mcp status [target...]
|
|
81
80
|
draftgo mcp test
|
|
82
81
|
draftgo mcp serve
|
|
83
82
|
```
|
|
84
83
|
|
|
85
|
-
- `context` 是开发任务的一次性准备入口;不保存业务镜像,不传输完整正文。
|
|
86
84
|
- `setup` 写入项目级宿主配置,只替换 `draftgo` MCP 条目并保留其他配置。
|
|
87
85
|
- `status` 检查配置是否存在、格式是否有效,以及是否误写了凭据或远端 URL。
|
|
88
86
|
- `test` 从 `.draftgo/config.json` 读取连接,验证 initialize、tools/list、三类正文 resource_list,以及 db_meta 的 api_search、api_describe 和只读 api_call。
|
package/src/cli.js
CHANGED
|
@@ -15,6 +15,9 @@ const VALUE_FLAGS = new Set([
|
|
|
15
15
|
'browser-path',
|
|
16
16
|
'resource',
|
|
17
17
|
'mobile-check',
|
|
18
|
+
'ui',
|
|
19
|
+
'frame',
|
|
20
|
+
'viewport',
|
|
18
21
|
'screenshot',
|
|
19
22
|
'selector',
|
|
20
23
|
'width',
|
|
@@ -28,7 +31,6 @@ const VALUE_FLAGS = new Set([
|
|
|
28
31
|
'params',
|
|
29
32
|
'input',
|
|
30
33
|
'type',
|
|
31
|
-
'task',
|
|
32
34
|
'title',
|
|
33
35
|
'description',
|
|
34
36
|
'item-id',
|
package/src/commandRegistry.js
CHANGED
|
@@ -7,13 +7,13 @@ const commands = [
|
|
|
7
7
|
{ name: 'update', run: (dir, args, flags) => require('./commands/update')(dir, args, flags) },
|
|
8
8
|
{ name: 'uninstall', aliases: ['remove'], run: (dir, args, flags) => require('./commands/uninstall')(dir, args, flags) },
|
|
9
9
|
{ name: 'status', run: (dir) => require('./commands/status')(dir) },
|
|
10
|
-
{ name: 'context', run: (dir, args, flags) => require('./commands/context')(dir, args, flags) },
|
|
11
10
|
{ name: 'changelog', run: (dir, args, flags) => require('./commands/changelog')(dir, args, flags) },
|
|
12
11
|
{ name: 'task', run: (dir, args, flags) => require('./commands/task')(dir, args, flags) },
|
|
13
12
|
{ name: 'clean', run: (dir, args, flags) => require('./commands/clean')(dir, args, flags) },
|
|
14
13
|
{ name: 'map', run: (dir, _args, flags) => require('./commands/map')(dir, flags) },
|
|
15
14
|
{ name: 'check', run: (dir, args, flags) => require('./commands/check')(dir, args, flags) },
|
|
16
|
-
{ name: 'verify
|
|
15
|
+
{ name: 'verify', run: (dir, args, flags) => require('./commands/verify')(dir, args, flags) },
|
|
16
|
+
{ name: 'verify-ui', aliases: ['verifyui'], run: (dir, args, flags) => require('./commands/verifyUiCompat')(dir, args, flags) },
|
|
17
17
|
{ name: 'mcp', run: (dir, args, flags) => require('./commands/mcp')(dir, args, flags) },
|
|
18
18
|
{ name: 'checkout', run: (dir, args, flags) => require('./commands/checkout')(dir, args, flags) },
|
|
19
19
|
{ name: 'refresh', run: (dir, args, flags) => require('./commands/checkout')(dir, args, flags) },
|
package/src/commands/check.js
CHANGED
|
@@ -27,7 +27,15 @@ async function check(projectDir, positional = [], flags = {}) {
|
|
|
27
27
|
log.err('Usage: draftgo check custom-services <id...> [--remote]');
|
|
28
28
|
return 1;
|
|
29
29
|
}
|
|
30
|
-
const
|
|
30
|
+
const resourceKeys = flags.resourceKeys || null;
|
|
31
|
+
const result = analyzeProject(projectDir, { resourceKeys });
|
|
32
|
+
if (resourceKeys) {
|
|
33
|
+
const manifestKeys = new Set(Object.keys(result.map.checkouts.reduce((entries, entry) => {
|
|
34
|
+
entries[`${entry.resource_type}:${entry.resource_id}`] = true;
|
|
35
|
+
return entries;
|
|
36
|
+
}, {})));
|
|
37
|
+
for (const key of resourceKeys) if (!manifestKeys.has(key)) result.errors.push(`${key}: resource is not checked out`);
|
|
38
|
+
}
|
|
31
39
|
const hygiene = workspaceHealth(projectDir);
|
|
32
40
|
hygiene.warnings.forEach((warning) => result.warningDetails.push({ code: warning.code, confidence: 'high', message: `${warning.path}${warning.size ? ` (${warning.size} bytes)` : ''}` }));
|
|
33
41
|
hygiene.warnings.forEach((warning) => result.warnings.push(`${warning.code}: ${warning.path}`));
|
|
@@ -35,7 +43,7 @@ async function check(projectDir, positional = [], flags = {}) {
|
|
|
35
43
|
const customServiceChecks = [];
|
|
36
44
|
const requested = new Set(requestedIds.map(String));
|
|
37
45
|
const serviceEntries = Object.values(serviceManifest.entries)
|
|
38
|
-
.filter((entry) => !requestedType || requested.has(String(entry.resource_id)));
|
|
46
|
+
.filter((entry) => !resourceKeys && (!requestedType || requested.has(String(entry.resource_id))));
|
|
39
47
|
if (requestedType) {
|
|
40
48
|
for (const id of requested) {
|
|
41
49
|
if (!serviceEntries.some((entry) => String(entry.resource_id) === id)) {
|
|
@@ -56,8 +64,12 @@ async function check(projectDir, positional = [], flags = {}) {
|
|
|
56
64
|
if (flags.remote) {
|
|
57
65
|
try {
|
|
58
66
|
const [contentRemote, serviceRemote] = await Promise.all([
|
|
59
|
-
inspectRemoteCheckouts(projectDir
|
|
60
|
-
|
|
67
|
+
inspectRemoteCheckouts(projectDir, resourceKeys ? {
|
|
68
|
+
entries: result.map.checkouts.filter((entry) => resourceKeys.includes(`${entry.resource_type}:${entry.resource_id}`)),
|
|
69
|
+
} : {}),
|
|
70
|
+
resourceKeys
|
|
71
|
+
? Promise.resolve([])
|
|
72
|
+
: customServices.inspectRemote(projectDir, requestedType ? { ids: [...requested] } : {}),
|
|
61
73
|
]);
|
|
62
74
|
remote = requestedType
|
|
63
75
|
? serviceRemote.filter((entry) => requested.has(String(entry.resource_id)))
|
|
@@ -87,9 +99,12 @@ async function check(projectDir, positional = [], flags = {}) {
|
|
|
87
99
|
}
|
|
88
100
|
|
|
89
101
|
log.title('draftgo check');
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
const selectedCount = (type, entries) => resourceKeys
|
|
103
|
+
? entries.filter((entry) => resourceKeys.includes(`${type}:${entry.resource_id}`)).length
|
|
104
|
+
: entries.length;
|
|
105
|
+
log.info(`Checked-out pages: ${selectedCount('pages', result.map.pages)}`);
|
|
106
|
+
log.info(`Checked-out navigations: ${selectedCount('navigations', result.map.navigations)}`);
|
|
107
|
+
log.info(`Checked-out docs: ${selectedCount('docs', result.map.docs)}`);
|
|
93
108
|
log.info(`Checked-out custom services: ${customServiceChecks.length}`);
|
|
94
109
|
log.info(`Workspace: ${hygiene.managed_files} managed, ${hygiene.unknown_files} unknown, ${hygiene.temporary_files} temporary, ${hygiene.artifact_files} artifact file(s)`);
|
|
95
110
|
log.info(`Workspace size: ${hygiene.total_bytes} bytes; reclaimable: ${hygiene.reclaimable_bytes} bytes`);
|
package/src/commands/clean.js
CHANGED
|
@@ -23,6 +23,24 @@ function plan(projectDir, flags = {}) {
|
|
|
23
23
|
const stat = fs.statSync(absolute); if (age && now - stat.mtimeMs < age) continue;
|
|
24
24
|
candidates.push({ ...entry, absolute, size: stat.isFile() ? stat.size : 0, reason: 'runtime_manifest' });
|
|
25
25
|
}
|
|
26
|
+
const tmp = path.resolve(root, 'tmp');
|
|
27
|
+
if (fs.existsSync(tmp) && runtime.inside(root, tmp) && (!types.size || types.has('tmp') || types.has('ai'))) {
|
|
28
|
+
const visitTmp = (current) => {
|
|
29
|
+
for (const child of fs.readdirSync(current, { withFileTypes: true })) {
|
|
30
|
+
const absolute = path.join(current, child.name);
|
|
31
|
+
if (child.isDirectory()) visitTmp(absolute);
|
|
32
|
+
else if (child.isFile() && !candidates.some((entry) => entry.absolute === absolute)) {
|
|
33
|
+
const stat = fs.statSync(absolute);
|
|
34
|
+
if (!age || now - stat.mtimeMs >= age) candidates.push({
|
|
35
|
+
path: path.relative(root, absolute).replace(/\\/g, '/'), absolute,
|
|
36
|
+
type: path.relative(tmp, absolute).replace(/\\/g, '/').startsWith('ai/') ? 'ai' : 'tmp',
|
|
37
|
+
size: stat.size, reason: 'temporary_area',
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
visitTmp(tmp);
|
|
43
|
+
}
|
|
26
44
|
if (flags['all-artifacts']) {
|
|
27
45
|
for (const prefix of MANAGED_PREFIXES.filter((item) => item.startsWith('artifacts/'))) {
|
|
28
46
|
const directory = path.resolve(root, prefix); if (!runtime.inside(root, directory) || !fs.existsSync(directory)) continue;
|
|
@@ -39,6 +57,14 @@ async function clean(projectDir, _positional, flags = {}) {
|
|
|
39
57
|
if (!flags.yes || flags['dry-run']) { if (!flags.output) log.dim('Run with --yes to delete this plan.'); return 0; }
|
|
40
58
|
const manifest = runtime.load(projectDir); const removed = new Set();
|
|
41
59
|
for (const entry of result.entries) { if (!runtime.inside(runtime.draftgoRoot(projectDir), entry.absolute)) throw new Error('Clean target escaped .draftgo.'); fs.rmSync(entry.absolute, { force: true }); removed.add(entry.path); }
|
|
60
|
+
const tmp = path.join(runtime.draftgoRoot(projectDir), 'tmp');
|
|
61
|
+
if (fs.existsSync(tmp)) {
|
|
62
|
+
const removeEmpty = (directory) => {
|
|
63
|
+
for (const child of fs.readdirSync(directory, { withFileTypes: true })) if (child.isDirectory()) removeEmpty(path.join(directory, child.name));
|
|
64
|
+
if (directory !== tmp && fs.readdirSync(directory).length === 0) fs.rmdirSync(directory);
|
|
65
|
+
};
|
|
66
|
+
removeEmpty(tmp);
|
|
67
|
+
}
|
|
42
68
|
manifest.entries = manifest.entries.filter((entry) => !removed.has(entry.path)); runtime.save(projectDir, manifest);
|
|
43
69
|
if (!flags.output) log.ok(`Deleted ${result.count} managed file(s).`); return 0;
|
|
44
70
|
}
|