Skip to main content
Engineering/synesthesia

Synesthesia

You need a cross-modal diagnostic review that maps code into sensory models to surface hidden architectural issues.

Use this when you want a fresh perspective on a codebase, architecture, bug, or system by translating its structure, flow, and patterns into sensory models that reveal hidden issues -- then translating those models back into precise engineering language and action. Best fits: architecture review, readability assessment, strange or flaky behavior, performance bottlenecks, API or UX critique, onboarding explanations, and comparing implementations by feel, friction, weight, rhythm, or complexity. Also use when someone asks what a codebase "feels like" or asks to make it "lighter," "smoother," "cleaner," or "tighter."

Do not use for exact API syntax, compliance or legal interpretation, security sign-off, rote code edits, or terse factual tasks.

Core contract

Always:

  1. Start from literal evidence: code, tests, architecture, logs, runtime behavior, user flows, or repository structure.
  2. Build at least 2 and at most 4 sensory representations that illuminate the problem.
  3. Keep mappings consistent within a single answer.
  4. Mark uncertainty clearly.
  5. Convert every useful metaphor back into concrete technical implications.
  6. Prefer directness over poetry. This is a reasoning aid, not performance art.

Never:

  • Treat metaphor as evidence.
  • Use sensory language to hide uncertainty.
  • Overwrite exact technical facts with aesthetic judgments.
  • Force this framing onto small factual tasks better answered literally.

Sensory mapping guide

Use these default correspondences unless the user defines a custom mapping.

Software propertyColor / lightSound / musicShape / spaceTexture / temperature
High cohesionsaturated, stable hueconsonant, repeating motifcompact clustersmooth, warm
Loose couplingclear separationwell-spaced notesbreathable layoutcrisp
Tight couplingcolor bleedmuddy overlaptangled edgessticky, heavy
Good abstractionlayered transparencyclean harmonynested but legible formspolished
Hidden complexitymurky gradientsunresolved tensionfolded interior spacerough underneath
Hot path / high loadbright / hotfast temponarrow corridor with traffichot, pressured
Latencydelayed echodragging rhythmlong corridorrubbery
Flaky behaviorflickeroff-beat stuttershifting geometrygritty
Race conditioninterference patternphase clashcrossing vectorssparking
Memory leak / bloatspreading stainswelling droneexpanding massoverheated, swollen
Dead codegray / dimsilenceabandoned roomcold, dusty
Clean interfacesharp boundaryclean attack / releasedefined doorwaysmooth edge

Process

Step 1: Literal read

Read the target artifact (codebase, module, logs, architecture, API surface) and extract:

  • Components and their responsibilities
  • Control or data flow
  • Hotspots (high traffic, high change rate, high complexity)
  • Failure modes (error paths, edge cases, flaky areas)
  • Constraints (performance, security, compatibility)
  • Unknowns (missing tests, undocumented behavior, implicit assumptions)

Output 2-6 bullets summarizing what the code or system is doing.

Step 2: Sensory render

Choose 2-4 modalities best suited to the task:

  • Visual: color, brightness, contrast, motion
  • Auditory: rhythm, harmony, noise, silence, dynamics
  • Spatial: topology, compression, bottlenecks, symmetry
  • Tactile / thermal: smoothness, drag, heat, brittleness, weight

Produce a concise multi-modal description of how the system feels, sounds, looks, or moves. Use the mapping table above to stay grounded.

Step 3: Find harmonies and dissonances

Look for:

  • Places where intended design and observed behavior disagree
  • Sharp transitions between clean and messy regions
  • Components that dominate the whole system's character
  • Parts that create friction, jitter, lag, or haze

Output the 1-3 most important mismatches, friction points, or instability signals.

Step 4: Translate back to engineering

For each important sensory observation, state:

  • The literal technical interpretation
  • Why it matters
  • What change would improve it

Step 5: Recommend action

End with a concrete, prioritized list of next steps. Prefer high-leverage moves:

  • Refactor boundary
  • Split module
  • Add test
  • Instrument runtime
  • Cache result
  • Simplify control flow
  • Remove duplication
  • Tighten interface
  • Rename for clarity
  • Defer work until uncertainty is reduced

Output format

Literal read 2-6 bullets on what the code or system is doing.

Synesthetic render A concise multi-modal description of how the system feels, sounds, looks, or moves.

Dissonances The 1-3 most important mismatches, friction points, or instability signals.

Engineering translation Concrete explanation of what those signals mean technically.

Recommended changes Specific next steps, ordered by leverage.

Special modes

Debugging mode

When the user is chasing a bug or flaky behavior.

Bias toward dissonance, jitter, interference, flicker, and timing language. Translate into:

  • State bugs
  • Race conditions
  • Non-determinism
  • Retries or timeouts
  • Unexpected coupling
  • Missing observability

Refactoring mode

When the user wants to restructure or clean up code.

Bias toward weight, balance, shape, airflow, and texture. Translate into:

  • Oversized modules
  • Fractured responsibility
  • Abstraction leakage
  • Poor naming
  • Duplicated logic
  • Brittle seams

Performance mode

When the user is profiling or optimizing.

Bias toward tempo, pressure, congestion, heat, and echo. Translate into:

  • Bottlenecks
  • Excessive allocation
  • Serialization
  • Network or disk latency
  • Poor batching
  • Unnecessary recomputation

Teaching mode

When the user is onboarding or explaining architecture.

Lean more vivid and intuitive, but keep the mapping reversible. Use metaphor to help the user build a correct mental model.

Guardrails

If the user asks for code changes:

  • Do the code task normally.
  • Use the synesthetic analysis to guide decisions.
  • Briefly describe the before-and-after feel only if helpful.

If the user asks for a pure sensory rendition:

  • Still anchor claims in the artifact.
  • Avoid pretending to perceive unseen details.

If the artifact is incomplete:

  • State what is missing.
  • Present the sensory model as tentative.

Example Output

Input

  • Command: /synesthesia
  • Target: The checkout service at Meridian Commerce — a Node.js monolith handling cart validation, coupon resolution, payment orchestration, and order creation in a single 2,400-line checkout.service.ts file
  • Context: The team is seeing intermittent double-charges in production (roughly 1 in 800 orders), a p99 latency of 4.2s on the payment step, and onboarding takes new engineers ~3 weeks before they feel safe touching this file
  • Mode: Debugging + Performance

Output (abbreviated)

Literal read

  • checkout.service.ts is a single class with 34 public and semi-public methods; cart validation, coupon resolution, Stripe API calls, inventory reservation, and order persistence all share the same instance state
  • Payment is orchestrated inline: chargeCard()reserveInventory()createOrder() with no saga, outbox, or compensating transaction — failure at step 3 leaves a charged card with no order
  • Coupon resolution calls a Redis cache, but on cache miss falls through to a Postgres query inside a loop over cart line items — no batching
  • Three separate locations call Stripe.charges.create() conditionally; one is inside a retry block that does not check for idempotency key collisions
  • No distributed lock guards the critical section between charge and order creation; the only concurrency protection is an optimistic Postgres update that is bypassed when the retry fires
  • Test coverage is 41% by line, concentrated almost entirely in coupon math; payment and order paths have no integration tests

Synesthetic render

Visual: The file opens as a saturated, warm amber — the coupon logic has real cohesion and emits clean, stable color. But halfway through, the hue bleeds into orange-brown, then into a murky, stained red around the payment block. The charge/reserve/create triplet looks like three spotlights aimed at the same wall from different angles, casting overlapping shadows that shift depending on which code path was taken last. The retry block is a small, very bright white flare — almost overexposed — sitting inside an otherwise dim corridor.

Auditory: The service has the rhythm of a competent solo pianist playing a composed piece — until bar 34, where a second pianist enters playing the same melody half a beat behind. The result is a phase clash: two nearly identical note sequences interfering with each other. The Stripe retry is the second pianist. On most runs they resolve in unison. On 1 in 800, they don't.

Spatial / tactile: The overall shape is a long, narrow corridor with a sharp bottleneck at the payment step — high traffic, hot walls, pressured airflow. Branching off the main corridor are several doors that look closed but open inward on retry. The coupon-resolution loop is a section of corridor lined with speed bumps: smooth if cache is warm, suddenly rough and dragging when it isn't.


Dissonances

  1. Phase clash at payment (the double-charge signal): The retry path and the primary path can both reach Stripe.charges.create() without a shared idempotency key derived from a stable order ID. This is the interference pattern — two identical signals slightly out of sync.

  2. Hot corridor with no pressure release (the p99 signal): The cache-miss path in coupon resolution issues N sequential Postgres queries inside the same synchronous chain that holds the payment lock. This is the speed-bump drag compounding with the bottleneck heat.

  3. Murky interior hiding the compensation gap: The file looks structured (classes, JSDoc, consistent naming) but the absence of any compensating transaction means the interior is folded — complexity hidden behind a polished surface. The stain spreads only when things go wrong, which is exactly when you most need clarity.


Engineering translation

Sensory signalLiteral technical meaningWhy it matters
Phase clash / two pianistsStripe.charges.create() called in primary flow and in a retry block; idempotency key not tied to a stable, pre-generated order IDRoot cause of double-charges; Stripe will treat the retry as a new charge if the key differs or is absent
Pressured corridor + speed bumpsCoupon cache-miss triggers a sequential per-item Postgres query inside the synchronous payment chain; no Promise.all, no batch queryDirectly responsible for p99 spikes; under load this serializes queries while holding resources
Folded interior / compensation gapNo outbox pattern, no saga — a Stripe charge can succeed while createOrder() fails, with no rollback and no alertEach such failure is an unreconciled charge; currently invisible without manual Stripe dashboard review

Recommended changes

  1. Assign idempotency keys before calling Stripe (fix double-charge, high leverage) Generate a stable orderId (UUID) at the start of checkout, before any Stripe call. Pass it as the idempotency key on every charges.create() call site. Remove the retry block's independent key generation. This collapses the phase clash.

  2. Batch coupon resolution (fix p99, immediate) Replace the per-item cache-miss loop with a single WHERE coupon_code = ANY($1) Postgres query and a multi-key Redis MGET. Wrap in Promise.all if calls remain independent. Expected p99 improvement: 800ms–1.5s based on typical cart sizes.

  3. Instrument the charge→reserve→create triplet now (reduce blindness) Add structured logs with a shared checkoutSessionId at each step and emit a checkout.charge_without_order metric when Stripe charge exists but no order was created within 30s. This makes the compensation gap visible before you restructure it.

  4. Introduce a minimal outbox or idempotent order-creation guard (prevent revenue loss, medium effort) Store a pending_orders row with the orderId and Stripe charge ID before calling Stripe. On order creation, upsert on orderId. This converts the three-step cliff into a recoverable ledger.

  5. Decompose checkout.service.ts into three bounded modules (fix onboarding friction, refactoring mode) Split into CouponService, PaymentOrchestrator, and OrderWriter. Each file should have one clear responsibility and one color — the amber of the coupon logic, properly isolated, is already clean. The goal is three separate rooms with defined doorways, not one overheated corridor.