Skip to content

fix(leads): load every campaign field into the edit form, and select it - #134

Merged
ralyodio merged 1 commit into
masterfrom
fix/campaign-edit-fields
Jul 28, 2026
Merged

ralyodio merged 1 commit into
masterfrom
fix/campaign-edit-fields

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Reported: sender name, reply-to and angle come up blank when editing a campaign.

They weren't just missing from the form. save() submits the whole form state, so saving an edit wrote those blanks back and wiped the columns.

The bigger one underneath

The page casts campaign rows with as CampaignSummary — which tells TypeScript the shape without checking the query asked for it. The .select() had never been widened past its original nine columns, so everything added since #130/#132 read as undefined at runtime with no compile error:

  • c.id undefined → run history couldn't be keyed, so every campaign showed an empty history
  • auth_required_hosts undefined → the waiting_for_auth badge never appeared
  • pitch_mode / pitch_intro / pitch_ask / pitch_facts undefined → the edit form got no pitch fields

All of it compiled. All of it was broken. The run history and waiting badge shipped in #132 have never actually worked.

Third bug in the same path

save() hardcoded autoSend: false, active: true. Correct for a new campaign — it should start paused-for-sending so the first drafts get read — but on an edit it switched sending off and un-paused a campaign the user had deliberately paused. It now carries the existing values through.

Regression guard

A source-level test asserting the select requests every column the page and panel go on to read. Source-level checks are unusual, but the type system has been explicitly told to look away here, so nothing else catches it.

Verified it actually bites: stashing the fix fails it in 11 places.

Checks

  • tsc --noEmit clean
  • 748/748 tests pass, 20 new
  • production build compiles

🤖 Generated with Claude Code

Editing a campaign left the sender name, reply-to and angle blank. They
were not merely missing from the form: save() submits the whole form, so
saving an edit wrote those blanks back and wiped the columns.

Underneath was a worse one. The page casts its campaign rows with `as
CampaignSummary`, which tells TypeScript the shape without checking that
the query asked for it, and the select had never been widened past the
original nine columns. Everything added since read as undefined at
runtime with no compile error — so the run history could not be keyed
(campaign id was undefined), the waiting_for_auth badge never appeared,
and the edit form got no pitch fields. All of it compiled, and all of it
was broken.

save() also hardcoded autoSend false and active true. That is right for
a new campaign, which should start paused-for-sending so its first
drafts get read, but on an edit it switched sending off and un-paused a
campaign the user had deliberately paused. It now carries the existing
values through.

The regression guard is a source-level test asserting the select
requests every column the page and panel go on to read. Source-level
checks are unusual, but the type system has been explicitly told to look
away here, so nothing else would catch it. Reverting the fix fails it in
eleven places.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit 177a2e0 into master Jul 28, 2026
8 checks passed
@ralyodio
ralyodio deleted the fix/campaign-edit-fields branch July 28, 2026 02:58
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