A suite of focused code-review skills for Tessl Agent and GitHub Actions review workflows (`tessl change review`). Each review lens is its own skill, so a workflow can invoke one lens or several. Fork and tune any skill for your own repository.
—
—
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Each pattern fails the cold-reader test, the from-scratch test, or both. The fix is always a code change, never a comment.
oldFooHandler or legacyFoo is
only acceptable when a current foo exists alongside it. A lone legacyFoo
with no foo is just foo.Record<string, X>, Map<string, Y>, or plain
string-tuple arrays hide what the key means and what an entry represents. Fix:
name the types (type FixtureName = string), wrap the relationship in a
struct so the key has a name, or eliminate the helper that produced the opaque
shape so the caller iterates the keyed structure where the key's role is
obvious.process(input, mode) where
mode is an untyped tag, or a function returning a generic map tagged with a
source flag the caller re-branches on. Fix: narrow parameter types to a
literal union, split the function so each branch has a precise name, or push
the work into the caller so the context lives in the loop.lib/ means shared,
not "where this file ended up": one consumer means colocate, multiple
consumers means a shared module is right. Fix: inline; if the caller's body
gets unwieldy, use a file-local private helper named in the caller's
vocabulary rather than a separate module.doThingInternal vs
doThing when the wrapper is gone; an interface with one implementation and
no other planned). If the reason for the split is gone, collapse it.Opacity is fundamental, not sediment, in a few cases — do not flag these:
Result<T, E> is opaque on purpose.dot(a, b) need not spell out its arguments.