User report of this issue
Context
Created by Roadmapper build issue autrun-dj1c8v8ke914-a39f3d3eec on 2026-06-08. ADR 0373 superseded the attempted async-function declined-runner bridge retirement because rejecting route-ineligible async functions broke current async semantics. docs/plans/bytecode-proof-manifest.json now keeps E5b/E5d async-function runner anchors as classified open residue.
Scope
Pick one bounded route-parity slice that reduces async-function declined-runner reliance without replacing fallback execution with rejection. Keep terminal dynamic residue and ordinary sync/class/sync-generator runner owners separate.
Proof Shape
Update docs/plans/bytecode-proof-manifest.json, docs/plans/bytecode-burndown-checklist.md, and focused async-function route/fallback tests together. The proof must show declined async bodies still complete through the classified legacy runner unless the exact shape is semantically owned by the resumable unified route.
Investigation
Blast Radius
- src/Asynkron.JsEngine/Ast/TypedAstEvaluator.AsyncFunctionInvoker.cs - owns async-function resumable route attempts, classified fallback runner construction, and should thread strictness into eligibility.
- src/Asynkron.JsEngine/Execution/UnifiedBytecode/UnifiedBytecodeProductionEligibility.cs - owns the descriptor-backed block-scoped function declaration decline gate and activation descriptor.
- src/Asynkron.JsEngine/Execution/UnifiedBytecode/UnifiedBytecodeVirtualMachine.cs - already has DeclareFunction handling; inspect only if the strict route exposes missing declaration-environment behavior.
- tests/Asynkron.JsEngine.Tests/AsyncAwaitTests.cs - contains the current strict block-function fallback pins and the nearby sloppy fallback completion pin.
- tests/Asynkron.JsEngine.Tests/BytecodeProofManifestTests.cs - validates E5b/E5d manifest shape and may need the new proof row accounted for.
- docs/plans/bytecode-proof-manifest.json - source of the E5b/E5d async declined-runner proof rows; add the new route proof without retiring the source-presence residue.
- docs/plans/bytecode-burndown-checklist.md - human checklist must match the manifest’s narrowed async-function route/fallback boundary.
Dependencies
- ADR 0373 is the controlling contract: route-ineligible async functions must complete through the classified legacy runner, not reject.
- The existing
E5-async-function-declined-body-runner-still-present proof should remain open/source-present after this slice.
- No human decision is needed.
User Stories
Story 1: As a runtime maintainer, I want one exact async-function body shape to route through resumable unified bytecode, so that E5 async declined-runner residue shrinks without changing fallback semantics.
Story 2: As a JavaScript semantics reviewer, I want unsupported async-function bodies to keep completing through the classified legacy runner, so that currently valid async programs do not reject or hang.
Approach
- Use the narrow candidate slice: strict async-function block-scoped function declarations that do not need sloppy Annex B var-style hoisting or unowned activation-capture behavior.
- Compute/pass
IsStrict into the async-function UnifiedBytecodeProductionActivationDescriptor before EvaluateResumable.
- Narrow the descriptor-backed
FunctionDeclarationInstruction resumable decline so the strict async-owned shape can route, while sloppy/Annex B, captured-activation, dynamic, and terminal residue shapes stay declined.
- Convert or add focused async tests: one strict route-hit proof should assert
unified-bytecode-resumable-async-fast-path func=run and no classified-async-function-declined-body-runner-residue; one nearby unsupported case should still resolve through the classified fallback.
- Add the corresponding runtime proof row to the manifest and update the checklist wording. Keep E5b/E5d runner source-presence/allowlist rows open.
Risks
- Broadly admitting all descriptor-backed block declarations would accidentally include sloppy Annex B or capture cases.
- Treating this as runner retirement would violate ADR 0373; the classified async fallback helper must remain until every declined shape is owned.
- Async settlement tests can pass incorrectly if promises are not deterministically drained; keep the focused async timeout pattern.
Additional quality gates
- Async fallback preservation - declined async bodies must still complete through
classified-async-function-declined-body-runner-residue unless the exact source shape routes.
- No rejection-based retirement - do not replace fallback completion with explicit rejection.
- Owner separation - do not fold terminal dynamic residue or ordinary sync/class/sync-generator runner owners into this async-function slice.
Recommended Labels
- task
- bytecode
- area/runtime
- unified-bytecode
- priority: medium
- size:M
Build Reasoning Effort
High. The code change is narrow, but the correctness boundary crosses async promise settlement, strict block declaration semantics, and manifest source-presence ratchets. Build should avoid broad admission and prove both the new route and the preserved fallback neighbor.
Acceptance Criteria (Refined)
AC-1: A strict async-function block-scoped function declaration resolves correctly through the resumable async route and logs unified-bytecode-resumable-async-fast-path func=run.
AC-2: A nearby unsupported async-function block declaration shape still resolves through classified-async-function-declined-body-runner-residue and does not log the resumable async fast path.
AC-3: CreateClassifiedAsyncDeclinedBodyRunner remains source-present and classified in the E5b/E5d manifest rows.
AC-4: docs/plans/bytecode-proof-manifest.json, docs/plans/bytecode-burndown-checklist.md, and manifest tests are synchronized with the new route proof.
AC-5: Focused async and manifest proof commands pass with the repository async timeout settings.
User report of this issue
Context
Created by Roadmapper build issue autrun-dj1c8v8ke914-a39f3d3eec on 2026-06-08. ADR 0373 superseded the attempted async-function declined-runner bridge retirement because rejecting route-ineligible async functions broke current async semantics. docs/plans/bytecode-proof-manifest.json now keeps E5b/E5d async-function runner anchors as classified open residue.
Scope
Pick one bounded route-parity slice that reduces async-function declined-runner reliance without replacing fallback execution with rejection. Keep terminal dynamic residue and ordinary sync/class/sync-generator runner owners separate.
Proof Shape
Update docs/plans/bytecode-proof-manifest.json, docs/plans/bytecode-burndown-checklist.md, and focused async-function route/fallback tests together. The proof must show declined async bodies still complete through the classified legacy runner unless the exact shape is semantically owned by the resumable unified route.
Investigation
Blast Radius
Dependencies
E5-async-function-declined-body-runner-still-presentproof should remain open/source-present after this slice.User Stories
Story 1: As a runtime maintainer, I want one exact async-function body shape to route through resumable unified bytecode, so that E5 async declined-runner residue shrinks without changing fallback semantics.
Story 2: As a JavaScript semantics reviewer, I want unsupported async-function bodies to keep completing through the classified legacy runner, so that currently valid async programs do not reject or hang.
Approach
IsStrictinto the async-functionUnifiedBytecodeProductionActivationDescriptorbeforeEvaluateResumable.FunctionDeclarationInstructionresumable decline so the strict async-owned shape can route, while sloppy/Annex B, captured-activation, dynamic, and terminal residue shapes stay declined.unified-bytecode-resumable-async-fast-path func=runand noclassified-async-function-declined-body-runner-residue; one nearby unsupported case should still resolve through the classified fallback.Risks
Additional quality gates
classified-async-function-declined-body-runner-residueunless the exact source shape routes.Recommended Labels
Build Reasoning Effort
High. The code change is narrow, but the correctness boundary crosses async promise settlement, strict block declaration semantics, and manifest source-presence ratchets. Build should avoid broad admission and prove both the new route and the preserved fallback neighbor.
Acceptance Criteria (Refined)
AC-1: A strict async-function block-scoped function declaration resolves correctly through the resumable async route and logs
unified-bytecode-resumable-async-fast-path func=run.AC-2: A nearby unsupported async-function block declaration shape still resolves through
classified-async-function-declined-body-runner-residueand does not log the resumable async fast path.AC-3:
CreateClassifiedAsyncDeclinedBodyRunnerremains source-present and classified in the E5b/E5d manifest rows.AC-4:
docs/plans/bytecode-proof-manifest.json,docs/plans/bytecode-burndown-checklist.md, and manifest tests are synchronized with the new route proof.AC-5: Focused async and manifest proof commands pass with the repository async timeout settings.