docs(routes): describe wrapper fallback, barrel and recall boundaries

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Gergo Magyar 2026-10-19 19:12:27 +00:00
parent d3c3572768
commit 528ea1478b
3 changed files with 40 additions and 5 deletions

View file

@ -220,6 +220,11 @@ an unproven argument, or a reassigned parameter establishes nothing, and a helpe
with no recorded call site is read as written, so an unknown mount path still
suppresses its router's standalone paths.
Fetch-wrapper facts use the same lexical identities. The shared resolver in
`route-extractors/fetch-wrapper-index.ts` names no language, but it applies
ECMAScript `ResolveExport` rules to the re-export facts it receives: only
providers whose modules link that way implement the re-export hook.
A standalone router retains its local paths. A known dynamic mount suppresses
that fallback, while independently proven static mounts remain available. Cycles
terminate, and exceeding the expansion budget omits the affected mount component

View file

@ -154,10 +154,15 @@ Bare wrapper calls and forwarded calls resolve declaration or import identity
before using name fallback. Relative imports, renamed imports, tsconfig aliases,
and workspace imports use the project module resolver. A known local
non-wrapper, a different resolved target, or an ambiguous target blocks fallback.
An unresolved name can fall back only when exactly one distinct definition has
that name across all candidates, including non-wrappers, and that definition is
a proven wrapper. This fallback is an analyzer recovery heuristic; it does not
prove lexical identity. Explicit `fetchWrappers` configuration takes precedence
An unresolved name can fall back only when exactly one distinct definition can
be the target, including non-wrappers, and that definition is a proven wrapper.
For an import the resolver cannot follow, the candidates are module-level
functions exported under the imported name; for an undeclared global, they are
top-level functions of that name. Nested and unexported helpers are never
candidates. This fallback is an analyzer recovery heuristic; it does not prove
lexical identity. A function whose binding is reassigned in its file, including
through `export { request as send }; request = other;` or a later
`var request = …` initializer, proves no wrapper in importing files either. Explicit `fetchWrappers` configuration takes precedence
over automatic inference, including for names shadowed by local parameters; member
calls retain their existing matching rules. See the
[wrapper consumer integration tests](../../gitnexus/test/integration/resolvers/fetch-wrapper-consumers.test.ts)
@ -172,7 +177,22 @@ body declarations; a rest parameter alone is not a parameter expression. The
[lexical binding tests](../../gitnexus/test/unit/route-lexical-bindings.test.ts)
pin this conservative boundary. If scope extraction fails, scope-dependent HTTP
facts are omitted and the existing scope-extraction failure remains visible;
unrelated structural extraction continues.
unrelated structural extraction continues. A failing HTTP hook drops only that
file's HTTP facts. Either way the file's function names are still recorded, so
name fallback elsewhere declines instead of treating another definition as
unique.
Barrels follow ECMAScript `ResolveExport`. A local or named export shadows
`export *`, star exports never carry `default`, and a name that two star-exported
modules export as different bindings is ambiguous, whether or not either is a
wrapper. Two export names of one declaration are one binding.
Some recall is given up deliberately. A helper that conditionally rebinds its
parameter, as in `if (!app) { var app = express(); }`, loses that parameter's
provenance: the initialized `var` is a write. A dynamic-import shim such as
`(...args) => import('node-fetch').then(...)` is not platform fetch evidence. A
write to the URL parameter clears URL forwarding. Calls inside recovered syntax
are still resolved, but nothing else inside an `ERROR` node is trusted.
Vue's explicit JS/JSX script requires an additional bounded semantic parse because
the worker's structural tree uses TypeScript. That parse runs inside the real

View file

@ -140,3 +140,13 @@ Corpus SHA-256:
The final corpus differs from the first capture only in formatting of the
standalone ownership probe. Both final exports use this identical corpus and
the baseline remains the untouched revision above.
## Committed results
`results/baseline-scaling.json`, `results/candidate-scaling.json` and
`results/semantic-diff.json` are point-in-time reports. Each records the revision
it measured (`source.revision`, or the export revisions in the comparison), so a
later commit that changes no measured file keeps them valid. Regenerate all three
with the commands above after changing a measured file. Host load during a run is
described only by the report's environment note; any sampled load log stays with
the operator.