Skip to content

v4.30 — Editorial Community Curation

Communities discovery gets a human hand: an admin can now place a community into a named rail without a deploy, and is_featured — a badge nobody could ever set — finally has a write path.

Summary

Discovery on the Communities tab was entirely algorithmic — community_suggestions, trending_communities, recommended_communities — and nobody, including Josh, could place a community anywhere without shipping code. v4.30 adds an admin-gated editorial slot system: three named rails (active_now, just_started, most_members) with ordinal position within each, an admin screen at /communities/curation to assign them, and the consumer rails that render them on the Communities tab, behind PostHog flag editorial-discovery (registered, deliberately not promoted). It also closes a live, unrelated defect it found along the way: CommunityCardV2.vue had been rendering an is_featured "Featured" badge with no mutation, admin UI, or service anywhere in the codebase able to set it — Phase 2's screen is that flag's first-ever write path.

The work is a salvage, not a greenfield build. Phase 79 of the abandoned gsd/v1.18-pre-launch-readiness branch built almost exactly this and never shipped — the branch was abandoned as a whole, but this slice was only partially superseded when master took the algorithmic half. What was preserved — a migration, a validated model constant, a complete interaction, a mutation, an admin view, two Vue components, a composable, and six spec files — was a strong starting point but not a drop-in: six distinct ways the preserved code had drifted out of sync with master were found and designed around across kickoff and all three phases, the highest-severity one being a preserved diff that would have silently deleted master's live recommended_communities resolver as part of unrelated, out-of-scope work.

The milestone shipped clean on every phase, but not without two of its own planning gaps (not preserved-code drift) surfacing mid-flight: Phase 2 was originally scoped without a backend write path for is_featured even though keeping that flag (Josh's kickoff call) made a write path load-bearing for Phase 2's own acceptance criteria, and Phase 1's admin resolver filtered out exactly the sub-threshold rows Phase 2's own warning criterion needed to see. Both were caught and closed before shipping. So was the milestone's own closing sequencing: an initial dispatch would have written the shipped-narrative before the integration branch was promoted to master — the exact stranded-branch failure this milestone's own source material suffered — caught by the close ritual's own gate before anything was written.

Goal

Give Objectuve a human hand on the Communities discovery surface. Today discovery is entirely algorithmic — community_suggestions, trending_communities, recommended_communities — and nobody, including Josh, can place a community anywhere without a deploy. This milestone ships an admin-gated editorial slot system (three named rails, ordinal position within each), an admin screen to assign slots, and the consumer rails that render them, behind a flag.

Scope — What Shipped

  • Data model. communities gained editorial_slot, editorial_position, editorial_updated_at (nullable, indexed, additive migration — no backfill, reverses cleanly). Community::EDITORIAL_SLOTS fixes the three valid slot names; editorial_slot validates against it with nil permitted.
  • Admin write path. Admin::SetCommunityEditorialSlot — admin-gated, wraps the write in Admin::Logged for a full audit trail, evicts the prior occupant of an assigned slot+position inside a transaction, and clears all three columns on slot: nil. Admin::SetCommunityFeatured mirrors the same shape for is_featured, kept deliberately independent (Option A) rather than folded into the slot mutation.
  • Admin curation screen. CommunityCurationView.vue at /communities/curation, reachable from the admin sidebar and role-gated to super_admin/admin. Per-row staged edit → save with unsaved/saving/saved/error states, an inline warning on sub-threshold rows holding a slot, eviction feedback naming both communities, and the is_featured toggle.
  • Consumer discovery rails. EditorialCarousel.vue (three editorial rails) and FoundingMemberOpportunitiesSection.vue (an algorithmic "founding spots open" rail, 0–4 members) render on the Communities tab behind editorial-discovery. Flag off renders Communities.vue byte-identical to before this milestone, asserted in a test — that assertion is the rollback guarantee.
  • curatable_communities admin query, widened mid-milestone to include any community already holding a slot even below the 5-member discoverability floor, closing an orphan hole where a slotted community that dropped below the floor would otherwise become invisible and unclearable at the same time.
  • Docs, across the admin guide, feature inventory, communities deep-dive, feature-flags registry, and CHANGELOG — every claim traceable to a named source file.
  • What did not ship: a "See all →" destination for either rail (both preserved components emit the event; no target route exists — deliberately deferred to a follow-up rather than shipping a dead control).

Phases

PhaseNameStatusPlansHighlights
1Editorial data model, admin write path, read queriesShipped2Migration, model, SetCommunityEditorialSlot, editorialCommunities/formingCommunities/curatableCommunities resolvers; existing recommendation specs passed unmodified, proving the port stayed additive (PR #2130, a19caae8b)
2Admin curation screenShipped2CommunityCurationView.vue + sidebar entry + Admin::SetCommunityFeatured (scope expanded mid-milestone, Josh's Option A) + orphan-slot resolver fix (PR #2159, 5811bbaa0)
3Consumer editorial discovery surfaceShipped2Four rails on the Communities tab behind editorial-discovery, flag-off byte-identical guarantee, useFeatureFlag-based composable, docs (PR #2143, 6d38eddb0) — executed ahead of Phase 2 while Phase 2 was held on a scope decision

Key Decisions

  • is_featured stays orthogonal to editorial_slot, not consolidated. Josh's kickoff call: is_featured is a per-card badge, editorial_slot is rail placement — different concepts, no migration to merge them. Phase 2's screen becomes is_featured's first write path via its own mutation, Admin::SetCommunityFeatured, rather than folding it into SetCommunityEditorialSlot.
  • "Founding spots open" is in scope, algorithmic, not editorial. FoundingMemberOpportunitiesSection computes from member count alone (0–4, newest first, excluding the caller's own communities) — no admin assignment needed. Included because the source issue named it explicitly; also the cleanest thing to cut if the milestone had needed trimming.
  • "See all →" omitted in v1. Both preserved components emit a see-all event with no destination — the shelved branch never built the target route. Shipping a dead control was rejected; a real "all editorial communities" page is a follow-up issue, not this milestone.
  • The preserved branch's community_queries.rb diff was ported additively, not wholesale. The shelved branch had removed recommended_communities as part of an unrelated, out-of-scope ally-gating rework. Porting the diff as-is would have silently deleted a live master surface; Phase 1 ported only editorial_communities/forming_communities and Roy independently verified recommended_communities/community_suggestions/trending_communities stayed byte-identical to base.
  • Milestone close held on master containment, not just phase completion. The integration branch sat unpromoted for roughly two hours after all three phases shipped. A close dispatch that would have written the shipped-narrative first was caught and corrected before any doc landed — the promotion (a separate, hand-created issue, per this repo's own documented stranded-branch pattern) ran to completion first.

Requirements Coverage

14 / 14 requirements satisfied — no standalone REQUIREMENTS.md; the milestone's own ROADMAP requirements table is the traceability surface, independently re-verified against live master source in the MILESTONE-AUDIT.md.

CategoryCountStatus
DATA-1–33All satisfied
ADMIN-1–77All satisfied
DISCOVER-1–33All satisfied
DOCS-11Satisfied (closed a mid-flight docs-inversion window before promotion — see Tech Debt)

Outcomes

  • An admin can place a community into a named discovery rail — or clear one — from /communities/curation, without a deploy.
  • is_featured finally has a write path; the badge CommunityCardV2.vue had rendered for an unknown span of time is no longer a dead flag.
  • The Communities tab renders four new rails when editorial-discovery is enabled for a user, and is byte-identical to before this milestone when it isn't — flipping the flag off in PostHog is a full, instant rollback with no deploy.
  • A community that drops below the 5-member discoverability floor after being slotted stays visible and clearable in the admin list rather than becoming an invisible, unclearable orphan.
  • master's existing algorithmic recommendation surface (recommended_communities, community_suggestions, trending_communities) is provably untouched.

Tech Debt

  • (Process, cross-milestone pattern) A phase's own docs sub-task, deferred to run after the phase's code merges, is the task most likely to be silently dropped by a stage-rollup signal. This milestone's Phase 2 docs task (OBJ-2239) landed after Phase 2's code merged; in the window between, the shipped docs briefly asserted the curation screen didn't exist. Caught and closed before promotion — no live drift on master — but this is the second time this repo has seen this exact shape. No mechanical guard exists yet.
  • (Evidence gap, disclosed at review time) No light+dark screenshot evidence exists for PR #2159 (Phase 2). admin_dashboard/ had no PR-time evidence-capture path when the PR opened; the infra fix landed on master afterward, too late for this branch. Reviewer substituted source/token-level UI-SPEC verification instead. Recorded as a disclosed gap, not a clean pass.
  • (Scope, deliberate) "See all →" has no destination route for either editorial rail — correctly scoped out at kickoff. A future "all editorial communities" page is a follow-up issue.
  • a19caae8b — Phase 1: editorial data model, admin write path, read queries (PR #2130)
  • 6d38eddb0 — Phase 3: consumer editorial discovery surface (PR #2143)
  • 5811bbaa0 — Phase 2: admin curation screen + is_featured write path (PR #2159)
  • 28b35f7de — Merge v4.30 editorial community curation to master (PR #2170)

Last updated: 2026-08-07

Loading…