refactor: sync_board discovers plans from project notes, not board items #210
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/pal-e-api!210
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "208-sync-board-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Refactors
POST /boards/{slug}/syncto discover plan notes directly from the project (WHERE note_type='plan' AND project_id=board.project_id) instead of from plan-type board items. This unblocks #203 (removing plan items from boards) without breaking phase sync.Changes
src/pal_e_docs/routes/boards.py-- Replaced the plan board item query with a direct Note query filtered byproject_idandnote_type='plan'. Removed the intermediateplan_item -> note_slug -> Notelookup chain. The phase discovery and board item create/update logic is unchanged.tests/test_boards.py-- AddedTestBoardSyncclass with 5 tests covering: sync without plan items on board, sync with plan items still present (backwards compat), column update on status change, skip unchanged phases, and empty project with no plans.Test Plan
pytest tests/test_boards.py -v-- 71 tests pass (66 existing + 5 new)test_sync_without_plan_items_on_board-- creates plan/phase notes on a project, runs sync with zero plan board items, verifies phases are still createdtest_sync_with_plan_items_still_on_board-- backwards compatibility, sync works identically when plan items existReview Checklist
boards.pysync logic modified -- no CRUD or sync-issues changesRelated
QA Review
Scope: 2 files changed, +153/-16 lines. Only
sync_boardlogic modified -- CRUD and sync-issues untouched.Code Quality
BoardItem -> note_slug -> Note -> children) is replaced with a single direct query (Note WHERE project_id AND note_type='plan'). The phase discovery loop downstream is unchanged.BoardItemandBoardItemTypeare still used elsewhere in the file.Test Coverage
test_sync_updates_column_on_status_changecorrectly uses direct DB manipulation to bypass the note update handler's auto-sync, isolating the sync endpoint's own column update logicNits
None.
VERDICT: APPROVE
PR #210 Review
DOMAIN REVIEW
Stack: Python / FastAPI / SQLAlchemy (pal-e-docs API)
Correctness of the refactor
The core change is clean and minimal. The old pattern was:
BoardItemWHEREitem_type='plan'ANDboard_id=board.idnote_slug->Notenote_slugor no matchingNoteNote.parent_note_idThe new pattern:
NoteWHEREproject_id=board.project_idANDnote_type='plan'Note.parent_note_idThis is a strictly better approach:
plan_item.note_slugcheck,plan_notenull check)Query correctness: The filter
Note.project_id == board.project_idcorrectly scopes to the same project. TheNote.note_type == "plan"filter is a string comparison against a nullable string column -- this matches the model definition at/home/ldraney/pal-e-docs/src/pal_e_docs/models.py:101wherenote_typeisString, nullable=True.Dead code removal: Confirmed zero remaining references to
plan_itemsorplan_iteminboards.py. The old query pattern is fully removed. No orphaned imports --BoardItem,BoardItemType,Note,Board,BoardColumn,Projectare all still used elsewhere in the file.Backwards compatibility: The sync logic downstream (phase discovery, board item create/update, column mapping) is unchanged. The only change is how plan notes are discovered, not what happens with them.
SQLAlchemy patterns: The
.filter().all()pattern is correct. No session leaks -- the existingdb.commit()at the end of the function handles the transaction.PEP compliance: Docstrings updated to reflect the new behavior. Type hints maintained. No style issues.
BLOCKERS
None.
NITS
Line 336 parenthesization: The query has an extra level of parentheses around the entire expression:
The
.all()is inside the outer parens, which works but is slightly inconsistent with the rest of the file where.all()is typically on its own continuation line after the filter chain. This is cosmetic and non-blocking.Test:
test_sync_updates_column_on_status_changeusesTestingSessionLocaldirectly (line 1275). This creates a separate session to modify the DB directly, which is a valid test technique for simulating out-of-band changes. Thetry/finallywithsession.close()is correct. However, the import ofNotefrompal_e_docs.modelsat line 1267 is inside the method body -- this is fine for test isolation but could be at the top of the test file. Not blocking since test files commonly do this.No test for multiple plans in one project: The test suite covers 0 plans and 1 plan scenarios, but not a project with 2+ plan notes each having phase children. This would verify that the new query correctly discovers all plans. Low risk since the
.all()on the query naturally handles multiple results, but it would be a good addition for completeness.SOP COMPLIANCE
208-sync-board-refactor(references issue #208)Closes #208, and notes it blocks #203boards.py,test_boards.py), both directly relevantPROCESS OBSERVATIONS
VERDICT: APPROVED
Clean, minimal refactor that correctly changes the plan discovery strategy from board-item-based to project-note-based. No blockers. Test coverage is thorough. The change is backwards compatible and directly enables the next phase of work (#203).