Best for
- Use when the user is operating on (or wants to operate on) a live runtime they have running locally.
day8/re-frame2/skills/re-frame2-pair/SKILL.md
Pair-program against a **running** re-frame2 application via its Tool-Pair contract — attach to a live shadow-cljs nREPL, inspect a frame's app-db, dispatch events, hot-swap handlers, read the trace stream and per-frame epoch history, and time-travel with `restore-epoch`. Use when the user is operating on (or wants to operate on) a live runtime they have running locally. **Do not use** for static spec reading, architecture questions, design discussion, or ordinary source edits when no runtime is
Decision brief
Pair-program on a live, running re-frame2 application (a browser tab behind shadow-cljs watch): help the developer understand, debug, and modify it by operating on the live runtime, not just reading source.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/day8/re-frame2 --skill "skills/re-frame2-pair"Inspect the Agent Skill "re-frame2-pair" from https://github.com/day8/re-frame2/blob/500f455ab81740840a38338633554e4f8ffd7821/skills/re-frame2-pair/SKILL.md at commit 500f455ab81740840a38338633554e4f8ffd7821. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
The skill's helper namespace ships into the app via shadow-cljs's :devtools :preloads mechanism (separate from Xray's devtools preload and true-inline [data-rf-xray-host] panel contract). The re-frame2-pair preload is required; there is no per-session cljs-eval inject fallback.…
Your agency runs through three coupled primitives, all part of re-frame2's Tool-Pair contract:
Know which mode you're in and why. Strict source-edit protocol: references/ops.md §Hot-reload coordination.
Before any other op, run discover-app (mcpre-frame2-pairdiscover-app). It locates the shadow-cljs nREPL port, connects, switches the session to :cljs mode for the running build, verifies re-frame2 is loaded with interop/debug-enabled? true, and confirms the re-frame2-pair.runtim…
Your read order, every session: discover-app → orient → a targeted slice.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 98/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 44 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Pair-program on a live, running re-frame2 application (a browser tab behind shadow-cljs watch): help the developer understand, debug, and modify it by operating on the live runtime, not just reading source.
Router skill. Trigger-time guard rails are below; operational depth (op catalogue, recipes, error handling, hot-reload protocol, v1-migration notes) lives in references/, loaded on demand.
Your agency runs through three coupled primitives, all part of re-frame2's Tool-Pair contract:
(re-frame.trace.tooling/register-listener! id cb) for live trace events; (re-frame.trace.tooling/trace-buffer frame-id) for the retain-N ring. (The facade form is the stream-parameterized (rf/register-listener! :trace id cb) — a stream-dispatching wrapper, not a same-signature re-export of the 2-arg tooling fn; trace-buffer is a JVM-only rf/ alias — CLJS callers, including this shim's cljs-eval, must use re-frame.trace.tooling/trace-buffer directly or the form silently returns nil.) trace-buffer takes the frame-id first ((trace-buffer frame-id) cascade bundles, (trace-buffer frame-id opts) filtered) — a missing/destroyed frame-id silently returns [], so never pass an opts map as the sole arg. This skill registers exactly one trace listener (id :re-frame2-pair) so tools coexist.(rf/epoch-history frame-id) returns the per-frame ring of :rf/epoch-record values, each carrying the cascade's :db-before, :db-after, :trace-events, and the structured :sub-runs / :renders / :effects projections. (rf/register-listener! :epoch id cb) is the assembled-stream listener.Every op eventually becomes a short ClojureScript form evaluated through the REPL, usually against a helper in the re-frame2-pair.runtime namespace the consumer app preloads (see §Setup).
re-frame2-pair.runtimeThe skill's helper namespace ships into the app via shadow-cljs's :devtools :preloads mechanism (separate from Xray's devtools preload and true-inline [data-rf-xray-host] panel contract). The re-frame2-pair preload is required; there is no per-session cljs-eval inject fallback. When discover-app can't find the marker it runs a diagnostic ladder; the normal missing-preload verdict is :reason :runtime-loaded-but-preload-missing. See references/errors.md §discover-app preload-failure ladder for the full reason set and each recovery.
The skill installs from a repo checkout (not npm — see the README's Install / docs/LOCAL_DEV.md), so the preload comes off the linked skill's own preload/ directory. Point the consumer app's shadow-cljs :source-paths at it — the two-line shadow-cljs.edn change:
{:source-paths ["src"
"<abs>/skills/re-frame2-pair/preload"] ;; add this (the linked skill's preload/)
:builds
{:app {:devtools {:preloads [re-frame2-pair.runtime]}}}} ;; …and this
The re-frame2-pair.runtime namespace is separate from the MCP server (@day8/re-frame2-pair-mcp) — the MCP server does NOT ship preload/, so wiring only the server leaves discover-app failing with :runtime-loaded-but-preload-missing. (Once the @day8/re-frame2-pair package is published to npm, npm install -D @day8/re-frame2-pair and point :source-paths at node_modules/@day8/re-frame2-pair/preload instead — see docs/LOCAL_DEV.md.)
Verify by running discover-app — success is {:ok? true :build-id ... :debug-enabled? true :frames [...]} plus other health slots. A missing preload returns {:ok? false :reason :runtime-loaded-but-preload-missing :hint "..."}; report the hint verbatim (fixable in seconds). The other ladder rungs (:build-not-running / :no-runtime-connected / :nrepl-unreachable, plus the blanket :runtime-not-preloaded degradation fallback) each mean a different fix — see references/errors.md §discover-app preload-failure ladder.
Registering the MCP server takes a fresh session, not --continue. Wiring @day8/re-frame2-pair-mcp into the agent host (claude mcp add, or editing settings.json) only takes effect in sessions that start afterwards — a --continue'd session won't surface the tools even though claude mcp list reports Connected. Exit and start a new session after registering (also after rebuilding out/server.js).
The v1→v2 migration boot-smoke needs only a browser-console read, not this MCP — see skills/re-frame-migration/references/runtime-smoke-test.md. Reserve the full pair MCP for the deeper interactive debugging once the boot-smoke flags something.
app-db) are ephemeral — survive hot-reloads of unaffected namespaces, lost on full page reload. Use for probes, experiments, throwaway fixes.Edit / Write) are permanent. After any source edit you must run the hot-reload coordination protocol (tail-build with a probe) before dispatching or tracing, or you'll interact with pre-reload code and get misleading results.Know which mode you're in and why. Strict source-edit protocol: references/ops.md §Hot-reload coordination.
Before any other op, run discover-app (mcp__re-frame2-pair__discover-app). It locates the shadow-cljs nREPL port, connects, switches the session to :cljs mode for the running build, verifies re-frame2 is loaded with interop/debug-enabled? true, and confirms the re-frame2-pair.runtime preload landed (see §Setup).
Connect once — the resolved build sticks. A successful discover-app records the resolved build as the session-sticky default on the connection, for every resolution path — auto-selected single build, explicit :build, and :port. After one discover-app, call every other tool (orient, read-dom, read-ui, snapshot, get-path, …) with no build arg and it targets the resolved build — even with several builds running. Pass build again only to switch builds (an explicit :build on any later call wins and re-sticks). The sticky default resets on nREPL reconnect (a shadow restart); the next discover-app re-establishes it.
Arg forms (don't guess). Each arg has one expected shape:
| Arg | Form | Examples |
|---|---|---|
build | bare build id; a leading colon is also tolerated. Omit it when one build is running — discover-app auto-selects it | "examples/standard-epochs" or ":examples/standard-epochs" — identical |
port | integer — the port from the browser URL | 8031 — see Connecting from a URL below |
frame / frames | keyword with the colon | ":rf/default", ":app/main", [":rf/default" ":rf/xray"] |
Single-build auto-selection / connecting from a URL. You usually don't pass build — one running build auto-selects (several → it errors with the running-builds list, never a silent guess). When you know only the open tab's URL, pass discover-app {port: 8031}: the server reads the :dev-http map and resolves the build served on that port (no build maps to it → :reason :port-unresolved, no silent fallback; an explicit :build wins if you pass both). The port-resolved build sticks like every other path. discover-app reports every build/frame id as a full keyword in the canonical EDN — read the EDN text for the id exactly as you'd type it back into a :frame arg (the :structuredContent JSON view strips the colon, a documented lossy projection).
Read the :freshness token before you trust a read. Every :ok? true discover-app payload carries :freshness {:liveness <verdict> :hint <str> ...}. Pattern-match :liveness first: :fresh (read away), :stale-build (tab serving OLD code — the :hint names the URL to reload), :no-runtime (no live CLJS runtime — reads come back blank; :hint names the URL to reload then re-run discover-app), :unknown (build-worker state unreadable — not a green light; usual cause is a zombie shadow-cljs JVM, so the :hint steers to npx shadow-cljs stop → one watch → reload → re-discover).
You cannot reload a browser yourself — on a non-:fresh verdict, relay the :freshness :hint to the user as the single next step rather than firing reads that return blank.
On any failed precondition, discover-app returns structured edn ({:ok? false :reason :runtime-loaded-but-preload-missing} or another ladder rung: :build-not-running / :no-runtime-connected / :nrepl-unreachable). Report the failing check verbatim; do not guess workarounds. See references/errors.md for reasons + recoveries.
Port + build discovery are automatic. On the first tool call the server discovers the live shadow-cljs nREPL itself and absorbs shadow restarts transparently; the resolved build sticks. Only reach for manual resolution on :reason :port-unresolved (read the app's shadow-cljs.edn :dev-http yourself to correlate the URL port to its build, then pass discover-app {build: ...}). The full discovery cascade, build-id resolution rules, and the --port-file / SHADOW_CLJS_NREPL_PORT overrides live in references/mcp-transport.md — rarely needed.
The nREPL session persists between turns. A full page refresh drops the runtime, but the preload re-installs it on the next bundle load — no manual reconnect. Every op checks the load-time marker (js/globalThis.__re_frame2_pair_runtime) first; if missing, the op refuses with the runtime-side :runtime-not-preloaded hint pointing here. (That per-op check is distinct from discover-app's richer ladder, which on the same missing-marker condition reports the more precise :runtime-loaded-but-preload-missing — see references/errors.md.)
For a refresher on the MCP surface before the first real op, optionally call get-re-frame2-pair-instructions — inline onboarding text (tool catalogue, EDN posture, tagged-mutation conventions, streaming-subscribe semantics, the wire pipeline) with no nREPL round-trip.
Your read order, every session: discover-app → orient → a targeted slice.
After discover-app connects, your first read is always orient (mcp__re-frame2-pair__orient {}) — never a snapshot. orient returns a compact, one-round-trip app-shape summary: liveness, the app frames (reserved :rf/* tool frames excluded), each app frame's top-level app-db keys only, registry counts, and the navigable event / sub / fx / machine ids. Bounded by construction — it hands you the map without pulling any bulk, and omits the :rf/xray tool frame's contents.
Only after orient do you drill — into slices, never whole frames:
| You want | Use |
|---|---|
| one sub's current value | read-sub {sub: "[:cart/total]"} |
| one app-db path | get-path {path: "[:cart :items]"} |
| a bounded sub-tree | snapshot {path: "[:cart]"} (the snapshot tool defaults to :summary — top-level shape only; a path narrows it further) |
Never read a whole frame to orient. A snapshot {path: "[]"} (full, unsliced) or an eval-cljs form that derefs an entire frame's app-db can be enormous — especially the reserved :rf/xray tool frame: its app-db is Xray's entire working set (the epoch ring with each epoch's :db-before / :db-after, the trace buffer, diff projections, panel state) and grows without bound. A full read of it has overflowed past 100K tokens in one call. You essentially never read the :rf/xray frame at all — pair against the app frame (whatever id the app registered, e.g. :app/main, or :rf/default if the app chose that).
Mental model: breadth-first shallow (orient) → depth-first narrow (read-sub / get-path / snapshot {path}). snapshot is a drill-in tool you hand a path, not the way you take in an app.
re-frame2 supports multiple, named frames (Spec 002). Most apps run one app frame (registered at the root — whatever id the app chose, e.g. :app/main); larger apps run several. The public address is the frame (EP-0023) — image -> frame -> event stream: target a frame id in a single process-local frame-id space, no realm/container coordinate. Every read/write op resolves an operating frame through a four-tier cascade: per-call frame arg (tier 1) → session pin (tier 2) → the sole registered app frame (tier 3) → nil/ambiguous (tier 4). Tier 3 is unique resolution, not synthesis. Framework-reserved :rf/* tool frames (Xray's :rf/xray, SSR/stories slots) are excluded from the ambiguity count, so a single-app session also running Xray auto-resolves to its one app frame. (:rf/default, if an app registers it, is an ordinary app frame — no framework privilege, still counted.) Full detail: references/ops.md §Frames.
Set the session pin with the dedicated operating-frame tools — three MCP tools surface tier 2 directly, no eval round-trip: set-operating-frame {frame: ":foo"} (pin — the escape from the tier-4 refusal; validates the id, returns the {:frames :selected :operating} triple), reset-operating-frame {} (clear), get-operating-frame {} (read; :operating nil means ambiguous). These three are NOT subject to the :ambiguous-frame refusal — they resolve it.
subscribe is the exception — it has no frame arg, so the operating-frame pin does not scope a streaming subscription; scope a stream with filter {:frame ":foo"} instead.
When the operating frame is ambiguous (two-plus app frames, no pin), every other frame-targeted op refuses with :ambiguous-frame rather than guess — a write into the wrong frame is unrecoverable without restore-epoch. Reads refuse too (the validated read helpers return :reason :ambiguous-frame rather than silently reading :rf/default). Mirrors Spec 002 §Frame presets / lifecycle convention.
Read the leaf matching the task. Most references are ≤250 lines; the two catalogue leaves (ops.md, recipes.md) run longer.
| Task shape | Reference |
|---|---|
| Pick a structured op (read, validated sub-read, write, dry-run, trace, DOM/UI read, signal recording, blocking wait, hot-reload, time-travel) | references/ops.md |
| Orient on an unfamiliar app in one call, or read a single sub's validated value | orient / read-sub — see references/ops.md §Read (arg signatures in references/mcp-transport.md §MCP tool reference) |
| Find out which registrations / image a specific frame actually runs (the multi-image / Story case where the same id resolves differently per frame), with per-frame provenance | describe-image — see references/ops.md §Frames |
| Read what's actually on screen (rendered content + producing view entity) | read-ui / read-dom — see references/ops.md §View → rendered content |
Ask what a Freehand (v/defview) view declares — its manifest/source (read-view-manifest), the subscriptions feeding it (read-view-dependencies), the events it can fire (read-view-event-sites) — all readable before it mounts. Reagent and UIx views answer :view-tier-unavailable on these five; every other op in this skill works on them unchanged | see references/ops.md §Freehand view inspection |
Ask which Freehand occurrences are connected right now (read-mounted-views), or why one rendered when you didn't expect it to (explain-render) | see references/ops.md §Freehand view inspection |
| Simulate an event's consequence WITHOUT committing it (no fx fire) | dispatch-dry-run — see references/recipes.md §"What would this event do?" |
| Record signals while the human interacts, or block until a condition lands | record / read-recording / watch-until — see references/ops.md §Signal recording |
| Run a named procedure the user asked for ("why didn't my view update?", post-mortem, experiment loop, etc.) | references/recipes.md |
| Drive a Story variant from a re-frame2-pair session — the variant is a frame; variant-id ↔ frame-id identity, per-variant isolation, the four-phase lifecycle, gotchas, discovery | references/variant-as-frame.md |
| Open a push-mode subscription on the trace or epoch bus (topics, filters, termination) | references/streaming-subscriptions.md |
| Diagnose a stream that was refused / went quiet / terminated — server-side caps, slot leaks, rate-limit/abuse pressure (answers even when the runtime is down) | get-stream-controls / list-streams — see references/streaming-subscriptions.md §Diagnostics |
Decode a deduped wire payload (:rf.mcp/dedup-table) or pick the right size-conscious arg (max-tokens, path, mode, dedup, elision, limit/cursor, cache, max-buffered-*) | references/wire-size-budget.md |
Translate a structured {:ok? false :reason ...} to plain English; suggest the recovery | references/errors.md |
| Edit source, then wait for the browser to pick up the new code | references/ops.md §Hot-reload coordination |
Map a v1 (re-frame-pair) surface to its v2 equivalent (or know it has none) | references/ops.md §Dropped from v1 |
| Install/configure the persistent-connection MCP server | references/mcp-transport.md |
Drive the running browser app's own Story registry via eval-cljs (re-frame.story/ids / variants-of / run-variant, await the run-result) — the pair is the live-browser Story host, story-mcp cannot see the browser registry; OR use the story-mcp tools during a live session (the five live-session tools run-variant / read-failures / snapshot-identity / read-a11y-violations / record-as-variant plus the three read-only enumerations list-decorators / explain-variant / get-docs-markdown; composition with watch-epochs and dispatch-from-pair) | references/stories.md |
Load at most two references for a single task. Wanting three means the request spans concerns and should be broken up.
orient first, then drill into slices. Your first read each session is orient, never a whole-frame read; ground a hypothesis by drilling into a slice (read-sub / get-path / snapshot {path}). See Orient before you drill for the rule and the :rf/xray overflow.eval-cljs is the workhorse for the long tail, not a last resort. Dedicated tools (orient, read-sub, get-path, read-ui, dispatch, …) give a validated, elided, single-round-trip answer for the gesture they own; epoch forensics, arbitrary-selector DOM reads, cross-referencing, and recovery are first-class eval-cljs work — see recipes.md §eval-cljs is the workhorse. (Privacy caveat: raw eval-cljs is un-elided — see the privacy bullet below.)dispatch-dry-run, not a live dispatch or throwaway eval-cljs handler. For "test this handler" / "try a dispatch" / "what would happen if…", reach for dispatch-dry-run first: it runs the whole cascade (reducer, interceptors, schema, machine transitions, sub-runs, renders) without committing — no fx execute, the framework auto-rolls-back app-db. It is the safe primitive for this gesture; dispatch and raw eval-cljs are not. Dry-run targets a registered event, so to probe a throwaway handler: register it with eval-cljs ((rf/reg-event :exp/probe …)), then dispatch-dry-run {event: "[:exp/probe …]"} — the rollback still applies, leaving no trace. See recipes.md §Experiment loop and §"What would this event do?".reg-event handler returning {:db <bare-map>} REPLACES app-db wholesale (does NOT merge), so a throwaway probe driven by a live dispatch nukes the entire frame's app-db, unrecoverable without restore-epoch. Two safe paths: prefer dispatch-dry-run (rolls back), or if you must commit return {:db (assoc db …)} from the live db cofx — never a bare literal map. Full treatment: recipes.md §Experiment loop.reset! of a frame's app-db except when surgically needed, and say so when you do.shadow-cljs.edn, deps.edn) rather than bouncing off the tool. "Which build is this port?" / "where does this artefact live?" usually sits in the source config in plain sight.dom/source-at before speculating. Reporting re-com/button at app/cart/view.cljs:84 grounds the conversation in a file the user can open; "probably the Save button somewhere in the profile view" doesn't.:sub-runs, :renders, :effects are the routing surface; :trace-events is the escape hatch for detail the projection omits (e.g. per-interceptor timing, or the raw fx :args the :effects projection redacts off-box).:re-frame2-pair) and one epoch listener (:re-frame2-pair-epoch). Multi-tool coexistence is the default — don't worry about other listeners; per Spec 009 §Listener ordering, ordering is not contract.eval-cljs does NOT. Per Spec 009 §Privacy, the structured read/stream tools (snapshot, get-path, read-sub, trace-window, watch-epochs, subscribe, dispatch-dry-run, and the recorders) force wire-boundary elision server-side under the --allow-sensitive-reads gate (OFF by default) — sensitive → :rf/redacted, large → :rf.size/large-elided, epoch records additionally route through projected-record. So structured reads/streams are safe to fire by default. But eval-cljs is default-ON (governed only by --no-eval) and NOT governed by this gate — it returns the form's value without running the elision walker, so a raw (re-frame2-pair.runtime/snapshot) / (rf/epoch-history …) can ship verbatim app-db / trace / epoch state — secrets included. This is the raw-eval carve-out: don't reach for raw eval to read a sensitive path / sub / trace / epoch when a structured tool fits — reserve it for forensics, cross-referencing, and recovery. Full mechanism in references/vocabulary.md §Privacy posture.restore-epoch and replace-app-db — both allow-listed and the canonical path (validate, append a synthetic undoable epoch, tap>, return a :cascade-summary). Both are gated by the server's --allow-writes flag (default OFF); the server's gate, not the allow-list, is the write boundary. Raw eval of a write form ((rf/restore-epoch! …) / app-db-reset!) is the backstop, not the default — reach for the dedicated tool first. Full detail: references/ops.md §Time-travel.A re-frame2-pair session and a running Xray panel are complementary surfaces over the same trace bus + epoch history. re-frame2-pair owns the driving (dispatch, hot-swap, restore-epoch); Xray owns the seeing (visual reading of what just happened across its Dynamic event-spine tabs and Static registry-browse tabs — skills/re-frame2-xray/ is the canonical source for Xray facts). Reach for Xray alongside re-frame2-pair when:
| re-frame2-pair just did | Open Xray to … |
|---|---|
Rewound to an earlier epoch via restore-epoch | Scrub the bottom-rail time-travel scrubber to inspect adjacent epochs visually; pin slices via the app-db tab's inline diff. |
| Dispatched into a cascade you don't fully understand | The Epoch tab lands on the latest cascade and shows the dispatch-id tree. |
| Hot-swapped a sub or reg-event handler | Watch the Epoch SUBSCRIPTIONS step recompute the invalidation chain (:cart/total ← :cart/items ← [:cart :items]). |
| Stepped into a machine transition | Open the Machine tab / Machine Inspector for the state-chart view with transition history. |
| Triggered a schema violation | Schema violations surface inline on the Epoch tab (and as an L2 pink-wash) with recovery mode + source coord. |
Authoring-side guidance for getting Xray mounted (preload, layout host, suppress-auto-open knob, popout, host-CSS-variable resize) lives at skills/re-frame2/references/tooling/xray.md. When advising a user mid-session on which panel to look at, route them there for the mount-side detail; this skill stays focused on the driving side.
Deep-dive content (full API reference, EP design rationale, spec corpus, migration guide) routes through SKILL-REDIRECT.md at the repo root. Full skill-disambiguation matrix (when to use which skill) lives at skills/README.md §Skill routing — single source.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
prowler-cloud/prowler
PostgreSQL indexing best practices for Prowler: index design, partial indexes, partitioned table indexing, EXPLAIN ANALYZE validation, concurrent operations, monitoring, and maintenance. Trigger: When creating or modifying PostgreSQL indexes, analyzing query performance with EXPLAIN, debugging slow queries, reviewing index usage statistics, reindexing, dropping indexes, or working with partitioned table indexes. Also trigger when discussing index strategies, partial indexes, or index maintenance
JasonColapietro/suede-creator-skills
Suede-owned experimentation discipline for hypotheses, sample sizing, test duration, significance, and repeatable experiment programs. Use when comparing variants, deciding whether a result is reliable, or building an experiment backlog and cadence. NOT FOR: analytics instrumentation (use suede-analytics), post-click conversion diagnosis (use suede-site-alchemy), or writing the variant copy itself (use suede-copy).