draftgo-cli 3.0.44 → 3.0.48

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.
@@ -1,180 +0,0 @@
1
- ---
2
- read_when: 需要查具体 API 端点时 · 构造请求时
3
- ---
4
-
5
- # 后端 API 速查
6
-
7
- > 实时契约以 MCP `draftgo_api_search` / `draftgo_api_describe` 为准;CLI 中可用 `draftgo api <keyword>` 查询。
8
- > 本页只保留领域速查和 OpenAPI 无法表达的约束,不是静态完整契约。自定义服务的运行时路由由 `app.Route`
9
- > 动态注册,不会出现在底座 OpenAPI 中;按 `<METHOD> /api/x/<slug><route-path>` 推导,保存或发布后必须请求
10
- > 无副作用 GET Route 验证。
11
- > 统一响应信封:`{ code: 200, data: <载荷>, message: "success" }`
12
- > GET 列表端点通常在不传 `page` / `page_size` 时全量返回;自定义服务执行记录是固定分页特例(默认 20,最大 100)。
13
- > Go 自定义服务使用 `draftgo.DB.Query(type, sdk.QueryOptions{...})`;返回 `sdk.QueryResult`,筛选和分页见 `references/custom-services.md`。
14
-
15
- ## 认证
16
-
17
- ```
18
- POST /api/auth/login, /register, /logout, /refresh
19
- POST /api/auth/forgot-password, /reset-password
20
- POST /api/auth/wechat/mp/oauth, /wechat/mini/login
21
- POST /api/auth/wechat/mp/qr/create GET /wechat/mp/qr/poll
22
- ```
23
-
24
- ## 用户 & 角色
25
-
26
- ```
27
- GET/PUT /api/users/me PUT /api/users/me/password
28
- GET/POST /api/users GET/PUT/DELETE /api/users/{id}
29
- POST /api/users/{id}/ban, /unban
30
-
31
- GET/POST /api/roles GET/PUT/DELETE /api/roles/{id}
32
- POST /api/roles/{id}/assign/{uid} DELETE /api/roles/{id}/revoke/{uid}
33
- ```
34
-
35
- ## 页面
36
-
37
- ```
38
- GET/POST /api/pages/
39
- GET/PUT/DELETE /api/pages/{id}
40
- POST /api/pages/{id}/reset-system
41
- GET /api/pages/by-route?route=/xxx
42
- GET /api/pages/{id}/versions
43
- POST /api/pages/{page_id}/versions/{version_id}/restore, /star
44
- ```
45
-
46
- ## 导航栏
47
-
48
- ```
49
- GET/POST /api/navigations
50
- GET /api/navigations/{code}
51
- PUT/DELETE /api/navigations/{id}
52
- ```
53
-
54
- ## 动态 DB
55
-
56
- ```
57
- GET /api/db/{type}
58
- 支持 filters/order_by/order/page/page_size/populate/scope=mine
59
- scope=mine 仅 admin 用户的列表 GET 生效:非后台业务页用,后台管理页不用
60
- 📌 filters 语法 → references/data.md#filters-操作符
61
- 📌 searchable 模式 → references/data.md#searchable-字段标记
62
- 📌 ref/populate/onDelete → references/data.md#关联关系ref
63
- POST /api/db/{type} body: { data: {...} } 或数组
64
- PATCH /api/db/{type}/batch
65
- GET/PUT/DELETE /api/db/{type}/{id}
66
- DELETE 会按真实引用字段的 ref.onDelete 处理级联 / 置空 / 阻止 / 解除关联
67
- ```
68
-
69
- ## DB Meta ⚠️
70
-
71
- ```
72
- GET/POST /api/db-meta
73
- GET /api/db-meta/{type} ← 必须用 type,不是 id!
74
- PUT/DELETE /api/db-meta/{id}
75
- POST /api/db-meta/{type}/reconcile-fields
76
- ```
77
-
78
- ## 自定义服务
79
-
80
- ```
81
- GET/POST /api/scripts
82
- GET /api/scripts/options/roles
83
- GET/PUT/DELETE /api/scripts/{id}
84
- GET /api/scripts/{id}/routes
85
- POST /api/scripts/{id}/enable, /disable, /execute
86
- GET /api/scripts/{id}/versions
87
- POST /api/scripts/{id}/versions/{version_id}/restore
88
- GET /api/scripts/{id}/executions
89
- GET /api/scripts/{id}/executions/{execution_id}
90
- ANY /api/x/{slug}/{path} ← 脚本运行时端点
91
- ```
92
-
93
- 自定义服务要点:
94
-
95
- - 自定义服务是结构化远端资源:通过 MCP 查询元数据和实时接口契约,通过 `draftgo_api_call` 创建或更新;不要依赖本地 `index.json` 镜像。
96
- - 新服务使用 Go `Register(app *sdk.App)`;用 `app.Route` / `app.On` / `app.Schedule` 自动注册。
97
- - 新服务使用 `mode=mixed`,可同时暴露 HTTP、响应事件和执行 cron。
98
- - route 注册来自 `app.Route("METHOD", "/path", handler)`;一个服务可声明多个 route,共用同一个 slug 命名空间。
99
- - event 和 scheduled 分别来自 `app.On(...)` 与 `app.Schedule(...)`;均支持在一个服务内声明多个 handler。
100
- - 旧 `triggers` 字段不参与注册,CLI 不再创建或推送该字段。
101
- - route handler 签名:`func handler(draftgo *sdk.Context) (any, error)`;实际字段位于 `draftgo.Input`,用户身份用 `draftgo.Auth.CurrentUser()`。
102
- - Route 的普通 SDK 调用继承当前调用者资源权限,管理员创建服务不自动提升;需要管理员权限时逐次显式调用 `draftgo.Admin.DB`、`draftgo.Admin.Users` 等。`Admin` 调用以管理员身份执行并自动写入执行审计,但不会向代码暴露 SAT。带 `user_id` / `actor_user_id` 的事件继承该用户,定时任务及无可解析用户的事件才是系统身份。
103
- - 路径换算:`slug=order` + `app.Route("POST", "/pay", handler)` → `POST /api/x/order/pay`。
104
- - route 是精确路径匹配,不支持 `/items/{id}` 参数模板;ID 使用 query/body。
105
- - 动态数据访问使用 `draftgo.DB.Query("order", sdk.QueryOptions{...})`,结果为 `sdk.QueryResult`;筛选与分页见 `references/custom-services.md`。
106
- - `permission` 控制调用权限;`config.route_security` 控制限流、IP、body 大小和超时。
107
- - `scripts:*` 控制服务管理权限,和 Route 的调用权限彼此独立;执行列表固定分页,详情日志按单条加载。
108
- - `config.max_concurrency` / `queue_timeout_ms` 控制服务级退避;Route 饱和返回 429。
109
- - 完整 SDK、`draftgo`、AIHub、事件、配置与运行限制见 `references/custom-services.md`。
110
-
111
- ## AIHub & AI推理
112
-
113
- ```
114
- GET/POST /api/aihub ← AIHub 资源(模型/Agent 定义)CRUD
115
- POST /api/aihub/{id}/sync ← 同步供应商模型目录
116
- GET /api/v1/models
117
- POST /api/v1/chat/completions ← OpenAI 兼容格式(直连模型)
118
- POST /api/v1/embeddings ← 向量嵌入(OpenAI 兼容)
119
- POST /api/v1/images/generations ← 图片生成(OpenAI 兼容)
120
- ```
121
-
122
- Agent 调用面(页面/调用方用 agent id 调用,不是直连模型):
123
- ```
124
- GET /api/agents ← 列出当前用户可调用的 Agent(拿 id/name/describe)
125
- GET /api/agents/{id}/selectable-models ← { user_selectable, models }
126
- POST /api/agents/{id}/chat ← 对话,见下方 body;stream=true 返回 SSE
127
- POST /api/agents/{id}/images ← 图片模式 Agent(body.prompt 必填)
128
- POST /api/agents/{id}/preview-chat ← 只解析不执行:回 { model, fallback_models, candidate_provider_ids, messages },用于调试路由
129
- ```
130
-
131
- `/api/agents/{id}/chat` 请求体:
132
- ```
133
- { messages:[{role,content}] | message:"简写字符串", stream?:bool,
134
- model?:"覆盖模型", session_id?:"多轮会话键", context?:{} }
135
- ```
136
- - `stream:true` → `text/event-stream`,逐帧 `data: {...}`,以 `data: [DONE]` 结束;否则返回 OpenAI 风格完整结果。
137
- - 传 `session_id` 且 Agent 开启持续对话(checkpoint)时,服务端加载并续写该会话历史;不传即无状态单轮。
138
-
139
- AI 运行观测(`/admin/ai-runs` 页数据源):
140
- ```
141
- GET /api/aihub/runs ← 运行列表,支持 status/model/trace_id/agent_id/event_type/time_start/time_end + 分页
142
- GET /api/aihub/runs/{trace_id} ← 单次运行详情(含 spans / tokens / ttft_ms / 延迟)
143
- DELETE /api/aihub/runs ← 按 trace_ids 或时间范围批量清理
144
- ```
145
-
146
- ## 文档中心
147
-
148
- ```
149
- GET/POST /api/docs/categories
150
- GET /api/docs/articles, /api/docs/articles/{key}, /api/docs/search
151
- POST /api/docs/articles PUT/DELETE /api/docs/articles/{id}
152
- ```
153
-
154
- ## 系统 & 备份
155
-
156
- ```
157
- GET /api/system/config
158
- GET/PUT/DELETE /api/system/{key}
159
- GET/POST /api/system/backup
160
- POST /api/system/restore, /api/system/reset
161
- POST /api/system/restore/selective?mode=replace|merge|append
162
- POST /api/upload
163
- GET /api/system/logs
164
- ```
165
-
166
- ## 二次认证(高危操作前必须)
167
-
168
- restore / reset / undo / cleanup-orphans 需要:
169
- ```
170
- POST /api/auth/reauth { password, scope } → 返回 confirm_token
171
- 请求头加:X-Confirm-Token: <token>
172
- ```
173
-
174
- ## 不使用信封的端点
175
-
176
- | 端点 | 格式 |
177
- |---|---|
178
- | `POST /api/v1/chat/completions` | OpenAI SSE / JSON |
179
- | `GET /api/v1/models` | `{ object:"list", data:[...] }` |
180
- | `ANY /api/x/{slug}/{path}` | 脚本自定义 |
@@ -1,308 +0,0 @@
1
- ---
2
- name: draftgo-debugging-syntax
3
- description: 页面代码量大时,语法/逻辑缺陷导致页面静默失效的排查指南。页面功能不执行、无报错或报错误导时,先按此清单逐项检查。
4
- version: 1.0.0
5
- ---
6
-
7
- # DraftGo 页面排错指南
8
-
9
- > **为什么需要这份文档:** DraftGo 页面是完整 HTML 运行在 iframe.srcdoc,业务逻辑、DOM 操作、API 调用全部混在单个文件里。代码量大之后,某些语法/逻辑缺陷不会触发控制台报错,也不会弹出异常,但功能就静默失效了。这份清单帮 AI 快速定位这类"查不到报错"的致命缺陷。
10
-
11
- ---
12
-
13
- ## 核心排错原则
14
-
15
- **页面功能不执行时,按这个顺序排查,不要漫无目的地读代码:**
16
-
17
- 1. 先看浏览器控制台有没有红色报错,有就按报错定位
18
- 2. 没有报错 → 用本文档逐项检查(最常见的就是下面列出的几类)
19
- 3. 在关键位置加 `console.log('=== A 点到达 ===')` 二分定位死在哪一步
20
- 4. 仍找不到 → 用二分法注释掉一半代码,缩小范围
21
-
22
- ---
23
-
24
- ## 致命缺陷速查清单(按出现频率排序)
25
-
26
- 以下每一项都可能导致页面**完全静默失效**——无报错、无异常、功能就是不动。
27
-
28
- ### 1. 模板字符串未闭合(最常见!)
29
-
30
- 在 iframe.srcdoc 环境中,`</script>` 出现在模板字符串里会**提前关闭 script 标签**,导致后续所有 JS 代码被当 HTML 解析。这种问题**没有任何报错**。
31
-
32
- ```javascript
33
- // ❌ 致命:模板字符串中的 </script> 终止了外层 <script> 标签
34
- const html = `
35
- <script>
36
- console.log('inner');
37
- </script> // ← 这里!浏览器解析器看到 </script> 就关闭了外层 script
38
- `;
39
-
40
- // ✅ 安全:把 </ 拆开
41
- const html = `
42
- <script>
43
- console.log('inner');
44
- <` + `/script>
45
- `;
46
- ```
47
-
48
- **排查方法:** 检查所有模板字符串,搜索 `</script>` 是否出现在 JS 字符串中。同时检查 `</style>` 是否出现在模板字符串中(同理)。
49
-
50
- ---
51
-
52
- ### 2. await 用在了非 async 函数里
53
-
54
- 浏览器对顶层 `await` 支持有限(取决于环境)。如果在普通函数里用了 `await`,**整个 script 块可能不执行**。
55
-
56
- ```javascript
57
- // ❌ 致命:init 不是 async 函数
58
- function init() {
59
- const data = await App.get('db/patients'); // SyntaxError,后续代码全死
60
- render(data);
61
- }
62
-
63
- // ✅ 正确
64
- async function init() {
65
- const data = await App.get('db/patients');
66
- render(data);
67
- }
68
- ```
69
-
70
- ```javascript
71
- // ❌ 致命:DOMContentLoaded 回调忘了 async
72
- document.addEventListener('DOMContentLoaded', () => {
73
- const data = await App.get('db/patients'); // 回调不是 async!
74
- });
75
-
76
- // ✅ 正确
77
- document.addEventListener('DOMContentLoaded', async () => {
78
- const data = await App.get('db/patients');
79
- });
80
- ```
81
-
82
- **排查方法:** 搜索文件中所有 `await`,逐个人工确认外层函数是否标了 `async`。
83
-
84
- ---
85
-
86
- ### 3. App.confirm() 忘了 await
87
-
88
- `App.confirm()` 返回 `Promise<boolean>`。忘了 `await`,变量是 Promise 对象(**始终 truthy**),条件判断永远通过。
89
-
90
- ```javascript
91
- // ❌ 致命:ok 是 Promise 对象,不是 boolean,if 永远为 true
92
- const ok = App.confirm('确认删除?');
93
- if (ok) { /* 永远执行 */ }
94
-
95
- // ✅ 正确
96
- const ok = await App.confirm('确认删除?');
97
- if (ok) { /* 用户点了确定才执行 */ }
98
- ```
99
-
100
- **排查方法:** 搜索 `App.confirm(`,检查返回值是否用了 `await`。
101
-
102
- ---
103
-
104
- ### 4. 对 null/undefined 调用方法
105
-
106
- API 返回数据不存在时,链式调用会抛出 TypeError,**打断后续所有代码执行**。
107
-
108
- ```javascript
109
- // ❌ 致命:data 可能是 null
110
- const name = App.get('db/patients/999').full_name.toUpperCase();
111
-
112
- // ❌ 致命:items 可能是 undefined
113
- items.forEach(item => render(item)); // TypeError: Cannot read properties of undefined
114
-
115
- // ✅ 安全
116
- const patient = await App.get('db/patients/999');
117
- if (!patient) { App.showError('未找到'); return; }
118
- const name = patient.full_name?.toUpperCase() || '';
119
-
120
- // ✅ 安全
121
- (items || []).forEach(item => render(item));
122
- ```
123
-
124
- **排查方法:** 搜 `.forEach(`、`.map(`、`.filter(` 等数组方法,确认调用者不会是 undefined。
125
-
126
- ---
127
-
128
- ### 5. getElementById 拿到 null 后操作
129
-
130
- ```javascript
131
- // ❌ 致命:如果 DOM 中不存在 #form,直接 TypeError,后续代码全死
132
- document.getElementById('form').addEventListener('submit', handler);
133
-
134
- // ✅ 安全
135
- const form = document.getElementById('form');
136
- if (form) { form.addEventListener('submit', handler); }
137
- ```
138
-
139
- **排查方法:** 搜索 `document.getElementById(`,检查返回值是否判空。
140
-
141
- ---
142
-
143
- ### 6. 变量重复声明 / 提前引用
144
-
145
- ```javascript
146
- // ❌ 致命:const 重复声明
147
- const App = window.parent?.App;
148
- // ... 500 行后 ...
149
- const App = window.parent?.App; // SyntaxError: Identifier 'App' has already been declared
150
-
151
- // ❌ 致命:TDZ 死区
152
- console.log(app); // ReferenceError
153
- const app = window.parent?.App;
154
- ```
155
-
156
- **排查方法:** 搜索 `const App`、`let App`、`var App` 看是否重复。搜索 `const ` 全局看是否有同名声明。
157
-
158
- ---
159
-
160
- ### 6.5 display 类型冲突(JS 覆盖 CSS flex/grid)
161
-
162
- JS 通过 `el.style.display = 'block'` 切换显隐时,如果元素 CSS 声明了 `display:flex` 或 `display:grid`,inline style 会覆盖,导致布局塌陷——子元素的居中、分布全部失效。
163
-
164
- ```javascript
165
- // ❌ 致命:CSS 里 .empty { display:flex; align-items:center; justify-content:center }
166
- // 但 JS 把它改成 block,flex 布局被杀死
167
- function showState(name) {
168
- ['skeleton','emptyState','tableWrap'].forEach(id => {
169
- document.getElementById(id).style.display = id === name ? 'block' : 'none';
170
- });
171
- }
172
-
173
- // ✅ 方案1:匹配元素实际需要的 display 类型
174
- document.getElementById(id).style.display = id === name ? 'flex' : 'none';
175
-
176
- // ✅ 方案2(推荐):用 class 切换,不操作 inline display
177
- function showState(name) {
178
- ['skeleton','emptyState','tableWrap'].forEach(id => {
179
- document.getElementById(id).classList.toggle('hidden', id !== name);
180
- });
181
- }
182
- // CSS: .hidden { display: none !important; }
183
- ```
184
-
185
- **排查方法:** 搜索 `style.display = 'block'`,逐个确认目标元素是否有 flex/grid 布局。空态、居中容器、card-grid 最易中招。
186
-
187
- ---
188
-
189
- ### 7. JSON.parse 静默失败
190
-
191
- ```javascript
192
- // ❌ 如果 str 不是合法 JSON,直接抛异常
193
- const config = JSON.parse(App.config.some_setting);
194
-
195
- // ✅ 安全
196
- let config = {};
197
- try { config = JSON.parse(App.config.some_setting || '{}'); } catch (e) {}
198
- ```
199
-
200
- ---
201
-
202
- ### 8. 对象字面量尾部逗号(极少见但存在)
203
-
204
- 虽然现代浏览器大多容忍,但在某些内嵌环境中尾部逗号仍可能出错。
205
-
206
- ```javascript
207
- // 某些严格解析场景可能报错
208
- const obj = {
209
- name: 'test',
210
- age: 30, // ← 尾逗号
211
- };
212
- ```
213
- 这道一般不是问题,但如果其他都排除了仍找不到 bug,可以检查。
214
-
215
- ---
216
-
217
- ### 9. innerHTML 中的 HTML 片段提前闭合
218
-
219
- ```javascript
220
- // ❌ 如果 row.name 包含特殊字符,可能破坏 HTML 结构
221
- el.innerHTML = `<div>${row.name}</div>`;
222
-
223
- // ✅ 安全:至少做基本转义
224
- const esc = s => String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
225
- el.innerHTML = `<div>${esc(row.name)}</div>`;
226
- ```
227
-
228
- **排查方法:** 搜索 `innerHTML =`,确认插入内容做了转义。
229
-
230
- ---
231
-
232
- ### 10. 正则表达式灾难性回溯
233
-
234
- 大文本上运行复杂正则,页面卡死,看起来像挂了。
235
-
236
- ```javascript
237
- // ❌ 多个 .* 叠加可能导致回溯爆炸
238
- const matches = hugeText.match(/(.*)<div>(.*)<\/div>(.*)/gs);
239
-
240
- // ✅ 用具体选择器或限制范围
241
- ```
242
-
243
- ---
244
-
245
- ## 系统性排查法
246
-
247
- 当你查了上面清单还是找不到 bug 时:
248
-
249
- ### 步骤 1:确认代码是否在跑
250
-
251
- 在 `<script>` 最开头加:
252
- ```javascript
253
- console.log('=== SCRIPT START ===');
254
- ```
255
- 如果这行没输出 → script 根本没加载(检查 HTML 结构、script 标签闭合)
256
-
257
- ### 步骤 2:二分定位死点
258
-
259
- 在疑似问题区域两侧加 log:
260
- ```javascript
261
- console.log('A');
262
- // ... 代码 ...
263
- console.log('B');
264
- ```
265
- 如果 A 输出但 B 没输出 → bug 在两者之间
266
-
267
- ### 步骤 3:检查全局错误处理
268
-
269
- ```javascript
270
- window.addEventListener('error', e => console.error('全局错误:', e.message, e.filename, e.lineno));
271
- window.addEventListener('unhandledrejection', e => console.error('未处理 Promise:', e.reason));
272
- ```
273
-
274
- ### 步骤 4:检查异步代码是否真执行了
275
-
276
- 很多"没反应"是因为异步函数抛了异常但没 catch:
277
- ```javascript
278
- // ❌ 异步异常链断裂
279
- async function load() {
280
- const data = await App.get('db/patients'); // 如果这里 reject,外面感知不到
281
- render(data);
282
- }
283
- load(); // 没有 .catch()
284
-
285
- // ✅ 加错误边界
286
- load().catch(err => console.error('load 失败:', err));
287
- ```
288
-
289
- ---
290
-
291
- ## HTML 结构层面的静默缺陷
292
-
293
- 以下缺陷不会触发任何 JS 错误,但会导致页面空白或样式错乱:
294
-
295
- | 缺陷 | 后果 | 排查方法 |
296
- |---|---|---|
297
- | `</script>` 前缺少闭合引号 | 后续 HTML 全被当 JS 解析 | 检查 `<script>` 内容中是否有未闭合的字符串 |
298
- | `<style>` 中有 `</style>` | CSS 提前结束,后续样式丢失 | 检查内联 CSS 中是否有 `</style>` 文本 |
299
- | 属性值引号不匹配 `id="xxx'` | HTML 解析错位 | 搜 `=".*'` 或 `='.*"` 正则 |
300
- | `<` 出现在 JS 比较符中没转义 | HTML 解析器误解 | 在 inline JS 中 `if (a < b)` 可能导致问题,改用 `if (b > a)` |
301
-
302
- ---
303
-
304
- ## 总结:查不到 bug 时的三板斧
305
-
306
- 1. **搜索 `</script>`**——如果在 JS 字符串里出现,查!这是最最常见的静默杀手。
307
- 2. **搜索 `await`**——确认所有 await 都在 async 函数内。
308
- 3. **二分注释**——注释掉一半代码,看功能能不能跑,逐次缩小范围。不要用眼睛硬读。
@@ -1,56 +0,0 @@
1
- # DraftGo 并行执行
2
-
3
- 主 Agent 在任务开始时只执行一次 `draftgo context --task <task> --output json`,随后维护共享契约和资源 owner。并行是按依赖和资源边界选择的执行方式,不是每个任务的固定要求。
4
-
5
- ## 资源依赖
6
-
7
- 先为每个工作单元记录:
8
-
9
- - `depends`:开始前必须完成的工作单元。
10
- - `resource_lock`:本单元会修改的文件或 DraftGo 资源。
11
- - `evidence`:完成后返回的验证证据。
12
-
13
- 按以下关系建立依赖:
14
-
15
- | 资源关系 | 执行顺序 |
16
- |---|---|
17
- | 多个实现依赖同一 schema、API、权限或路由 | 先确定共享契约,再并行实现消费者。 |
18
- | 多个工作单元涉及同一文件或 DraftGo 资源 | 全程分配给同一个修改 owner;其他 Agent 只能只读分析并回传建议。 |
19
- | 页面与对应导航入口 | 页面 route 确定后接入导航。 |
20
- | 不同文件且没有数据或接口依赖 | 放入同一 wave 并行执行。 |
21
-
22
- 单页面、强依赖任务,或拆分后仍共享主要文件/资源的任务由一个 Agent 完成,不强行并行。
23
-
24
- ## 工作单元
25
-
26
- 分发内容包括:
27
-
28
- ```yaml
29
- objective: 要完成的结果
30
- inputs: 当前资源和共享契约
31
- resource_lock: [允许修改的文件或资源]
32
- evidence: 返回的检查或运行证据
33
- delivery_owner: main
34
- ```
35
-
36
- 工作单元返回修改结果、验证证据和阻塞信息。主 Agent 独占资源 owner 分配、共享契约维护、wave 推进、汇总回读、统一验证、commit 和 changelog 职责;子 Agent 不写 changelog。
37
-
38
- ## Wave 执行
39
-
40
- 1. 主 Agent 执行一次 context,确定 schema、服务端点、权限、route 和导航结构等共享契约,并建立唯一资源 owner 表。
41
- 2. 将 `depends` 已满足且 `resource_lock` 不冲突的工作单元放入同一 wave。
42
- 3. 并行执行当前 wave,汇总后回读所有变更资源。
43
- 4. 处理接口接线和入口绑定,再启动依赖已满足的下一 wave。
44
- 5. 主 Agent 统一运行一次 `draftgo check` 和必要的 API/UI 验证;只对已 checkout 的 pages/nav/docs 执行 commit,结构化资源通过 MCP 实时 API 交付。
45
- 6. 全部验证和交付成功后,由主 Agent 执行一次 `draftgo changelog add "<完成结果>"`。
46
-
47
- 某个工作单元失败时,其依赖项等待处理;其余独立分支继续汇总。发现资源锁冲突时,将相关实现重新归并给既有唯一 owner,不得通过移动到后续 wave 改由另一个 Agent 修改。
48
-
49
- 已 checkout 长正文的批量交付示例:
50
-
51
- ```bash
52
- draftgo commit pages 1 2 3
53
- draftgo commit nav 4
54
- ```
55
-
56
- 不同类型分开提交。发生 409/412 时当前 wave 必须停止并保留冲突材料,不得继续自动提交后续依赖项。统一验证失败、409/412 或任何交付失败时都不得执行 `changelog add`。
@@ -1,74 +0,0 @@
1
- ---
2
- read_when: 开发前检查合规性时 · Code Review 时
3
- ---
4
-
5
- # 开发禁区(违反必报错)
6
-
7
- ## 网络资源
8
-
9
- | ❌ 禁止 | ✅ 替代 |
10
- |---|---|
11
- | 任何境外 CDN(googleapis / jsdelivr / cdnjs / unpkg) | 国内镜像(npmmirror.com / staticfile.net)或本地资源 |
12
- | 外部 CDN 引入图标 | `/assets/icons/{name}.svg` 内置图标库 |
13
-
14
- ---
15
-
16
- ## App 对象使用
17
-
18
- | ❌ 禁止 | ✅ 替代 |
19
- |---|---|
20
- | `App()` 写法(App 是对象不是函数) | `const App = window.parent?.App` |
21
- | `const App = () => window.parent?.App` | 去掉箭头函数 |
22
- | `App?.user?.role` 判断权限 | `App.isAdmin` 或 `App.currentUser?.role_code` |
23
-
24
- ---
25
-
26
- ## 路由 & 导航
27
-
28
- | ❌ 禁止 | ✅ 替代 |
29
- |---|---|
30
- | `window.location.search` 读参数 | `window.__DG_ROUTE_CONTEXT__.query` |
31
- | `navigate('/login')` 退出 | `window.parent.location.href = '/login'` |
32
- | 页面内 `window.location.href = ...` 跳转 | `window.parent.location.href = ...`(页面在 iframe 中) |
33
-
34
- ---
35
-
36
- ## 弹窗 & 交互
37
-
38
- | ❌ 禁止 | ✅ 替代 |
39
- |---|---|
40
- | `window.alert(msg)` | `App.showModal(msg, title?)` |
41
- | `window.confirm(msg)` | `await App.confirm(msg, title?)` |
42
- | `window.prompt(msg)` | 自建 modal + input |
43
-
44
- ---
45
-
46
- ## UI 组件
47
-
48
- | ❌ 禁止 | ✅ 替代 |
49
- |---|---|
50
- | 硬编码 hex / rgb / rgba 颜色 | 优先用系统主题 `var(--dg-*)` 语义 token;品牌/图表/用户指定配色必须同时适配浅色与深色 |
51
- | 在页面内读 `localStorage.dg_theme` | `App.theme` |
52
-
53
- ---
54
-
55
- ## 全局层
56
-
57
- | ❌ 禁止 | ✅ 替代 |
58
- |---|---|
59
- | 在业务页面内实现全局浮窗 / 客服 / 统计脚本 | 使用 `frontend_global_*` 固定槽位 |
60
- | 在页面内渲染系统 Header / Logo / 用户头像下拉 | 这些属于壳层,不属于业务页面 |
61
- | 新增全局层槽位 | 只能编辑系统内置固定槽位 |
62
-
63
- ---
64
-
65
- ## 颜色 Token 参考
66
-
67
- 默认优先采用系统主题配色:页面直接引用 `var(--dg-*)`,跟随壳层当前浅色 / 深色模式。只有页面不搭配、品牌要求、用户明确指定或图表多系列等场景才允许自主配色;自主配色必须提供浅色与深色两套变量或 `[data-theme="light"]` / `[data-theme="dark"]` 覆盖,并满足 WCAG AA 对比度。
68
-
69
- | Token | 用途 |
70
- |---|---|
71
- | `--dg-bg-base` / `--dg-bg-page` / `--dg-bg-surface` | 背景层级 |
72
- | `--dg-text-primary` / `--dg-text-secondary` / `--dg-text-muted` | 文字层级 |
73
- | `--dg-accent` / `--dg-accent-hover` / `--dg-accent-subtle` | 主题色 |
74
- | `--dg-border` / `--dg-success` / `--dg-error` / `--dg-warning` | 功能色 |