Nutrition multi-service analysis proposal

Summary

This proposal recommends expanding the nutrition analysis workflow from a mostly single-path process into a multi-service comparison pipeline.

The core change is simple:

  1. persist the athlete nutrition item as usual
  2. generate a common analysis input from the athlete photo and any athlete text
  3. send that same input to multiple analysis sources
  4. store each source's returned estimates side by side in a structured comparison table
  5. compute a derived aggregate estimate, initially focused on calories, protein, carbohydrate, and fat
  6. write both the per-service outputs and the aggregate result into the athlete nutrition log record

The immediate motivation is to reduce over-reliance on any one interpretation path.

Right now the workflow is effectively:

  • local or in-agent interpretation of the photo and food item
  • optional or partial Edamam support
  • a single final estimate

That is workable, but it hides disagreement between sources and makes it harder to improve macro accuracy over time.

The proposed design makes disagreement explicit, preserves the raw outputs, and creates a better foundation for a future averaging or weighting algorithm.

Objective

Build a nutrition analysis architecture that can compare multiple nutrition-estimation services on the same athlete input and record the returned results in a structured, auditable way.

The first target state should support three analysis paths:

  1. Local analysis
    • current Coach Luca or nutrition-agent interpretation path
    • updated to use the shared nutrition analysis prompt so the local and Claude paths follow the same output contract
  2. Edamam analysis
    • current external nutrition lookup path
  3. Claude CLI analysis
    • a new local external-service path using the same saved nutrition analysis prompt and the athlete's photo and text

The workflow should then store:

  • the photo description used for the analysis
  • the macro estimate from each service
  • confidence or uncertainty notes when provided
  • any useful supporting details returned by the service
  • a derived aggregate estimate for the key macros

Why this change is needed

1. Single-path estimates are fragile

Nutrition estimates from photos are inherently noisy.

Portion size, hidden ingredients, preparation method, and visual ambiguity all create uncertainty. A single local estimate may be directionally useful, but it does not expose how uncertain the estimate really is.

2. Cross-checking should be first-class, not incidental

The current workflow sometimes uses Edamam as support, but that comparison is not yet structured into the record. The system should preserve the fact that multiple services looked at the same input and should show how their outputs differ.

3. Macro averaging can improve practical robustness

Even if no service is perfectly accurate, a simple aggregate across multiple independent estimates may produce a more stable practical estimate than relying on one source alone.

The workspace should be able to evolve from:

  • one estimate with implicit judgment

to:

  • multiple estimates with explicit comparison
  • a transparent aggregation method
  • a better final practical estimate

4. The system needs a reusable comparison substrate

This is not only about one extra Claude call.

The right architecture should allow additional services later, such as:

  • another CLI agent
  • another nutrition API
  • a vision-focused model
  • a specialized label OCR step

That argues for a service-agnostic comparison design rather than a one-off Claude special case.

Current state

The current durable understanding is:

  • local analysis remains the main interpretation path
  • Edamam is currently used as a nutrition lookup layer, not the sole decision-maker
  • the Edamam image-analysis path is URL-based and not a fully confirmed direct local-file upload path
  • a reusable shared nutrition analysis prompt now exists at team/nutrition/nutrition-analysis-prompt.md
  • Claude CLI is available locally and authenticated on this machine
  • the prompt should become the common contract for both the local analysis path and the Claude CLI path

This proposal builds on those facts rather than replacing them.

Proposed feature

Core idea

For each nutrition intake item that is suitable for analysis, create a normalized analysis package and run it through multiple services.

That normalized analysis package should include:

  • athlete message text, if present
  • local path to the saved photo, if present
  • a canonical short photo description generated locally when needed
  • relevant metadata such as received time, local time, and item position in the day's nutrition log

Each service then returns a structured result that can be normalized into a shared comparison schema.

Initial service set

Service 1, local analysis

This is the current internal analysis path.

It should be updated to use the shared prompt at team/nutrition/nutrition-analysis-prompt.md so the local analysis and Claude CLI analysis are working from the same prompt and expected structure.

It should produce a structured output instead of only freeform reasoning.

Expected fields:

  • food identified
  • observed evidence
  • estimated portions
  • estimated macros by item, if applicable
  • estimated total calories, protein, carbohydrate, and fat
  • confidence
  • assumptions
  • uncertainty notes
  • optional extra notes

Service 2, Edamam

This is the current external nutrition support path.

Depending on the item, Edamam may be driven by:

  • identified named foods plus quantity estimates
  • image-analysis path when a supported image path is actually available and working

Expected fields:

  • matched foods or candidate foods
  • calories
  • protein
  • carbohydrate
  • fat
  • any labels, categories, or nutrient metadata that are useful
  • service limitations or call-path notes

Service 3, Claude CLI

This is the proposed new path.

The system should call the local Claude CLI and provide:

  • the shared nutrition analysis prompt from team/nutrition/nutrition-analysis-prompt.md
  • the athlete text, if present
  • the saved nutrition photo, if present

Claude should then return a structured estimate in the prompt's required format.

Expected fields:

  • food identified
  • observed evidence
  • estimated portions
  • estimated macros by item, if applicable
  • estimated total calories, protein, carbohydrate, and fat
  • confidence
  • assumptions
  • uncertainty notes

Proposed workflow

Phase 1, intake and persistence

No change to the high-level intake rule:

  • the nutrition item must still be persisted first
  • the canonical athlete daily log remains the durable record

This proposal changes the analysis layer, not the intake-first rule.

Phase 2, normalized analysis input creation

Create a normalized analysis input object for the current nutrition item.

Suggested fields:

Field Purpose
item_id Stable identifier for the nutrition item within the log
athlete_date Athlete-local date of the nutrition item
received_time System receipt time
local_time Athlete-local receipt or consumed time
text_input Athlete text associated with the item
photo_path Canonical local path to saved nutrition media
photo_description Short neutral description of the visible food or packaging
analysis_prompt_path Prompt source used for agent-based services
source_context Optional context such as pre-ride, post-ride, meal, snack, supplement

The goal is that every downstream service receives the same effective evidence base.

Phase 3, multi-service execution

Run each enabled service against the normalized input.

The first implementation should allow services to succeed or fail independently.

If one service fails:

  • the others should still run
  • the comparison table should record the failure cleanly
  • the nutrition workflow should not collapse unless all required analysis paths fail

Phase 4, normalization of returned outputs

Each service returns different raw shapes. Those must be normalized into a shared schema.

Suggested normalized result fields:

Field Description
service_name local, edamam, claude-cli, or future service name
status ok, partial, failed, skipped
food_identified Service-level description of detected items
portion_summary Portion interpretation from that service
calories_kcal Total calories estimate
protein_g Protein estimate
carbohydrate_g Carbohydrate estimate
fat_g Fat estimate
confidence Service confidence if available
assumptions Key assumptions
uncertainty_notes Main uncertainty or warning
raw_summary Short summary of extra useful output
raw_payload_ref Path or pointer to the full raw service output if stored separately

Phase 5, comparison table generation

After normalization, write a side-by-side table into the athlete nutrition record.

Comparison-table design goal

The user asked for one column per service.

That is the right display model for human review because it makes cross-service disagreement immediately visible.

Proposed primary table

Metric Local Edamam Claude CLI Aggregate
Calories (kcal)        
Protein (g)        
Carbohydrate (g)        
Fat (g)        
Confidence        
Status        

This is the minimum required table.

Proposed secondary information table

Because not all useful outputs are numeric, add a second table or structured bullet section for supporting information.

Suggested format:

Field Local Edamam Claude CLI
Food description      
Portion summary      
Assumptions      
Uncertainty notes      
Raw-output reference      

This keeps the macro comparison compact while still preserving each service's interpretation.

Phase 6, aggregate estimate

Once per-service outputs are normalized, compute an aggregate estimate.

First-version recommendation

Start simple.

Use an arithmetic mean across successful services for:

  • calories
  • protein
  • carbohydrate
  • fat

Rules:

  • exclude failed or skipped services
  • exclude clearly non-numeric outputs
  • round the aggregate to practical values
  • if only one service succeeds, the aggregate equals that service result
  • if two or more services succeed, note how many services were included in the aggregate

Second-version recommendation

Once the basic comparison path is working, consider weighted averaging.

Possible weighting inputs later:

  • service confidence
  • presence of visible label data
  • structured versus heuristic source path
  • known service strengths by item type, such as packaged product versus mixed meal versus supplement

Do not start with weighting unless there is a clear validation basis.

Proposed output location in the athlete log

The comparison and aggregate result should be saved with the nutrition item inside the canonical daily log under ## Nutrition.

The goal is not to replace the existing item entry, but to enrich it.

Recommended additions to each analyzed nutrition item:

  • Photo description
  • Analysis services used
  • Macro comparison
  • Service notes
  • Aggregate estimate

A possible shape:

### 13:10

- Received: 2026-04-22 13:11 MDT
- Local: 2026-04-22 13:10 MDT
- Type: nutrition photo
- Photo description: bowl with white rice, grilled chicken pieces, avocado, and light sauce
- Analysis services used: local, Edamam, Claude CLI

#### Macro comparison

| Metric | Local | Edamam | Claude CLI | Aggregate |
|---|---:|---:|---:|---:|
| Calories (kcal) | 620 | 580 | 640 | 613 |
| Protein (g) | 34 | 31 | 36 | 34 |
| Carbohydrate (g) | 58 | 54 | 61 | 58 |
| Fat (g) | 22 | 20 | 24 | 22 |
| Confidence | moderate | moderate | moderate | derived |
| Status | ok | ok | ok | 3 services |

#### Service notes

| Field | Local | Edamam | Claude CLI |
|---|---|---|---|
| Food description | chicken rice bowl with avocado | chicken, rice, avocado candidates | grilled chicken rice bowl with avocado and sauce |
| Portion summary | medium bowl | ingredients estimated from named-food matches | medium takeaway bowl |
| Assumptions | light sauce | avocado quantity uncertain | sauce amount uncertain |
| Uncertainty notes | hidden oil unknown | mixed-dish decomposition imperfect | sauce and rice depth not visible |
| Raw-output reference | inline | raw/edamam/...json | raw/claude-cli/...md |

#### Aggregate estimate

- Calories: 613 kcal
- Protein: 34 g
- Carbohydrate: 58 g
- Fat: 22 g
- Aggregate method: simple mean across 3 successful services

Architecture recommendations

1. Keep service adapters separate from canonical log writing

Do not mix provider-specific calling logic directly into the daily-log writer.

Recommended separation:

  • one layer builds normalized analysis input
  • one adapter per service performs the call and captures the raw result
  • all configured nutrition analysis services are run for every nutrition log request
  • one normalizer converts each raw result to the shared schema
  • one writer updates the canonical daily log format

This will make later service additions much easier.

2. Preserve raw outputs when practical

For debugging and future validation, store raw returned outputs in a durable location when feasible.

Suggested raw-output archive path:

  • athlete/data/nutrition-analysis/raw/YYYY-MM-DD/

Possible files:

  • item-01-local.json
  • item-01-edamam.json
  • item-01-claude-cli.md
  • item-01-normalized.json

The daily log should remain readable and concise, while raw artifacts can live in the archive.

3. Make the local and Claude CLI paths prompt-driven

Do not hard-code the prompt in code.

Both the local analysis adapter and the Claude CLI adapter should read:

  • team/nutrition/nutrition-analysis-prompt.md

This keeps prompt revision separate from execution code, aligns the two analysis paths on the same structure, and ensures that differences between local and Claude results come from the service or model behavior rather than from two different prompt contracts.

4. Support partial success cleanly

The system should treat the analysis stage as a multi-source collection step, not as a single brittle dependency.

Examples:

  • if Edamam fails, local plus Claude can still produce a comparison table
  • if Claude fails, local plus Edamam can still produce a comparison table
  • if only local analysis succeeds, the record should still be updated, but it should note that no cross-service comparison was available

Open design questions

1. What should count as the canonical final estimate?

Options:

  • aggregate estimate always becomes the canonical final estimate
  • Coach Luca still approves or adjusts the final estimate after seeing the comparison table
  • nutrition specialist owns the final adopted estimate while the table remains evidence

Recommendation for first version:

  • keep the aggregate estimate explicit
  • keep Coach Luca or nutrition specialist judgment as the final interpretation layer
  • do not silently replace coaching judgment with a blind average

2. Should the photo description be generated once or per service?

Recommendation:

  • create one neutral local photo description for the item record
  • allow each service to also return its own food-identification description
  • keep both, because the neutral description and the service interpretation serve different purposes

3. How much of the raw service output belongs in the daily log?

Recommendation:

  • keep the daily log concise
  • store numeric comparison and short service notes in the log
  • archive the full raw outputs elsewhere

4. Should all nutrition items use all services?

Yes.

Current user direction is to run all configured nutrition analysis services for every nutrition log request.

Rationale:

  • the system needs broad comparison data before it can judge which services are most useful or most accurate
  • early selective routing would hide disagreement patterns and reduce the validation dataset
  • consistent all-service execution will make downstream comparison, averaging, and service evaluation much cleaner

Recommendation:

  • run all configured nutrition analysis services for every nutrition log request in the current design
  • defer any future service-reduction or selective-routing logic until there is enough evidence to justify it

Implementation phases

Phase 1, proposal-aligned prototype

Build a prototype that:

  • reads the nutrition analysis prompt from team/nutrition/nutrition-analysis-prompt.md
  • runs local analysis, Edamam, and Claude CLI on the same nutrition item
  • normalizes calories, protein, carbohydrate, and fat
  • writes a comparison table plus aggregate estimate into a test or staging record

Success criteria:

  • one real nutrition item can be analyzed through all available services
  • the comparison table is readable
  • partial failures are handled cleanly

Phase 2, canonical daily-log integration

Integrate the comparison table into the canonical athlete nutrition log format.

Success criteria:

  • the result is durable and readable in athlete/logs/daily/YYYY-MM-DD.md
  • raw outputs are archived separately when appropriate
  • the aggregate estimate is explicit and traceable

Phase 3, weighting and validation

Once enough comparison data exists, evaluate:

  • whether simple averaging is useful enough
  • whether weighting improves practical estimates
  • which services overestimate or underestimate specific food classes

Recommendation

Proceed with this feature.

The recommended first step is not to redesign the whole nutrition system at once.

Instead, build a narrow but real prototype around one nutrition item flow:

  • local analysis
  • Edamam analysis
  • Claude CLI analysis using the saved prompt
  • comparison table
  • simple aggregate macro estimate
  • all configured services executed on that item, with no selective routing

That is enough to validate the architecture before broader rollout.

Proposed file and workflow impacts

This proposal likely affects:

  • skills/nutrition-analysis/
  • skills/nutrition-intake/, if the comparison results are written during intake-adjacent flow
  • team/nutrition/, for service prompt and service policy
  • canonical athlete daily-log nutrition item format
  • a new raw-output archive path for multi-service results

Final principle

The system should stop treating nutrition estimation as a one-answer task.

It should treat it as an evidence-comparison task:

  • multiple services
  • explicit disagreement
  • transparent aggregation
  • preserved raw outputs
  • better practical final estimates