From ea113ea1d2540a0b5cd93eef7a7efe82ba4a225b Mon Sep 17 00:00:00 2001 From: Miroslav Drbal Date: Mon, 20 Apr 2026 11:25:46 +0200 Subject: [PATCH] Restore MUST weight and variadic-capture guardrail in tool prompts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review-pass findings: 1. python.md (P3) — "Put workflow explanations in assistant message or cell title" lost its **MUST** weight during compression. Agents were observed embedding explanations as in-cell comments, polluting the kernel and wasting tokens. Restored as "You **MUST** put workflow explanations in the assistant message or cell title — never inside cell code." 2. ast-grep.md + ast-edit.md (P3) — The variadic-capture warning that $$$NAME (three dollars) is correct and $$NAME (two dollars) is invalid was dropped during compression. LLMs trained on shell/regex conventions where $$ is common are prone to this mistake; ast-grep emits a generic parse error rather than a "bad metavariable" diagnostic, so the negative example has direct reproduction value. Added "Use $$$NAME, **NOT** $$NAME" to both files. All 6/6 template tests pass; bun check clean. --- packages/coding-agent/src/prompts/tools/ast-edit.md | 2 +- packages/coding-agent/src/prompts/tools/ast-grep.md | 2 +- packages/coding-agent/src/prompts/tools/python.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/coding-agent/src/prompts/tools/ast-edit.md b/packages/coding-agent/src/prompts/tools/ast-edit.md index f4ea94939..fecb76376 100644 --- a/packages/coding-agent/src/prompts/tools/ast-edit.md +++ b/packages/coding-agent/src/prompts/tools/ast-edit.md @@ -5,7 +5,7 @@ Performs structural AST-aware rewrites via native ast-grep. - `path` accepts a comma-separated list in addition to file/dir/glob - Set `lang` explicitly in mixed-language trees for deterministic rewrites - Metavariables captured in `pat` (`$A`, `$$$ARGS`) are substituted into that entry's `out` template -- **Patterns match AST structure, not text.** `$NAME` = one node (captured); `$_` = one without binding; `$$$NAME` = zero-or-more (lazy — stops at next matchable element); `$$$` = zero-or-more without binding. Metavariable names are UPPERCASE and **MUST** be the whole AST node — partial text like `prefix$VAR` or `"hello $NAME"` does NOT work +- **Patterns match AST structure, not text.** `$NAME` = one node (captured); `$_` = one without binding; `$$$NAME` = zero-or-more (lazy — stops at next matchable element); `$$$` = zero-or-more without binding. Use `$$$NAME`, **NOT** `$$NAME` — the two-dollar form is invalid. Metavariable names are UPPERCASE and **MUST** be the whole AST node — partial text like `prefix$VAR` or `"hello $NAME"` does NOT work - When the same metavariable appears twice, both occurrences **MUST** match identical code (`$A == $A` matches `x == x`, not `x == y`) - Rewrite patterns **MUST** parse as a single valid AST node. For method fragments or body snippets that don't parse standalone, wrap in context (e.g. `class $_ { … }`) and set `sel` to target the inner node — match and replacement target the selected node, not the wrapper. If ast-grep reports `Multiple AST nodes are detected`, wrap and use `sel` - For TS declarations/methods, tolerate unknown annotations: `async function $NAME($$$ARGS): $_ { $$$BODY }` or `class $_ { method($ARG: $_): $_ { $$$BODY } }` diff --git a/packages/coding-agent/src/prompts/tools/ast-grep.md b/packages/coding-agent/src/prompts/tools/ast-grep.md index 32f4b6bb1..61be08b6a 100644 --- a/packages/coding-agent/src/prompts/tools/ast-grep.md +++ b/packages/coding-agent/src/prompts/tools/ast-grep.md @@ -6,7 +6,7 @@ Performs structural code search using AST matching via native ast-grep. - Set `lang` explicitly in mixed-language trees to avoid parse noise from non-source files - Multiple patterns in `pat` run in one native pass, merged, then `offset`/`limit` applied - **Patterns match AST structure, not text** — whitespace/formatting is ignored -- `$NAME` captures one node; `$_` matches one without binding; `$$$NAME` captures zero-or-more (lazy — stops at next matchable element); `$$$` matches zero-or-more without binding +- `$NAME` captures one node; `$_` matches one without binding; `$$$NAME` captures zero-or-more (lazy — stops at next matchable element); `$$$` matches zero-or-more without binding. Use `$$$NAME`, **NOT** `$$NAME` — the two-dollar form is invalid and produces a parse error - Metavariable names are UPPERCASE and must be the whole AST node — partial-text like `prefix$VAR`, `"hello $NAME"`, or `a $OP b` does NOT work; match the whole node instead - When the same metavariable appears twice, both occurrences **MUST** match identical code (`$A == $A` matches `x == x`, not `x == y`) - Patterns **MUST** parse as a single valid AST node for the target language. For method fragments or body snippets that don't parse standalone, wrap in valid context (e.g. `class $_ { … }`) and set `sel` to target the inner node — results return for the selected node, not the outer wrapper. If ast-grep reports `Multiple AST nodes are detected`, the pattern isn't a single parseable node — wrap and use `sel` diff --git a/packages/coding-agent/src/prompts/tools/python.md b/packages/coding-agent/src/prompts/tools/python.md index ee73d4ffa..bc583c0d8 100644 --- a/packages/coding-agent/src/prompts/tools/python.md +++ b/packages/coding-agent/src/prompts/tools/python.md @@ -3,7 +3,7 @@ Runs Python cells sequentially in persistent IPython kernel. Kernel persists across calls and cells; **imports, variables, and functions survive — use this.** -**Work incrementally:** one logical step per cell (imports, define, test, use). Pass multiple small cells in one call. Define small reusable functions you can debug individually. Put workflow explanations in the assistant message or cell title. +**Work incrementally:** one logical step per cell (imports, define, test, use). Pass multiple small cells in one call. Define small reusable functions you can debug individually. You **MUST** put workflow explanations in the assistant message or cell title — never inside cell code. **On failure:** errors identify the failing cell (e.g., "Cell 3 failed"). Resubmit only the fixed cell (or fixed cell + remaining cells).