fix(mcp): render parked refusals and graph-tool errors as typed fields - #2340
Merged
Merged
Conversation
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Sep 27, 2026
Closed
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.
Fixes #2280
What was wrong
tracedecay sync/tracedecay init) and background freshness-probe refusals carried the park as typedParkeddetail inside the route error, but every consumer still flattened it. The CLI printedDisplay: one sentence,The code index for this worktree is parked; remedy: …; cause: …, and the 512-byte bound on that sentence cut the cause off. The daemon log did the same (error=project route error (…): …). The MCP JSON-RPC problem data had the detail but nokind. Branch publication still raised the same park as aformat!("{reason}; {remediation}")string in two places.unavailable/authority, which claims a missing authority. It is an internal failure.Change
CodeIndexConvergenceParkedV1::publication_authority_corrupt_error(contracts) is now the one constructor for this refusal. Admin sync, the freshness probe, and both branch-publication sites use it, and the server-local copy is deleted.project_route_problemtakes the problemkindfor a typed detail fromApplicationProblem::from_detail, so a parked refusal is{kind: unavailable, code, reason_code, retryable: false, detail: {kind: parked, cause, remedy, retries_on_wake}}.label: valueline per detail field (ApplicationProblemDetailV1::labelled_fields). Nothing is truncated.reason_code,cause,remedy,retries_on_wakeas tracing fields.invalid_request, route refusals areunavailableunder their reason code, typed details/lock deadlines keep their detail, and any other handler failure isexecution_failed(graph_tool.failed,retry: never,legal_actions: [contact_administrator]), the contract's internal-failure kind. The test(mcp): pin owner refusals as typed isError problems #2319isErrorproblem-record shape is unchanged. The four refactor(mcp): answer info and runtime reads through their owners #2335 pins for a broken registry table now assertexecution_failed.Fail before / pass after
With the behavioral pieces reverted (tests kept), these fail with the literals below and pass on this branch:
mcp::tools::handlers::dispatch_tests::admin_sync_reports_terminal_publication_corruption_without_queueing: wire data lacked"kind": "unavailable", "code": ….tool_errors::tests::project_route_parked_detail_stays_structured_on_the_wire: same.commands::index::init_bootstrap_tests::brokered_init_prints_a_parked_refusal_as_fields: fixture daemon answers with the realtool_error_response. Left wasproject route error (code_index_publication_authority_corrupt): The code index for this worktree is parked; remedy: …; cause: … xxxx(cut); right isproject route error (…)\nParked cause: <full 600+ byte cause>\nParked remedy: run \tracedecay daemon restart`\nRetries on wake: false`.mcp::server::background_refresh_writer_tests::parked_freshness_probe_logs_cause_and_remedy_as_fields: lefterror=project route error (…): … parked; remedy: …; cause: … xxx(cut); rightreason_code="code_index_publication_authority_corrupt" cause="<full>" remedy="run \tracedecay daemon restart`" retries_on_wake=false`.code_index_scheduler::tests::branch_publication_tests::mid_wait_branch_publication_surfaces_terminal_publication_park: typed detail wasNone.mcp::tools::handlers::application_surface::tests::every_graph_tool_handler_error_renders_as_a_kinded_problem: io error kind wasunavailable, expectedexecution_failed.Runtime proof (debug CLI, isolated
HOME, one daemon undersystemd-run --scope -p MemoryMax=6G)Corpus: a scratch git repo. Its code-index publication was corrupted (garbage generation manifests) and the scope store made read-only, so the automatic reset fails and the worktree parks terminally.
Master binary,
tracedecay sync:(the cause is cut before
code-generation retention storage failure: Permission denied (os error 13))Branch binary, same profile,
tracedecay sync(exit 1):Daemon JSON-RPC error data:
{"code": "code_index_publication_authority_corrupt", "detail": {"cause": "…Permission denied (os error 13)", "kind": "parked", "remedy": "…", "retries_on_wake": false}, "kind": "unavailable", "reason_code": "code_index_publication_authority_corrupt", "retryable": false, "tool": "tracedecay_admin_sync"}Daemon log after a read triggered the freshness probe:
Graph tools already rendered the whole record on master (
tracedecay tool tracedecay_rank --args '{"direction":"bogus"}' --json:isError: true,problem.kind: invalid_request); that is unchanged.Suites
parked publication admin_sync graph_tool brokered_init project_route freshness_probe, after merging current master):tracedecaylib 38 passed;tracedecay-clibin 5 passed;tracedecay-code-index-runtimelib 87 passed;tracedecay-mcplib 9 passed.mcp_suite(rebased tip, CLI built first, run outside any memory scope):test result: ok. 580 passed; 0 failed. Master itself now has 580 tests: since this lane started, master removed 6 and added 1, and this PR adds or removes none. Two earlier runs under heavy shared load each hit unrelated readiness timeouts (code index did not publish … after 20000 ms; composition gate … waiting=88, and onediff_contexttruncation test that passes alone). The clean run above is the evidence.cargo clippy -p tracedecay-contracts -p tracedecay-code-index-runtime -p tracedecay-mcp -p tracedecay -p tracedecay-cli --all-targets -- -D warnings: clean with and withouttracedecay/test-transport,tracedecay/test-helpers,tracedecay-cli/test-transport.cargo fmt --all -- --check: clean.dashboardcontracts:check:contracts up to date.cargo check --workspace --all-targets --target x86_64-pc-windows-gnu --features tracedecay/test-transport,tracedecay/test-helpers,tracedecay-cli/test-transport: exit 0. Nocfg(windows)code touched.Left as is
tracedecay statusalready reports the park ascode_index_freshness.parked.{reason, remediation}fields in--json. Its human warning line still joins them in one sentence, and this PR does not change it.