Smoke-sweep fixes: exact saves, local dates, safer remove, readable markers #125

Merged
steve merged 3 commits from fix/smoke-sweep into main 2026-08-23 02:26:06 +00:00
3 Commits
Author SHA1 Message Date
steveandClaude Fable 5 0d95578c6a Address #125 review: memoized ink, one fallback color, reactive copy name
Build image / build-and-push (push) Successful in 10s
- monogramInk is memoized by color string; the canvas asks for every
  visible plop on every frame of a pan (Gadfly, 2/4 models).
- FALLBACK_PLANT_COLOR lives in lib/plants and is used by the canvas, the
  inspector and the garden thumbnail instead of three raw '#97a97c's.
- CopyDialog keeps its proposed "<base> — <year>" in step with the gardens
  list until the person edits the name, so a list that loads after the
  dialog opens can't leave a taken year in the field.
- GardenCard: reflowed the summary comment; no dead fallback on a plan
  name that's already known to parse.
- today() has one import path (lib/dates); the journal re-export is gone.
- CLAUDE.md says what the inspector actually does (a text-compare guard)
  rather than claiming it uses LengthField.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-22 22:25:02 -04:00
steveandClaude Fable 5 157e04ed24 Skip no-op saves in the edit dialogs; clear a stale model-spec error
Build image / build-and-push (push) Successful in 26s
A Save that changed nothing still sent a PATCH, which bumped the row's
version and landed an "Edited garden settings" step in History that undid
nothing — the drift is gone since the last commit, but the write was still
there. Both dialogs now close without a request when every field matches
the loaded row.

In Settings, a rejected model spec's reason stayed under the field after
the field was blanked back to the saved value; committing an unchanged
value now clears it.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-22 22:22:22 -04:00
steveandClaude Fable 5 27f658c1f7 Smoke-sweep fixes: exact saves, local dates, safer remove, readable markers
Build image / build-and-push (push) Successful in 2m55s
Gadfly review (reusable) / review (pull_request) Successful in 8m59s
Adversarial Review (Gadfly) / review (pull_request) Successful in 8m59s
- Garden and plant dialogs keep centimeters as the source of truth
  (LengthField in lib/units.ts): a no-change Save no longer rewrites
  900 cm as 899.922 or a 45 cm spacing as 44.958, bumping versions and
  writing bogus history entries on the way.
- The UI stamps every date with the browser's local day (lib/dates.ts).
  Journal notes already did; plop placement, fill and removal now do too,
  so a 9 pm placement isn't "planted tomorrow". The fill endpoint gained an
  optional plantedAt; API and agent callers still default to UTC today.
- Removing an object that holds plants asks first and says how many go
  with it. An empty one still goes straight away (one Undo restores it).
- The expanded plant card's action row wraps instead of clipping "Delete".
- Monogram lettering switches to a dark ink on pale marker colors (garlic,
  cabbage, marigold) instead of near-white on near-white.
- Copy-as-plan proposes the next free year and warns when the typed name
  already exists, so two gardens can't both read as "the 2027 plan".
- Plan cards show the base name with a "2027 plan" tag, so the year — the
  point of the name — survives truncation.
- A rejected model spec now says which model and why: a wrapped
  ErrInvalidInput's reason reaches the client as the 400's message, and the
  Settings field shows it inline instead of toasting "invalid input".

Also defuses a clock bomb in TestRemainingReturnsWhenAPlantingIsRemoved,
which only passed while the real date was before 2026-08-01.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-22 22:11:12 -04:00