CtrlK
BlogDocsLog inGet started
Tessl Logo

semantic-bug-detector

Detects logical and semantic bugs by understanding program intent — catches issues that syntax-only tools miss. Use when static analysis has already run and found nothing, when the user reports incorrect behavior but no crash, or when reviewing algorithmic code for correctness.

Install with Tessl CLI

npx tessl i github:santosomar/general-secure-coding-agent-skills --skill semantic-bug-detector
What are skills?

96

Quality

95%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SKILL.md
Review
Evals

Semantic Bug Detector

Find bugs where the code is syntactically fine and type-correct but does the wrong thing. → static-bug-detector catches provable errors; this skill catches violated intent.

The intent question

You cannot find a semantic bug without a model of intent. For each function, establish intent from (in order of reliability):

  1. A failing test (the assertion is the intent)
  2. A docstring / type signature / name that makes a contract (sort should sort; retry(n) should try at most n+1 times)
  3. An algorithm name (if the function is called binarySearch, you know what invariants it should hold)
  4. Surrounding usage (what do callers assume about the return value?)

If you have none of these, you are not detecting bugs — you are generating hypotheses.

Signal catalog — semantic smells that correlate with real bugs

SmellWhat it looks likeWhy it's suspicious
Copy-paste-mutate asymmetryTwo near-identical blocks differ in one tokenThe one token was supposed to change in both — or neither
Condition-action mismatchif x > limit: ... x — the condition checks one variable, the body mutates anotherThe variable in the condition is probably the one the author meant to modify
Loop variable ignoredfor x in items: but body never uses xEither the loop is a repeat n times — or author meant to use x
Inverted boundarySorted-collection logic that uses < where the surrounding comparisons use <= (or vice versa)Boundary consistency is algorithmic; inconsistency is usually a bug
Mutation during iterationModifying the collection being iteratedSkipped elements / ConcurrentModificationException — correct use is rare
State set, never readField written in 3 places, read in 0Either dead state — or the read is the bug (someone forgot to check it)
Integer division in float ctxa / b where a, b are ints but result feeds a float opPython 2 habits, C integer division — silent truncation
Exception changes control flow silentlytry: ...; except: pass followed by code that assumes try succeededThe swallow masks the failure; the following code operates on garbage

Ranking

Unlike static bugs, semantic findings are hypotheses until confirmed. Rank by how cheaply they can be confirmed:

  1. Can write a 3-line test → write it, then it's confirmed or killed
  2. Named algorithm with known invariant → check invariant inline
  3. Only evidence is asymmetry → flag as needs-review, don't assert

FP suppression

  • Copy-paste asymmetry: check git blame. If both blocks were written in the same commit, high confidence. If they diverged over time via separate edits, low — probably intentional.
  • Loop variable ignored: check if _ naming convention would apply. for _ in range(n) is intentional; for item in items with no item reference is suspicious.
  • Inverted boundary: check the domain. Half-open intervals [a, b) legitimately mix <= and <.

Worked example

Code:

def apply_discounts(cart, coupons):
    total = sum(item.price for item in cart)
    for coupon in coupons:
        if coupon.type == "percent":
            total -= total * coupon.value / 100
        elif coupon.type == "fixed":
            total -= total * coupon.value / 100     # line 7
    return max(total, 0)

Detection: Copy-paste-mutate asymmetry. Lines 5 and 7 are identical, but the branch conditions differ. The fixed branch should subtract coupon.value, not total * coupon.value / 100.

Confirmation: Write a test — cart total 100, one fixed coupon value 10 → expect 90, get 90. Wait — it passes? Re-check: 100 - 100 * 10 / 100 = 90. The bug is masked at total=100. Try total=50: expect 40, get 45. Confirmed.

Finding:

pricing.py:7  COPY_PASTE_ASYMMETRY  confidence=high (confirmed by test)
  Fixed-coupon branch applies percent formula. At total=50, fixed coupon of
  $10 discounts $5 instead of $10.

  Fix: `total -= coupon.value`

  Confirming test:
    cart(total=50), fixed_coupon(10) → assert total == 40

Edge cases

  • The smell is the spec: Sometimes the "asymmetry" is intentional domain logic you don't understand. If git blame shows different authors and the code has survived multiple releases, the prior is that it's correct.
  • Performance code: state set, never read in a hot loop might be cache prefetching. mutation during iteration might be a carefully designed in-place algorithm. Lower confidence for anything marked // PERF.
  • Generated code: Often full of semantic smells that are safe by construction. Skip.

Do not

  • Do not report a semantic finding with the same certainty as a static finding. Say "suspicious," not "bug," until confirmed.
  • Do not assume the intent from the function name alone. normalize() means fifteen different things.
  • Do not report the same underlying bug in every function it propagates to. One root, one finding.

Output format

<file>:<line>  <SMELL_NAME>  confidence=<hypothesis|confirmed>
  <what the code does vs. what intent suggests it should do>
  <confirming evidence or test, or "needs manual review">
  <proposed fix if confident>
Repository
santosomar/general-secure-coding-agent-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.