@wnlen/agent-execution-template 0.8.20 → 0.8.22
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 +25 -2
- package/README.zh-CN.md +18 -0
- package/bin/agent-execution-template.js +129 -63
- package/docs/SPEC.md +65 -12
- package/package.json +1 -1
- package/template/en/ai/README.md +4 -1
- package/template/en/ai/project/task.md +13 -53
- package/template/en/ai/template/VERSION +1 -1
- package/template/en/ai/template/bootstrap.md +4 -1
- package/template/en/ai/template/execution-policy.md +28 -1
- package/template/en/ai/template/prompt.md +20 -11
- package/template/en/ai/template/protocol.md +16 -3
- package/template/zh/ai/README.md +2 -0
- package/template/zh/ai/project/task.md +8 -52
- package/template/zh/ai/template/VERSION +1 -1
- package/template/zh/ai/template/bootstrap.md +3 -1
- package/template/zh/ai/template/execution-policy.md +25 -2
- package/template/zh/ai/template/prompt.md +16 -9
- package/template/zh/ai/template/protocol.md +9 -0
- package/test/selftest.js +94 -22
package/test/selftest.js
CHANGED
|
@@ -40,6 +40,17 @@ function write(cwd, relativePath, content) {
|
|
|
40
40
|
fs.writeFileSync(path.join(cwd, relativePath), content);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
function countOccurrences(content, pattern) {
|
|
44
|
+
return content.split(pattern).length - 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function managedEntrypointBlock(content) {
|
|
48
|
+
const start = content.indexOf("<!-- agent-execution-template:start -->");
|
|
49
|
+
const end = content.indexOf("<!-- agent-execution-template:end -->", start);
|
|
50
|
+
assert(start >= 0 && end >= 0, "entrypoint content should include a managed block");
|
|
51
|
+
return content.slice(start, end + "<!-- agent-execution-template:end -->".length);
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
function createTempProject(name) {
|
|
44
55
|
return fs.mkdtempSync(path.join(os.tmpdir(), `${name}-`));
|
|
45
56
|
}
|
|
@@ -48,6 +59,16 @@ function testInitUpdateDoctor() {
|
|
|
48
59
|
const cwd = createTempProject("agent-execution-template-selftest");
|
|
49
60
|
|
|
50
61
|
run(["init"], cwd);
|
|
62
|
+
assert(exists(cwd, "AGENTS.md"), "init should create root AGENTS.md entrypoint");
|
|
63
|
+
assert(exists(cwd, "CLAUDE.md"), "init should create root CLAUDE.md entrypoint");
|
|
64
|
+
assert(read(cwd, "AGENTS.md").includes("agent-execution-template:start"), "AGENTS.md should include managed protocol block");
|
|
65
|
+
assert(read(cwd, "AGENTS.md").includes("ai/template/prompt.md"), "AGENTS.md should route agents to the protocol prompt");
|
|
66
|
+
assert(read(cwd, "CLAUDE.md").includes("ai/template/prompt.md"), "CLAUDE.md should route Claude to the same protocol prompt");
|
|
67
|
+
assert(managedEntrypointBlock(read(cwd, "AGENTS.md")) === managedEntrypointBlock(read(cwd, "CLAUDE.md")), "AGENTS.md and CLAUDE.md should contain the same managed compatibility block");
|
|
68
|
+
assert(read(cwd, "AGENTS.md").includes("有意同时写入 `AGENTS.md` 和 `CLAUDE.md`"), "AGENTS.md should explain intentional compatibility duplication");
|
|
69
|
+
assert(read(cwd, "AGENTS.md").includes("在 `ai/template/prompt.md` 完成路由前"), "AGENTS.md should stay a short router");
|
|
70
|
+
assert(!read(cwd, "AGENTS.md").includes("ai/template/bootstrap.md"), "AGENTS.md should not duplicate bootstrap routing details");
|
|
71
|
+
assert(!read(cwd, "CLAUDE.md").includes("ai/template/bootstrap.md"), "CLAUDE.md should not duplicate bootstrap routing details");
|
|
51
72
|
assert(read(cwd, "ai/template/LANG") === "zh\n", "init should default to zh template");
|
|
52
73
|
assert(exists(cwd, "ai/template/VERSION"), "init should create template VERSION");
|
|
53
74
|
assert(exists(cwd, "ai/template/bootstrap.md"), "init should create template bootstrap prompt");
|
|
@@ -80,7 +101,9 @@ function testInitUpdateDoctor() {
|
|
|
80
101
|
assert(read(cwd, "ai/template/bootstrap.md").includes("未吸收资料"), "bootstrap handoff should audit unabsorbed material");
|
|
81
102
|
assert(read(cwd, "ai/template/bootstrap.md").includes("冲突处理"), "bootstrap handoff should audit conflict handling");
|
|
82
103
|
assert(read(cwd, "ai/template/prompt.md").includes("任务草稿交接"), "execution prompt should include task handoff");
|
|
83
|
-
assert(read(cwd, "ai/template/prompt.md").includes("
|
|
104
|
+
assert(read(cwd, "ai/template/prompt.md").includes("本文件只负责路由"), "execution prompt should be a lightweight router");
|
|
105
|
+
assert(read(cwd, "ai/template/prompt.md").includes("才读取 `ai/template/protocol.md`"), "execution prompt should lazy-load execution policy only for execution");
|
|
106
|
+
assert(read(cwd, "ai/template/bootstrap.md").includes("不要把 `AGENTS.md` 或 `CLAUDE.md` 当作项目业务证据"), "bootstrap should not treat root agent entrypoints as project evidence");
|
|
84
107
|
assert(read(cwd, "ai/template/execution-policy.md").includes("风险分级"), "execution policy should include risk rubric");
|
|
85
108
|
assert(read(cwd, "ai/template/execution-policy.md").includes("execution_policy.task_tree"), "execution policy should require task tree persistence");
|
|
86
109
|
assert(read(cwd, "ai/template/prompt.md").includes("也默认只处理 `ai/project/inbox/*.md`"), "execution prompt should narrow inbox reconciliation");
|
|
@@ -103,12 +126,12 @@ function testInitUpdateDoctor() {
|
|
|
103
126
|
assert(read(cwd, "ai/template/rules/core.md").includes("需要扩大范围、权限、命令、网络或验收时"), "core rules should stop continuous execution before boundary expansion");
|
|
104
127
|
assert(read(cwd, "ai/project/task.md").includes("execution_policy:"), "task template should include execution policy");
|
|
105
128
|
assert(read(cwd, "ai/project/task.md").includes("readiness:"), "task template should include readiness state");
|
|
106
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
107
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
108
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
109
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
129
|
+
assert(read(cwd, "ai/project/task.md").includes("compact task contract"), "task template should default to compact contracts");
|
|
130
|
+
assert(read(cwd, "ai/project/task.md").includes("expanded 任务"), "task template should explain when to expand task contracts");
|
|
131
|
+
assert(!read(cwd, "ai/project/task.md").includes("activation_rule: \"auto_enable_when_l1_count_gte_2\""), "task template should not default to expanded activation metadata");
|
|
132
|
+
assert(!read(cwd, "ai/project/task.md").includes("checkpoint_budget:"), "task template should not default to checkpoint budget fields");
|
|
133
|
+
assert(!read(cwd, "ai/project/task.md").includes("model_policy:"), "task template should not default to model policy fields");
|
|
110
134
|
assert(read(cwd, "ai/project/task.md").includes("status: \"pending | running | done | blocked\""), "task template should define task tree node status");
|
|
111
|
-
assert(read(cwd, "ai/project/task.md").includes("progress_unit: \"vertical_slice\""), "task template should define continuous progress unit");
|
|
112
135
|
assert(read(cwd, "ai/template/prompt.md").includes("开始初始化这个项目"), "execution prompt should route natural bootstrap entry");
|
|
113
136
|
assert(read(cwd, "ai/template/prompt.md").includes("开始初始化这个项目,并吸收 ai/project/inbox/ 里的资料"), "execution prompt should route bootstrap with inbox material");
|
|
114
137
|
assert(read(cwd, "ai/template/prompt.md").includes("不要重新 bootstrap"), "execution prompt should reconcile inbox material when project context already exists");
|
|
@@ -132,17 +155,23 @@ function testInitUpdateDoctor() {
|
|
|
132
155
|
assert(read(cwd, "ai/project/proposals/final-shape-updates/_template.md").includes("`accepted`"), "proposal template should describe accepted status");
|
|
133
156
|
const initOutput = run(["init"], cwd);
|
|
134
157
|
assert(initOutput.includes("开始初始化这个项目"), "init output should provide compact natural bootstrap prompt");
|
|
135
|
-
assert(initOutput.includes("
|
|
158
|
+
assert(initOutput.includes("根目录 AI 入口: AGENTS.md / CLAUDE.md"), "init output should mention root AI compatibility entrypoints");
|
|
159
|
+
assert(initOutput.includes("协议已安装。项目上下文尚未初始化"), "init output should distinguish protocol install from project context bootstrap");
|
|
160
|
+
assert(initOutput.includes("下一步,把这句话发给你的 AI coding 工具"), "init output should guide the AI bootstrap as the next step");
|
|
136
161
|
assert(initOutput.includes("开始初始化这个项目,并吸收 ai/project/inbox/ 里的资料"), "init output should explain bootstrap with existing material");
|
|
137
|
-
assert(initOutput.includes("
|
|
138
|
-
assert(initOutput.includes("
|
|
139
|
-
assert(initOutput.includes("把 ai/project/inbox/ideas/ 里的新灵感生成方向修订提案"), "init output should provide natural strategy prompt");
|
|
162
|
+
assert(initOutput.includes("已确定资料: ai/project/inbox/"), "init output should explain confirmed material path");
|
|
163
|
+
assert(initOutput.includes("未决定的新想法: ai/project/inbox/ideas/"), "init output should explain idea inbox path");
|
|
140
164
|
assert(initOutput.includes("agent-execution-template next"), "init output should tell users how to recover the next step");
|
|
141
|
-
assert(initOutput.includes("
|
|
165
|
+
assert(initOutput.includes("文件已就绪:"), "init output should summarize file changes");
|
|
166
|
+
assert(initOutput.includes("检查安装:"), "init output should show install check command");
|
|
142
167
|
assert(!initOutput.includes("维护者提示"), "init output should not show source checkout guidance in user projects");
|
|
143
168
|
assert(!initOutput.includes("[已更新]"), "init output should hide detailed file changes by default");
|
|
144
169
|
assert(!initOutput.includes("Read ai/template/bootstrap.md"), "init output should not use weak Read bootstrap command");
|
|
170
|
+
assert(countOccurrences(read(cwd, "AGENTS.md"), "agent-execution-template:start") === 1, "init should not duplicate AGENTS.md managed blocks");
|
|
171
|
+
assert(countOccurrences(read(cwd, "CLAUDE.md"), "agent-execution-template:start") === 1, "init should not duplicate CLAUDE.md managed blocks");
|
|
145
172
|
assert(run(["init", "--verbose"], cwd).includes("[已更新] ai/template/VERSION"), "init --verbose should show detailed file changes");
|
|
173
|
+
assert(countOccurrences(read(cwd, "AGENTS.md"), "agent-execution-template:start") === 1, "re-running init should keep one AGENTS.md managed block");
|
|
174
|
+
assert(countOccurrences(read(cwd, "CLAUDE.md"), "agent-execution-template:start") === 1, "re-running init should keep one CLAUDE.md managed block");
|
|
146
175
|
const reconcileOutput = run(["reconcile"], cwd);
|
|
147
176
|
assert(reconcileOutput.includes("Agent Execution Template 上下文整合"), "reconcile should use installed Chinese language");
|
|
148
177
|
assert(reconcileOutput.includes("整合 ai/project/inbox/ 里的新资料"), "reconcile should print natural Chinese prompt");
|
|
@@ -154,8 +183,10 @@ function testInitUpdateDoctor() {
|
|
|
154
183
|
write(cwd, "ai/project/project.md", "USER PROJECT MARKER\n");
|
|
155
184
|
run(["update"], cwd);
|
|
156
185
|
assert(read(cwd, "ai/project/project.md") === "USER PROJECT MARKER\n", "update must not overwrite project.md");
|
|
186
|
+
assert(read(cwd, "AGENTS.md").includes("ai/template/prompt.md"), "update should keep root agent entrypoint block installed");
|
|
157
187
|
|
|
158
188
|
const doctorOutput = run(["doctor"], cwd);
|
|
189
|
+
assert(doctorOutput.includes("根目录 AI 兼容入口已安装: AGENTS.md / CLAUDE.md"), "doctor should report root AI compatibility entrypoint status");
|
|
159
190
|
assert(doctorOutput.includes("ai/project/result.json JSON"), "doctor should validate result JSON");
|
|
160
191
|
assert(doctorOutput.includes("ai/project/result.json schema"), "doctor should validate result schema");
|
|
161
192
|
assert(doctorOutput.includes("ai/project/metrics.json JSON"), "doctor should validate metrics JSON");
|
|
@@ -167,6 +198,15 @@ function testEnglishInitUpdateDoctor() {
|
|
|
167
198
|
const cwd = createTempProject("agent-execution-template-en");
|
|
168
199
|
|
|
169
200
|
const initOutput = run(["init", "--lang", "en"], cwd);
|
|
201
|
+
assert(exists(cwd, "AGENTS.md"), "English init should create root AGENTS.md entrypoint");
|
|
202
|
+
assert(exists(cwd, "CLAUDE.md"), "English init should create root CLAUDE.md entrypoint");
|
|
203
|
+
assert(read(cwd, "AGENTS.md").includes("ai/template/prompt.md"), "English AGENTS.md should route agents to the protocol prompt");
|
|
204
|
+
assert(read(cwd, "CLAUDE.md").includes("ai/template/prompt.md"), "English CLAUDE.md should route Claude to the same protocol prompt");
|
|
205
|
+
assert(managedEntrypointBlock(read(cwd, "AGENTS.md")) === managedEntrypointBlock(read(cwd, "CLAUDE.md")), "English AGENTS.md and CLAUDE.md should contain the same managed compatibility block");
|
|
206
|
+
assert(read(cwd, "AGENTS.md").includes("intentionally duplicated in `AGENTS.md` and `CLAUDE.md`"), "English AGENTS.md should explain intentional compatibility duplication");
|
|
207
|
+
assert(read(cwd, "AGENTS.md").includes("before `ai/template/prompt.md` routes"), "English AGENTS.md should stay a short router");
|
|
208
|
+
assert(!read(cwd, "AGENTS.md").includes("ai/template/bootstrap.md"), "English AGENTS.md should not duplicate bootstrap routing details");
|
|
209
|
+
assert(!read(cwd, "CLAUDE.md").includes("ai/template/bootstrap.md"), "English CLAUDE.md should not duplicate bootstrap routing details");
|
|
170
210
|
assert(read(cwd, "ai/template/LANG") === "en\n", "init --lang en should install English template");
|
|
171
211
|
assert(exists(cwd, "ai/template/execution-policy.md"), "English init should create execution policy prompt");
|
|
172
212
|
assert(exists(cwd, "ai/template/schemas/result.schema.json"), "English init should create result schema");
|
|
@@ -183,7 +223,9 @@ function testEnglishInitUpdateDoctor() {
|
|
|
183
223
|
assert(read(cwd, "ai/template/bootstrap.md").includes("Unabsorbed material"), "English bootstrap handoff should audit unabsorbed material");
|
|
184
224
|
assert(read(cwd, "ai/template/bootstrap.md").includes("Conflict handling"), "English bootstrap handoff should audit conflict handling");
|
|
185
225
|
assert(read(cwd, "ai/template/prompt.md").includes("Start initializing this project"), "English execution prompt should route natural bootstrap entry");
|
|
186
|
-
assert(read(cwd, "ai/template/prompt.md").includes("
|
|
226
|
+
assert(read(cwd, "ai/template/prompt.md").includes("This file only routes the workflow"), "English execution prompt should be a lightweight router");
|
|
227
|
+
assert(read(cwd, "ai/template/prompt.md").includes("Only then read `ai/template/protocol.md`"), "English execution prompt should lazy-load execution policy only for execution");
|
|
228
|
+
assert(read(cwd, "ai/template/bootstrap.md").includes("Do not treat `AGENTS.md` or `CLAUDE.md` as project business evidence"), "English bootstrap should not treat root agent entrypoints as project evidence");
|
|
187
229
|
assert(read(cwd, "ai/template/execution-policy.md").includes("Risk Rubric"), "English execution policy should include risk rubric");
|
|
188
230
|
assert(read(cwd, "ai/template/execution-policy.md").includes("execution_policy.task_tree"), "English execution policy should require task tree persistence");
|
|
189
231
|
assert(read(cwd, "ai/template/prompt.md").includes("default to only `ai/project/inbox/*.md`"), "English execution prompt should narrow inbox reconciliation");
|
|
@@ -206,12 +248,12 @@ function testEnglishInitUpdateDoctor() {
|
|
|
206
248
|
assert(read(cwd, "ai/template/rules/core.md").includes("expand scope, permission, commands, network access, or acceptance"), "English core rules should stop continuous execution before boundary expansion");
|
|
207
249
|
assert(read(cwd, "ai/project/task.md").includes("execution_policy:"), "English task template should include execution policy");
|
|
208
250
|
assert(read(cwd, "ai/project/task.md").includes("readiness:"), "English task template should include readiness state");
|
|
209
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
210
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
211
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
212
|
-
assert(read(cwd, "ai/project/task.md").includes("
|
|
251
|
+
assert(read(cwd, "ai/project/task.md").includes("compact task contract"), "English task template should default to compact contracts");
|
|
252
|
+
assert(read(cwd, "ai/project/task.md").includes("Expanded tasks"), "English task template should explain when to expand task contracts");
|
|
253
|
+
assert(!read(cwd, "ai/project/task.md").includes("activation_rule: \"auto_enable_when_l1_count_gte_2\""), "English task template should not default to expanded activation metadata");
|
|
254
|
+
assert(!read(cwd, "ai/project/task.md").includes("checkpoint_budget:"), "English task template should not default to checkpoint budget fields");
|
|
255
|
+
assert(!read(cwd, "ai/project/task.md").includes("model_policy:"), "English task template should not default to model policy fields");
|
|
213
256
|
assert(read(cwd, "ai/project/task.md").includes("status: \"pending | running | done | blocked\""), "English task template should define task tree node status");
|
|
214
|
-
assert(read(cwd, "ai/project/task.md").includes("progress_unit: \"vertical_slice\""), "English task template should define continuous progress unit");
|
|
215
257
|
assert(read(cwd, "ai/template/prompt.md").includes("Start initializing this project and absorb the material in ai/project/inbox/"), "English execution prompt should route bootstrap with inbox material");
|
|
216
258
|
assert(read(cwd, "ai/template/prompt.md").includes("instead of bootstrapping again"), "English execution prompt should reconcile inbox material when project context already exists");
|
|
217
259
|
assert(read(cwd, "ai/template/prompt.md").includes("Reconcile the new material in ai/project/inbox/"), "English execution prompt should route natural reconcile entry");
|
|
@@ -232,13 +274,15 @@ function testEnglishInitUpdateDoctor() {
|
|
|
232
274
|
assert(read(cwd, "ai/template/reconcile.md").includes("Unabsorbed material"), "English reconcile handoff should audit unabsorbed material");
|
|
233
275
|
assert(read(cwd, "ai/template/reconcile.md").includes("Conflict handling"), "English reconcile handoff should audit conflict handling");
|
|
234
276
|
assert(initOutput.includes("Start initializing this project"), "English init output should provide English bootstrap prompt");
|
|
235
|
-
assert(initOutput.includes("
|
|
277
|
+
assert(initOutput.includes("Root AI entrypoints: AGENTS.md / CLAUDE.md"), "English init output should mention root AI compatibility entrypoints");
|
|
278
|
+
assert(initOutput.includes("protocol installed. Project context is not initialized yet"), "English init output should distinguish protocol install from project context bootstrap");
|
|
279
|
+
assert(initOutput.includes("Next, send this to your AI coding tool"), "English init output should guide the AI bootstrap as the next step");
|
|
236
280
|
assert(initOutput.includes("Start initializing this project and absorb the material in ai/project/inbox/"), "English init output should explain bootstrap with existing material");
|
|
237
|
-
assert(initOutput.includes("
|
|
238
|
-
assert(initOutput.includes("
|
|
239
|
-
assert(initOutput.includes("Generate a direction amendment proposal from ai/project/inbox/ideas/"), "English init output should provide natural strategy prompt");
|
|
281
|
+
assert(initOutput.includes("Confirmed material: ai/project/inbox/"), "English init output should explain confirmed material path");
|
|
282
|
+
assert(initOutput.includes("Undecided ideas: ai/project/inbox/ideas/"), "English init output should explain idea inbox path");
|
|
240
283
|
assert(initOutput.includes("agent-execution-template next"), "English init output should tell users how to recover the next step");
|
|
241
|
-
assert(initOutput.includes("Files:"), "English init output should summarize file changes");
|
|
284
|
+
assert(initOutput.includes("Files ready:"), "English init output should summarize file changes");
|
|
285
|
+
assert(initOutput.includes("Check install:"), "English init output should show install check command");
|
|
242
286
|
assert(!initOutput.includes("Maintainer note"), "English init output should not show source checkout guidance in user projects");
|
|
243
287
|
assert(!initOutput.includes("[UPDATED]"), "English init output should hide detailed file changes by default");
|
|
244
288
|
assert(run(["init", "--lang=en", "--verbose"], cwd).includes("[UPDATED] ai/template/VERSION"), "English init --verbose should show detailed file changes");
|
|
@@ -250,6 +294,7 @@ function testEnglishInitUpdateDoctor() {
|
|
|
250
294
|
|
|
251
295
|
const doctorOutput = run(["doctor"], cwd);
|
|
252
296
|
assert(doctorOutput.includes("Template language: en"), "doctor should show installed English language");
|
|
297
|
+
assert(doctorOutput.includes("root AI compatibility entrypoints installed: AGENTS.md / CLAUDE.md"), "English doctor should report root AI compatibility entrypoint status");
|
|
253
298
|
assert(doctorOutput.includes("ai/project/result.json JSON"), "English doctor should validate result JSON");
|
|
254
299
|
assert(doctorOutput.includes("ai/project/result.json schema"), "English doctor should validate result schema");
|
|
255
300
|
assert(doctorOutput.includes("ai/project/task.md front matter"), "English doctor should validate task front matter");
|
|
@@ -362,6 +407,32 @@ permission: {}
|
|
|
362
407
|
assert(taskPolicyWarnOutput.includes("任务 front matter 缺少关键字段"), "doctor should warn when execution policy fields are incomplete");
|
|
363
408
|
}
|
|
364
409
|
|
|
410
|
+
function testRootEntrypointPreservesUserContent() {
|
|
411
|
+
const cwd = createTempProject("agent-execution-template-entrypoints");
|
|
412
|
+
write(cwd, "AGENTS.md", "# Existing agent rules\n\nKeep this user rule.\n");
|
|
413
|
+
|
|
414
|
+
run(["init"], cwd);
|
|
415
|
+
assert(read(cwd, "AGENTS.md").includes("Keep this user rule."), "init should preserve existing AGENTS.md content");
|
|
416
|
+
assert(read(cwd, "AGENTS.md").includes("agent-execution-template:start"), "init should append a managed AGENTS.md block");
|
|
417
|
+
assert(countOccurrences(read(cwd, "AGENTS.md"), "agent-execution-template:start") === 1, "init should append one AGENTS.md block");
|
|
418
|
+
|
|
419
|
+
run(["init"], cwd);
|
|
420
|
+
assert(read(cwd, "AGENTS.md").includes("Keep this user rule."), "re-running init should preserve existing AGENTS.md content");
|
|
421
|
+
assert(countOccurrences(read(cwd, "AGENTS.md"), "agent-execution-template:start") === 1, "re-running init should replace, not duplicate, the managed AGENTS.md block");
|
|
422
|
+
|
|
423
|
+
run(["update"], cwd);
|
|
424
|
+
assert(read(cwd, "AGENTS.md").includes("Keep this user rule."), "update should preserve existing AGENTS.md content");
|
|
425
|
+
assert(countOccurrences(read(cwd, "AGENTS.md"), "agent-execution-template:start") === 1, "update should keep one managed AGENTS.md block");
|
|
426
|
+
|
|
427
|
+
fs.unlinkSync(path.join(cwd, "CLAUDE.md"));
|
|
428
|
+
const missingClaudeOutput = run(["doctor"], cwd);
|
|
429
|
+
assert(missingClaudeOutput.includes("缺少根目录 AI 兼容入口托管块"), "doctor should warn when one root agent entrypoint is missing");
|
|
430
|
+
|
|
431
|
+
fs.unlinkSync(path.join(cwd, "AGENTS.md"));
|
|
432
|
+
const doctorOutput = run(["doctor"], cwd);
|
|
433
|
+
assert(doctorOutput.includes("缺少根目录 AI 兼容入口托管块"), "doctor should warn when root agent entrypoints are missing");
|
|
434
|
+
}
|
|
435
|
+
|
|
365
436
|
function testRefreshBacksUpAndImportsOldProject() {
|
|
366
437
|
const cwd = createTempProject("agent-execution-template-refresh");
|
|
367
438
|
run(["init"], cwd);
|
|
@@ -445,6 +516,7 @@ function main() {
|
|
|
445
516
|
testInitUpdateDoctor();
|
|
446
517
|
testEnglishInitUpdateDoctor();
|
|
447
518
|
testDoctorFailureAndWarning();
|
|
519
|
+
testRootEntrypointPreservesUserContent();
|
|
448
520
|
testRefreshBacksUpAndImportsOldProject();
|
|
449
521
|
testNextCommandRoutesByProjectState();
|
|
450
522
|
testPermissionErrorIsActionable();
|