Review: Phase status -> board item column sync on note update (re-review)

review-1600-2026-06-24-r2 Review

review ready

Verdict: APPROVED

Re-review of board item #1600 after scope refinement. Previous review review-1600-2026-06-24 returned NEEDS_REFINEMENT with two findings. Both have been addressed.

Previous Findings Resolution

  • [x] [BODY] Test command — FIXED. Changed from bin/rails test test/requests/api/notes_* to bundle exec rspec spec/requests/api/notes_spec.rb. Verified: spec/requests/api/notes_spec.rb exists (799 lines, RSpec format).
  • [x] [SCOPE] arch-rails-api note — ACKNOWLEDGED as cross-cutting gap. The refinement comment correctly identifies this affects all arch:rails-api labeled items, not just this ticket. Not a blocker for this specific scope.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Spike #75 (PR #76) — Gap 9
  • [x] Repo — ldraney/paldocs
  • [x] User Story — well-formed As-a/I-want/So-that
  • [x] Context — clear explanation of pal-e-docs vs Rails gap, now includes explicit status-to-column mapping
  • [x] File Targets — 3 targets listed
  • [x] Feature Flag — none (correct, internal model change)
  • [x] Acceptance Criteria — 3 criteria
  • [x] Test Expectations — corrected to RSpec (bundle exec rspec spec/requests/api/notes_spec.rb)
  • [x] Constraints — 2 constraints listed
  • [x] Checklist — standard 3-item
  • [x] Related — references project and spike

Traceability

  • [x] story:consolidation label — story-paldocs-consolidation
  • [x] story note verified — found in project-paldocs user-stories section: "absorb pal-e-docs into Rails monolith (schema, API, embeddings)"
  • [x] arch:rails-api label — rails-api component
  • [ ] arch note MISSING — arch-rails-api does not exist in pal-e-docs. Cross-cutting gap affecting all arch:rails-api items. Not a blocker for this ticket.
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/ldraney/paldocs/issues/79, open

File Targets

  • [x] app/controllers/api/notes_controller.rb — verified: exists at HEAD. Update action (lines ~167-233) handles status changes via validate_status! but has no board item sync logic. Correct location for the change.
  • [x] app/models/board_item.rb — verified: exists at HEAD. Has COLUMNS constant and sprint association but no status-to-column mapping method. Correct location for the class method.
  • [x] Reference: pal-e-docs/src/pal_e_docs/routes/notes.py (_status_to_column) — verified by previous review. Mapping now explicitly stated in issue Context section: not-started->backlog, in-progress->in_progress, completed->done, deferred->done, nil->backlog.

Repo Placement

OK — issue filed on ldraney/paldocs, all file targets in ldraney/paldocs. Reference to pal-e-docs is read-only (pattern to match). Single-repo change.

Dependencies

  • Depends on #57 (API namespace + Notes controller) — DONE, merged.
  • Related to Spike #75 (MCP compatibility analysis) — in_progress on board. This ticket was born from Gap 9. Not a hard blocker.
  • No other board items blocked by this ticket.

Acceptance Criteria

  • [x] AC1: "When a phase note's status changes via PATCH /api/notes/:slug, the linked board_item column updates" — testable via request spec.
  • [x] AC2: "Status-to-column mapping matches pal-e-docs behavior" — testable via unit test with explicit mapping now documented in issue body.
  • [x] AC3: "Non-phase notes are unaffected" — testable via negative request spec.
All criteria are agent-verifiable. Test command is correct.

Blast Radius

Low. The change adds sync logic to the update action only. BoardItem gains a pure class method. No existing behavior modified — sync is additive. The board_items table already has a note_slug column used by pal-e-docs for this purpose.

Decomposition Assessment

No decomposition needed. 2 file targets in 1 repo, 3 acceptance criteria, estimated agent work well under 5 minutes. Single focused change.

Recommendations

No action needed. Ticket is ready for implementation.
Standing recommendation (not blocking): Create architecture note arch-rails-api as a separate task to close the cross-cutting traceability gap.