Skip to content

Integrate treasury management, refactor bounty UI, and enhance crowdfunding features#665

Merged
0xdevcollins merged 35 commits into
mainfrom
feat/t-replace
Jun 30, 2026
Merged

Integrate treasury management, refactor bounty UI, and enhance crowdfunding features#665
0xdevcollins merged 35 commits into
mainfrom
feat/t-replace

Conversation

@0xdevcollins

@0xdevcollins 0xdevcollins commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added AI-assisted creation and regeneration flows for organizing bounties and hackathons, including step-by-step guidance, live draft previews, and optional brief examples.
    • Added review-time AI summaries and assumption banners so organizers can inspect AI output before publishing.
    • Added clearer funding and publish dialogs with support for different funding sources and progress states.
  • Bug Fixes

    • Improved draft regeneration and publish recovery flows, including better handling of interrupted or busy AI requests.
    • Added monthly AI usage visibility to help avoid running out of generations.

0xdevcollins and others added 30 commits June 11, 2026 07:37
…eceipts/send

Winners: new task-first Winners section (pick winner per prize with engine default, inline stacking confirm, deliberate 'Don't award' + unawarded-funds acknowledgement); /rewards redirects to /winners; staged Pick -> Confirm -> Pay.

Judging: slimmed Results tab to read-only standings + 'Go to Winners'; criterionId name fix; AI scorecards, recommendation thresholds, CSV judge import, tracks + custom questions wizard sections; validation + empty-state polish.

Public: private + password access gate, community links, card private badge. Treasury: receipts + Send funds. Removed the stacking toggle from prize setup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…599) (#611)

The net-new bounty UI with no hackathon analog: the two-axis mode picker and
the mode-conditional submission settings that drive all six combinations.

- modeSchema.ts: plain taxonomy unions (entryType x claimType), the
  computeBountyModeLabel helper, and getModeFields — the mode -> field matrix
  derived functionally from the publish gate (validateTwoAxisMode) so it cannot
  drift from the backend.
- submissionModelSchema.ts: makeSubmissionModelSchema(mode), a mode-aware Zod
  factory whose required fields and the >=2 floors (maxApplicants for open
  competition, shortlistSize for application competition) mirror the server gate.
- ModeTab.tsx: entry x claim picker, a winners stepper (1-3) for competitions,
  and a live computed mode label.
- SubmissionModelTab.tsx: renders each field per the matrix (required / optional
  / hidden) and shows submissionVisibility read-only, forced by the mode
  (HIDDEN_UNTIL_DEADLINE for competitions).

Standalone components (props: mode, onSave, onContinue, initialData, isLoading);
they wire into the wizard shell + routes in #597 / #598.
…ow) (#596) (#612)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.
Completes the editable surface of the bounty Configure wizard, dropping the
three remaining tabs into the seams the shell (#598) left.

- tabs/schemas/scopeSchema.ts: title, description, optional GitHub issue
  url/number, optional project/window.
- tabs/schemas/rewardSchema.ts: makeRewardSchema(claimType) — exactly one tier
  for single claim, 1-3 for a competition; amounts > 0, unique positions
  including position 1 (mirrors the publish gate's deriveWinnerDistribution).
- lib/utils/bounty-escrow.ts: adapts the bounty reward shape to reuse the
  hackathon prize-pool math (getTotalPrizePoolForFunding, buildWinnerDistribution,
  2.5% PLATFORM_FEE) rather than duplicating it.
- tabs/ScopeTab.tsx: scope form.
- tabs/RewardTab.tsx: currency + mode-driven prize tiers (field array sized to
  the winner count) with a live prize-pool / fee / total preview.
- tabs/ReviewTab.tsx: per-section summary, validation summary, funding totals,
  and a publish CTA disabled until every section validates.
- NewBountyTab.tsx + constants.ts: wire the three tabs into the wizard; the form
  snapshot now uses the per-tab form schema types.

Reward currency is collected in the Reward step (the backend section that
persists it) rather than Scope, so it round-trips. The publish action is a
placeholder pending the escrow publish flow (#601); the disabled-until-valid
gate is wired here.
…601) (#615)

* feat(bounty): Scope + Reward + Review tabs and Zod schemas (#600)

Completes the editable surface of the bounty Configure wizard, dropping the
three remaining tabs into the seams the shell (#598) left.

- tabs/schemas/scopeSchema.ts: title, description, optional GitHub issue
  url/number, optional project/window.
- tabs/schemas/rewardSchema.ts: makeRewardSchema(claimType) — exactly one tier
  for single claim, 1-3 for a competition; amounts > 0, unique positions
  including position 1 (mirrors the publish gate's deriveWinnerDistribution).
- lib/utils/bounty-escrow.ts: adapts the bounty reward shape to reuse the
  hackathon prize-pool math (getTotalPrizePoolForFunding, buildWinnerDistribution,
  2.5% PLATFORM_FEE) rather than duplicating it.
- tabs/ScopeTab.tsx: scope form.
- tabs/RewardTab.tsx: currency + mode-driven prize tiers (field array sized to
  the winner count) with a live prize-pool / fee / total preview.
- tabs/ReviewTab.tsx: per-section summary, validation summary, funding totals,
  and a publish CTA disabled until every section validates.
- NewBountyTab.tsx + constants.ts: wire the three tabs into the wizard; the form
  snapshot now uses the per-tab form schema types.

Reward currency is collected in the Reward step (the backend section that
persists it) rather than Scope, so it round-trips. The publish action is a
placeholder pending the escrow publish flow (#601); the disabled-until-valid
gate is wired here.

* feat(bounty): use-bounty-publish (escrow publish via shared runner) (#601)

Wires the bounty publish action, mirroring use-hackathon-publish.

- hooks/use-bounty-publish.ts: builds PublishBountyEscrowDto (ownerAddress,
  tokenAddress via getTokenAddress('USDC'), budget = sum of tier amounts,
  submissionDeadline as unix from the draft deadline, applicationCreditCost,
  winnerDistribution via the shared buildBountyWinnerDistribution, fundingMode)
  and drives it with useEscrowOpRunner: MANAGED returns PENDING_CONFIRM then
  polls; EXTERNAL signs the returned XDR via signXdrWithKit then submits + polls.
  On COMPLETED the bounty has moved draft_awaiting_funding -> open. Pre-flight
  resumes an in-flight op, short-circuits an already-published bounty, and runs a
  MANAGED USDC balance check (pool + 2.5% fee).
- NewBountyTab.tsx: replace the Review placeholder with the real publish() and
  wire isPublishing into the CTA.

Treasury funding (sourceWalletId) is omitted until the backend treasury-parity
issue (boundless-nestjs #314) lands; MANAGED + EXTERNAL are supported. The
funding-source picker + progress modal remain a follow-up; the hook exposes the
escrow phase/error/txHash they need.
Adds the organizer bounty routes, mirroring the hackathon route tree, and the
published-list data needed by the list page.

- app/(landing)/organizations/[id]/bounties/page.tsx: list page with a Drafts
  section (resume links + status badges + mode label / section count) and a
  Published section (status badges + reward), plus a "Host a bounty" CTA.
- .../bounties/new/page.tsx: renders <NewBountyTab organizationId={id} />.
- .../bounties/drafts/[draftId]/page.tsx: renders
  <NewBountyTab organizationId={id} draftId={draftId} />.
- features/bounties/api/core.ts + use-bounties.ts: listOrganizationBounties +
  useOrganizationBounties for the root list (the backend root GET has no
  response DTO, so the row shape is projected to OrganizationBountyListItem).

The pages mount the existing wizard shell (#598); the list separates drafts
(draft / draft_awaiting_funding) from published bounties so they don't
double-list.
Adds a Bounties menu item (/organizations/{orgId}/bounties) and a Post Bounty
quick action (/organizations/{orgId}/bounties/new) to OrganizationSidebar, so
organizers can reach the bounty list + Configure wizard.

Codegen reconcile: re-ran npm run codegen against the v2 backend; the committed
lib/api/generated/schema.d.ts already matches (BountyDraftResponseDto +
UpdateBountyDraftDto present, no drift), so no schema change is needed.
…618)

* feat(bounty): wizard enhancements (resources step, currency, reputation, nav)

- Resources: new optional Resources step (links + PDF/DOC/PPT/MD uploads),
  mirroring the hackathon resources tab; never blocks publish. Reuses a now
  configurable ResourceFileUpload (folder/tags/accepted types props; unique
  input id per row).
- Reward currency: dropdown of USDC (default) / XLM (disabled) with real token
  logos, replacing the free-text field.
- Reputation: per-category minimum floor (development highest); the organizer
  can raise it but not drop below the category baseline.
- Navigation: Back button on every step after the first.
- Scope: category chips + searchable country dropdown with flags + markdown
  description; GitHub issue URL required only for development.
- Publish: redirect to the organizer's bounty list once publish finalizes.
- Dev-only "Fill with mock" button to populate every section at once.

* feat(bounty): hackathon-style org bounty list + delete-draft confirm

- Rebuild the organization bounty list page in the hackathon style: sticky
  header with stats, Published/Drafts tabs, search + sort, and a banner-less
  reward-focused card grid (draft cards show a progress bar + resume link).
- Deleting a draft now opens a confirmation modal (DeleteBountyDraftDialog)
  instead of deleting on the first click.
- Expose `_count.submissions` on the org bounty list item for the cards.
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.

* feat: implement multi-step crowdfunding campaign wizard with milestone management

* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking

- Redesigned public listing (ProjectCard) and detail page with proper
  lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
  contributions) with shared header showing milestone X/Y progress and
  Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
  "paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
  during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
  inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
  footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
  milestone status copy and tone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update lockfile dependencies for package-lock.json

---------

Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.

* feat: implement multi-step crowdfunding campaign wizard with milestone management

* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking

- Redesigned public listing (ProjectCard) and detail page with proper
  lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
  contributions) with shared header showing milestone X/Y progress and
  Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
  "paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
  during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
  inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
  footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
  milestone status copy and tone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update lockfile dependencies for package-lock.json

* refactor: standardize API error extraction to support array-based messages across crowdfunding components

* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic

---------

Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.

* feat: implement multi-step crowdfunding campaign wizard with milestone management

* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking

- Redesigned public listing (ProjectCard) and detail page with proper
  lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
  contributions) with shared header showing milestone X/Y progress and
  Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
  "paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
  during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
  inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
  footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
  milestone status copy and tone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update lockfile dependencies for package-lock.json

* refactor: standardize API error extraction to support array-based messages across crowdfunding components

* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic

* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details

---------

Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.

* feat: implement multi-step crowdfunding campaign wizard with milestone management

* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking

- Redesigned public listing (ProjectCard) and detail page with proper
  lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
  contributions) with shared header showing milestone X/Y progress and
  Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
  "paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
  during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
  inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
  footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
  milestone status copy and tone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update lockfile dependencies for package-lock.json

* refactor: standardize API error extraction to support array-based messages across crowdfunding components

* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic

* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details

* fix: useCampaign routes UUID params to fetchCampaignById

Post-create redirect lands on /me/crowdfunding/{uuid}. The hook was
always calling the slug endpoint which rejected UUIDs. Now detects
UUID format and uses the correct /api/crowdfunding/{id} endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: auth-gate voting/contribute + branded fallback banner

- VotePanel: unauthenticated users see "Sign in to vote" instead of
  the yes/no buttons
- Public page: "Back this project" replaced with "Sign in to back this
  project" link for unauthenticated visitors
- Fallback banner (no banner set): full-height Boundless-branded SVG
  with dot grid, concentric arcs in brand colour, and faint wordmark
  instead of the flat zinc gradient div

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(bounty): features/bounties data layer (types, keys, draft + escrow) (#596)

Adds the features/bounties/ data layer for the v1 app, mirroring
features/hackathons/. REST-only via the typed openapi-fetch client; every
server shape is aliased from the backend-generated schema so it cannot drift.

- types.ts: aliases the generated draft + escrow DTOs (BountyDraft,
  UpdateBountyDraftBody, the four section types, BountyEscrowOpResponse,
  PublishBountyEscrowRequest, ...). Derives the two-axis taxonomy from the
  generated mode DTO, superseding the local stubs in the ModeTab.
- api/keys.ts: bountyKeys factory.
- api/draft-client.ts + use-draft.ts: imperative CRUD plus the
  useDraft / useDraftList / useCreateDraft / useUpdateDraft / useDeleteDraft
  hooks against /organizations/{organizationId}/bounties/draft[/{id}] + /drafts.
- api/escrow-client.ts + use-escrow.ts: organizer escrow calls (publish /
  cancel / select-winners / submit-signed / poll) plus useEscrowOp +
  useEscrowOpRunner, mirroring the hackathon machinery (MANAGED polls; EXTERNAL
  signs -> submit -> poll) bounty-scoped.
- index.ts: public surface.

Regenerates lib/api/generated/schema.d.ts from the v2 backend so the bounty
draft paths/DTOs are present.

* feat(bounty): wizard shell + step/draft machinery (#598)

Adds the bounty Configure wizard orchestrator and its step + draft state,
mirroring the hackathon wizard. No AI assist.

- components/organization/bounties/new/constants.ts: StepKey
  (scope/mode/submission/reward/review), STEP_ORDER, BountyFormData, and
  isBountyStepDataValid.
- hooks/use-bounty-steps.ts: URL ?step= navigation (free-roam) with a
  presentational step-status map.
- hooks/use-bounty-draft.ts: lazy create (ensureDraftId) then per-section PATCH,
  resume via useDraft, and transformBountyFromApi (sections -> form state;
  winnerCount derived from prize tiers, ISO dates trimmed for the inputs).
- components/organization/bounties/new/NewBountyTab.tsx: orchestrator wiring
  steps + draft + per-step save, persisting ?draftId= for resume, and threading
  the chosen mode from ModeTab into SubmissionModelTab.

Scope/Reward/Review tabs (#600) and the publish + funding flow (#601) are left
as marked placeholders with their save/navigate/draftId seams in place; this
satisfies the acceptance criteria (navigate, autosave, resume) without
speculative publish UI that depends on the unbuilt publish hook.

* feat: implement multi-step crowdfunding campaign wizard with milestone management

* feat(crowdfunding): v2 public pages, builder dashboard, milestone tracking

- Redesigned public listing (ProjectCard) and detail page with proper
  lifecycle states, voting panel, contributor list, and fully-funded detection
- Added public milestone list + detail pages under /crowdfunding/[slug]/milestones
- Builder per-campaign management: tabbed layout (overview / milestones /
  contributions) with shared header showing milestone X/Y progress and
  Fully Funded badge once fundingRaised >= fundingGoal
- Milestone status sourced from milestoneState() utility: claimedAt-based
  "paid out" detection replaces stale reviewStatus === 'completed' checks
- CampaignStatusBanner: shows milestone delivery bar and Fully Funded label
  during the FUNDING phase when goal is reached
- milestones-metrics: completedAmount correctly sums paid-out milestones;
  inProgress checks SUBMITTED/UNDER_REVIEW enum values
- ProjectCard: switches from funding bar to milestone X/Y bar on fully funded;
  footer and status badge update to Fully Funded (green)
- lib/crowdfunding/status.ts: single source of truth for all campaign and
  milestone status copy and tone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update lockfile dependencies for package-lock.json

* refactor: standardize API error extraction to support array-based messages across crowdfunding components

* refactor: restructure StoryStep inputs, enable sidebar navigation, and update campaign wizard validation logic

* feat: replace textarea with AnnouncementEditor and add markdown rendering for campaign project details

* fix: useCampaign routes UUID params to fetchCampaignById

Post-create redirect lands on /me/crowdfunding/{uuid}. The hook was
always calling the slug endpoint which rejected UUIDs. Now detects
UUID format and uses the correct /api/crowdfunding/{id} endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: auth-gate voting/contribute + branded fallback banner

- VotePanel: unauthenticated users see "Sign in to vote" instead of
  the yes/no buttons
- Public page: "Back this project" replaced with "Sign in to back this
  project" link for unauthenticated visitors
- Fallback banner (no banner set): full-height Boundless-branded SVG
  with dot grid, concentric arcs in brand colour, and faint wordmark
  instead of the flat zinc gradient div

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: unify campaign description rendering logic to prioritize details over description fields across project components

---------

Co-authored-by: Benjtalkshow <chinedubenj@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.

- participant-escrow-client: on-chain apply/submit/withdraw-application/
  withdraw-submission/contribute + participant op poll + submit-signed
  (the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
  (apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
  useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
  hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
  useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
  runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
  op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports

MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).

Closes #621
* feat(bounty): participant data layer (escrow client + hooks)

Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.

- participant-escrow-client: on-chain apply/submit/withdraw-application/
  withdraw-submission/contribute + participant op poll + submit-signed
  (the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
  (apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
  useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
  hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
  useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
  runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
  op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports

MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).

Closes #621

* feat(bounty): public bounty marketplace (discover/list)

Replace the /coming-soon placeholder at /bounties with a real public
marketplace, mirroring the hackathon browse and wired to the participant
data layer (#621).

- route app/(landing)/bounties/page.tsx + bounties metadata entry
- BountiesPage: search + status + mode filters, infinite scroll,
  loading/empty/error states
- BountyCard: mode badge (plain label), status, reward, organization,
  application-window date; links to /bounties/[id]
- BountiesFiltersHeader + colocated useInfiniteBounties (infinite query
  over listBounties)

Status + search filter server-side; mode narrows client-side (the public
list endpoint doesn't filter on mode). Category filter and a card submission
deadline are omitted because BountyPublicDto exposes neither — small backend
follow-ups.

Closes #622
* feat(bounty): participant data layer (escrow client + hooks)

Add the builder/participant data layer to features/bounties, mirroring the
hackathon participant scope and reusing the shared escrow runner. The visible
builder UI (marketplace, detail, apply/submit/withdraw, my-bounties) consumes
this.

- participant-escrow-client: on-chain apply/submit/withdraw-application/
  withdraw-submission/contribute + participant op poll + submit-signed
  (the no-org-prefix /api/bounties/{id}/escrow/* routes)
- participant-client: public list/detail, v2 application records
  (apply/edit/withdraw/me), competition join/leave
- use-participant hooks: useBountiesList/useBounty/useMyBountyApplication,
  useApply/Edit/WithdrawApplication, useJoin/LeaveCompetition, and escrow-op
  hooks (useSubmitBounty/useWithdrawSubmission/useContributeToBounty/
  useApplyToBountyEscrow/useWithdrawApplicationEscrow) driven through the
  runner, default MANAGED
- use-escrow: EscrowOpScope is now organizer | participant; the runner routes
  op-poll/submit-signed to the participant URLs
- keys/types/index: participant query keys, type aliases, public exports

MyBountyApplication is hand-typed until boundless-nestjs #331 lands and codegen
runs; useMyBountyActivity is deferred until the participant dashboard (#332).

Closes #621

* feat(bounty): public bounty marketplace (discover/list)

Replace the /coming-soon placeholder at /bounties with a real public
marketplace, mirroring the hackathon browse and wired to the participant
data layer (#621).

- route app/(landing)/bounties/page.tsx + bounties metadata entry
- BountiesPage: search + status + mode filters, infinite scroll,
  loading/empty/error states
- BountyCard: mode badge (plain label), status, reward, organization,
  application-window date; links to /bounties/[id]
- BountiesFiltersHeader + colocated useInfiniteBounties (infinite query
  over listBounties)

Status + search filter server-side; mode narrows client-side (the public
list endpoint doesn't filter on mode). Category filter and a card submission
deadline are omitted because BountyPublicDto exposes neither — small backend
follow-ups.

Closes #622

* feat(bounty): bounty detail page (/bounties/[id])

The builder hub: shows the bounty, the caller's status, and a mode-aware
entry CTA. Wired to the participant data layer (#621).

- route app/(landing)/bounties/[id]/page.tsx
- BountyDetail: markdown description, prize tiers, mode/status badges,
  organization, reward pool + eligibility sidebar (reputation minimum /
  application window / max applicants / shortlist); loading + not-found
- BountyEntryCta: mode-aware CTA — Claim (open+single), Join (open+
  competition), Apply (application). Gated/explained when not accepting,
  the application window closed, or already applied; shows the caller's
  application status via useMyBountyApplication

The actual entry execution (forms / on-chain op) ships in #624; the CTA is
gated + labeled and hands off to it. applicationCreditCost is not in
BountyPublicDto so it's omitted from the eligibility panel.

Closes #623
…647)

Fill the entry execution the detail-page CTA hands off to (#623), wired to
the participant data layer (#621). Covers all six modes.

- applicationSchema: mode-aware zod validation + body builders (light:
  proposalShort 100-300 words + estimatedDays + <=3 links; full: proposalFull
  500-2000 words + qualifications >=50 chars + <=6 links + optional video)
- BountyApplicationForm: conditional fields per entry type with live word
  count; reused for create + edit
- BountyEntryDialog: mode-aware modal — Apply (POST v2/applications) / Edit
  (PATCH); Join (POST v2/competition/join); Claim (on-chain apply escrow op,
  MANAGED, with progress + reputation pre-check). Wallet-gated.
- BountyEntryCta: opens the dialog and, for an active application, exposes
  Edit + Withdraw (application), Leave (competition), or on-chain Withdraw
  (single claim) behind a two-step confirm

Closes #624
After entry (claim/join/selection) the builder submits their deliverable,
anchored on-chain via the participant escrow runner (#621). Mirrors the
hackathon submission anchor.

- BountySubmitPanel (detail sidebar, shown when eligible: claimed/joined/
  SELECTED/SHORTLISTED): contentUri deliverable input -> submit escrow op
  (useSubmitBounty, MANAGED) with anchor progress (preparing -> anchoring ->
  confirmed) + tx-hash explorer link
- Withdraw submission via useWithdrawSubmission behind a two-step confirm
- Wallet-gated; guarded by entry eligibility

Persistent submission state across reloads is session-local until the #332
my-submission read lands in the schema; the submission-deadline gate is
enforced on-chain (not in BountyPublicDto).

Closes #625
The builder's /me surfaces for bounty applications, submissions, and reward
receipts, consuming the participant dashboard (#332) + earnings (#335).

- data layer: useMyBountyApplications / useMyBountySubmissions (the deferred
  useMyBountyActivity) via the legacy axios api (hand-typed rows, retry:false,
  degrading to empty until #332 lands in the schema)
- /me/bounties page: Applications + Submissions tabs with status/progress
  badges; won submissions show the reward amount + a payout tx-hash link;
  rows link to the detail page
- sidebar: "My Bounties" nav entry
- /me/earnings: the page already renders breakdown.bounties + activities
  generically (so #335 surfaces them); add a "View tx" link to reward
  activities (txHash cast until codegen)

Closes #626
GitHub's built-in Closes/Fixes/Resolves auto-close only fires for PRs
merged into the default branch. Feature PRs here merge into integration
branches (feat/t-replace, etc.), leaving linked issues open. This adds a
pull_request_target workflow that parses the merged PR body and closes
the referenced same-repo issues on any base branch.
…627) (#653)

The participant gap endpoints (applications/me, my-activity, results) have
landed in v2, so regenerate the OpenAPI schema and replace the two
hand-typed casts (MyBountyApplication, my-activity dashboard rows) with
their generated DTO aliases. Refresh openapi.snapshot.json so offline/CI
codegen matches. Nav entries (marketplace + /me sidebar) already shipped.
0xdevcollins and others added 4 commits June 25, 2026 11:05
…quirements (#662)

* feat(bounty): submission metadata types, category filter, and wizard requirement toggles

Refresh the generated OpenAPI schema for the new public-bounty fields
(claimedBy, category, submissionDeadline, submissionRequirements) and the
submit-op metadata. Add the category query param to the marketplace list
client, the per-bounty my-submission read + hook, and the organizer
requirement toggles in the Configure wizard's submission step. Flatten the
category reputation baseline to 0 for testing and let the wizard accept a
0 floor.

* feat(bounty): marketplace card redesign, category tabs, and detail display

Bounty cards now show the organizer logo, category, a live due-date
countdown, and the USDC token logo (title only, no markdown bleed). Add a
category tab bar to the marketplace and mirror the same details on the
detail page, plus a mode-explainer tooltip. Single-claim bounties render a
'Claimed by' card linking to the claimant profile, and the application
withdraw button is gated while a submission is anchored.

* feat(bounty): dedicated submit page with metadata and media upload

Replace the single-input submit panel with a /bounties/[id]/submit page:
primary submission link plus optional documentation, tweet, and demo video
links and a drag-and-drop media uploader. Required fields follow the
bounty's organizer-configured requirements; on success it returns to the
detail page. The sidebar panel now routes here (new tab) and reflects the
submitted/withdraw state.
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
boundless Ready Ready Preview, Comment Jun 30, 2026 7:56am
boundless-kd16 Ready Ready Preview, Comment Jun 30, 2026 7:56am

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 636f5c1d-0dbb-4941-bf33-0f0b801b8b13

📥 Commits

Reviewing files that changed from the base of the PR and between a817075 and e08d06c.

⛔ Files ignored due to path filters (1)
  • lib/api/generated/schema.d.ts is excluded by !**/generated/**
📒 Files selected for processing (30)
  • components/ai/AiAssumptionsBanner.tsx
  • components/ai/AiBriefPanel.tsx
  • components/ai/AiClarifyQuestions.tsx
  • components/ai/AiExampleReference.tsx
  • components/ai/AiRegenerateControl.tsx
  • components/ai/AiStreamPreview.tsx
  • components/ai/AiUsageNote.tsx
  • components/organization/bounties/new/GenerateWithAiBountyDialog.tsx
  • components/organization/bounties/new/NewBountyTab.tsx
  • components/organization/bounties/new/RegenerateBountySectionButton.tsx
  • components/organization/bounties/new/tabs/RewardTab.tsx
  • components/organization/bounties/new/tabs/ScopeTab.tsx
  • components/organization/bounties/new/tabs/SubmissionModelTab.tsx
  • components/organization/funding/FundingConfirmationModal.tsx
  • components/organization/funding/FundingProgressModal.tsx
  • components/organization/funding/types.ts
  • components/organization/hackathons/new/GenerateWithAiDialog.tsx
  • components/organization/hackathons/new/NewHackathonTab.tsx
  • components/organization/hackathons/new/RegenerateSectionButton.tsx
  • features/bounties/api/draft-ai-client.ts
  • features/bounties/api/escrow-client.ts
  • features/bounties/api/use-draft-ai.ts
  • features/bounties/index.ts
  • features/bounties/types.ts
  • features/hackathons/api/use-clarify.ts
  • features/hackathons/index.ts
  • features/hackathons/types.ts
  • hooks/use-ai-usage.ts
  • hooks/use-bounty-publish.ts
  • lib/ai/stream-draft.ts

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Walkthrough

Adds AI-assisted draft generation (streaming SSE, clarify gating, per-section regeneration) for both hackathons and bounties. Introduces a shared streaming client, six reusable AI UI components, bounty AI API hooks, and OTP-based escrow funding with treasury-wallet support. Generalizes funding modals to support entity-agnostic wording.

Changes

Organizer Assist AI Drafting + Bounty Funding Flow

Layer / File(s) Summary
Shared types and public feature exports
features/bounties/types.ts, features/bounties/index.ts, features/hackathons/types.ts, features/hackathons/index.ts, components/organization/funding/types.ts, hooks/use-ai-usage.ts
Introduces bounty AI provenance, clarification, section-regen, and OTP types; hackathon clarify interfaces; shared EscrowRunPhase/FundingMode union types; AiUsage interface; and re-exports through feature index files.
SSE streaming draft client
lib/ai/stream-draft.ts
Adds streamDraft with StreamDraftHandlers, parseFrame for double-newline SSE frames, backend origin resolution, abort handling, non-OK error extraction, and partial/done/error frame routing.
Shared AI UI components
components/ai/AiAssumptionsBanner.tsx, components/ai/AiBriefPanel.tsx, components/ai/AiClarifyQuestions.tsx, components/ai/AiExampleReference.tsx, components/ai/AiStreamPreview.tsx, components/ai/AiUsageNote.tsx
Adds dismissible assumptions banner, collapsible brief panel, chip-selection clarify step, past-entity example picker, streaming shimmer preview with cancel, and remaining-generation usage note.
AiRegenerateControl popover
components/ai/AiRegenerateControl.tsx
Adds a popover that runs an async onRun(instructions), handles no-changes and ApiError 503 via toasts, previews proposals via defaultSummary, and gates application behind explicit Discard/Apply actions.
Bounty and hackathon AI API clients and hooks
features/bounties/api/draft-ai-client.ts, features/bounties/api/escrow-client.ts, features/bounties/api/use-draft-ai.ts, features/hackathons/api/use-clarify.ts, hooks/use-ai-usage.ts
Adds generateBountyDraftFromBrief, clarifyBountyDraft, regenerateBountyDraftSection, OTP escrow functions (requestBountyFundingOtp, verifyBountyFundingOtp, resetBountyEscrowToDraft), corresponding React Query mutation hooks with cache seeding/invalidation, hackathon useClarifyDraft, and useAiUsage query.
Generalized funding modals and treasury publish hook
components/organization/funding/FundingConfirmationModal.tsx, components/organization/funding/FundingProgressModal.tsx, hooks/use-bounty-publish.ts
FundingConfirmationModal/FundingProgressModal accept entityNoun and onView replacing hardcoded "hackathon" strings. useBountyPublish gains treasurySource prop, derives usingTreasury/ownerAddress, conditionally includes sourceWalletId, skips USDC preflight for treasury, and adds resetBountyEscrowToDraft in the awaiting-funding resume branch.
Hackathon GenerateWithAiDialog streaming refactor
components/organization/hackathons/new/GenerateWithAiDialog.tsx
Replaces polling-based generation with abortable streamDraft, adds clarify gate via useClarifyDraftAiClarifyQuestions, AiExampleReference past-entity picker, AiUsageNote, AiStreamPreview during streaming, react-query cache seeding on done, and 503 "Start manually" toast.
New GenerateWithAiBountyDialog
components/organization/bounties/new/GenerateWithAiBountyDialog.tsx
Adds a complete bounty AI drafting dialog: Zod form (brief, budget, earliest start), curated BRIEF_TEMPLATES with TemplateChip, clarify gate via useClarifyBountyDraft, streaming via streamDraft with AiStreamPreview/cancel, draft cache write + list invalidation on done, and 503 error toast.
Per-section regenerate buttons and tab wiring
components/organization/hackathons/new/RegenerateSectionButton.tsx, components/organization/bounties/new/RegenerateBountySectionButton.tsx, components/organization/bounties/new/tabs/RewardTab.tsx, components/organization/bounties/new/tabs/ScopeTab.tsx, components/organization/bounties/new/tabs/SubmissionModelTab.tsx
Refactors hackathon RegenerateSectionButton to delegate UX to AiRegenerateControl. Adds bounty RegenerateBountySectionButton with the same pattern. Integrates into RewardTab (prize tiers + currency apply), ScopeTab (description apply), and SubmissionModelTab (mode-changed banner + multi-field apply with toDatetimeLocal).
NewBountyTab and NewHackathonTab orchestration
components/organization/bounties/new/NewBountyTab.tsx, components/organization/hackathons/new/NewHackathonTab.tsx
NewBountyTab: adds AI entry banner + GenerateWithAiBountyDialog, treasury/external funding-source selection, wallet balance query, OTP helpers, FundingConfirmationModal/FundingProgressModal wiring, and AiBriefPanel/AiAssumptionsBanner on the Review tab. NewHackathonTab: reads aiGeneration from draft, renders same AI panels with onReview routing, passes entityNoun/onView to funding modals.

Sequence Diagram(s)

sequenceDiagram
  participant Organizer
  participant GenerateDialog as GenerateWithAi(Bounty/Hackathon)Dialog
  participant useClarify as useClarifyDraft
  participant streamDraft
  participant Backend
  participant ReactQuery

  Organizer->>GenerateDialog: submit brief
  GenerateDialog->>useClarify: mutateAsync(brief)
  useClarify->>Backend: POST /draft/clarify
  Backend-->>useClarify: {ready, questions}
  alt not ready (questions present)
    GenerateDialog-->>Organizer: render AiClarifyQuestions
    Organizer->>GenerateDialog: submit answers (or skip)
  end
  GenerateDialog->>streamDraft: POST /draft/from-brief/stream (augmented brief)
  loop SSE frames
    Backend-->>streamDraft: partial frame → suggestion
    streamDraft-->>GenerateDialog: onPartial → AiStreamPreview updates
  end
  Backend-->>streamDraft: done frame {draftId, draft}
  streamDraft-->>GenerateDialog: onDone
  GenerateDialog->>ReactQuery: setQueryData(draft) + invalidate drafts list
  GenerateDialog-->>Organizer: toast + navigate to draft page
Loading
sequenceDiagram
  participant Organizer
  participant NewBountyTab
  participant FundingConfirmationModal
  participant useBountyPublish
  participant Backend
  participant FundingProgressModal

  Organizer->>NewBountyTab: select funding source (treasury vs external)
  NewBountyTab->>FundingConfirmationModal: open (entityNoun='bounty', source, balance)
  Organizer->>FundingConfirmationModal: confirm + OTP verify
  FundingConfirmationModal->>useBountyPublish: runFunding()
  useBountyPublish->>Backend: POST escrow (sourceWalletId when treasury)
  Backend-->>useBountyPublish: escrowPhase updates
  useBountyPublish-->>FundingProgressModal: phase=completed
  FundingProgressModal-->>Organizer: "View bounty" button
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Suggested reviewers

  • Benjtalkshow

Poem

🐇✨ A brief typed with care,
The AI streams drafts through the air,
Clarify questions chip by chip,
Treasury wallets fund the trip,
Each section regenerates just right —
The rabbit ships features overnight! 🚀

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/t-replace

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Integrate main (#663 bounty UI + data layers, DTCC blog post, dependency
bumps) with the Organizer Assist (AI drafting), shared funding modal, and
bounty reset-to-draft work on this branch.

Resolution notes:
- Bounty/hackathon wizard files (NewBountyTab, NewHackathonTab, ScopeTab,
  RewardTab, SubmissionModelTab, GenerateWithAiDialog, RegenerateSectionButton):
  kept this branch's versions, which evolve the same code #663 touched —
  AI drafting, streaming reveal, clarify gate, example reference, the shared
  funding-source picker (treasury + external), and OTP step-up.
- use-bounty-publish: kept treasury funding + reset-to-draft recovery and
  dropped applicationCreditCost (no longer on PublishBountyEscrowDto per the
  regenerated schema).
- Funding modals: removed the duplicate copies #663 left under
  hackathons/new/; the canonical shared copies live in organization/funding/.
- schema.d.ts: regenerated via npm run codegen against the live backend.
- package-lock.json: reconciled against the merged package.json.

Verified: tsc --noEmit and eslint both pass on the merged tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@0xdevcollins 0xdevcollins merged commit 7f6857a into main Jun 30, 2026
3 of 10 checks passed
0xdevcollins added a commit that referenced this pull request Jun 30, 2026
Reconcile production (#664 hackathon track-based prizes + UI updates) with
main. main already contains #664's substance (track-based prizes landed via
the prize overhaul) plus the AI drafting, shared funding modal, treasury, and
bounty reset-to-draft work, so the merge is a content no-op against main.

Conflicts resolved by keeping main's versions (the AI/funding/treasury files
that supersede production's pre-#665 base); removed the duplicate funding
modals production carried under hackathons/new/ (canonical copies live in
organization/funding/); kept main's generated schema.d.ts.

Verified: tsc --noEmit and eslint both pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants