The daemon answers source-edit and graph-tool requests with a typed ApplicationProblem. Since the typed problem detail change, that problem carries kind, retry, legal_actions, and detail. Two client adapters turn the problem into a TraceDecayError::ProjectRoute { reason_code, retryable, detail: String } before rendering, so MCP and the CLI see only a code, a retry flag, and the message string:
tracedecay_mcp::handlers::edit::render_source_edit_outcome calls problem.into_source().into_trace_decay_error()
tracedecay::mcp::tools::handlers::application_surface::graph_tool_problem_error (the graph-tool client path)
Concrete loss: a source-edit writer lock that misses its 30s admission deadline is now saturated with detail = {kind: lock_deadline, resource: "source-edit writer lock", deadline_ms: 30000} on the daemon wire (see invocation::source_edit::tests::a_missed_writer_lock_deadline_is_retryable_capacity_with_typed_detail). But tracedecay tool str_replace and MCP tracedecay_str_replace report it as a JSON-RPC project-route error with data.detail set to the rendered sentence. structuredContent.problem is absent and legal_actions is dropped.
Application-surface and retained tools already render the whole record: structuredContent.problem on MCP, the envelope on --json, and labelled lines in markdown. Source edit and graph tools should render the same way instead of converting to ProjectRoute. Several source_edit_reconcile_test expectations currently pin the flattened project route error (...) strings and will move with the fix.
The code-index publication-corruption refusals raised directly as ProjectRoute errors are in the same situation. They are code_index_publication_corrupt and the branch_publication refusals, and they format "{reason}; {remediation}" into the detail string.
The daemon answers source-edit and graph-tool requests with a typed
ApplicationProblem. Since the typed problemdetailchange, that problem carrieskind,retry,legal_actions, anddetail. Two client adapters turn the problem into aTraceDecayError::ProjectRoute { reason_code, retryable, detail: String }before rendering, so MCP and the CLI see only a code, a retry flag, and the message string:tracedecay_mcp::handlers::edit::render_source_edit_outcomecallsproblem.into_source().into_trace_decay_error()tracedecay::mcp::tools::handlers::application_surface::graph_tool_problem_error(the graph-tool client path)Concrete loss: a source-edit writer lock that misses its 30s admission deadline is now
saturatedwithdetail = {kind: lock_deadline, resource: "source-edit writer lock", deadline_ms: 30000}on the daemon wire (seeinvocation::source_edit::tests::a_missed_writer_lock_deadline_is_retryable_capacity_with_typed_detail). Buttracedecay tool str_replaceand MCPtracedecay_str_replacereport it as a JSON-RPC project-route error withdata.detailset to the rendered sentence.structuredContent.problemis absent andlegal_actionsis dropped.Application-surface and retained tools already render the whole record:
structuredContent.problemon MCP, the envelope on--json, and labelled lines in markdown. Source edit and graph tools should render the same way instead of converting toProjectRoute. Severalsource_edit_reconcile_testexpectations currently pin the flattenedproject route error (...)strings and will move with the fix.The code-index publication-corruption refusals raised directly as
ProjectRouteerrors are in the same situation. They arecode_index_publication_corruptand thebranch_publicationrefusals, and they format"{reason}; {remediation}"into the detail string.