The five-dimension voice profile with evidence quotes and Preserve / Neutral / Challenge mentor steering, planned against the canonical mockup.
atticus-implementation.md:171 lists Voice Lab under “Explicitly out of v1 scope” — “leave it stubbed for v1.” Its Phase 9 is Launch prep. Meanwhile replan.md, marked Status: Active. Supersedes the original Phase-4-onward roadmap, makes Phase 9 = “Voice Lab + polish.”
Every Phase 9 reference in the source follows the replan numbering. The master plan is also ~3 months stale — it claims a 352-test suite; we’re at 671. This plan assumes Voice Lab is in. If that’s wrong, stop — the master plan currently says don’t do this.
| Decision | Resolution | |
|---|---|---|
| Surfaces that honor the profile | Draft synthesis, Critique findings, Composition advisor + ambient callouts. Discovery mentor turns excluded. | v1 |
Deterministic gates (RegisterBaseline → VoiceCeiling) | Left untouched. Voice Lab runs as a parallel qualitative layer. | v1 |
| Per-sample title + work type | Prerequisite — the samples panel and quote attribution can’t render without them. | v1 |
| Drag-and-drop ingest | Added. Formats stay TXT / Markdown / RTF / DOCX. | v1 |
| Register filter (All work / Fiction / Essays) | ~3× analysis cost; needs more samples per type than a new writer has. | deferred |
| “Profile updated” diff banner | Needs profile version history plus a second LLM pass. | deferred |
| Opt-in “include my Atticus drafts” | — | deferred |
| PDF · Google Docs link | Docs link is realistically its own plan (OAuth, fetch, token refresh). | deferred |
Three deferred features mean the register-filter row, the update banner, and the “Your recent drafts… Turn on” footer don’t render in v1. The upload zone’s format line must say .txt, .md, .rtf, .docx — not the mockup’s .txt, .pdf, .docx, or Google Docs link. A UI that promises formats it rejects is worse than a shorter list.
VoiceCeiling ships today and actively regenerates drafts scoring above your register. Two reasons not to feed Voice Lab samples in:
sentenceComplexity is weighted zero. A polished uploaded chapter sits far above a Discovery chat answer on lexical rarity too.Voice Lab therefore influences prompts, not scores.
No LLM, no UI. The current model holds one sample and actively deletes the others.
writeVoiceSample. It runs delete(stale) on every sibling row. Correct for a single-sample UI; in a multi-sample world it eats the library on every edit. The most dangerous existing line for this plan.title and workTypeRaw to VoiceSample + a VoiceWorkType enum with a computed wrapper — house convention, so new cases absorb via lightweight migration..other.addVoiceSample (appends), removeVoiceSample, renameVoiceSample, setWorkType.Renders what exists; no analysis yet. Shippable and honest on its own.
VoiceLabView replaces VoiceLabStubSurface — delete the stub rather than leaving both.AtticusTheme tokens; don’t reintroduce raw hex.× remove with confirmation — it’s destructive action on writer material.Pure, no LLM. Built and fully tested before anything calls a model.
VoiceDimension — exactly five fixed cases, not LLM-chosen. This is what lets your stance survive a re-analysis; the model fills in prose for known dimensions, it never invents the taxonomy.MentorStance: preserve / neutral / challenge, defaulting to neutral.VoiceAnalysis Codable value type with schemaVersion, stored as a JSON blob on VoiceProfile.analysisJSON — mirrors the voiceFingerprintJSON convention so the 5-dimension shape iterates without schema migrations.QuoteVerifier — every evidence quote must be a verbatim substring of the sample it’s attributed to, after normalizing whitespace, smart quotes, dashes, ellipses. Non-matching quotes are dropped, not displayed.
This is your own prose. A subtly paraphrased quote — the failure mode LLMs are most prone to — is instantly visible to the one person who wrote it, and it destroys trust in the whole profile. Reuse the existing substring-anchoring logic rather than writing a third one.
The LLM pass. Where the product risk lives.
VoiceAnalyzing protocol test seam, mirroring DiffSummarizing. Non-streaming: a discrete background job, not a conversation.RegisterBaseline.minimumContentWords — below the floor, say so plainly rather than producing confident prose from two sentences.The phase that makes this more than a mirror.
VoiceDirectiveBuilder compiles analysis + stances into a compact prompt block. Neutral dimensions emit nothing — only your deliberate choices speak, which keeps the default cheap and the block small.DraftGenerator.swift:6 already says “Voice Lab in Phase 9 replaces this”), Critique (a Preserve on rhythm must stop “break up these long sentences”), and Composition advisor + ambient callouts.cache_control: ephemeral block — it’s stable across turns, so cache it rather than re-billing per message.Including the one step tests can’t cover.
RegisterScorer.swift:30 that “Phase D calibration confirmed” the weights — that was analytical, not fixture-calibrated.// TODO(lens-shift) at ConceptViewModel.swift:1500, which replan.md gates on Voice Lab landing.synthesis-quality-gates.md for three months. This plan will hit the same wall.VoiceCeiling may regenerate a draft for being “elevated” while Voice Lab says Preserve on word choices. Independence avoids regression but doesn’t make them agree — same shape as the Callouts-vs-Critique conflict.