Repository navigation
feat(planning): save conflict detection (409) for plans, empires and cx, and per-key preference merge for multi-tab planning - #77
Merged
Conversation
…cx, and per-key preference merge for multi-tab planning - Plan, empire and CX responses carry modified_at; PUT accepts an optional base_modified_at and answers 409 (code "conflict", current modified_at) when the row changed since, checked under a row lock in the saving transaction - Empires get config_modified_at (migration with backfill) as their version, so state syncs and cx-junctions never cause a conflict; read-only in the admin - PATCH /user/preferences/ merges planOverrides per plan uuid; null deletes one - Deleting a plan removes its override from the owner's preferences - Backward compatible: without base_modified_at saves work as before Spec: specs/2026-10-03-multitab-01-backend.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 15 |
| Duplication | 0 |
🟢 Coverage 100.00% diff coverage · +0.05% coverage variation
Metric Results Coverage variation ✅ +0.05% coverage variation (-1.00%) Diff coverage ✅ 100.00% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (56c2521) 4895 4685 95.71% Head commit (1d9d7cb) 4947 (+52) 4737 (+52) 95.76% (+0.05%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#77) 65 65 100.00% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
When people plan in several tabs, plan, empire and CX saves silently overwrite each other (last write wins). A preference PATCH replaces the whole
plan_overridesdict, so per-plan settings from another tab are lost. With this change, a save based on an outdated version is rejected with 409 instead of overwriting, and a preference PATCH only changes the keys and plan overrides it sends.Changes
modified_at.PUTaccepts an optionalbase_modified_atand answers409({"detail", "code": "conflict", "modified_at"}) when the row has changed since.planning/api/serializers/conflict.py).config_modified_at(migration with backfill) as their version, so empire state syncs andcx-junctionsnever cause a conflict. It is read-only in the admin.PATCH /user/preferences/mergesplanOverridesper plan uuid, andnulldeletes one.base_modified_at, saves work as before.How it was verified
QA passed after 2 rounds (1 full, 1 scoped).
uv run ruff check,ruff format --check,ty checkandpytest(849 passed).mainfrontend):/sync-api:spectacular --validateis clean and nothing breaks for the frontend.Deploy order
This can deploy on its own, any time before the frontend counterpart (multitab-02-frontend), which will send
base_modified_atand handle the 409.🤖 Generated with Claude Code