@wnlen/agent-execution-template 0.8.16 → 0.8.18

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/test/selftest.js CHANGED
@@ -51,6 +51,7 @@ function testInitUpdateDoctor() {
51
51
  assert(read(cwd, "ai/template/LANG") === "zh\n", "init should default to zh template");
52
52
  assert(exists(cwd, "ai/template/VERSION"), "init should create template VERSION");
53
53
  assert(exists(cwd, "ai/template/bootstrap.md"), "init should create template bootstrap prompt");
54
+ assert(exists(cwd, "ai/template/execution-policy.md"), "init should create execution policy prompt");
54
55
  assert(exists(cwd, "ai/template/prompt.md"), "init should create template prompt");
55
56
  assert(exists(cwd, "ai/template/reconcile.md"), "init should create template reconcile prompt");
56
57
  assert(exists(cwd, "ai/project/inbox/.gitkeep"), "init should create inbox directory");
@@ -77,16 +78,21 @@ function testInitUpdateDoctor() {
77
78
  assert(read(cwd, "ai/template/bootstrap.md").includes("未吸收资料"), "bootstrap handoff should audit unabsorbed material");
78
79
  assert(read(cwd, "ai/template/bootstrap.md").includes("冲突处理"), "bootstrap handoff should audit conflict handling");
79
80
  assert(read(cwd, "ai/template/prompt.md").includes("任务草稿交接"), "execution prompt should include task handoff");
81
+ assert(read(cwd, "ai/template/prompt.md").includes("ai/template/execution-policy.md"), "execution prompt should read execution policy");
82
+ assert(read(cwd, "ai/template/execution-policy.md").includes("风险分级"), "execution policy should include risk rubric");
83
+ assert(read(cwd, "ai/template/execution-policy.md").includes("execution_policy.task_tree"), "execution policy should require task tree persistence");
80
84
  assert(read(cwd, "ai/template/prompt.md").includes("默认也只处理 `ai/project/inbox/*.md`"), "execution prompt should narrow inbox reconciliation");
81
- assert(read(cwd, "ai/template/protocol.md").includes("边界内连续执行"), "protocol should include bounded continuous execution");
82
- assert(read(cwd, "ai/template/protocol.md").includes("`vertical_slice`"), "protocol should require vertical-slice progress for continuous execution");
83
- assert(read(cwd, "ai/template/protocol.md").includes("L1 为 2 个或更多,自动启用"), "protocol should auto-enable continuous execution from L1 count");
84
- assert(read(cwd, "ai/template/protocol.md").includes("每个 Checkpoint 必须给出证据"), "protocol should require evidence-backed checkpoints");
85
+ assert(read(cwd, "ai/template/protocol.md").includes("`bounded_continuous`"), "protocol should include bounded continuous execution");
86
+ assert(read(cwd, "ai/template/execution-policy.md").includes("垂直切片"), "protocol should require vertical-slice progress for continuous execution");
87
+ assert(read(cwd, "ai/template/execution-policy.md").includes("L1 为 2 个或更多,自动启用"), "protocol should auto-enable continuous execution from L1 count");
88
+ assert(read(cwd, "ai/template/execution-policy.md").includes("每个 Checkpoint 必须包含"), "protocol should require evidence-backed checkpoints");
85
89
  assert(read(cwd, "ai/template/rules/core.md").includes("边界内连续执行门"), "core rules should include bounded continuous execution gate");
86
90
  assert(read(cwd, "ai/template/rules/core.md").includes("需要扩大范围、权限、命令、网络或验收时"), "core rules should stop continuous execution before boundary expansion");
87
91
  assert(read(cwd, "ai/project/task.md").includes("execution_policy:"), "task template should include execution policy");
92
+ assert(read(cwd, "ai/project/task.md").includes("readiness:"), "task template should include readiness state");
88
93
  assert(read(cwd, "ai/project/task.md").includes("activation_rule: \"auto_enable_when_l1_count_gte_2\""), "task template should define automatic activation rule");
89
94
  assert(read(cwd, "ai/project/task.md").includes("risk_gate:"), "task template should define risk gate");
95
+ assert(read(cwd, "ai/project/task.md").includes("status: \"pending | running | done | blocked\""), "task template should define task tree node status");
90
96
  assert(read(cwd, "ai/project/task.md").includes("progress_unit: \"vertical_slice\""), "task template should define continuous progress unit");
91
97
  assert(read(cwd, "ai/template/prompt.md").includes("开始初始化这个项目"), "execution prompt should route natural bootstrap entry");
92
98
  assert(read(cwd, "ai/template/prompt.md").includes("开始初始化这个项目,并吸收 ai/project/inbox/ 里的资料"), "execution prompt should route bootstrap with inbox material");
@@ -116,6 +122,7 @@ function testInitUpdateDoctor() {
116
122
  assert(initOutput.includes("把 ai/project/inbox/ideas/ 里的新灵感生成方向修订提案"), "init output should provide natural strategy prompt");
117
123
  assert(initOutput.includes("agent-execution-template next"), "init output should tell users how to recover the next step");
118
124
  assert(initOutput.includes("文件:"), "init output should summarize file changes");
125
+ assert(!initOutput.includes("维护者提示"), "init output should not show source checkout guidance in user projects");
119
126
  assert(!initOutput.includes("[已更新]"), "init output should hide detailed file changes by default");
120
127
  assert(!initOutput.includes("Read ai/template/bootstrap.md"), "init output should not use weak Read bootstrap command");
121
128
  assert(run(["init", "--verbose"], cwd).includes("[已更新] ai/template/VERSION"), "init --verbose should show detailed file changes");
@@ -142,6 +149,7 @@ function testEnglishInitUpdateDoctor() {
142
149
 
143
150
  const initOutput = run(["init", "--lang", "en"], cwd);
144
151
  assert(read(cwd, "ai/template/LANG") === "en\n", "init --lang en should install English template");
152
+ assert(exists(cwd, "ai/template/execution-policy.md"), "English init should create execution policy prompt");
145
153
  assert(read(cwd, "ai/template/bootstrap.md").includes("Confirmation Dimensions"), "English init should install English bootstrap prompt");
146
154
  assert(read(cwd, "ai/template/bootstrap.md").includes("Do not summarize this file"), "English bootstrap prompt should prevent summary-only behavior");
147
155
  assert(read(cwd, "ai/template/bootstrap.md").includes("ai/project/refs/final-shape.md"), "English bootstrap prompt should initialize the North Star");
@@ -154,16 +162,21 @@ function testEnglishInitUpdateDoctor() {
154
162
  assert(read(cwd, "ai/template/bootstrap.md").includes("Unabsorbed material"), "English bootstrap handoff should audit unabsorbed material");
155
163
  assert(read(cwd, "ai/template/bootstrap.md").includes("Conflict handling"), "English bootstrap handoff should audit conflict handling");
156
164
  assert(read(cwd, "ai/template/prompt.md").includes("Start initializing this project"), "English execution prompt should route natural bootstrap entry");
165
+ assert(read(cwd, "ai/template/prompt.md").includes("ai/template/execution-policy.md"), "English execution prompt should read execution policy");
166
+ assert(read(cwd, "ai/template/execution-policy.md").includes("Risk Rubric"), "English execution policy should include risk rubric");
167
+ assert(read(cwd, "ai/template/execution-policy.md").includes("execution_policy.task_tree"), "English execution policy should require task tree persistence");
157
168
  assert(read(cwd, "ai/template/prompt.md").includes("default to only `ai/project/inbox/*.md`"), "English execution prompt should narrow inbox reconciliation");
158
169
  assert(read(cwd, "ai/template/protocol.md").includes("`bounded_continuous`"), "English protocol should include bounded continuous execution");
159
- assert(read(cwd, "ai/template/protocol.md").includes("`vertical_slice`"), "English protocol should require vertical-slice progress for continuous execution");
160
- assert(read(cwd, "ai/template/protocol.md").includes("Automatically use `bounded_continuous`"), "English protocol should auto-enable continuous execution from L1 count");
161
- assert(read(cwd, "ai/template/protocol.md").includes("Every checkpoint must include evidence"), "English protocol should require evidence-backed checkpoints");
170
+ assert(read(cwd, "ai/template/execution-policy.md").includes("vertical"), "English protocol should require vertical-slice progress for continuous execution");
171
+ assert(read(cwd, "ai/template/execution-policy.md").includes("Automatically use `bounded_continuous`"), "English protocol should auto-enable continuous execution from L1 count");
172
+ assert(read(cwd, "ai/template/execution-policy.md").includes("Every checkpoint must include"), "English protocol should require evidence-backed checkpoints");
162
173
  assert(read(cwd, "ai/template/rules/core.md").includes("Bounded Continuous Execution Gate"), "English core rules should include bounded continuous execution gate");
163
174
  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");
164
175
  assert(read(cwd, "ai/project/task.md").includes("execution_policy:"), "English task template should include execution policy");
176
+ assert(read(cwd, "ai/project/task.md").includes("readiness:"), "English task template should include readiness state");
165
177
  assert(read(cwd, "ai/project/task.md").includes("activation_rule: \"auto_enable_when_l1_count_gte_2\""), "English task template should define automatic activation rule");
166
178
  assert(read(cwd, "ai/project/task.md").includes("risk_gate:"), "English task template should define risk gate");
179
+ assert(read(cwd, "ai/project/task.md").includes("status: \"pending | running | done | blocked\""), "English task template should define task tree node status");
167
180
  assert(read(cwd, "ai/project/task.md").includes("progress_unit: \"vertical_slice\""), "English task template should define continuous progress unit");
168
181
  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");
169
182
  assert(read(cwd, "ai/template/prompt.md").includes("instead of bootstrapping again"), "English execution prompt should reconcile inbox material when project context already exists");
@@ -190,6 +203,7 @@ function testEnglishInitUpdateDoctor() {
190
203
  assert(initOutput.includes("Generate a direction amendment proposal from ai/project/inbox/ideas/"), "English init output should provide natural strategy prompt");
191
204
  assert(initOutput.includes("agent-execution-template next"), "English init output should tell users how to recover the next step");
192
205
  assert(initOutput.includes("Files:"), "English init output should summarize file changes");
206
+ assert(!initOutput.includes("Maintainer note"), "English init output should not show source checkout guidance in user projects");
193
207
  assert(!initOutput.includes("[UPDATED]"), "English init output should hide detailed file changes by default");
194
208
  assert(run(["init", "--lang=en", "--verbose"], cwd).includes("[UPDATED] ai/template/VERSION"), "English init --verbose should show detailed file changes");
195
209
 
@@ -236,6 +250,25 @@ function testDoctorFailureAndWarning() {
236
250
  write(taskWarnCwd, "ai/project/task.md", "# Task only\n");
237
251
  const taskWarnOutput = run(["doctor"], taskWarnCwd);
238
252
  assert(taskWarnOutput.includes("任务 front matter 缺少关键字段"), "doctor should warn incomplete task front matter");
253
+
254
+ const taskPolicyWarnCwd = createTempProject("agent-execution-template-task-policy");
255
+ run(["init"], taskPolicyWarnCwd);
256
+ write(taskPolicyWarnCwd, "ai/project/task.md", `---
257
+ task_id: ""
258
+ type: "feature"
259
+ priority: "P2"
260
+ risk_level: "low"
261
+ readiness: "ready_to_execute"
262
+ execution_policy:
263
+ mode: "auto"
264
+ model_policy: {}
265
+ refs: {}
266
+ permission: {}
267
+ ---
268
+ # Task
269
+ `);
270
+ const taskPolicyWarnOutput = run(["doctor"], taskPolicyWarnCwd);
271
+ assert(taskPolicyWarnOutput.includes("任务 front matter 缺少关键字段"), "doctor should warn when execution policy fields are incomplete");
239
272
  }
240
273
 
241
274
  function testRefreshBacksUpAndImportsOldProject() {
@@ -271,14 +304,14 @@ function testNextCommandRoutesByProjectState() {
271
304
  assert(run(["next"], cwd).includes("开始初始化这个项目"), "next should bootstrap a freshly installed project");
272
305
 
273
306
  write(cwd, "ai/project/project.md", "USER PROJECT MARKER\n");
274
- assert(run(["next"], cwd).includes("继续推进这个项目"), "next should continue when no intake is waiting");
307
+ assert(run(["next"], cwd).includes("执行前先拆 L1 任务"), "next should continue with automatic execution guidance when no intake is waiting");
275
308
 
276
309
  write(cwd, "ai/project/inbox/product.md", "# Product material\n");
277
310
  assert(run(["next"], cwd).includes("整合 ai/project/inbox/ 里的新资料"), "next should route material inbox to reconcile");
278
311
  fs.unlinkSync(path.join(cwd, "ai/project/inbox/product.md"));
279
312
 
280
313
  write(cwd, "ai/project/inbox/processed/product.md", "# Processed material\n");
281
- assert(run(["next"], cwd).includes("继续推进这个项目"), "next should ignore processed inbox material");
314
+ assert(run(["next"], cwd).includes("执行前先拆 L1 任务"), "next should ignore processed inbox material");
282
315
  fs.unlinkSync(path.join(cwd, "ai/project/inbox/processed/product.md"));
283
316
 
284
317
  write(cwd, "ai/project/inbox/ideas/new-direction.md", "# Direction idea\n");
@@ -286,7 +319,7 @@ function testNextCommandRoutesByProjectState() {
286
319
  fs.unlinkSync(path.join(cwd, "ai/project/inbox/ideas/new-direction.md"));
287
320
 
288
321
  write(cwd, "ai/project/proposals/final-shape-updates/proposal.md", "---\nstatus: \"applied\"\n---\n");
289
- assert(run(["next"], cwd).includes("继续推进这个项目"), "next should ignore already applied proposals");
322
+ assert(run(["next"], cwd).includes("执行前先拆 L1 任务"), "next should ignore already applied proposals");
290
323
 
291
324
  write(cwd, "ai/project/proposals/final-shape-updates/proposal.md", "---\nstatus: \"proposed\"\n---\n");
292
325
  assert(run(["next"], cwd).includes("已有方向修订提案"), "next should route existing proposals to human review");
@@ -307,6 +340,16 @@ function testPermissionErrorIsActionable() {
307
340
  }
308
341
  }
309
342
 
343
+ function testSourceCheckoutNotice() {
344
+ const doctorOutput = run(["doctor"], repoRoot);
345
+ assert(doctorOutput.includes("维护者提示"), "doctor should warn when run in the package source checkout");
346
+ assert(doctorOutput.includes("node bin/agent-execution-template.js <command>"), "source checkout notice should show local node command");
347
+ assert(doctorOutput.includes("不要把维护者本地初始化产生的 ai/project/** 当成产品改动提交"), "source checkout notice should warn against committing local bootstrap context");
348
+
349
+ const nextOutput = run(["next"], repoRoot);
350
+ assert(nextOutput.includes("维护者提示"), "next should warn when run in the package source checkout");
351
+ }
352
+
310
353
  function main() {
311
354
  testInitUpdateDoctor();
312
355
  testEnglishInitUpdateDoctor();
@@ -314,6 +357,7 @@ function main() {
314
357
  testRefreshBacksUpAndImportsOldProject();
315
358
  testNextCommandRoutesByProjectState();
316
359
  testPermissionErrorIsActionable();
360
+ testSourceCheckoutNotice();
317
361
  console.log("selftest ok");
318
362
  }
319
363