Add Context release runbook with guard test
Summary
Adds docs/context-release-runbook.md, the single release runbook for the Context Engine release gate, plus a vitest guard that keeps it honest. The runbook covers: the state vocabulary (implemented / fixture-tested / connected / deployed / live-verified) and what each repo PR may claim; the docs → database → api → app sequence with the ordered list of all 37 context migrations and what each unlocks (citing the database README "Rollout and rollback" policy); the rollback switches (CONTEXT_GUEST_ENABLED, CONTEXT_GUEST_ORIGINS, CONTEXT_RECORD_BLOCKED_PLAN_ENABLED, CONTEXT_SPOTIFY_RELEASE_VERIFY_ENABLED, CONTEXT_SPOTIFY_RELEASE_TRACK_ISRC_ENABLED, app CONTEXT_API_URL) with the "revert app, then api; keep additive tables, receipts and snapshots; never drop Context tables as routine rollback" rule; a table of all 27 shared HTTP/MCP action literals (4 release-case + 23) with required migrations, switches and their reported state; and a verification checklist whose fixture rows record this PR's runs and whose hosted smoke steps are each marked "not performed in this PR". lib/context/__tests__/contextReleaseRunbook.test.ts derives the action literals and brief purposes from contextOperationSchema and the runtime CONTEXT_* switches from non-test files, so a new action, purpose or switch fails the test until the runbook names it. One link line is added under lib/context/README.md "## Validation". This advances #2134's Done-when items on documented deployment sequence, distinguishable states and rollback guidance; it performs no deployment and claims no hosted verification.
Backward compatibility of earlier api code with the newest migrations is stated as not verified: several migrations replace functions in place (commit_spotify_context, save_context_execution_outcome, the enrichment claim/complete functions, list_context_release_cases, save_context_brief), and the runbook asks the rollback drill to confirm the specific target.
Refs recoupable/app#2134 (child of epic recoupable/app#2116).
Merge sequencing
docs → database → api → app. No database or app PR for this ticket.
Docs: the public purpose enums still lack company_onboarding on docs main. recoupable/docs#360 (ticket #2130) adds it with a purpose description, the assessment_scope/next_steps response text and an example; recoupable/docs#358 (draft) and this ticket's recoupable/docs#365 make the same enum edit and conflict with it. docs#365 is now a draft marked superseded by docs#360; only one of the three should merge. This api PR does not depend on any of them.
In-flight sibling PRs that add Context actions or switches (open as of 2026-10-10). Their names are pre-listed in runbook section 4.1, so merging any of them before or after this PR does not fail the guard on the merged head; when one merges, its names should be moved from 4.1 into the shipped table (or 3.1) in that PR or the next:
- api#981 + database#89:
read_company_baseline - api#983 + database#90:
attach_evidence,list_evidence_attachments,read_evidence_attachment - api#985 + database#92:
list_evidence_versions - api#986–#991 + database#94/#95: api#991 adds switch
CONTEXT_ORIGINAL_INTAKE_ENABLED - api#1004 + database#99:
read_document_history - api#1008 + database#102:
withdraw_source - api#1017 + database#106:
cancel - api#1019 + database#107:
ingest_video - api#1022 + database#110:
resolve_songwriter_identity - api#1023 + database#111:
ingest_unreleased_recording,ingest_planned_release - api#1024 + database#112:
record_company_relationship,list_company_relationships
A sibling PR opened after this list (or a name that appears nowhere in the runbook) still fails the guard until it adds a line.
Verification
- Ran:
pnpm exec vitest run lib/context/__tests__/contextReleaseRunbook.test.ts— 4 passed. - Ran:
pnpm exec vitest run lib/context— 68 files passed, 8 skipped (76 files); 330 tests passed, 8 skipped (338 tests), 0 failed. - Ran:
pnpm exec vitest run app/workflows/context app/workflows/contextGuest— 3 files, 4 tests passed. - Ran:
pnpm exec eslint lib/context/__tests__/contextReleaseRunbook.test.ts— clean;pnpm exec prettier --checkon the test, runbook and README — "All matched files use Prettier code style" (vacuous for the two.mdfiles:*.mdis in.prettierignore). - Ran:
pnpm exec tsc --noEmit— 199 pre-existing errors in 66 unrelated files (65__tests__files pluslib/mcp/extension/registerRecoupExtension.ts); zero errors inlib/context,docs/or any changed file. - Ran: simulated merges (
git merge-tree --write-treeof this branch with each sibling branch, tree extracted, guard run on the merged tree) for api#981, #983, #985, #991, #1004, #1008, #1017, #1019, #1022, #1023, #1024 — guard 4/4 passed on all 11. The threecodex/*evidence branches conflict inlib/context/README.md/ OAuth catalog files identically againstmain; this PR adds no new conflict with any of the 11. - Ran (database
origin/main993f134 exported to a scratch directory, disposable local cluster, PostgreSQL 17.7 withLC_ALL=en_US.UTF-8):python3 -m unittest discover -s tests -p 'test_release_cases.py'— 1 test OK;-p 'test_company_assessment.py'— 3 tests OK. CI's PostgreSQL 15/16 matrix was not run here. - Ran: migration count check against database
origin/main— 37contextmigrations = 37 rows in the runbook table; table rows 1, 7 and 14 now list every table/function those migrations create; function replacements cited in the rollback section checked withgit showon each migration. - Red → green:
contextReleaseRunbook.test.tsfailed 4/4 withENOENT ... docs/context-release-runbook.mdbefore the runbook existed, then passed 4/4 after it was written. - Not verified: hosted deployment of api or app, live providers (no Spotify or paid provider call), production database (no migration applied, no hosted inventory re-checked), rollback drill (never exercised for Context), backward compatibility of earlier api code with replaced functions, MCP transport parity on a deployed revision. Every such step is listed in the runbook as "not performed in this PR".
Out of scope / known gaps
- MCP tool descriptions lag the schema: the
contexttool description and the OAuthcompile_music_context_brief/save_music_context_briefdescriptions still name only creative direction and playlist pitch, although the shared schema acceptscompany_onboarding. Documented in runbook 2.2 and smoke step 6; not changed here to avoid conflicts with the many sibling PRs editingcontextToolOperations.ts. - Cost reconciliation and the paid-execution lane (#2123/#2105); Sites quality and pipeline (#2094/#2133, hard blockers of #2134); the controlled live pilot; broad release.
- The hosted "State" column in the runbook quotes epic #2116 comments (database#74/#75/#96, api#916/#917/#992, app#2172/#2173/#2178); nothing was re-verified here.
- No new dependencies; no Supabase, workflow or route code changed; app untouched (its suites are listed in the checklist as not run here).
🤖 Generated with Claude Code