Analyzing past studies
Turn any uploaded study into charts and claims.
The throughline: you attach the study, Mavera computes the analysis. Tools read your study's already-computed aggregates (or the raw transcript text) as immutable facts and refuse to invent numbers. Each result is labeled code-computed vs model-analyzed so you always know what's a measurement and what's an interpretation.
The five analysis modes
| Mode | Tool | Use it when | Returns |
|---|---|---|---|
| Mine a transcript | mine_insights | You have the raw conversation (focus group, debate, IDI, an old call) | Chartables (convergence, polarization, sentiment arc) + steer/contradiction/branch signals |
| Synthesize an insight | synthesize_insight | You have a finished study's computed stats and want the typed write-up | Headline, code-derived confidence, CI-aware findings (each cites an aggregateId), drivers/objections, actions |
| Compare studies | compare_studies | You ran the same thing over time or across audiences | Pooled estimate, per-study weights, pairwise significance, trend, I² heterogeneity |
| Detect drift | detect_drift | You want to know if a metric moved between two runs | Δ, σ-magnitude, significance, direction, stable/moved/reversed |
| Back-test accuracy | measure_synthetic_accuracy | Reality came in and you want to know how right the prediction was | Correlation / MAE / bias vs realized, a published track record |
Step 1 — Attach the study
How you attach depends on what form the study is in.
A) It's a file (deck, PDF, survey export, spreadsheet)
Import it into a grounded Source. Supported: PDF, DOCX, PPTX, XLSX, CSV, TXT, MD (and Google-native docs from a connected drive).
{ "instanceId": "drive_main", "fileId": "1AbC...", "attachToProjectId": "proj_q3_research" }
# → a Source(file) with extracted text/tables, provenance + freshness, grounded into the vector store.
# List what you've imported:
POST /api/v1/tools/list_storage_sources { }Don't have it on a connected drive? Upload the bytes directly through the Files API (POST /api/v1/files) and analyze it there, or paste the transcript straight into mine_insights (next section) — no import needed.
B) It's a transcript you already have
You don't need to import anything — pass the turns straight in. The shape is the same for chat, a focus group, a debate, or a diary arc: an array of { speaker, text }.
C) It's a prior Mavera study
It already has a studyId and computed aggregates. Reference it directly in synthesize_insight, compare_studies, or detect_drift — no re-import.
Step 2 — Run the analysis (pick a mode)
Mode 1 · Mine a transcript → structured chartables + signals
The workhorse for "I have the words, give me the structure." Every chart number is derived from the text — never invented.
{
"turns": [
{ "speaker": "Maya", "text": "The onboarding felt endless. I almost gave up at step four." },
{ "speaker": "Devin", "text": "Same — but once it clicked the value was obvious." },
{ "speaker": "Priya", "text": "I never trusted the numbers it showed me." }
],
"topic": "onboarding friction",
"useLlm": true,
"llmMode": "identify"
}Returns two clearly-separated layers:
| Layer | basis | Contents |
|---|---|---|
charts | code-computed-from-transcript | kind ∈ share_bar · diverging_bar · sentiment_arc · theme_distribution — each a real count/share from the text |
signals | code-computed | kind ∈ steer · contradiction · divergence · branch (a ready-to-run follow-up prompt) |
llm (when useLlm) | model-analyzed | Deeper read in your chosen llmMode: mine (signals), identify (where opinions diverge now), find (hypotheses to test). Labeled as interpretation, not measurement. |
Tunables: maxSignals, minStrength (filter weak signals), topic (focuses theme extraction).
Mode 2 · Synthesize a finished study → a typed Insight
When the study already has computed aggregates, this writes the defensible insight around those numbers. It produces no statistics and rejects any uncited number in the prose.
{ "aggregates": "agg_set_q3pricing", "studyRunId": "run_8842" }
# → { insight: { headline, confidence, confidenceRationale,
# keyFindings:[{ text, aggregateId }], ← every finding cites a number
# drivers:[{theme,support}], objections:[...], recommendations:[...] } }confidence is derived in code from CI width × grounding strength × N × freshness — not the model's vibe. The confidenceRationale tells you which aggregate set the ceiling.
Mode 3 · Compare studies → meta-analysis
Same metric, two or more studies (over time, or across audiences). Reads each study's computed aggregate as fact and pools them.
{ "studyIds": ["run_apr","run_may","run_jun"], "metric": "purchase_intent", "groupBy": "time" }
# → { pooled: {mean, ci, n},
# perStudy: [{ studyId, label, value, weight }], ← inverse-variance weights
# betweenStudy: [{ a, b, significance:{pValue,...} }], ← every pair tested
# trend: [...],
# heterogeneity: { iSquared, tauSquared } } ← warns when studies disagree too muchIf heterogeneity.iSquared > 0.5 the studies disagree enough that a single pooled number is misleading — the tool flags it. That honesty is the point: it won't hand you a clean average over apples and oranges.
Mode 4 · Detect drift → did it move?
{ "metric": "nps", "baselineRunId": "run_q1", "currentRunId": "run_q2", "threshold": { "sigma": 1 } }
# → { delta, deltaZ, significance, direction: "up|down|flat",
# classification: "stable | moved | reversed" }This is the node inside scheduled trackers — wire it to a cron and get alerted only when a metric actually moves past your σ threshold (see Studies & trackers).
Mode 5 · Back-test accuracy → how right were we?
The flywheel. When the real-world metric lands, measure how well the synthetic prediction held up — per test type — and publish a track record.
{ "testType": "pricing", "feedBack": true }
# → correlation / MAE / bias of pre-launch predictions vs the realized metric.
# Track record any time:
POST /api/v1/tools/get_parity_history { }
# → latest overall parity per study type — "how much did these claims hold up".Related: run_parity_check scores a synthetic run against a real benchmark on the same questions (Pearson/Spearman); validate_with_humans routes a slice to real panelists for a hybrid check.
Step 3 — Export the structured analysis
Any Insight or Study becomes a board-ready artifact — with uncertainty preserved (CI whiskers), cited findings, and an optional evidence appendix.
{ "source": "insight_3391", "format": "pptx", "includeEvidenceAppendix": true }
# format ∈ pptx | sheets | pdf → a real, downloadable file (see Files API for download).Two pipelines worth memorizing
Old transcript → structured read → deck
mine_insights (turns) → synthesize_insight (the computed stats) → export_deck (pptx)Two runs over time → did it hold up → alert
compare_studies (trend) → detect_drift (baseline vs current) → measure_synthetic_accuracy (vs realized)The honesty contract, restated. code-computed numbers come from your study's aggregates or the transcript text. model-analyzed items are labeled interpretations. confidence is derived, not asserted. Uncited numbers are rejected from prose. High heterogeneity is flagged, not hidden. That's what makes these results something you can put in front of a board.