Skip to content

feat: rework the submit screen and retire "bounty" for "request"#127

Merged
vidit-admin merged 4 commits into
mainfrom
claude/charming-haslett-e4e90f
Jul 4, 2026
Merged

feat: rework the submit screen and retire "bounty" for "request"#127
vidit-admin merged 4 commits into
mainfrom
claude/charming-haslett-e4e90f

Conversation

@vidit-admin

Copy link
Copy Markdown
Member

Three related changes on one branch.

1. Submit screen rework

The geolocation-vs-bounty mode toggle is gone. One unified form: fill what you have, and two content-gated actions decide the outcome.

  • A "Start from" chooser (Single / Bulk import) sits on top; the X-post pre-fill lives inside Single.
  • The two publish actions (Publish geolocation / Publish request) are gated by a live requirements tick-list that escalates from the request floor to the full geolocation floor. Each button dims until its floor is met and flags the missing fields red on a short click.

2. "bounty" retired for "request"

The product term "bounty" implied a reward that does not exist, so it is retired in favour of "request" (to return only if incentives ever do).

  • Frontend: route /bounties to /requests (with redirect stubs), all UI copy, internal names.
  • Backend wire vocabulary: the type=request search filter, the /admin/seed-demo-requests endpoint plus schemas.
  • Regenerated api-types plus reference docs.
  • The requested event status is unchanged (already request-based, no DB migration).
  • The alembic migrations and the historical CHANGELOG prose keep "bounty" as immutable history; CHANGELOG file links are repointed to the renamed files.

3. Icon language

  • New secondary Pill tone (documented in /palette).
  • Megaphone is request (nav, landing, search filter, Requested badge, Publish request button).
  • MapPin is geolocation (Geolocated badge, Publish geolocation button). The old bounty Target icon is retired.

Verification

  • Backend: ruff, mypy, 688 pytest.
  • Frontend: tsc, eslint, 155 vitest, knip, palette-coverage, api-types drift-clean.
  • Live preview: routes, /bounties redirects, submit flow, status badges, search filters.

🤖 Generated with Claude Code

vidit-admin and others added 3 commits July 4, 2026 21:29
Submit screen: one unified form replaces the geolocation-vs-bounty mode
toggle. A "Start from" chooser (Single / Bulk import) sits on top, and the
two publish actions (Publish geolocation / Publish request) are gated on a
live requirements tick-list, dimming until their floor is met and flagging
the missing fields red on a short click.

Terminology: "bounty" is retired in favour of "request" across the frontend
(route /bounties to /requests with redirect stubs, UI copy, internal names),
the backend wire vocabulary (the type=request search filter, the
/admin/seed-demo-requests endpoint plus schemas), the regenerated api-types,
and the reference docs. The `requested` event status is unchanged (already
request-based, no DB migration). The alembic migrations and the historical
CHANGELOG prose keep "bounty" as immutable history; CHANGELOG file links are
repointed to the renamed files.

Icons: a new secondary Pill tone, plus a consistent language. Megaphone is
request (nav, landing, search filter, Requested badge, Publish request) and
MapPin is geolocation (Geolocated badge, Publish geolocation). The old bounty
Target icon is retired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
The Requests board is the open-request queue by nature (its subtitle already
says so). The Open/Closed/All filter was a leftover from the bounty model and
read wrong: a fulfilled request becomes a geolocation and leaves the view, so
"closed" here meant "withdrawn", which reads as "done" on a work queue. The
page now shows only open (`requested`) requests; withdrawn ones stay reachable
by permalink. Enriching this into a triage board (sort, filters, activity
signals) is filed as a v1.0 item in planning/next.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
…llout

Two backend relaxations for the real OSINT workflow (the triple-review found
the old constraints too strict):
- A request may now carry OPTIONAL proof images (work started but not finished),
  reusing the geolocation intake (create_request sanitises with placeholders and
  runs attach_evidence_and_commit); no proof-image floor, so a blank request
  stays imageless. The /events/requests endpoint and createEventRequest send
  proof_files.
- event_time no longer requires event_date: an approximate hour-of-day (sun
  position, shadows) is knowable before the day. Removed the write.py guard.

Review cleanup, mostly the mechanical bounty->request sed's collateral:
- CHANGELOG: reverted the historical-prose edits (kept verbatim as an audit
  record, dead links and all) and added one Unreleased entry for this PR.
- planning/next.md: "the /requests router removed" was a rename artifact (there
  was never a /requests router); restored to "/bounties".
- Stale docs and comments the sed left: design.md's "two types" submit model,
  schemas/search.py's "reader vocabulary" note, the "ex-request" / "yesterday's
  request" phrasings, engineering.md's route tree.
- Removed em-dashes on lines the sed touched (search.py, admin.py, fieldHelp.ts).
- Tick-list labels now derive from a single FIELD_LABELS record in events.ts
  (they were a second copy of the validators' labels). ReqChecklist defaults to
  the secondary tone. Search result loop var b to r.

ruff / mypy (78) / pytest (689) green; tsc / eslint / vitest (156) / knip /
palette green; api-types.ts regenerated and in sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
vidit-admin added a commit that referenced this pull request Jul 4, 2026
… polish submit

Second review pass on #127: the triple-review's one judgment call plus the
accepted nits. Reuses the existing primitives and validators throughout.

Display:
- EventDetailBody splits the date row in two: "Event date" (date only) and a
  separate "Event time" row, shown when a time is set. A request may carry an
  approximate hour (sun position, shadows) with no day, so the time now
  surfaces on its own row instead of being folded into the date value or
  dropped when the day is unknown. formatEventDate (its only caller) is
  retired; formatDate covers the date row.

Coordinates:
- One strict parse for every coordinate on the submit form. The subject guess
  and the geolocation subject point move off parseFloat (which accepted
  "48.85abc" as 48.85) onto cleanNumber, matching the camera point. A new
  parseGuessCoords mirrors parseCaptureCoords (both-or-neither); the readiness
  validator uses the same parse, so a "ready" button can't fail on the backend.

Submit polish:
- ReqChecklist drops its dead metTone parameter (every call site used the
  default) and hardcodes the secondary / neutral tones.
- Readiness (the missing-field scans plus the curated-tag passes) is memoised,
  so it no longer recomputes on every keystroke.
- geoFulfilReqs filters on a semantic inheritedOnFulfil flag instead of
  string-matching the source_media key.
- The two publish handlers share a resetActions helper for their common
  reset-then-validate preamble.

Model + tests:
- event.py: the event_time comment no longer frames it as belonging to
  event_date (it may stand alone).
- New backend tests: a blank request stores the empty proof doc (never NULL),
  and an unsafe proof image src is dropped on the request path (the sanitiser
  still runs now that images are allowed). New frontend tests cover the
  two-row date / time split.
- next-env.d.ts: reverted the local dev-only path churn.

ruff / mypy (78) / pytest (691) green; tsc / eslint / vitest / knip / palette
green; api-types in sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
vidit-admin added a commit that referenced this pull request Jul 4, 2026
… polish submit

Second review pass on #127: the triple-review's one judgment call plus the
accepted nits. Reuses the existing primitives and validators throughout.

Display:
- EventDetailBody splits the date row in two: "Event date" (date only) and a
  separate "Event time" row, shown when a time is set. A request may carry an
  approximate hour (sun position, shadows) with no day, so the time now
  surfaces on its own row instead of being folded into the date value or
  dropped when the day is unknown. formatEventDate (its only caller) is
  retired; formatDate covers the date row.

Coordinates:
- One strict parse for every coordinate on the submit form. The subject guess
  and the geolocation subject point move off parseFloat (which accepted
  "48.85abc" as 48.85) onto cleanNumber, matching the camera point. A new
  parseGuessCoords mirrors parseCaptureCoords (both-or-neither); the readiness
  validator uses the same parse, so a "ready" button can't fail on the backend.

Submit polish:
- ReqChecklist drops its dead metTone parameter (every call site used the
  default) and hardcodes the secondary / neutral tones.
- Readiness (the missing-field scans plus the curated-tag passes) is memoised,
  so it no longer recomputes on every keystroke.
- geoFulfilReqs filters on a semantic inheritedOnFulfil flag instead of
  string-matching the source_media key.
- The two publish handlers share a resetActions helper for their common
  reset-then-validate preamble.

Model + tests:
- event.py: the event_time comment no longer frames it as belonging to
  event_date (it may stand alone).
- New backend tests: a blank request stores the empty proof doc (never NULL),
  and an unsafe proof image src is dropped on the request path (the sanitiser
  still runs now that images are allowed). New frontend tests cover the
  two-row date / time split.
- next-env.d.ts: reverted the local dev-only path churn.

ruff / mypy (78) / pytest (691) green; tsc / eslint / vitest / knip / palette
green; api-types in sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
@vidit-admin vidit-admin force-pushed the claude/charming-haslett-e4e90f branch from 799c0dd to b0a8ea5 Compare July 4, 2026 21:47
… polish submit

Second review pass on #127: the triple-review's one judgment call plus the
accepted nits. Reuses the existing primitives and validators throughout.

Display:
- EventDetailBody splits the date row in two: "Event date" (date only) and a
  separate "Event time" row, shown when a time is set. A request may carry an
  approximate hour (sun position, shadows) with no day, so the time now
  surfaces on its own row instead of being folded into the date value or
  dropped when the day is unknown. formatEventDate (its only caller) is
  retired; formatDate covers the date row.

Coordinates:
- One strict parse for every coordinate on the submit form. The subject guess
  and the geolocation subject point move off parseFloat (which accepted
  "48.85abc" as 48.85) onto cleanNumber, matching the camera point. A new
  parseGuessCoords mirrors parseCaptureCoords (both-or-neither); the readiness
  validator uses the same parse, so a "ready" button can't fail on the backend.

Submit polish:
- ReqChecklist drops its dead metTone parameter (every call site used the
  default) and hardcodes the secondary / neutral tones.
- Readiness (the missing-field scans plus the curated-tag passes) is memoised,
  so it no longer recomputes on every keystroke.
- geoFulfilReqs filters on a semantic inheritedOnFulfil flag instead of
  string-matching the source_media key.
- The two publish handlers share a resetActions helper for their common
  reset-then-validate preamble.

Model + tests:
- event.py: the event_time comment no longer frames it as belonging to
  event_date (it may stand alone).
- New backend tests: a blank request stores the empty proof doc (never NULL),
  and an unsafe proof image src is dropped on the request path (the sanitiser
  still runs now that images are allowed). New frontend tests cover the
  two-row date / time split.
- Removed the orphaned EMPTY_TIPTAP_DOC constant (nothing imported it once
  create_request stopped; each layer inlines a fresh empty doc for aliasing
  safety), which unblocks the vulture dead-code gate.
- next-env.d.ts: reverted the local dev-only path churn.

ruff / mypy (78) / pytest (691) green; tsc / eslint / vitest / knip / palette
green; api-types in sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: vidit-admin <admin@vidit.app>
@vidit-admin vidit-admin force-pushed the claude/charming-haslett-e4e90f branch from b0a8ea5 to 2d3f474 Compare July 4, 2026 21:54
@vidit-admin vidit-admin merged commit b920198 into main Jul 4, 2026
11 checks passed
@vidit-admin vidit-admin deleted the claude/charming-haslett-e4e90f branch July 4, 2026 21:59
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