Sync Issue Traceability#
When decant sync ingests session transcripts, parse failures and cross-message linkage anomalies are recorded as ingest issues. The traceability system connects those issues back to the affected sessions — surfacing them in the CLI via a health recommendation, exposing them through the REST API, and rendering badges in the UI.
Issue Codes#
Five issue codes are defined in src/model.ts:
| Code | Category | Meaning |
|---|---|---|
unparsed_line | Actionable (data loss) | JSON parse failure; raw transcript line could not be read |
unknown_record_type | Informational | Unrecognized record type; possible format drift |
orphan_tool_result | Informational | Tool result with no matching tool use |
duplicate_tool_use_id | Informational | Tool use ID appeared more than once |
duplicate_tool_result | Informational | Multiple results for the same tool use ID |
Each session summary exposes two derived counts: ingest_issue_count (actionable, unparsed_line only) and informational_ingest_issue_count (sensors) .
Detection Layers#
Issues are detected at two points during ingest:
- Parse-time — JSON failures in per-source parsers produce
unparsed_linerecords stored directly inParsedSession.issues. - Post-parse linkage —
src/diagnostics.tsscans cross-message tool references and emitsorphan_tool_result,duplicate_tool_use_id, andduplicate_tool_resultcodes.
All results land in the ingest_issue table, keyed by source_path (the transcript file path), not by session ID. Sessions are joined to their issues via this path column.
API Endpoint: GET /api/sessions/:id/issues#
The endpoint is registered in src/server.ts and delegates to sessionIngestIssues() in src/query.ts.
Response: an array of SessionIngestIssue objects:
{ code, line_no, error, raw_line, created_at }
- Returns
[]if the session has no source file or no issues. - Returns a
session_not_founderror envelope when the session ID is unknown. raw_lineis included for local debugging but is never logged server-side.
CLI Hints#
decant sync --json includes issues (total count) and issues_by_code (per-code breakdown) in its output . When issues > 0, the JSON output also includes issues_hint, a shell command string for inspecting affected sessions. This is the recommended way to get a machine-readable snapshot immediately after a sync.
Stderr hint — when issues are detected and output is not in JSON mode, decant sync prints a hint to stderr showing how to filter decant ls --json output with jq to find sessions with ingest issues:
inspect affected sessions with: decant --db '/path/to/db' ls --json | jq '[.[] | select(.ingest_issue_count + .informational_ingest_issue_count > 0)]' (issue detail: GET /api/sessions/:id/issues under `decant serve`)
The hint includes:
- The
--dbflag ifDECANT_DBis set or--dbwas passed (omitted when using the default archive) - A jq filter selecting sessions where
ingest_issue_count + informational_ingest_issue_count > 0 - A reference to the
GET /api/sessions/:id/issuesendpoint underdecant servefor detailed issue information
The database path is shell-quoted (via shellQuote()) to handle special characters safely, so the hint remains copy-pasteable even when the archive lives under a directory with a space in it.
Health recommendation — when diagnostics exceed a threshold across recent sessions, the recommendations engine in src/recommendations.ts emits a signal:
"N recent sessions ingested with diagnostics"
The detail explains what percentage of the last 30 days' sessions carry issues, and the suggestion directs users to file an issue with decant sync --json output. The count is computed via a SQL join on session → ingest_issue (excluding unparsed_line from the informational tally):
SELECT COUNT(DISTINCT s.id) AS affected
FROM session s JOIN ingest_issue ii ON ii.source_path = s.source_path
WHERE <30-day window> AND <visible sessions> AND ii.code != 'unparsed_line'
Surface this recommendation with decant recommendations ls.
UI#
Session detail views display an ingest issue badge rendered by src/ui/ingest-issues.ts. Unknown record type summaries are grouped and shown inline, letting users see format-drift signals without leaving the session view.
Key Files#
| Purpose | File |
|---|---|
| API route handler | src/server.ts:446-451 |
sessionIngestIssues() query | src/query.ts:884-900 |
SessionIngestIssue type | src/query.ts:870-876 |
| Issue code definitions | src/model.ts:176-182 |
| Linkage diagnostics | src/diagnostics.ts:6-51 |
| Health recommendation logic | src/recommendations.ts:906-942 |
| CLI sync output | src/cli.ts:200-242 |
| UI badge rendering | src/ui/ingest-issues.ts |