Repository navigation
A StaleAdopted live-source compile is dispatched DURING its package's install: source discovery under-matches, CS0246 on committed siblings, and CompileWatcher PARKS the transient failure #4280
Description
The defect
When bake-seed finds a NodeType's prebuilt bundle stale, CompileWatcher keeps the adopted build
serving as StaleAdopted and dispatches a compile of the live source (#3583). That compile is
dispatched while the package is still installing, so its source discovery sees only the subset of
the package's shared Source/ siblings that have been written so far. It fails CS0246 on
committed siblings — and CompileWatcher then PARKS the NodeType, so a transient,
install-order-dependent failure becomes the run's terminal verdict.
A later compile of the same type, after the install completes, succeeds in the same run. The
gate never re-reads it.
Measured
Systemorph/MeshWeaver.Reinsurance main run
34804118498,
job test-repos / Gate shard 1/1, platform set 3.0.0-ci.8547 (core
1c1d62adffc1d7d0545f1600898b89ca475e6ea0).
04:11:44.095 ── Ifrs17: installing 403 file(s)…
04:11:45.778 bake-seed Prebuilt assembly ADOPTED for Ifrs17/RawVariable … module version 1.0.7
04:11:45.783 CompileWatcher [AdoptedSourceStamp] Ifrs17/RawVariable: the source moved past the
adopted build (bundle fingerprint aa82137e45651a6c, live bebbfc488bd3c8bd) and the two
are COMPATIBLE by module version (1.0.7 over (unknown)) — the build keeps serving as
StaleAdopted (#3583); a compile of the live source is dispatched
04:11:45.868 bake-seed Prebuilt assembly for Ifrs17/RawVariable DECLINED before writing (#2813):
the bundle records source fingerprint aa82137e45651a6c but the live sources are
bebbfc488bd3c8bd … Rebake this pack[age]
04:11:46.109 Compiling assembly for Ifrs17_RawVariable (disk, 0 NuGet refs)
04:11:47.772 fail: Failed to compile assembly for node 'Ifrs17/RawVariable' … CS0246 'PeriodType' …
04:11:48.008 fail: NodeType 'Ifrs17/RawVariable' PARKED after compile failure — further activations
serve the cached error without recompiling (failure contained, no retry storm)
04:11:50.038 RED Ifrs17/RawVariable [compile:Failed render:Skipped tests:Skipped]
04:11:50.777 [PackageInstaller] warmed installed root Ifrs17 ← the install ends HERE
…
04:12:03.338 Compiling assembly for Ifrs17_RawVariable (disk, 0 NuGet refs)
04:12:03.974 info: Successfully compiled assembly for Ifrs17/RawVariable to
…/compilation-cache/Ifrs17_RawVariable_…/Ifrs17_RawVariable.dll ← it COMPILES
…
04:12:46.459 RED Ifrs17/RawVariable: compile=FAILED(Error) render=skipped tests=skipped
The compile is dispatched 1.7 s into a 6.7 s install and fails 3.0 s before the install ends.
The other two affected types are tighter: Planning install starts 04:11:57.861 and its compile
fails 04:11:58.847 (0.99 s in); Underwriting starts 04:12:37.324, fails 04:12:38.224
(0.90 s in).
The under-match
The premature compile prints its own source discovery:
Executed source queries (4):
- namespace:Ifrs17/RawVariable/Source scope:subtree nodeType:Code
- path:Ifrs17/Source nodeType:Code
- namespace:Ifrs17/Source scope:subtree nodeType:Code
- namespace:Ifrs17/RawVariable/Test scope:subtree nodeType:Code
Matched Code nodes (8):
- Ifrs17/RawVariable/Source/RawVariable
- Ifrs17/RawVariable/Test/RawVariableTests
- Ifrs17/Source/Arithmetics
- Ifrs17/Source/Consts
- Ifrs17/Source/DataCube
- Ifrs17/Source/IScopeRegistryFactory
- Ifrs17/Source/QueryReach
- Ifrs17/Source/ScopeConfiguration
Ifrs17/Source/ holds 12 committed .cs files; 6 matched. Of the 6 that did not, Enums.cs
declares PeriodType, CashFlowPeriodicity and InterpolationMethod and IScope.cs declares
IScope — exactly the CS0246 names in the failure. Ifrs17/RawVariable/Test/RawVariableTestsArea
is missing from query 4 while its own-folder sibling RawVariableTests matched, producing
CS0103: The name 'RawVariableTestsArea' does not exist in the current context.
Note that the live source fingerprint bebbfc488bd3c8bd in step 2 is itself computed over this
partial set, which is why the bundle is declined in the first place: the decline and the compile
failure have the same cause, one instant apart.
Why it is a race and not a property of any type
The affected set is drawn fresh every run, and in each run it is exactly the set bake-seed
declined, CompileWatcher parked, and the compiler failed — three independently printed lists:
| run | declined = parked = compile-failed |
|---|---|
| 34804118498 (09-14 04:11Z) | Ifrs17/RawVariable, Planning/PlanVersion, Underwriting/Decision |
| 34770922648 (09-13 17:13Z) | Ifrs17/RiskDriver, Reinsurance/Cedent, Reinsurance/Country, Reinsurance/RiskCategory, Signature/DeepSignCredential |
The two sets are disjoint, and Signature/DeepSignCredential is not a type MeshWeaver.Reinsurance
owns — so this is not a satellite's content.
Four candidate discriminators were checked and falsified: the // <meshweaver> heading block
(Enums.cs has one and is missing; IScopeRegistryFactory.cs has none and matched), file size,
node-Id collisions across packages (QueryReach collides 9× and matched, Enums is unique and is
missing), and a stale manifest.lock (gen-manifests.py --check → "✓ all manifest.lock files up
to date").
Two separable fixes
- Do not judge a NodeType's sources mid-install. The
StaleAdoptedfingerprint comparison and
the live-source compile it dispatches must not run against a package whose install has not
completed — either gate them on the package's completion, or derive the live fingerprint from the
manifest rather than from a livenodeType:Codequery. - A compile that failed on an incomplete source set must not be PARKED. The park is what turns
a transient failure terminal:Ifrs17/RawVariablecompiled cleanly 16 s later in the same
process and the verdict never moved. Park on a compile whose inputs were complete; retry (or at
minimum re-evaluate) one whose inputs were not.
Related
- Bundles are baked for ONE framework identity per run, so a portal's GitSynced sources stay days behind main (or its types go unadopted) — options 1-4 undecided #3583 — the
StaleAdoptedpath this dispatch comes from. - Adopt-then-sync, hole 4: the seal marker cannot name a NodeType, so a fully satisfied gate still leaves types unadopted #3845 — adopt-then-sync, Bundles are baked for ONE framework identity per run, so a portal's GitSynced sources stay days behind main (or its types go unadopted) — options 1-4 undecided #3583 requirement 2.
- GitSync adopts a stale prebuilt assembly over the source it just synced — silently running last week's code, and it destroyed client data #2813 — the decline-before-writing guard that fires here.
- Starved cross-silo source discovery produces FALSE CompileErrors that the bake gate reads as image regressions #1218 (CLOSED) — "Starved cross-silo source discovery produces FALSE CompileErrors that the bake
gate reads as image regressions": the same class of false CompileError, by a different route.
This one is a package-install race in a single process, not cross-silo starvation, so Starved cross-silo source discovery produces FALSE CompileErrors that the bake gate reads as image regressions #1218's fix
does not cover it. - Systemorph/MeshWeaver.Reinsurance#206 — the satellite-side ledger, with the full analysis.
Gate: a NodeType activated before its shared sources landed adopts NOTHING and is PARKED red — 'MISSING SOURCES: 3 of 3 queries matched NO nodes', live fingerprint e3b0c442 (empty) #4208/fix: a NodeType is not judged against a source set that has not landed (#4208) #4216 is ruled out: set 8547 carries71be034fand the failure class persists.
Impact
MeshWeaver.Reinsurance main cannot go green while this bites, and the repo cannot fix it: the
affected set is different every run and includes types it does not own. Its
Tests-area ratchet was additionally converting the parked types' tests=skipped into an
instruction to write test suites those types already ship — corrected in
Systemorph/MeshWeaver.Reinsurance#209.
🤖 Generated with Claude Code
Activity
rbuergi commentedon Sep 14, 2026
Cross-reference from the other half — #4295 (the in-memory children index handing a subtree query a SHORT listing that the synced query then caches for good). Not touching this issue's three files; stating the composition so the two are not merged into one:
ApplyAdoptedSourceStamp/CompileWatcher/ park registryInMemoryStorageAdapterchildren index (#4169)Matched Code nodesGROWS between compiles; a later compile succeedsYour Reinsurance runs show the first tell — on PR#209 job 103902719770,
Ifrs17/ReportingNodematched 13 on compiles 1 and 2 (0.5 s apart) and succeeded on compile 3 after the idempotence re-install; same forAggregateExposureProfileandAuthorityRung. The Plugins run (#1823) shows the second: 39 of 49 on both compiles, the second one 15 s after the install ended, with 8 of the missing 10 inStore/Core/Source— written three minutes earlier and read back as "unchanged" by Store's re-install. Note that the Reinsurance log cannot separate the two on its own: the CreateOrUpdate reply precedes the debounced per-node persist, so "N seconds afterInstalled" says nothing about the store.Neither fix alone clears both runs: yours leaves Plugins red (its second compile still saw the frozen 39), mine leaves Reinsurance red on the first park. Doc page for the index half:
Doc/Architecture/InMemoryChildIndexConsistency(in #4295).🤖 Generated with Claude Code
rbuergi commentedon Sep 14, 2026
Reopening — #4293 merged past a review finding that says half of it cannot fire, and I have verified the finding on
main#4293 merged at 08:44:48Z (
812d82b684) with two Copilot findings unanswered; the second is correct and is load-bearing.The finding (
NodeTypeCompilationHelpers.cs:4463): the park-lift half — "at the terminal failure stamp, ifResult.CompiledSourcesdiffers fromCurrentSourceVersions, lift the park and flip Pending with the live set" — comparesSourcesMovedSince(Result.CompiledSources, …). But the failureNodeCompilationResultnever carriesCompiledSources.Verified on
origin/mainafter the merge,src/MeshWeaver.Compiler.Pipeline/MeshNodeCompilationService.cs~1240–1255:sources— the exact set the failed compile consumed — is destructured on the first line and discarded on the return. So on the normal Roslyn-diagnostic failure (theCS0246that Reinsurance#209 showed on three types and Plugins#1823 onEssentials/OperationRequest), the comparison isSourcesMovedSince(null, def.CurrentSourceVersions), and a verdict formed under a moved set still rests at Error. Only the deferral half (CanJudgeAdoptionwaiting onAdoptedSourcePaths) is live.The fix is small and the value is already in hand: populate
CompiledSourcesfromsourceson the failure result at that return. The success path's own comment three lines below says why this is the right source — "one snapshot per compile, so CompiledSources records what was compiled instead of a second, independently raced observation" — and that reasoning applies equally to the failure.The first finding (
:1286) also stands: the completeness witness covers manifestsourceVersionsonly, and both bake paths populate that from query-resolved roots and omitResolvedIncludePaths(TreeBake.cs:114–119, 452–479). An@@-included Code node can still be landing while every recorded path is present, soCanJudgeAdoptionreturns true and the premature compile dispatches anyway. That is a hole in the deferral half too, narrower than the first.Why it merged anyway: the findings arrived while the PR was in the queue and it merged on green — the fourth instance today of core #4299 (review advisory on
mainbecause checks outrun the reviewer). Not a fault of #4293's author; the lane did what it does.Reopening so this does not read as fixed. The delivery freeze is now: #4295 (the index race, in CI) + this (populate
CompiledSourceson failure; coverResolvedIncludePathsin the witness) + the Roll.🤖 Generated with Claude Code
rbuergi commentedon Sep 14, 2026
Both review findings on #4293 are now in follow-up PRs, each opened as a draft so the Copilot review lands before the lane can merge (#4299):
main:CompileAndGetConfigurations's failure branch destructuredsourcesand returned without it, soSourcesMovedSince(null, …)could not fire on the CS0246 path — the park-lift half of fix(#4280): an adoption is not judged while the bundle's sources are still landing; a failure formed under a set that moved is re-driven, not parked #4293 was inert on exactly the path it targets. Pinned by a real failing compile (red onmain, green with the fix).@@-include closure joins the completeness witness. An absent include is an answer inSourceFingerprintIncludeReader(it contributes nothing), so an included node still landing shortens the live fold and read as a move. Both sides now state the include paths as a fact —sourceIncludesin the bundle manifest,AdoptedSourceIncludes/CurrentSourceIncludeson the record — andCanJudgeAdoptionwaits on both lists.🚨 The obvious wrong fix for finding 1, stated so the next reader does not reach for it: adding include paths to
sourceVersionsalone would defer every include-bearing type forever, because the live snapshot (CurrentSourceVersions) never contains includes by design.With #4295 (the index race) this is the delivery-freeze set; the Roll of
memex/memex-cloud(Plugins#1823) is the remaining half and is the maintainer's.🤖 Generated with Claude Code
rbuergi commentedon Sep 14, 2026
Roll target shared with MeshWeaver.Plugins#1823: the first sealed core CD set whose commit range includes #4295 (
9f3598b7017c9bd5f048ff2e9fa9b6e8b90d2662, merged 09:02Z — CD run ≥ 8576), #4293 (merged) AND #4302/#4304 once they land. Both issues now point at the same target; the portals stay on 8411 until that Roll.fix(#4280): an include's arrival wakes the sources watcher, and the p…
fix(#4280): the include-arrival watch reads as System through RunAsSy…
rbuergi commentedon Sep 14, 2026
Closing — both halves are on
main, and the review finding that reopened this is fixed63c3c49150SourcesMovedSincecan now fire on the CS0246 path — the comparison was againstnullbefore, so the park-lift was inert exactly where it was needed. Pinned by a real CS0246 compile through the mesh compiler: red on the old code, green with the fix.@@includesf639c7130b27d22650e6bd9b6ce2b8650ac8f26bsourceIncludesper assembly;CanJudgeAdoptionwaits on both lists; an include's arrival now wakes the watcher (Copilot found the deferral was correct but unbounded — 72 s timeout; converges in 12 s). The rejected shortcut — adding include paths tosourceVersionsalone — would have deferred every include-bearing type forever, since the live snapshot never has them.The original #4293 (
812d82b684) shipped the deferral itself; these two are its review findings, both verified real, both landed with the shape the repo asks for (draft-first, findings answered before arming).What this composes with, stated once more so the Roll is not made short: the seal freeze was two defects. This issue is the mid-install judgement. The other is the in-memory child-index race — core #4295 (
9f3598b701) — which made the bundle's fingerprint decline false by handing the query a partial listing. Neither alone clears both measured runs (Plugins#1823 shows the index race's tell: never recovered; Reinsurance#209 shows this issue's tell: recovered on compile 3).The Roll target, measured: CD run #8580 (
ffae2e1b7, sealed 09:37Z) carries9f3598b701and63c3c49150but notf639c713— #4304 merged after it. So the target is the first sealedmain-cdrun on a head at or afterf639c7130— the next one. A roll onto #8580 would carry two of three and leave the include case open. That decision is the maintainer's; this is only the sentence.🤖 Generated with Claude Code