Guarantee manual fallback without AI and in-session draft recovery (#12) #68

Closed
rockachopa wants to merge 0 commits from timmy/12-manual-fallback-draft-recovery into main
pull from: timmy/12-manual-fallback-draft-recovery
Member

Closes #12

Outcome

Logging never depends on AI availability, and an unsaved entry is not lost by recoverable navigation.

Acceptance criteria

  • Offline/provider-down reaches manual Bristol entry in one action. src/vision-readiness.js gives the photo flow a single readiness contract. When the worker is offline, disabled, or still unknown, the analyze control and the consent prompt are not rendered at all (no dead control, no consent for an upload that cannot happen), and the manual CTA is the primary action on the pick, ready, and error steps.
  • Selected photo and entered context survive recoverable navigation. src/draft.js makes the draft own the photo and context. Closing the sheet, switching views, and reopening the logger resume the same draft with a visible kept-draft summary and an explicit Start over.
  • Service worker never caches analysis requests or image bodies. api/ stays network-only and the fetch handler now also refuses to persist image/* responses.

Privacy/safety disposition

Drafts are deliberately held in session memory only, never written to storage, so a photo awaiting analysis consent is not persisted. A reload starts clean; this is recorded in docs/PRODUCT-DECISIONS.md ("Availability and draft retention"). No AI field, escalation rule, or non-diagnostic boundary changed.

Evidence

  • npm test: 81/81 pass (adds tests/draft.test.js, tests/vision-readiness.test.js)
  • python3 tests/staging-deploy.test.py: 20/20 OK
  • Browser acceptance: test:ui, test:photo, test:mobile-capture, test:sleek, and new test:manual-fallback all pass
  • npm run check:syntax, npm run check:diff: clean
  • 3 service-worker privacy tests: one genuine RED cycle (image body was cached before the guard), one hold-out that ordinary shell assets are still cached

Demo path

scripts/record_release_demo.mjs now flips the app's own readiness contract mid-recording and visibly replays: vision offline -> no consent/no upload -> one tap to manual Bristol entry -> kept draft (Type 4 * photo) -> start over. It asserts the retained draft on the live DOM, and tests/release-demo.test.js locks the captions. Verified locally: the recording decodes end to end and OCR of the recorded frames shows the offline ready screen and the kept-draft banner.

Not merged; release candidate approval stays a human gate.

Closes #12 ## Outcome Logging never depends on AI availability, and an unsaved entry is not lost by recoverable navigation. ## Acceptance criteria - **Offline/provider-down reaches manual Bristol entry in one action.** `src/vision-readiness.js` gives the photo flow a single readiness contract. When the worker is offline, disabled, or still unknown, the analyze control and the consent prompt are not rendered at all (no dead control, no consent for an upload that cannot happen), and the manual CTA is the primary action on the pick, ready, and error steps. - **Selected photo and entered context survive recoverable navigation.** `src/draft.js` makes the draft own the photo and context. Closing the sheet, switching views, and reopening the logger resume the same draft with a visible kept-draft summary and an explicit **Start over**. - **Service worker never caches analysis requests or image bodies.** `api/` stays network-only and the fetch handler now also refuses to persist `image/*` responses. ## Privacy/safety disposition Drafts are deliberately held in session memory only, never written to storage, so a photo awaiting analysis consent is not persisted. A reload starts clean; this is recorded in `docs/PRODUCT-DECISIONS.md` ("Availability and draft retention"). No AI field, escalation rule, or non-diagnostic boundary changed. ## Evidence - `npm test`: 81/81 pass (adds `tests/draft.test.js`, `tests/vision-readiness.test.js`) - `python3 tests/staging-deploy.test.py`: 20/20 OK - Browser acceptance: `test:ui`, `test:photo`, `test:mobile-capture`, `test:sleek`, and new `test:manual-fallback` all pass - `npm run check:syntax`, `npm run check:diff`: clean - 3 service-worker privacy tests: one genuine RED cycle (image body was cached before the guard), one hold-out that ordinary shell assets are still cached ## Demo path `scripts/record_release_demo.mjs` now flips the app's own readiness contract mid-recording and visibly replays: vision offline -> no consent/no upload -> one tap to manual Bristol entry -> kept draft (`Type 4 * photo`) -> start over. It asserts the retained draft on the live DOM, and `tests/release-demo.test.js` locks the captions. Verified locally: the recording decodes end to end and OCR of the recorded frames shows the offline ready screen and the kept-draft banner. Not merged; release candidate approval stays a human gate.
rockachopa added 1 commit 2026-10-07 08:12:51 +00:00
feat: guarantee manual fallback and in-session draft recovery (#12)
Quality gates / quality (pull_request) Successful in 1m54s
dce668e72b
Logging must never depend on AI availability, and an unsaved entry must not
disappear when the user navigates away mid-log.

- add src/vision-readiness.js so the photo flow consumes one readiness contract
- when the worker is offline/disabled/unknown, offer no AI action and no
  analysis-consent prompt, and keep manual Bristol entry one action away
- add src/draft.js and make the draft own the photo so a chosen photo and
  entered context survive a recoverable close or navigation, with a visible
  kept-draft summary and an explicit start over
- drafts stay in session memory only: a photo awaiting consent is never
  persisted, and reload starts clean
- service worker now refuses to cache image bodies in addition to analysis
  requests and no-store responses
- tests: 2 new unit files, 3 service-worker privacy assertions (1 hold-out),
  1 browser acceptance file, release-demo and CI/package assertions
- release demo now visibly replays the vision-offline pass and the retained
  draft with synthetic data and an in-script assertion
Author
Member

Merged into main as merge commit 3e87f881c5 (head dce668e72b).

Pre-merge verification on dce668e in an isolated clone: npm test 81/81 pass; browser acceptance flows ui, photo-first, mobile-capture, sleek-chat, and manual-fallback all PASS; diff scanned for secrets and forbidden artifacts (none); added artifacts/ PNGs are app-UI screenshots of the synthetic flow, not real imagery.

Closing this PR record so the forge matches main.

Merged into main as merge commit 3e87f881c57cee928c18d00ba5b1d1ebe2637021 (head dce668e72b97b64b6b1b4ec862e7629c08c2b6c0). Pre-merge verification on dce668e in an isolated clone: npm test 81/81 pass; browser acceptance flows ui, photo-first, mobile-capture, sleek-chat, and manual-fallback all PASS; diff scanned for secrets and forbidden artifacts (none); added artifacts/ PNGs are app-UI screenshots of the synthetic flow, not real imagery. Closing this PR record so the forge matches main.
rockachopa closed this pull request 2026-10-07 12:03:18 +00:00

Pull request closed

Please reopen this pull request to perform a merge.
Sign in to join this conversation.