Skip to content

feat(marketer): campaign/content draft-approve-schedule-publish loop (#3148/#3149) - #4016

Open
kevinthelago wants to merge 2 commits into
developfrom
marketer
Open

feat(marketer): campaign/content draft-approve-schedule-publish loop (#3148/#3149)#4016
kevinthelago wants to merge 2 commits into
developfrom
marketer

Conversation

@kevinthelago

Copy link
Copy Markdown
Owner

Summary

The frontend slice of the Marketer epic's remaining phases (#3145 P3/P4), scoped to src/features/marketer/** per the marketer stream's fleet assignment.

  • Domain model + state machine (lib/campaign.ts) — Campaign/ContentItem, the draft → approved → {scheduled, published} transitions (Marketer P3 — campaign/content store + draft→approve→publish loop #3148: publish is never reachable directly from draft), dueForDispatch for scheduled items whose fire time has passed.
  • Compliance guardrails (lib/compliance.ts, Marketer P5 — persona rewrite + skills + docs + compliance guardrails #3150) — email requires an unsubscribe link + sender identity (CAN-SPAM/GDPR); social enforces a channel length limit; all content is checked for PII-shaped strings. A content item with any violation cannot reach approved (enforced in store.ts's approveContentItem).
  • Channel status view (lib/channels.ts, Marketer P1 — first channel MCP server + keychain-backed secret env #3146) — derives a channel list from the mcp feature's installed-server catalog (consumed only via its public barrel, @/features/mcp), tagging installed/assigned state.
  • Analytics read-back (lib/metrics.ts, Marketer P4 — analytics read-back + iterate #3149) — rollup + per-channel readout formatting, mirroring crates/channel's get_metrics shape ({ total, by_tool }).
  • Contract-first backend bridge (lib/api.ts) — marketing_* Tauri command calls with graceful degrade (the same pattern sourceConnection.ts uses for data_platform_scan): the UI works standalone today and will pick up the real backend the moment crates/marketing + its Tauri commands land, with no code change.
  • Store (store.ts) — a standalone Zustand store (persisted via the same persistStorage adapter the composed app store uses, under its own "bsc-marketer" key). Not folded into useAppStore — that needs a two-line edit to src/store/index.ts + src/store/types.ts, both outside this feature's write scope. Noted as a follow-up integration step.
  • UI (MarketerWorkspace.tsx, ContentDrawer.tsx, MarketerStatus.tsx) — Campaigns/Channels/Analytics tabs, the compose→approve→schedule→publish drawer, and a compact status widget. Not yet mounted to a rail Workspace or Settings page (a director-owned integration step); exported from the feature's index.ts barrel, ready for it.

Notes on scope

  • #3146's remaining acceptance criteria (keychain-backed secret env, the Settings "connect a channel" UI) are deliberately deferred per the issue's own comment thread — the owner noted both land when the real beautiful-emails channel needs credentials, not for the mock channel.
  • #3147 (outbound confirm gate + role tier) and the rest of #3150 (persona/skills/docs) touch src/shared/lib/session/** and src-tauri/data/personas/** — outside this feature's write scope; left to whichever stream owns those paths.
  • #3800 (Glance marketing tab + standing maintainer session) is explicitly filed-not-scheduled in the epic.

Test plan

  • npm run typecheck — clean
  • npm run lint — 0 errors in src/features/marketer/** (0 new warnings)
  • npx vitest run src/features/marketer — 48/48 passing (pure lib tests, store tests, component tests)
  • npm test (full suite) — 6076/6078 passing; the 2 failures are pre-existing, unrelated src/features/designs/lib/reactUiKit.gen.test.ts CRLF hash-sidecar failures (untouched by this PR)

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01WDc7B2fkQxzAjhZPRfTRQ7

kevinthelago and others added 2 commits July 30, 2026 13:51
…3148/#3149)

Adds the Marketer feature's frontend: a pure domain model + state machine for
campaigns/content items (draft -> approved -> scheduled -> published, #3148),
compliance guardrails that block approval on noncompliant content (missing
unsubscribe/sender identity, PII, over-length social posts, #3150), a
channel-status view over the mcp feature's server catalog (#3146), an
analytics read-back with graceful degrade when the backend isn't wired yet
(#3149), and the workspace UI tying it together. Not yet mounted to a rail
Workspace/Settings page or folded into the composed app store -- both are
narrow follow-up integration steps outside this feature's write scope.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WDc7B2fkQxzAjhZPRfTRQ7
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