Handoff: Stale local build-artifact cache reuse (kompile / bldbinary / buildMaven) — root-cause consolidation, ready to fix
✅ STATUS UPDATE — 2026-07-10 (UTC): ROOT CAUSE FIXED + SHIPPED; dev-box rollout 3/7, finishing
The durable fix this handoff called for has landed. The resolver-layer half of the defect — two WorkspaceCoordinateResolver bldbinary/memrepo fetch paths not marked served-fresh — is fixed in kompile-core #211 (MERGED 2026-07-09T23:31:34Z, squash ad57b7b), completing what kompile-core #210 (the fingerprint-validated BuildRuleResultIndex, MERGED) started for the per-repo caches. Verified with a red↔green reproducer. The fixed toolchain is published to kotlin.directory: kompile:manager:0.0.112 (fix confirmed in bytecode) → kompile.cli:kompile-cli:0.0.79 via kompile-cli #126 (MERGED 2026-07-10T02:39:45Z; its POM depends on manager 0.0.112, so downstream pulls the fix transitively).
Dev-box rollout (bump each priority repo's pinned kompile-cli → 0.0.79): 3 of 7 done — NetLabWorkerServer #59, NetLabEmbedded #63, NetLabApi #28 merged. 4 remain OPEN and correct, blocked only by shared buildtest-droplet CI instability (not code): UrlProtocol #351, UrlResolver #737, NetLabManagerServer #101, NetLabCLI #41.
→ Current status + how to finish the rollout live in the follow-on handoff: 2026-07-10-kompile-cli-0.0.79-rollout-blocked-by-buildtest-droplet-instability.md. Delete THIS handoff once all 7 repos are on 0.0.79. The root-cause analysis below is accurate and remains useful historical context; the "in-flight / mid-flight / until then" framing in it is now superseded by this banner.
Written: 2026-07-09 (UTC). Consolidates 36 challenges/ notes spanning 2026-07-07 → 2026-07-09 plus two standing auto-memory notes.
RE-VERIFY BEFORE ACTING. Every state claim below (toolchain versions, "fixed in", "in-flight PR", cache paths, which repos are affected) was true only at write time. The kompile toolchain is actively moving — manager 0.0.110's fingerprint-validated index and the 0.0.112 → kompile-cli 0.0.79 chain were mid-flight on 2026-07-09. Before you touch anything: re-check the live state of the kompile-core / kompile-cli / build-kotlin-jvm toolchain (gh pr view <n> --json state,mergeStateStatus,statusCheckRollup,mergedAt), confirm the current pinned kompile-cli version in a target repo's scripts/build.bash + scripts/test.bash, and confirm the cache layout on the dev box you are on (ls ~/.aibuildcaches/ and ls ~/.cache/coursier/v1/bldbinary/repository/). A fresh query always wins over this document.
1. Executive summary
Across a 2.5-day window, 36 separate challenge notes — filed by multiple agents across at least a dozen repos (BuildTestApi, BuildTestEmbedded, BuildTestRunner, UrlProtocol, kotlin-build-ci, FakeDropletService, build-kotlin-jvm, KompileRemoteBuild{Api,Embedded,Wui}, DigitalOceanDropletServiceServer, HardwareControlFabricWuiHealthCheck, kompile-buildrule-enhancer, build-watchman, BuildTestServerService) — all describe one defect wearing many costumes: kompile's local build-artifact caches key on the Maven coordinate/version, not on the source content, so after a source edit (and frequently even after a coordinate bump) a local scripts/test.bash run silently reuses a stale, previously-built artifact and executes the OLD behavior. The tell is a build rule that "succeeds" in ~1–8 ms (a cache hit, not a rebuild) while tests report pre-edit behavior, stale ABI (Unresolved reference: …, Cannot find a parameter with this name: …, overrides nothing, AbstractMethodError, NoSuchMethodError), or — worst — a partial red/green mix. This silently invalidates the local TDD red/green loop: it produces false reds (correct fixes look broken) and false greens (a passing test may be exercising old code), and it repeatedly cost engineers multiple 2–25-minute rebuild cycles and hours of forensic time, sometimes during production emergencies. The durable fix is to make source (and deleted-source) content part of the cache key so a same-version rebuild after a source change is a cache miss. A toolchain chain that does exactly this (manager 0.0.110's fingerprint-validated BuildRuleResultIndex, kompile-core issue #208 / PR 210) was landing at write time — the handoff's job is to get that chain shipped and onto dev boxes, then prove it with a regression test, and until then stop the workarounds from silently failing.
2. Root-cause mechanism (precise)
The cache lookup key omits source content. Kompile treats a buildMaven() Maven coordinate as immutable and, on a repeat request for the same coordinate, returns the first-built artifact for that coordinate instead of rebuilding from the current working tree — so a source edit (or even a coordinate bump, when a stale companion layer intervenes) is not reflected in the artifact that lands on the test classpath.
This is a cache-invalidation defect, not "the build is slow" and not "the artifact failed to download." The diagnostic proof, present in nearly every note, is a contradiction: scripts/build.bash <rule>.buildMaven compiles the edited source and javap/jar tf on the freshly built jar shows the new bytecode, yet the test classpath loads an older jar with the old bytecode. Server-of-truth (fresh build output) and consumer (test classpath) disagree about what the artifact contains — and per the engineering guidance, that contradiction is the bug. Do not "reconcile" it with a wider timeout or a retry; find the layer where the lookup diverges.
There are four distinct cache/staleness layers implicated, and a fixer must address all four (or the meta-fix that subsumes them). They are distinct because clearing one does not clear the others — several notes clear layer (a) and still get stale results from layer (b):
(a) buildMaven() per-repo cache — same-version artifact reuse (~/.aibuildcaches/<escaped-workspace-path>/)
The per-checkout build cache (also holding the buildRuleResultIndex) reuses a same-coordinate artifact after a source edit. Signature: build rule "succeeds in ~1 ms"; clearing ~/.aibuildcaches/_<escaped-workspace-path> alone fixes it.
Evidenced by: 1622 (UrlProtocol link-state), 1754 (mplex removal, the canonical ~1ms repro), 1810 / 2020 (BuildTestEmbedded), 1912 (kompile-buildrule-enhancer 0.0.2), 2319 (DropletServiceServer WebCron), 2343 (buildClientResourcesJar nested jar), 0119 (health-check bytecode), 0258 / 0423 (BuildTestApi interface), 0413 (build-watchman FakeApis ABI), 0424 (FakeDropletService constructor metadata), 0811 (KompileRemoteBuildEmbedded), 0852 (KompileRemoteBuildWui HTML), 0917 (kotlin-build-ci), 1446 (BuildTestEmbedded constructor params), and the kompile-buildmaven-version-cache memory note.
(b) Global bldbinary coursier cache — coordinate-keyed local Maven repo (~/.cache/coursier/v1/bldbinary/repository/<group>/<artifact>/<version>/)
buildMaven() installs into a local coursier "bldbinary" repository under the fixed version literal; @file:WithArtifact("<pkg>.buildMaven()") resolves that coordinate. The FIRST build of a version is installed and every later run reuses it — surviving ~/.aibuildcaches clears. Two aggravating sub-cases: the test resolver can prefer the stale global bldbinary copy over a freshly built local build-rule output with the same coordinates (0717), and the workspace-substitution path can serve stale bytecode even when the repo-local jar is correct (0234).
Evidenced by: 0154 / 0311 / 0401 (BuildTestApi 0.0.41/0.0.42), 0229 (FakeDropletService 0.0.9), 0234 (build-kotlin-jvm 0.0.25 — repo-local clear NOT sufficient), 0717 (KompileRemoteBuildApi — resolver prefers stale global over fresh local), 0811 (KompileRemoteBuildEmbedded), 0824 (BuildTestEmbedded 0.0.221 runtime load), 0911 (buildtest-embedded lease fix), and the kompile-bldbinary-stale-cache memory note.
(c) Per-repo kompile caches / name-only BuildRuleResultIndex
A sub-case of (a) worth calling out: pre-manager-0.0.110, the ~/.aibuildcaches/<slug>/buildRuleResultIndex keyed build-rule results by rule name alone (no fingerprint), so after a rebase that changed rule source the index served the pre-rebase jar, and nested local-substitution fixtures failed bldbinary does not provide …. Fixed by manager 0.0.110's fingerprint-validated index (kompile-core issue #208, PR 210, merged 2026-07-08 at write time).
Evidenced by: 0118 (2026-07-09) (the name-only index diagnosis; also documents that the live cache is ~/.aibuildcaches/<slug>/, NOT the older ~/.buildcache many docs still reference).
(d) Stale kompile-cli version pins / stale generated launcher in scripts/
Adjacent staleness in the toolchain rather than the artifact: repos pinning kompile-cli <= 0.0.77 in scripts/*.bash hit the un-timed-Coursier-socket defect (fixed in kompile-core PR 207, shipped in kompile-cli 0.0.78) and stall silently for 20+ min; and because scripts/*.bash only generate jars/KompileCli.jar when it is missing, an ignored, pre-existing launcher from an earlier checkout keeps launching the old kompile-cli even after the pin is bumped — which then compiles tests against a stale artifact and produces false source errors.
Evidenced by: 1228 (0.0.77 → 0.0.78 stall), 1645 (stale launcher missing community-kotlin-coursier-bldbinary → NoClassDefFoundError: BldBinaryRepositoryHandler), 0635 (ignored jars/KompileCli.jar still launches 0.0.77 after pin bump).
Two orthogonal traps recur alongside the core defect and must not be conflated with it (they are separate bugs, noted here so the fixer doesn't chase them as staleness):
- Buildscript-bridge TCP timeout —
TCP communication error in visitMethodInsn / SocketTimeoutException: Read timed out in BuildscriptRunner.sendMessageAndGetResponse (0435, 0635). Infrastructure flake in the build bridge, not a cache miss.
- Noisy harness output — routine
[ERROR] Unhandled effect: kompile.BuildRuleExecutedEffect / WithArtifactVersionMismatchWarningEffect / BuildScriptStderrEffect stack traces, plus recoverable TCP StreamCorruptedException / UTFDataFormatException, printed even on runs that pass 413/413 (1810, 0424, 0852, 0911, 1317, 2020). These bury the real failing assertion and make a passing run look failed.
3. Observed manifestations / symptom catalog
The 36 notes cluster into these distinct symptoms (a note can appear under more than one):
M1 — Misleading ~1ms (single-digit-ms) "build" that is actually a cache hit. The clearest tell. kompile.BuildRuleExecutedEffect: build rule executed: <rule>() (succeeded in 1ms) (or 0–8 ms) after a source edit means no rebuild happened.
→ 1754, 2319, 0811, 0423, 0424, 0413, 0649 (8 ms), 0917.
M2 — Stale ABI / API shape served after a source edit (false RED). Tests fail to compile against symbols that ARE in the working tree: Unresolved reference: …, Cannot find a parameter with this name: …, overrides nothing, overload-resolution ambiguity.
→ 1622 (refreshLocalAdvertisement, maxAdvertisements), 1630 (normalizeTestSpecs), 1817 (CheckSuiteSummary, listCheckSuitesForRef), 2020 (gitContext, perftestGitContextForRun), 0258 (toJson/fromJson), 0311 (BuildTestOptimizerApi), 0413 (mergeQueueEntryResponseJson et al.), 0423 (createUploadSessionStructured), 0424 (FakeDropletService constructors), 0717 (DataCapacityPlan, dropletSizeSlug), 0917 (createUploadSessionStructured), 1446 (sshConnectTimeoutMs et al.), 0635 (HierarchicalSigningKey, NameResolutionConfig), 0855 (BuildLeaseRenewalFailedEffect, renewDropletLeases).
M3 — Stale runtime behavior / constructor / binary compat (false RED or false GREEN at runtime). Compiles fine but executes old code: AbstractMethodError, NoSuchMethodError, removed method still on the stack, old wording in messages.
→ 1754 (negotiated mplex after removal), 2319 (old WebCron), 2343 (NoSuchMethodError: BuildRunImpl.getGitContext), 0119 (old health-check text), 0154 (AbstractMethodError, abstract getters still present), 0229 (interceptor still invoked), 0234 (static initializer lists kotlin.directory first), 0824 (cleanupOrphanedDroplets still on stack), 0811 (planRationale assertion), 0852 (old HTML), 1317 (missing constructor params after rebase).
M4 — Stale reuse persists ACROSS a coordinate bump. The scary one — bumping the version literal did NOT fix it, because a companion layer (global bldbinary, or a racing process, or an ignored launcher) still served old bytes.
→ 1630 / 1801 (0.0.47→0.0.48 no 0.0.48 jar produced), 2020 (0.0.218→0.0.219), 0311 / 0401 (0.0.41→0.0.42, global bldbinary still 0.0.41), 0413 (0.0.10→0.0.11), 0917 (0.0.41→0.0.43), 1317 (rebase + bump), 1446 (0.0.231→0.0.232), 0824 (0.0.220→0.0.221), 0855 (0.0.231), 0649 (persists across bump AND purge while a straggler process repopulates).
M5 — Nested / generated-resource artifacts (WUI, client jars) served stale. The staleness reaches inside buildClientResourcesJar() and WUI builds, so a nested client-impl.jar or rendered HTML is stale even when the outer build is fresh.
→ 2343 (buildClientResourcesJar nested BuildRunImpl missing getGitContext), 0852 (KompileRemoteBuildWui /accuracy HTML fallback), 0119 (WUI-adjacent health-check, worked around by switching buildMaven()→buildFatJar() for a distinct jar path).
M6 — Deleted source / removed method not reflected. Removing a method or muxer entry leaves the old member callable/negotiable via the stale jar.
→ 1754 (deleted Mplex entries), 0824 (removed cleanupOrphanedDroplets still present), 0229 (removed interceptor call still runs).
M7 — Masked fixes that later re-flake / partial staleness. A real fix (or a real pre-existing compile error) is hidden by the stale cache; and a partial stale hit yields a genuinely confusing green/red mix where tests hitting code paths present in the stale jar pass while tests needing the newest edit fail.
→ 0234 (production-incident TDD false negative), 0258 (full suite falsely passed — 51 fakes should have failed against newly-abstract methods), 0911 (lease-fix false negative during a production emergency), 1446 (cache hid a real BUILDTEST_DROPLET_NAME_PREFIX compile error), 0649 (1-of-6 scenarios fails, 5 pass — partial-staleness signature), 0118 (rebase makes results untrustworthy on pre-0.0.110 boxes).
M8 — Toolchain-pin / launcher staleness (adjacent, layer d). → 1228, 1645, 0635.
M9 — Attribution / noise confounders that hid the real cause. Pre-test build-rule timeouts mis-attributed to a named test (1645), buildscript-bridge TCP timeouts (0435, 0635), harness effect-noise burying the failing assertion (1810, 0424, 0852, 0911, 1317, 2020), stale publish instruction --publish rejected (2023), and the wrong cache location in old docs — ~/.buildcache vs the live ~/.aibuildcaches/<slug>/ (0118).
4. Impact — why this is high-priority
- It silently invalidates local TDD verification. The entire red→green loop depends on the test executing the code you just edited. When the cache serves the prior artifact, red/green is measuring the wrong bytecode. Per the engineering philosophy, reliable reproduction is a precondition for a correct fix — this defect destroys that precondition without any error, so agents "verify" fixes that were never actually exercised.
- Both false reds and false greens. False reds (M2/M3) send agents to rewrite correct source or tests, or to weaken tests, or to bump public versions unnecessarily. False greens are worse: 0258 shows a full API suite passing while 51 fakes should have failed against newly-abstract methods — a broken change looked shippable.
- Repeatedly cost hours, sometimes mid-emergency. Notes report "multiple test iterations," "multiple 2–3 minute runs," "three wasted verification cycles (~25 min each)" (0649), "hours of forensic work" (0118). 0234 and 0911 hit this during production incident fixes (build-kotlin-jvm Maven-probe storm; BuildTestEmbedded lease loss), directly slowing emergency remediation.
- It masquerades perfectly as a code regression (0118), so it consumes senior forensic effort every time and erodes trust in local results — several notes end by recommending agents cross-check with temp checkouts +
javap, i.e. stop trusting scripts/test.bash.
- High frequency, still recurring. 36 notes in ~2.5 days, and 0649 (2026-07-09) shows it biting three more times in one session despite applying the documented workarounds — the workarounds themselves race running processes and silently fail.
5. Reproduction recipe
Minimal, reliable trigger (layer a/b, the core defect):
- Pick any kompile repo whose tests use
@file:WithArtifact("<pkg>.buildMaven()") (e.g. FakeDropletService, BuildTestApi, KompileRemoteBuildEmbedded).
- Run the target test once so the artifact is built and installed:
./scripts/test.bash --test <someTest>. Confirm it builds source (multi-second build, real compile).
- Edit
src/… to change an observable public behavior without bumping the version literal in build.kts. The sharpest edit is one that changes an assertion outcome (e.g. remove a code path, change a message string) or adds a public symbol a new test references.
- Re-run
./scripts/test.bash --test <someTest>.
- Observe the defect: the test reports the OLD behavior (or fails to resolve the new symbol), and the log shows
build rule executed: <pkg>.buildMaven() (succeeded in 1ms) — a cache hit, not a rebuild. scripts/build.bash <pkg>.buildMaven /tmp/out.jar + javap on /tmp/out.jar proves the fresh build DOES contain your change, establishing the classpath/build-output contradiction.
Concrete instances to lift directly:
- 1754 (canonical ~1ms/layer-a): remove all
StreamMuxerProtocol.Mplex entries from src/foundation/url/protocol/Libp2pHostFactory.kt, rerun testFactoryHostInteroperatesWithMplexOnlyLegacyPeer → still negotiates mplex; log shows succeeded in 1ms.
- 0234 (layer b, repo-local clear insufficient): in build-kotlin-jvm change
defaultMavenRepositories order in src/JvmBuildRules.kt; even after rm -rf ~/.aibuildcaches/…build-kotlin-jvm, the fixture test stays red because the global ~/.cache/coursier/v1/bldbinary/repository/kompile/build-kotlin-jvm/0.0.25/…jar static initializer still lists kotlin.directory first. Requires clearing BOTH.
- 0649 (persists across bump + purge, needs process isolation): with a straggler
test.bash/kompile.cli.CliKt process alive for the workspace, bump the version and purge both caches — a racing process repopulates the purged cache with the pre-edit evaluation; partial 1-of-6 red/5-green results.
- 0118 (layer c, name-only index, post-rebase): on a box whose kompile-cli predates manager 0.0.110, rebase a repo so a build rule's source changes without a coordinate change;
~/.aibuildcaches/<slug>/buildRuleResultIndex serves the pre-rebase jar by rule name alone (verify via mid-hang jstack + the child JVM's @argfile classpath pointing at the stale …/0.0.25-tests/ jar).
Diagnostic tells (put these in the fix's failure message): build rule "succeeds" in single-digit ms after a source edit; javap/jar tf on scripts/build.bash …buildMaven output disagrees with the test classpath; probing <Class>::class.java.protectionDomain.codeSource.location points into ~/.cache/coursier/v1/bldbinary/….
6. Current workarounds (these are workarounds, NOT fixes — do not ship any of them as "the fix")
The notes and the two memory files converge on this sequence. Mark clearly in any doc that these are stopgaps that the durable fix should make unnecessary.
- Bump the version literal in
build.kts as part of every source change (repo convention: add a changelog comment). Reliably defeats layer (a) but not (b)/(c)/(d) — see M4. (kompile-buildmaven-version-cache memory.)
- Purge the global bldbinary entry for the coordinate:
rm -rf ~/.cache/coursier/v1/bldbinary/repository/<group-path>/<artifact>/<version> (kompile-bldbinary-stale-cache memory; 0154, 0229, 0234, 0311, 0401, 0717, 0811, 0824, 0911).
- Purge the per-repo cache (note the live path is
~/.aibuildcaches/_<escaped-workspace-path>, not the older ~/.buildcache in stale docs — 0118):
rm -rf ~/.aibuildcaches/_<escaped-workspace-path> (and, pre-0.0.110, mv …/buildRuleResultIndex aside).
- Clear BOTH (a)+(b) together when repo-local alone doesn't help (0234, 0811, 0649).
- Kill straggler processes first, then purge, then run SERIALLY — the full sequence that actually works under concurrency (0649):
pgrep -f <workspace-dir> and kill any live test.bash/kompile.cli.CliKt; then purge (b) then (a); never run test invocations concurrently.
- Toolchain/launcher (layer d): bump the
kompile-cli pin to ≥ 0.0.78 in scripts/{build,test}.bash (use the kompile-cli-bump skill); delete the ignored jars/KompileCli.jar so it regenerates against the new pin (0635); regenerate if it's missing community-kotlin-coursier-bldbinary (1645).
- Escape hatches used ad hoc: run the launcher with a throwaway
--cache-location (1817); switch a test's @WithArtifact from buildMaven() to buildFatJar() for a distinct jar path (0119); build with scripts/build.bash …buildMaven and drive a hand-written /tmp harness against the verified jar (0855).
7. Suggested durable fix(es)
Presented most-supported first. The overwhelming consensus across the notes is option A.
A. (PRIMARY) Include source-content (and deleted-source) fingerprint in every local artifact cache key
Make the cache key for buildMaven() / buildSimpleKotlinMavenArtifact outputs a function of {build-rule identity, effective build.kts body incl. compiler args & dependency coordinates, full source-tree content hash incl. deletions, nested build-rule outputs} — not the Maven coordinate alone. Apply it to all three artifact layers: the per-repo ~/.aibuildcaches/<slug> cache (incl. buildRuleResultIndex, which manager 0.0.110 already moved from name-only to fingerprint-validated — kompile-core #208 / PR 210), the global ~/.cache/coursier/v1/bldbinary/repository/… install, and nested buildClientResourcesJar/WUI outputs. Consequences that must hold: a same-version rebuild after any source change is a cache miss (M1 defeated); the freshly built local build-rule output wins over any same-coordinate global bldbinary artifact (fixes 0717/0234); removed source members are reflected (M6). Cited as the fix in nearly every note: 1622, 1630, 1754, 1801, 1810, 1912, 2020, 2319, 2343, 0119, 0154, 0229, 0234, 0258, 0311, 0401, 0413, 0423, 0424, 0717, 0811, 0824, 0852, 0911, 0917, 1317, 1446, 0118, 0649, 0855.
Trade-off: hashing a full source tree per build rule adds cost; mitigate with mtime-cheap pre-checks and by hashing only the rule's declared inputs. This is the direction the in-flight toolchain chain already took — the highest-leverage action is to finish landing manager 0.0.110/0.0.112 → kompile-cli 0.0.79 and roll it to dev boxes, then extend the same fingerprinting to the global bldbinary install if #208's fix didn't already cover it.
B. Make freshly-built local output authoritative + hold a per-workspace cache lock
Independent of hashing: (1) a local build-rule WithArtifact must prefer the artifact the current build just produced over any pre-existing same-coordinate global bldbinary entry (0717, 0824, 0234); (2) kompile should hold an exclusive per-workspace cache lock so a concurrent/straggler invocation cannot repopulate a just-purged cache with a stale evaluation (0649). B closes the concurrency race that makes A's purge-based workarounds silently fail; ideally ship A and B.
C. Surface staleness loudly (mitigation, but valuable diagnostics — not a substitute for A/B)
For every @WithArtifact("<rule>.buildMaven()") resolution, print the exact jar path + version + cache age placed on the test classpath, and warn/fail when (i) a build rule "executes" in single-digit ms after the working tree changed, (ii) a workspace checkout has uncommitted source changes affecting a build-rule artifact, or (iii) a test's @WithArtifact coordinates disagree with a cached local artifact's compile classpath. Cited as "at minimum" in 1630, 1754, 1817, 0154, 0311, 0401, 0413, 0423, 0717, 0824, 0852, 0855, 0649. Explicitly a mitigation per the global anti-band-aid guidance — it makes the defect visible, it does not remove it. Ship only alongside A/B, never instead of them.
D. Documented first-class cache-bust + launcher self-validation (ergonomics; do not let it substitute for A)
Add a documented --clean-cache / --no-cache / force-rebuild mode to scripts/test.bash / kompile-cli that clears the correct two locations for the workspace under test (1622, 1817, 1912, 0258, 0424, 0811, 0852, 1317); make scripts/{build,test}.bash validate the generated jars/KompileCli.jar against the pinned kompile-cli version and regenerate when stale (0635); and fix the docs that still point at ~/.buildcache instead of ~/.aibuildcaches/<slug>/ (0118). Separately (not staleness, but co-filed): give buildtest summaries a way to distinguish a pre-test build-rule failure/timeout from a named-test assertion failure (1645), downgrade routine BuildRuleExecutedEffect/WithArtifactVersionMismatchWarningEffect/BuildScriptStderrEffect from [ERROR] stack traces (1810, 0424, 0852, 0911, 1317), and classify buildscript-bridge SocketTimeoutException as an infra-retry hint (0435, 0635).
8. Verification / definition of done
The fix is proven only by a test that would have caught this class, run on the fixed toolchain:
- Same-version-edit regression test (the core proof). In a hermetic temp workspace: (a) define a
buildMaven() rule + a @file:WithArtifact("<rule>.buildMaven()") test asserting behavior X; run it green. (b) Without bumping the coordinate, edit source so behavior becomes Y (and, in a variant, delete a public member). (c) Re-run. Assert the test now observes Y (or fails to resolve the deleted member) — i.e. the edit is executed. This test must FAIL on the pre-fix toolchain (reproducing the defect ≥ near-100%) and PASS on the fixed one.
- Assert it is NOT a ~1ms cache hit. Assert the post-edit build rule performed a real rebuild — e.g. build duration above a floor and/or a
CacheMiss/rebuild signal in the build-rule result — so a stale same-version hit cannot masquerade as green. (Do not assert on a wall-clock threshold alone; assert on an explicit cache-miss/rebuild signal so the test isn't itself flaky.)
- Cross-layer coverage. Add a variant that leaves a stale global
bldbinary entry for the coordinate and asserts the freshly built local output wins (covers 0717/0234), and a variant that removes a public method and asserts callers no longer resolve it (covers M6/0824).
- Concurrency variant (if B is implemented). Start a straggler build for the workspace, purge, re-run; assert no stale repopulation and no partial red/green (covers 0649).
- Downstream confirmation. On a dev box upgraded to the fixed kompile-cli, re-run the original failing scenarios from ≥2 of the source repos (e.g. BuildTestApi 0311/0401, FakeDropletService 0229/0424) without any manual cache purge and confirm green. Follow the global "reproduce in consumer, fix upstream in kompile-core, verify in consumer" upstream-bug workflow — the defect is in the kompile toolchain, so the fix belongs there, not in per-repo
scripts/.
- Tests are real, not mocked, use in-memory/temp workspaces, close all resources, and follow the Testing Architecture Documentation. Do NOT reduce iteration counts or widen timeouts to make it pass. Verify comprehensiveness with an Opus subagent and run an adversarial Opus review per the global workflow before relying on CI.
9. Complete reference index (all 36 challenge notes)
Base: https://github.com/CodexCoder21Organization/PlanRepository/blob/main/challenges/
- 2026-07-07-1228-stale-kompile-cli-0-0-77-pins-in-repo-scripts-cause-silent.md — Layer (d): stale
kompile-cli ≤0.0.77 pin → 20-min un-timed-Coursier-socket stall; bump to 0.0.78 (PR 207 / kompile-cli 0.0.78).
- 2026-07-07-1622-kompile-local-test-cache-served-stale-urlprotocol-classes.md — Layer (a): UrlProtocol link-state ABI stale; three tests fail on missing new symbols/params; repo-local clear fixes.
- 2026-07-07-1630-buildtestrunner-local-kompile-tests-reused-a-stale.md — M4: 0.0.47→0.0.48 bumped & committed, yet no 0.0.48 jar produced;
normalizeTestSpecs unresolved; BuildRuleExecutedEffect looked like success.
- 2026-07-07-1645-kotlin-build-ci-resolver-pin-investigation-exposed.md — M9/(d): pre-test build-rule timeout mis-attributed to a named test; stale launcher missing
bldbinary handler → NoClassDefFoundError.
- 2026-07-07-1754-urlprotocol-targeted-test-reused-stale-buildmaven-artifact.md — Canonical M1/(a) repro: mplex removed but still negotiated;
succeeded in 1ms; deleted-source not reflected (M6).
- 2026-07-07-1801-buildtestrunner-selected-tests-reused-a-stale-local.md — M4: 0.0.47→0.0.48, bldbinary only has 0.0.46/0.0.47; both projects mis-attributed to AlphaProject until repo cache deleted.
- 2026-07-07-1810-buildtestembedded-local-tests-reused-stale-cached-artifact.md — (a)+M9: fresh coordinate yet 3 empty-project warnings (old behavior); plus harness effect-noise +
UTFDataFormatException.
- 2026-07-07-1817-kompile-test-cache-reused-stale-kotlin-build-ci-artifact.md — (a): even seeding the 0.0.57 bldbinary dir didn't fix the contaminated classpath; workaround = throwaway
--cache-location.
- 2026-07-07-1912-kompile-build-tests-reused-a-stale-local-0-0-2-artifact.md — (a)+(b): kompile-buildrule-enhancer 0.0.2 stale in BOTH
~/.aibuildcaches and bldbinary; javap-verified guard not exercised.
- 2026-07-07-2020-kompile-local-tests-reused-stale-same-coordinate.md — M4: 0.0.218→0.0.219 still stale
gitContext/perftestGitContextForRun; disabled-test version-warnings drowned the diagnosis.
- 2026-07-07-2023-stale-kompile-publish-instruction-rejects-publish-what-was.md — M9 (adjacent): SHARED_CONTEXT.md
--publish flag rejected by KompileCli 0.0.65; use the maven-artifact-publishing CLI instead.
- 2026-07-07-2319-kompile-tests-can-execute-stale-same-version-local-maven.md — M1/M3: DropletServiceServer 0.0.40 WebCron; javap-fresh but runtime stale;
succeeded in 1ms; bump 0.0.41 + clear fixed.
- 2026-07-07-2343-kompile-buildclientresourcesjar-cache-served-stale-nested.md — M5 (nested):
buildClientResourcesJar nested client-impl.jar stale → NoSuchMethodError: BuildRunImpl.getGitContext; even after coordinate bump 0.0.26→0.0.27.
- 2026-07-08-0119-kompile-test-withartifact-buildmaven-served-stale-health.md — (a)/M5: health-check bytecode stale even after cache-buster + repo-cache delete; workaround = switch
buildMaven()→buildFatJar() for a distinct path.
- 2026-07-08-0154-stale-bldbinary-artifact-cache-masked-buildtestapi.md — Layer (b): BuildTestApi 0.0.41
jvmDefault=all-compatibility fix masked; stale jar keeps abstract getters → AbstractMethodError.
- 2026-07-08-0229-kompile-local-test-reused-a-stale-same-version-bldbinary.md — (b): FakeDropletService 0.0.9; interceptor fix looks unfixed until the bldbinary 0.0.9 dir is deleted.
- 2026-07-08-0234-stale-global-bldbinary-cache-masked-build-kotlin-jvm-local.md — (b), repo-local clear NOT sufficient: build-kotlin-jvm 0.0.25 static initializer lists kotlin.directory first; production-incident false negative; must clear BOTH.
- 2026-07-08-0258-kompile-local-cache-served-stale-buildtest-api-buildmaven.md — M7 false-GREEN: full API suite falsely passed; after clearing, 51 fakes correctly failed against newly-abstract methods.
- 2026-07-08-0311-stale-bldbinary-same-version-buildmavenartifact-cache-hid.md — (b): BuildTestApi 0.0.41
BuildTestOptimizerApi unresolved; note author fixed a custom skinny-jar key to fingerprint source; the recurring reference point cited by 0649.
- 2026-07-08-0401-kompile-withartifact-reused-stale-bldbinary-artifact-after.md — M4/(b): 0.0.41→0.0.42 bump, but bldbinary still serves 0.0.41 jar; suggests invalidating older bldbinary entries for the same group/artifact.
- 2026-07-08-0413-kompile-test-runner-reused-stale-local-artifact-abi-after.md — M4/(a): build-watchman 0.0.10→0.0.11 stale FakeApis ABI;
succeeded in 1-5ms; fat-jar javap proves source correct.
- 2026-07-08-0423-kompile-per-repo-cache-served-stale-buildtestapi-interface.md — Layer (c)/(a): BuildTestApi 0.0.42
createUploadSessionStructured "overrides nothing"; succeeded in 1ms; per-repo cache delete fixes.
- 2026-07-08-0424-kompile-test-runs-used-stale-constructor-metadata-after.md — M2/M4: FakeDropletService 0.0.9→0.0.10 stale constructor metadata → overload-resolution ambiguity; plus effect-noise.
- 2026-07-08-0435-kompile-buildmaven-timed-out-in-buildscript-tcp-bridge.md — Confounder (not staleness): buildscript-bridge
SocketTimeoutException in visitMethodInsn; classify as infra retry.
- 2026-07-08-0635-urlprotocol-verification-hit-stale-ignored-kompile.md — Layer (d): ignored
jars/KompileCli.jar still launches 0.0.77 after pin bump → stale artifact + false source errors; also TCP-bridge timeouts.
- 2026-07-08-0717-kompile-test-dependency-resolution-preferred-a-stale.md — (b), resolver prefers stale global over fresh local: KompileRemoteBuildApi 0.0.3
DataCapacityPlan; motivates fix B (fresh local wins).
- 2026-07-08-0811-kompile-local-test-cache-reused-stale-buildmaven-artifact.md — (a)+(b): KompileRemoteBuildEmbedded
planRationale assertion; succeeded in 0-1ms; clearing BOTH → 10/10.
- 2026-07-08-0824-buildtestembedded-local-tests-loaded-stale-bldbinary.md — M6/(b): removed
cleanupOrphanedDroplets still on the stack from stale bldbinary 0.0.221; javap of temp jar shows it gone.
- 2026-07-08-0852-kompile-local-test-cache-served-stale-wui-artifact-and.md — M5 (WUI): KompileRemoteBuildWui
/accuracy fallback HTML stale even after 0.1.4→0.1.5; plus DiagnosticEffect noise, exit 0 after [ERROR] blocks.
- 2026-07-08-0911-buildtest-lease-fix-was-obscured-by-stale-bldbinary.md — M7, production emergency: lease-renewal fix masked by stale bldbinary 0.0.220; plus publish 409-even-with-
--force trap and harness noise.
- 2026-07-08-0917-stale-kompile-cache-masked-the-buildtest-api-0-0-43.md — M4: kotlin-build-ci upgraded buildtest-api 0.0.41→0.0.43 but cached
kotlinbuild.ci.buildMaven() compiled vs older API → "overrides nothing".
- 2026-07-08-1317-buildtestembedded-verification-was-misled-by-stale-same.md — M2/M4 post-rebase: stale 0.0.221 missing
buildLeaseLastRenewedAt et al.; 408/413; harness prints StreamCorruptedException before 413/413 PASSED.
- 2026-07-08-1446-buildtestembedded-local-kompile-cache-returned-stale.md — M4/M7: 0.0.231→0.0.232 stale
sshConnect* params; and earlier the same cache hid a real BUILDTEST_DROPLET_NAME_PREFIX compile error.
- 2026-07-09-0118-local-test-suites-silently-execute-stale-workspace-built.md — Layer (c), the mechanism note: pre-0.0.110 name-only
BuildRuleResultIndex serves post-rebase source stale; live cache is ~/.aibuildcaches/<slug>/ (NOT ~/.buildcache); fixed by manager 0.0.110 (kompile-core #208/PR 210).
- 2026-07-09-0649-kompile-bldbinary-stale-reuse-persists-across-version.md — Concurrency race + partial staleness: stale reuse survives bump AND purge while a straggler repopulates; 1-of-6 red/5-green; motivates fix B (per-workspace lock) + serial runs.
- 2026-07-09-0855-buildtestembedded-selected-test-runner-resolved-stale.md — M2 + hang: stale watchdog symbols despite javap-verified 0.0.231 jar; selected-test path then stalls silently after the warning-heavy metadata scan (needs a heartbeat).
Related standing knowledge (auto-memory): kompile-buildmaven-version-cache (source edits invisible until the build.kts version literal is bumped) and kompile-bldbinary-stale-cache (buildMaven deps keyed by coordinates in ~/.cache/coursier/v1/bldbinary/…; purge after same-version edits). Both are workarounds captured in §6, not fixes.
Filing note (for the PR that lands this handoff)
This repo's handoffs live in PlanRepository/handoffs/ and are named YYYY-MM-DD-<short-kebab-slug>.md (per handoffs/README.md). Suggested path:
handoffs/2026-07-09-stale-kompile-bldbinary-buildmaven-local-cache-reuse-rootcause.md
Handoff PRs into this directory are the standing exception to "never merge without approval" — enqueue via the GraphQL enqueuePullRequest mutation (get the node id from gh pr view <n> --json id), then poll gh pr view <n> --json state until MERGED; never --delete-branch. Supporting artifacts (if any) go under handoffs/artifacts/.