From 96668cb53e300edfd44caee74132844767f8787d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samet=20=C3=87EL=C4=B0KBI=C3=87AK?= Date: Tue, 6 Oct 2026 15:15:43 +0300 Subject: [PATCH] fix: escape angle brackets in agent notes so the docs build --- docs/agents.md | 8 ++++---- scripts/generate-agents-docs.js | 14 +++++++++++++- src/agents/manifest.test.js | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/docs/agents.md b/docs/agents.md index c01dd0b..a5255b0 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -128,13 +128,13 @@ rolecraft knows where each AI agent looks for skills. When you use a flag like ` - **jazz:** jazz-ai (lvndry/jazz, not an AWS product); also reads project ./skills - **iflow:** iFlow CLI was shut down on 2026-04-17; the vendor directs users to migrate to Qoder - **lingma:** Also reads project .lingma/skills; renamed to Qoder CN on 2026-05-20 -- **zcode:** ZCode, the GLM coding client. Reads ~/.zcode/skills//SKILL.md and ~/.agents/mcp.json +- **zcode:** ZCode, the GLM coding client. Reads ~/.zcode/skills/<name>/SKILL.md and ~/.agents/mcp.json - **pochi:** Pochi (TabbyML). Also reads ~/.agents/skills; project .pochi/skills - **chatgpt:** ChatGPT/Codex share the .agents skills locations; symlinked skill folders honored - **amp:** amp skill add --global installs to ~/.config/agents/skills; also reads ~/.agents/skills -- **antigravity:** Antigravity 2.0 and the IDE read ~/.gemini/config/skills; the IDE also accepts legacy ~/.gemini/antigravity/skills. All surfaces share /.agents/skills -- **antigravity-cli:** Antigravity CLI (agy) has its own global dir, separate from the 2.0/IDE surface; plugin skills at ~/.gemini/antigravity-cli/plugins//skills. Shares /.agents/skills -- **grok:** Project skills at ./.grok/skills. Reads ~/.agents/skills via AGENTS.md compatibility. MCP lives in ~/.grok/config.toml as [mcp_servers.] (TOML), which rolecraft does not yet write +- **antigravity:** Antigravity 2.0 and the IDE read ~/.gemini/config/skills; the IDE also accepts legacy ~/.gemini/antigravity/skills. All surfaces share <workspace>/.agents/skills +- **antigravity-cli:** Antigravity CLI (agy) has its own global dir, separate from the 2.0/IDE surface; plugin skills at ~/.gemini/antigravity-cli/plugins/<name>/skills. Shares <workspace>/.agents/skills +- **grok:** Project skills at ./.grok/skills. Reads ~/.agents/skills via AGENTS.md compatibility. MCP lives in ~/.grok/config.toml as [mcp_servers.<name>] (TOML), which rolecraft does not yet write - **muse-code:** Muse Code by Meta. Scans ~/.config/muse/skills, ~/.agents/skills, ~/.claude/skills, ~/.codex/skills and project .agents/.codex/.claude/skills. MCP at ~/.config/muse/settings.json under mcpServers - **posit-assistant:** Posit Assistant (Positron, RStudio). Also reads ~/.agents/skills; project .posit/assistant/skills. Legacy ~/.positai/ - **replit:** Project-committed .agents/skills only; no user-global skills dir diff --git a/scripts/generate-agents-docs.js b/scripts/generate-agents-docs.js index d3e7598..398876b 100644 --- a/scripts/generate-agents-docs.js +++ b/scripts/generate-agents-docs.js @@ -59,6 +59,16 @@ function formatMcp(agent) { return agent.mcpSupport.format } +/** + * Agent notes carry literal paths like `~/.zcode/skills//SKILL.md`. + * Markdown-in-`<...>` is read as a Vue tag when VitePress builds the docs, + * and an unclosed one aborts the whole build, so angle brackets are escaped + * here rather than relying on every future note to avoid them. + */ +function escapeMarkdown(text) { + return text.replace(//g, '>') +} + /** * Generate docs/agents.md content from manifest data */ @@ -103,7 +113,9 @@ rolecraft knows where each AI agent looks for skills. When you use a flag like \ const notes = manifest.filter((a) => a.notes) const notesSection = notes.length > 0 - ? `\n## Notes\n\n${notes.map((a) => `- **${a.name}:** ${a.notes}`).join('\n')}\n` + ? `\n## Notes\n\n${notes + .map((a) => `- **${a.name}:** ${escapeMarkdown(a.notes)}`) + .join('\n')}\n` : '' const mcpFormats = [...new Set(mcpAgents.map((a) => a.mcpSupport.format))] diff --git a/src/agents/manifest.test.js b/src/agents/manifest.test.js index 6c4a6b8..3c3093d 100644 --- a/src/agents/manifest.test.js +++ b/src/agents/manifest.test.js @@ -245,6 +245,21 @@ describe('agent manifest', () => { assert.equal(current, generated) }) + // Agent notes contain literal paths like `~/.zcode/skills//SKILL.md`. + // VitePress reads a bare `<...>` in a .md file as a Vue tag, and an unclosed + // one aborts the docs build with no link back to the note that caused it. + it('escapes angle brackets in agent notes so the docs build', () => { + const generated = generateAgentsDocs() + const notesSection = generated.slice(generated.indexOf('## Notes')) + for (const line of notesSection.split('\n')) { + assert.ok( + !line.includes('<'), + `unescaped tag in generated notes: ${line}`, + ) + } + assert.match(notesSection, /<name>/, 'expected an escaped path') + }) + it('matrix token values match the agent manifest', () => { const manifest = getAgentManifest() const tokens = getTokenValues()