Awards exceed the 10,000,000 cap once campaign and streak multipliers apply
Award grants (showcase approval, admin award points) skip campaign/streak multipliers
Disable the inbox notification email ("You have received a notification in Swamp Club")
Add LinkedIn as a login provider
Showcase reward backfill can double-pay 5,000,000 points when replicas start together
Showcase editor: caption counter is not announced to screen readers
Profile showcase read: approved list sorts on review.reviewedAt in memory
Showcase countByStatus: $match live statuses before the $group
Showcase admin queues: index-serve the updatedAt sort on approved/rejected
Block temporary email services on signup
auth login leaves auth.json apiKey empty and stores the key only in ~/.config/swamp/api-key, which the auth gate never reads
swamp-club.com serves every response uncompressed
CLI companion to #3396: private-source collectives can score repository-verified 14/14 in extension quality
Replayable state fragments: Git-reviewable desired state for resources changed by model methods
Use whoami entitlement to explain private-extension push refusals
Top-level swamp init never earns repo-init quest or tier credit
Docs: telemetry reference — the envelope we send and our redaction policy
Telemetry opt-out scope: one user-level setting that disables telemetry everywhere
Telemetry: mark paths where errors are built so redaction needs no guessing
Combat log: batch the extension visibility lookup into one query
CLI telemetry redaction: user values still transmitted (errorMessage, workflowContext, init path, history args, private types) while command words are over-redacted
Maximum call stack size exceeded once a resource passes ~129k versions (Math.max(...versions) in the data repository)
worker connect --ca-cert is not applied to the data plane; dispatches fail with 'fetch failed' unless DENO_CERT is set
Ephemeral worker fleets accumulate worker records and token bindings that are never reaped
Expired enrollment token cannot be re-minted unless a worker was connected when it expired
Billing telemetry: surface scheduled cancellations (cancelAtPeriodEnd) and emit subscription_canceled reliably
access token mint: support --server so worker server tokens can be minted remotely
Workload identity (Kubernetes ServiceAccount / OIDC) for worker enrollment
Feed grant projection stamps a site route that does not exist
Retire or rebuild /admin/nurture once the epic lands — it is a gate, and gates are single-use
feat(nurture): /admin/nurture — who would get what, and why
feat(nurture): the nurture_send ledger and the dry-run projector, with the cold-start seal
feat(nurture): batch cohort reads — account-grain identification that carries its evidence
feat(nurture): the flow catalog and the qualification contract (pure domain)
harness-marketing-funnel posts {batch:[...]} to /ingest, which is not a batch — every run silently measures zero
feat(cli): swamp inbox — read swamp-club notifications without leaving the terminal
feat(cli): tell operatives they have swamp-club notifications waiting
feat(api): a cheap unread-notification count for API-key clients
feat(nurture): deliver to the swamp-club inbox on the same dedupe decision as email
feat(nurture): arm needs-help-after-a-failed-run (NEEDS HELP)
feat(nurture): arm model-usage-without-workflows (BUILDING PRODUCT FEATURES)
feat(nurture): arm no-activation-after-30-days (ARRIVED, NEVER RAN)
feat(nurture): arm reactivation-after-7-days (DRIFTED)
feat(nurture): arm the first flow — extension published, email only, verified in prod
feat(nurture): the six nurture email templates, previewed before anything sends
feat(nurture): an outbound transport that reports its outcome, and per-channel send status
feat(nurture): suppression — opt-out, address-grain frequency caps, one-click unsubscribe
Epic: Product nurture — lifecycle identification, dedupe-safe delivery, and operator control (email, inbox, CLI)
SSO: SAML assertion attributes are never logged or persisted — cannot tell whether the IdP sent groups
IdP group memberships go stale indefinitely — user.idpGroups is only written by the SSO login hook
Extension version binaries never persisted — binaries security notice has never rendered
Genesis "New Blood" (recruit_first) only counts collective invites — a platform invite can never complete it
SCIM 2.0 provisioning endpoint for swamp-club (Users + Groups, deprovision)
SSO user profile fields are frozen at first login — overrideUserInfo is never set on any provider
@swamp/s3-datastore disables IMDS on plain EC2, so an attached instance profile cannot resolve
AWS credential handling is duplicated across five implementations — the #803 preflight and the #226/#228 SSO hints reached only one of them
A subscription stuck in incomplete has no path forward: it grants nothing, and the billing page offers no way to finish paying
Identifier lookups are exact-match and case-sensitive across username, email and slug
Invite failures emit no telemetry, so a rejected invitation leaves no trace anywhere
Collective invitations expire after 48h and the auto-claim is gated on that window, so a late signup is never bound
Invite typeahead searches username prefix only, so an operative cannot be found by name or email
Send the release headline from the release pipeline so New Release announcements say what shipped
Epic: /leaderboard and /u/{username} do not survive 10B events — measured audit + phased plan
Reconcile collective-token CLI activity to members (attribute → bonus → stamp → even-split)
deps-audit skips deno-runner and agent-runner lockfiles in ci.yml
Sync every signup to Attio, and backfill the existing population (#809 follow-up)
@swamp/issue-lifecycle probes /api/health, which swamp-club stopped serving when the Fresh scaffold stubs were removed
Lab lifecycle POST rejects any payload string that starts with a dollar sign, not just operator keys
Push down the two cheap leaderboard scans: ghost-gate dictionary and eventCounts owner filter
$identify events are never consumed — anonymous web history never binds to the account
Finish the swamp_* attribute set on Attio users, and settle the two unprefixed ones (#809 follow-up)
aria-expanded is a raw boolean in 12 places — collapsed state is unannounced to screen readers
One standing read: every scalar score consumer reads board_totals, not the ledger
Profile Edit trigger is a fire-and-forget island: no aria-expanded, and a silent no-op if the editor island does not hydrate
Profile XP bar jumps ~25px on fill, and pays the full cumulative walk for two numbers board_totals already holds
Incremental activity projector + swamp.events username bloom index (spun off #925, stages 5+7)
Telemetry stats consumer: insert_id dedup commits before the write it guards — any upsert failure is silently swallowed on retry
score-rollup projector runs N× per cadence — the run gate is per-replica memory, not shared state
Leaderboard board windows re-anchor on wall-clock while the rest of the view is frozen at asOf
swamp CLI: surface the audience and resolvedInVersion fields swamp-club now serves
ApiKeyManager's collapsed trigger points aria-controls at an element it never renders
A boolean aria-expanded renders as no aria-expanded: two disclosure widgets report no state to a screen reader
Ripple redaction rewrites HTTP status-code runs as phone numbers, silently corrupting evidence
Profile score section blocks the render on a ClickHouse read
Collective invite emailed-link return path is dropped: /accept-invite sends ?returnUrl= but /login reads ?redirect=
Tell the inviter when a collective invite mis-lands, instead of leaving it pending forever
Ghost profile bypasses the score-read seam and 500s on a slow ledger
A ledger read failure still renders as 'no activity': loadProfileScore swallows to an empty standing behind HTTP 200
Model lookup misreports EMFILE (too many open files) as a broken definition file and dumps a raw stacktrace
serve telemetry identity warnings are diagnostic but not actionable — say how to fix them
swamp quest: drop the heartbeat field the server no longer sends
Daemon telemetry flush: stop() can skip its final flush when a timer drain is already in flight
Guard the projector's full rewrites against the fail-open lease (ADV-6 from #1575/#1576)
Projector write amplification: board_totals/owner_devices full rewrites are owners × runs/day
Profile candidateIds prune costs a full ledger scan to build itself — 42.88M rows for one keyed read
Leaderboard phase 3: owner-grain board_totals so a cache miss is survivable at 10B
swamp serve is telemetry-dark: scheduled workflow runs never reach /ingest, and the daemon never flushes
CLI has never sent insert_id: retried telemetry batches are double-counted into cli_daily, inflating XP in an append-only ledger
Catalog backfill reconciles against the local cache, not the datastore
dailyHistory range pushdown — deferred from #1576, and the measurement says why
Docs: manual never mentions telemetry, and the serve/scheduling pages imply automated runs are visible when they are not
Leaderboard phase 2: take score_grants off the board read path — read today from score_daily
Profile day drill-down returns 0 entries at the 5s ClickHouse ceiling for every operative
reconcile_from_disk_bench.ts fails deno check (stale DenoRuntime stub)
Leaderboard phase 1: cache the board read and bust it on tier crossings (no schema change)
Catalog backfill deletes rows for any model whose data names are numeric
Docs: document catalog completeness check and --repair in doctor reference
Leaderboard phase 5: score-rollup-projector write cost at 10B — ~430M rows scanned per 60s tick
swamp auth whoami should report paid tier and trial status
Split the score-read circuit breaker so leaderboard pressure can't blank profile scores
oauth_sign_in telemetry records provider as the literal ":id" for every event
Council: set the scoring balance — command tiers, farm-decay parameters, cross-category ratio
Scoring coverage gaps: instrument drop-off, score ripples/mentions, reward invite-converts
Materialize an active-days-by-id table for the streak board
score-rollup-projector: O(all-time ledger) closure + per-pod fan-out saturates prod ClickHouse CPU
swamp auth server-login ignores SWAMP_SERVE_URL
serve oauth: an unrecognized device-token error kills the whole serve process instead of the bootstrap
CLI reports 'HTTP/2 not supported by this client' when the server actually returned 401 — masks auth failures as a transport error
serve oauth: startDeviceGrant discards the OAuth error field, making device-code failures undiagnosable
serve oauth bootstrap: device flow rate-limited to a 45-second window by validateClient counter, shared globally across tenants
CLI: swamp invite <email> to drive the platform-invite API
Hide enterprise (SSO) operatives from announcements and leaderboard by default
Expose the swamp.club feed as an RSS feed
Docs: manual should state workflow unknown keys are rejected and placement is step-only (follow-up to #1240)
ExtensionInfo.latestVersion typed 'string' but registry returns null; harden pull/resolve for prerelease-only extensions
Profile stats: per-user daily rollup table + MV in ClickHouse
CLI telemetry: fold third-level verbs into subcommand + canonicalize aliases
Docs: swamp skill repo-structure reference still documents repo-local .swamp/telemetry/ as live
Docs: document user-global telemetry (telemetry.yaml opt-out, spool location, telemetry stats behavior)
score_daily rollup strands stale grains when a day-less grant re-stamps onto a later day
swamp-club: global rate limiter runs pre-auth and collapses all direct clients into one per-IP bucket — 429s authenticated CLI traffic
feed_post_score_events queue grows unboundedly (no TTL, no delete-on-delivery)
@-mention autocomplete for users when writing lab ripples
Remove comments from /feed and redesign the page
Score-refresh consumer: harden coalescing against a diverse backlog (bistability)
Remove feed comments — consolidate discussion in Discord
Relax the profanity filter
Extension search returns edit-distance noise for short queries ("asdl" → "AWS DEADLINE")
Telemetry recoverOrphaned startup race with multiple replicas (created_at-based)
Telemetry retry/failed path has the same non-atomic claim as #820
Dead code: CollectivesSection island (pending-invite prompt) is never mounted; listPendingInvitationsByEmail has no production consumer
Telemetry silently dropped outside a swamp repo — lost events + undercounted scores
serve: create*Deps() factories leak file-based catalog stores (3 FDs) per API request
flaky test: manual_approval suspension test leaks 3 timers (OTel InMemorySpanExporter setTimeout)
flaky test: serve OAuth client tests leak unconsumed fetch response bodies (+ connection_test readDir leak)
serve leaks file descriptors (EMFILE) — runFileSink.unregister runs after yield, not in finally
swamp-club: /api/whoami 500s on fresh install — ensureIndexes {id:1} conflicts with migration 012 id_lookup index
data prune --json omits reclaimedModels[].modelName when a report entry is grouped first
One-time prod data checks: github:-authored lab issues blast radius + legacy uppercase extension names
Serve leaderboard locate ('find yourself') live, retiring its per-replica standings cache
Serve leaderboard live from the score_daily rollup — retire per-pod snapshot & campaign-blind board fallback
Docs: document swamp data prune (orphaned-data reclamation)
UAT: CLI coverage for swamp data prune (orphaned-data reclamation)
Leaderboard search excludes ghosts — a visible ghost can't be found by its alias
issue-lifecycle: plan lifecycle entry silently dropped when summary exceeds 1000 chars
Make paid subscribers visually stand out (badge, profile popup summary)
Giphy integration via /giphy command
/lab shipped list is sorted by issue number, not ship date
Collscan/index-gap pack: unindexed $or id branches (every registry request), computed-field sort kills extension browse indexes, $expr blocks pull counts, apikey.userId, workflow_runs, 1100-doc profile fetch
Request-path external fetches with no timeout / no negative cache: profile GitHub/Discord resolution and landing-page total count (30s → 504 mechanism)
Auth hot path: 7 serial Atlas round trips per API-key request; session cookie cache dies after 5 min; session/apikey lookups unindexed
Leaderboard: window boards are unindexed full-collection aggregations ×4 per locate miss; locate fetches 4×10k rows to rank one user; search() has O(sum-of-ranks) lookup fan-out
/lab loads every issue with full markdown bodies on every request (incl. detail pages) + ~12 serial DB waves — the 3.4s avg / 30s tail
Activity projector runs on both telemetry replicas — same-day chunks can double-grant (grant_id collides but granted_at differs, ReplacingMergeTree never dedups)
Activity heatmap clips the current UTC day — uses local browser time for "today" but snapshots are UTC-keyed
Epic #847 · Unit 2: score_grants append-only ledger write-model in Mongo (shadow, no read flip)
feat(clickhouse): tracked archive→CH backfill tooling (backfill.sql)
feat(clickhouse): idempotent DDL migration path for running prod (#859 deliverable 2)
chore(clickhouse): retire S3-backed v1 + s3 objects after #859 cutover
Decouple prod ClickHouse from S3 (drop storage_policy=s3_main) + add a DDL migration path
Epic #847 · Unit 1: Land the ClickHouse projection foundation (schema + init SQL + compose service)
Extension publish score is non-monotonic: yanking versions lowers a user's score
Live Swamp Club event console on /feed — scrolling stream of all non-sensitive events
Telemetry watcher has no replica coordination: N replicas double-process the same batch (non-atomic find→updateMany claim)
Telemetry drain still capped ~80-100/s in prod: per-username full-history re-aggregate is O(users) sequential per batch (deferred #817 fix #4)
Telemetry ingest is consumer-bound: counter & stats dedup via O(N) sequential insertOne, throughput stuck ~20 events/s regardless of BATCH_SIZE
Batch step 2 of enrichAuthorPlans (per-collective subscription reads)
Add SWAMP CLUB wordmark logo next to sc-mark.png in TRADEMARKS.md
Docs: document trigger.inputs for scheduled/webhook workflows in the manual
serve --webhook usage string makes <header> look optional for generic scheme
Leaderboard window baseline: 90-day cutoff zeroes returning-dormant users (latent, 0 impact today)
Yank semantics inconsistent: all-versions-yanked acts as a free hidden/private extension; extension-level yank hard-blocks re-push
serve: webhook scheme not surfaced in startup event, health endpoint, or log line
Slack webhook pre-body gate only checks signature header, not timestamp
Dead code: verifySignature in webhook.ts superseded by verifier abstraction
Data-driven webhook signature verifiers (avoid a code change + release per provider)
Replace third-party trademark symbol with Swamp Club (SC) mark in TRADEMARKS.md
datastore setup migration relocates and deletes repo-root .swamp/secrets, breaking all local_encryption vault.get
Registry content-type search filter can match versions absent from the displayed extension
Docs: document reports.require failure semantics in the manual (unresolvable required report fails the run)
Resource-leak test failures on main: extension_rubric_scorer_test and worker_gateway_test
Tier-up announcements never fire for direct score contributions (badge awards, feed credits)
Feed-post scoring is a direct domain write, not a consumer of feed_post_approved telemetry
reindexByUsername re-strands pre-association history and wipes sign_in_dates
extension search returns null repository fields that extension info populates
Docs: TLS behind inspecting proxies / private CAs (system trust store, DENO_CERT, SSL_CERT_FILE)
username_metrics projection backfill does not trigger re-scoring (stale UserScore for dormant users)
Telemetry never retroactively credits a device's pre-association history
Telemetry admin reindex endpoint is gated on a defunct @systeminit.com email domain — permanently 403
extension update/pull deadlocks when the repo's datastore is the extension being updated
CLI telemetry forwards non-personally-resolvable identity for collective auth; distinct_id is per-machine, not per-repo
Telemetry ingest only resolves personal API keys — collective-token events are unattributed, identity_map under-claims
--json output is polluted by non-JSON content, breaking machine parsing
swamp serve: extension bundle failure at startup is silently pinned, breaking scheduled workflows with permanent 'Unknown model type'
Harness detection invents env vars for kiro/opencode/codex
Extension METHODS table truncates Method column; short names like apply/check wrap mid-word on /extensions/@swamp/ssh
swamp extension rm leaves empty <kind>-bundles/<hash>/ dirs behind
`swamp extension rm` leaves empty scaffold dirs behind
identity_map row not updated when user renames
Unified login input that detects email vs username by presence of '@'
Introduce `swampd`: long-running local daemon for shared cache, secrets, and extensions
Step key parsing in execution_service uses naive split(":") and silently truncates colon-containing step names
Workflow-scope report artifacts unreachable via `swamp data get --workflow`
telemetry: emit child entries for follow-up action method invocations
Per-method telemetry events for workflow runs
Award leaderboard points for referrals and collective invites
Add agent harness detection and AiTool to telemetry
Missing unique indexes on user.email and user.username allow duplicate users
Local extension edits don't reliably trigger rebundle
discord-bot double-sends sign_up notifications
Discord bot sends duplicate signup notifications
Extend DatastoreSyncService.markDirty() with optional relPath argument
Adversarial UAT test: missing cached bundle with intact catalog should self-recover
Port importBundleByPath ENOENT fallback to datastore/driver/vault/report loaders
swamp-club extension card no longer exposes @ns/slug as contiguous text
Docs: repository-configuration.md missing defaultDriver / defaultDriverConfig
Better Auth rejects requests on hostnames not in hardcoded trustedOrigins (signup/signin broken on non-canonical hosts)
Persist lab filter selection in localStorage
Server-side parse query params on /lab/all so refresh preserves multi-filter URLs
cleanup for repoDriver
Add repo-level `defaultDriver` to `.swamp.yaml`
First-class jsr: specifier support in extension bundler
Inline editing: click-to-edit fields instead of pencil icons
Cross-extension code sharing via manifest exports field
Footer floats when page content is shorter than viewport
Remove traffic lights in column 2 of /lab
Flow modal: text rendering issues
Bog flow: text rendering and layout issues
Multi-select combo filtering on /lab
Relationships
↔ sibling #2817#301 Per-method telemetry events for workflow runs
Opened by keeb · 5/8/2026· Shipped 5/9/2026
Problem
Today, swamp workflow run <name> emits exactly one telemetry event for the entire CLI invocation. The event captures command: "workflow", subcommand: "run", the workflow name in args, total duration, invocation context, and a single aggregate result.status.
This means we lose all per-step/per-method observability for workflows:
- Which model methods ran inside the workflow, and how many.
- Per-method duration, so we can't see which steps dominated wall-clock time.
- Which specific step failed when a workflow errors — only the rolled-up status survives.
- Per-driver / per-model-type usage signals for workflows specifically.
The workflow engine already emits rich internal MethodExecutionEvent and WorkflowExecutionEvent events for the UI/renderers, but DefaultMethodExecutionService does not record telemetry, and the CLI bootstrap (src/cli/mod.ts:1143,1225) only fires recordSuccess() / recordError() once after the whole command completes.
Proposed Solution
Emit child telemetry records for each model method invocation that happens inside a workflow run, parented to the outer CLI invocation:
- New event type (e.g.
workflow_method_invocation) emitted from the workflow execution path. - Fields:
parent_invocation_id, workflow name, job name, step name, model type, method name, driver, duration, status, error category on failure. - Reuse the existing internal
MethodExecutionEvent/WorkflowExecutionEventstream so we don't add a second instrumentation point — bridge them into theTelemetryServiceinstead. - Apply only to
workflow run(and any future workflow execution commands); keep the single-event shape for non-workflow CLI invocations.
Alternatives Considered
- Leave as-is. Cheapest, but workflow observability stays blind past the outer envelope.
- Single rolled-up event with embedded step summaries. One event per invocation with a
steps[]array. Simpler ingest, but harder to query/aggregate across workflows and bloats individual rows. - Emit child events only on failure. Cuts volume, but loses the duration/usage signal on the happy path, which is the more interesting analytics case.
Preference is option (1) in the proposed solution — full per-method child events parented by invocation_id — because it makes both success and failure paths queryable with the same shape.
Context
- CLI telemetry bootstrap:
src/cli/mod.ts:1143,1225 - Per-invocation context fields landed recently in
3d787176(agent harness + TTY). - Workflow execution emits
MethodExecutionEvent/WorkflowExecutionEventfor the renderer; these are the natural source to bridge into telemetry.
Shipped
Click a lifecycle step above to view its details.