# AiCliSupervisorManagerWui stale-session main-branch drift investigation 2026-08-05 21:00 UTC OBSERVED: Read `out/r13-final-findings.md` and `out/r12-ladder-findings.md`. The pristine `origin/main` control at commit `220554b6fd10dd3925cd7c2f34c765240e2d546c` resolves the production and test SJVM graph to 0.0.49 yet fails `testConcurrentStaleSessionDoesNotInterruptLiveConversation` with the same bounded 20-frame cause-chain rendering seen on the 0.0.52 bump branch. This rules out the SJVM version bump as the source of the changed error text. OBSERVED: The repository discovery workflow located `CodexCoder21Organization/AiCliSupervisorManagerWui` at https://github.com/CodexCoder21Organization/AiCliSupervisorManagerWui. Its default branch is `main`, and its description identifies it as the stateless fleet console for the AiCliHostSupervisor fleet. INFER: The investigation must identify a runtime or test-fixture artifact outside the checked-in SJVM pins whose resolution changed after the green 2026-08-04 13:39 UTC CI run. No tracked assertion change is authorized unless a complete resolution comparison refutes that drift mechanism. 2026-08-05 21:10 UTC OBSERVED: A fresh ordinary-cache run of `tests/testConcurrentStaleSessionDoesNotInterruptLiveConversation.kts` reproduced the failure (exit 1; test body 3.0 seconds). The console and structured logs are `out/r14-baseline-concurrent.log` and `out/r14-baseline-concurrent.xml`. OBSERVED: Searching the resolved jars found the exact renderer in `net.javadeploy.sjvm:libSJVM-jvm:0.0.52`, class `net.javadeploy.sjvm.util.HostThrowableDescriptionKt`. `javap -c -p` shows that class emits both `Stack trace of the deepest cause described above:` and ` more frames omitted (frame limit is 20)` from its bounded host-throwable description path. The corresponding class does not exist in the cached 0.0.49 jar. OBSERVED: The main checkout's production compile graph resolves `libSJVM-jvm-0.0.49.jar`, but the failing test's generated local build-rule dependency record resolves `aicli.supervisormanager.wui.buildMaven()` to `libSJVM-jvm-0.0.52.jar`. The record is `/home/leslie/.aibuildcaches/_tmp_claude-501_-code_87a9b641-ea5c-4fc5-bd6b-479980e599f4_scratchpad_workspace_wui-drift/buildRuleResultIndex/174e13cdf9dbf6a25e09b63c3bb17c8b4300384b30fa86aa5d6f77a0987899f7.json`. OBSERVED: The disagreement comes from the mutable local Maven coordinate `aicli.supervisormanager:wui:0.0.36`. The global bldbinary POM for that coordinate was written at 2026-08-05 19:45:46 UTC from `origin/sjvm-0.0.52-bump`, whose build script keeps the same WUI coordinate while changing its three SJVM dependencies to 0.0.52. Main's test then consumes that cached POM through `@file:WithArtifact("aicli.supervisormanager.wui.buildMaven()")`; Maven mediation selects the cached transitive 0.0.52 over the test's direct 0.0.49 declarations. OBSERVED: The kotlin.directory metadata for `net.javadeploy.sjvm:libSJVM-jvm` has `20260805193027`, after the green 2026-08-04 13:39 UTC CI run. This is consistent with the bump branch first being able to write the 0.0.52-bearing local POM on August 5, but the publication alone does not move a clean main graph because main names 0.0.49 exactly. OBSERVED: A second pristine main clone run with an isolated empty Coursier cache generated `aicli.supervisormanager:wui:0.0.36` with a 0.0.49 POM and PASSED the unchanged concurrent stale-session test (exit 0). Its logs are `out/r14-clean-cache-concurrent.log` and `out/r14-clean-cache-concurrent.xml`. INFER: The August 4 green and August 5 red are fully explained without a third-party latest/range dependency: the green worker had a clean local build-rule repository, while the red local run inherited a same-coordinate POM produced by the separate SJVM bump branch. The repo-controlled hermeticity defect is that these tests ask for the Maven build result, including mutable generated transitive metadata, even though they already enumerate their complete runtime dependencies explicitly. INFER: The narrow fix is to make the two stale-session tests consume `buildSkinnyJar()` instead of `buildMaven()`. This keeps the locally built WUI classes but removes the mutable generated POM from dependency mediation, leaving the tests' explicit 0.0.49 declarations authoritative; the checked-in error assertions remain unchanged. 2026-08-05 21:18 UTC OBSERVED: Applied the narrow fix on branch `fix-stale-session-error-drift`: only the first `@file:WithArtifact` declaration in each tracked stale-session test changed from `aicli.supervisormanager.wui.buildMaven()` to `aicli.supervisormanager.wui.buildSkinnyJar()`. No assertion, timeout, concurrency parameter, fixture coordinate, or production source changed. OBSERVED: With the ordinary global cache still containing the 0.0.52-bearing `wui:0.0.36` POM, both tracked tests pass under `_JAVA_OPTIONS='-Xmx128m -XX:+UseSerialGC'`: `testConcurrentStaleSessionDoesNotInterruptLiveConversation` PASS and `testStaleSessionDoesNotCloseLiveConversation` PASS. The build-rule result for `buildSkinnyJar()` contains only the locally built WUI jar path, so dependency mediation is controlled by each test's explicit declarations. OBSERVED: Committed the repair as `83a8d8c` (`Keep stale-session tests on explicit dependency pins`), fetched and rebased on the unchanged `origin/main` at `220554b6`, and reran both tests after the mandatory rebase. Both passed again; logs are `out/r14-postrebase-concurrent.log`, `out/r14-postrebase-concurrent.xml`, `out/r14-postrebase-stale.log`, and `out/r14-postrebase-stale.xml`. INFER: Test-comprehensiveness review found no assertion gap introduced by the repair: both public HTTP behaviors remain covered end to end, both still require the exact historical 0.0.49 error string, and the concurrent test still verifies the live conversation remains responsive and cached. The change removes only an unintended dependency source. INFER: Adversarial review found no production regression or test weakening. `buildSkinnyJar()` delegates to the same local WUI build and changes only whether its generated Maven POM participates in test resolution; the complete dependency lists already present in each test are exercised successfully on the deliberately contaminated cache that reproduced the bug. 2026-08-05 21:25 UTC OBSERVED: Pushed `fix-stale-session-error-drift` and opened the dedicated repair PR: https://github.com/CodexCoder21Organization/AiCliSupervisorManagerWui/pull/36 (`Keep stale-session tests on explicit dependency pins`). The PR body records the renderer class, mutable local-POM mechanism, August 5 metadata timestamp, clean-cache control, and targeted test results. No merge or CI watcher was started. OBSERVED: In a separate fresh checkout, locally rebased `origin/sjvm-0.0.52-bump` onto `origin/fix-stale-session-error-drift`. The resulting local history is `70e2434` (`Adopt libSJVM 0.0.52 runtime`) on top of repair commit `83a8d8c`; this local rebased branch was not pushed and no bump PR was opened. OBSERVED: Bump validation run 1/5 FAILED (exit 1; test body 1.8 seconds) under `_JAVA_OPTIONS='-Xmx128m -XX:+UseSerialGC'`. The response kept the exact expected `renderScreenWithCursor` / `INVALID_PARAMS` / stale-session / live-session prefix and ended with the 0.0.52 renderer's 20-frame bounded stack (`... 68 more frames omitted (frame limit is 20)`), while the rebased bump test still requires the 0.0.49 `cause: null` suffix. Full logs are `out/r14-bump-concurrent-01.log` and `out/r14-bump-concurrent-01.xml`. INFER: This failure is deterministic and fully explained: the repair makes each test's explicit dependency pins authoritative, so main uses 0.0.49 and passes its old exact contract, while the bump branch now genuinely uses 0.0.52 and exposes that release's intentional bounded cause-chain rendering. The repair solves main's cross-branch cache drift but cannot make an unchanged 0.0.49 error assertion valid on the deliberately upgraded 0.0.52 branch. INFER: The inherited p9 rule requires an immediate stop on any checked-in repetition failure. Therefore bump repetitions 2-5 and all p9 targeted neighbors were not run. The next bump step requires the already-authorized, strictly structural assertion update in exactly the two stale-session tests, but applying it after a counted validation failure would violate the current hard-stop instruction; it should be done in the orchestrator's next bump turn before restarting validation from run 1.