Skip to content

Instantly share code, notes, and snippets.

@danielhe4rt
Last active June 15, 2026 22:03
Show Gist options
  • Select an option

  • Save danielhe4rt/02215787417fe3d5bdc82b90785cd7cf to your computer and use it in GitHub Desktop.

Select an option

Save danielhe4rt/02215787417fe3d5bdc82b90785cd7cf to your computer and use it in GitHub Desktop.

Community Context

Domain core for community-facing rituals: meetings, feedback, and the Retrospective — a publishable recap of what the community did over a period, aggregated across multiple platforms.

This module also houses the older Meeting and Feedback sub-domains (not yet glossed here).

Language

Retrospective

Retrospective: A persisted, publishable recap of one tenant's activity over a fixed calendar period, assembled from one or more Sources. Avoid: Recap, report, summary, edition (use "Retrospective").

Cadence: The kind of period a Retrospective covers — Weekly, Monthly, or Annual. Weeks are ISO (Monday–Sunday); months and years are civil calendar buckets. Avoid: Type, frequency, interval.

Period: The concrete date range a Retrospective covers, computed from its Cadence + an anchor date (never free-form since/until in the normal flow). Avoid: Range, window.

Source: A pluggable provider (Strategy) that, given a tenant + Period, returns a SourceResult for one platform — GitHub, Discord, or Twitch: a HeadlineMetrics envelope plus an ordered list of Slides (its mini-deck). The contract lives here in community; each implementation lives in the module that owns the data. Avoid: Provider (in code the contract is RetrospectiveSource), integration, channel, feed.

Slide: The unit a Source emits — one renderable panel of the Compiled deck, identified by a kind (e.g. github.repos, discord.voice_board) that the portal maps to a Blade component. Slides carry data only, never markup. Avoid: Section, panel, card.

Compiled deck: The single public deck (portal's community-retrospective.blade.php) assembled as: shared cover (with cross-source unified totals) → each enabled Source's Slides as a contiguous block, in configured order → shared closing. Avoid: Presentation, slideshow.

Exclusion: A per-Source blocklist of refs (pr:142, actor:login) the operator hand-hides so they never render in any of that source's Slides. The surgical counterpart to the automatic hideBots filter; collect() strips them deck-wide. Covers both items and people. Avoid: Curation, blacklist (use "exclusion"), promotion (there is no manual promotion — auto-selection stands, operators only hide).

Publish lifecycle: A Retrospective moves from draft (editable by Marketing/Admin) to published (publicly visible in the portal). Operators control when it goes public. Avoid: Status, state (those are column names, not the concept).

Relationships

  • A Retrospective has exactly one Cadence and one computed Period.
  • A Retrospective enables one or more Sources; each Source contributes a HeadlineMetrics envelope and an ordered block of Slides for that Period.
  • The Compiled deck concatenates the enabled Sources as provider blocks (all of GitHub's slides, then all of Discord's, etc.) between a shared cover and closing. The cover shows cross-source totals; people are counted per Source (no cross-platform identity dedup in the MVP).
  • Sources are resolved by key as tagged services; adding a platform adds a Source in its owning module, not in the portal.
  • Operators (Marketing/Admin) edit a Retrospective in panel-admin through a 3-column Deck Builder (structure timeline · live preview · contextual inspector), not a stacked form — see app-modules/panel-admin/docs/adr/0001-retrospective-admin-deck-builder.md. The portal renders the published one and shares the deck preview's render path.

Dependency note

community is a domain module — it never imports from Integration modules. The Source contract lives here so Integration modules (integration-github, integration-twitch) and the activity domain module can implement it (Integration→Domain is allowed). The cross-source orchestration + rendering live in portal (presentation imports everything). See docs/adr/ for the ADR behind this split.

Example dialogue

Dev: "For a Weekly Retrospective anchored on June 2nd, what's the Period?" Domain expert: "ISO week, Monday to Sunday — May 26th to June 1st. The Cadence decides it; the operator never types dates." Dev: "And if Discord has no data that week?" Domain expert: "The Discord Source returns empty metrics; the slide just doesn't render. The Retrospective still publishes with whatever Sources have data."

Flagged ambiguities

  • "Type" was used for the weekly/monthly/annual kind — resolved to Cadence (avoids clashing with ContributionType in integration-github).
  • "Provider" overloaded with OAuth Provider model in identity — in code the retrospective contract is named RetrospectiveSource; the glossary term is Source.

Retrospective admin is a 3-column Deck Builder, not a stacked form or wizard

For editing a multi-source Retrospective in panel-admin, we prototyped five interaction models and chose a 3-column Deck Builder: a left structure timeline (the cover node, draggable source blocks each holding draggable slide chips, and the closing node), a center live-rendered deck preview, and a right contextual inspector whose contents change with the selected node. We picked it because composing a multi-source deck benefits from direct manipulation (drag to reorder blocks/slides) with an immediate preview, and a single contextual inspector keeps every editable "variable" in one place instead of scattered knobs.

The inspector has four modes, driven by selection:

  • Deck (top "Edição / Capa" node) — global config: cadence + anchor → computed period, draft/publish state, cover title/intro, global toggles (e.g. hide bots), read-only summary. Global config lives here, not in a separate top bar.
  • Block / Source — on/off, block position, read-only headline (what it adds to the cover totals), optional block opening text, slide overview, and a consolidated Exclusion list to review/restore.
  • Slide — include on/off, title override, position, and for curatable slides: max items, sort, and the Exclusion list (hide where you see it — applies deck-wide for that source per ADR community-0001 / decision Q6).
  • Closing — the closing message.

Considered options

We prototyped all five (throwaway artifacts under /tmp/proto-*.html, indexed by /tmp/proto-index.html):

  • Minimal stacked form (simples) — single Filament form, checkboxes, no preview/drag. Rejected as the primary editor: too flat for composing/curating a multi-source deck, no sense of the result.
  • Wizard (média) — linear 5-step guided flow. Not chosen as the editor, but kept as a candidate for the creation path (a future hybrid: wizard to create, builder to edit).
  • Kanban board (complexa) — sources as columns, slides as cards, an "Ocultos" lane. Rejected: spatial but weaker at showing the actual published result.
  • WYSIWYG edit-on-deck (radical) — edit directly on the rendered deck. Compelling but higher build risk; revisit later.
  • Deck Builder (complexa) — chosen.

Consequences

  • This is not a vanilla Filament resource form. The edit page needs a custom Livewire + Alpine 3-pane UI (draggable timeline, live preview render, contextual inspector). The list page (ListRetrospectives) and manual creation can stay closer to standard Filament.
  • The admin preview and the public deck should share one render path so "ver rascunho" matches what's published.
  • Exclusions surface in the Slide inspector but are stored per-source and applied deck-wide (consistent with community ADR-0001 and the exclusion model).
  • Prototype that captured this decision: /tmp/proto-3-builder.html (throwaway — delete or absorb once the real page exists).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment