fix: align AGENTS.md template section names with post-compaction extraction (#25029)

The official AGENTS.md template uses '## Every Session' and '## Safety',
but post-compaction context extraction expects '## Session Startup' and
'## Red Lines'. This causes workspaces using the official template to
lose startup context and safety rules after compaction.

Changes:
- Rename template sections to match code expectations (both EN and zh-CN)
- Add legacy fallback: code now tries 'Every Session'/'Safety' when
  'Session Startup'/'Red Lines' are not found (backward compatible)
- Add tests for legacy fallback and precedence when both exist
This commit is contained in:
echoVic
2026-02-24 13:46:11 +08:00
committed by Josh Lehman
parent 4242c5152f
commit ac17729161
5 changed files with 71 additions and 7 deletions

View File

@@ -13,7 +13,7 @@ This folder is home. Treat it that way.
If `BOOTSTRAP.md` exists, that's your birth certificate. Follow it, figure out who you are, then delete it. You won't need it again.
## Every Session
## Session Startup
Before doing anything else:
@@ -52,7 +52,7 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
- When you make a mistake → document it so future-you doesn't repeat it
- **Text > Brain** 📝
## Safety
## Red Lines
- Don't exfiltrate private data. Ever.
- Don't run destructive commands without asking.

View File

@@ -19,7 +19,7 @@ x-i18n:
如果 `BOOTSTRAP.md` 存在,那就是你的"出生证明"。按照它的指引,弄清楚你是谁,然后删除它。你不会再需要它了。
## 每次会话
## 会话启动
在做任何事情之前:
@@ -58,7 +58,7 @@ x-i18n:
- 当你犯了错误 → 记录下来,这样未来的你不会重蹈覆辙
- **文件 > 大脑** 📝
## 安全
## 红线
- 不要泄露隐私数据。绝对不要。
- 不要在未询问的情况下执行破坏性命令。

View File

@@ -522,6 +522,7 @@ function appendSummarySection(summary: string, section: string): string {
/**
* Read and format critical workspace context for compaction summary.
* Extracts "Session Startup" and "Red Lines" from AGENTS.md.
* Falls back to legacy names "Every Session" and "Safety".
* Limited to 2000 chars to avoid bloating the summary.
*/
async function readWorkspaceContextForSummary(): Promise<string> {
@@ -546,7 +547,12 @@ async function readWorkspaceContextForSummary(): Promise<string> {
fs.closeSync(opened.fd);
}
})();
const sections = extractSections(content, ["Session Startup", "Red Lines"]);
// Accept legacy section names ("Every Session", "Safety") as fallback
// for backward compatibility with older AGENTS.md templates.
let sections = extractSections(content, ["Session Startup", "Red Lines"]);
if (sections.length === 0) {
sections = extractSections(content, ["Every Session", "Safety"]);
}
if (sections.length === 0) {
return "";

View File

@@ -226,4 +226,57 @@ Read WORKFLOW.md on startup.
expect(result).not.toBeNull();
expect(result).toContain("Current time:");
});
it("falls back to legacy section names (Every Session / Safety)", async () => {
const content = `# Rules
## Every Session
Read SOUL.md and USER.md.
## Safety
Don't exfiltrate private data.
## Other
Ignore this.
`;
fs.writeFileSync(path.join(tmpDir, "AGENTS.md"), content);
const result = await readPostCompactionContext(tmpDir);
expect(result).not.toBeNull();
expect(result).toContain("Every Session");
expect(result).toContain("Read SOUL.md");
expect(result).toContain("Safety");
expect(result).toContain("Don't exfiltrate");
expect(result).not.toContain("Other");
});
it("prefers new section names over legacy when both exist", async () => {
const content = `# Rules
## Session Startup
New startup instructions.
## Every Session
Old startup instructions.
## Red Lines
New red lines.
## Safety
Old safety rules.
`;
fs.writeFileSync(path.join(tmpDir, "AGENTS.md"), content);
const result = await readPostCompactionContext(tmpDir);
expect(result).not.toBeNull();
expect(result).toContain("New startup instructions");
expect(result).toContain("New red lines");
expect(result).not.toContain("Old startup instructions");
expect(result).not.toContain("Old safety rules");
});
});

View File

@@ -53,9 +53,14 @@ export async function readPostCompactionContext(
}
})();
// Extract "## Session Startup" and "## Red Lines" sections
// Extract "## Session Startup" and "## Red Lines" sections.
// Also accept legacy names "Every Session" and "Safety" for backward
// compatibility with older AGENTS.md templates.
// Each section ends at the next "## " heading or end of file
const sections = extractSections(content, ["Session Startup", "Red Lines"]);
let sections = extractSections(content, ["Session Startup", "Red Lines"]);
if (sections.length === 0) {
sections = extractSections(content, ["Every Session", "Safety"]);
}
if (sections.length === 0) {
return null;