Lint Triage — RTL Lint & Methodology Violation Triage
A playbook for driving SynthPilot's lint/methodology tools to find real RTL
problems, then sorting every violation into one of three buckets: fix it,
waive it (with a stated justification), or ask the human. The deliverable
is a triaged report, not a green number. A lint run that is "clean" because real
violations were silenced is a failure of this skill.
This skill follows one discipline above all: measure → classify → fix the
smallest safe thing → re-measure. It never invents a tool, never downgrades a
severity to hide a problem, and never claims "lint clean" without fresh tool
output proving it on the current source.
When to use
- User asks to "lint my RTL", "review my RTL", "check code quality", "find
unintended latches", "clean up warnings", or "is this design lint-clean".
- Before synthesis sign-off, before a design review, or before handing RTL to a
teammate, to catch latches, incomplete sensitivity lists, width mismatches,
unconnected ports, blocking/non-blocking misuse, and methodology violations.
- After an RTL edit, to confirm a class of violations is actually gone (not just
moved or masked).
- To produce a defensible waiver list — each waiver tied to an explicit reason —
for items that are intentional and safe.
When NOT to use
- Timing closure (WNS/TNS negative, failing setup/hold). Lint is not timing.
Use the timing-closure skill.
check_async_reset here surfaces reset-path
methodology issues, not slack.
- Pure CDC sign-off (metastability, gray-coding, handshake correctness).
check_cdc_lint / report_cdc are a first screen only; deep CDC analysis is a
separate playbook. Lint-triage flags CDC violations and hands them off.
- Functional verification (does the logic compute the right answer). That is
simulation (
sim_*), not lint. Lint cannot tell you a correct-looking design
is functionally wrong.
- DRC / route sign-off (
report_drc on a placed/routed design). Different
stage, different tool.
- No project is open / Vivado is not reachable. Resolve Prerequisites first.
Prerequisites (verify first)
Do not run any check until these pass. If one fails, stop and report it — do not
guess.
- MCP / Vivado reachable. Call
test_connection. If it fails, the Tcl
server inside Vivado is not connected on TCP:9999 — report and stop.
- A project is open with sources. Call
get_project_info and
list_source_files. If no project or no RTL sources, stop and ask the user to
open the project / point at the files.
- Top module is set (needed for elaboration-stage checks). If
get_project_info shows no top, call set_top_module only with a name the
user gave or that is unambiguous from list_source_files; otherwise ask.
- Know which stage you can reach. Syntax-stage checks need only sources.
Methodology-stage checks (
run_full_lint_check, report_methodology,
get_lint_violations, check_latches, check_fsm, check_coding_style,
check_cdc_lint, check_simulation_mismatch) require an open synthesized
design. Plan to reach that stage in Step 3 — do not call those tools before
the design is open or they will error.
Methodology (numbered, real tool calls)
Work the stages in order. Each stage is cheaper/earlier than the next; do not
skip ahead, because a syntax error makes every later check meaningless.
Step 1 — Establish the file baseline
list_source_files and (if useful) check_compile_order. A wrong compile
order produces phantom "undefined module" / black-box noise downstream;
fix ordering before trusting any later result.
- Record the file set and top module. This is the scope every later claim is
bounded to ("lint-clean" means these files, this top, nothing more).
Step 2 — Syntax-stage checks (no synthesis required)
Run the checks that work directly on source. These are fast and catch the errors
that would otherwise abort synthesis:
check_syntax (all sources) — must be clean before anything else is trustworthy.
check_compile_order — ordering / include problems.
check_black_box — undefined modules (missing files, typo'd module names, or a
genuinely intended black box / external IP).
check_port_width_mismatch — connection width mismatches at instantiation.
check_unconnected_ports — dangling/unconnected ports.
If check_syntax reports errors, STOP the lint flow here. Classify and
surface the syntax errors (Step 5 table) and do not pretend later stages are
clean — you cannot run them on broken source.
Step 3 — Reach a synthesized design for methodology checks
Most high-value RTL lint (latches, FSM health, coding style, CDC, sim/synth
mismatch) requires an elaborated/synthesized netlist.
- If a synthesized design is not already open, run synthesis. For anything beyond
a tiny design prefer the async pattern:
run_synthesis_async, then poll
get_run_status until complete (multi-minute operations must not block).
- Then
open_synthesized_design. (An already-open open_implemented_design also
satisfies the prerequisite.)
- Also pull
get_synthesis_warnings — synthesis warnings frequently are the
lint findings (inferred latch, truncation, dropped logic) and corroborate the
dedicated checks.
If synthesis fails, the failure itself is the top-priority violation: capture it,
classify it (Step 5), and stop — there is nothing to lint on a netlist that
doesn't exist.
Step 4 — Methodology / RTL-quality checks (on the open synth design)
Run the methodology suite and the targeted RTL checks:
run_full_lint_check — full syntax + methodology pass; the broad sweep.
report_methodology then get_lint_violations — the structured violation list
you will triage (each item has a check name / ID).
check_latches — inferred latches, the single most important RTL lint
signal; an unintended latch is almost always a real bug.
check_fsm — FSM encoding / unreachable-state / dead-state health.
check_coding_style — synthesis-relevant coding issues.
check_cdc_lint — first-screen clock-domain-crossing flags (hand deep CDC off).
check_simulation_mismatch — constructs that simulate differently than they
synthesize (the worst class: it works in sim, fails in hardware).
For any violation you do not understand, pull detail with
report_lint_violation_detail(violation_id=...) before deciding what to do with
it. Never triage blind.
Step 5 — Triage every violation
For each violation, read its detail and place it in exactly one bucket using
the table below. Do not batch-waive. Do not batch-ignore. One verdict per item,
each with a one-line reason.
Step 6 — Apply the smallest safe change, one class at a time
- Fixes are recommended, not silently applied. Latches, width mismatches, and
sim/synth mismatches are RTL bugs — describe the exact edit (which signal, which
always/process block, default assignment vs full case, blocking vs non-blocking)
and let the human approve before you touch source with
update_file /
replace_in_file. Use read_file_lines to ground the recommendation in the
real code.
- Waivers require a stated assumption. Only after the item is confirmed
intentional do you call
waive_lint_violation(check_name=..., reason="<why this is safe and intended>", objects=...).
The reason string is mandatory and must be a real justification, not "waived".
- Change one class per iteration (e.g. fix latches, OR waive a reviewed style
rule — not both), so the re-measure attributes cause to effect.
Step 7 — Re-measure (close the loop)
After each change class, re-run the relevant check on the current source/
netlist (re-synthesize if RTL changed) and diff the violation list. A fix is only
"done" when the violation it targeted is gone from fresh tool output and no new
violation appeared. Record before/after counts.
Classification / decision table
Map each violation to a cause and the smallest safe response. The default
verdict is FIX; WAIVE is allowed only with an explicit, true
justification; ASK when intent is unknown.
| Symptom / check |
Likely cause |
Smallest safe response |
Default verdict |
check_latches finds inferred latch |
Incomplete if/case or missing default in comb logic |
Recommend full assignment (default value / else / default:); confirm with read_file_lines |
FIX (RTL) |
check_port_width_mismatch |
Instantiation port width ≠ signal width |
Recommend resizing the signal/port; never widen blindly — verify intent |
FIX (RTL) / ASK |
check_unconnected_ports |
Dangling port |
If functionally required → FIX (connect); if intentionally unused → tie-off/objects waiver with reason |
FIX / WAIVE |
check_black_box |
Missing file, typo'd name, OR intended external IP/stub |
If missing → add file / fix check_compile_order; if intended → WAIVE with reason |
FIX / WAIVE |
check_simulation_mismatch |
Init values, #delay, sensitivity-list, X-pessimism gaps |
RTL fix — these are silent hardware bugs |
FIX (RTL) |
check_fsm unreachable/dead state |
Unhandled case / wrong reset / dead code |
Recommend handling or removing the state; do not waive a reachable hole |
FIX (RTL) |
check_coding_style violation |
Blocking/non-blocking misuse, mixed assigns, style rule |
If functional risk → FIX; if cosmetic & team-approved → WAIVE with reason |
FIX / WAIVE |
check_cdc_lint flag |
Unsynchronized crossing / missing handshake |
Hand to CDC sign-off; never waive a real crossing to clear lint |
ASK / FIX |
report_methodology / get_lint_violations generic item |
Vivado methodology rule (e.g. SYNTH-/TIMING- family) |
Read report_lint_violation_detail; fix or justify per the item |
depends → triage |
| Rule is a known false positive for this design |
Tool over-reports a safe pattern |
WAIVE the specific check_name/objects with a reason naming why it's safe |
WAIVE |
| Intent genuinely unknown |
Can't tell if the construct is deliberate |
Present the finding + options; hand back to human |
ASK |
Iteration loop & STOP conditions
LOOP:
1. Run the relevant check(s) (Step 2 / Step 4)
2. get_lint_violations -> list
3. For each item: report_lint_violation_detail -> classify (table)
4. Apply ONE change class:
- FIX (recommend RTL edit, get approval, then update_file/replace_in_file)
- WAIVE (waive_lint_violation with a real reason) [reviewed items only]
5. Re-synthesize if RTL changed; re-run the check (Step 7)
6. Diff before/after violation list
-> repeat
STOP the loop when any of these is true:
- Clean: the targeted check returns zero violations on fresh output, and
every remaining item is an explicit, justified waiver in
list_waivers. This is
the only "lint clean" you may claim — and only with the fresh output in hand.
- All remaining items need human judgment (ASK bucket): present options +
trade-offs and hand back. Do not thrash trying to auto-resolve intent.
- A fix would require unapproved RTL surgery beyond the smallest safe change
(architectural change, retiming logic, restructuring an FSM): surface the
recommendation and stop; do not silently apply it.
- No progress / oscillation: the same violation count persists or a "fix"
spawns new violations after two iterations. Stop, report the conflict, hand back.
- An upstream blocker reappears (syntax error, synthesis failure): drop back
to that stage; the lower stage owns the fix.
Safety rails (do not violate)
- No fake-pass. Never make the number green by hiding a real problem. Do
not call
set_lint_severity to downgrade a check, disable_lint_rule, or
waive_lint_violation on an item that could be a genuine bug just to clear it.
A latch, width mismatch, CDC crossing, or sim/synth mismatch is presumed real
until proven intentional.
- Waivers need a stated, true justification. Every
waive_lint_violation
call carries a reason that explains why the construct is safe and intended —
scoped with objects to the specific cell/net where possible, never a blanket
waiver of an entire check. If you cannot articulate the justification, you may
not waive it; ask the user.
- Smallest safe change first. Prefer connecting a port, fixing compile order,
or scoping a waiver over rewriting RTL. Constraint/config/style fixes before
source edits; source edits before architectural changes.
- Recommend RTL edits; don't silently apply them. Show the exact change
(file, line range from
read_file_lines, before/after) and get approval before
update_file / replace_in_file. Latch and mismatch fixes especially must be
reviewed.
- Evidence before claims. "Lint clean" / "no latches" / "violation fixed"
REQUIRES fresh output from the relevant tool after the change, on the
current source/netlist. Never infer it from "I made the edit." If RTL changed,
re-synthesize before re-checking — stale netlist results are not evidence.
- Stay in scope. Lint-triage flags timing/CDC/DRC items and hands them to the
right skill. It does not pretend a CDC waiver or a severity downgrade closes a
timing/CDC issue.
- Real tools only. Use only the SynthPilot tool names referenced here. If a
needed capability is missing, say so plainly rather than inventing a tool.
Output
Deliver a triage report, not a verdict-by-assertion:
- Scope — files (
list_source_files) + top module + the stage reached
(syntax-only vs synthesized). Every claim is bounded to this.
- Violation summary — counts by severity/check, before vs after, from
get_lint_violations / get_synthesis_warnings (fresh output, quoted/cited).
- Triage table — one row per violation:
check / ID | location | cause | verdict (FIX / WAIVE / ASK) | action taken or recommended.
- Fixes applied — only those the user approved; show before/after snippet
(
read_file_lines) and the re-measured result proving the violation cleared.
- Waivers — the current
list_waivers output, each with its justification.
Flag any waiver whose reason is weak so the human can revisit it.
- Open items / hand-offs — ASK-bucket items with options + trade-offs, and
anything routed to timing / CDC / DRC / simulation skills.
- Honest status line — e.g. "Lint clean on / at synthesis stage:
0 unwaived violations, N justified waivers (fresh
get_lint_violations output
attached)." Never state "clean" without that fresh evidence; if blocked, say
exactly what blocks it and what decision you need from the user.
1---2name: lint-triage3description: Run RTL lint / methodology checks and triage each violation into a real fix vs a justified, documented waiver. Use when the user says "lint my RTL", "code quality", "review my RTL", "check my Verilog/VHDL", "any latches / unintended latches", "clean up warnings before synthesis", "is my design lint-clean", or asks for a code-quality / methodology report on an FPGA design. Requires the SynthPilot MCP server (Xilinx Vivado running with the Tcl server connected on TCP:9999). Methodology-stage checks additionally require an open synthesized design (open_synthesized_design / open_implemented_design).4---56# Lint Triage — RTL Lint & Methodology Violation Triage78A playbook for driving SynthPilot's lint/methodology tools to find real RTL9problems, then sorting every violation into one of three buckets: **fix it**,10**waive it (with a stated justification)**, or **ask the human**. The deliverable11is a triaged report, not a green number. A lint run that is "clean" because real12violations were silenced is a failure of this skill.1314This skill follows one discipline above all: **measure → classify → fix the15smallest safe thing → re-measure**. It never invents a tool, never downgrades a16severity to hide a problem, and never claims "lint clean" without fresh tool17output proving it on the current source.1819---2021## When to use2223- User asks to "lint my RTL", "review my RTL", "check code quality", "find24 unintended latches", "clean up warnings", or "is this design lint-clean".25- Before synthesis sign-off, before a design review, or before handing RTL to a26 teammate, to catch latches, incomplete sensitivity lists, width mismatches,27 unconnected ports, blocking/non-blocking misuse, and methodology violations.28- After an RTL edit, to confirm a class of violations is actually gone (not just29 moved or masked).30- To produce a defensible waiver list — each waiver tied to an explicit reason —31 for items that are intentional and safe.3233## When NOT to use3435- **Timing closure** (WNS/TNS negative, failing setup/hold). Lint is not timing.36 Use the timing-closure skill. `check_async_reset` here surfaces *reset-path37 methodology* issues, not slack.38- **Pure CDC sign-off** (metastability, gray-coding, handshake correctness).39 `check_cdc_lint` / `report_cdc` are a first screen only; deep CDC analysis is a40 separate playbook. Lint-triage flags CDC violations and hands them off.41- **Functional verification** (does the logic compute the right answer). That is42 simulation (`sim_*`), not lint. Lint cannot tell you a correct-looking design43 is functionally wrong.44- **DRC / route sign-off** (`report_drc` on a placed/routed design). Different45 stage, different tool.46- No project is open / Vivado is not reachable. Resolve Prerequisites first.4748---4950## Prerequisites (verify first)5152Do not run any check until these pass. If one fails, stop and report it — do not53guess.54551. **MCP / Vivado reachable.** Call `test_connection`. If it fails, the Tcl56 server inside Vivado is not connected on TCP:9999 — report and stop.572. **A project is open with sources.** Call `get_project_info` and58 `list_source_files`. If no project or no RTL sources, stop and ask the user to59 open the project / point at the files.603. **Top module is set** (needed for elaboration-stage checks). If61 `get_project_info` shows no top, call `set_top_module` only with a name the62 user gave or that is unambiguous from `list_source_files`; otherwise ask.634. **Know which stage you can reach.** Syntax-stage checks need only sources.64 Methodology-stage checks (`run_full_lint_check`, `report_methodology`,65 `get_lint_violations`, `check_latches`, `check_fsm`, `check_coding_style`,66 `check_cdc_lint`, `check_simulation_mismatch`) require an **open synthesized67 design**. Plan to reach that stage in Step 3 — do not call those tools before68 the design is open or they will error.6970---7172## Methodology (numbered, real tool calls)7374Work the stages in order. Each stage is cheaper/earlier than the next; do not75skip ahead, because a syntax error makes every later check meaningless.7677### Step 1 — Establish the file baseline7879- `list_source_files` and (if useful) `check_compile_order`. A wrong compile80 order produces phantom "undefined module" / black-box noise downstream;81 fix ordering before trusting any later result.82- Record the file set and top module. This is the scope every later claim is83 bounded to ("lint-clean" means *these files, this top*, nothing more).8485### Step 2 — Syntax-stage checks (no synthesis required)8687Run the checks that work directly on source. These are fast and catch the errors88that would otherwise abort synthesis:8990- `check_syntax` (all sources) — must be clean before anything else is trustworthy.91- `check_compile_order` — ordering / include problems.92- `check_black_box` — undefined modules (missing files, typo'd module names, or a93 genuinely intended black box / external IP).94- `check_port_width_mismatch` — connection width mismatches at instantiation.95- `check_unconnected_ports` — dangling/unconnected ports.9697If `check_syntax` reports errors, **STOP the lint flow here**. Classify and98surface the syntax errors (Step 5 table) and do not pretend later stages are99clean — you cannot run them on broken source.100101### Step 3 — Reach a synthesized design for methodology checks102103Most high-value RTL lint (latches, FSM health, coding style, CDC, sim/synth104mismatch) requires an elaborated/synthesized netlist.105106- If a synthesized design is not already open, run synthesis. For anything beyond107 a tiny design prefer the async pattern: `run_synthesis_async`, then poll108 `get_run_status` until complete (multi-minute operations must not block).109- Then `open_synthesized_design`. (An already-open `open_implemented_design` also110 satisfies the prerequisite.)111- Also pull `get_synthesis_warnings` — synthesis warnings frequently *are* the112 lint findings (inferred latch, truncation, dropped logic) and corroborate the113 dedicated checks.114115If synthesis fails, the failure itself is the top-priority violation: capture it,116classify it (Step 5), and stop — there is nothing to lint on a netlist that117doesn't exist.118119### Step 4 — Methodology / RTL-quality checks (on the open synth design)120121Run the methodology suite and the targeted RTL checks:122123- `run_full_lint_check` — full syntax + methodology pass; the broad sweep.124- `report_methodology` then `get_lint_violations` — the structured violation list125 you will triage (each item has a check name / ID).126- `check_latches` — **inferred latches**, the single most important RTL lint127 signal; an unintended latch is almost always a real bug.128- `check_fsm` — FSM encoding / unreachable-state / dead-state health.129- `check_coding_style` — synthesis-relevant coding issues.130- `check_cdc_lint` — first-screen clock-domain-crossing flags (hand deep CDC off).131- `check_simulation_mismatch` — constructs that simulate differently than they132 synthesize (the worst class: it works in sim, fails in hardware).133134For any violation you do not understand, pull detail with135`report_lint_violation_detail(violation_id=...)` before deciding what to do with136it. Never triage blind.137138### Step 5 — Triage every violation139140For **each** violation, read its detail and place it in exactly one bucket using141the table below. Do not batch-waive. Do not batch-ignore. One verdict per item,142each with a one-line reason.143144### Step 6 — Apply the smallest safe change, one class at a time145146- **Fixes are recommended, not silently applied.** Latches, width mismatches, and147 sim/synth mismatches are RTL bugs — describe the exact edit (which signal, which148 always/process block, default assignment vs full case, blocking vs non-blocking)149 and let the human approve before you touch source with `update_file` /150 `replace_in_file`. Use `read_file_lines` to ground the recommendation in the151 real code.152- **Waivers require a stated assumption.** Only after the item is confirmed153 intentional do you call154 `waive_lint_violation(check_name=..., reason="<why this is safe and intended>", objects=...)`.155 The reason string is mandatory and must be a real justification, not "waived".156- Change **one class per iteration** (e.g. fix latches, OR waive a reviewed style157 rule — not both), so the re-measure attributes cause to effect.158159### Step 7 — Re-measure (close the loop)160161After each change class, re-run the relevant check on the **current** source/162netlist (re-synthesize if RTL changed) and diff the violation list. A fix is only163"done" when the violation it targeted is gone from fresh tool output and no new164violation appeared. Record before/after counts.165166---167168## Classification / decision table169170Map each violation to a cause and the **smallest safe** response. The default171verdict is **FIX**; **WAIVE** is allowed only with an explicit, true172justification; **ASK** when intent is unknown.173174| Symptom / check | Likely cause | Smallest safe response | Default verdict |175|-----------------------------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------|-----------------|176| `check_latches` finds inferred latch | Incomplete `if`/`case` or missing default in comb logic | Recommend full assignment (default value / `else` / `default:`); confirm with `read_file_lines` | **FIX (RTL)** |177| `check_port_width_mismatch` | Instantiation port width ≠ signal width | Recommend resizing the signal/port; never widen blindly — verify intent | **FIX (RTL)** / ASK |178| `check_unconnected_ports` | Dangling port | If functionally required → FIX (connect); if intentionally unused → tie-off/`objects` waiver with reason | FIX / WAIVE |179| `check_black_box` | Missing file, typo'd name, OR intended external IP/stub | If missing → add file / fix `check_compile_order`; if intended → WAIVE with reason | FIX / WAIVE |180| `check_simulation_mismatch` | Init values, `#delay`, sensitivity-list, X-pessimism gaps | RTL fix — these are silent hardware bugs | **FIX (RTL)** |181| `check_fsm` unreachable/dead state | Unhandled case / wrong reset / dead code | Recommend handling or removing the state; do not waive a reachable hole | **FIX (RTL)** |182| `check_coding_style` violation | Blocking/non-blocking misuse, mixed assigns, style rule | If functional risk → FIX; if cosmetic & team-approved → WAIVE with reason | FIX / WAIVE |183| `check_cdc_lint` flag | Unsynchronized crossing / missing handshake | Hand to CDC sign-off; **never** waive a real crossing to clear lint | **ASK / FIX** |184| `report_methodology` / `get_lint_violations` generic item | Vivado methodology rule (e.g. SYNTH-/TIMING- family) | Read `report_lint_violation_detail`; fix or justify per the item | depends → triage |185| Rule is a **known false positive** for this design | Tool over-reports a safe pattern | WAIVE the specific `check_name`/`objects` with a reason naming why it's safe | **WAIVE** |186| Intent genuinely unknown | Can't tell if the construct is deliberate | Present the finding + options; hand back to human | **ASK** |187188---189190## Iteration loop & STOP conditions191192```193LOOP:194 1. Run the relevant check(s) (Step 2 / Step 4)195 2. get_lint_violations -> list196 3. For each item: report_lint_violation_detail -> classify (table)197 4. Apply ONE change class:198 - FIX (recommend RTL edit, get approval, then update_file/replace_in_file)199 - WAIVE (waive_lint_violation with a real reason) [reviewed items only]200 5. Re-synthesize if RTL changed; re-run the check (Step 7)201 6. Diff before/after violation list202 -> repeat203```204205**STOP the loop when any of these is true:**206207- **Clean:** the targeted check returns zero violations on **fresh** output, and208 every remaining item is an explicit, justified waiver in `list_waivers`. This is209 the only "lint clean" you may claim — and only with the fresh output in hand.210- **All remaining items need human judgment** (ASK bucket): present options +211 trade-offs and hand back. Do not thrash trying to auto-resolve intent.212- **A fix would require unapproved RTL surgery** beyond the smallest safe change213 (architectural change, retiming logic, restructuring an FSM): surface the214 recommendation and stop; do not silently apply it.215- **No progress / oscillation:** the same violation count persists or a "fix"216 spawns new violations after two iterations. Stop, report the conflict, hand back.217- **An upstream blocker reappears** (syntax error, synthesis failure): drop back218 to that stage; the lower stage owns the fix.219220---221222## Safety rails (do not violate)223224- **No fake-pass.** Never make the number green by hiding a real problem. Do225 **not** call `set_lint_severity` to downgrade a check, `disable_lint_rule`, or226 `waive_lint_violation` on an item that could be a genuine bug just to clear it.227 A latch, width mismatch, CDC crossing, or sim/synth mismatch is presumed real228 until proven intentional.229- **Waivers need a stated, true justification.** Every `waive_lint_violation`230 call carries a `reason` that explains *why the construct is safe and intended* —231 scoped with `objects` to the specific cell/net where possible, never a blanket232 waiver of an entire check. If you cannot articulate the justification, you may233 not waive it; ask the user.234- **Smallest safe change first.** Prefer connecting a port, fixing compile order,235 or scoping a waiver over rewriting RTL. Constraint/config/style fixes before236 source edits; source edits before architectural changes.237- **Recommend RTL edits; don't silently apply them.** Show the exact change238 (file, line range from `read_file_lines`, before/after) and get approval before239 `update_file` / `replace_in_file`. Latch and mismatch fixes especially must be240 reviewed.241- **Evidence before claims.** "Lint clean" / "no latches" / "violation fixed"242 REQUIRES fresh output from the relevant tool **after** the change, on the243 current source/netlist. Never infer it from "I made the edit." If RTL changed,244 re-synthesize before re-checking — stale netlist results are not evidence.245- **Stay in scope.** Lint-triage flags timing/CDC/DRC items and hands them to the246 right skill. It does not pretend a CDC waiver or a severity downgrade closes a247 timing/CDC issue.248- **Real tools only.** Use only the SynthPilot tool names referenced here. If a249 needed capability is missing, say so plainly rather than inventing a tool.250251---252253## Output254255Deliver a triage report, not a verdict-by-assertion:2562571. **Scope** — files (`list_source_files`) + top module + the stage reached258 (syntax-only vs synthesized). Every claim is bounded to this.2592. **Violation summary** — counts by severity/check, before vs after, from260 `get_lint_violations` / `get_synthesis_warnings` (fresh output, quoted/cited).2613. **Triage table** — one row per violation: `check / ID | location | cause |262 verdict (FIX / WAIVE / ASK) | action taken or recommended`.2634. **Fixes applied** — only those the user approved; show before/after snippet264 (`read_file_lines`) and the re-measured result proving the violation cleared.2655. **Waivers** — the current `list_waivers` output, each with its justification.266 Flag any waiver whose reason is weak so the human can revisit it.2676. **Open items / hand-offs** — ASK-bucket items with options + trade-offs, and268 anything routed to timing / CDC / DRC / simulation skills.2697. **Honest status line** — e.g. "Lint clean on <files>/<top> at synthesis stage:270 0 unwaived violations, N justified waivers (fresh `get_lint_violations` output271 attached)." Never state "clean" without that fresh evidence; if blocked, say272 exactly what blocks it and what decision you need from the user.