diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a503eb17f..5d54ec4cf 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -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 diff --git a/docs/languages/local-import-scoping.md b/docs/languages/local-import-scoping.md index 5e2b15a46..e34d8d4a4 100644 --- a/docs/languages/local-import-scoping.md +++ b/docs/languages/local-import-scoping.md @@ -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 diff --git a/gitnexus/bench/lexical-binding-provenance/README.md b/gitnexus/bench/lexical-binding-provenance/README.md index 7038fb8d1..79ed1e535 100644 --- a/gitnexus/bench/lexical-binding-provenance/README.md +++ b/gitnexus/bench/lexical-binding-provenance/README.md @@ -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.