Skip to content

docs: spec + implementation plan for --amount <quantity><unit> flag#23

Open
phitoduck wants to merge 3 commits into
mainfrom
docs/amount-flag-spec
Open

docs: spec + implementation plan for --amount <quantity><unit> flag#23
phitoduck wants to merge 3 commits into
mainfrom
docs/amount-flag-spec

Conversation

@phitoduck

Copy link
Copy Markdown
Owner

Summary

Captures the work to add a general --amount <quantity><unit> flag (e.g. --amount 490mL, --amount 86g) to lose-it log. This is a SPEC ONLY — no code changes. The implementation is intended for a separate PR. Filed now so the work survives a context-loss boundary between sessions.

What the spec covers

  • Wire-level evidence: the HAR the user captured on 2026-06-11 of the official UI logging 490 mL of the Trader Joe's soup, decoded against _schemas.json. Pins what each FoodServingSize.f0..f5 field means and confirms the conversion factor (f4=236.588) is the universal US cup→mL constant.
  • Existing code citations: entries._build_log_payload (lines 35-181, FoodServingSize block at 164-178); cli.log (--grams handling at 398-409 and 455-478); foods.get_unsaved_food_log_entry (268-288); _models.UnsavedFoodLogEntry (23-34) and FoodLogEntry.calories (62-67).
  • New module: _units.py with CONVERSIONS table, UNIT_ALIASES, parse_amount, conversion_factor. Universal volumetric constants; oz deliberately rejected as ambiguous.
  • Edge case the user explicitly called out: foods that don't support the requested unit (a "1 each" tortilla rejecting --amount 50g). Detection via conversion_factor() returning None; fallback via foods.find_supporting_alternatives showing 2-5 candidates from the same search that DO support the unit, each annotated with serving_qty so the catalog's known traps are visible.
  • Implementation plan in 4 phases with effort estimates (~80 minutes total).
  • Verification: unit tests pinning the wire bytes against the HAR snippet (cup→mL block: 27|2.071…|1|28|11|1.0|236.588|490), dry-run grep check, live-log + app rendering check.
  • Risks: diary readback semantics after PR fix(log): send per-serving nutrients, not pre-scaled by servings #22 (per-serving HashMap → FoodLogEntry.calories shows per-serving until we multiply by servings in a follow-up); partial-decoder concern when probing alternatives.

Why ship the spec separately

The session that produced PRs #18-#22 is approaching its context budget. Capturing the findings + plan to disk lets the next session land the feature without re-deriving the HAR analysis or hunting line numbers.

Test plan

  • prek run --files docs/amount-flag-spec.md clean.
  • Renders correctly on GitHub.
  • Every claim cites either a code line or a HAR quote.

Capture findings + implementation plan in docs/ so the work survives
context loss between sessions. Backed by the user-provided HAR capture
of the official UI logging the same Trader Joe's tomato soup at 490 mL.

The spec covers:
- Wire-level evidence: the HAR's `updateFoodLogEntry` payload and what
  each field means (FoodServingSize.f4 = conversion factor,
  f5 = raw user input, FoodMeasure.ordinal = user's chosen unit).
- Concrete code citations for where to change `_build_log_payload`,
  the `log` CLI command, and the new `_units.py` module.
- 4-phase implementation plan with effort estimates.
- Edge case the user explicitly called out: foods that don't support
  the requested unit. Detection via `conversion_factor` returning None,
  fallback via `foods.find_supporting_alternatives` showing a numbered
  list of candidates that *do* support the unit.
- Verification: unit tests pinning the wire bytes to the HAR snippet,
  dry-run grep check, live log + app rendering check.
- Risks and follow-ups: diary readback semantics after #22 (separate
  fix), the partial-decoder concern when probing alternatives.

Cited code: entries.py:35-181, cli.py:398-478, foods.py:268-288,
_models.py:23-67. HAR quotes inlined.
Per maintainer policy, the evidence file is kept outside the repo. The
wire-byte facts (cup→mL conversion factor 236.5882365, FoodServingSize
field layout, per-serving HashMap pattern) are the protocol-level
findings and remain in the spec verbatim — only the references to
*where* the evidence file lives are removed.

Affected:
- docs/amount-flag-spec.md: rewrite "captured a HAR" → "observed in
  manual testing"; rewrite citation index entry; tweak verification
  steps that compared to "the HAR".
- src/lose_it_utils/client/entries.py: rewrite the comment in
  _build_log_payload that mentioned the HAR capture; keep the
  per-serving vs pre-scaled explanation.
…od-id spec

Per maintainer feedback:

1. The unit-conversion spec switches from a single `--amount 490mL`
   flag to a two-flag pair `--serving-amount 490 --serving-unit mL`.
   Rationale documented in the spec: each flag is a familiar
   `<flag> <value>` shape, the unit is a discrete enum that can be
   tab-completed, and unit/amount-only mistakes surface as flag
   validation errors rather than silent regex failures. Rename:
   docs/amount-flag-spec.md → docs/serving-unit-spec.md. The
   `_units` module no longer needs a `parse_amount` regex —
   `resolve_unit(str) → ord` is enough.

2. New spec: docs/food-id-flow-spec.md covers the broader CLI flow
   problem. Today `lose-it log "1 tortilla" --pick N` relies on a
   natural-language query the CLI can't disambiguate plus a `--pick`
   index that drifts. Adds `--food-id <32-char hex>` that bypasses
   search entirely by calling a new `getFood` RPC wrapper (wire shape
   already observed in manual UI testing — quoted verbatim in the
   spec) and using the food's stable 16-byte PK as the identifier.
   Includes the encoding helpers (_ids.py), the search-output changes
   to surface the ID, edge-case behaviour for invalid/missing IDs, a
   5-phase implementation plan, and how the two specs compose
   (`--food-id <hex> --serving-amount 490 --serving-unit mL` is the
   fully-disambiguated form).
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.

1 participant