Back to Sourced
For researchers

Qualitative coding, with traceable numbers on the other end.

Sourced is a coding tool. You declare what you're listening for, run a corpus through it, and get back claims tied to quotes — plus optional per-dimension scores with coverage tags. Every number on the right-hand side traces back to a sentence on the left. The system does not invent evidence.

What you get back

Three layers, never mixed

Sourced separates evidence, claims, and scores at every step. Each is a different kind of truth. You can stop at any layer and still have something defensible.

Evidence

The exact words a participant said, with character offsets. The system never paraphrases evidence. If you can read it back to the participant unchanged, it's evidence.

Equivalent to the raw quote in qualitative coding.

Claim

A typed assertion the system makes about the participant, anchored to one or more pieces of evidence: dimension (what kind of thing), relation (how they relate to it — the frame's own vocabulary), confidence (0–1), value (what was said).

Equivalent to a code in thematic analysis or grounded theory.

Score

A per-dimension number derived from claims: density × average confidence. Reported alongside a coverage tag (thin / moderate / strong) so a thin score can't be mistaken for a strong one.

Equivalent to a construct estimate in mixed-methods reporting.

What's new

A deterministic reading layer under the scores

Alongside Evidence → Claim → Score, Sourced now ships a stance stack for conversational reading: hedges, questions, negation, agreement, and gated claim-to-claim relations — with the person's confirmations outranking any model assessment. Topic matching stays in embeddings; posture does not.

Four-layer epistemic model

  1. 01

    Evidence

    Immutable messages and spans — hash, offsets, verbatim quote. The LLM never rewrites this layer.

  2. 02

    Claims

    Proposed assertions with structured producer provenance. Born contestable; born unassessed.

  3. 03

    Assessments & relations

    Model support is separate from person governance. Claim relations stay proposed until a person confirms or dismisses them.

  4. 04

    Narratives

    Drafts only — portraits and reflections that cite claims and go stale when those claims are contested.

How reading works

Lexical and syntax detectors recover surface stance (hedge, commitment, negation scope, questions). Agreement reads confirm / reject / partial replies. Small NLI runs only on topic-matched prior claims — never free-range — and every relation is born proposed.

Ambiguous privacy cues quarantine first; mechanical phrases and API memory-off controls gate before any semantic work.

Try it now

Studio's VIA Lab previews character-strength evidence from a story without writing to memory. Local demos under examples/via_profile/ run the full SQLite loop with quotes, hashes, and governance.

The loop

Four steps. The audit step is where the work is.

A frame is rarely right on the first run. Sourced is built around the audit-and-sharpen loop most qualitative researchers already do — except the codebook lives in version control and the inter-rater comparison is run by command line.

01

Declare a frame

A frame is a YAML file with the dimensions you're listening for, written examples of what each one looks like (matches), and counter-examples (non_matches). The frame is your codebook. It is versioned and exportable.

02

Run the corpus

Send each participant text to /v1/observe. Each call produces a list of traces. Every trace carries the source quote, the dimension it matched, the posture, the confidence, and the method ID. This is your coded dataset.

03

Audit, then sharpen

Sample 20–50 traces. Mark each as core / secondary / incidental / wrong. Add the wrongs as anti-examples back into the frame and re-run. One round of sharpening typically moves accuracy 25–30 points. The audit loop is the work.

04

Export and report

Pull traces and scores out as JSON, CSV, or as a single export bundle. Every score links back to its claims; every claim links back to its evidence. The audit trail is the data — not a separate artifact.

Trust the numbers

Coverage before confidence

Every score ships with a coverage tag. A score with two traces under it is labelled thin. One with five or more is strong. A reviewer can decide whether to interpret a thin score; it's not hidden.

Provenance

Every score links to its claims. Every claim links to its evidence. Every piece of evidence is a quote with character offsets. You can reconstruct any score in the report from the source text alone.

Reproducibility

Frames are versioned. The same text against the same frame version produces the same traces. If you change the frame, the old run is preserved with its frame version stamped on it.

Portability

Export everything as a single JSON bundle: frame, traces, evidence, scores, audit history. Re-import into the next study or hand it to a co-author. The bundle is your data; we don't hold it back.

Honest limits

Sourced has not been published with a validity study. Inter-rater reliability against human coders, convergent validity against VIA-IS and Big Five, and discriminant validity against sentiment-only baselines are all open work. We label the tool honestly until those results exist.

Tradeoffs

When to reach for this tool

What this is good for

  • Coding journals, transcripts, reflective writing, intake forms.
  • Producing per-construct estimates for descriptive, exploratory, or formative work.
  • Scaling a thematic analysis to a corpus too large for hand-coding while keeping every quote citeable.
  • Building a codebook iteratively — the system surfaces unmodeled language as gaps you can name.

What this is not good for (yet)

  • Replacing validated psychometric instruments. The scores are construct estimates, not measurements.
  • Confirmatory hypothesis tests on small samples. Use it descriptively until you've done a reliability study.
  • Domains where the language differs sharply from the frame's training examples. Sharpen the frame first.
  • Anything where the participant has not consented to the corpus being processed by an LLM.
Run a corpus

Minimum viable study

Three commands. One participant. The shape of every study at any scale.

# 1. Declare your frame (your codebook)
cat > my_frame.yaml <<'EOF'
frame_id: study_alpha_v1
dimensions:
  - id: agency
    description: Statements about taking initiative or being acted upon
    matches:
      - "I decided to apply"
      - "I had no say in it"
    non_matches:
      - "the weather was bad"
EOF

# 2. Observe a participant text
curl -X POST $SOURCED_API/v1/observe \
  -H "Content-Type: application/json" \
  -H "X-Sourced-App: $APP_ID" \
  -H "Authorization: Bearer $APP_SECRET" \
  -d '{
    "person_id": "p_001",
    "frame_id": "study_alpha_v1",
    "source_id": "interview_1",
    "text": "I had been waiting months. Then one morning I just decided."
  }'

# 3. Pull the report
curl "$SOURCED_API/v1/frames/study_alpha_v1/report/p_001" \
  -H "X-Sourced-App: $APP_ID" \
  -H "Authorization: Bearer $APP_SECRET"
A worked example

39,347 experience reports, one command

The same four-step loop, run at corpus scale. The Erowid phenomenology study codes a public archive of psychedelic experience reports against phenomenology@1 — a frame of twelve dimensions (unity, ego dissolution, time distortion, noetic quality, ineffability…) detected from a corpus-grounded marker codebook, not hand-tuned keywords. It is the reference study for doing this yourself: the frame, the corpus config, and the run command all ship in the repo.

# The whole loop — corpus → signals → traces → review → stats — in one command.
# Frame + corpus config live in usecases/erowid_phenomenology.yaml.
sourced corpus usecases/erowid_phenomenology.yaml \
    --sample 200 --where "exp_id IN (SELECT exp_id FROM meq_scores)" \
    --meq-correlate --seed 7 --artifacts runs/erowid-pilot-200

# Artifacts (replayable, every score traces to a quote):
#   signals.db  traces.jsonl  doc_stats.csv  corpus_stats.csv
#   review_sample.csv  meq_correlations.csv  run.json

What the pilot produced

200 reports (sampled from the 568 with human MEQ scores) → 11,190 detection signals 1,522 promoted traces, in 4.6 minutes on a local embedding model. Each trace carries the exact sentence it fired on, its dimension, its relation (reports / denies / questions), and a confidence. Nothing is asserted without a quote under it.

time_distortion
0.98
body_load
0.95
noetic_quality
0.87
surrender
0.85
transcendence
0.83
unity
0.81
sacredness
0.81
fear
0.75
ineffability
0.67
ego_dissolution
0.67
entity_encounter
0.66

Corpus prevalence — fraction of the 200 reports with at least one trace on that dimension.

What it does — and doesn't — show

The pilot validates the data layer: the loop runs end to end, every trace is grounded in a span, and the artifacts are replayable. It does not yet claim construct validity. Against human MEQ subscales the local-embedding correlations are weak (best positive_mood r = +0.23 on prevalence) — consistent with prior work measuring this corpus (local AUC 0.476 vs OpenAI-direct 0.794). The honest read: the embedding space, not the method, is the current ceiling.

The pilot also surfaced its own next move — time_distortion over-fires at 30% of sentences because drug-narrative time-talk matches generic temporal markers. That is exactly the audit-and-sharpen step: the false positives become anti-examples in the frame, and the run repeats. The tool tells you where it's wrong.

Full write-up: docs/reports/2026-06-research-pilot.md. Frame and corpus config: usecases/erowid_phenomenology.yaml. Reproducible runbook: docs/RESEARCHER_GUIDE.md.

The numbers should be honest about where they came from.

Sourced is a translation layer from human language to traceable construct estimates. It is not a black-box scoring engine. The provenance is the contribution.