fix(feedback): publish the advisory mount's own typed state - #2724
Merged
Merged
Conversation
|
This was referenced Sep 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
The deferred project-open advisory mount published no state of its own. The pre-mount placeholder owner (
ProjectOpenProximityReadOwnerV1::mount) guessed whether a mount was in progress from two scheduler reads:retained_text_owner_freshness_for_scope(..).is_some() || latest_feedback_generation_for_scope(..).is_some()(added by #2228, widened by #2668). A mount that failed terminally still left a sealed generation behind, so the placeholder kept reportingMounting. Every advisory-cycle request then waited out its whole dispatch deadline. Theponytail:note onmount()admitted this.Fix
watchchannel,AdvisoryMountStateV1, with four states:AwaitingGeneration,Mounting,Mounted, andFailed(AdvisoryMountFailureV1). The owner holds it throughAdvisoryMountPublisherV1. Every exit publishes a verdict. The direct mount at project open publishesMounted. The deferred task publishesMounted, orFailedwith its cause (code index disabled, feedback cycle, LSP grant, LSP owner, or advisory owner). Dropping the publisher without a verdict (a cancelled task, or a closed scheduler channel) publishesFailed(Abandoned). This mirrorsProjectRuntimeBuildReservationLeaseV1.mount()reads only that state. Itsinvoke()returnsfeedback.advisory-cycle.mount-failed(unavailable, retrynever,contact_administrator) once the state isFailed.DaemonAdvisoryCycleMountV1::Mountingnow carries a future that resolves when the owner's state changes.answering_advisory_cycle_ownerwaits on both the registry publication and that future, so a failure ends the wait right away.Mounting. Anything else isAwaitingGeneration, which keeps the immediate retryable warming answer on a cold checkout.ponytail:note.Proof
Fail before (
origin/master9b79b48 plus only the new test),cargo test -p tracedecay --lib -- daemon::production_harness::advisory_cycle_language_journey_test:Pass after (rebased on 51aa2b8):
The new test goes through the production composition harness. It holds a foreign live hook-notice queue for the reopened checkout's scope, which is the production registry conflict that makes
register_production_advisory_ownerfail on every attempt. It then assertsproblem.code == "feedback.advisory-cycle.mount-failed",kind == "unavailable",legal_actions == ["contact_administrator"], and an elapsed time under half the capability's canonical dispatch ceiling.Other focused suites:
cargo test -p tracedecay-daemon-service --lib -- feedback advisory: 14 passed.cargo test -p tracedecay --test mcp_suite --features test-transport -- feedback_diagnostics_test feedback_list_test affected_tests_test: 4 passed.cargo clippy -p tracedecay-daemon-service -p tracedecay --all-targets -- -D warnings: clean.cargo fmt --all -- --check: clean.Runtime journey with the debug
tracedecayCLI (1.0.0-beta.63+1331a4b3d3), an isolated HOME and data dir, and one daemon at a time undersystemd-run --user --scope -p MemoryMax=6G -p MemorySwapMax=1G. The steps wereinit, advisory cycle, stop, restart, then the first advisory call after the reopen:The terminal-failure path has no CLI-reachable trigger; the harness test above covers it through the production owner path.