Tracking: chatd Debug Logs — Deferred Review Items
This issue tracks deferred review items from the chatd debug logs PR stack (#23913–#23921) that mafredri flagged as needing a tracking artifact.
PR #23914 — Types, Context, Model Normalization
PR #23915 — Recorder, Transport, Redaction
PR #23916 — Service, Summary, Aggregation
PR #23917 — Chat Lifecycle Wiring
PR #23918 — HTTP Handlers, API Docs
PR #23919 — Frontend API, Panel Utils
PR #23920 — Debug Panel Components, Settings
PR #23913 — Database Schema, SDK Types
PR #23921 — Storybook Stories
Tracking: chatd Debug Logs — Deferred Review Items
This issue tracks deferred review items from the chatd debug logs PR stack (#23913–#23921) that mafredri flagged as needing a tracking artifact.
PR #23914 — Types, Context, Model Normalization
normalizeToolResultOutputtest coverage: 7/8 type-switch arms untested including nil guards, error-to-string conversion, media placeholder formatting, and default JSON fallbackGenerateObjecttest coverage: unique paths (normalizeObjectCall,normalizeObjectResponse, nil guard,structured_outputmetadata) have 0% test coveragefinalize, leaving step permanentlyin_progressonce real recorder lands. Considercontext.AfterFuncorruntime.SetFinalizerstepHandle.finishsynchronization: addsync.OncetostepHandle.finishitself or serialize through holder mutex to prevent data race when recorder inherits the patternPR #23915 — Recorder, Transport, Redaction
RedactJSONSecrets, non-JSON response body handlingPR #23916 — Service, Summary, Aggregation
FinalizeStaleusestime.Now()directly: Resolved —quartz.Clockinjected viaWithClockoption;FinalizeStale, heartbeat tickers, andstepHandle.finishall uses.clock.Now()ReasoningTokensSummedAcrossStepsandZeroReasoningTokensOmitsFieldtests added withupdateTestStepWithFullUsagehelpernullJSONtyped nils:nullJSONmaps both nil and typed nils toNullRawMessage{Valid: false}— intentional for write-once-finalize pattern, not a correctness issuefor {}loop iteration cap: Resolved —maxCreateStepRetries = 10cap andctx.Err()check between iterationsTouchStepuses fullUpdateChatDebugRun: Resolved — added dedicatedTouchChatDebugRunUpdatedAtSQL query that only bumpsupdated_atCreateStepfinalization guard: Resolved — addedAND run.finished_at IS NULLtoInsertChatDebugStepWHERE clause;sql.ErrNoRowsmapped toerrRunFinalizedstepHandle.generationdead code: Resolved — removed field and increment<=to<extractEndpointLabeldeserializes fullAttempt: Resolved —attemptLabelminimal projection structerrRunFinalizedguard test coverage: Resolved —TestService_CreateStep_RejectsFinalizedRunaddedtime.Now()in recorder.go: Resolved — replaced withh.svc.clock.Now()truncateRunesduplicatesutil/strings.Truncate: Resolved — replaced withstringutil.TruncateexpectUpdateStepshallow JSON assertions: model tests check.Validflags but not JSON content; needs provider-specific fixture dataGenerate/GenerateObject: Resolved -- addedlaunchHeartbeatcalls in bothGenerateandGenerateObjectto keep the step alive during blocking provider callsPR #23917 — Chat Lifecycle Wiring
NewServicecall: Resolved — chatd now initializes thedebug service lazily through a factory and only materializes it on demand
processChat/finishActiveChatinterleaving: Resolved — finish-timestatus publishing now re-reads the chat state and suppresses stale final
updates after a newer write wins
newDebugModelnil guard: Resolved — debug model wrapping now routesthrough guarded debug-service accessors instead of assuming the service is
always present
that wraps the model before run creation and finalizes with a bounded,
uncancelled context
chatd.go:4215deferred cleanup: Resolved — edit/archive debug cleanupnow uses retrying best-effort cleanup with bounded timeouts plus the existing
stale-finalization safety net
chatd.go:1311deferred item: Resolved — startup stale-finalizationnow reuses the existing debug service instead of eagerly constructing one
chatd.go:1918deferred item: Resolved — active-chat finalization nowavoids publishing stale terminal state after newer control-path updates
quickgen.go:784deferred item: Resolved — quickgen debug lifecycleDeleteChatDebugDataAfterMessageIDnow accepts a
started_beforetimestamp so retried cleanup does not deleteruns created by a replacement turn that raced ahead of the retry window
debugService()(forces lazy init) instead ofexistingDebugService()sostale debug rows from a previous crash are finalized even when no request
has triggered initialization yet
setup is centralized so title and push-summary generation share the same
guarded create/finalize flow
PR #23918 — HTTP Handlers, API Docs
getChatDebugRuns,getChatDebugRun,getChatDebugLoggingEnabled,putChatDebugLoggingEnabledneed test coverageChatDebugEventzero consumers: type defined but unused in Go/TS — wire or removedebug_logs_enabled_overridevsdebug_logging_enablednaming mismatchChatDebugSettings/UpdateChatDebugLoggingRequesttype sharing:DebugLoggingOverrideSetonly meaningful for user endpointNullableBool.MarshalJSONwire format: produces object instead ofnullfor unset statePR #23919 — Frontend API, Panel Utils
debugPanelUtils.test.tstest coverage: 1 test for 15 exported coercion functions across 1146 linesPR #23920 — Debug Panel Components, Settings
erroredstatus missing fromERROR_STATUSES, causing infinite 5s pollingstate.datatyped asunknown:debugQueries.ts:35should be properly typedtool_choicebareString()onunknown:DebugStepCard.tsx:178uses unsafe castresponse.contentrendering:DebugStepCard.tsx:346has no content limitDebugPanel.tsx:23sort comparatorDebugRunList.tsx:16dead codeAgentChatPageView.tsx:317PR #23913 — Database Schema, SDK Types
UpdateChatDebugStepoperation updatable: defense was acknowledged, no ticketPR #23921 — Storybook Stories