@wnlen/agent-execution-template 0.8.20 → 0.8.21
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 +19 -2
- package/README.zh-CN.md +14 -0
- package/bin/agent-execution-template.js +99 -10
- package/docs/SPEC.md +55 -12
- package/package.json +1 -1
- package/template/en/ai/README.md +4 -1
- package/template/en/ai/template/VERSION +1 -1
- package/template/en/ai/template/bootstrap.md +4 -1
- package/template/en/ai/template/prompt.md +12 -9
- package/template/en/ai/template/protocol.md +9 -3
- package/template/zh/ai/README.md +2 -0
- package/template/zh/ai/template/VERSION +1 -1
- package/template/zh/ai/template/bootstrap.md +3 -1
- package/template/zh/ai/template/prompt.md +10 -7
- package/template/zh/ai/template/protocol.md +4 -0
- package/test/selftest.js +76 -4
package/README.md
CHANGED
|
@@ -21,6 +21,9 @@ Start initializing this project
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Agent Execution Template is not another agent framework. It is the missing execution layer between your repository and tools like Codex, Claude Code, Cursor, Aider, or any other AI coding agent.
|
|
24
|
+
More precisely, it is an **AI Repo Execution Protocol**: it governs how an AI reads context, confirms a task, respects file modification boundaries, verifies acceptance, and records results inside a specific repository.
|
|
25
|
+
|
|
26
|
+
It does not manage workspace switching, session isolation, sandbox lifecycle, or worker scheduling. Those belong to an external workspace/session runtime.
|
|
24
27
|
|
|
25
28
|
It turns AI coding from:
|
|
26
29
|
|
|
@@ -56,7 +59,7 @@ ai/template/ reusable execution protocol
|
|
|
56
59
|
ai/project/ project-specific working context and direction layer
|
|
57
60
|
```
|
|
58
61
|
|
|
59
|
-
`update` can refresh the protocol, while your project
|
|
62
|
+
`update` can refresh the protocol, while your repo-local project context stays protected.
|
|
60
63
|
|
|
61
64
|
## Quick Start
|
|
62
65
|
|
|
@@ -72,6 +75,14 @@ Ask your agent to bootstrap project context from existing docs and manifests:
|
|
|
72
75
|
Start initializing this project
|
|
73
76
|
```
|
|
74
77
|
|
|
78
|
+
`init` installs compatibility managed blocks in root `AGENTS.md` and `CLAUDE.md`.
|
|
79
|
+
They have the same content and are not separate protocols; they adapt to generic
|
|
80
|
+
Agent / Codex and Claude Code discovery conventions. Compatible AI tools read
|
|
81
|
+
`ai/template/prompt.md` first, then route bootstrap to `ai/template/bootstrap.md`.
|
|
82
|
+
If your AI tool does not auto-read those root
|
|
83
|
+
entrypoints, ask it to read `AGENTS.md` or `CLAUDE.md` before sending the
|
|
84
|
+
initialization instruction above.
|
|
85
|
+
|
|
75
86
|
The agent will generate project context and summarize what needs confirmation,
|
|
76
87
|
risks, and the recommended next step in chat:
|
|
77
88
|
|
|
@@ -228,7 +239,7 @@ ai/
|
|
|
228
239
|
The split is the core design:
|
|
229
240
|
|
|
230
241
|
- `ai/template/**` is reusable protocol. It can be safely updated from this package.
|
|
231
|
-
- `ai/project/**` is your project
|
|
242
|
+
- `ai/project/**` is your repo-local project context. It stores local context, tasks, references, results, and metrics.
|
|
232
243
|
|
|
233
244
|
## Commands
|
|
234
245
|
|
|
@@ -243,6 +254,8 @@ Creates `ai/` in the current project.
|
|
|
243
254
|
- Updates or creates `ai/template/**`.
|
|
244
255
|
- Creates missing `ai/project/**` files.
|
|
245
256
|
- Keeps existing `ai/project/**` files intact.
|
|
257
|
+
- Creates or updates the same compatibility managed block in root `AGENTS.md` /
|
|
258
|
+
`CLAUDE.md` so different AI tools can discover the protocol entrypoint.
|
|
246
259
|
- Use `--lang zh` or omit `--lang` for the Chinese template.
|
|
247
260
|
|
|
248
261
|
### `next`
|
|
@@ -425,12 +438,16 @@ Agent Execution Template is not:
|
|
|
425
438
|
- an IDE,
|
|
426
439
|
- an agent platform,
|
|
427
440
|
- a multi-agent scheduler,
|
|
441
|
+
- a workspace / sandbox / session runtime,
|
|
442
|
+
- a multi-repository context manager,
|
|
428
443
|
- a cloud service,
|
|
429
444
|
- a prompt collection,
|
|
430
445
|
- a replacement for Codex, Claude Code, Cursor, or Aider.
|
|
431
446
|
|
|
432
447
|
It is a small file protocol for making those tools behave more consistently inside real software projects.
|
|
433
448
|
|
|
449
|
+
It does not handle workspace switching, sandbox lifecycle, session fork / rollback, or worker scheduling. Conversely, an external runtime should not replace in-repository task definitions, file modification rules, acceptance criteria, or concrete coding context.
|
|
450
|
+
|
|
434
451
|
## Specification
|
|
435
452
|
|
|
436
453
|
- [Full specification](docs/SPEC.md)
|
package/README.zh-CN.md
CHANGED
|
@@ -27,6 +27,9 @@ npx -y @wnlen/agent-execution-template init --lang zh
|
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Agent Execution Template 不是新的 Agent 框架。它是代码仓库和 Codex、Claude Code、Cursor、Aider 等 AI Coding Agent 之间缺失的执行层。
|
|
30
|
+
更准确地说,它是 **AI Repo Execution Protocol**:只约束 AI 在某个仓库内如何读取上下文、确认任务、遵守文件修改边界、验收并记录结果。
|
|
31
|
+
|
|
32
|
+
它不管理 workspace 切换、Session 隔离、sandbox 生命周期或 worker 调度。这些属于外部 workspace/session runtime。
|
|
30
33
|
|
|
31
34
|
它把 AI 编程从:
|
|
32
35
|
|
|
@@ -83,6 +86,12 @@ npx -y @wnlen/agent-execution-template init --lang en
|
|
|
83
86
|
开始初始化这个项目
|
|
84
87
|
```
|
|
85
88
|
|
|
89
|
+
`init` 会在仓库根目录安装 `AGENTS.md` 和 `CLAUDE.md` 兼容入口托管块。两者内容相同,
|
|
90
|
+
不是两套协议;它们分别适配通用 Agent / Codex 和 Claude Code 的自动发现约定。
|
|
91
|
+
支持这些入口的 AI 工具会先读取 `ai/template/prompt.md`,再路由到 `ai/template/bootstrap.md`。
|
|
92
|
+
如果你的 AI 工具没有自动读取根目录入口文件,请先让它读取 `AGENTS.md` 或
|
|
93
|
+
`CLAUDE.md`,再发送上面的初始化指令。
|
|
94
|
+
|
|
86
95
|
Agent 会生成项目上下文,并在聊天里给出需要确认的摘要、风险和建议下一步:
|
|
87
96
|
|
|
88
97
|
```text
|
|
@@ -247,6 +256,7 @@ npx -y @wnlen/agent-execution-template init
|
|
|
247
256
|
- 更新或创建 `ai/template/**`。
|
|
248
257
|
- 创建缺失的 `ai/project/**` 文件。
|
|
249
258
|
- 保留已有的 `ai/project/**` 文件。
|
|
259
|
+
- 创建或更新根目录 `AGENTS.md` / `CLAUDE.md` 中的同内容兼容托管块,让不同 AI 工具能发现协议入口。
|
|
250
260
|
- 默认安装中文模板;英文模板使用 `--lang en`。
|
|
251
261
|
|
|
252
262
|
### `next`
|
|
@@ -426,12 +436,16 @@ Agent Execution Template 不是:
|
|
|
426
436
|
- IDE;
|
|
427
437
|
- Agent 平台;
|
|
428
438
|
- 多 Agent 调度器;
|
|
439
|
+
- workspace / sandbox / session 运行时;
|
|
440
|
+
- 多仓库上下文管理器;
|
|
429
441
|
- 云服务;
|
|
430
442
|
- 提示词合集;
|
|
431
443
|
- Codex、Claude Code、Cursor 或 Aider 的替代品。
|
|
432
444
|
|
|
433
445
|
它是一个小型文件协议,用来让这些工具在真实软件项目中表现得更稳定。
|
|
434
446
|
|
|
447
|
+
它不负责 workspace 切换、sandbox 生命周期、session fork / rollback 或 worker 调度。反过来,外部运行时不应该替代仓库内的任务定义、文件修改规则、acceptance criteria 或具体编码上下文。
|
|
448
|
+
|
|
435
449
|
## 规格
|
|
436
450
|
|
|
437
451
|
- [完整规格](docs/SPEC.md)
|
|
@@ -8,6 +8,9 @@ const TEMPLATE_ROOT = path.join(PACKAGE_ROOT, "template");
|
|
|
8
8
|
const TARGET_AI = path.join(process.cwd(), "ai");
|
|
9
9
|
const DEFAULT_LANG = "zh";
|
|
10
10
|
const SUPPORTED_LANGS = new Set(["zh", "en"]);
|
|
11
|
+
const ROOT_ENTRYPOINT_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
12
|
+
const ENTRYPOINT_BLOCK_START = "<!-- agent-execution-template:start -->";
|
|
13
|
+
const ENTRYPOINT_BLOCK_END = "<!-- agent-execution-template:end -->";
|
|
11
14
|
|
|
12
15
|
const REQUIRED_FILES = [
|
|
13
16
|
"ai/template/LANG",
|
|
@@ -74,11 +77,13 @@ const TEXT = {
|
|
|
74
77
|
`,
|
|
75
78
|
unknown: "未知",
|
|
76
79
|
sourceMissing: "找不到模板来源",
|
|
77
|
-
ready: "Agent Execution Template
|
|
78
|
-
initGuide: `[
|
|
79
|
-
|
|
80
|
+
ready: "Agent Execution Template 协议已安装。项目上下文尚未初始化。",
|
|
81
|
+
initGuide: `[下一步:让 AI 初始化项目上下文]
|
|
82
|
+
已安装根目录 AI 兼容入口: AGENTS.md / CLAUDE.md
|
|
83
|
+
|
|
84
|
+
1. 无额外资料
|
|
80
85
|
对 AI 说: 开始初始化这个项目
|
|
81
|
-
2.
|
|
86
|
+
2. 有已确定资料
|
|
82
87
|
先放到: ai/project/inbox/
|
|
83
88
|
对 AI 说: 开始初始化这个项目,并吸收 ai/project/inbox/ 里的资料
|
|
84
89
|
|
|
@@ -131,6 +136,8 @@ const TEXT = {
|
|
|
131
136
|
invalidJson: "JSON 无效",
|
|
132
137
|
invalidSchema: "不符合协议 schema",
|
|
133
138
|
taskFrontMatterIncomplete: "任务 front matter 缺少关键字段",
|
|
139
|
+
entrypointReady: "根目录 AI 兼容入口已安装: AGENTS.md / CLAUDE.md",
|
|
140
|
+
entrypointMissing: "缺少根目录 AI 兼容入口托管块;AI 可能不会自动读取 ai/template/prompt.md",
|
|
134
141
|
versionMismatch: "模板版本与包版本不一致",
|
|
135
142
|
runInit: "请运行 npx -y @wnlen/agent-execution-template init",
|
|
136
143
|
readyWithWarnings: "已就绪,但存在警告",
|
|
@@ -184,11 +191,13 @@ Usage:
|
|
|
184
191
|
`,
|
|
185
192
|
unknown: "unknown",
|
|
186
193
|
sourceMissing: "Template source not found",
|
|
187
|
-
ready: "Agent Execution Template
|
|
188
|
-
initGuide: `[
|
|
189
|
-
|
|
194
|
+
ready: "Agent Execution Template protocol installed. Project context is not initialized yet.",
|
|
195
|
+
initGuide: `[Next: ask the AI to initialize project context]
|
|
196
|
+
Installed root AI compatibility entrypoints: AGENTS.md / CLAUDE.md
|
|
197
|
+
|
|
198
|
+
1. Without extra material
|
|
190
199
|
Tell the AI: Start initializing this project
|
|
191
|
-
2.
|
|
200
|
+
2. With confirmed material
|
|
192
201
|
Put it in: ai/project/inbox/
|
|
193
202
|
Tell the AI: Start initializing this project and absorb the material in ai/project/inbox/
|
|
194
203
|
|
|
@@ -241,6 +250,8 @@ Usage:
|
|
|
241
250
|
invalidJson: "contains invalid JSON",
|
|
242
251
|
invalidSchema: "does not match protocol schema",
|
|
243
252
|
taskFrontMatterIncomplete: "task front matter is missing required fields",
|
|
253
|
+
entrypointReady: "root AI compatibility entrypoints installed: AGENTS.md / CLAUDE.md",
|
|
254
|
+
entrypointMissing: "missing root AI compatibility entrypoint managed block; the AI may not auto-read ai/template/prompt.md",
|
|
244
255
|
versionMismatch: "template version does not match package version",
|
|
245
256
|
runInit: "Run npx -y @wnlen/agent-execution-template init",
|
|
246
257
|
readyWithWarnings: "Ready to run with warnings",
|
|
@@ -397,6 +408,72 @@ function copyTree(sourceRoot, targetRoot, overwrite) {
|
|
|
397
408
|
);
|
|
398
409
|
}
|
|
399
410
|
|
|
411
|
+
function rootEntrypointBlock(lang) {
|
|
412
|
+
if (lang === "en") {
|
|
413
|
+
return `${ENTRYPOINT_BLOCK_START}
|
|
414
|
+
## Agent Execution Template
|
|
415
|
+
|
|
416
|
+
This repository has Agent Execution Template installed in \`ai/\`.
|
|
417
|
+
This managed block is intentionally duplicated in \`AGENTS.md\` and \`CLAUDE.md\` for different AI tool discovery conventions.
|
|
418
|
+
|
|
419
|
+
Mandatory routing:
|
|
420
|
+
- Before acting on any project request, first read and follow \`ai/template/prompt.md\`.
|
|
421
|
+
- If the user says "Start initializing this project" or asks to initialize/bootstrap project context, do not run installs, create lockfiles, or edit app files before \`ai/template/prompt.md\` routes the workflow.
|
|
422
|
+
${ENTRYPOINT_BLOCK_END}`;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return `${ENTRYPOINT_BLOCK_START}
|
|
426
|
+
## Agent Execution Template
|
|
427
|
+
|
|
428
|
+
本仓库已安装 Agent Execution Template,协议位于 \`ai/\`。
|
|
429
|
+
此托管块会有意同时写入 \`AGENTS.md\` 和 \`CLAUDE.md\`,用于适配不同 AI 工具的自动发现约定。
|
|
430
|
+
|
|
431
|
+
强制路由:
|
|
432
|
+
- 处理任何项目请求前,必须先读取并遵守 \`ai/template/prompt.md\`。
|
|
433
|
+
- 如果用户说“开始初始化这个项目”或要求初始化/整理项目上下文,在 \`ai/template/prompt.md\` 完成路由前,不要运行安装命令、不要创建 lockfile、不要编辑业务文件。
|
|
434
|
+
${ENTRYPOINT_BLOCK_END}`;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function hasManagedEntrypointBlock(content) {
|
|
438
|
+
return content.includes(ENTRYPOINT_BLOCK_START) && content.includes(ENTRYPOINT_BLOCK_END);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function upsertManagedBlock(content, block) {
|
|
442
|
+
if (!hasManagedEntrypointBlock(content)) {
|
|
443
|
+
const separator = content.trim().length > 0 ? "\n\n" : "";
|
|
444
|
+
return `${content.replace(/\s*$/, "")}${separator}${block}\n`;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const start = content.indexOf(ENTRYPOINT_BLOCK_START);
|
|
448
|
+
const end = content.indexOf(ENTRYPOINT_BLOCK_END, start) + ENTRYPOINT_BLOCK_END.length;
|
|
449
|
+
return `${content.slice(0, start)}${block}${content.slice(end)}`;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function ensureRootEntrypoints(lang) {
|
|
453
|
+
const block = rootEntrypointBlock(lang);
|
|
454
|
+
const changes = [];
|
|
455
|
+
for (const file of ROOT_ENTRYPOINT_FILES) {
|
|
456
|
+
const fullPath = path.join(process.cwd(), file);
|
|
457
|
+
const existed = fs.existsSync(fullPath);
|
|
458
|
+
const current = existed ? fs.readFileSync(fullPath, "utf8") : "";
|
|
459
|
+
const next = upsertManagedBlock(current, block);
|
|
460
|
+
if (existed && current === next) {
|
|
461
|
+
changes.push({ action: "kept", path: file });
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
fs.writeFileSync(fullPath, next);
|
|
465
|
+
changes.push({ action: existed ? "updated" : "created", path: file });
|
|
466
|
+
}
|
|
467
|
+
return changes;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function hasAllRootEntrypoints() {
|
|
471
|
+
return ROOT_ENTRYPOINT_FILES.every((file) => {
|
|
472
|
+
const fullPath = path.join(process.cwd(), file);
|
|
473
|
+
return fs.existsSync(fullPath) && hasManagedEntrypointBlock(fs.readFileSync(fullPath, "utf8"));
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
400
477
|
function formatTimestamp(date = new Date()) {
|
|
401
478
|
const pad = (value) => String(value).padStart(2, "0");
|
|
402
479
|
return [
|
|
@@ -495,7 +572,7 @@ function proposalState() {
|
|
|
495
572
|
return hasProposed ? "proposed" : null;
|
|
496
573
|
}
|
|
497
574
|
|
|
498
|
-
function init({ lang = DEFAULT_LANG, verbose = false, quiet = false } = {}) {
|
|
575
|
+
function init({ lang = DEFAULT_LANG, verbose = false, quiet = false, manageEntrypoints = true } = {}) {
|
|
499
576
|
const text = getText(lang);
|
|
500
577
|
if (!SUPPORTED_LANGS.has(lang)) {
|
|
501
578
|
console.error(`[${text.fail}] ${text.invalidLang}: ${lang}`);
|
|
@@ -522,6 +599,10 @@ function init({ lang = DEFAULT_LANG, verbose = false, quiet = false } = {}) {
|
|
|
522
599
|
changes.push(...copyTree(path.join(sourceAi, "project"), path.join(TARGET_AI, "project"), false)
|
|
523
600
|
.map((change) => ({ ...change, path: path.join("ai/project", change.path) })));
|
|
524
601
|
|
|
602
|
+
if (manageEntrypoints) {
|
|
603
|
+
changes.push(...ensureRootEntrypoints(lang));
|
|
604
|
+
}
|
|
605
|
+
|
|
525
606
|
if (!quiet) {
|
|
526
607
|
const sourceNotice = isSourceCheckout() ? `${text.sourceCheckoutNotice}\n\n` : "";
|
|
527
608
|
console.log(`${text.ready}
|
|
@@ -559,7 +640,7 @@ function refresh({ lang = DEFAULT_LANG, title } = {}) {
|
|
|
559
640
|
const backupPath = uniqueBackupPath(path.join(TARGET_AI, `project.backup.${formatTimestamp()}`));
|
|
560
641
|
fs.renameSync(projectPath, backupPath);
|
|
561
642
|
|
|
562
|
-
init({ lang, verbose: false, quiet: true });
|
|
643
|
+
init({ lang, verbose: false, quiet: true, manageEntrypoints: false });
|
|
563
644
|
|
|
564
645
|
const importPath = path.join(TARGET_AI, "project", "inbox", "raw", "old-project");
|
|
565
646
|
ensureDir(importPath);
|
|
@@ -653,6 +734,7 @@ function update({ lang = readInstalledLang() } = {}) {
|
|
|
653
734
|
ensureDir(targetTemplate);
|
|
654
735
|
const changes = copyTree(sourceTemplate, targetTemplate, true)
|
|
655
736
|
.map((change) => ({ ...change, path: path.join("ai/template", change.path) }));
|
|
737
|
+
changes.push(...ensureRootEntrypoints(lang));
|
|
656
738
|
printChanges(text.updateTitle, changes, lang);
|
|
657
739
|
console.log(`[${text.pass}] ${text.updated} ${readVersion(sourceTemplate) || text.unknown}. ${text.projectNotModified}`);
|
|
658
740
|
}
|
|
@@ -866,6 +948,13 @@ function doctor() {
|
|
|
866
948
|
console.log(`[${text.pass}] ${file}`);
|
|
867
949
|
}
|
|
868
950
|
|
|
951
|
+
if (hasAllRootEntrypoints()) {
|
|
952
|
+
console.log(`[${text.pass}] ${text.entrypointReady}`);
|
|
953
|
+
} else {
|
|
954
|
+
console.log(`[${text.warn}] ${text.entrypointMissing}`);
|
|
955
|
+
warnings += 1;
|
|
956
|
+
}
|
|
957
|
+
|
|
869
958
|
const schemaChecks = [
|
|
870
959
|
["ai/project/result.json", "ai/template/schemas/result.schema.json"],
|
|
871
960
|
["ai/project/metrics.json", "ai/template/schemas/metrics.schema.json"]
|
package/docs/SPEC.md
CHANGED
|
@@ -8,7 +8,7 @@ Current protocol: v0.8
|
|
|
8
8
|
|
|
9
9
|
## 2. 一句话定位
|
|
10
10
|
|
|
11
|
-
**Agent Execution Template 是一个 30 秒可安装、可升级、保护用户项目现场的 AI
|
|
11
|
+
**Agent Execution Template 是一个 30 秒可安装、可升级、保护用户项目现场的 AI Repo Execution Protocol。**
|
|
12
12
|
|
|
13
13
|
它把 AI 编程从“聊天式执行”变成:
|
|
14
14
|
|
|
@@ -18,11 +18,13 @@ npx 安装协议 -> AI 整理项目上下文 -> 人类确认 -> AI 生成任务
|
|
|
18
18
|
|
|
19
19
|
当前版本的核心不是做一个新的 Agent,也不是做复杂调度系统,而是给 Codex、Claude Code、Cursor、Aider 等 AI Coding Agent 提供同一套项目内执行协议。
|
|
20
20
|
|
|
21
|
+
它只管 AI 在某个仓库内怎么干活:当前任务是什么、哪些文件能改、需要读哪些上下文、执行结果怎么记录、如何审计本次任务,以及 Agent 进入项目后先读什么。
|
|
22
|
+
|
|
21
23
|
## 3. 当前版本
|
|
22
24
|
|
|
23
25
|
```text
|
|
24
26
|
Protocol: v0.8
|
|
25
|
-
Package: @wnlen/agent-execution-template@0.8.
|
|
27
|
+
Package: @wnlen/agent-execution-template@0.8.21
|
|
26
28
|
中文安装: npx -y @wnlen/agent-execution-template init
|
|
27
29
|
英文安装: npx -y @wnlen/agent-execution-template init --lang en
|
|
28
30
|
```
|
|
@@ -33,6 +35,7 @@ Package: @wnlen/agent-execution-template@0.8.19
|
|
|
33
35
|
- `init` / `next` / `refresh` / `improve-context` / `update` / `reconcile` / `strategy` / `doctor` 命令;
|
|
34
36
|
- `init --lang zh|en` 双语安装入口,默认中文;
|
|
35
37
|
- `template/project` 双区结构;
|
|
38
|
+
- 根目录 AI 兼容入口托管块:`AGENTS.md` / `CLAUDE.md`;
|
|
36
39
|
- 保护 `ai/project/**` 不被升级覆盖;
|
|
37
40
|
- 模板版本文件 `ai/template/VERSION`;
|
|
38
41
|
- 引导模式:通过 `ai/template/bootstrap.md` 从受控范围内的项目文档、manifest 和必要代码生成 `project.md` / refs 草稿;
|
|
@@ -70,6 +73,8 @@ Agent Execution Template 不是:
|
|
|
70
73
|
- AI IDE;
|
|
71
74
|
- Agent 平台;
|
|
72
75
|
- 多 Agent 调度器;
|
|
76
|
+
- workspace / sandbox / session 运行时;
|
|
77
|
+
- 多仓库上下文管理器;
|
|
73
78
|
- 任务队列系统;
|
|
74
79
|
- 云服务;
|
|
75
80
|
- Prompt Collection;
|
|
@@ -81,6 +86,20 @@ Agent Execution Template 不是:
|
|
|
81
86
|
AI Coding Agent 在项目里工作的文件协议和安全边界。
|
|
82
87
|
```
|
|
83
88
|
|
|
89
|
+
明确禁止混淆:
|
|
90
|
+
|
|
91
|
+
- Agent Execution Template 不做 workspace 切换、多仓库管理、sandbox 生命周期、session fork / rollback 或 worker 调度。
|
|
92
|
+
- 与外部运行时集成时,不应把业务任务定义、项目最终形态说明、仓库内文件修改规则、acceptance criteria 或具体编码上下文移出本协议。
|
|
93
|
+
|
|
94
|
+
与 `openclaw-workspaces` 这类外部运行时一起使用时,推荐分工是:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
openclaw-workspaces = AI Workspace & Session Runtime
|
|
98
|
+
agent-execution-template = AI Repo Execution Protocol
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
外部运行时负责仓库外能力,例如创建独立 workspace、切换项目上下文、保存/恢复/打包 session、管理 worker/agent 运行环境、隔离污染,以及未来承载多 Agent Task Graph。
|
|
102
|
+
|
|
84
103
|
## 6. 安装与日常使用
|
|
85
104
|
|
|
86
105
|
在任意项目根目录执行:
|
|
@@ -225,6 +244,8 @@ template 是协议。
|
|
|
225
244
|
project 是现场。
|
|
226
245
|
```
|
|
227
246
|
|
|
247
|
+
这里的“项目现场”只指某个仓库内的 `ai/project/**` 执行上下文,不是跨项目 workspace/runtime。外部 workspace、session 和 sandbox 生命周期应由外部运行时管理。
|
|
248
|
+
|
|
228
249
|
## 8. template 区与 project 区
|
|
229
250
|
|
|
230
251
|
### 8.1 `ai/template/`
|
|
@@ -301,6 +322,7 @@ npx -y @wnlen/agent-execution-template init
|
|
|
301
322
|
- 创建缺失的 `ai/project/**` 文件;
|
|
302
323
|
- 不覆盖已有 `ai/project/**`;
|
|
303
324
|
- 安装或覆盖 `ai/template/**`;
|
|
325
|
+
- 创建或更新根目录 `AGENTS.md` / `CLAUDE.md` 中的同内容兼容托管块;
|
|
304
326
|
- 支持 `--lang zh|en`,默认中文;
|
|
305
327
|
- 输出下一步使用说明。
|
|
306
328
|
|
|
@@ -310,6 +332,11 @@ npx -y @wnlen/agent-execution-template init
|
|
|
310
332
|
init 可以安装模板协议,但不能覆盖用户现场。
|
|
311
333
|
```
|
|
312
334
|
|
|
335
|
+
根目录 AI 兼容入口文件只管理 `agent-execution-template` 标记块,不能覆盖用户已有
|
|
336
|
+
`AGENTS.md` 或 `CLAUDE.md` 内容。两个文件中的托管块内容必须一致;这不是两套协议,
|
|
337
|
+
而是分别适配通用 Agent / Codex 和 Claude Code 的自动发现约定。托管块必须要求 AI 在“开始初始化这个项目”时先读
|
|
338
|
+
`ai/template/prompt.md`,再由它路由到 `ai/template/bootstrap.md`。
|
|
339
|
+
|
|
313
340
|
### 9.2 `update`
|
|
314
341
|
|
|
315
342
|
```bash
|
|
@@ -319,6 +346,7 @@ npx -y @wnlen/agent-execution-template update
|
|
|
319
346
|
作用:
|
|
320
347
|
|
|
321
348
|
- 只更新 `ai/template/**`;
|
|
349
|
+
- 刷新根目录 AI 兼容入口文件中的托管块;
|
|
322
350
|
- 绝不修改 `ai/project/**`;
|
|
323
351
|
- 默认沿用 `ai/template/LANG` 中记录的已安装语言;
|
|
324
352
|
- 输出更新文件列表和模板版本。
|
|
@@ -392,7 +420,7 @@ npx -y @wnlen/agent-execution-template doctor
|
|
|
392
420
|
```text
|
|
393
421
|
Agent Execution Template 检查
|
|
394
422
|
|
|
395
|
-
模板版本: 0.8.
|
|
423
|
+
模板版本: 0.8.21
|
|
396
424
|
模板语言: zh
|
|
397
425
|
|
|
398
426
|
[通过] ai/template/LANG
|
|
@@ -448,6 +476,13 @@ npx -y @wnlen/agent-execution-template reconcile
|
|
|
448
476
|
开始初始化这个项目
|
|
449
477
|
```
|
|
450
478
|
|
|
479
|
+
为了让 AI 工具能发现这个入口,`init` 会在仓库根目录安装 `AGENTS.md` 和
|
|
480
|
+
`CLAUDE.md` 兼容入口托管块。两个托管块内容相同,不代表两套协议;它们分别适配不同
|
|
481
|
+
AI 工具的自动发现约定。兼容这些入口的 AI 工具必须先读取托管块,再读取
|
|
482
|
+
`ai/template/prompt.md`,最后由 `prompt.md` 路由到 `ai/template/bootstrap.md`。
|
|
483
|
+
如果宿主工具没有自动读取根目录入口,人类应先要求它读取 `AGENTS.md` 或
|
|
484
|
+
`CLAUDE.md`。
|
|
485
|
+
|
|
451
486
|
面向用户的任务执行入口是:
|
|
452
487
|
|
|
453
488
|
```text
|
|
@@ -469,17 +504,18 @@ npx -y @wnlen/agent-execution-template reconcile
|
|
|
469
504
|
内部协议入口分别由 `ai/template/bootstrap.md`、`ai/template/prompt.md` 和
|
|
470
505
|
`ai/template/reconcile.md` 承载,用户不需要记忆这些文件名。
|
|
471
506
|
|
|
472
|
-
|
|
507
|
+
执行入口采用懒加载。AI Agent 先读:
|
|
473
508
|
|
|
474
509
|
```text
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
3. ai/project/project.md
|
|
478
|
-
4. ai/project/runtime.md
|
|
479
|
-
5. ai/project/task.md
|
|
510
|
+
0. AGENTS.md 或 CLAUDE.md 中的同内容 agent-execution-template 兼容托管块
|
|
511
|
+
1. ai/template/prompt.md
|
|
480
512
|
```
|
|
481
513
|
|
|
482
|
-
|
|
514
|
+
`prompt.md` 只做模式路由:初始化时再读 `bootstrap.md`;整合时再读
|
|
515
|
+
`reconcile.md`;执行任务时才读 `protocol.md`、`rules/core.md`、
|
|
516
|
+
`execution-policy.md`、`project.md`、`runtime.md` 和 `task.md`。
|
|
517
|
+
|
|
518
|
+
执行完成后写入:
|
|
483
519
|
|
|
484
520
|
```text
|
|
485
521
|
ai/project/result.json
|
|
@@ -540,12 +576,15 @@ ai/project/task.md
|
|
|
540
576
|
|
|
541
577
|
AI 在引导模式中负责先生成项目上下文草稿。默认读取范围包括:
|
|
542
578
|
|
|
543
|
-
- 根目录文档:`README*`、`
|
|
579
|
+
- 根目录文档:`README*`、`CONTRIBUTING*`、`CHANGELOG*`;
|
|
544
580
|
- package/build manifest:`package.json`、`pyproject.toml`、`Cargo.toml`、`go.mod`、`pom.xml`、`build.gradle*`、`Makefile`;
|
|
545
581
|
- 项目文档:`docs/**`,优先 overview、architecture、setup、testing、deployment、API、ADR、decision;
|
|
546
582
|
- 已有 AI refs:`ai/project/refs/*.md`;
|
|
547
583
|
- source / test / config / docs 的浅层目录结构。
|
|
548
584
|
|
|
585
|
+
`AGENTS.md` 和 `CLAUDE.md` 是同内容 AI 入口路由文件,只用于宿主工具自动发现,
|
|
586
|
+
不作为项目业务证据读取。
|
|
587
|
+
|
|
549
588
|
如果文档和 manifest 不足,允许从业务代码做有边界推断:
|
|
550
589
|
|
|
551
590
|
- 先看顶层目录和文件名;
|
|
@@ -1066,6 +1105,10 @@ git diff --check
|
|
|
1066
1105
|
- 自动运行 Agent;
|
|
1067
1106
|
- 自动切换模型;
|
|
1068
1107
|
- 多 Agent 编排;
|
|
1108
|
+
- workspace 切换;
|
|
1109
|
+
- sandbox 生命周期;
|
|
1110
|
+
- session fork / rollback;
|
|
1111
|
+
- worker 调度;
|
|
1069
1112
|
- 云同步;
|
|
1070
1113
|
- IDE 插件;
|
|
1071
1114
|
- 发布流水线。
|
|
@@ -1075,7 +1118,7 @@ git diff --check
|
|
|
1075
1118
|
Agent Execution Template v0.8 已经从一个 prompt/template 原型,升级为:
|
|
1076
1119
|
|
|
1077
1120
|
```text
|
|
1078
|
-
低摩擦、可安装、可升级、保护用户现场的 AI
|
|
1121
|
+
低摩擦、可安装、可升级、保护用户现场的 AI Repo Execution Protocol npm 包雏形。
|
|
1079
1122
|
```
|
|
1080
1123
|
|
|
1081
1124
|
它的长期价值不在于替代任何模型或 Agent,而在于提供一套稳定协议:
|
package/package.json
CHANGED
package/template/en/ai/README.md
CHANGED
|
@@ -4,9 +4,12 @@ Copy this folder into a target software project.
|
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
6
|
template is protocol
|
|
7
|
-
project is
|
|
7
|
+
project is repo-local context
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
+
Here, `project` means the repo-local `ai/project/**` context. It is not an
|
|
11
|
+
external workspace, session, or sandbox runtime.
|
|
12
|
+
|
|
10
13
|
## Files
|
|
11
14
|
|
|
12
15
|
- `template/prompt.md`: AI startup prompt.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.8.
|
|
1
|
+
0.8.21
|
|
@@ -44,7 +44,7 @@ runtime files, result files, or metrics files during bootstrap.
|
|
|
44
44
|
|
|
45
45
|
Read high-signal project evidence in this order:
|
|
46
46
|
|
|
47
|
-
1. Root docs: `README*`, `
|
|
47
|
+
1. Root docs: `README*`, `CONTRIBUTING*`, `CHANGELOG*`
|
|
48
48
|
2. Manifests: `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`,
|
|
49
49
|
`pom.xml`, `build.gradle*`, `Makefile`
|
|
50
50
|
3. Project docs: `docs/**`, preferring overview, architecture, setup, testing,
|
|
@@ -62,6 +62,9 @@ bounded read:
|
|
|
62
62
|
project purpose, module boundaries, commands, and constraints;
|
|
63
63
|
- do not read the whole codebase unless the human explicitly authorizes it.
|
|
64
64
|
|
|
65
|
+
Do not treat `AGENTS.md` or `CLAUDE.md` as project business evidence; they are
|
|
66
|
+
AI entrypoint routing files only.
|
|
67
|
+
|
|
65
68
|
Do not read dependency folders, build outputs, coverage outputs, lockfiles
|
|
66
69
|
except to infer package manager, secret files, environment files, or archives
|
|
67
70
|
unless the human explicitly references them.
|
|
@@ -5,23 +5,25 @@ Execute the workflow below.
|
|
|
5
5
|
|
|
6
6
|
You are operating inside an Agent Execution Template workspace.
|
|
7
7
|
|
|
8
|
-
First read:
|
|
8
|
+
This file only routes the workflow. First read minimal state:
|
|
9
9
|
|
|
10
|
-
1. `ai/
|
|
11
|
-
2. `ai/
|
|
12
|
-
3. `ai/
|
|
10
|
+
1. `ai/project/project.md` if present
|
|
11
|
+
2. `ai/project/task.md` if present
|
|
12
|
+
3. Shallow listings of `ai/project/inbox/`, `ai/project/inbox/ideas/`, and `ai/project/proposals/final-shape-updates/`
|
|
13
13
|
|
|
14
14
|
Then choose the mode:
|
|
15
15
|
|
|
16
16
|
- If the user asks to update the North Star, final shape, product constitution,
|
|
17
17
|
module map, roadmap, or project direction, or if
|
|
18
18
|
`ai/project/inbox/ideas/` contains non-`.gitkeep` ideas waiting for
|
|
19
|
-
evaluation,
|
|
20
|
-
then
|
|
19
|
+
evaluation, read `ai/template/protocol.md`, `ai/template/rules/core.md`, and
|
|
20
|
+
relevant direction refs, then draft a `strategy_update` task or produce the
|
|
21
|
+
proposal directly, then stop for human confirmation.
|
|
21
22
|
- If the user explicitly confirms that a proposal under
|
|
22
23
|
`ai/project/proposals/final-shape-updates/*.md` may be merged, draft or
|
|
23
|
-
execute an `apply_strategy_update` task
|
|
24
|
-
`
|
|
24
|
+
execute an `apply_strategy_update` task after reading
|
|
25
|
+
`ai/template/protocol.md` and `ai/template/rules/core.md`. If the proposal is
|
|
26
|
+
still `proposed`, update it to `accepted` based on that explicit confirmation.
|
|
25
27
|
- If the user says "Start initializing this project and absorb the material in ai/project/inbox/",
|
|
26
28
|
or asks to initialize while also absorbing material from
|
|
27
29
|
`ai/project/inbox/`, inspect `ai/project/project.md` first. If it already
|
|
@@ -54,7 +56,8 @@ Then choose the mode:
|
|
|
54
56
|
the human hunt through files for gaps.
|
|
55
57
|
- Use Execution Mode only after `ai/project/project.md` and
|
|
56
58
|
`ai/project/task.md` are ready enough to define identity, goal, scope,
|
|
57
|
-
permission, and acceptance.
|
|
59
|
+
permission, and acceptance. Only then read `ai/template/protocol.md`,
|
|
60
|
+
`ai/template/rules/core.md`, and `ai/template/execution-policy.md`.
|
|
58
61
|
|
|
59
62
|
## Task Draft Handoff
|
|
60
63
|
|
|
@@ -5,12 +5,18 @@ execution context.
|
|
|
5
5
|
|
|
6
6
|
```text
|
|
7
7
|
ai/template/ = reusable execution protocol
|
|
8
|
-
ai/project/ = current
|
|
8
|
+
ai/project/ = current repo execution context
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Template is protocol. Project is
|
|
11
|
+
Template is protocol. Project is repo-local context.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Here, "repo execution context" means the repo-local `ai/project/**` context,
|
|
14
|
+
not an external workspace / session / sandbox runtime. An external
|
|
15
|
+
runtime may enter the repository and read this protocol, but should not replace
|
|
16
|
+
`task.md`, file modification rules, acceptance criteria, or concrete coding
|
|
17
|
+
context.
|
|
18
|
+
|
|
19
|
+
The repo-local context stores both execution state and direction. The direction
|
|
14
20
|
layer answers "why is this worth doing and where should the project grow"; the
|
|
15
21
|
execution layer answers "what is this task and how will it be accepted."
|
|
16
22
|
|
package/template/zh/ai/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.8.
|
|
1
|
+
0.8.21
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
按下面顺序读取高价值项目证据:
|
|
38
38
|
|
|
39
|
-
1. 根目录文档:`README*`、`
|
|
39
|
+
1. 根目录文档:`README*`、`CONTRIBUTING*`、`CHANGELOG*`
|
|
40
40
|
2. 清单文件:`package.json`、`pyproject.toml`、`Cargo.toml`、`go.mod`、
|
|
41
41
|
`pom.xml`、`build.gradle*`、`Makefile`
|
|
42
42
|
3. 项目文档:`docs/**`,优先阅读概览、架构、安装、测试、部署、API、ADR 和决策文件
|
|
@@ -51,6 +51,8 @@
|
|
|
51
51
|
- 只读取足够识别目的、模块边界、命令和约束的路由、模块、配置和测试文件;
|
|
52
52
|
- 除非人类明确授权,不要读取整个代码库。
|
|
53
53
|
|
|
54
|
+
不要把 `AGENTS.md` 或 `CLAUDE.md` 当作项目业务证据;它们只是 AI 入口路由文件。
|
|
55
|
+
|
|
54
56
|
除非人类明确引用或授权,不要读取依赖目录、构建产物、覆盖率输出、锁文件
|
|
55
57
|
(推断包管理器除外)、密钥文件、环境文件或归档目录。
|
|
56
58
|
|
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
不要总结这个文件。
|
|
4
4
|
按下面流程执行。你正在 Agent Execution Template 工作区内操作。
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
本文件只负责路由。先读取最小状态:
|
|
7
7
|
|
|
8
|
-
1. `ai/
|
|
9
|
-
2. `ai/
|
|
10
|
-
3. `ai/
|
|
8
|
+
1. `ai/project/project.md`(如果存在)
|
|
9
|
+
2. `ai/project/task.md`(如果存在)
|
|
10
|
+
3. `ai/project/inbox/`、`ai/project/inbox/ideas/` 和 `ai/project/proposals/final-shape-updates/` 的浅层列表
|
|
11
11
|
|
|
12
12
|
选择模式:
|
|
13
13
|
|
|
14
14
|
- 用户要求更新北极星、最终形态、产品宪法、模块地图、路线图或项目方向,
|
|
15
|
-
或 `ai/project/inbox/ideas/`
|
|
15
|
+
或 `ai/project/inbox/ideas/` 有待评估灵感:读取 `ai/template/protocol.md`、
|
|
16
|
+
`ai/template/rules/core.md` 和相关方向 refs,走 `strategy_update`,生成提案后停下确认。
|
|
16
17
|
- 用户明确确认某个 `ai/project/proposals/final-shape-updates/*.md` 可合并:
|
|
17
|
-
|
|
18
|
+
读取 `ai/template/protocol.md` 和 `ai/template/rules/core.md`,走
|
|
19
|
+
`apply_strategy_update`。若 proposal 仍为 `proposed`,先改为 `accepted`。
|
|
18
20
|
- 如果用户说“开始初始化这个项目,并吸收 ai/project/inbox/ 里的资料”,
|
|
19
21
|
或要求初始化时吸收 inbox:先检查 `ai/project/project.md`。若已存在且有效,
|
|
20
22
|
执行 `ai/template/reconcile.md`,不要重新 bootstrap;若为空、占位或不完整,执行
|
|
@@ -33,7 +35,8 @@
|
|
|
33
35
|
待确认上下文、待确认任务、失败结果、未完成任务或明显风险;给出建议或起草
|
|
34
36
|
`ai/project/task.md`,不要让人类自己找问题。
|
|
35
37
|
- 只有当 `project.md` 和 `task.md` 足以定义身份、目标、范围、权限和验收时,
|
|
36
|
-
|
|
38
|
+
才读取 `ai/template/protocol.md`、`ai/template/rules/core.md`、
|
|
39
|
+
`ai/template/execution-policy.md` 并进入执行模式。
|
|
37
40
|
|
|
38
41
|
## 任务草稿交接
|
|
39
42
|
|
|
@@ -9,6 +9,10 @@ ai/project/ = 当前项目执行工作区
|
|
|
9
9
|
|
|
10
10
|
`template` 是协议,`project` 是现场。
|
|
11
11
|
|
|
12
|
+
这里的“项目执行工作区”只指当前仓库内的 `ai/project/**` 现场上下文,不是仓库外
|
|
13
|
+
workspace / session / sandbox 运行时。外部运行时可以进入仓库并读取本协议,但不应
|
|
14
|
+
替代 `task.md`、文件修改规则、验收标准或具体编码上下文。
|
|
15
|
+
|
|
12
16
|
项目现场同时保存任务和方向层。方向层回答“为什么做、往哪里长”,执行层回答
|
|
13
17
|
“这次做什么、如何验收”。
|
|
14
18
|
|
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");
|
|
@@ -132,7 +155,9 @@ 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 初始化项目上下文]"), "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
162
|
assert(initOutput.includes("整合 ai/project/inbox/ 里的新资料"), "init output should provide compact natural reconcile prompt");
|
|
138
163
|
assert(initOutput.includes("优化上下文"), "init output should expose project context refresh in user language");
|
|
@@ -142,7 +167,11 @@ function testInitUpdateDoctor() {
|
|
|
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");
|
|
@@ -232,7 +274,9 @@ 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 compatibility 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: ask the AI to initialize project context]"), "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
281
|
assert(initOutput.includes("Reconcile the new material in ai/project/inbox/"), "English init output should provide English reconcile prompt");
|
|
238
282
|
assert(initOutput.includes("Improve context"), "English init output should expose context refresh in user language");
|
|
@@ -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();
|