Problem
codeanalyzer/entrypoints/rules.py accepts exactly one matcher kind under heuristics: —
decorators — and rejects unknown keys by design (_TOP_LEVEL_KEYS, and the comment at rules.py:22:
blocks not implemented are "deliberately absent here rather than accepted-and-ignored, so a user file
using them fails loudly instead of loading clean and doing nothing").
codeanalyzer-typescript is adding a second matcher kind to the same block, heuristics.calls, because
its ecosystem declares entrypoints by call as often as by decorator — Express, Koa and Fastify are
app.get('/p', handler), not @Get('/p'). Design and rationale:
codeanalyzer-typescript docs/design/specs/entrypoint-detection.md,
section "The heuristic tier".
The semantics are the ones #185 defined — written spelling, no resolution, runs on every node
regardless of frameworks_detected, confidence: heuristic forced by the loader, runs last, never
doubles a record a framework rule made — applied to a call expression's callee instead of a
decorator. Same tier, same engine, one more shape.
Consequence today: a rules file shared between the two analyzers that contains heuristics.calls is a
hard error in python. That is the loader working as intended, which is exactly why this needs a
decision rather than a workaround.
Scope boundary
Loader acceptance only. Python does not need to act on calls: — it has no call-declared
entrypoint frameworks in its shipped ruleset.
Not in scope: implementing a call-site matcher in python.
Goals
Caveats and known risks
- Accepted-and-ignored is the thing
rules.py:22 argues against, and rightly. The distinction
here: calls: is not an unimplemented python feature a user might be relying on — it is a matcher
kind that has no python meaning. Validating its shape while not acting on it keeps a malformed
rule loud without pretending python matches calls. Worth stating in the code comment, so the next
reader does not see it as an exception to the rule.
- If python ever grows a call-declared framework worth shipping rules for, the key is already there.
Definition of done
- The shared-format test loads a file with both keys and asserts python produced entrypoints only
from decorators
- A
heuristics.calls entry with a malformed shape still raises RulesError
- An unknown key under
heuristics still raises RulesError
Problem
codeanalyzer/entrypoints/rules.pyaccepts exactly one matcher kind underheuristics:—decorators— and rejects unknown keys by design (_TOP_LEVEL_KEYS, and the comment atrules.py:22:blocks not implemented are "deliberately absent here rather than accepted-and-ignored, so a user file
using them fails loudly instead of loading clean and doing nothing").
codeanalyzer-typescript is adding a second matcher kind to the same block,
heuristics.calls, becauseits ecosystem declares entrypoints by call as often as by decorator — Express, Koa and Fastify are
app.get('/p', handler), not@Get('/p'). Design and rationale:codeanalyzer-typescript
docs/design/specs/entrypoint-detection.md,section "The heuristic tier".
The semantics are the ones #185 defined — written spelling, no resolution, runs on every node
regardless of
frameworks_detected,confidence: heuristicforced by the loader, runs last, neverdoubles a record a framework rule made — applied to a call expression's callee instead of a
decorator. Same tier, same engine, one more shape.
Consequence today: a rules file shared between the two analyzers that contains
heuristics.callsis ahard error in python. That is the loader working as intended, which is exactly why this needs a
decision rather than a workaround.
Scope boundary
Loader acceptance only. Python does not need to act on
calls:— it has no call-declaredentrypoint frameworks in its shipped ruleset.
Not in scope: implementing a call-site matcher in python.
Goals
heuristics.callsis a known key: validated for shape (a list of rules withid,match, andthe same optional
route/methodsspec asdecorators, plushandler), then ignoredheuristics.decoratorsandheuristics.callsloads cleanheuristics.<anything else>still fails loudly, so the "no silent no-ops" property is keptCaveats and known risks
rules.py:22argues against, and rightly. The distinctionhere:
calls:is not an unimplemented python feature a user might be relying on — it is a matcherkind that has no python meaning. Validating its shape while not acting on it keeps a malformed
rule loud without pretending python matches calls. Worth stating in the code comment, so the next
reader does not see it as an exception to the rule.
Definition of done
from
decoratorsheuristics.callsentry with a malformed shape still raisesRulesErrorheuristicsstill raisesRulesError