2026-01-03: Data Format Uplift
Task Metadata
Date: 2026-01-03
Status: Complete
1. Context
- Goal: Standardize data formats across the stack (Casing & Types) to resolve tech debt and enable decimal precision.
- Trigger: "Layered Testing" task identified mixed casing (Pascal vs Camel) and artificial integer constraints blocking decimal inputs.
- Scope:
- Casing Unification: Standardize on camelCase for API/Frontend interactions.
- Float Support: Update GraphQL Schema and Frontend to support
Floattypes for Calories and Macros. - Prompt Engineering: Update LLM instructions to output floats.
2. Approach
-
Technical Strategy:
- Schema: Update
graphql/schema.graphql(ChangeInttoFloat). - Frontend: Update
SettingsModalanduseMealsto removeMath.round()casts. - Backend (AppSync): Ensure resolvers handle floats correctly (DynamoDB
Ntype supports this natively). - Data Migration:
- Write a Python script (
scripts/migrate_data_format.py) to scan DynamoDB. - Standardize keys to camelCase if necessary (or confirm AppSync mapping handles this).
- Decision Required: Do we migrate existing Integer data to Floats? (DynamoDB doesn't distinguish
1from1.0, but we should verify).
- Write a Python script (
- Schema: Update
-
Key Decisions:
- Float Precision: Use standard floating point. UI display logic will handle rounding for display (e.g. 1 decimal place).
- Casing: Ensure frontend sees
camelCasebut DynamoDB stores consistent keys (likely PascalCase if that's the current STD pattern, or switch entire stack to camelCase). Investigation needed.
-
Testing Strategy:
- Must Test:
- Decimal Inputs: Verify
1.5protein is saved and retrieved as1.5. - Legacy Data: Verify old Integer records still load correctly.
- Casing: Verify frontend does not break if backend returns PascalCase keys (or fix the mapping).
- Decimal Inputs: Verify
- Skip:
- Complex historical data migration if the schema change is backward compatible.
- Must Test:
3. Impact Analysis
- Files to Modify:
graphql/schema.graphqlfrontend/src/components/SettingsModal.jsxfrontend/src/utils/constants.js(Prompt templates)appsync/addMeal.js(Resolver logic)
- Risks:
- Breaking Change: Changing GraphQL types from
InttoFloatmight break strict clients, though JS/JSON is usually forgiving. - Data mismatch: If Frontend expects camelCase but DB returns PascalCase (without AppSync mapping), UI will show empty data.
- Breaking Change: Changing GraphQL types from
4. Execution Plan
- Step 1: Investigation
- Audit current DynamoDB casing: PascalCase (
Calories,MealSummary) used in DB andMealtype. - AppSync Mapping:
UserTargetsmanually maps Pascal to camelCase.Mealdoes not (direct pass-through). - Type Constraint: Enforced strictly by
Intinschema.graphql. Resolvers are type-agnostic.
- Audit current DynamoDB casing: PascalCase (
- Step 2: GraphQL Schema Update
- Updated
schema.graphqlto useFloatandcamelCase. - Standardized
addMealmutation arguments.
- Updated
- Step 3: Frontend Update
- Updated
ApiMealService.jsto use the new camelCase fields and float types. - Updated
useMeals.jsto support both legacy and new casings for totals calculation and optimistic updates. - Updated
SettingsModal.jsxto support decimal targets and increased the input step to 5g for macros. - Updated
Dashboard.jsxandPendingMealCard.jsxto be casing-resilient during the migration.
- Updated
- Step 4: Prompt Engineering
- Updated
SYSTEM_PROMPTinconstants.jsto outputcamelCaseand decimals.
- Updated
- Step 5: Verification
- Added
getMeals.test.jsto verify backend mapping layer for mixed casings. - Added
MealItem.test.jsxto verify frontend rendering resilience. - Added
mealParser.test.jsto verify JSON normalization logic for all casing formats. - Run full test suite (30 passing).
- Added
- Step 6: Documentation
- Updated
docs/architecture/data_model.mdto reflectcamelCaseandFloatstandards. - Updated
docs/architecture/ui_data_validation.mdto reflectFloatsupport and new macro steps.
- Updated
5. Execution Notes
- Audit Findings:
- DynamoDB attributes are primarily
PascalCase. - GraphQL
Mealtype isPascalCase, butUserTargetsiscamelCase. - Mutations use a mix of
snake_case(addMeal) andcamelCase(updateUserTargets). - Uplift Strategy: We will standardize the entire API layer on
camelCaseandFloat. We will implement a "Mapping Layer" in AppSync to handle legacyPascalCasedata in DynamoDB to avoid an immediate mass migration of production data.
- DynamoDB attributes are primarily
- Implementation Notes:
- Architecture: Extracted JSON parsing logic into
utils/mealParser.js. This centralizes the "Casing Mapping" logic, making the UI components (Dashboard, PendingMealCard) agnostic to the source data format. - Casing Resilience Logic:
- Backend (API Return): The
getMeals.jsandgetUserTargets.jsresolvers now check both casings when mapping DynamoDB attributes to GraphQL fields (e.g.,item.calories || item.Calories). This ensures that the Frontend always receives consistentcamelCaseregardless of the storage state. - Frontend (Ingestion): The
mealParser.jsutility uses nullish coalescing to support three input formats:camelCase(New),snake_case(Legacy LLM), andPascalCase(Direct DB copy). - Frontend (UI): Components like
MealItem.jsxandPendingMealCard.jsxare now agnostic to the raw object casing, relying on the normalization performed by the Parser and API mapping layer.
- Backend (API Return): The
- Restored technical comments in
useMeals.jsthat were accidentally removed during the casing refactor. - Adjusted
SettingsModalinput steps: Macros (Protein/Fat/Carbs) now step by 5g for better usability, while Energy remains at 1 (kcal). - Verified that
PendingMealCardandMealItemrender floats with.toFixed(1)for precision without UI clutter.
- Architecture: Extracted JSON parsing logic into
- Hotfix (2026-01-04): Replaced nullish coalescing operator (
??) indeleteMeal_step2.jswith explicitundefinedchecks to ensure compatibility with theAPPSYNC_JSruntime, which resolved a deployment failure in the Test stack. - Safety Warning: Since the project currently uses a single DynamoDB table (
MinimalCalorieMeals) for both Test and Prod stacks, the data migration script MUST NOT be run until the new code (which is casing-resilient) is fully deployed to Production.
6. User Approval & Key Learnings
- User Approval: Approved on 2026-01-03.
- Key Learnings:
- DynamoDB Data Types: A key discovery was that DynamoDB's
Numbertype already natively supports both integers and decimals. The primary restriction was in the GraphQL Schema (IntvsFloat), which necessitated the uplift to enable decimal precision in the application. - Centralized Normalization: Extracting normalization logic into utilities (
mealParser.js) significantly reduces UI component complexity and ensures consistent data handling across various input methods (links, clipboard, manual logging). - Casing Resilience: Implementing a "Double-Check" pattern in AppSync and the Parser allows for a zero-downtime transition between different naming standards.
- DynamoDB Data Types: A key discovery was that DynamoDB's
7. Context Memory (AI-Only)
Summary for Future Context
Successfully migrated the data format standard from PascalCase/Integers to camelCase/Floats.
Key Changes:
- GraphQL: All numeric fields are now
Float. All field names arecamelCase. - AppSync: Resolvers
getMeals,getUserTargets, andupdateUserTargetsnow handle both legacy and new casings.addMealnow writes new items incamelCase(version 4). - Frontend:
mealParser.jshandles ingestion of all formats.SettingsModalandMealItemsupport decimals. - Migration:
scripts/migrate_data_format.pyis ready but should only be run after full production deployment.
Next Task: Deployment to dev/test environment to verify these changes in a live environment before merging to production.