Nutrition intake workflow

Workflow decision tree

Use this reference when handling inbound nutrition content for an athlete.

Classify the inbound item

Determine which case applies:

  1. New intake item
    • meal photo
    • snack photo
    • drink photo
    • supplement photo
    • food label
    • text-only nutrition log
  2. Follow-up context for an unresolved item or batch
    • consumed timing correction
    • ingredient clarification
    • meal-role clarification
    • quantity clarification
  3. Return-media request
    • athlete asks for a logged nutrition photo back in chat
  4. Summary request
    • user asks for a summary over already logged nutrition items

If the message updates an earlier item or batch, attach the follow-up context to the relevant unresolved intake item before treating the workflow as complete.

Step 1, resolve athlete and date context

  • Identify the athlete.
  • Use the best available timestamp information.
  • Default consumed timing to receipt time unless the athlete states otherwise.
  • If the athlete gives a different consumed date or timing window, preserve both Received and Consumed.
  • If several photos arrive together and one later message adds shared context, apply that context to the unresolved batch unless the athlete clearly separates the items.

Step 2, persist media when media exists

  • Copy the image into /athlete/logs/media/<date>/ inside the workspace.
  • Use the consumed date for the media folder when that date is known reliably.
  • If the consumed date is not known, fall back to the received date.
  • Use simple ordered filenames.

Step 3, ensure the canonical daily log exists

  • Use athlete/logs/daily/YYYY-MM-DD.md.
  • Use the consumed date when known reliably.
  • Otherwise use the received date.
  • If the file does not exist, create it before trying to edit it.

Step 4, write or repair the canonical nutrition record

Write the human-readable intake record inside ## Nutrition.

Follow logging-entry-template.md as the single source of truth for:

  • required field names
  • field order
  • when to include or omit media lines
  • when to include or omit athlete-message blocks
  • how to preserve raw athlete text inside ~~~ fenced blocks

Use the heading, timing, and media rules from persistence.md.

Required write standard

  • Use the best athlete-local heading anchor available.
  • Preserve Received, Local, and Consumed as separate facts.
  • If the athlete sent text, store the original athlete text in the log item as raw text inside one or more ~~~ fenced blocks.
  • If the athlete sent only media and no text, omit the athlete-message block.
  • If media exists, include the workspace-root-relative source media path and the markdown image.
  • If a prior process wrote the item in a different format, repair it to the current template instead of layering a second format on top.

Step 5, update the derived summary table

After every nutrition-item write that changes logged intake:

  • ensure ### Summary exists under ## Nutrition
  • rebuild the table and totals row using logging-summary-table.md
  • preserve chronological order

Chronological order rule for detail blocks

This rule applies to both the ### Summary table and the individual ### HH:MM detail blocks under ## Nutrition.

  • All ### HH:MM detail blocks must appear in ascending time order.
  • After any write or repair pass that revises ## Nutrition, verify the section is still in time order before considering the write complete.
  • If the section is out of order for any reason, repair it by reordering the blocks before proceeding.

Insertion algorithm (mandatory - follow this exactly when writing a new detail block)

Before writing a new ### HH:MM block:

  1. Read the current ## Nutrition section and list all existing ### HH:MM block headings and their order in the file.
  2. Determine the correct chronological position for the new block:
    • If there are no existing ### HH:MM blocks, place the new block after the last named subsection (e.g. ### Watch, ### Carry-forward, or ### Observations).
    • If the new item is later than all existing blocks: insert it after the last existing ### HH:MM block, not before the first one and not after a named subsection heading.
    • If the new item is earlier than all existing blocks: insert it before the first existing ### HH:MM block.
    • If the new item falls between two existing blocks: insert it after the earlier block and before the later block.
  3. Identify the exact oldText anchor for the edit. When appending after the last block, use the closing content of that last block as the anchor, not the opening of the next named section or the next ### HH:MM heading.
  4. Write the new block at that position.
  5. After writing, re-read the ## Nutrition section and confirm all ### HH:MM blocks are in ascending time order. If they are not, reorder them before treating the write as complete.

Common failure mode to avoid: do not insert a new block immediately after the last named subsection heading (e.g. ### Watch or ### Carry-forward) when existing ### HH:MM blocks already follow it. That places the new block before those existing blocks regardless of their time. Always anchor the insert position relative to the existing ### HH:MM blocks, not relative to named subsection headings.

  • When a multi-service analysis completes late (after a subsequent item has already been logged), the resulting block must still be inserted at its correct time position, not appended.

Step 6, keep operational ledgers optional

Operational ledgers are optional support artifacts, not the canonical record.

Do not treat these ledgers as the primary record.

Step 7, run the pipeline script (hard gate - no exceptions)

Every nutrition item write must go through scripts/process_nutrition_intake.py. This is the only permitted path. Do not manually write a nutrition entry and do not skip the script for text-only items or items without a photo.

If the script exits non-zero, stop and report the error. Do not fall back to a manual write.

Completion check: after the script runs, verify that athlete/data/nutrition-analysis/raw/YYYY-MM-DD/<heading-time>/ exists and that the daily log entry contains #### Macro comparison, #### Service notes, and #### Aggregate estimate. If those are absent, the item is not complete.

Step 8, decide whether a reply is allowed

A nutrition item is not handled until the canonical daily-log nutrition entry exists.

Before any athlete-facing reply:

  • persistence must already be complete
  • required specialist coordination must already be complete
  • nutrition-reply must be read and applied at the reply step
  • the final reply must be generated under nutrition-reply

If an outbound reply is expected for the case, do not treat the workflow as complete until that reply has been composed under nutrition-reply and either sent or intentionally withheld for an operator-only or test-only reason.

Do not send the athlete:

  • logging updates
  • routing notes
  • staging notes
  • file paths
  • workflow-status chatter
  • a nutrition message drafted only from general Coach Luca instructions without re-entering nutrition-reply

Return-media requests

If the athlete asks for a logged nutrition image back:

  • locate the stored workspace media file under athlete/logs/media/
  • use the direct delivery path described in the workspace rules
  • do not treat a plain text path as a completed media return

Summary requests

If the request is for a summary of already logged intake:

  • use the canonical daily log as the source of truth
  • do not rewrite history from chat memory when the daily log already exists
  • if the outbound message involves Coach Luca or an athlete, apply actual contributor attribution rules

Repair rule

If an existing nutrition item is incomplete, duplicated, or written in an older format:

  • repair the existing canonical entry when possible instead of writing a parallel duplicate
  • normalize the item to logging-entry-template.md
  • rebuild ### Summary after the repair if logged intake values changed