Simulix

Concepts · post-hoc

Post-hoc Reading

Every simulation completes with a calibrated verdict and per-segment crosstabs. Reading is what a careful person does with the transcripts afterward: notice the patterns, surface the reservations, pick out the hero quotes. A separate, smaller model does this work and returns observational prose under the

post_hoc
envelope.

What Reading is

A post-hoc layer that reads the transcripts a sim already produced and returns eight blocks of observational prose: synthesis, patterns, reservations, attractions, intensity, quotes, segment intensity, and across-runs comparisons.

It runs once the sim completes. It does not change the underlying responses, the verdict, or the per-segment numbers. It reads what is already there and writes a brief, careful account of it.

What Reading isn't

Reading does not extend or supersede the calibrated verdict. The verdict on

/results
remains the answer to "what did the population say?" Reading is the answer to a different question: "how did they say it?"

Reading is also not a predictor. Synthesis is past-tense; it describes what the respondents collectively expressed. It does not recommend action. It does not project future behavior. It does not pick winners.

Reading is not part of the workflow calibration. A workflow ships once its verdict matches the published-benchmark target (per CLAUDE.md I-3 & I-4). The Reading layer rides downstream of that gate; the gate doesn't apply to it.

Calibration boundary

The API surfaces the distinction structurally: Reading lives under

data.post_hoc
, separate from the calibrated fields (
verdict
,
by_segment
) on
/results
. A
calibration_boundary
object accompanies every Reading response and carries the disclaimer string we recommend you render verbatim:

These passages were read after the run completed by a separate small model. They are not part of the calibrated verdict above.

Treat anything under

post_hoc
as editorial: useful for shaping the conversation around the run, not a source of truth for the underlying numbers.

The eight blocks

Each block has its own lifecycle (queued, running, completed, skipped, failed, not_applicable) tracked under

block_status
. A small-n sim may render only a subset; a single sim with no sibling runs will leave
across_runs
as
not_applicable
.

BlockWhat it returns
synthesisOne observational past-tense sentence describing what the respondents collectively expressed.
patternsUp to 6 recurring clusters surfaced across transcripts, with supporting agent indexes and a directional lean.
reservationsUp to 5 specific concerns voiced by no-leaning respondents. Empty list is a valid result.
attractionsUp to 5 specific positives voiced by yes-leaning respondents. Empty list is a valid result.
intensity1-5 sentiment distribution with a median and an optional observational note about the shape.
quotesTwo hero quotes lifted verbatim — strongest yes, strongest no. Either may be null when no transcript qualifies.
segment_intensityPer-segment 1-5 distributions for cases with declared segments. Empty list when the case has no segments.
across_runsComparison against sibling runs of the same workflow. not_applicable when no siblings exist.

Stability contract

Three tiers govern how the contract may change between versions.

Stable (semver-major commitment — 12 month deprecation window)

  • The
    post_hoc
    envelope key as the calibration-boundary signal
  • The eight block names:
    synthesis
    ,
    patterns
    ,
    reservations
    ,
    attractions
    ,
    intensity
    ,
    quotes
    ,
    segment_intensity
    ,
    across_runs
  • Field names within each block payload
  • The
    calibration_boundary
    object shape + disclaimer string
  • Enum values for
    insights_status
    and
    block_status

Minor-version compatible (additive only)

  • New blocks under
    post_hoc
    (e.g. a future
    competitor_mentions
    block)
  • New optional fields on existing blocks
  • New enum values for
    block_status
    covering transitional states

Preview (may evolve before v1.0.8)

  • The exact text of disclaimer copy in places other than
    calibration_boundary.disclaimer
    (the disclaimer itself is stable)
  • Prose tone and length within each block (we may tighten ceilings based on production telemetry)
  • Confidence labels on Synthesis (currently
    sharp
    |
    soft
    ; a third tier is possible)

X-Simulix-Preview signal

Every Reading response includes:

X-Simulix-Preview: insights

The header marks the contract as in the "preview" bucket above. Read it as: "the shape may evolve once real production telemetry beds in." The stable + minor-compatible commitments hold regardless. The header is removed in v1.0.8 once the contract has settled.

Model + cost

Reading runs through Cloudflare Workers AI per Simulix's sole-provider discipline (CLAUDE.md I-1). The synthesis block uses Llama 3.3 70B; the seven other blocks use Llama 3.1 8B for the lower-reasoning tasks. The same model envelope as the sim itself.

Per-sim cost is bounded at roughly $0.05 mean, $0.10 hard ceiling. Per-tier monthly caps live at /docs/guides/integrating-reading#cost. The Reading layer adds no new data-exposure surface — the transcripts already flowed through Cloudflare during the sim.

Next