Skip to content

Phase 2: group data model (migration 23 to 24) with colour inheritance - #179

Open
mapgie wants to merge 2 commits into
mainfrom
claude/logging-redesign-phase-2-nuaywv
Open

Phase 2: group data model (migration 23 to 24) with colour inheritance#179
mapgie wants to merge 2 commits into
mainfrom
claude/logging-redesign-phase-2-nuaywv

Conversation

@mapgie

@mapgie mapgie commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Phase 2 of the logging & category-system redesign (PLAN.md, build guide: phases/phase-2-group-model.md). Groups now exist in the data layer with colour inheritance. Fully additive: no UI redesign, no existing behaviour changed.

What's in here

  • Group entity (table `groups`): id, name, colorRole (always a CategoryColor key, never hex), defaultInputType (a CategoryType key), displayOrder. Defaulted columns carry @ColumnInfo(defaultValue = ...) so Room's expected DDL matches the migration SQL exactly.
  • TrackingCategory.groupId: Long? added as the last constructor field (the only constructor call site uses named args). No FK and no cascade: TrackingRepository.deleteGroup unfiles members (groupId = NULL) before deleting the group row, so deleting a group can never touch categories or history.
  • MIGRATION_23_24 creates `groups` and adds the nullable groupId column. Existing rows: groupId = NULL, colorToken untouched.
  • GroupDao + group methods on TrackingRepository (CRUD, rename, role/input-type update, reorder, delete-with-unfile, assign/unassign), wired via a new nullable groupDao constructor param in GoFloApplication.
  • Colour inheritance (PLAN.md section 5 rule): new COLOR_TOKEN_INHERIT ("inherit") sentinel. TrackingCategory.effectiveColorToken(groups) resolves it to the group's colorRole; inherit-without-group renders neutral (surfaceVariant/onSurfaceVariant branches added to the resolvers). "inherit" is deliberately not a CategoryColor entry, so the Phase 1 role picker does not offer it; the opt-in surface arrives with the Phase 6 management UI.
  • Migration test (Migration23To24Test): the project has no instrumented tests and exportSchema = false, so Room's MigrationTestHelper is unusable. Instead a JVM test builds the real v23 schema in in-memory SQLite (sqlite-jdbc, test-only dep mirroring the existing org.json precedent), seeds representative data, runs the actual MIGRATION_23_24 object through a reflection proxy that routes execSQL to JDBC, and asserts the exact schema Room expects (PRAGMA table_info including DEFAULT clauses) plus full data preservation. The migration SQL was additionally executed against a seeded v23 schema in real SQLite during development; PRAGMA output matches the test's expectations.
  • Changelog fragment (minor), PLAN.md section 7 progress-log row, subsystem map 02 updated for v24, LESSONS.md entry on JVM-side Room migration testing.

Deviation notes

  • Colour-inheritance deviation from the handover ("neutral surfaceVariant by default") is per PLAN.md sections 5/8: existing categories keep their colours, inherit is opt-in. Confirmed with the owner (option A) before implementation.
  • Group methods live on TrackingRepository rather than a separate GroupRepository (guide allowed either); assign/unassign is category-side and this avoids cross-repository coordination for delete-with-unfile.

Acceptance criteria (phase guide)

  • Migration test: open a seeded v23 database, run MIGRATION_23_24, assert (a) groups exists, (b) tracking_categories.groupId exists and is null for all rows, (c) all pre-existing category/value/log data is intact. (JVM test as described above, in app/src/test.)
  • A category with colorToken = "inherit" assigned to a group renders the group's role colour and re-themes. (effectiveColorToken returns the group's colorRole, which feeds the existing theme-relative resolvers from Phase 1.)
  • An inherit category with no group renders neutral (surfaceVariant / onSurfaceVariant branches in toCategoryColor / toCategoryOnColor).
  • Existing categories look identical to before: no row's colorToken is modified and non-inherit tokens short-circuit in effectiveColorToken.
  • App builds in CI. (This environment cannot build; CI on this PR is the check.)

Feature-preservation checklist (phase guide)

  • All existing category reads (getActiveCategories, getCategoryById, ...) still compile and return the same data plus the new nullable field (only an appended nullable constructor field; all queries are SELECT *).
  • Stats/History/Home/DayLogSheet/export unaffected: no read path was modified and none needs groupId yet.
  • Deleting a group never deletes categories or their history (deleteGroup unfiles members first; no FK cascade exists).
  • saveLog / value CRUD untouched.

Checks run locally: a11y_check.py clean (97 files), wcag_check.py exit 0 (no colour values changed), changelog fragment validates against check_changelog_fragment.py rules. DB version after this PR: 24.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PZJLynVBkgLtehJFXffnfg


Generated by Claude Code

claude and others added 2 commits August 25, 2026 00:50
Adds the redesign's only genuinely new table: a category group that owns
a colour role and a default input type. Fully additive; no UI changes.

- Group entity (table `groups`) + GroupDao; TrackingCategory gains a
  nullable groupId (no FK: deleting a group unfiles members instead of
  cascading). MIGRATION_23_24 creates the table and adds the column;
  existing rows keep groupId NULL and their colorToken, so nothing
  changes visually after migrating.
- Group CRUD, reorder, delete-with-unfile, and assign/unassign methods
  on TrackingRepository (new nullable groupDao constructor param, wired
  in GoFloApplication).
- Colour inheritance per PLAN.md section 5: new "inherit" colorToken
  sentinel resolved by TrackingCategory.effectiveColorToken(groups) to
  the group's colorRole, or neutral surfaceVariant when groupless.
  Deliberately not a CategoryColor entry so the Phase 1 role picker
  does not offer it. Existing tokens are untouched (no grey wipe;
  confirmed with owner against the handover's neutral-by-default).
- Migration test (Migration23To24Test): runs the real MIGRATION_23_24
  against a real SQLite v23 schema via sqlite-jdbc (test-only dep),
  routing execSQL through a reflection proxy, and asserts the exact
  schema Room expects plus data preservation. MigrationTestHelper is
  unusable here (no instrumented tests, exportSchema = false).
- PLAN.md section 7 progress log updated; subsystem map 02 updated for
  v24; changelog fragment (minor); LESSONS.md entry on JVM-side Room
  migration testing.

Verified: migration SQL executed against a seeded v23 schema in SQLite
(PRAGMA output matches the test's expected schema exactly);
a11y_check.py and wcag_check.py both clean.

Claude-Session: https://claude.ai/code/session_01PZJLynVBkgLtehJFXffnfg

Co-authored-by: Claude <noreply@anthropic.com>
@mapgie
mapgie marked this pull request as ready for review August 25, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants