Spec: Fowler-style refactoring review (cloud agent, 2026-08-05). This one deliberately changes API response bodies — review as its own change.
Blocked by: #145
What to change
The API's error vocabulary is inconsistent:
threadId_required (sync/review, sync/split) vs thread_id_required (enrichment/threads, artifacts/publish) vs project_id_required
app/api/digest returns prose ("Invalid JSON body.", "dayKey and question are required.") where every other route returns snake_case codes
- three routes surface raw
error.message as the API code (sync/review, sync/projects, digest) while others return fixed codes like publish_failed
Settle one convention (snake_case codes, thread_id_required style), express it through the apiError helper from the blocking ticket, and update the few client call sites that match on these strings (search lib/ and components/ for each literal before renaming).
Out of scope: new validation behavior; changing HTTP status codes.
Acceptance criteria
Spec: Fowler-style refactoring review (cloud agent, 2026-08-05). This one deliberately changes API response bodies — review as its own change.
Blocked by: #145
What to change
The API's error vocabulary is inconsistent:
threadId_required(sync/review,sync/split) vsthread_id_required(enrichment/threads,artifacts/publish) vsproject_id_requiredapp/api/digestreturns prose ("Invalid JSON body.","dayKey and question are required.") where every other route returns snake_case codeserror.messageas the API code (sync/review,sync/projects,digest) while others return fixed codes likepublish_failedSettle one convention (snake_case codes,
thread_id_requiredstyle), express it through theapiErrorhelper from the blocking ticket, and update the few client call sites that match on these strings (searchlib/andcomponents/for each literal before renaming).Out of scope: new validation behavior; changing HTTP status codes.
Acceptance criteria
app/api/error.messageas an API codemise run lintandmise run testpass