Skip to content

spec(v0.2.0): photo OCR + last-fillup card design - #18

Merged
varunpan merged 4 commits into
mainfrom
spec/v0.2.0-photo-ocr-and-last-fillup
May 9, 2026
Merged

spec(v0.2.0): photo OCR + last-fillup card design#18
varunpan merged 4 commits into
mainfrom
spec/v0.2.0-photo-ocr-and-last-fillup

Conversation

@varunpan

@varunpan varunpan commented May 9, 2026

Copy link
Copy Markdown
Owner

Design doc for the v0.2.0 feature pair brainstormed 2026-05-09. No code, doc only.

Captures the full design for:

  1. Photo OCR — optional, env-gated camera-button feature. Provider rule: ollama-only OR openrouter-only OR both-as-chain. Hidden from UI when neither is configured. Server-side schema-constrained extraction (Volume + Cost + pricePerUnit + unit), per-provider timeouts, daily budget cap, per-IP rate limit, append-only audit log to /data.
  2. Last-fillup card — compact two-line strip above the Vehicle picker showing the most recent LubeLogger entry for the loaded vehicle (Option A from the brainstorm). Uses already-loaded data from the page loader; no new endpoint.

Constraints honored:

  • Flat file convention in src/lib/server (no new nested dirs)
  • Zero new npm dependencies (Canvas API client-side, hand-written magic-byte sniff + schema validator + rate limiter)
  • /data bind mount reused for new persistence (no new compose mounts)
  • Compose hardening (read_only, cap_drop, etc.) preserved
  • All env vars documented inside existing Configuration tables (no new doc files)
  • Forward-compat for receipt OCR in v0.3.0

Implementation plan to follow in a separate session via the writing-plans skill.

Test plan

  • Spec self-review: no TBD/TODO placeholders, all referenced files declared in the layout section, error matrix matches data flow steps, env vars match across sections
  • User review of the spec doc before next session

varunpan and others added 4 commits May 9, 2026 08:33
PR #13 added a Settings card where the user pasted an iCloud share
URL and tapped to install. The framing implied "for future devices"
— but iCloud already auto-syncs Shortcuts across all Apple devices
on the same Apple ID, making the URL field redundant for the
single-user case.

The remaining real use case (sharing with a different Apple ID:
fork users, family) doesn't justify the in-app UI for a tool with
zero current fork users. Shifting that capability into docs only:
how to publish an iCloud link from Shortcuts and share with someone
who's not on your iCloud account.

Reverts:
- src/lib/client/prefs.ts — drop `siriShortcutUrl` field from Prefs
  + DEFAULT_PREFS
- src/routes/settings/+page.svelte — drop the entire "Siri shortcut"
  section, the saveShortcutUrl() / isLikelyValidIcloudUrl() helpers,
  and their imports

Updates:
- docs/shortcuts.md — replace the "Two ways to install" section
  (which referenced the now-removed Settings card) with a single
  "Sharing a shortcut with someone else" subsection covering the
  iCloud-link share flow with the placeholder-host trick. Mentions
  upfront that iCloud auto-syncs to your own devices so no manual
  step is needed for personal portability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "Re-publishing iCloud links" intro said the links were for
"future-you (or fork users) can install in one tap" — but iCloud
already auto-syncs to all your own Apple devices, so that's
misleading. The link is only useful for sharing across Apple IDs
(fork users, family).

Rewrites the intro to acknowledge iCloud auto-sync upfront and
re-scopes the table's purpose to cross-Apple-ID sharing only.
Adds a forward-pointer to the "Sharing a shortcut with someone
else" section near the top of the doc for the placeholder-host
trick.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
It's been daily-driven on the homelab through real fillups since
the v0.1.2 release with no regressions. The "early" label was
appropriate at v0.1.0 release; v0.1.2 has earned the stable label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design doc for the v0.2.0 feature pair brainstormed 2026-05-09:
photo OCR for pump-display Volume + Cost extraction (optional,
env-gated, ollama-or-openrouter or chained), and a compact
last-fillup card on the form.

Captures: architecture, file layout (flat — no new dirs, follows
existing src/lib/server convention), data flow, error matrix,
security (incl. prompt injection mitigations), env vars (with
per-provider timeouts), audit log shape, frontend principles for
the eventual frontend-design pass, testing strategy, doc updates,
forward-compat for receipt OCR (v0.3.0), and a 4-phase build plan.

Zero new npm dependencies — Canvas API for client-side resize,
hand-written magic-byte sniff, hand-written schema validator,
in-memory rate limiter extending the existing TtlCache pattern.

Implementation plan happens in a new session via writing-plans.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@varunpan
varunpan enabled auto-merge (squash) May 9, 2026 20:59
@varunpan
varunpan merged commit 1c29e40 into main May 9, 2026
1 check passed
varunpan added a commit that referenced this pull request May 9, 2026
Brainstorm specs and implementation plans are working artifacts
for the build process — not user-facing documentation. They lived
under docs/superpowers/ and got picked up by every PR. Moving
them out of git keeps the repo focused on shippable code +
end-user docs.

Removes from tracking:
- docs/superpowers/plans/2026-05-07-quicklogger-implementation.md
  (v0.1.0 implementation plan, no longer needed)
- docs/superpowers/specs/2026-05-07-quicklogger-design.md
  (v0.1.0 design, superseded by the shipped product)
- docs/superpowers/specs/2026-05-09-photo-ocr-and-last-fillup-design.md
  (v0.2.0 design, just landed via PR #18 — moving out of repo
  before any other contributor sees it)

Files stay on local disk (git rm --cached, not git rm). Future
specs/plans live there locally and never get committed thanks to
the .gitignore entry.

Note: prior commits in git history still contain the artifacts.
Acceptable per existing project policy on history retention.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@varunpan
varunpan deleted the spec/v0.2.0-photo-ocr-and-last-fillup branch May 10, 2026 14:42
varunpan added a commit that referenced this pull request Jun 11, 2026
The per-provider guard was 'typeof rate !== "number"', but typeof NaN is
'number', so a provider returning NaN (or 0, or a negative) passed, got
cached, and yielded cost * NaN / 0 / negative. Tightened all three branches
to Number.isFinite(rate) && rate > 0, so a bad rate is a provider failure
and the chain falls through.

Also removed the withTimeout() wrapper: it built an AbortController whose
signal was never wired to anything, so it was a no-op around the frankfurter
fetch. The real timeout is AbortSignal.timeout(TIMEOUT_MS), already on every
provider fetch; the frankfurter call now uses it directly.

Refs review #2, #18.
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