Cover quarantined identity conflicts in the Context runner

SI
5d ago
+91-2

Summary

With database migration 20261010211900_context_identity_conflict_quarantine.sql, commit_spotify_context no longer raises when a Spotify track is already mapped to a different ISRC. It returns a failed request with an identity_conflict: … error and output.identityConflicts.

  • Runner. runContextRequest already passes that record through unchanged. lib/context/__tests__/identityConflictRead.test.ts pins this behavior: the quarantined record comes back as-is, and fail_context_request is not called, so the specific error is not overwritten. A resolved request retries through the ordinary claim path.
  • Workflow. Previously, contextWorkflow went on to recordContextPlanStep for a failed request. That step throws "Context request is not ready for planning" when CONTEXT_RECORD_BLOCKED_PLAN_ENABLED=true, so the run failed with a misleading error. The workflow now returns a failed request without planning.
  • Docs. lib/context/README.md "Persistence and identity" and SCENARIOS.md S09 describe the quarantine accurately:
    • A legacy mapping gets a conflict link.
    • An accepted mapping is reported, not downgraded.
    • Nothing is accepted, and brief refuses the request.
    • A later accepted observation promotes or closes the quarantined link.
    • Artist ambiguity still rejects.

Refs recoupable/app#2119 (child of epic recoupable/app#2116).

Merge sequencing

docs recoupable/docs#363 → database recoupable/database#100 → api (this PR). No app PR. The early return in contextWorkflow is safe before or after the migration. The persisted error uses the same identity_conflict: code prefix as the open sibling recoupable/api#1001 (#2126), so callers see one format. This PR does not touch runContextRequest.ts, processContextOperation.ts, callContextRpc.ts, schema.ts or any file changed by api#981/#983/#985–#991/#996.

Verification

  • Ran: pnpm exec vitest run lib/context app/workflows/context → 71 files passed, 8 skipped (opt-in live tests); 333 tests passed, 8 skipped, 0 failed.
  • Ran: pnpm exec eslint app/workflows/context/contextWorkflow.ts app/workflows/context/__tests__/contextWorkflow.test.ts lib/context/__tests__/identityConflictRead.test.ts → exit 0.
  • Ran: pnpm exec prettier --check on those three files plus lib/context/README.md and lib/context/SCENARIOS.md → clean.
  • Ran: pnpm exec tsc --noEmit → 199 errors, the same count as on origin/main. All are in unrelated __tests__ files (lib/tasks, lib/trigger, lib/chats, lib/credits, lib/messages, …). None are under lib/context or app/workflows/context.
  • Red → green:
    • contextWorkflow.test.ts "returns a failed request … without planning" failed against the previous contextWorkflow.ts (the plan step was called) and passes with the early return.
    • identityConflictRead.test.ts characterizes existing runner behavior and was green on its first run. The behavioral RED→GREEN for the quarantine itself is in the database PR.
  • Not verified: hosted deployment, a real Vercel Workflow execution, live Spotify, production database, HTTP/MCP transport parity for the failed request shape.

Out of scope / known gaps

  • No new operation, Zod schema or contract fixture (recoupable/app#2118 owns schema.ts/contract tests).
  • No review UI or accept/correct/withdraw operations for conflict links (recoupable/app#2124).
  • Artist-identity ambiguity still rejects transactionally.

🤖 Generated with Claude Code