Field Upload — Multi-Photo, Caption Notes, On-Page Closeout

Date: 2026-07-30 (session 66) · Commits: entirely-api 4939599, 0517eb7

Trigger

MAN-9152 (6607 Muskrat Ct, Waldorf) — Darius ran his whole stop through the per-stop unlikely.pics link: 6 photos one at a time, notes typed as photo captions, every Vision proposal confirmed. Result: photos filed fine, but his notes never reached the portal (captions lived only in the 5-min proposal Redis TTL), the project stayed In Progress, and the site visit stayed Scheduled. He never messaged Kilroy, so the chat EOD closeout — the only path that advanced anything — never ran.

Changes (field_upload route + field_inspection service)

  1. Captions persist — non-empty caption → comm_log (“Field Note”, internal) via the write service → shows in portal Notes.
  2. Multi-photo upload — camera + gallery (multiple) inputs, thumbnail list with per-file remove, sequential batch upload with progress. Vision analyzes only the FIRST photo of a batch (one proposal per burst, not N — today’s single-photo flow produced 5 duplicate ENC-CSEAL proposals).
  3. On-page closeoutPOST /field-upload/p/{token}/closeout:
    • as_permitted → same fi.eod_closeout chain as Kilroy (lines inspected, as_built = permitted, F4 auto-advance → auto-validation), production-days input required when UND/ANC/BRC scope present.
    • issue → comm_log + Dustin portal notification, NO status change.
    • Page embeds the permitted scope list for the attestation question.
  4. eod_closeout now completes due site visits — new complete_due_visits() flips today-or-earlier Scheduled/En Route/On Site visits to Completed; future-dated return visits untouched. This fixes the same hole in Kilroy’s chat closeout (its SOUL never knew about /ops/complete-visit).

Kilroy interplay

SOUL.md updated: the page may close a stop before Kilroy hears about it — check field-status before running a chat EOD closeout; 30-min eod_closeout dedup window protects against double-fire. Scope CHANGES still go through Kilroy chat (page is as-permitted-only).

MAN-9152 remediation (same session)

Captions recovered from surviving Redis job payloads and filed to comm_log; eod-closeout executed (8 lines inspected, as_built = permitted), F4 → Field Complete → auto-validation passed → Ready for Cert (cert Draft); site visit marked Completed via /ops/update-visit-status.