debug-formatter
Debug a SQL formatter bug. Use when the user reports incorrect formatting output — wrong whitespace, misplaced comments, blank lines, etc.
Best use case
debug-formatter is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Debug a SQL formatter bug. Use when the user reports incorrect formatting output — wrong whitespace, misplaced comments, blank lines, etc.
Teams using debug-formatter should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/debug-formatter/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How debug-formatter Compares
| Feature / Agent | debug-formatter | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Debug a SQL formatter bug. Use when the user reports incorrect formatting output — wrong whitespace, misplaced comments, blank lines, etc.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# debug-formatter
Debug a SQL formatter bug using red-green testing and pipeline tracing.
## Instructions
### 1. Reproduce (RED)
Add a failing test to `syntaqlite/tests/fmt_comments.rs` (comment bugs) or the
relevant `tests/fmt_diff_tests/*.py` file. Always `eprintln!` the actual output:
```rust
#[test]
fn descriptive_name() {
let input = "...";
let out = fmt(input);
eprintln!("=== actual ===\n{out}=== end ===");
assert_eq!(out, "...\n");
}
```
Run it and confirm RED:
```sh
cargo test -p syntaqlite --features fmt,sqlite --test fmt_comments TEST_NAME -- --nocapture
```
### 2. Trace the pipeline
Work through these layers to find the root cause:
| Layer | File | What to check |
|-------|------|---------------|
| Grammar | `syntaqlite-buildtools/parser-nodes/*.synq` | `fmt { }` block; `clause("KW", field)` expands to `IF_SET → LINE → KEYWORD → NEST(LINE, CHILD)` |
| Bytecode compiler | `syntaqlite-buildtools/src/dialect_codegen/fmt_compiler.rs` | How `Fmt::Clause`, `Fmt::Keyword` compile to opcodes |
| Interpreter | `syntaqlite/src/fmt/interpret.rs` | Main loop in `interpret_node`; state = `running` (committed doc) + `pending` (deferred line breaks) |
| Comment drain | `syntaqlite/src/fmt/comment.rs` | `drain_before(offset)` respects `has_non_comment_text` guard; `drain_keyword_interior()` skips it for multi-word keywords |
| flush_drain | `interpret.rs` | Integrates `DrainResult { trailing, leading }` into running/pending; when `leading != NIL`, pending is dropped |
| Doc renderer | `syntaqlite/src/fmt/doc.rs` | Wadler-style; `hardline` always breaks, `line` breaks if group broken |
### 3. Common bug patterns
- **Blank line between comments**: Two consecutive drains both produce `hardline + comment + hardline`; back-to-back hardlines = blank line. Fix via `continuation` flag on `drain_keyword_interior`.
- **Comment on wrong side of keyword**: `flush_drain` for interior comments runs before keyword text is emitted. Check flush vs keyword append ordering in the `Keyword` match arm.
- **Comment lost**: `has_non_comment_text` guard stops `drain_before` when a keyword sits between the comment and target offset. Multi-word interiors need `skip_text_check: true`.
- **Pending dropped**: `flush_drain` with `leading != NIL` zeroes pending. If pending held a LINE from the clause template, that break is lost.
### 4. Fix and verify (GREEN)
```sh
cargo test -p syntaqlite --features fmt,sqlite --test fmt_comments TEST_NAME -- --nocapture
cargo test -p syntaqlite --features fmt,sqlite
cargo build -p syntaqlite-cli && tools/run-integration-tests
```
All 7 integration suites must pass (including ~650 idempotency checks).Related Skills
validate
Validate SQL and report diagnostics using syntaqlite. Use when the user wants to check SQL for errors, lint SQL files, or verify correctness against a schema.
parse
Parse SQL and inspect the AST using syntaqlite. Use when the user wants to see the parse tree, debug SQL syntax, or understand how a query is structured.
format
Format SQL files using the syntaqlite formatter. Use when the user wants to format, reformat, or pretty-print SQL code.
run-tests
Run tests to verify correctness after code changes. Use when the user asks to run tests, verify changes, or check that things still work. Runs Rust unit tests and integration tests.
run-codegen
Regenerate all generated code from .synq definitions and SQLite grammar. Use when .synq files, grammar actions, or dialect definitions have been modified and generated C/Rust code needs updating.
release
Bump version, commit, tag, and create a draft GitHub Release. Use when the user
cpfast
Quickly commit and push current changes to a feature branch and create a PR, skipping pre-push checks. WARNING: if CI starts failing, use /cp instead.
cp
Commit all current changes, push to a feature branch, and create a PR. Use when the user asks to commit, push, save progress, or ship changes.
debugging-streamlit
Debug Streamlit frontend and backend changes using make debug with hot-reload. Use when testing code changes, investigating bugs, checking UI behavior, or needing screenshots of the running app.
ios-debugger-agent
Debug the current iOS project on a booted simulator with XcodeBuildMCP.
error-diagnostics-smart-debug
Use when working with error diagnostics smart debug
error-debugging-multi-agent-review
Use when working with error debugging multi agent review