Build1 distinct publisher3 min readPublished
Packs die on unexpected keyword arguments more often than on missing names, so binding calls against upstream signatures looks like the obvious next rule. Run it over twenty real packs and it fires hardest on the ones doing compatibility properly.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Binding a call is a different operation from looking up a name, and that is where the rule got expensive. Presence checking builds the set of names bound at module scope from the AST and diffs it against what the pack references [3]. Call binding parses the upstream module at whatever git ref you care about, reads the real parameter list, and tries to match every call site the pack makes against it; a call that cannot bind raises TypeError the moment it runs [6].
The first failure is scope. A pack imports `calculate_weight` from `comfy.lora` and then defines its own `calculate_weight` in the same file, so the bare call resolves to the local one. The rule resolved it against upstream and reported a hard break on working code, and any rebinding does the same thing: a local def, a function parameter, a loop target, a walrus, a later import of the same name [8]. The patch is a conservative file-wide shadow set [9].
The design decision underneath is the part worth stealing. The author deliberately did not tighten the import checks to match, because a presence-check false positive is a warning somebody glances at and dismisses, while a call-binding false positive is a red build; same codebase, two tolerances, picked by what the wrong answer costs [10].
The second failure is worse, because it selects for care. One pack sets a flag from `hasattr(comfy.model_prefetch, "GRAPH_MODULES")` and calls `cleanup_prefetched_modules` with the arity that matches your installed version. At any given ref one branch binds and the other is dead code, and the rule read the dead branch and graded the pack WILL BREAK [11]. Dead code cannot raise the TypeError the rule was measuring. The author's line is that a lint which taxes the careful and ignores the careless is worse than no lint [12]. The heuristic that fixes it: if a sibling call to the same function in the same file binds, treat the failing one as a shim, report it, never fail the build, and let `except TypeError` soften a call the way `except ImportError` already softens an import [13].
The validation run was 20 cloned packs, 1,273 Python files, 1,116 call sites into `comfy.*`, 10 monkeypatches, every hit hand-verified against pack source and ComfyUI's git history [7]. Two findings survived, both true, with 18 of 20 packs silent [14]. That is roughly 0.18 percent of call sites, about one per 558 [17], and 10 percent of the corpus flagged [18]. For that rate to transfer you would need your pack mix and your pinned upstream ref to look like this sample; against an older pin the same rule reports different code.
The interesting finding is in ComfyUI-Easy-Use, at 2.7k stars, whose BrushNet path passes `scaled_fp8` to `comfy.ops.pick_operations`. That parameter was removed in commit 43071e3de, PR #11000, in December 2025; v0.3.77 is the last release that accepts it and v0.4.0 the first that does not [15]. The post then stops mid-sentence, at the moment the author goes to file the bug and finds an existing issue [16], so the public record does not say whether the tool found anything the tracker did not already know.
Ranked by verification strength, evidence, and original report placement.
Before release the author cloned the 20 most popular ComfyUI node packs, ran the new rules against origin/master, and hand-verified every hit against both pack source and ComfyUI's git history, covering 1,273 Python files, 1,116 call sites into comfy.*, and 10 monkeypatches.
The post's account ends mid-sentence, at the point where the author goes to file the finding and finds an existing issue numbered in the 9s.
The author shipped a tool that predicts which ComfyUI custom nodes will break on the next git pull; its original question was whether every name a pack imports still exists upstream.
ComfyUI's comfy.* modules are internal, with no deprecation policy, no __all__ and no shim; packs import from them anyway because there is no other way to hook the sampler or patch a model.
The presence check works by building the set of names bound at module scope from the AST and diffing it against what the pack references.
An example of the failure static analysis handles well: ImportError: cannot import name 'precompute_freqs_cis' from 'comfy.ldm.lightricks.model'.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 28, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
build
A cache hit is a quota refund: semantic caching with trigrams and no vector database1 distinct publisher
build
Stop timing your GraphQL tests and start counting loader calls1 distinct publisher
build
Agent memory rots by accumulation, and the missing primitive is a supersession key1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Checkable where it counts, unchecked everywhere else
The one finding that matters comes with coordinates — commit 43071e3de, PR #11000, last-good v0.3.77, first-broken v0.4.0, issue #991 — and anyone with a git clone can confirm or demolish it in twenty minutes. The scaffolding around it cannot be confirmed that way: 1,273 files, 1,116 call sites, ten monkeypatches, two hits, all hand-verified by the person whose tool produced them, on dev.to, with no editor between claim and page. The weakest link is the premise, that TypeErrors now dominate the tracker, offered as three tracebacks and an impression.
The tool has a release; the bug has users
For comfy-import-guard itself the record is a release and nothing more: no installs, no issues, no second maintainer running it in CI. The adoption in this story belongs to what the tool was pointed at — twenty of the most popular packs, one of them at 2.7k stars, a December 2025 upstream removal that shipped in v0.4.0, and an issue open four months with users trading a workaround. That is real-world exposure to the problem, not uptake of the answer.
Talked down, not up
A launch post that spends its middle third on the two classes of correct code its own rule condemned, then admits the single real find was already known and reframes the contribution as 'we attached a commit and a version boundary to it', is arguing against its own marketing. The numbers cut the same way: two hits per 1,116 call sites is a thin yield, and the author volunteers it as the metric to judge him on.
The maker is the only witness
The post ends with an install command, which tells you what it is for. Every count that makes the rule look disciplined was produced and checked by the person selling the rule, and the pack he names as broken is a competitor for nobody's attention but his own credibility. Against that: he names the pack his rule mistreated, publishes the tolerance asymmetry as a judgement call rather than a feature, and calls a lint that taxes careful maintainers worse than no lint. The interest is plain and worn openly, which is not the same as absent.
Firm on one break, soft on the ecosystem
Split the story and the confidence splits with it. That ComfyUI-Easy-Use's BrushNet path dies above v0.4.0, and that the popular workaround is unsafe below it, rests on named artefacts and a corroborating open issue — call that solid. How often signature drift breaks packs, whether 0.18 percent is a good hit rate, and whether other version-probing packs behave like this one, rest on one afternoon, twenty repositories and one person's judgement with nobody checking behind him.