Files
thoughtsync/tests
bvandeusenandClaude Opus 4.8 f1033da75e
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 7s
CI & Build / Python tests (push) Successful in 9s
CI & Build / Build & push image (push) Successful in 34s
M9 S3 (backend): organize routes adopt toolkit + shared label reconciliation
DRY across the "organize/recall" backend surface:

- serialize.py (new): serialize_label(label) — the base {id,name,color}
  shape. labels.py builds on it (adds count); sync deltas will (S4).
- labeling.py (new): resolve_owned_label_ids() + reconcile_manual_labels()
  — the "set a note's MANUAL (picker) labels, leave the via_tag rows alone"
  logic was duplicated line-for-line between notes.set_note_labels and
  sync._apply_note_manual_labels. Now one home; both adopt it (removes the
  redundant `chosen`==owned recompute in notes). Behavior-preserving.
- labels.py: json_error/not_found/parse_uuid, colors.normalize_color, and
  serialize_label; dropped local LABEL_COLORS + _normalize_label_color
  (NOTE_COLORS is the single palette) and `import uuid` (rule 22).
- saved_filters.py: json_error/not_found/parse_uuid for its 2 uuid parses
  + error shapes.
- graph.py: no change — no error/uuid/palette-normalize duplication to fold.

Test: DB-free test_serialize_label_shape guards the base shape.
sync.py's reconciliation swap is behavior-identical; operator-verified on
deploy (no Postgres CI lane).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
2026-07-23 21:26:59 -04:00
..