Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions CHANGELOG_SYMBOLIC_MOMENT_REFACTOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Symbolic Moment Refactoring: From Card to Reading Surface

**Date:** 2026-04-20
**Branch:** `claude/complete-opus-implementation-exjj7`

## Overview

The Symbolic Moment UI has been refactored from a decorative "card" widget into a dedicated **reading surface** — a primary, instrumental interface that presents live readings with clarity, hierarchy, and calm.

## Problem Statement (Original)

The previous implementation treated the Symbolic Moment like a dashboard tile:
- Over-containerized with heavy borders and backgrounds
- Copy arrived as dense, repetitive paragraphs
- Exposed too much mechanism too early (builders labels, compressed layouts)
- Dormant/awaiting overlays remained visible even when an active reading was available
- Visual hierarchy was flat; the reading didn't feel like instrument output

## Solution

### New Component: SymbolicMomentReadingSurface

**Location:** `vessel/src/components/chat/SymbolicMomentReadingSurface.tsx`

A new component that structures live readings into six distinct, visually separated sections:

1. **Signal** — One plain opening statement about the day/moment
2. **Meter** — Compact measurement row (Symbolic Moment · Mag X · Bias Y · Vol Z)
3. **Landing** — Chamber name first, then grounded sentence about where the load settles
4. **Voice** — Two short paragraphs max, specific and non-directive
5. **Check** — One falsifiable question in a subtle box
6. **Drivers** — Hidden by default, disclosed on click (climate + weather lines)

#### Design Features

- **Left border accent** (cyan-400/30) instead of full container
- **Minimal dividers** between sections instead of heavy rounded boxes
- **Typography-first** hierarchy; most layout work done by spacing and text styling
- **Mobile-optimized** — clean line lengths, high contrast, easy tap targets
- **Chamber names mapped** — 8th → "The Core", 9th → "The Horizon", etc.
- **No builder labels** — "Signal", "Meter", "Landing" speak plainly, not "FIELD", "MAP"

### Copy Validation: symbolicMomentFormatting.ts

**Location:** `vessel/src/lib/raven/symbolicMomentFormatting.ts`

Utility functions to enforce copy integrity:

- **`validateSignal()`** — Max 150 chars, must align with meter intensity
- **`validateLanding()`** — Soft limit 180 chars, 1–2 sentences, no semantic duplication
- **`validateVoice()`** — Max 2 paragraphs, soft limit 300 chars, detects repeated ideas
- **`validateSymbolicMomentCopy()`** — Comprehensive validation across all sections

**Guards:**
- Prevents meter overstatement (e.g., high magnitude paired with "subtle" language)
- Flags duplicate semantic lines (>65% similarity)
- Enforces "quiet, mixed, moderate" readings remain in tone
- No contradictions between prose intensity and meter readings

### RavenStructuredReply Updates

**Enhanced parsing** to recognize the new Symbolic Moment sections:
- Added: `'meter'`, `'landing'`, `'check'`, `'drivers'` to section IDs
- Helper functions: `parseSymbolicMeterData()`, `parseLandingData()`, `parseDriversData()`
- Dual rendering path:
- **New format:** Uses `SymbolicMomentReadingSurface` component
- **Legacy format:** Falls back to original signal/map/voice/translation bubble (for backward compat)

### State Management (page.tsx)

Added suppression logic for dormant overlays:

- **`hasActiveSymbolicMomentReading()`** — Detects if the latest message contains new Symbolic Moment sections
- When active reading exists:
- Dormant meter ribbon is hidden
- Balance Meter pill is suppressed
- Only the active reading surface is foreground
- **Rule:** One primary state visible at a time

## Breaking Changes

None. The refactoring is **additive**:
- Existing "legacy" Symbolic Moment format (signal/map/voice/translation) still works
- New format is recognized and rendered via the new reading surface
- Old Raven prompts continue to work without modification
- Backward compatibility maintained for all existing reads

## Acceptance Criteria Met

✅ Active reading no longer looks like a promo card or dashboard tile
✅ Reading is scan-friendly on mobile
✅ Signal, Meter, Landing, Voice, and Check are visually distinct
✅ Drivers are hidden by default (disclosed via chevron)
✅ Chamber names always shown (mapped to poetic labels)
✅ Repetition reduced (copy validation guards against duplication)
✅ Technical footnote material is backstage by default
✅ Reading feels like instrument output, not a boxed feature
✅ Dormant/awaiting overlays suppressed when active reading exists
✅ Mobile responsiveness: clean line lengths, high contrast, easy taps

## Files Changed

### New Files
- `vessel/src/components/chat/SymbolicMomentReadingSurface.tsx` — New reading surface component
- `vessel/src/lib/raven/symbolicMomentFormatting.ts` — Copy validation utilities

### Modified Files
- `vessel/src/components/chat/RavenStructuredReply.tsx`
- Added new section types: meter, landing, check, drivers
- Added parsing helpers for new format
- Dual rendering path (new surface vs. legacy bubble)
- `vessel/src/app/page.tsx`
- Added `hasActiveSymbolicMomentReading()` detection
- Updated state logic to suppress dormant overlays when active reading exists

## Frontstage Order (Preserved)

As specified, the new reading surface enforces this order:

1. Signal
2. Meter
3. Landing
4. Voice
5. Check
6. Drivers (collapsed)

## Backend Contract (Unchanged)

- Transit math ✓
- Measurement logic ✓
- Relocation / landing logic ✓
- Sealed backend order: force → measurement → landing → translation ✓

## Next Steps for Raven Prompt Writers

To generate new Symbolic Moment readings with the improved format:

```
Signal:
[One plain human line about the day]

Meter:
Symbolic Moment · Mag X · Bias Y · Vol Z

Landing:
[Chamber Name] ([house number])
[One grounded sentence about where the load lands]

Voice:
[Two short paragraphs max, specific and plain]

Check:
[One falsifiable question]

Drivers:
Background Climate
· [Driver 1]
· [Driver 2]

Immediate Weather
· [Driver 3]
```

Validation will catch overstatement, repetition, and meter contradictions.

## Testing Notes

- No build errors (typecheck passes)
- Component renders correctly in both formats
- Copy validation guards work as expected
- Mobile layout is responsive and readable
- Accessibility maintained (text contrast, tap targets, no blur overlays)

## Design Philosophy

The refactoring embodies this principle: **The reading is the primary object.** Not a card. Not a tile. Not a feature box. A surface where the instrument speaks plainly, grounded in measurement, clear in landing, quiet in tone.

---

**Session:** https://claude.ai/code/session_01XvYeEZjKU1rS7KWUTh1DQS
172 changes: 172 additions & 0 deletions CHANGELOG_VOICE_CORRECTION_V2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Symbolic Moment Voice Correction (v2) — Changelog

**Date:** 2026-04-26
**Branch:** `claude/complete-opus-implementation-exjj7`
**Summary:** Completed the voice correction pass for Raven's Symbolic Moment readings. This pass refines the reading voice itself to center named astrology, rich symbolism, and honest boundary auditing.

---

## Overview

The first pass (Task 1) refactored the UI/layout from a dashboard card into a primary reading surface with proper frontstage order (Signal → Meter → Landing → Voice → Check → Drivers). This second pass refactors the *reading voice itself* to ensure:

1. **One flowing paragraph** — no labeled chunks, one continuous astrological thought
2. **Named astrology stays visible** — planets, aspects, and chamber names in the prose itself
3. **Rich symbolic language** — never flatten to weather-app phrasing
4. **Honest boundary auditing** — three plainly-named classifications for user testimony (Within Boundary / At Boundary Edge / Outside Symbolic Range)
5. **Listening mode after the check** — Raven stops probing; the instrument reads zero cleanly

---

## Key Changes

### Files Modified

#### 1. `vessel/src/app/api/raven-chat/promptLines.ts`
Added three new voice rules to the `fieldReportRuleLines` array:

- **RICH SYMBOLISM LAW**: Ground prose in interesting, rich symbolic language that invites users to think about the shape of their day. Never flatten to flat weather-app phrasing.
- **POST-CHECK LISTENING LAW**: After the narrow falsifiable check, Raven stops probing. No Barnum-effect follow-up fishing.
- **SST AUDIT LAW**: When the user replies with testimony to the check, audit into one of three plainly-named classifications:
- *Within Boundary (The Direct Hit)* — testimony aligns with predicted landing; validate without celebrating
- *At Boundary Edge (The Paradox)* — testimony sits at the margin or inverts the prediction; name the anomaly plainly
- *Outside Symbolic Range (The Signal Void)* — testimony shows no resonance; accept the non-resonance; "the map is silent here; the instrument reads zero"

#### 2. `vessel/src/app/api/raven-chat/route.ts`
Mirrored the three new voice rules into the route.ts `fieldReportRuleLines` array to ensure consistent enforcement across the prompt pipeline.

#### 3. `vessel/src/lib/raven/symbolicMomentTranslation.ts`
*(No changes in v2; created in v1, verified canonical chamber names match route.ts contract)*

- `PLANET_CONSEQUENCE`: Symbolic meaning of each planet (Neptune = obscures/diffuses; Pluto = deepens/intensifies; etc.)
- `ASPECT_QUALITY`: How two planets relate (conjunction = fuses/amplifies, opposition = pulls against/polarizes, etc.)
- `COMMON_ASPECT_PHRASE`: Polished fallback phrases for frequent pairings (e.g., "Sun square Sun puts friction in the will…")
- `CHAMBER_META`: Canonical Woven Map house names (1/The Gate, 2/The Store, … 12/The Shell) with life-domain referents
- `BANNED_FRONTSTAGE_TERMS`: Internal-engine vocabulary never visible in normal mode ('field', 'current', 'pipeline', 'sealed geometry', 'protocol', etc.)
- Helper functions: `formatChamberLabel()`, `chamberLifeDomain()`, `chamberShortForm()`, `phraseForAspect()`

---

## Before/After Examples

### Example 1: Unified Reading Paragraph

**Before (v1 output):**
```
Signal: Mercury square Mars — sharp thinking meets friction.
Landing: The 3rd house — daily exchanges and quick decisions.
Voice: This tension tends to turn ordinary conversation into sharp friction.
Check: Does that match where you feel the static?
```

**After (v2 output):**
```
Mercury square Mars puts friction in thinking and speech right now, making even quick exchanges feel more loaded than they should. This looks more likely to land in the 3rd house — The Path — around daily exchanges and conversations, where the usual flow might feel tighter or more prone to misfire. Is that where the static is landing, in your daily speech and exchanges, or does it miss?

Why this read?
- Mercury square Mars (friction in thinking/speech)
- 3rd house placement (daily exchanges, communication)
```

**Key differences:**
- One flowing paragraph instead of labeled chunks
- Named planets and aspects visible in the prose ("Mercury square Mars")
- Symbolic consequence immediately translated ("friction in thinking and speech")
- Chamber name paired with life-domain referent ("3rd house — The Path — around daily exchanges")
- Rich phrasing ("tighter or more prone to misfire") instead of generic ("feels tense")
- Single narrow falsifiable check on its own line
- Technical drivers moved to collapsed disclosure

---

### Example 2: Rich Symbolism vs. Weather-App Flatness

**Anti-example (what we avoid):**
```
Neptune is making things unclear. There's some confusion happening. It might feel foggy.
```

**What v2 requires:**
```
Neptune opposite Pluto makes the deeper background harder to see clearly, softening edges where intensity is concentrating below the surface. You're working with obscured sight and hidden weight at the same time — what should be clear is diffusing, what should stay private is pulling upward. This looks more likely to land in the 8th house — The Core — around shared money, trust, intimacy, and heavier emotional currents.
```

**Why:**
- Named planets and aspects visible
- Symbolic consequences explained ("what should be clear is diffusing", "what should stay private is pulling upward")
- Chamber name + life domains ("8th house — The Core — around shared money, trust, intimacy")
- Makes the user think about the shape of their day, not just that "it's cloudy"

---

### Example 3: Boundary Audit Classifications (Listening Mode)

**Check question:**
```
Is that where the pressure is landing — in shared trust and deeper obligation — or does it miss?
```

**User replies with:** `"Actually, the tension is more in my career. My boss is making decisions without consulting me."`

**Within Boundary response (Direct Hit):**
```
The 10th house is exactly where this would show — The Canopy — your public standing and authority. When the deep intensity (Pluto) meets the obscured sight (Neptune), it often lands in how decisions are being made above you or outside your circle. That's a direct read.
```

**At Boundary Edge response (The Paradox):**
```
That's interesting — the geometry points to shared trust and deeper currents (8th house), but you're reporting the pressure in authority and career structure (10th house). The two aren't separate; the boss dynamic may actually *be* a trust/intimacy edge disguised as a chain-of-command issue. The 10th is where the 8th shows its teeth in public.
```

**Outside Symbolic Range response (The Signal Void):**
```
The sealed geometry doesn't pick up a career or authority signal this turn. Neptune opposite Pluto isn't landing in your 10th-house space based on the timing. The map is silent there; the instrument reads zero. Something else is driving the boss dynamic, or the transit timing for that particular load is different than the one this reading is tracking.
```

---

## Voice Rules Added

### RICH SYMBOLISM LAW
Ground the prose in interesting, rich symbolic language that invites the user to think about the shape of their day. Never flatten to flat weather-app phrasing like "it may be raining today" or "things might feel heavy." Keep the symbolism alive — explain what a condition *means*, not just that it is present. Make the user think.

### POST-CHECK LISTENING LAW
After the narrow falsifiable check, Raven stops probing. No follow-up fishing questions, no Barnum-effect hedging like "if not in your body, then in your pocketbook?", no re-framing to keep a miss looking like a hit. The instrument reads or does not read. If the user says the check missed, Raven enters listening mode.

### SST AUDIT LAW
When the user replies with testimony to the check, audit their reply against the sealed geometry into one of three plainly-named classifications:

1. **Within Boundary (The Direct Hit)** — the testimony aligns with the predicted landing; validate the alignment without celebrating or gaslighting
2. **At Boundary Edge (The Paradox)** — the testimony sits at the margin or contains an inversion of the predicted pattern; name the anomaly plainly
3. **Outside Symbolic Range (The Signal Void)** — the testimony shows no resonance with the sealed condition; accept the non-resonance; "the map is silent here; the instrument reads zero"

Never deflect. Never gaslighting. Never pivot to a new read to save face. A falsifiable check must be willing to fail.

---

## Testing Notes

- Typecheck: passes cleanly
- Builder/debug mode (`?builder=1` or localStorage `raven_builder_mode=1`) can still show scaffolding and banned terms for diagnostic purposes
- Frontstage mode scrubs banned terms at render time via `scrubBannedTermsForFrontstage()` as last-ditch guard
- Chamber name mapping aligns with canonical Woven Map contract: 1/The Gate, 2/The Store, 3/The Path, 4/The Root, 5/The Forge, 6/The Field, 7/The Mirror, 8/The Core, 9/The Horizon, 10/The Canopy, 11/The Grove, 12/The Shell
- Unified reading paragraph + check + drivers disclosure now the standard output format
- Backward compatibility: legacy signal/map/voice/translation sections still render in old bubble if payload includes them; new unified format takes precedence

---

## Next Steps

- Monitor Gemini prompt assembly for consistent rule application
- Collect user feedback on richness and clarity of new prose
- Validate SST boundary classifications are being applied correctly when users reply to checks
- Consider refinement to "At Boundary Edge" classification handling based on field feedback

---

## Branch & Commit

- **Branch:** `claude/complete-opus-implementation-exjj7`
- **Commits:**
- Task 1 (Card-to-Reading-Surface refactor): `ee60f21` [committed earlier]
- Task 2 (Voice correction v2): [this work, to be committed and pushed]
Loading