draftgo-cli 1.0.4

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.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -0
  3. package/bin/draftgo.js +9 -0
  4. package/package.json +70 -0
  5. package/resources/project-design/README.md +42 -0
  6. package/resources/skill/SKILL.md +62 -0
  7. package/resources/skill/init/SKILL.md +41 -0
  8. package/resources/skill/manifest.json +35 -0
  9. package/resources/skill/references/ai.md +41 -0
  10. package/resources/skill/references/app-api.md +97 -0
  11. package/resources/skill/references/architecture.md +13 -0
  12. package/resources/skill/references/chat-sdk.md +205 -0
  13. package/resources/skill/references/checkout.md +140 -0
  14. package/resources/skill/references/data.md +49 -0
  15. package/resources/skill/references/db-relations.md +29 -0
  16. package/resources/skill/references/delivery.md +33 -0
  17. package/resources/skill/references/development.md +41 -0
  18. package/resources/skill/references/diagnostics.md +50 -0
  19. package/resources/skill/references/frontend.md +158 -0
  20. package/resources/skill/references/mcp.md +110 -0
  21. package/resources/skill/references/methods.md +143 -0
  22. package/resources/skill/references/modules.md +75 -0
  23. package/resources/skill/references/runtime.md +109 -0
  24. package/resources/skill/references/services.md +32 -0
  25. package/src/apiContractCache.js +120 -0
  26. package/src/cli.js +100 -0
  27. package/src/commandRegistry.js +46 -0
  28. package/src/commands/api.js +244 -0
  29. package/src/commands/apiKey.js +30 -0
  30. package/src/commands/autoPush.js +36 -0
  31. package/src/commands/capabilities.js +100 -0
  32. package/src/commands/check.js +82 -0
  33. package/src/commands/checkout.js +18 -0
  34. package/src/commands/clean.js +72 -0
  35. package/src/commands/commit.js +47 -0
  36. package/src/commands/components.js +554 -0
  37. package/src/commands/conflict.js +30 -0
  38. package/src/commands/conflicts.js +16 -0
  39. package/src/commands/connect.js +91 -0
  40. package/src/commands/delete.js +95 -0
  41. package/src/commands/deploy.js +77 -0
  42. package/src/commands/diff.js +39 -0
  43. package/src/commands/group.js +37 -0
  44. package/src/commands/help.js +190 -0
  45. package/src/commands/init.js +126 -0
  46. package/src/commands/listTargets.js +13 -0
  47. package/src/commands/local.js +79 -0
  48. package/src/commands/map.js +395 -0
  49. package/src/commands/mcp.js +150 -0
  50. package/src/commands/reconcile.js +20 -0
  51. package/src/commands/role.js +31 -0
  52. package/src/commands/status.js +98 -0
  53. package/src/commands/uninstall.js +52 -0
  54. package/src/commands/update.js +79 -0
  55. package/src/commands/verify.js +188 -0
  56. package/src/commands/visualVerify.js +281 -0
  57. package/src/commands/worklog.js +117 -0
  58. package/src/consoleEncoding.js +34 -0
  59. package/src/contractCompatibility.js +65 -0
  60. package/src/detect.js +25 -0
  61. package/src/diffReport.js +106 -0
  62. package/src/fsx.js +67 -0
  63. package/src/index.js +46 -0
  64. package/src/localRuntime/compose.js +119 -0
  65. package/src/localRuntime/detect.js +77 -0
  66. package/src/localRuntime/index.js +211 -0
  67. package/src/localRuntime/mysqlClient.js +155 -0
  68. package/src/localRuntime/services.js +117 -0
  69. package/src/logger.js +37 -0
  70. package/src/mcp/client.js +558 -0
  71. package/src/mcp/hosts.js +520 -0
  72. package/src/mcp/parallel.js +54 -0
  73. package/src/mcp/protocol.js +223 -0
  74. package/src/mcp/stdio.js +300 -0
  75. package/src/mcp/tools.js +51 -0
  76. package/src/paths.js +32 -0
  77. package/src/platforms.js +110 -0
  78. package/src/projectConfig.js +139 -0
  79. package/src/projectDesign.js +19 -0
  80. package/src/projectHealth.js +33 -0
  81. package/src/projectMap.js +220 -0
  82. package/src/prompt.js +94 -0
  83. package/src/releaseInstall.js +105 -0
  84. package/src/runtimeFiles.js +45 -0
  85. package/src/skill.js +295 -0
  86. package/src/targets.js +43 -0
  87. package/src/timeout.js +18 -0
  88. package/src/updateCheck.js +100 -0
  89. package/src/worklog.js +276 -0
  90. package/src/worktree/backend.js +438 -0
  91. package/src/worktree/errors.js +28 -0
  92. package/src/worktree/index.js +751 -0
  93. package/src/worktree/inlineScripts.js +99 -0
  94. package/src/worktree/locks.js +52 -0
  95. package/src/worktree/manifest.js +89 -0
  96. package/src/worktree/status.js +124 -0
  97. package/src/worktree/streams.js +200 -0
  98. package/src/worktree/types.js +103 -0
  99. package/src/worktree/validate.js +37 -0
@@ -0,0 +1,97 @@
1
+ ---
2
+ read_when: 页面开发时需要查 App API · 忘记某个方法签名时
3
+ ---
4
+
5
+ # App 对象速查表
6
+
7
+ ```javascript
8
+ const App = window.parent?.App;
9
+ ```
10
+
11
+ ## 请求
12
+
13
+ | 方法 | 签名 | 说明 |
14
+ |---|---|---|
15
+ | `App.get` | `(path, params?, headers?)` | GET,params 为 query 参数 |
16
+ | `App.post` | `(path, body?, headers?)` | POST |
17
+ | `App.put` | `(path, body?, headers?)` | PUT |
18
+ | `App.patch` | `(path, body?, headers?)` | PATCH |
19
+ | `App.delete` | `(path, params?, headers?)` | DELETE |
20
+ | `App.uploadFile` | `(file, onProgress?)` | 文件上传,返回标准信封 |
21
+
22
+ **响应格式**:`{ code: 200, data: <载荷>, message: "success" }`
23
+ **消费范式**:
24
+ ```javascript
25
+ const res = await App.get('pages', { page: 1, page_size: 20 }); // 按返回的分页信息继续读取
26
+ if (res.code !== 200) { App.showError(res.message); return; }
27
+ const items = res.data.items;
28
+
29
+ const paged = await App.get('pages', { page: 1, page_size: 20 }); // 显式分页
30
+ ```
31
+
32
+ ## 反馈
33
+
34
+ | 方法 | 签名 | 说明 |
35
+ |---|---|---|
36
+ | `App.showSuccess` | `(msg)` | 成功 Toast |
37
+ | `App.showError` | `(msg)` | 错误 Toast |
38
+ | `App.showWarning` | `(msg)` | 警告 Toast |
39
+ | `App.showInfo` | `(msg)` | 信息 Toast |
40
+ | `App.toast` | `(msg, type?)` | 通用 Toast,type: success/error/warning/info |
41
+ | `App.confirm` | `(msg, title?)` | 确认弹窗,返回 `Promise<boolean>` |
42
+ | `App.showModal` | `(msg, title?)` | 信息模态框(替代 alert) |
43
+ | `App.showLoading` | `()` | 全局 loading 蒙层 |
44
+ | `App.hideLoading` | `()` | 关闭 loading |
45
+
46
+ ## 路由
47
+
48
+ | 方法 | 说明 |
49
+ |---|---|
50
+ | `App.navigate(route)` | 路由跳转(pushState) |
51
+ | `App.getCurrentRoute()` | 当前路径字符串 |
52
+ | `App.getCurrentRouteContext()` | 完整路由上下文,含 `query` |
53
+
54
+ **读取 URL 参数**(必须用此方式,不能用 `window.location.search`):
55
+ ```javascript
56
+ const routeContext =
57
+ window.__DG_ROUTE_CONTEXT__
58
+ || window.__DG_GET_ROUTE_CONTEXT__?.()
59
+ || window.parent?.App?.getCurrentRouteContext?.()
60
+ || { query: {} };
61
+ const { patientId, visitId } = routeContext.query;
62
+ ```
63
+
64
+ ## 状态
65
+
66
+ | 属性 | 类型 | 说明 |
67
+ |---|---|---|
68
+ | `App.currentUser` | object \| null | 当前用户,未登录为 null |
69
+ | `App.isAdmin` | boolean | 是否管理员 |
70
+ | `App.permissions` | string[] | 当前用户有效权限的展示投影;仅用于页面显隐,不替代服务端授权 |
71
+ | `App.isAuthenticated` | boolean | 是否已认证 |
72
+ | `App.hasToken` | boolean | 是否有 token(含未验证) |
73
+ | `App.config` | object | 系统配置 KV |
74
+ | `App.theme` | `'light'` \| `'dark'` | 当前显示模式 |
75
+ | `App.colorScheme` | string | 当前配色方案 |
76
+
77
+ ## 主题
78
+
79
+ ```javascript
80
+ App.applyTheme('dark'); // 切换显示模式
81
+ App.setColorScheme('deep-blue-white'); // 切换预设配色
82
+ App.setColorScheme('custom', customVarsObject); // 自定义配色
83
+ App.getColorScheme(); // 获取方案详情
84
+ ```
85
+
86
+ ## 其他
87
+
88
+ ```javascript
89
+ await App.logout(); // 服务端登出、清理状态并跳转配置的登录页
90
+ App.setAuthTokens({ access_token, refresh_token }); // 登录后写入 token
91
+ App.reloadGlobalLayer(); // 重载全局层
92
+ App.openGlobalWidget(name); // 触发全局挂件打开
93
+ App.t(key, fallback?, values?); // 页面级国际化文本,values 保留 ICU 占位符
94
+ App.formatDateTime(value, options?); // 按 system_timezone 格式化 API 返回的 UTC 时间
95
+ ```
96
+
97
+ Token、刷新、路由上下文和认证事件见 `references/runtime.md`。AI 对话组件契约见 `references/chat-sdk.md`,其他 AI 能力见 `references/ai.md`。Chat 与其他 DraftGo 组件使用同一组件库交付,不存在独立 SDK 静态文件。
@@ -0,0 +1,13 @@
1
+ ---
2
+ read_when: 进入陌生项目或选择实现层时
3
+ ---
4
+
5
+ # 架构与实现边界
6
+
7
+ Go 后端承载业务模块和协议入口;React/Vite 前端负责浏览器壳层与 Page 运行时。业务页面是底座管理的完整 HTML,导航也是 HTML 资源,通过 CLI 定位、checkout、编辑和 commit。
8
+
9
+ 页面运行于 iframe.srcdoc,通过 window.parent.App 使用认证请求、路由、主题和反馈;签名见 `app-api.md`,生命周期见 `runtime.md`。访问与数据权限由后端执行,壳层显隐仅辅助交互。
10
+
11
+ 按需求选择现有模块、动态数据和组件;确需额外业务逻辑时读 `services.md`。组件目录来自当前实例,优先复用实际 props/slots。不同项目的数据隔离必须由实际部署与授权设计保证,不能从页面结构推断多租户隔离。
12
+
13
+ 用户产品目标从 Design/README.md 按模块读取;实际能力通过 Registry 查询,设计存在不代表已实现。模块入口见 `modules.md`,跨领域最短操作链见 `methods.md`。
@@ -0,0 +1,205 @@
1
+ ---
2
+ read_when: DraftGo Page 需要 AI 对话组件时 · 开发或扩展 draftgo/chat 时
3
+ ---
4
+
5
+ # DraftGo Chat 组件
6
+
7
+ DraftGo Page 统一使用组件目录中的 `draftgo/chat`。完整实现保存在组件 `Definition.JS`,负责原生 `<dg-chat>`、消息状态机、流解析、停止、重试和历史逻辑,并与 HTML、CSS、Props 和事件使用同一草稿与发布版本。Page 不复制实现,也不手写流式请求。
8
+
9
+ ## 目录
10
+
11
+ - [最小接入](#最小接入)
12
+ - [协议](#协议)
13
+ - [配置与布局](#配置与布局)
14
+ - [JavaScript API 与事件](#javascript-api-与事件)
15
+ - [历史与会话](#历史与会话)
16
+ - [扩展](#扩展)
17
+ - [鉴权与安全](#鉴权与安全)
18
+
19
+ ## DraftGo Page 最小接入
20
+
21
+ 先从当前实例读取组件契约,不按本文猜测 Props:
22
+
23
+ ```text
24
+ draftgo components show draftgo/chat --output json
25
+ ```
26
+
27
+ 在 Page 中保存组件活引用;运行时仅在实际引用时返回完整组件,同页相同 revision 与 hash 只编译一次:
28
+
29
+ ```html
30
+ <dg-chat
31
+ data-dg-use="draftgo/chat"
32
+ data-dg-instance="page-assistant"
33
+ data-dg-prop-agent-id="AGENT_ID"
34
+ data-dg-prop-view="conversation"
35
+ data-dg-prop-surface="inline"
36
+ data-dg-prop-enable-attachments="true">
37
+ </dg-chat>
38
+ ```
39
+
40
+ `draftgo-agent` 默认请求 `/api/agents/{id}/chat`,并复用同源 DraftGo App 的 Bearer token 与刷新机制。
41
+
42
+ `draftgo/chat` 公开 Agent、视图、surface、主题、语言、附件、历史、流式开关、打开状态和超时等稳定 Props,并透传已声明的 `dg-chat:*` 事件。函数、DOM Node、自定义 transport、renderer 和 plugin 不进入 `data-dg-prop-*`。
43
+
44
+ DraftGo 不维护独立 Chat SDK 静态文件或外部应用直连交付路径。无 UI 的文本、图片或其他模型能力调用统一使用服务端 AI Registry operation;这样可保持 Provider 密钥、路由和用量控制在服务端。
45
+
46
+ ## 协议
47
+
48
+ | `protocol` | 必需配置 | 说明 |
49
+ |---|---|---|
50
+ | `draftgo-agent` | `agentId` | DraftGo Agent;默认端点 `/api/agents/{id}/chat` |
51
+ | `openai-chat`(alias `openai`) | `endpoint` | OpenAI Chat Completions 兼容协议 |
52
+ | `openai-responses` | `endpoint` | OpenAI Responses 协议 |
53
+ | `anthropic-messages`(alias `anthropic`) | `endpoint` | Anthropic Messages 协议 |
54
+ | `custom` 或注册名 | 已注册 transport | 页面提供 async generator transport |
55
+
56
+ 外部协议必须指向服务端代理:
57
+
58
+ ```html
59
+ <dg-chat protocol="openai-chat" endpoint="/api/ai-proxy/openai" model="MODEL"></dg-chat>
60
+ <dg-chat protocol="openai-responses" endpoint="/api/ai-proxy/responses" model="MODEL"></dg-chat>
61
+ <dg-chat protocol="anthropic-messages" endpoint="/api/ai-proxy/anthropic" model="MODEL"></dg-chat>
62
+ ```
63
+
64
+ 这些 `/api/ai-proxy/*` 是接入方实现的占位路由,不是 DraftGo 自动提供的默认代理。不要将供应商密钥或长期 token 写入页面。
65
+
66
+ 内置 transport 支持 SSE、NDJSON 和普通 JSON,并把上游响应归一化为 `text.delta`、`reasoning.delta`、`tool.start`、`tool.delta`、`tool.finish`、`step.finish`、`artifact.complete`、`source`、`usage`、`message.finish`、`error` 等事件。DraftGo Page 只使用实时 `draftgo/chat` 组件契约,不要猜测字段或把函数、DOM、renderer、plugin、transport 写入 Props。
67
+
68
+ ## 组件配置与布局
69
+
70
+ 以下直接属性与 JSON 配置用于组件库高级扩展;普通 DraftGo Page 以实时 `draftgo/chat` Props 为准。
71
+
72
+ ```html
73
+ <dg-chat
74
+ id="page-assistant"
75
+ protocol="draftgo-agent"
76
+ agent-id="AGENT_ID"
77
+ surface="drawer"
78
+ view="threads"
79
+ position="right"
80
+ title="AI Assistant"
81
+ placeholder="输入内容"
82
+ persist="true"
83
+ stream="true"
84
+ enable-attachments
85
+ show-reasoning
86
+ ></dg-chat>
87
+ ```
88
+
89
+ | 配置 | 可选值 |
90
+ |---|---|
91
+ | `surface` | `inline`、`floating`、`drawer`、`fullscreen` |
92
+ | `view` | `conversation`、`threads`、`compact`、`canvas` |
93
+ | `position` | `left`、`right` |
94
+ | `theme` | `light`、`dark`;省略时跟随系统 |
95
+
96
+ 复杂的纯数据配置使用 `config-ref`:
97
+
98
+ ```html
99
+ <script type="application/json" id="page-chat-config">
100
+ {
101
+ "protocol": "draftgo-agent",
102
+ "agentId": "AGENT_ID",
103
+ "surface": "inline",
104
+ "view": "canvas",
105
+ "storageKey": "dg-chat:PAGE_KEY:INSTANCE_KEY",
106
+ "features": {
107
+ "reasoning": true,
108
+ "attachments": true,
109
+ "history": true,
110
+ "feedback": false,
111
+ "artifacts": true
112
+ },
113
+ "suggestions": ["总结当前页面", "生成结构化结果"],
114
+ "context": { "page": "PAGE_KEY" }
115
+ }
116
+ </script>
117
+ <dg-chat config-ref="page-chat-config"></dg-chat>
118
+ ```
119
+
120
+ 函数、DOM Node、renderer、plugin、upload 和 custom transport 只能通过 JavaScript 配置,不能写进 JSON。主题优先使用 `--dg-chat-*` CSS variables、公开 `::part()` 和 slots,不选择 Shadow DOM 内部 class。
121
+
122
+ ## JavaScript API 与事件
123
+
124
+ ```javascript
125
+ const chat = document.querySelector('#page-assistant');
126
+
127
+ chat.configure({ model: 'MODEL', context: { page: 'PAGE_KEY' } });
128
+ await chat.send('处理当前输入');
129
+ chat.stop();
130
+ chat.regenerate();
131
+ chat.newThread();
132
+ chat.selectThread('THREAD_ID');
133
+ chat.deleteThread('THREAD_ID');
134
+ chat.renameThread('THREAD_ID', '新的会话名称');
135
+ chat.clearThreads();
136
+ chat.setMessages([]);
137
+ chat.clear();
138
+ chat.open();
139
+ chat.close();
140
+ chat.toggle();
141
+ ```
142
+
143
+ 组件内部运行时保留 `DraftGoChat.create()`、`registerTransport()`、`registerRenderer()`、`registerComponent()`、`definePreset()`、`use()` 等扩展接口,但它们不是独立静态 SDK 契约。
144
+
145
+ 常用事件:`dg-chat:ready`、`dg-chat:before-send`、`dg-chat:message`、`dg-chat:run-start`、`dg-chat:stream-event`、`dg-chat:run-finish`、`dg-chat:run-abort`、`dg-chat:error`、`dg-chat:message-action`、`dg-chat:session-change`、`dg-chat:model-change`、`dg-chat:open`、`dg-chat:close`。
146
+
147
+ ```javascript
148
+ chat.addEventListener('dg-chat:run-finish', event => {
149
+ console.log(event.detail);
150
+ });
151
+ ```
152
+
153
+ 页面销毁或离开路由时调用 `stop()`,取消上传、plugin 和在途 transport。
154
+
155
+ `requestTimeoutMs` 和 `streamTimeoutMs` 分别控制客户端非流式/流式总时限,默认 120000/610000 毫秒,`0` 表示禁用。两者只处理客户端半开连接,不替代 Agent 的服务端超时。
156
+
157
+ ## 历史与会话
158
+
159
+ - `persist` 默认开启,将 UI thread 历史写入 `localStorage`;敏感或临时页面设为 `false`。
160
+ - 同一路由存在多个实例时,每个实例设置唯一 `storageKey`。
161
+ - 每个 UI thread 自动维护独立 `sessionId`;`draftgo-agent` 将其作为 `session_id` 发送。
162
+ - 切换会话只改变当前视图,不会停止其它 thread 的在途请求。会话列表标题左侧显示运行中状态;后台完成或失败后显示未读状态,进入该会话即视为已读并清除。
163
+ - 每个请求使用独立 `run_id`。用户停止或 SDK 超时会调用 Agent 取消接口;普通会话切换不会发送取消。
164
+ - 推理片段和工具调用按服务端事件的输出位置保留在消息内,不固定贴在消息底部;思考在正文、工具或结束事件到达后进入完成态,不再闪烁或滚动预览。
165
+ - `newThread()` 创建新的后端会话边界;不要让不同用户共享固定 `storageKey` 或 `sessionId`。
166
+ - `clear()` 和 `setMessages([])` 会重置当前 session,避免视觉清空后恢复旧 checkpoint。
167
+
168
+ ## 扩展
169
+
170
+ 自定义协议通过 async generator 产生统一事件:
171
+
172
+ ```javascript
173
+ DraftGoChat.registerTransport('page-protocol', async function* (request, context) {
174
+ const response = await fetch('/api/x/page/chat', {
175
+ method: 'POST',
176
+ signal: context.signal,
177
+ headers: { 'Content-Type': 'application/json' },
178
+ body: JSON.stringify({ messages: request.messages })
179
+ });
180
+ const data = await response.json();
181
+ yield { type: 'text.delta', delta: String(data.text || '') };
182
+ yield { type: 'message.finish' };
183
+ });
184
+
185
+ chat.configure({ protocol: 'page-protocol' });
186
+ ```
187
+
188
+ 局部定制优先级:属性/JSON → CSS variables、parts、slots → 实例 `components`/`renderers` → plugin/custom transport。全局注册会影响同一 window 的所有实例;页面特有行为优先放在实例配置中。
189
+
190
+ ## 鉴权与安全
191
+
192
+ - 同源请求优先使用 iframe 可见的 `window.App.fetchAbsolute`,复用 DraftGo token 和刷新机制。
193
+ - 供应商凭证不得自动或手工发送到外部 origin;OpenAI/Anthropic 使用服务端代理。
194
+ - 页面 HTML、JSON config、`headers`、`context` 和 `localStorage` 中不得保存长期供应商密钥。
195
+ - 不把模型输出直接赋给 `innerHTML`;使用 SDK 内置 Markdown/URL 安全渲染或显式净化。
196
+ - 后端始终负责 Agent 调用权限、模型白名单、附件能力和大小限制,前端开关不能越权。
197
+ - Agent 协议响应不应包含 Agent 内部模型名。模型选择器只能读取 Agent 明确授权的 `/selectable-models` 目录。
198
+
199
+ 交付前确认:DraftGo Page 使用 `draftgo/chat` 且不手工加载第二套脚本;同页多实例隔离 `storageKey`;外部协议走服务端代理;页面离开时停止在途请求。
200
+
201
+ ## 移动端契约
202
+
203
+ - `inline`、`floating`、`drawer`、`fullscreen` 四种 surface 均由 SDK 自适应窄屏;`threads`、`canvas` 和 Artifact 会按容器宽度自动收敛为单栏,不要复制 Shadow DOM 内部布局规则。
204
+ - SDK 使用 `VisualViewport` 和 `safe-area-inset-*` 跟随软键盘、浏览器工具栏与横竖屏变化。触摸设备打开面板时不会主动弹出软键盘。
205
+ - 触摸端按钮和行操作具有移动端点击尺寸,输入字号防止 iOS 自动缩放;所有内部滚动区隐藏滚动条,但仍保留触摸、滚轮和键盘滚动能力。
@@ -0,0 +1,140 @@
1
+ ---
2
+ read_when: 编辑 pages、navigation 或 docs 正文时 · 查看 checkout manifest 时 · 处理 409/412 冲突时
3
+ ---
4
+
5
+ # Checkout / Commit
6
+
7
+ ## 页面与内容最短流程
8
+
9
+ ```bash
10
+ draftgo map --type pages --route /admin/channel-ops --output json
11
+ draftgo checkout pages 42
12
+ draftgo diff pages 42 --stat
13
+ draftgo verify pages 42
14
+ draftgo commit pages 42
15
+ ```
16
+
17
+ 导航和文档分别替换为 `nav`、`docs`。route/title 为精确匹配,两个条件取交集;只需确认范围或 checkout 状态时使用 `map --summary`,必须浏览时使用 `--limit <1-100>`(默认 20),并仅在单一 `--type` 下用 `--cursor <opaque>` 翻页。新资源先用 `draftgo api search "create page"` 或对应内容类型定位创建 operation,describe/call 取得 ID 后再 checkout;不要用 checkout 创建资源。`verify` 通过不等于已交付,commit 返回新版本与哈希才算正文写入成功。发生 409/412 时保留冲突材料并停止提交。
18
+
19
+ ## Workflow 2.0 coverage
20
+
21
+ The checkout set includes `pages`, `navigations`, and `docs/articles`. DB Meta and all other structured resources remain live MCP/API resources and are never checked out.
22
+
23
+ `draftgo refresh <type> <id...>` is a safe checkout shortcut. It updates only a clean local worktree; local changes stop it. A successful commit keeps current local files and one base only. Cloud version storage is the sole history source.
24
+
25
+ > 根 `SKILL.md` 在 Skill 触发时会自动加载。使用本文件前,先完成根 Skill 的“强制预读:Reference 优先于 MCP”任务路由。本文件只说明长正文的传输、版本和冲突规则,不能替代页面、前端、运行时或安全资料。
26
+
27
+ ## 适用范围
28
+
29
+ 只有长正文使用 worktree:
30
+
31
+ | 输入类型 | 规范类型 | 本地目录 | 文件前缀 |
32
+ |---|---|---|---|
33
+ | `page` / `pages` | `pages` | `.draftgo/worktree/pages/` | `page_` |
34
+ | `nav` / `navigation` / `navigations` | `navigations` | `.draftgo/worktree/navigations/` | `nav_` |
35
+ | `doc` / `docs` / `article(s)` / `docs/articles` | `docs` | `.draftgo/worktree/docs/` | `article_` |
36
+
37
+ db_meta、AI 配置、system_config、roles、users、doc_categories 和普通配置使用 MCP 实时 API,不 checkout。
38
+
39
+ Checkout 只为已存在且已确认 ID 的资源建立本地正文与 base,不创建页面、导航或文档。新增资源先按 MCP 实时 API 契约创建并取得 ID;需要编辑完整正文时再 checkout。只需元数据或正文片段即可完成判断时,不必 checkout。
40
+
41
+ ## 命令
42
+
43
+ ```bash
44
+ draftgo checkout <pages|nav|docs> <id...>
45
+ draftgo commit <pages|nav|docs> <id...>
46
+ draftgo reconcile <pages|nav|docs> <id...>
47
+ draftgo diff <pages|nav|docs> <id> [--stat|--summary]
48
+ draftgo conflicts
49
+ draftgo conflict show <pages|nav|docs> <id>
50
+ draftgo conflict resolve <pages|nav|docs> <id>
51
+ ```
52
+
53
+ `checkout --force` 只用于用户明确允许丢弃未提交本地修改的情况。默认 checkout 检测到 worktree 文件相对
54
+ base 已变化时必须拒绝覆盖。
55
+
56
+ `diff --stat` 只显示文件与增删行数;`diff --summary` 显示资源、基线版本和变化概要。两者均不输出正文 diff,先用它们确认范围,再按需展开完整 `diff`。`--output json` 时 stdout 只包含 UTF-8 JSON,诊断走 stderr。
57
+
58
+ ## Checkout 流程
59
+
60
+ 1. CLI 通过 MCP `draftgo_resource_get_metadata` 取得规范类型、content_type、SHA-256、大小、版本/revision、
61
+ ETag 和受信任的下载/提交 URL。
62
+ 2. CLI 使用 `.draftgo/config.json` 中的用户 API Key 通过专用 HTTP 下载完整正文;API Key 不进入 MCP 参数或日志。
63
+ 3. 响应体直接流式写入同目录临时文件,校验 content_type、字节数和 SHA-256。
64
+ 4. 校验成功后原子重命名到 worktree 文件,并保存相同字节的 `.base` 文件。
65
+ 5. 最后原子更新 `.draftgo/worktree/manifest.json`。失败时不得留下半截正式文件或推进 manifest。
66
+
67
+ 正文不做 HTML/Markdown 转换,也不改变编码。扩展名规则:
68
+
69
+ - `text/html`、`application/xhtml+xml` -> `.html`
70
+ - `text/markdown`、`text/x-markdown` -> `.md`
71
+ - `text/plain` -> `.txt`
72
+ - 其他类型只接受底座返回的安全扩展名;缺失或不安全时拒绝 checkout
73
+
74
+ ## Manifest
75
+
76
+ 路径固定为 `.draftgo/worktree/manifest.json`,schema version 当前为 `1`。条目键使用规范类型和 id:
77
+
78
+ ```json
79
+ {
80
+ "schema_version": 1,
81
+ "updated_at": "2026-07-30T12:00:00.000Z",
82
+ "entries": {
83
+ "pages:42": {
84
+ "server": "https://draftgo.example",
85
+ "resource_type": "pages",
86
+ "resource_id": "42",
87
+ "title": "Example",
88
+ "route": "/example",
89
+ "code": null,
90
+ "slug": null,
91
+ "local_path": ".draftgo/worktree/pages/page_42.html",
92
+ "content_type": "text/html",
93
+ "file_extension": ".html",
94
+ "content_size": 123,
95
+ "base_path": ".draftgo/worktree/.base/pages/page_42.html",
96
+ "base_version": "7",
97
+ "base_revision": null,
98
+ "base_etag": null,
99
+ "base_hash": "<sha256>",
100
+ "checked_out_at": "2026-07-30T12:00:00.000Z"
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ `server` 必须和当前连接一致。`local_path`、`base_path` 必须是项目内相对路径。manifest、worktree `.base`
107
+ 和冲突目录必须 gitignore;不要手工伪造版本或哈希。
108
+
109
+ ## Commit 流程
110
+
111
+ 1. 读取 manifest 指向的 worktree 文件,计算当前字节数和 SHA-256;未变化时返回 `unchanged`。
112
+ 2. 按 content_type 执行本地结构和内联脚本检查。
113
+ 3. 通过专用 HTTP 流式上传原始文件,携带 `If-Match`、base version/revision、content_type、长度和 SHA-256。
114
+ 4. 完整正文不得作为 MCP tool 参数发送。
115
+ 5. 底座确认 hash 和新版本后,CLI 原子更新 `.base` 与 manifest。返回 hash 不一致时不得推进基线。
116
+
117
+ 本地正文已经等于远端、但 base/manifest 落后时,先用 `draftgo check --remote` 确认 `committed_unrecorded`,再运行 `draftgo reconcile`;不要手改 manifest。
118
+
119
+ 单个 commit 成功不自动完成 worklog 项。只有整个事项统一验证且全部 commit/MCP 交付成功后,主 Agent 才执行 `draftgo work complete <编号> --note "<完成结果>"`。任何检查失败、409/412 或交付失败都不得标记为完成。
120
+
121
+ ## 409 / 412 冲突
122
+
123
+ 版本冲突时 CLI 返回非零,不自动重试、不 force、不覆盖 worktree local,并写入:
124
+
125
+ ```text
126
+ .draftgo/conflicts/<pages|navigations|docs>/<id>/
127
+ ├── conflict.json
128
+ ├── base.<ext>
129
+ ├── local.<ext>
130
+ └── remote.<ext>
131
+ ```
132
+
133
+ - `base` 是 checkout 时的内容;`local` 是发生冲突时的本地快照;`remote` 是重新下载并校验的当前远端内容。
134
+ - `conflict.json` 记录三份路径、版本、ETag 和哈希,不嵌入完整正文。
135
+ - Agent 或用户在 worktree local 文件中完成合并;不要手写 HTML 自动合并器,也不要改动保存的三份证据。
136
+ - 合并完成后运行 `draftgo verify`,再执行 `draftgo conflict resolve <type> <id>`。
137
+ - resolve 校验 worktree 与 remote,采用 remote 版本作为新的 base,但保留合并后的 worktree;随后运行
138
+ `draftgo diff` 并 `draftgo commit`。
139
+
140
+ 存在 unresolved conflict 时 commit、deploy 或 auto-commit 必须停止。
@@ -0,0 +1,49 @@
1
+ ---
2
+ read_when: 动态数据建模、权限、筛选或记录读写
3
+ ---
4
+
5
+ # 动态数据
6
+
7
+ 元数据定义类型、字段和访问规则,记录保存业务数据。两者使用结构化 API,不 checkout。先用 `draftgo api search "db meta"` 或记录相关关键词搜索能力,再 `draftgo api describe <operation_id>` 和 `draftgo api call <operation_id> --input request.json`;通用调用与缓存规则见 `mcp.md`。
8
+
9
+ ## 建模与权限
10
+
11
+ - 先确定字段、关系和访问规则,再绑定页面。元数据按 type 读取,修改和删除使用元数据 ID;创建后 type 不可修改。
12
+ - 字段通过 schema.properties 定义,按需求选择 type、required、default、searchable;不复制整份静态 schema 替代实时契约。
13
+ - 当前权限使用 public、authenticated、roles 配置 CRUD 级别,角色项引用实际 role_id。公开仅允许读取,且必须明确 public_fields;writable_fields 约束可写字段。授权由服务端执行,页面显隐不替代授权。
14
+ - 保存前读取元数据 version,更新和删除携带 expected_version。记录所有者在 API 中为 owner_user_id,不凭客户端提供的 ID 授权。
15
+ - 保存后回读规范化的类型和权限。契约与响应不一致时报告具体差异,不混用旧权限模型。
16
+
17
+ ## 记录与并发
18
+
19
+ 页面使用 window.parent.App,管理任务使用 CLI 实时 operation。以下是页面操作模式,类型、字段和记录来自当前任务;每个示例是独立操作,更新或删除前读取目标记录:
20
+
21
+ ```javascript
22
+ const result = await App.get('db/order', {
23
+ page: 1, page_size: 20,
24
+ filters: ['amount:gte:100'], order_by: 'created_at', order: 'desc',
25
+ });
26
+ const { items, total } = result.data;
27
+ await App.post('db/order', { data: { amount: 200 } });
28
+ await App.put(`db/order/${record.id}`, {
29
+ version: record.version, data: { ...record.data, amount: 250 },
30
+ });
31
+ await App.delete(`db/order/${record.id}`, { version: record.version });
32
+ await App.patch('db/order/batch', records.map(item => ({
33
+ id: item.id, version: item.version, data: { ...item.data, paid: true },
34
+ })));
35
+ ```
36
+
37
+ 修改后使用响应或回读的新 version,不复用旧版本。409 时保留修改意图、重新读取并处理冲突,不盲目重放。批量最多 100 条,任一失败整批回滚。测试写入使用授权的隔离数据。
38
+
39
+ ## 筛选与关系
40
+
41
+ - 数据列表默认分页,page_size 上限 100;按 total 继续读取,不假定省略分页返回全部。
42
+ - filters 必须使用 field:operator:value,多个条件为 AND,不能省略操作符。
43
+ - searchable 使用 false、exact、fuzzy、range 或 contains;按模式选择 eq/in、like、gt/gte/lt/lte 或 contains,支持范围以实例校验为准。
44
+ - 业务 status 与记录顶层 status 分开理解。日期、检索和排序字段按当前类型及契约确认。
45
+ - 关系设计按需读 `db-relations.md`。默认删除策略 restrict,级联由服务端在事务与权限约束中完成。
46
+
47
+ ## 验收
48
+
49
+ 类型、字段和权限回读正确;目标角色读写与拒绝场景符合需求;筛选、分页可用。涉及并发和批量时验证版本冲突及原子性。400 检查容器、版本、筛选和 schema,403 检查角色和所有者,409 检查版本。其他模块参数以各自 describe 为准。
@@ -0,0 +1,29 @@
1
+ ---
2
+ read_when: 配置动态数据关联、populate 或关联删除
3
+ ---
4
+
5
+ # 数据关联
6
+
7
+ 先读取相关类型和引用字段,明确哪一侧保存 ID。关系定义保存到元数据,使用当前 expected_version。
8
+
9
+ | 关系 | 定义位置与用途 |
10
+ |---|---|
11
+ | many-to-one | 持有目标 ID 的字段,ref.type 指向目标类型 |
12
+ | many-to-many | 持有目标 ID 数组的 array 字段 |
13
+ | one-to-many | 虚拟反向字段,ref.inverse_field 指向对方真实引用字段;仅用于 populate,不能作为记录数据写入 |
14
+
15
+ ref 使用 type、relation、onDelete,反向关系另需 inverse_field。具体字段类型和写入容器按实时契约确定。
16
+
17
+ | onDelete | 行为 |
18
+ |---|---|
19
+ | restrict | 默认策略,有引用时拒绝删除 |
20
+ | cascade | 删除引用目标的记录 |
21
+ | set_null | 将引用字段置空 |
22
+ | set_default | 使用字段自身的 default,必须定义该默认值 |
23
+ | detach | 从多对多数组中移除目标 ID |
24
+
25
+ 策略放在实际持有引用的字段上。旧 no_action 规范化为 restrict,不代表忽略引用检查。级联继承调用者权限并在事务中执行,不在前端连续 DELETE 模拟。
26
+
27
+ 页面通过 App.get 的 populate 参数请求必要关系。只展开当前页面需要的字段;展开数量、深度和返回结构以实例为准,不默认递归抓取全部关系。
28
+
29
+ 验收:关联按目标权限读取;反向字段只读;删除符合所选策略;缺权限或版本冲突时保持一致状态并显示服务端结果。
@@ -0,0 +1,33 @@
1
+ ---
2
+ read_when: 准备验证、提交、发布、交付或标记工作项完成时
3
+ ---
4
+
5
+ # 交付验收
6
+
7
+ 先按资源类型选择唯一交付链,不把“本地验证通过”写成“已发布”。
8
+
9
+ ## 长正文
10
+
11
+ ```bash
12
+ draftgo diff pages 42 --stat
13
+ draftgo verify pages 42
14
+ draftgo commit pages 42
15
+ draftgo check --remote --output json
16
+ ```
17
+
18
+ `nav`、`docs` 同理。先用 `--stat` 或 `--summary` 确认变更范围,只有需要审查正文时才展开完整 diff。`commit` 返回新版本与哈希后,再用远端检查确认基线一致。409/412、未解决冲突或远端状态不明时停止。
19
+
20
+ ## 结构化资源
21
+
22
+ 结构化资源按最新 describe 调用写 operation,再用 get/list operation 回读。
23
+
24
+ ## 统一收尾
25
+
26
+ ```bash
27
+ draftgo verify
28
+ draftgo work complete <ref> --note "<结果与证据>"
29
+ ```
30
+
31
+ 默认 `verify` 不启动浏览器。用户要求视觉修改或视觉验收时,才增加 `--url <url> --screenshot always`;需要 DOM 或交互验证时再用 `--ui always`。所有 commit、MCP 写入和回读都成功后才能 complete;失败项保持 active,并在 note 外记录可脱敏的 request ID。
32
+
33
+ 完成条件:本地检查通过,目标远端资源可回读,版本/哈希或结构化状态与预期一致,任务要求的运行或视觉证据齐全,且证据不含凭据。
@@ -0,0 +1,41 @@
1
+ # 项目开发与恢复
2
+
3
+ 新系统、需求变化、任务恢复、UI 定位或多 Agent 协作时按需读取对应小节。
4
+
5
+ ## 设计与执行
6
+
7
+ 用户项目根目录 `Design/README.md` 是设计入口;Design 表达当前及未来的目标,worklog 表达实际任务状态。CLI 源码仓库的 Design 描述工具本身,不能复制为用户产品设计或开发阶段。
8
+
9
+ 新系统先根据用户描述形成最小产品概述和模块设计。模块使用编号文件夹,简单模块只需 README;复杂后拆分。记录流程、规则、验收条件,正向描述能力,不编写“不做什么”清单。已明确的未来能力可以保存,但不得扩大当前任务范围。Design 直接维护最新目标,不并列新旧稿。
10
+
11
+ 开始即 `draftgo work start "<事项>" --note "设计路径/需求编号;owner;范围和验收条件"`,保存完整日期引用。信息充分且已授权时继续执行,仅澄清影响产品结果的问题。功能变化同步相关设计;Bug 修复遵循正确设计;小修改不强制生成新文档。设计文件由宿主普通编辑工具维护。
12
+
13
+ 涉及数据时先确定字段、关系、权限和读写契约,再实现页面。正文走 checkout → diff → verify → commit;结构化写入使用实时 operation 并回读。结构化写入可能即时作用于实例,开发优先使用开发实例。验收按设计需求及实际写入结果执行,本地 verify 不证明全部业务已验证或已上线。
14
+
15
+ ## 上下文与恢复
16
+
17
+ 先读 Design 索引,再读相关模块、公共规则和领域 Reference,不加载全量文档或 Registry。具体编辑所需的完整正文和契约必须按需读取。
18
+
19
+ 恢复时使用 `draftgo work list --status active --limit 20 --output json`,必要时查询 waiting;结果有 `next_offset` 时用 `--offset` 继续。支持 `--date YYYY-MM-DD`。单项使用 `draftgo work show YYYY-MM-DD#N --output json`,读取设计引用、备注和目标资源当前状态,再 `work start-item` 恢复。
20
+
21
+ 进度或交接通过 `work start-item <ref> --note "已完成结果;阻塞;下一步;资源 ID"` 追加,等待外部条件使用 work wait。完成时 work complete 的备注包含版本、验证和必要回读证据。不要把完整正文、凭据或全部响应写进日志。complete 是状态更新,不会自动核实证据;Agent 必须先完成验证。
22
+
23
+ ## UI 定位与验收
24
+
25
+ 页面说明包括用途、路由、关键操作和加载/空数据/错误状态。独立 UI 稿只在视觉方向、复杂布局或用户要求时提供,实际产生资料才建立模块 `UI/`;说明目标稿、参考图或定位材料的用途,并保持目标稿与文字一致。
26
+
27
+ 已有页面直接定位实际页面、区域、按钮名称/功能及相对容器。用户描述“右上角那个按钮”时先读页面和组件;多个合理候选时只澄清关键目标。需要视觉辅助时使用实际页面截图标注候选,有 DOM 能力则对应真实元素,不凭坐标猜业务。截图不作为默认整页重建路径。
28
+
29
+ 用户要求视觉修改即包含检查该修改的渲染结果:环境可用时用 verify 的 --url 和 --screenshot always 检查并查看图片,交互验收按需用 --ui always;视口按任务选择。无法验证时报告范围,普通非视觉任务仍默认本地 verify。验收截图通过已登记的 .draftgo/artifacts/ 保存,不堆入 Design。
30
+
31
+ ## 多 Agent 与 Git
32
+
33
+ 宿主支持且任务适合并行时,主 Agent 按文件和实例资源分配唯一 owner,先稳定共享数据和权限契约,再并行独立模块。公共设计、导航、共享组件有明确 owner;只提交本任务目标,避免 auto-push 携带他人未完成资源。子 Agent 返回设计引用、资源、结果、证据和下一步,主 Agent 汇总验收。
34
+
35
+ 本地源码隔离使用原生 Git worktree;DraftGo worktree 是实例正文与基线的编辑区,checkout/commit/auto-push 均不是 Git 分支或提交。diff 依赖本机 Git。文档与源码可纳入 Git,凭据和 DraftGo worktree 保持忽略。
36
+
37
+ CLI 命令锁不能覆盖 Agent 整轮编辑;不同目录的锁也不隔离同一远端资源。owner 约定贯穿任务全过程,同资源串行,冲突按正文工作树规则处理。真正独立实验使用独立开发实例。CLI 请求使用有界并发,不能把多个 Agent 等同于无限连接。
38
+
39
+ ## 旧 Story 迁移
40
+
41
+ 仅旧项目需要:检查 .draftgo/story.yaml,将仍有效的产品定位、模块目标和决策原因迁入 Design;与现有 Design 或最新用户要求冲突的内容先核实,不覆盖有效文档。历史进度留给 worklog,不转成设计流水账。迁移核对前保留原文件,核对后在 worklog 记录迁移结果并停止读取 Story;用户未要求时不删除原产品档案。新项目不创建 Story,不并行维护两套设计来源。