Running log of Phase 2 slices. Each entry: what was implemented, what was deferred, suspect signatures.
Per PHASE2-BRIEF.md §6 (definition of done).
Date: 2026-06-01 Status: ✅ COMPLETE — build green, host runs, tests 12/12.
Orchestration: PM-driven multi-agent (Workflow), all sub-agents on Opus. Run 1 (wf_b9081644-5c9):
Foundation + Scaffold(host,tests) + Audit(clean-room, architecture, signature/build). Run 2
(wf_99a94061-1d3): assembly-version/ALC finalize + independent verify.
src/System.Web.csproj— SDK-style,net8.0,AssemblyName=System.Web,RootNamespace=System.Web,AssemblyVersion=4.0.0.0,Version=4.0.0.0,FileVersion=4.8.0.0(product-line info only),AllowUnsafeBlocks=true,Nullable=disable,LangVersion=latest,GenerateAssemblyInfo=true(needed so the Version props actually stamp; the 25 skeleton files declare no[assembly:]attrs so no clash).NoWarn= skeleton set1701;1702;0108;0114;0628;0809;0612;0618;0672;1591;3005;0419;0465;0469SYSLIB0003;SYSLIB0011;SYSLIB0021;SYSLIB0051;CS0618. Builds 0 errors / 0 warnings. All existing bodies remainNotImplementedException.
- Dependency port — 6 NuGet packages. Mandated 3:
System.Configuration.ConfigurationManager 8.0.1,System.Drawing.Common 8.0.10,System.ComponentModel.Annotations 5.0.0. Three more the build genuinely demanded (all CS1069 "type forwarded" errors, not invented):System.CodeDom 8.0.0—CodeCompileUnit,CodeTypeDeclaration,CodeMemberMethod,CodeDomProvider,CompilerResults/Parameters/Error, … (used acrossSystem.Web.cs,System.Web.UI.cs).System.Data.SqlClient 4.8.6—SqlException,SqlCommand(management/caching surface).System.Security.Permissions 8.0.0—System.Security.NamedPermissionSet(returned byHttpRuntime.GetNamedPermissionSet,src/System.Web.cs:1667) andSystem.Security.PermissionSet(WebPart base).- Blocker assemblies (
System.Windows.Forms,System.Design,System.DirectoryServices*,System.ServiceProcess,Microsoft.Build.*,System.Runtime.Caching) leaked 0 public types — no action required.
- Shims —
src/Shims/Shims.cs(clean-room, minimal shape, all bodies throw NIE):System.EnterpriseServices.TransactionOption(enum) andSystem.Web.Services.Configuration.WebServicesSection— per brief.- 9 membership/role types:
MembershipCreateStatus,MembershipPasswordFormat,MembershipUser,MembershipUserCollection,MembershipProvider,MembershipProviderCollection,ValidatePasswordEventArgs,MembershipValidatePasswordEventHandler,RoleProvider. Reason: on FW 4.8 these live in the sister assemblySystem.Web.ApplicationServices(no net8 package) — exactly the "reimplement/stub the circular sisters" case from the brief. Bases derive fromSystem.Configuration.Provider.ProviderBase/ProviderCollection; each declares only the union of members the skeleton's concrete subclasses override.
- Standalone HTTP host (Mono/XSP-style, ships in System.Web.dll, INTERNAL types — public surface unchanged):
src/Server/ListenerWorkerRequest.cs—internal sealed ListenerWorkerRequest : HttpWorkerRequest, overrides all 17 abstract members + useful virtuals, mappingHttpListenerContext↔ request/response.src/Server/HttpListenerServer.cs—internal interface IStandaloneServer+internal sealed HttpListenerServer;System.Net.HttpListeneraccept loop →HttpRuntime.ProcessRequest(wr)in try/catch (NIE → 500, loop survives).src/Server/AssemblyInfo.Server.cs—InternalsVisibleTo("SampleHost"),InternalsVisibleTo("System.Web.Tests").- No LINQ (explicit for/foreach).
- Sample host —
samples/host/(SampleHost.csprojSDK Exe +Program.cs+AlcBootstrap.cs+RealEntry.cs+wwwroot/index.aspx). Runs, binds, serves;--smoke <port>for bind-and-exit. - Tests —
tests/System.Web.Tests.csproj(xUnit, net8.0;Microsoft.NET.Test.Sdk 17.11.1,xunit 2.9.2).SmokeTests.cs= 12 facts on assembly identity (nameSystem.Web, version 4.0.0.0, unsigned) and presence of pivotal frozen types. 12/12 pass. (Tests load our DLL via an isolated ALC to dodge the framework facade.)
Microsoft.NETCore.App ships its own strong-named System.Web.dll facade (AssemblyVersion 4.0.0.0, only
forwards HttpUtility) on the Trusted Platform Assemblies list. In the default AssemblyLoadContext it
shadows our app-local copy, so plain typeof(System.Web.HttpContext) binds to the facade and throws.
- Build-time: MSBuild RAR (MSB3243) prefers the facade. Solved by targets in
SampleHost.csprojandSystem.Web.Tests.csprojthat strip the framework-resolvedSystem.Webreference before RAR so the compiler binds to our ref assembly. (Retained — still needed.) - Runtime: solved with a custom AssemblyLoadContext (decision: keep frozen 4.0.0.0 identity rather
than bump the version).
samples/host/AlcBootstrap.csdefinesSystemWebLoadContextwhoseLoad()returns our app-localSystem.Web.dllfor theSystem.Websimple name (null otherwise → BCL resolves normally).Program.Main(default ALC, touches no System.Web type) → loadsSampleHost.dllinto the custom ALC → invokesSampleHost.RealEntry.Runby reflection; all System.Web references then resolve to our copy. Verified at runtime: loadedSystem.Web= v4.0.0.0, path undersamples/host/bin/...,LoadContext=SystemWebHostContext. (Earlier agent's 4.0.0.0→4.8.0.0 version bump was reverted.)
- Clean-room: PASS — no copied/decompiled source; new code limited to Server/Shims plumbing.
- No-LINQ: PASS — zero
using System.Linq/operators insrc/. (SoleSystem.Linqtoken is the pre-existing frozen signatureQueryableDataSourceHelper.SortBy<T>/IQueryable<T>atsrc/System.Web.UI.WebControls.cs:3847— a type reference with NIE body, not a violation. Do not edit.) - Architecture: PASS — zero
Microsoft.AspNetCore.*in any*.cs/*.csproj; server internal/standalone. - Signature integrity: PASS — spot-diffed
HttpContext/HttpRuntime/HttpApplication/HttpRequest/HttpResponse/ HttpWorkerRequest/UI.Page/UI.Controlagainstsystem.web.api.json; all member bodies still NIE; new shim/ server types are additive only; no existing signature edited (25 skeleton files retain original mtime).
HttpWorkerRequest()protected base ctor (src/System.Web.cs:2143) throws NIE. Any concrete worker request (incl. the frozenSimpleWorkerRequest) therefore cannot be constructed until this body is filled. Host currently catches the NIE per request → HTTP 500. Must get a real (non-throwing) body in Tier 2. Not edited (frozen).- Unsigned assembly. True strong-name binary compat with MS
System.Web(PKTb03f5f7f11d50a3a) is impossible without their private key. We preserve AssemblyVersion 4.0.0.0 but PKT is null. Accept. - Custom-ALC requirement for any standalone consumer. Any host/app running on
Microsoft.NETCore.Appmust use theAlcBootstrappattern (or equivalent) so ourSystem.Webwins over the framework facade. This is an architectural fixture for all future hosts, not a one-off. - Build-time RAR-strip targets live in
SampleHost.csprojandSystem.Web.Tests.csproj; keep them for any project thatProjectReferencesSystem.Web.
dotnet build src/System.Web.csproj -c Debug→ 0/0; built DLL AssemblyVersion 4.0.0.0, PKT none.dotnet test tests/System.Web.Tests.csproj→ 12/12.dotnet run --project samples/host/SampleHost.csproj -- --smoke 8092→ binds, diagnostic confirms our app-local System.Web inSystemWebHostContext, self-hit returns 500 (expected Tier-0 NIE), clean exit.
Date: 2026-06-01 Status: ✅ COMPLETE — build green, 27/27 tests pass, both audits PASS.
Orchestration: Workflow run wf_1954d2e0-d56 (6 Opus agents, ~47 min). 3 parallel writers (one per
skeleton file) → 1 integrate+build+behavioral-test agent (custom-ALC test bridge) → 2 read-only auditors
(clean-room/no-LINQ; signature-integrity + independent build/test gate).
System.Web.Util— fully implemented:HttpEncoder(HtmlEncode/HtmlDecode/HtmlAttributeEncode, UrlEncode(byte[]), UrlPathEncode, JavaScriptStringEncode, HeaderNameValueEncode; spec-correct char-by-char logic),RequestValidator(conservative dangerous-string scan),Transactions.InvokeTransacted(synchronous invoke — distributed-tx documented unsupported on net8),WorkItem.Post(ThreadPool). No stubs.System.Web.Caching—Cachebacked byConcurrentDictionary(indexer, Add, 5× Insert, Get, Remove, Count, GetEnumerator; absolute + sliding expiration withNoAbsoluteExpiration/NoSlidingExpiration;CacheItemRemovedCallbackwith correctCacheItemRemovedReason;CacheItemUpdateCallbackrefresh path; lazy expiry + 20s sweeper).CacheDependency/AggregateCacheDependency(file last-write + FileSystemWatcher, HasChanged, dependency-key linkage, eviction with DependencyChanged). Documented stubs:SqlCacheDependency,SqlCacheDependencyAdmin,OutputCache,OutputCacheUtility(SQL/output-cache scope).System.Web.Configuration— ~70 types fully implemented (the whole<system.web>parsing path):HttpRuntimeSection,CompilationSection(+ Compiler/Assembly/BuildProvider/ExpressionBuilder/CodeSubDirectory collections),PagesSection(+ Namespace/TagPrefix/TagMap/IgnoreDeviceFilter),GlobalizationSection,CustomErrorsSection,AuthenticationSection(+ Forms*/Passport),AuthorizationSection(+ rules),SessionStateSection,MachineKeySection,TraceSection,IdentitySection,TrustSection,AnonymousIdentificationSection,HttpHandlersSection,HttpModulesSection,HttpCookiesSection,HostingEnvironmentSection,DeploymentSection,WebControlsSection,UrlMappingsSection,XhtmlConformanceSection,SystemWebSectionGroup/SystemWebCachingSectionGroup, andWebConfigurationManager. Built onSystem.Configurationbase classes via explicitConfigurationPropertyregistration (no reflection attributes). ~60 out-of-scope types documented-stubbed (browser caps/HttpCapabilitiesBase+factory family, healthMonitoring, profile, membership, roleManager, outputCache, siteMap, processModel, protocols, webParts, CAS/trust-assembly sections, SQL cache-dep sections, remote/IIS-metabase config) — each a per-typeNotImplementedException("TODO Tier X: … not needed for Tier-1 web.config parse").
tests/SystemWebUnderTest.cs— bridge: loads ourSystem.Web.dllinto a dedicated ALC (intercepts theSystem.Websimple name), with reflection invoke/property/enum/RunInAlc helpers. Reusable for all later tiers.- 15 new behavioral tests (5 Util + 5 Caching + 5 Configuration) + 12 Tier-0 smoke = 27/27 pass:
encoding vectors (
HtmlEncode("<a>&\"")→<a>&", URL/JS escaping), cache insert/expire/ eviction-callback (reasonRemoved), and a real temp web.config parsed → assertedMaxRequestLength,ExecutionTimeout,Compilation.Debug,Pagesflags,Authentication.Mode=Forms+LoginUrl,SessionState.
FolderLevelBuildProviderCollection.this[string]returnsBuildProvider(notFolderLevelBuildProvider) per the frozen skeleton — cannot return a correctly-typed element; left as documented NIE.WebConfigurationManager.GetSection(string, path)/GetWebApplicationSectionignore the path/web-app context in Tier 1 (delegate toConfigurationManager.GetSection) — correct only for the process-default config until the Tier-2 hosting/virtual-path layer exists.
System.Configuration's internal TypeUtil.GetType resolves each section's "…, System.Web" type string in
the default AssemblyLoadContext, where the System.Web simple name binds to the strong-named shared-
framework facade (which lacks our section types) → TypeLoadException. So WebConfigurationManager.GetSection
will not resolve OUR section types in an ordinary process. The Tier-1 tests work around this by reading each
section's raw XML (SectionInformation.GetRawXml()) and feeding it through our section's own
ConfigurationSection.DeserializeSection(XmlReader) — proving the clean-room parsing logic without any
System.Web type-string resolution. Implication: the Tier-2 runtime (HttpContext/HttpRuntime config access)
must drive config either under the custom ALC (so type strings resolve to ours) or via a config host that maps
section names to our types directly — same family as the host ALC bootstrap. This is the dominant cross-cutting
risk for the runtime tier.
dotnet build src/System.Web.csproj -c Debug→ 0 errors / 0 warnings.dotnet test tests/System.Web.Tests.csproj→ 27/27 (0 failed, 0 skipped).- Audits: clean-room ✅ (no copied source), no-LINQ ✅ (only
List<T>.ToArray()/customContains— noEnumerable), signature-integrity ✅ (pivotal types diffed againstsystem.web.api.json; 22 other skeleton files untouched).
Date: 2026-06-01 Status: ✅ COMPLETE — build green, host serves real HTTP 200, 40/40 tests, both audits PASS.
Orchestration: Workflow run wf_066fed95-9b1 (7 Opus agents, ~37 min). Vendor(cshttp) → CoreA → CoreB →
CoreC → IntegrateTest → 2 audits. Core clusters ran sequentially (single shared file System.Web.cs).
samples/host now returns a real HTTP/1.1 200 OK (curl-verified: Content-Type: text/plain, body
Hello from System.Web) via a default IHttpHandler, running our System.Web v4.0.0.0 under the custom
ALC — no longer 500-ing. The full request→pipeline→handler→response→flush spine works end to end.
- cshttp vendored →
src/Http/(19 files), namespaceCsHttp→System.Web.Http.CsHttp, all 39 types internalized (verified via MetadataLoadContext: 0 new public types). Public-domain, RFC-built — reinforces clean-room. BacksHttpRequestcontent parsing. - CoreA — data/collections/exceptions:
HttpCookie,HttpCookieCollection, internalHttpValueCollection(NameValueCollection container for QueryString/Form/Headers),HttpFileCollection,HttpPostedFile,HttpStaticObjectsCollection, and the exception family (HttpException+ GetHttpCode,HttpUnhandledException,HttpCompileException,HttpParseException,HttpRequestValidationException,ParserError(Collection)). - CoreB — per-request I/O:
HttpRequest(URL surface;QueryString/Form/Files/Cookiesvia the cshttp parsers honoring urlencoded vs multipart; Headers/ServerVariables/InputStream/Params/BinaryRead),HttpResponse(Write/BinaryWrite/Output/OutputStream, status/headers/cookies→Set-Cookie on flush, Buffer/Clear/Flush/End/Redirect, Filter, pushing to the worker request),HttpServerUtility(HtmlEncode/UrlEncode/UrlDecode/UrlPathEncode via Tier-1 HttpEncoder + cshttp PercentDecoder, MapPath, ScriptTimeout, GetLastError),HttpCachePolicy(basic state). - CoreC — orchestration spine:
HttpContext(Request/Response/Server/Items/User/Handler/Application/Cache/ Current via AsyncLocal/Error/RewritePath/GetService/GetSection),HttpApplicationState(Monitor-locked store),HttpModuleCollection,HttpApplication(full integrated pipeline: BeginRequest…EndRequest in order, handler resolution at MapRequestHandler, sync + APM-async handler dispatch, trailing stages always run on CompleteRequest/error, Error event, all 40 AddOn*Async overloads),HttpRuntime.ProcessRequest(build context from worker request → pooled HttpApplication → ExecutePipeline → flush →EndOfRequest()exactly once). HttpWorkerRequest()base ctor — already non-throwing in the current skeleton revision (the Tier-1 log's line:2143 NIE concern was stale numbering);ListenerWorkerRequestconstructs fine. Resolved.
13 new (+27 prior = 40/40): RequestTests (QueryString/Form-urlencoded/multipart→one HttpPostedFile with
exact bytes/Cookies/Headers), ResponseTests (status line/headers/Set-Cookie/body/Content-Length),
ServerUtilTests (encode round-trips, MapPath), PipelineTests (ProcessRequest → captured 200 + body +
EndOfRequest; stage ordering with handler firing between Pre/PostRequestHandlerExecute), TestWorkerRequests
(in-memory capturing/feeding HttpWorkerRequest helpers — reusable).
The static System.Web.HttpUtility class (HtmlEncode/HtmlDecode/HtmlAttributeEncode/UrlEncode/
UrlDecode/UrlEncodeToBytes/UrlPathEncode/JavaScriptStringEncode/ParseQueryString/…) is still entirely
NotImplementedException — it wasn't assigned to a Tier-2 cluster. It is one of the most-used public types in
System.Web and a near-trivial fill: every member can delegate to the existing Tier-1 HttpEncoder and vendored
cshttp QueryStringParser/PercentDecoder. Recommend knocking it out first thing (quick win). Note:
HttpCookie.Value multi-value rendering and HttpValueCollection.ToString(urlencoded:true) currently call
HttpUtility.UrlEncode/UrlDecode and will throw until this is filled (single-value cookie path is unaffected).
HttpContext.Session/Profile→ null (Tier 3);Trace/PageInstrumentation/AcceptWebSocketRequest/ resource getters → throw (later tiers).HttpServerUtility.Transfer/Execute/TransferRequest→ NIE (server-side re-dispatch; handler infra now exists, can be filled soon);CreateObject*→ NIE (COM, out of scope).HttpResponserouting redirects (RedirectToRoute*),WriteSubstitution, asyncBeginFlush/EndFlush/ HTTP-2 push → NIE; cache-dependencyAdd*→ no-op (output-cache layer).HttpCachePolicy.VaryBy*,HttpRequest.Browser(browser caps),ClientCertificate,Unvalidated,LogonUserIdentity,MapImageCoordinates→ NIE (separate features/clusters).- Async pipeline currently runs synchronously to completion (APM returns a completed result).
- Full
<httpHandlers>/<handlers>config→handler mapping deferred; aDefaultDemoHandlerfallback serves unmapped requests (200).RewritePathrecords intent but doesn't yet re-dispatch.
dotnet buildsrc + samples/host + tests → 0 errors / 0 warnings (1 pre-existing benign CS0169 in vendored cshttp).dotnet test→ 40/40. Host--smokeandcurl -i→HTTP/1.1 200 OK.- Audits: clean-room ✅ (no MS provenance; content parsing delegates to cshttp), no-LINQ ✅, signature-integrity ✅ (523 signatures diffed across 10 pivotal types; 0 changed; 0 new public types; unrelated skeletons untouched).
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 51/51 tests, both audits PASS (after a 1-line fix).
Orchestration: Workflow run wf_779487d4-7b8 (7 Opus agents, ~23 min). Hooks → 3 parallel Service writers
(separate files) → IntegrateTest → 2 audits. PM applied one post-audit fix (see below).
HttpUtility(the priority gap) — DONE. All 31 members: HtmlEncode/Decode/AttributeEncode + JavaScriptStringEncode delegate to Tier-1HttpEncoder; UrlEncode/UrlEncodeToBytes/UrlPathEncode/ UrlEncodeUnicode + UrlDecode/UrlDecodeToBytes (+ Encoding overloads);ParseQueryString→ URL-decoded NameValueCollection. Unblocked theHttpCookiemulti-value /HttpValueCollectionurlencoded path. (UrlTokenEncode/Decodelive onHttpServerUtility, already done — not in HttpUtility.)HttpContexthooks — internalSetSessionStateInstance/SetProfileInstance; publicSession/Profilegetters now return the module-published instance (null until set).Useralready had get/set.System.Web.SessionState— InProc.HttpSessionState,HttpSessionStateContainer,SessionStateItemCollection,SessionIDManager(RNG 24-char URL-safe id; ASP.NET_SessionId cookie r/w),SessionStateModule(Acquire/Release; process-wideInProcSessionStateStorewith sliding-expiration sweep; publishes via the hook),SessionStateUtility. StateServer/SQL/custom → documented stubs.System.Web.Security— Forms auth + default providers.FormsAuthentication(real AES-256-CBC + HMACSHA256 encrypt-then-MAC ticket crypto keyed offMachineKeySection, constant-time compare; custom ticket format — NOT MS binary),FormsAuthenticationTicket,FormsAuthenticationModule(sets aFormsIdentity/principal on AuthenticateRequest),Membership+ internalInMemoryMembershipProvider(PBKDF2-SHA256, per-user RNG salt),Roles+ internalInMemoryRoleProvider,RolePrincipal,RoleManagerModule. The shimmedMembershipProvider/RoleProvider/MembershipUserbases (Shims.cs) were fleshed out. SQL/AD/AuthorizationStore/WindowsToken providers → documented stubs.System.Web.Profile— default provider.ProfileBase/DefaultProfile,ProfileProvider+ internalDefaultProfileProvider(process-wide in-memory),ProfileModule(publishes via the hook, auto-save on release),ProfileManager, info/collection/event/attribute types.SqlProfileProvider→ stub.
11 new (+40 prior = 51/51): HttpUtilityTests (encode/decode round-trips, ParseQueryString grouping,
JS-encode); SessionStateTests (container surface + 2-request InProc round-trip — request 1 sets an item
and emits the session cookie, request 2 replays it and sees the item with IsNewSession=false);
SecurityTests (ticket encrypt/decrypt round-trip + tamper rejection, Membership create/validate/wrong-pw,
Roles add/IsUserInRole); ProfileTests (provider + ProfileBase set/Save/reload).
Signature auditor flagged 1 MAJOR: DefaultProfileProvider was declared public (new type, absent from
system.web.api.json) → widened the frozen surface. Fixed: changed to internal (used only internally).
Rebuilt green, 51/51 still pass. (Session/Security in-memory providers were already correctly internal.)
- The skeleton's
internal HttpSessionState()ctor was changed tointernal HttpSessionState(HttpSessionStateContainer)— an internal ctor, within the "add internal members" latitude; public/protected surface unchanged. SessionStateStoreProviderBaseprotected ctor changed from throwing-NIE to no-op (signature unchanged) so concrete derivations can chain.
dotnet buildsrc + samples/host + tests → 0 errors (1 pre-existing benign CS0169 in vendored cshttp).dotnet test→ 51/51. Host--smoke→ HTTP 200 (pipeline unaffected).- Audits: clean-room ✅ (genuine independent crypto; HttpUtility delegates to HttpEncoder/cshttp), no-LINQ ✅,
signature-integrity ✅ after the
DefaultProfileProvider→ internal fix (0 changed frozen signatures; 0 leaked public types).
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 84/84 tests, both audits PASS, ViewState
proven byte-for-byte vs real .NET FW.
Orchestration: two runs — wf_4c46a1a4-184 (Fixtures + StateFormatter + ControlCore; failed at the
orchestration layer when the ControlCore agent ended without its structured report, but its disk writes
persisted and built green) then continuation wf_e4bab189-913 (FormatterCheck → PagePostback → IntegrateTest
→ 2 audits). All Opus.
Captured ground-truth from the real .NET FW ObjectStateFormatter via tools/fixtures-gen (net48 console
referencing the GAC System.Web; fixed machineKey; SHA1 + HMACSHA256 configs) → 34 cases in fixtures/viewstate/.
Our ObjectStateFormatter.Serialize reproduces 31/31 constructable cases byte-for-byte (cases 0–26, 30–33),
Deserialize round-trips, and the MAC pipeline reproduces both HMACSHA1 and HMACSHA256 MACed forms exactly
(all 27 mac cases). The 3 unverified cases (27–29) are WebControls.Unit, which is still NIE (Tier 5) — the
formatter's WriteUnit path is implemented but no Unit instance can be constructed yet; carry to Tier 5.
- Deep fidelity fix:
Hashtableserialization had to replay .NET Framework's exact open-addressing bucket layout (legacy non-randomized x64 string hash, initial 3 buckets, 0.72 load factor, double-hash probe1 + ((h>>5)+1)%(size-1), ascending bucket-index emission) — net8's randomized Hashtable order did NOT match.
- StateFormatter cluster:
StateBag/StateItem(dirty-tracking + Save/Load/Track ViewState),ObjectStateFormatter/LosFormatter(token writer/reader + MAC + base64, byte-compat),Pair/Triplet/IndexedString,IStateManager/StateManagedCollection,HtmlTextWriter/Html32TextWriter(+AttributeCollection/CssStyleCollection, tag/attr/style enums). - ControlCore cluster:
Control(ID/UniqueID/ClientID, naming, lifecycle Init/Load/PreRender/Unload, ViewState + control-state, EnsureChildControls/CreateChildControls, FindControl, Render/RenderChildren, recursive ViewState save/load → the Pair/Triplet/ArrayList shapes the fixtures show),ControlCollection,LiteralControl, IPostBackDataHandler/IPostBackEventHandler/INamingContainer wiring. - PagePostback cluster:
Page(full lifecycle PreInit→…→Unload, DeterminePostBackMode, IsPostBack, Load/Save PageState via persister, EnableViewStateMac apply/strip + tamper-check,__VIEWSTATE/__EVENTTARGET/__EVENTARGUMENT/__VIEWSTATEGENERATOR, RaisePostBackEvent/ProcessPostData, RegisterRequiresControlState),PageStatePersister/HiddenFieldPageStatePersister,ClientScriptManager(hidden fields,__doPostBack, RegisterStartup/ClientScriptBlock dedup, GetPostBackEventReference),PostBackOptions,TemplateControl(Construct/FrameworkInitialize/Error event;LoadControl/ParseControl/LoadTemplate→ Tier-6 NIE stubs).
ViewStateCompatTests (31 byte-compat + round-trip), ControlTests/ControlWorker (tree build, ViewState
round-trip across tree, FindControl, recursive render), PagePostbackTests/PageWorker (hand-written Page:
GET renders __VIEWSTATE; POST replays it + __EVENTTARGET, restores control state, raises postback +
post-data-changed events, re-saved state reflects mutation, IsPostBack true). Worker/control test types are
internal so the default-ALC test host doesn't try to load types whose base resolves only in the bridge ALC.
HiddenFieldPageStatePersister skeleton ctor chained : base(default(Page)) (passes null to a null-guarding
base) — looked like a skeleton bug; body corrected to use the supplied page. Public ctor signature unchanged.
Unitbyte-compat (cases 27–29) — verify onceWebControls.Unitis implemented in Tier 5.- Page ViewState MAC uses a stable per-process key, not
MachineKeySection.ValidationKey— functionally correct (round-trip + tamper detect) but not yet wired to config. Wire when machineKey config integration lands. HtmlForm.Rendernot implemented (Tier 5) — soPage.Rendercurrently emits the__VIEWSTATE/generator hidden fields + script at page level (real ASP.NET emits them inside the server<form>). Only behavioral deviation; revisit with HtmlForm.Control.EnsureIDauto-ID generation is a no-op placeholder (MINOR audit finding) — fill when WebControls rendering/ClientID fidelity matters (Tier 5).- Model binding (
TryUpdateModel), async page pipeline, master pages/themes/Validate/validators → documented NIE stubs (later tiers).
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 84/84. Host--smoke→ HTTP 200.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (185 public UI types == spec, 0 leaked), fixture-compat gate ✅ (31/31 constructable byte-match).
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 95/95 tests, both audits PASS. Closed both
Tier-4 loose ends (Unit → ViewState 34/34; HtmlForm → __VIEWSTATE inside <form>).
Orchestration: Workflow run wf_40d515e5-91a (7 Opus agents, ~59 min, 1.15M tok). Foundation → (Common ‖
HtmlControls) → Validators → IntegrateTest → 2 audits. Phased: data-bound controls + WebParts deferred to 5b/5c.
- WebControls foundation:
Unit(+UnitConverter)/FontUnit/FontInfo,Style/TableStyle/TableItemStyle(StateBag-backed, ViewState round-trip),WebControlbase (CssClass/colors/border/size/Attributes/Style/ ControlStyle, AddAttributesToRender, RenderBeginTag/Contents/EndTag),WebColorConverter/FontUnitConverter/FontNamesConverter.Unitbyte-matches real-FW fixtures (cases 27–29) → ViewState now 34/34. - Common controls: Label, Literal, Localize, PlaceHolder, HyperLink, Image, ImageButton, Button, LinkButton
(+
CommandEventArgs), TextBox (IPostBackDataHandler→TextChanged, HTML5 modes), CheckBox/RadioButton (→CheckedChanged), HiddenField, Panel, Table/TableRow/TableCell/TableHeaderCell (+ row/cell collections), ListItem/ListItemCollection (IStateManager), ListControl + DropDownList/ListBox/CheckBoxList/RadioButtonList/ BulletedList (postback → SelectedIndexChanged). - HtmlControls (~43): HtmlControl/HtmlContainerControl/HtmlGenericControl, HtmlForm (emits the page
hidden fields/scripts inside
<form>), HtmlInput* family, HtmlAnchor/HtmlImage/HtmlTextArea/HtmlSelect/ HtmlButton, HtmlTable/Row/Cell, HtmlTitle/Link/Meta/Head. - Validators: IValidator, BaseValidator, BaseCompareValidator, RequiredFieldValidator, CompareValidator,
RangeValidator, RegularExpressionValidator (System.Text.RegularExpressions), CustomValidator (+ServerValidate),
ValidationSummary, ValidatorCollection;
Page.Validators/Validate()/Validate(group)/IsValidwired (replaced the Tier-4 benign defaults).[ValidationProperty]added to TextBox/ListControl.
- HtmlTextWriter self-closing tags — added a self-closing set (input/img/br/hr/meta/link/…) so WebControls
render
<input … />not<input></input>. - Page↔HtmlForm reconcile —
Page.Renderemits framework hidden fields at page level only whenForm==null; otherwiseHtmlForm.RenderChildrenemits them once inside the form (verified:__VIEWSTATEappears exactly once between<form>…</form>and still round-trips). - Filled NIE base ctors/lifecycle on
BaseDataBoundControl/DataBoundControl(were blocking ListControl-derived controls from even constructing).
+11: WebControlsTests (Unit parse/ToString, Label/TextBox/Button/DropDownList render + postback, style attrs),
HtmlControlsTests (HtmlForm __VIEWSTATE-in-form, input/anchor/generic render, HtmlSelect postback),
ValidatorTests (RequiredField/Range/Compare/Regex + Page.Validate→IsValid), + ViewState cases 27–29 added.
- Internal collection ctors
TableCellCollection/TableRowCollection/Table.RowControlCollection/TableRow.CellControlCollectionwere declared parameterless (passing a null owner) — changed to take the owning control. Internal ctors only (not public/protected surface). HtmlHeadskeleton lacksIPageHeader(no such interface in the codebase) — implemented without it.ControlBuilder()base ctor is NIE (Tier-6 compilation) →HtmlHeadBuilder/HtmlSelectBuilder/HtmlEmptyTagControlBuilderctors throw at runtime until ControlBuilder is implemented. Not used at render time.HtmlGenericControl.TagNameis anewmember hiding the base get-onlyTagName; setter wired to mutate the base tag via an internal helper so base render uses the updated tag.
- 5b: data-bound controls —
GridView,DataGrid,Repeater,DataList,DetailsView,FormView,ListView,DataControlFieldfamily, data source controls (ObjectDataSource/SqlDataSource/etc.),Parameterfamily; complex controls (Wizard,Login*,Menu,TreeView,Calendar,AdRotator). - 5c:
System.Web.UI.WebControls.WebParts(119 types),Adapters. ControlBuilder(Tier 6) needed before the*Buildertypes function.
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 95/95. Host--smoke→ HTTP 200. ViewState 34/34.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (WebControls 410==spec, HtmlControls 41==spec, 0 leaked).
Tier 5b — Data-binding core (Repeater / DataList / GridView + fields / ObjectDataSource + SqlDataSource)
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 103/103 tests, both audits PASS.
Orchestration: Workflow run wf_4fb1bc5c-92d (7 Opus agents, ~78 min, 1.2M tok). Sequential clusters
DataInfra → Templated → GridView → DataSources → IntegrateTest → 2 audits (single WebControls.cs file).
- Data-binding infra:
DataBinder(Eval/dotted paths/indexers via TypeDescriptor),BaseDataBoundControl/DataBoundControl/CompositeDataBoundControl/HierarchicalDataBoundControl(DataSource/DataSourceID resolution via FindControl, PerformSelect/PerformDataBinding, EnsureDataBound),DataBoundLiteralControl,DataKey/DataKeyArray,DataSourceControl/DataSourceView/DataSourceSelectArguments/ListSourceHelper,Parameterfamily (Control/Form/QueryString/Session/Cookie/Profile/Route) +ParameterCollection. - Templated:
Repeater(+ Item/Collection/ItemEventArgs/CommandEventArgs; item hierarchy persisted via ViewState item-count, command bubbling),BaseDataList/DataList(IRepeatInfoUser rendering, item/edit/ selected/separator templates, Edit/Update/Cancel/Delete/Select command dispatch). - GridView:
DataControlField(abstract) +DataControlFieldCollection/DataControlFieldCell(HeaderCell),BoundField,AutoGeneratedField(+AutoFieldsGenerator/GridViewColumnsGenerator),ButtonField(Base),CommandField,CheckBoxField,HyperLinkField,ImageField,TemplateField;GridView(AutoGenerateColumns, Rows, DataKeys/Names, paging+PagerSettings+PagedDataSource, sorting, EditIndex + the full Row* event set, selection, table render, command bubbling),GridViewRow(Collection)+ all event args. - Data sources:
ObjectDataSource(+View, reflection-invoked Select/Insert/Update/Delete on a business type) andSqlDataSource(+View, ADO.NETDbConnection/DbCommand/DbDataAdapter; DataSet/DataReader modes) with their event args.AccessDataSource→ documentedPlatformNotSupportedstub (OLEDB/Jet not x-plat).
+8: DataBinderTests (Eval object + DataRowView + format), RepeaterTests (bind List/array via a programmatic
ITemplate → item blocks with Eval values, header/separator), GridViewTests (AutoGenerateColumns over a
DataTable → <table> header + rows + cell text; BoundField), DataSourceTests (ObjectDataSource SelectMethod →
rows feed a grid).
RepeaterCommandEventArgs/DataListCommandEventArgsskeleton ctors chained: base(default(CommandEventArgs))(null → base copy-ctor NPE) — corrected to pass the real args. Public ctor signatures unchanged.
DataListmulti-column layout uses single-column fallback becauseRepeatInfo.RenderRepeateris NIE (out of this cluster); theIRepeatInfoUsersurface is complete so a realRepeatInfocan drive it later.BaseDataList.DataKeysthrows untilDataKeyCollectionctor is filled (out of cluster);DataKeysArray/SelectedValuedon't depend on it.RouteParameteralways yields null (routing infraSystem.Web.Routingnot yet implemented).PagedDataSourcewas NIE; filled as a required paging helper.
- 5b-2:
DataGrid(legacy) + columns,DetailsView,FormView,ListView+ their fields;RepeatInfo,DataKeyCollection; complex/nav/login controls (Wizard,Login*,Menu,TreeView,SiteMapPath,Calendar,AdRotator,MultiView/View,ContentPlaceHolder/Content);XmlDataSource/SiteMapDataSource/LinqDataSource/EntityDataSource. - 5c:
System.Web.UI.WebControls.WebParts(119) + adapters.
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 103/103. ViewState 34/34. Host--smoke→ 200.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (WebControls 410==spec, 0 leaked; 16 pivotal types diffed, 0 mismatches).
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 106/106 tests, both audits PASS (after a 1-line fix).
A real .aspx file compiles and serves end-to-end through the standalone host.
Orchestration: run wf_f6fcf438-228 (SetupBuilders→Parser→CodeGenBuild→IntegrateE2E; failed at the
orchestration layer — rate-limit cut an agent off before its StructuredOutput — but all 4 phases' disk writes
persisted and built green) then continuation wf_ab983705-f8e (FixE2E → 2 audits). PM applied one post-audit fix.
samples/host/wwwroot/default.aspx (inline <script runat="server">: Page_Load binds a GridView to a
List<Product>, Submit_Click copies TextBox→Label) served by the live host:
- GET
/default.aspx→ HTTP 200, 1807 bytes, full rendered HTML: GridView rows (Widget/Gadget/Gizmo) in<table id="Grid_Grid">, the Label, the TextBox<input>, the Button's__doPostBack('Submit',''), and a__VIEWSTATEhidden field inside<form>. - POST replaying
__VIEWSTATE+__EVENTTARGET=Submit+NameBox=proof-value→ 200,Submit_Clickfires, Label becomes "You said: proof-value". True server-side postback through a compiled.aspx.
- Roslyn:
Microsoft.CodeAnalysis.CSharp 4.8.0PackageReference. - ControlBuilder family (
UI.cs):ControlBuilder/ControlBuilderCollection/RootBuilder/TemplateBuilder(ITemplate via captured sub-builder tree)/CodeBlockBuilder/etc. +ControlBuilderAttribute; the Tier-5a-flagged*Builderctors (HtmlHead/HtmlSelect/etc.) now construct. - Parser (
Compilation.cs+UI.cs):TemplateParser/PageParser/UserControlParser— tokenize directives (<%@ Page/Control/Register/Import/Assembly %>), literals, server controls,runat=serverHTML, code/expr/databind blocks (<% %>/<%= %>/<%# %>), comments → ControlBuilder tree; tagprefix→type resolution (asp:→WebControls, HTML→HtmlControls).TemplateParseExceptionwith line info. - CodeGen + BuildManager (
Compilation.cs): emit a C# Page class (__BuildControlTree/FrameworkInitialize: instantiate controls, set attributes as properties / IAttributeAccessor, nest via AddParsedSubObject + literals, generated nested ITemplates, AutoEventWireup +OnClick=handler wiring), Roslyn-compile it (metadata refs from the trusted-platform set + our System.Web) and load into System.Web's custom ALC so it binds to ours;BuildManager(GetCompiledType/CreateInstanceFromVirtualPath/cache),PageHandlerFactory/SimpleHandlerFactory. - Pipeline wiring (
System.Web.cs~1420–1469):*.aspxrequests route toPageHandlerFactory→BuildManager→ compiledPage.
Symptom: live GET /default.aspx → 200 but Content-Length 3 (UTF-8 BOM only), empty body — while
CompilationTests passed. Cause: HttpResponse.Output built its StreamWriter with BOM-emitting UTF-8 +
AutoFlush=true; the first touch wrote the 3-byte BOM and auto-flushed, locking Content-Length: 3, and
HttpListener (via ContentLength64) then truncated the entire body to 3 bytes. The in-process test worker
appended all writes regardless of declared length, so it never caught it. Fix: Output now uses a BOM-less
encoding + AutoFlush=false (single flush after render → correct Content-Length). Bodies + one private helper
property only; no signature change.
Clean-room audit flagged 1 MAJOR: a newly-invented public interface ICodeBlockTypeAccessor (surface
widening). Fixed: made it internal (its only implementer/consumer are internal). Rebuilt green, 106/106.
+CompilationTests incl. RendersFullPageThroughRuntimeAndHonorsContentLength — drives a real .aspx through
the SAME live path (HttpRuntime.ProcessRequest → PageHandlerFactory → BuildManager → render → flush) using a new
ContentLengthHonoringWorkerRequest (mimics HttpListener truncation) and asserts status/body/__VIEWSTATE-in-form/
no-BOM/Content-Length-exactness — so the truncation class of bug can't regress silently.
@OutputCache/@Reference/@Implements/@PreviousPageType, master-page content regions, precompilation / batch-folder compilation — explicit NIE stubs in directive processing.- Still-NIE namespaces (whole-tier, future work):
System.Web.Routing,System.Web.ModelBinding,System.Web.Management, parts ofSystem.Web.Hosting, WebSockets, Instrumentation; control long-tail 5b-2 (DataGrid/DetailsView/FormView/ListView+ nav/login/Calendar) and 5c (WebParts).
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 106/106. ViewState 34/34. Host--smoke→ ASPX SMOKE PASSED; live GET/POST ondefault.aspxproven (1807-byte render + working postback).- Audits: clean-room ✅ (independent parser/codegen, no MS source), no-LINQ ✅, signature-integrity ✅ (pivotal
Compilation/ControlBuilder types diffed; 0 changed; 0 leaked after the
ICodeBlockTypeAccessor→internal fix), live.aspxe2e gate ✅.
Tier 5b-2 — Data-bound completion (DataGrid / DetailsView / FormView + RepeatInfo + DataKeyCollection)
Date: 2026-06-02 Status: ✅ COMPLETE — build green, 112/112 tests, both audits PASS.
Orchestration: run wf_187e4c14-dba (5 Opus agents, ~40 min). DataGrid → DetailFormList → IntegrateTest →
2 audits (sequential, single WebControls.cs).
RepeatInfo— fullRenderRepeaterfor all layouts (Table grid honoring RepeatColumns + Vertical/ Horizontal direction, Flow, Unordered/OrderedList). Integrate then rewiredDataList.RenderContents+CheckBoxList.Render+RadioButtonList.Renderto delegate to it — so the Tier-5b single-column limitation is genuinely fixed (RepeatColumns/RepeatDirection now work).DataKeyCollection— fixesBaseDataList.DataKeys(previously threw).DataGrid(legacy: BaseDataList) — AutoGenerateColumns,Columns/DataGridColumnCollection,Items, DataKeys, paging (NextPrev + Numeric pager via PagedDataSource), sorting, editing, full style merge, command bubbling (Select/Edit/Update/Cancel/Delete/Sort/Page) + all event args. Column family:DataGridColumn(abstract, IStateManager) +BoundColumn/ButtonColumn/HyperLinkColumn/EditCommandColumn/TemplateColumn,DataGridItem(Collection),DataGridPagerStyle.DetailsView(: CompositeDataBoundControl) — vertical one-row-per-field render,AutoGenerateRows(DetailsViewRowsGenerator), DataKeyNames/DataKey, paging (PagedDataSource pageSize=1), ReadOnly/Edit/Insert modes + ChangeMode + Insert/Update/Delete via DataSourceView, rows/event args.FormView(: CompositeDataBoundControl) — templated single record (Item/Edit/Insert/Header/Footer/ EmptyData/Pager templates), modes, paging,FormViewRow+ event args.
- Multiple skeleton ctors chained
: base(default(X))(would null/zero the base) —DataGridCommandEventArgs,DetailsViewCommandEventArgs,FormViewCommandEventArgs(→base(originalArgs)),DetailsViewPagerRow/FormViewPagerRow(→ forward real rowIndex/type/state). Corrected in bodies. BoundColumn.thisExprwas an uninitializedpublic static readonly string(null) → initialized to"!"(documented value; field already public per spec).DataGridskeleton does NOT implementIPostBackEventHandler(real ASP.NET does). Per no-signature-change rule, NOT added — paging/sort/select work via bubbled Command events from pager/sort LinkButtons instead (functionally complete); directRaisePostBackEventon the DataGrid itself is unavailable.
ListView, ListViewItem, ListViewDataItem, ListViewItemCollection, InsertItemPosition,
ListViewPagedDataSource, DataPager and their event args have 0 occurrences in src/ or
artifacts/system.web.api.json — they were never extracted into the Phase-1 surface (they are legitimately
part of FW 4.8 System.Web). The agent correctly did NOT fabricate them (adding public types = surface leak).
Action item: re-run the Phase-1 tools/extract-api to check whether the extraction missed ListView/
DataPager (and possibly others); if so, regenerate the skeleton entries for them, then implement.
+6: DataGridTests (AutoGenerateColumns over a DataTable → table + rows + BoundColumn), DetailViewsTests
(DetailsView vertical field table; FormView ItemTemplate record), RepeatInfoTests (DataList/CheckBoxList
RepeatColumns=2 → multi-column structure; BaseDataList.DataKeys returns keys without throwing).
- 5b-2ii: nav/login/wizard/calendar —
Menu/TreeView/SiteMapPath,Wizard/MultiView/View,Login/LoginView/LoginStatus/LoginName/ChangePassword/PasswordRecovery/CreateUserWizard,Calendar,AdRotator,ImageMap/HotSpot,Substitution,Xml,ContentPlaceHolder/Content+MasterPage;XmlDataSource/SiteMapDataSource.LinqDataSource/EntityDataSource,DynamicData→ stubs. - 5c:
WebParts(119) + adapters. - Phase-1 gap: extract + implement
ListView/DataPager(see above).
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 112/112. ViewState 34/34.default.aspxrenders.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (WebControls public count == spec, 0 leaked; 11 pivotal types diffed, 0 mismatches).
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 120/120 tests, both audits PASS (after 2 PM surface fixes).
Orchestration: run wf_7494883e-fa3 (6 Opus agents, ~87 min, 1.2M tok). Navigation → LoginWizard → MiscMaster →
IntegrateTest → 2 audits (sequential; WebControls.cs + MasterPage/Content in UI.cs).
- Navigation:
Menu(+ MenuItem/Collection/Binding/Style families, nested<ul>/<li>render),TreeView(+ TreeNode/Collection/Binding/Style, nested div + expand/collapse/checkbox postback),SiteMapPath(+ SiteMapNodeItem) — breadcrumb degrades gracefully (SiteMap infra is NIE, see below). - Login/Wizard:
MultiView/View,Wizardfamily (+WizardStep/TemplatedWizardStep/CompleteWizardStep/CreateUserWizardStep, step-type resolution, nav, sidebar),Login(→ Tier-3Membership.ValidateUser+FormsAuthentication),LoginView/LoginStatus/LoginName,ChangePassword,PasswordRecovery,CreateUserWizard(→Membership.CreateUser),RoleGroup(Collection).CompositeControl(was NIE) filled as a needed base. - Misc + master pages + data sources:
Calendar(month table, DayRender, selection),AdRotator,ImageMap+HotSpotfamily (Circle/Rectangle/Polygon),Substitution,Xml;MasterPage/ContentPlaceHolder/Content(+MasterPageControlBuilder) — work programmatically (content merges into named placeholders);XmlDataSource(+ views, XML/XPath, hierarchical for TreeView/Menu),SiteMapDataSource;HierarchicalDataSourceControlbase (was NIE).
ICodeBlockTypeAccessorrevertedinternal→public. The spec lists it as a genuine public interface; the Tier-6 audit's "invented type" call was wrong, and my Tier-6 internal change had under-exposed a frozen public type. (Lesson: trustsystem.web.api.jsonover an auditor's "not a real type" claim — verify against spec.)XmlDataSource.GetView()(parameterless)public→internal— that overload is not in the spec (only the explicitIDataSource.GetView(string)is); was a surface leak.
- More skeleton
: base(default(X))ctor bugs corrected in bodies:MenuEventArgs,ViewCollection(owner),XmlDataSourceView/SiteMapDataSourceView(passed null to theDataSourceView/CommandEventArgsbase ctors). - Style-derived ctors
(StateBag bag)(MenuItemStyle/SubMenuStyle/TreeNodeStyle) lacked: base(bag)→ added so styles share the owner's StateBag (likeTableStyle). Menu.MenuItemClickCommandName/BoundColumn.thisExpr-style uninitializedpublic static readonly strings given their documented values.
- Menu/TreeView styling: node/item styles + image sets are stored and round-trip in ViewState but are not
applied during render (Menu = plain nested
<ul>/<li>; TreeView = indented divs with[+]/[-]); client-side expand/collapse script not emitted (uses full postback). - Wizard/Login/ChangePassword/PasswordRecovery/CreateUserWizard templates are stored but the default
built-in layout renders (custom
*Templates not instantiated). - Email (ChangePassword/PasswordRecovery/CreateUserWizard):
OnSendingMailhooks fire butMailDefinitionis NIE so no message is sent. SiteMapinfrastructure (System.Web.SiteMap/SiteMapProvider/SiteMapNodeinSystem.Web.cs) is NIE →SiteMapPath/SiteMapDataSourcedegrade to empty; will populate once SiteMap is implemented (no control change).- Master pages at the
.aspxlevel:Page.Master/MasterPageFileparser integration is not wired (the Tier-6 parser doesn't yet merge<asp:Content>→<asp:ContentPlaceHolder>during compilation); the controls work programmatically.
+8: NavigationTests (Menu/TreeView static render), LoginWizardTests (MultiView active view; Wizard
Start→Step→Finish; Login.OnAuthenticate vs a Tier-3 in-memory Membership user), MiscMasterTests (Calendar month
table; MasterPage+ContentPlaceHolder+Content merge; XmlDataSource over inline XML feeds a hierarchy).
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 120/120. ViewState 34/34 (+2 new = 36 cases pass). Livedefault.aspxGET/POST still works under the custom ALC.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ after the 2 surface fixes (public counts == spec, 0 leaked).
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 124/124 tests, both audits PASS (after a PM completeness fix).
Orchestration: run wf_189a85ef-2a0 (6 Opus agents, ~65 min, 1.07M tok). WPCore → ZonesParts →
PersonalizationConn → IntegrateTest → 2 audits (sequential, single WebParts.cs).
- Core:
WebPartManager(Add/Move/Close/DeleteWebPart with cancelable event pairs, zone registry,GenericWebPartwrapping, the 5 display modes),WebPart/Part/GenericWebPart/ProxyWebPart,WebPartZone/WebPartZoneBase/WebZone(+ chrome/verbs/styles),ZoneTemplate,WebPartVerb(Collection),WebPartDisplayMode(Collection),WebPartChrome,WebPartPersonalization, event-args family. - Zones/parts:
ToolZone; catalog —CatalogZone(Base),CatalogPart(Chrome/Collection),DeclarativeCatalogPart/PageCatalogPart/ImportCatalogPart,WebPartDescription(Collection); editor —EditorZone(Base),EditorPart(Chrome/Collection),AppearanceEditorPart/BehaviorEditorPart/LayoutEditorPart/PropertyGridEditorPart(ApplyChanges/SyncChanges);ConnectionsZone. - Personalization/connections: default in-memory
PersonalizationProvider+BlobPersonalizationState(reflects[Personalizable]members),PersonalizationDictionary/Entry/Scope;WebPartConnection(+ Collection),ProviderConnectionPoint/ConsumerConnectionPoint,WebPartTransformer+RowToFieldTransformer/RowToParametersTransformer. Personalization round-trips and connections activate (verified).SqlPersonalizationProvider→ documented stub.
Signature audit flagged a MAJOR API-completeness gap: the frozen public static class
PersonalizationAdministration was entirely absent from the skeleton (0 occurrences in src/ — never
emitted by Phase-1 stub generation; same class of gap as ListView/DataPager). Fixed: regenerated it
from system.web.api.json (3 properties + 25 methods, exact signatures, NIE-stub bodies in the skeleton style)
and inserted at namespace level. Public WebParts surface now 119/119 == spec; build green; 124/124.
- More
: base(default(WebPart))/: base(default(ICollection))skeleton ctor bugs corrected in bodies (WebPartAddingEventArgs/WebPartMovingEventArgs→base(webPart);CatalogZoneBase/EditorZoneBase/ConnectionsZone→SetAssociatedDisplayMode(...)since the base null-guards). WebPartManagerInternalshas only a parameterless internal ctor → wired the owning manager via an internalInitialize(manager).
WebPartManager export/import/copy/permission-set members; ErrorWebPart/UnauthorizedWebPart/
ProxyWebPartManager/ProxyWebPartConnectionCollection; WebPartMenuStyle; the Web*Attribute classes
(WebBrowsable/WebDisplayName/WebDescription); WebPartTracker; SqlPersonalizationProvider.
(PersonalizationAdministration members are also NIE stubs — admin-only, rarely used.)
+4: WebPartsTests — a Page with WebPartManager + WebPartZone hosting parts renders with chrome (titles
present); display-mode switch; personalization extract→apply round-trip; a provider→consumer connection activates.
dotnet buildsrc + host + tests → 0 errors.dotnet test→ 124/124. ViewState 36/36. Livedefault.aspxGET/POST still works.- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ after the
PersonalizationAdministrationre-add (WebParts public types now 119 == spec; 0 leaked, 0 demoted).
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 132/132 tests, both audits PASS.
Orchestration: run wf_82dd4fbc-8aa (6 Opus agents, ~34 min). GapAudit → Routing → SiteMap → IntegrateTest →
2 audits.
Built tools/gapdiff (Mono.Cecil) to enumerate public/protected types of the real runtime + reference
System.Web.dll and diff against our built assembly (read via Cecil's resolver, not the shadowed default load):
- Real
System.Web.dlldefines 1402 public/protected types; ours contains ALL of them — missing = 0. - Runtime vs reference assemblies: identical (1402 each, 0 diff) — confirms the SUMMARY's Phase-1 claim.
- The 11 "extra" types in ours are exactly the real assembly's 11 type-forwarders (9 →
System.Web.ApplicationServices: the Membership/Role family; +EnterpriseServices.TransactionOption; +Web.Services.Configuration.WebServicesSection). In a single-assembly port these must be defined in-place (oursrc/Shims/Shims.cs) — correct, not leaks. - Retires the "extraction gap" worry:
ListView/DataPagerwere never actually missing — they are present in the skeleton as NIE stubs; the Tier-5b-2 "absent" claim was a search error. OnlyPersonalizationAdministrationwas genuinely missing (added in Tier 5c). No backfill was needed. - Footnote: the real DLL also forwards
MembershipCreateUserException/MembershipPasswordException; these aren't referenced by any frozen skeleton signature so they're in neither set — addable to Shims.cs if strict forwarded-surface parity is ever wanted (the authoritative 1402 defined-type set is fully matched without them).
System.Web.Routing(17 types):RouteValueDictionary,RouteData,RouteBase/Route(pattern parse + literal/param/catch-all segment matching + defaults/constraints;GetVirtualPathbuilds URLs back),RouteCollection(MapPageRoute,Ignore, read/write locks),RouteTable,RequestContext,VirtualPathData,HttpMethodConstraint,PageRouteHandler(→BuildManagerfor the routed.aspx),StopRoutingHandler,UrlRoutingHandler,UrlRoutingModule(PostResolveRequestCache →context.RemapHandler). Wired the deferred gaps:HttpRequest.RequestContext,Page.RouteData,Control.GetRouteUrlnow resolve via routing.SiteMapinfrastructure (8 types, inSystem.Web.cs):SiteMap(static: CurrentNode/RootNode/Provider/ Providers +SiteMapResolveevent),SiteMapProvider(abstract; IsAccessibleToUser via Roles + wildcard),StaticSiteMapProvider(dictionary-backed node tree),XmlSiteMapProvider(loadsWeb.sitemap→ recursive node tree),SiteMapNode/SiteMapNodeCollection,SiteMapProviderCollection,SiteMapResolveEventArgs. Unblocks the Tier-5b-2iiSiteMapPath+SiteMapDataSourcecontrols (breadcrumb now renders).
Route.GetVirtualPathusesUri.EscapeUriString(obsolete on net8, compiles under pragma); exact MS escaping may differ slightly.PageRouteHandler.GetSubstitutedVirtualPathtoken substitution is behavior-equivalent, not byte-identical to MS. URL-normalization edge combos (~/→app-path, LowercaseUrls, AppendTrailingSlash) not exhaustively verified vs MS.- Routing uses internal
RoutingHttpContextWrapper/RoutingHttpRequestWrapper(over the real HttpContext) because the publicHttpContextWrapper/HttpRequestWrapperctors are still NIE stubs (out of scope). ⚠️ Test-harness flake (pre-existing, not a code bug): on a fresh rebuild immediately followed bydotnet test, 3WebPartsTestsintermittently fail with "Only one WebPartManager per page" — an xUnit parallel-collection race on thread-staticHttpContext.Current/Page.Items. Deterministic 132/132 with--no-buildacross 3 runs. TODO: isolate WebParts tests into a non-parallel xUnit collection (or reset HttpContext.Current per test).
+8: RoutingTests (route matches products/{category}/{id} → values; constraint rejects; GetVirtualPath round-trip;
MapPageRoute+UrlRoutingModule remap), SiteMapTests (XmlSiteMapProvider loads a temp Web.sitemap → RootNode
- children;
CurrentNoderesolves;SiteMapPathrenders the breadcrumb trail).
dotnet build→ 0 errors.dotnet test→ 132/132. ViewState passes. Livedefault.aspxrenders.- Audits: clean-room ✅, no-LINQ ✅, surface-completeness ✅ (our public types ⊇ real System.Web's 1402; 0 missing).
Tier 8 — Polish pass (Mail/login-email, Page MAC, EnsureID, Menu/TreeView styling, master pages, test flakes)
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 141/141 tests (deterministic on fresh builds), both audits PASS.
Orchestration: run wf_38b917e7-de7 (6 Opus agents, ~52 min). ListView → MailSecCore → StylingMaster →
IntegrateTest → 2 audits.
Proven 3 ways (grep src + spec = 0; reflected the real GAC System.Web.dll = no ListView/DataPager,
though it has DetailsView/FormView/GridView/TreeView; found them defined in System.Web.Extensions.dll,
different assembly/key, same System.Web.UI.WebControls namespace — the source of confusion). So they are
genuinely out of scope for this System.Web port; correctly not fabricated (would have leaked ~20 public
types and broken the Tier-7 1402/1402 proof). The Tier-5b-2 "absent" observation was right; the Tier-7 "present as
NIE stubs" note was the actual error. Our surface remains complete and correct. (If ListView is ever wanted, it
belongs in a separate System.Web.Extensions clean-room assembly.)
System.Web.Mail+MailDefinition:SmtpMail/MailMessage/MailAttachmentmapped ontoSystem.Net.Mail;MailDefinition.CreateMailMessage(token replacement,~/-rooted body viaServer.MapPath),EmbeddedMailObject(s). Wired login email:ChangePassword/PasswordRecovery/CreateUserWizardnow send via an internalLoginUtil.SendMail(raisesSendingMail/SendMailError, guarded — never throws without live SMTP).- Page ViewState MAC →
MachineKeySection:GetViewStateMacKeynow reads<machineKey validationKey>(explicit hex) from config, falling back to the per-process key. ViewState byte-compat tests unaffected (they key the formatter directly). Control.EnsureID: implemented auto-ID generation (was a no-op) —GenerateAutomaticIDon naming containers stabilizesUniqueID/ClientIDfor controls without an explicit ID.- Menu/TreeView style rendering: merged item/sub-menu/node styles (static/dynamic/level/selected/hover) now applied
during render; TreeView
ShowLinesemits a CSS marker class. (Image-set GIFs intentionally skipped — documented.) - Wizard/Login custom templates:
WizardHeader/SideBar/*Navigation,ChangePassword/PasswordRecoverystep templates instantiated into their containers; default layout when null. - Master pages (compile-time + runtime): added
MasterPageParser(@Master); content page (@Page MasterPageFile) codegen emitsAddContentTemplate(id, template)per<asp:Content>;Page.MasterPageFile/Master/ApplyMasterPagemerge content into the master'sContentPlaceHolders and render through the master. Verified by a full-pipeline test.
- WebParts parallel race ("Only one WebPartManager per page"): root cause was the manager singleton living in shared
HttpContext.Items; moved to an internalPage._currentWebPartManagerfield. Verified deterministic across 3 freshdotnet build+dotnet testruns. CachingTests.SlidingExpirationtiming flake: widened the sliding window + jitter margin.
- Menu/TreeView image-set rendering (GIF expand/collapse/pop-out images) — styles + ShowLines CSS only.
- Wizard
LayoutTemplate(named-placeholder merge) — stored, not rendered. - Master pages: runtime
ApplyMasterapproach (master compiled separately, merged after PreInit); nested master-of-master +@MasterTypestrong typing not exercised. MailMessage.Fields(legacy CDO knobs) kept as a property bag;MailEncodingnot applied (System.Net handles it).
+9: MailTests, CoreFixTests (EnsureID, configured MAC key), NavigationTests (Menu/TreeView styles),
LoginWizardTests (custom templates), CompilationTests.MergesMasterPageWithContentRegions (master+content render).
dotnet build→ 0 errors.dotnet test(fresh build) → 141/141 deterministic. ViewState byte-compat passes. Livedefault.aspxrenders. Surface still complete (1402; ListView/DataPager correctly absent).- Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (0 leaks/demotions; SmtpMail's extra ctor internal).
Validated the cross-platform claim on real Linux (WSL2 Ubuntu 24.04, .NET SDK 10.0.300; our net8.0 assemblies
run via DOTNET_ROLL_FORWARD=Major since only the net10 runtime is present). Invocation:
wsl -d Ubuntu-24.04 -- bash -lic "... DOTNET_ROLL_FORWARD=Major ..."; project at /mnt/d/Claude Files/System.Web Project.
- Build on Linux:
dotnet build src/System.Web.csproj→ 0 errors (net8 ref pack auto-restored under SDK 10). - Tests on Linux:
dotnet test→ 140/140 pass — incl. ViewState byte-compat (Windows-captured fixtures reproduce byte-for-byte on Linux), Roslyn.aspxcompilation, control rendering, postback/pipeline, the custom-ALC bridge. NoSystem.Drawing/ GDI+ failures — theColor/WebColorConverterstyle path is Linux-safe. - Live
.aspxon Linux: randotnet samples/host/bin/Debug/net8.0/SampleHost.dll 8099;curl /default.aspx→ HTTP 200, 1806 bytes, full rendered page (<form>,__VIEWSTATE, GridView rows Widget/Gadget/Gizmo, Label,Content-Type: text/html). Host log confirms our System.Web v4.0.0.0 loaded intoSystemWebHostContext(custom ALC) from the app-local path, on Linux. A real.aspxwas parsed → codegen → Roslyn-compiled → executed on Linux.
Conclusion: the project runs classic ASP.NET Web Forms (.aspx + data binding + ViewState + postback) on
cross-platform .NET on Linux — proven, not just designed for.
- WSL has only the net10 runtime → run net8 assemblies with
DOTNET_ROLL_FORWARD=Major(or install the net8 runtime in WSL). Run the host via the portable DLL (dotnet SampleHost.dll <port>) — the framework-dependent apphost doesn't launch off the/mnt/d9p mount. - Removed a stray debug test (
tests/DiagTests.cs+DiagWorker.cs, leftover from the Tier-6 empty-render investigation) that hardcoded a Windows pathD:/Claude Files/gen_dump.txtand failed on Linux. Suite is now 140 tests, all green on both Windows and Linux. - Live postback on Linux not separately curl'd, but covered by the passing
PagePostbackTests+CompilationTestspostback cases on Linux (live postback was curl-proven on Windows in Tier 6).
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 147/147 tests (verified on Windows and Linux), both audits PASS.
Orchestration: run wf_8ecc4974-5ff (6 Opus agents). MBCore → ValueProviders → BindersDataSource →
IntegrateTest → 2 audits. Linux re-validated by a dedicated WSL agent (compact report; no raw output ingested).
- Core:
ModelBindingExecutionContext,ModelState/ModelStateDictionary/ModelError(Collection),ModelMetadata/ModelMetadataProvider(s),IModelBinder/ModelBinderProvider(Collection)/ModelBinders,ModelBindingContext,ValueProviderResult/ValueProviderCollection, binding-behavior attributes. - Value providers:
Form/QueryString/RouteData/Control/Cookie/Session/Profile/UserProfile/ViewStateproviders (over the realHttpContext/RouteData/Profile/Session) + their[Form]/[QueryString]/[Control]/… source attributes; hierarchicalContainsPrefixmatching. - Binders + data source:
DefaultModelBinder(simple + complex/POCO binding with ModelState),TypeConverter/TypeMatch/Array/Collection/Dictionary/KeyValuePair/MutableObjectbinders + their providers,ComplexModelBinder;ModelDataSource/ModelDataSourceView(wires data-controlSelectMethod/UpdateMethod/etc. to code-behind methods with model-bound parameters). - Clean-room discipline note: the agents correctly declined to add MVC-only types the brief mistakenly
listed (
*ValueProviderFactory,ValueProviderFactory,RequestValueProvider,HttpFileCollectionValueProvider, etc.) — those belong to ASP.NET MVC, not WebFormsSystem.Web.ModelBinding, and are absent from the spec. One new helper (SessionValueProvider) added asinternal.
DataAnnotations metadata providers (AssociatedMetadataProvider/DataAnnotationsModelMetadataProvider/
EmptyModelMetadataProvider), the ModelValidator family (+ DataAnnotations validator adapters),
ModelValidationNode, ModelValidatingEventArgs/ModelValidatedEventArgs, ModelBinderErrorMessageProviders.
Core binding works without them; they're the next sub-cluster.
+7: ModelBindingTests — value providers return ValueProviderResult; ValueProviderCollection composites;
DefaultModelBinder binds simple + complex types into ModelState (invalid → error, IsValid=false);
ModelDataSource SelectMethod with a [QueryString] parameter resolves and returns rows.
WSL2 Ubuntu, DOTNET_ROLL_FORWARD=Major: build 0 errors; dotnet test → 147/147 on Linux; live host
curl /default.aspx → HTTP 200, 1806 bytes, all markers present, our System.Web v4.0.0.0 in
SystemWebHostContext. The whole stack — incl. model binding — runs on Linux.
dotnet build+dotnet test→ 147/147 on both Windows and Linux. ViewState byte-compat passes. Live.aspxrenders on Linux. Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (0 leaks/demotions).
Tier 10 — Final breadth (ModelBinding validators, AntiXss, Globalization, WebSockets, Instrumentation, Adapters, Management)
Date: 2026-06-03 Status: ✅ COMPLETE — build green, 160/160 tests on Windows and Linux, both audits PASS.
Orchestration: run wf_027fea87-ffe (6 Opus agents). 3 parallel writers (separate files) → integrate → audit
(with a Windows+Linux WSL gate folded in).
- ModelBinding validation sub-layer (finishes Tier 9):
ModelValidator(+provider/collection/ModelValidatorProviders),DataAnnotationsModelValidator+ per-attribute adapters (Required/Range/RegularExpression/StringLength/Min/Max),ValidatableObjectAdapter,AssociatedMetadataProvider/DataAnnotationsModelMetadataProvider/EmptyModelMetadataProvider,ModelValidationNode(recursive validate → ModelState), validating/validated events. System.Web.Security.AntiXss—AntiXssEncodersafe-list encoder (Html/HtmlAttribute/Url/HtmlFormUrl/Xml/ XmlAttribute/Css encode). (Spec has onlyAntiXssEncoder+ 5 code-chart enums — noUnicodeRange/JS-encode; not added.)Globalization—StringLocalizerProviders/IStringLocalizerProvider/ResourceFileStringLocalizerProvider(resolves a localization ResourceManager; graceful key-fallback when absent).WebSockets—AspNetWebSocket/AspNetWebSocketContext/AspNetWebSocketOptionsoverSystem.Net.WebSockets(host upgrade path documented where the listener doesn't yet upgrade).Instrumentation—PageInstrumentationService/PageExecutionContext/PageExecutionListener.- Adapters —
ControlAdapter/PageAdapter+WebControlAdapter/DataBoundControlAdapter/HierarchicalDataBoundControlAdapter/HideDisabledControlAdapter/MenuAdapter(delegate lifecycle/render to the adapted control). System.Web.Management(40 types) —WebBaseEventhierarchy (management/heartbeat/lifetime/request/error/audit events),WebEventProvider/BufferedWebEventProvider+EventLog(console/file)/Trace/Mailproviders,WebEventFormatter, process/request/thread info,WebEventCodes. External-infra stubs (documented):SqlWebEventProvider(needs DB schema),WmiWebEventProvider(Windows WMI),SqlServices/RegiisUtility(SQL install scripts / IIS-COM registration — not cross-platform).
+13: ModelValidationTests (DataAnnotations → ModelState errors), AntiXssTests (XSS payloads neutralized),
ManagementTests (raise events → buffered/EventLog provider; FormatToString non-empty), light
InstrumentationTests/AdaptersTests.
- Windows: build 0 errors,
dotnet test→ 160/160. - Linux (WSL2): build 0 errors,
dotnet test→ 160/160, live.aspx→ HTTP 200. - Audits: clean-room ✅, no-LINQ ✅, signature-integrity ✅ (0 leaks/demotions).
A clean-room System.Web that runs classic ASP.NET Web Forms on cross-platform .NET — built, audited, and
proven on Linux.
Journey: Tier 0 (net8.0 project + standalone host) → 1 (Util/Caching/Config) → 2 (core runtime, host serves 200)
→ 3 (Session/Forms-auth/Profile) → 4 (Control/Page/byte-compatible ViewState) → 5a/5b/5b-2/5b-2ii/5c (the entire
control library + WebParts) → 6 (.aspx parser + Roslyn compiler — real .aspx runs) → 7 (surface-completeness
proof + Routing + SiteMap) → 8 (polish: mail/MAC/EnsureID/styling/master-pages) → 9 (ModelBinding) → 10 (final breadth).
Final state:
- Public surface: 100% complete — all 1,402 types of the real
System.Web.dllpresent (proven viatools/gapdiff). - Functional implementation: the entire request→pipeline→control→ViewState→render→postback path, the full control
library, the
.aspx/.ascxcompiler, services (session/auth/profile/cache/config/routing/sitemap/model-binding/ health-monitoring). ~10,700 of ~13,796 members implemented; the remaining ~3,069 NIE bodies are external-infra (SQL/AD/WMI providers, IIS-COM) and design-time/exotic members — none on the live request path. - Compatibility:
__VIEWSTATEis byte-for-byte identical to real ASP.NET (incl. HMAC-SHA1/SHA256). - Cross-platform: PROVEN on Linux — build + 160/160 tests + a live data-bound
.aspx(HTTP 200) on WSL Ubuntu. - Quality bar held every tier: clean-room (no copied source), no public/protected signature changes, no LINQ in
src/, noMicrosoft.AspNetCore.*, green build + growing test suite (0 → 160 tests). - Standalone: owns its HTTP host, runtime, pipeline, and
.aspxcompiler — no IIS, no ASP.NET Core, no Kestrel.
Remaining (optional, post-1.0): SQL/AD/WMI provider implementations (need external infra), out-of-proc session (StateServer/SQL), Menu/TreeView image-sets, nested master pages, and the design-time/designer surface.
Post-1.0 — Tier 11: Global.asax, route registration, and the CompleteRequest short-circuit (2026-06-03)
Implemented the three features from the maintainer playbook (docs/extending-openwebforms.md §8a/b/c), following
its recipe. Windows + Linux: build 0 errors, 164/164 tests (160 prior + 4 new in
tests/GlobalAsaxRoutingTests.cs). Clean-room / no-LINQ / no-signature-change audit: CLEAN.
Global.asax(8a — keystone): the application file is now discovered at the app root (case-insensitive → Linux-safe), compiled, and pooled as theHttpApplicationinstance.- Parser: new
internal sealed class ApplicationFileParser : TemplateControlParser(src/System.Web.UI.cs), base type =PageParser.DefaultApplicationBaseType ?? HttpApplication, directiveApplication; routed the<%@ Application %>directive into the existing main-directive handler (ProcessDirective). - Codegen:
TemplateCodeGeneratorgained anisApplicationmode (src/System.Web.Compilation.Impl.cs,GenerateApplication()) that emitsASP.<class> : <base>carrying only the inline<script runat="server">declaration blocks — no control tree / FrameworkInitialize / AutoEventWireup. Works for both inline-script andInherits=/code-behind forms (the generated subclass inherits the magic methods). - Engine:
BuildManagerEngine(src/System.Web.Compilation.Engine.cs) maps.asax→ the new parser/codegen and exposesGetGlobalAsaxType()(discover + compile + cache);BuildManager.GetGlobalAsaxType()delegates to it (falls back totypeof(HttpApplication)). - Runtime wiring:
HttpApplication.InitInternal()installs the default modules then binds the "magic" methods by reflection —Application_<Event>/Application_On<Event>→ the matching pipeline event (BeginRequest/Error/…),Session_Start/Session_End→ theSessionStateModule, and the non-event hooksApplication_Start/End/Init. Methods may be(object,EventArgs)or parameterless (adapted via a privateMagicHandlerAdapter).HttpRuntime.EnsureFirstTimeInit()resolves the app type, builds the special instance, and raisesApplication_Startexactly once before the first request;Close()raisesApplication_Endonce.
- Parser: new
- Route registration (8b):
UrlRoutingModule(andSessionStateModule) are now installed in the default module set (previouslyHttpApplication.Init()installed none), soRouteTable.Routes.MapPageRoute(...)/Routes.Map(...)called fromApplication_Starttake effect with no extra config. Proven end-to-end:GET /products/5→Product.aspxrendersPID=5viaPage.RouteData. CompleteRequestshort-circuit (8c): verified already-correct (SuppressContent/TrySkipIisCustomErrorsstored & honored in the flush/header/body paths;CompleteRequest()skips remaining stages). Added a test proving the exact snippet suppresses the body and skips later stages.- One body fix surfaced by routing:
HttpWorkerRequest.GetPathInfo()was athrow NIE; the real framework default returnsString.Empty(routing readsRequest.PathInfo). Fixed to the documented default (body-only). - Test-only internal hooks (no surface impact):
HttpRuntime.SetAppPathsForTest/ResetApplicationForTest,BuildManagerEngine.ResetCachesForTest— let isolated tests point the runtime at a temp app dir and re-resolve.
Lesson: the .asax path is the page compiler minus the control tree — reuse TemplateCodeGenerator with a mode
flag rather than a parallel generator. The default-module set is the single switch that makes the whole Tier-7
routing engine actually fire on a live request.