# Sapien Proof of Quality Docs Source site: https://sapien-ai-docs-production.up.railway.app This file concatenates the current public docs into one agent-readable context file. --- # What is PoQ URL: https://sapien-ai-docs-production.up.railway.app/start/introduction Source: docs/current/start/introduction.md # What is PoQ **Proof of Quality (PoQ) is a verification layer for AI work.** You define quality as a rubric, a panel of independent validators scores each item against it, consensus resolves one verdict per item, and PoQ seals the rubric, outcome, and level of agreement as a permanent onchain attestation. Instead of asking anyone to trust an internal review process, PoQ records how the decision was reached — and anyone can verify that record. PoQ sits on top of the evaluation, audit, and review workflows you already run. It doesn't replace your tools or experts; it preserves how quality was judged so the claim can travel with the work. _Interactive on the website: a work item travels Define (rubric applied) → Validate (independent validators score it and converge to consensus) → Attest (the verdict is sealed onchain in a signed PoQ Report)._ ## Why verification matters A score tells you what was decided, not why. As AI work moves between teams and organizations, customers, partners, auditors, and regulators inherit the conclusion — but rarely the standard, the evidence, or the level of agreement behind it. PoQ attaches that record to the claim itself, so a quality claim no longer depends on the credibility of whoever made it. :::figure{src="trust-vs-verify" title="The same quality claim with and without its record: a bare score must be taken on faith, while a score carrying rubric, evidence, agreement, and a signature can be checked by anyone" caption="A bare score must be taken on faith. A PoQ-backed score carries its rubric, evidence, agreement, and signature — and anyone can check it."} ::: ## What teams use PoQ for Any workflow that depends on review benefits from a verifiable record of that review. :::figure{src="use-case-grid" title="Four places teams use PoQ: labeling and annotation, AI and agent evaluation, expert and audit review, and internal QA" caption="The work differs; the problem is the same. Once a review ends, its reasoning usually disappears — PoQ keeps it."} ::: ## Experts, agents, and scale Having experts review every item is the gold standard — and it is slow and expensive. PoQ makes the fast path trustworthy instead: panels mix human experts with AI agent validators, [consensus](/validate/consensus-explained) resolves each item, and only split panels escalate to experts. Both kinds of validators see the same rubric and evidence and are scored the same way. The attestation is what makes this automation viable — you don't have to trust the automated review, because you can verify it. :::figure{src="experts-vs-automation" title="Two ways to review a large batch, compared on cost and time: an expert pass on every item is slow and expensive with trust resting on reputation, while a consensus panel of experts and AI agents with escalation is fast and cheap with trust resting on the attestation" caption="Expert review of everything doesn't scale. Consensus panels with agent validators do — and the signed attestation is why the fast path can be trusted."} ::: ## What you get You bring intent and a folder of data. PoQ returns a signed [PoQ Report](/validate/poq-report): one verifiable record of what was reviewed, by whom, against what rubric, and with how much agreement. :::figure{src="poq-steps-output" title="From input to output: you bring data and intent, PoQ runs the pipeline, you get a signed PoQ Report" caption="You bring intent and data; PoQ compiles a spec, builds review items, scores them by consensus, and returns a signed PoQ Report."} ::: That signed report is a real artifact — open the [example PoQ Report](/example-report/poq-report.html) to browse one now, or run `poq verify` against it offline. :::details{title="The pipeline, step by step"} | Input | What happens | What you get | | --- | --- | --- | | Your intent | You describe the work in plain language, by writing a [`poq.md`](/build/defining-your-spec) brief or talking it through with the conversational agent | A human-readable project brief | | `poq.md` | The engine compiles your brief into a spec | An executable, deterministic [`poq.toml`](/build/defining-your-spec) | | Your data folder | [Ingestion](/build/supported-data-types) reads your files | Datapoints - one row is one review item | | Datapoints | [Validators](/validate/validation-ui) claim items, inspect the evidence, and answer the rubric | Per-dimension scores, each normalized to `0-100` | | Scores | [Consensus](/validate/consensus-explained) resolves each dimension and escalates split panels | One verdict and a consensus strength per item | | Verdicts | Each item's final verdict is sealed onchain and rolled up | A signed [PoQ Report](/validate/poq-report) | | PoQ Report | Anyone runs `poq verify` | Offline confirmation the report is authentic and unaltered | ::: ## Quickstart Ready to try it? The [Quickstart](/start/quickstart) creates your first project [in the UI](/start/quickstart#create-a-project-in-the-ui) or [via the API](/start/quickstart#create-a-project-via-the-api) in a few minutes. ## See also | Page | Description | | --- | --- | | [The PoQ workflow](/build/poq-workflow) | The Define, Validate, Attest flow in full | | [Define your spec](/build/defining-your-spec) | The three ways intent becomes an executable `poq.toml` | | [Supported data types](/build/supported-data-types) | What files ingestion understands and how datapoints are formed | | [Validation interface](/validate/validation-ui) | What validators see and how they answer the rubric | | [How consensus works](/validate/consensus-explained) | Dimensions, strength, and escalation | | [PoQ Report](/validate/poq-report) | What the report contains and how to verify it offline | --- # Quickstart URL: https://sapien-ai-docs-production.up.railway.app/start/quickstart Source: docs/current/start/quickstart.md # Quickstart Create your first PoQ project: bring your data, describe the validations you want, and get your datapoints ready for review. Two paths get you there: | Path | Use it when | | --- | --- | | [In the UI](#create-a-project-in-the-ui) | You want visual previews and the fastest way to a first project | | [Via the API](#create-a-project-via-the-api) | You want PoQ inside an existing workflow, driven by code or an AI agent | Both paths follow the same [PoQ workflow](/build/poq-workflow): Define, Validate, Attest. The steps below cover Define. From there, validators score each datapoint against your rubric, and the engine seals the outcome into a signed [PoQ Report](/validate/poq-report). ## Create a project in the UI | Step | Action | | --- | --- | | 1 | Log in to PoQ with your email [here](https://poq.sapien.io/). | | 2 | From [the Dashboard page](https://poq.sapien.io/dashboard), click the `New Project` button in the upper right corner. | | 3 | Select the `Custom dataset folder` option, click `Pick folder`, and choose the folder that contains your data artifacts and a `poq.md` file describing the validations you want performed in plain language. | | 4 | Review the generated validator preview UI and iterate until it gathers the desired data. | ## Create a project via the API You need an [API key](/integrate/api-keys) and a JSON project spec (a mirror of [poq.toml](/reference/poq-toml)): | Step | Action | | --- | --- | | 1 | Create an API key at [API Keys](https://poq.sapien.io/originator/api-keys). Copy the token, which is shown only once. | | 2 | Verify connectivity with `GET https://poq.sapien.io/developer/v1/ping`, passing your key as a bearer token. A valid key returns `{ "pong": true }`. | | 3 | Create a project with `POST https://poq.sapien.io/developer/v1/projects`, sending `name` and `spec` (JSON). | | 4 | Open an upload session on the new project, declaring each file with `relPath` and `size`. | | 5 | `PUT` each file's bytes to its presigned `uploadUrl` (no auth header on these PUTs). | | 6 | Call `process` on the session, then poll `status` until the ingest run finishes. | The same workflow is available over MCP for AI agents. See the [MCP server](/integrate/mcp) reference and start with its `get_started` tool. ## See also | Page | Description | | --- | --- | | [The PoQ workflow](/build/poq-workflow) | How data flows from project definition to attestation | | [API keys](/integrate/api-keys) | Key lifecycle, authorization, and security | | [Developer API](/integrate/developer-api) | Full HTTP endpoint reference | | [MCP server](/integrate/mcp) | Tool catalog and client setup | --- # The PoQ workflow URL: https://sapien-ai-docs-production.up.railway.app/build/poq-workflow Source: docs/current/build/poq-workflow.md # The PoQ workflow Every PoQ project moves through the same three phases: you **Define** the work, validators **Validate** it, and the engine **Attests** to the outcome in a durable report that can be verified. :::figure{src="poq-workflow" title="The PoQ workflow: Define, Validate, Attest" caption="Phases of a PoQ project."} ::: The Attest phase ends in a real artifact you can hold: open the [example PoQ Report](/example-report/poq-report.html) (also as [plain text](/example-report/poq-report.txt)) to see what a project produces. ## 1. Define Project definition turns a dataset into reviewable work. You start with intent: what needs review, what evidence validators should see, and what "good" means. That intent becomes the `poq.toml` spec that drives the project, in one of three ways, in order of precedence: - A [spec-compliant `poq.toml`](/reference/poq-toml) you provide is used directly as the source of truth. - A plain-language [`poq.md`](/build/defining-your-spec) brief (or a `poq.toml` that fails to compile) is handed to the engine, which drafts the `poq.toml` for you. - With no spec provided, the **conversational agent** walks you through the decisions in a guided chat and drafts the `poq.toml` as you go. Whichever path you take, the spec defines the whole workload: how inputs are ingested and merged into datapoints, what evidence and instructions validators see, the rubric they score, which validator classes are eligible and how work is routed to them, and when the engine escalates for more review. ## 2. Validate Validation is the human and agentic expert review step. Validators claim assigned datapoints, inspect the evidence, and answer according to the rubric. The UI and API present the rubric in several modalities, such as choices and numeric scales, but every answer resolves to a `0-100` score. Validators do not enter a quality score directly. From their rubric scores the engine derives two independent `0-100` ratings for each datapoint: a **Quality Rating** (the answer the panel landed on) and a **Consensus Strength** (how tightly they agreed). See [How quality is measured](/validate/quality-rating) for how to read the two together. Consensus Strength drives what happens next. When it is strong enough, the datapoint finalizes. When it is weak, the datapoint can **escalate**, adding validators (often a more senior class) who re-score it. Escalation runs only if your spec defines it; otherwise the datapoint resolves on the answers already collected, with any disagreement recorded. Both ratings are recorded on the datapoint and carried into the report. See [How consensus works](/validate/consensus-explained) for the mechanics. ## 3. Attest Attestation turns the resolved scores into a durable artifact. Once a datapoint has received all required validator inputs, the engine records the final outcome and builds the [PoQ Report](/validate/poq-report), the artifact a customer, auditor, or downstream system can inspect later. It is one signed payload, delivered as readable text, a designed HTML page, JSON, or a bare signature, and it can be [verified offline](/validate/poq-report#verifying-a-report). From the report, anyone can: - Inspect what was reviewed - See how validators answered - Check the consensus outcome - Verify the report is authentic and unaltered - Use the report downstream --- # Define your spec URL: https://sapien-ai-docs-production.up.railway.app/build/defining-your-spec Source: docs/current/build/defining-your-spec.md # Define your spec PoQ projects start as intent and become configuration. Every project runs on one artifact: `poq.toml`, the executable, deterministic spec the engine reads. Everything else on this page is a way of arriving at it. ## Three ways to get a spec You can arrive at `poq.toml` from any of three starting points. When you upload a folder during project creation, PoQ scans it for spec artifacts and picks the path for you, in order of precedence: | What you bring | What PoQ does | | --- | --- | | A finished [`poq.toml`](#poqtoml) | Validates it and uses it directly. No model is involved. | | A plain-language [`poq.md`](#poqmd) brief | Compiles it into a `poq.toml` draft for you to review. | | Nothing but your data and your intent | Opens the [conversational agent](#conversational-agent), which interviews you and drafts the spec with you. | All three end at the same place: a valid `poq.toml` that you review before the project runs. `poq.toml` wins over `poq.md` when both are present. If the `poq.toml` is invalid and a `poq.md` is present, PoQ compiles the brief instead of blocking you. If it is invalid and there is no brief to fall back on, you get the validation errors and nothing is created. > [!NOTE] > You do not have to upload a file. You can paste a brief or a spec into the project-creation flow, and pasted content takes precedence over whatever was in the folder. ## Key information for spec derivation Whichever path you take, the spec has to settle the same decisions. Knowing them in advance makes every path faster: the agent will raise them as questions, your `poq.md` should describe them in plain language, and your `poq.toml` must declare them as parameters. | Decision | What it settles | Required? | | --- | --- | --- | | **Validation goal** | What a validator decides about one item | Yes | | **Ingestion** | Which files become datapoints, how they join, which fields are canonical | Yes | | **Evidence** | What each validator sees, such as markdown, code, images, source links, and facts | Yes | | **Rubric** | The dimensions scored, each with a scale and answer labels | Yes | | **Validator count** | How many validators review each datapoint by default | Yes | | **Reward** | What each validation slot pays, in USD | Yes | | **Validator classes** | Named tiers or specialists, human or AI, with their own rewards and rules | Only when the work needs them | | **Qualifications** | Credentials a validator must hold to claim an item | Only when the work needs them | | **Routing** | Which items go to which class of validator | Only when the work needs them | | **Escalation** | What happens when a panel disagrees, such as adding reviewers or a senior tier | Only when the work needs them | | **Consensus weighting** | Whether some validators' answers count for more than others | Defaults to equal weight | | **Attestation** | How verdicts are sealed and reported | On by default | Without the required rows, a spec will not validate. The optional rows are where most projects get complicated, so add them only when the work calls for it. > [!TIP] > Validator classes and consensus weighting are separate decisions. Adding a senior class puts senior reviewers on the panel. Consensus weighting makes their answers outweigh everyone else's. Most projects want the first without the second. ## Conversational agent The conversational agent defines a spec with you inside the app, without you writing either artifact by hand. It is the path when you have data and intent but nothing written down. It works in two stages: | Stage | What the agent does | | --- | --- | | Decide | Reads your uploaded data, proposes the validation goal, evidence, and rubric in plain language, and asks you to confirm what it cannot infer | | Author | Turns the confirmed decisions into `poq.toml`, then keeps editing that spec as you ask for changes | Once the agent has produced a spec, you can ask for changes in plain language, such as "make the rubric stricter" or "add a second reviewer". It revises the existing TOML rather than starting over. That same conversational editing is available after the spec is generated, whichever path produced it. The agent does not ask about everything. Ingestion is settled earlier, when you finalize your data. Validator qualifications and compensation are configured in a later project-creation step rather than in the conversation. ## poq.md `poq.md` is where the work is described in plain language. Use it when you are bringing a brief you already wrote, or when you would rather author intent outside the app and version it alongside your data. A brief should answer the [key information](#key-information-for-spec-derivation) above, as far as your project needs it: every required decision, plus the optional ones the work calls for. Compiling a brief into a spec is a single model pass, so read the draft it produces before you run the project. See example `poq.md` documents [here](/examples/poq-md). ## poq.toml `poq.toml` is the structured, specification-compliant version of the project intent. Hand-author it when you want precision, repeatability, or a spec under version control. The app drives the project based on this document. Features defined in the document include ingestion, validation, consensus, routing, and report generation. The [`poq.toml` specification](/reference/poq-toml) is the source of truth for every section, field, type, and default. Raw rubric answers are ultimately represented as a `0-100` value, even when validators are presented with labels or choices. See example documents [here](/examples/poq-toml). ## See also | Page | Description | | --- | --- | | [`poq.toml` Specification](/reference/poq-toml) | The source of truth for every field, type, and default | | [`poq.md` examples](/examples/poq-md) | Worked briefs for common project shapes | | [`poq.toml` examples](/examples/poq-toml) | Worked specs for common project shapes | | [Supported data types](/build/supported-data-types) | What files ingestion understands and how datapoints are formed | --- # Supported data types URL: https://sapien-ai-docs-production.up.railway.app/build/supported-data-types Source: docs/current/build/supported-data-types.md # Supported data types Ingestion is the single pipeline that turns your uploaded files into datapoints. Whatever you bring (a CSV of labels, a folder of JSON, a bundle of PDFs, or a long Markdown report), ingestion reads it, **normalizes it into one canonical format**, and produces datapoints from that canonical form. Every supported file type is just a different on-ramp to the same pipeline, not a separate, one-off behavior. ## The canonical format Under the hood, ingestion treats every source as a temporary table: - **Rows**: one row per item in the source (a CSV line, a JSON file, a Markdown section). - **Columns**: the fields inside each item (a CSV header, a JSON key, a captured value). When a project uses more than one source, [joins](/reference/poq-toml/ingestion) line those tables up into one wider canonical table before anything else happens, and `[ingestion.fields]` selects which columns are kept and what they are named. Once ingestion finishes, the temporary tables are discarded and only the canonical rows remain. The rule that ties everything together: > **One canonical row = one datapoint.** Validators never see your original files. They see the datapoints produced from the canonical table, and every downstream section of the spec (evidence, rubric, consensus) operates on that shape alone. This is why the choice of file type matters less than it first appears: CSV, JSON, `file_collection`, and Markdown all resolve to the same rows-and-columns form, and the sections below just describe how each one gets there. ## Supported file types Ingestion recognizes four source types. Each is a different way of feeding the canonical format, and each has its own rule for how a source becomes canonical rows: | Source type | File types | How it becomes canonical rows | | --- | --- | --- | | [CSV](#csv-csv) | `.csv` | Each row is already a canonical row | | [JSON](#json-json) | `.json` | Each file, or each element of an unnested array, becomes a row | | [File collection](#binary-or-opaque-files-jpg-pdf-) | `.jpg`, `.pdf`, and other binary types | Each file becomes a row, unparsed | | [Markdown](#markdown-files-md) | `.md` | Each section, split on a heading, becomes a row | ### CSV (`.csv`) The most direct path into the canonical format: a CSV is already rows and columns. One row per item, with an optional header row supplying the column names. Columns and formatting are detected automatically, and each row becomes one canonical row unchanged. | Case | Supported? | | --- | --- | | A single file such as `labels.csv`, with a header row and one row per item | Yes | | Combining multiple `.csv` files into one source | No: each CSV source reads exactly one file | | Unusual or inconsistent formatting, such as odd quoting or mixed encodings | No: rows must parse deterministically | ### JSON (`.json`) Each JSON file becomes one canonical row, with columns read from its object keys, including nested keys, addressed with a dotted path such as `rubric.severity`. If a file instead wraps an array of items under a key, ingestion unnests that array into one row per element, so a single file can expand into many canonical rows. | Case | Supported? | | --- | --- | | One datapoint per file, for example `doc-summary-001.json`, `doc-summary-002.json` | Yes | | A file holding an array of items, unnested into one datapoint per element | Yes | | An array nested under a key, such as `report.doc-summaries` | Yes | | Fields read from nested objects, such as `rubric.severity` | Yes | | More than one array unnested per source, or an array nested inside another array | No: flatten the inner array (for example, to a CSV) first | ### Binary or opaque files (`.jpg`, `.pdf`, ...) The `file_collection` upload type ingests a folder of binary files, such as images and PDFs. File contents are not parsed, so each file becomes exactly one canonical row whose column is a reference to the file itself. It is the same rows-and-columns shape as any other source, just with the file as the value rather than parsed text. | Case | Supported? | | --- | --- | | A folder of images, PDFs, videos, or other binary types, matched by a pattern such as `images/*.jpg` | Yes | | Mixed file types in one pattern, such as `images/*.{jpg,png}` | Yes | | Pointing at a single file | No: this source type is for folders containing many files | ### Markdown files (`.md`) Markdown reaches the canonical format the same way every other source does. It is simply split first. A long document is divided into separate sections wherever a chosen heading appears, and **each section becomes one canonical row**, exactly like a CSV line or a JSON file. The section splits are not a special case: they are just the step that turns one `.md` document into the rows the pipeline expects. The section's text lands in a `body` column, and a regex pulls any repeated header parts (an id, a title) into their own columns. See [`markdown_split`](/reference/poq-toml/ingestion#the-markdown_split-input-type) for the full field reference. | Case | Supported? | | --- | --- | | One or more text or report files, divided wherever a heading such as `## Doc-summary 1` appears | Yes | | Pulling a few extra labeled facts out of each section into their own columns | Yes | | Dividing sections into smaller pieces again | No: only one level of division is supported | ## Limits | Limit | Value | | --- | --- | | Maximum file size | 5 GB | | Datapoints per project | 1,000,000 | | File paths | Must stay inside the project's own folder | If your data comes in a format ingestion does not yet understand, contact the Sapien team. ## See also | Page | Description | | --- | --- | | [Define your spec](/build/defining-your-spec) | How `poq.md` and `poq.toml` work together | | [`poq.toml` Specification](/reference/poq-toml) | Field-level reference for `[[ingestion.sources]]`, `[[ingestion.joins]]`, and `[ingestion.fields]` | | [Quickstart](/start/quickstart#create-a-project-in-the-ui) | Creating a first project | --- # How consensus works URL: https://sapien-ai-docs-production.up.railway.app/validate/consensus-explained Source: docs/current/validate/consensus-explained.md # How consensus works Imagine a cooking contest. One dish comes out of the kitchen, and a **panel of judges** tastes it. Each judge fills out the same scorecard, and somehow all those opinions have to become **one verdict**: does this dish move on, or not? That is exactly the problem Sapien solves for every piece of work — one answer, one audit finding, one labeled image. A group of independent reviewers each give their scores, and the system turns those scores into a single, trustworthy result. The reviewers are called **validators**, and the process of turning their scores into one result is **consensus**. Crucially, a judge on the panel can be a **human expert _or_ an AI agent**. Both are first-class validators — they see the same rubric and evidence, score the same way, and are routed identically. A panel can be all human, all AI, or a mix, which is what lets a project move fast on volume and still bring expert judgment where it matters. Here is the whole idea in five plain steps. ## 1. The scorecard has several questions A good judge doesn't just say "I liked it." The scorecard asks separate questions: *Is it cooked properly? How is the seasoning? How is the presentation?* In Sapien, each of these questions is a **dimension**. A security review, for example, scores a finding on its **severity**, its **exploitability**, and how **certain** the validator is. Each dimension is judged on its own, then combined at the end. > [!NOTE] > Some questions matter more than others. The project creator gives each dimension a > **weight** — "seasoning counts double, presentation is just a tie-breaker." A dimension with > zero weight is **advisory**: collected for the record, but it never changes the verdict. ## 2. Each judge scores, and we measure how much they agree Once the judges submit their scores for a dimension, we don't just average them blindly. We look at how **tightly they cluster**. If everyone scored the seasoning 4 out of 5, that's strong agreement. If scores are all over the place, that's weak agreement. That clustering is the **strength** of the consensus — a number from 0% (total disagreement) to 100% (perfect agreement). Each **dimension** has its own bar the strength has to clear, the **required strength** (70% is a sensible default) — a tricky question can demand tighter agreement than an easy one. > [!TIP] > Sapien uses the **median** rather than a plain average to find the agreed score. One judge > who scored a 1 out of pure spite can drag an *average* down to a wrong middle value — but it > can't move the **median**. The crowd's real opinion wins. ## 3. If the judges are split, call in the experts What if the panel can't agree? You don't just flip a coin. You bring in **senior judges** — fewer of them, but more experienced — and their opinion counts for more. In Sapien this is **escalation**, and it works as a **ladder**. Validators come in **classes** (think *junior* and *senior*, or *AI panel* and *human expert*) — each class is human or AI, with its own vote weight. Round one is the base panel. If the item isn't **verified** — any required question still below its bar — the next rung of the ladder is added: more judges (often a more senior class) who re-score the whole item. Each step that runs adds its own described mix of classes, and because senior classes carry a higher **vote weight**, they can tip a split decision. The ladder keeps climbing until the item is verified or the steps run out. > [!TIP] > A common setup is an **AI ensemble** on the base round for speed and coverage, escalating to > **human experts** only when the agents can't agree — so people spend their time on the genuinely > contested items. :::figure{src="consensus-escalation" title="The escalation ladder: a base panel scores every dimension, and while any required dimension is below its bar the next class of judges is added to re-score, until the item is verified or the ladder runs out." caption="The base panel scores every dimension. While any required dimension is below its bar, the next rung adds more judges to re-score — until the item is verified or the ladder runs out."} ::: ## 4. Combine the questions into one verdict Each dimension now has its own resolved score. The system rolls them up into a single **aggregate** — a weighted blend, where the heavier questions pull harder. If every **required** dimension cleared its bar, the item is **accepted**. If even one required dimension is still unresolved, it isn't. > [!NOTE] > Some questions don't always apply. "How good is the fix?" is meaningless if the panel > already decided the bug isn't real. A dimension can be set to **skip** when another > dimension resolves a certain way, so it never drags the verdict around. ## 5. What keeps the scores honest The scores hold up because of *who* judges and *how they're held accountable*, not because of any single penalty. Three things do the work: - **A vetted workforce.** Validators are named and qualified before they review — added to a project's roster, then granted classes (like "senior reviewer" or "dermatologist") with a written justification, so vetting is auditable. Many also **calibrate** against expert reference items before live work. Accountability rests on who they are and their workforce contract — no funds at risk, no smart contracts. - **Rewards for good work.** Validators are paid for each completed verification, which aligns the incentive with careful, honest scoring. - **Reputation that follows them.** Each validator's record is tracked across verifications; landing near the resolved consensus over time builds standing and access to higher-value work. > [!TIP] > The lesson for a validator is simple: **score what you actually believe.** Your reputation is > built on agreeing with the resolved consensus across many reviews — guessing the crowd or > rubber-stamping is what erodes the standing that earns you the best work. ## Put it together | Contest term | Sapien term | What it controls | | --- | --- | --- | | Scorecard question | **Dimension** | One thing validators rate | | How much a question counts | **Weight** | Influence on the final verdict | | How tightly judges agree | **Strength** | Whether a dimension resolves | | The bar to pass | **Required strength** | How much agreement is "enough" | | Calling in expert judges | **Escalation / classes** | What happens when judges split | | A judge's track record | **Reputation** | Standing and access over time | That's the entire mechanism: **score each question → measure agreement → escalate if split → combine by weight → and lean on a vetted, well-rewarded, reputation-driven panel to keep it honest.** Want to feel how the knobs interact? **[Open the consensus simulator →](/examples/consensus-simulator)** and configure your own dimensions, validator classes, and thresholds, then watch the verdict change as you move the votes. ## See also | Page | Description | | --- | --- | | [How quality is measured](/validate/quality-rating) | The other rating: what the Quality Rating means and how to act on it | | [Validation interface](/validate/validation-ui) | How validators score each dimension on the 0-100 scale | | [PoQ Report](/validate/poq-report) | The record of the Quality Rating and Consensus Strength this produces | | [Consensus simulator](/examples/consensus-simulator) | Interactive playground for dimensions, classes, and thresholds | | [The PoQ workflow](/build/poq-workflow) | Where validation fits: Define → Validate → Attest | --- # How quality is measured URL: https://sapien-ai-docs-production.up.railway.app/validate/quality-rating Source: docs/current/validate/quality-rating.md # How quality is measured Validation returns **two independent numbers** for every datapoint, both `0-100`: - **Quality Rating** — *what* the panel concluded. Directional: `100` is high quality, `0` is low. - **Consensus Strength** — *how tightly* they agreed, regardless of the answer. See [How consensus works](/validate/consensus-explained). This page is about the Quality Rating, and how to read it against Consensus Strength. ## What the Quality Rating measures To judge quality, a panel of validators rates each item on a scale — say an AI's report graded from *Poor* to *Excellent*. The Quality Rating is **where the panel landed**, mapped onto `0-100`. The rubric decides which end is "good", so the rating carries the *direction* of the answer, not just how far apart the votes were. :::figure{src="likert-to-quality" title="A five-point Likert scale from Poor to Excellent laid along a 0-100 track. Five validators pick labels — one at Good, two at Very good, two at Excellent — and the panel's Quality Rating lands at 80, just past Very good." caption="Labels map evenly onto 0–100 (Poor = 0 … Excellent = 100); the Quality Rating is where the panel's picks land — here 80."} ::: > [!NOTE] > A high Quality Rating means high on *your* rubric — not that the output is objectively correct or safe. ## How it rolls up One report is usually scored on several dimensions (accurate, complete, clear), and the rating rolls up from there: :::figure{src="quality-rollup" title="A left-to-right rollup: one report's three dimension ratings — Accurate 90, Complete 70, Clear 85 — blend into a single datapoint Quality Rating of 82, and many such reports average into the dataset headline of 78." caption="Per-dimension ratings blend into one score per report (the datapoint); every report's score then averages into the dataset headline."} ::: ## Quality is not the same as agreement The two numbers are independent. A panel can **agree completely that a report is poor** — high Consensus Strength, low Quality Rating. :::figure{src="quality-vs-consensus" title="Two validator panels answering on the same Poor-to-Excellent scale. Both cluster tightly — one entirely on Poor, one entirely on Excellent — so Consensus Strength is high (96) in each, but the Quality Rating is low (6) for the Poor panel and high (96) for the Excellent panel." caption="Both panels agree just as strongly, so Consensus Strength matches — but they agree on opposite things, so the Quality Rating is far apart."} ::: That independence is why you keep both numbers: Consensus Strength is the one that *acts* — it decides whether a datapoint is settled or needs another look — while the Quality Rating is only ever reported. ## Reading the two together: the outcome quadrant Split each axis at **70** and every datapoint lands in one of four cells: :::figure{src="outcome-quadrant" title="The outcome quadrant: Quality Rating on the vertical axis and Consensus Strength on the horizontal axis, each split at a display threshold of 70. High consensus (right column) is reliable — Trustworthy when quality is high, Confidently rejected when quality is low. Low consensus (left column) is unsettled and should escalate — Contested when quality is high, Unclear when quality is low." caption="Consensus Strength (horizontal) says whether the result is reliable; Quality Rating (vertical) says the verdict. Right column = settled; left column = escalate."} ::: **Consensus Strength decides whether to trust the result** (right column = settled); **Quality Rating decides the verdict** (top row = passed). *Confidently rejected* is a healthy outcome — the panel reliably caught weak work. Pushing a datapoint rightward means [escalating](/validate/consensus-explained#3-if-the-judges-are-split-call-in-the-experts) to more validators: it raises consensus, but each added reviewer is paid — so escalate only where more confidence would change a decision. > [!NOTE] > The quadrant is just a quick read of the two numbers: the `0-100` Quality Rating and Consensus > Strength are the real outputs, and `70` is simply where the picture splits "high" from "low". ## Where you'll see it - **In the app** — on each datapoint, beside its Consensus Strength and outcome. - **In the CSV export** — a column you can sort and threshold. - **In the [PoQ Report](/validate/poq-report)** — the signed record, per datapoint and per dataset. ## See also | Page | Description | | --- | --- | | [How consensus works](/validate/consensus-explained) | The other rating: how agreement is measured and how split panels escalate | | [Validation interface](/validate/validation-ui) | How validators score each dimension on the `0-100` scale | | [PoQ Report](/validate/poq-report) | The record where the Quality Rating and Consensus Strength are certified | | [The PoQ workflow](/build/poq-workflow) | Where validation fits: Define → Validate → Attest | --- # Validation interface URL: https://sapien-ai-docs-production.up.railway.app/validate/validation-ui Source: docs/current/validate/validation-ui.md # Validation interface The interface shown to a validator renders data from the ingestion phase according to transformations in the project's specification (`poq.toml`). This page describes the evidence and evaluation elements that can be defined via the project's specification. :::figure{src="validation-interface" title="The validator interface: an evidence panel stacking several artifacts (an image, formatted text, a code snippet, and a source link) rendered from the project's spec, a rubric question answered with a single row of buttons, and a submit control; the chosen button maps to a value on a 0-100 scale." caption="What a validator sees: evidence rendered from the spec — one or more artifacts such as images, text, code, and source links — then one rubric question with a single row of answer buttons and a submit control. Every answer maps to a position on a 0-100 scale."} ::: ## What Sapien can show a validator Each `[[validation.evidence]]` block in the spec names a renderer `type` and wires it to ingested data. These are the supported renderers — pick one to see what it looks like: | `type` | Renderer | What the validator sees | | --- | --- | --- | | `markdown` | Formatted text | A page of formatted writing (Markdown) — typically the finding narrative. | | `image` | Image | One image, loaded from a URL field. | | `json_finding` | Fact sheet | A formatted JSON object, provided inline or by URL. | | `datapoint_facts` | Fact table | A list of labeled facts, side by side. | | `source_excerpt` | Source excerpt | A quoted excerpt — text pinned from an exact file in a repository. | | `source_link` | Source link | A pointer to an exact file, commit, and line. | | `image_comparison` | Image comparison | Two images at once — side by side, as a slider, or as a difference view. | | `bounding_box_overlay` | Annotated image | An image with labeled boxes drawn over the important parts. | | `video_clip` | Video | An inline video player, with an optional cover image and captions. | | `prompt_response_pair` | Prompt & response | A prompt and the answer it received, sometimes with a second answer for comparison. | For most of these, the project specification names exactly what to show, for example a particular picture or a particular fact, and Sapien checks that everything required has been provided before anyone sees it. If something is missing when it is time to show a validator, they see a message stating the evidence is missing, instead of a blank space. ## How a validator answers There is one kind of answer control: a row of buttons, and the validator picks one. There is no typing, no sliders, and no selecting multiple options. Only one button can be picked. What changes is how many buttons there are and what they say. - A 5-point or 7-point scale, for example from "Strongly Disagree" to "Strongly Agree", evenly spaced. - A list of custom labels, for example "Low", "Medium", "High", also spaced evenly. - A list of custom numbers, as long as it includes the lowest and highest possible score. Regardless of which type is used, every answer is converted to a number from 0 to 100. The buttons are a way of picking a position on that scale. This is what allows Sapien to compare answers to each other and determine whether reviewers agree, even when the questions look different on screen. A few rules keep this working. - Every question needs at least two buttons to choose from. - If an AI is one of the reviewers, the numbers behind the buttons must be whole numbers, with no fractions. A 5-choice scale always satisfies this, but some other combinations do not. A question can also be skipped automatically. If the answer is already determined by the data, Sapien fills it in and marks it as skipped instead of asking the validator. ## See also | Page | Description | | --- | --- | | [Define your spec](/build/defining-your-spec) | How `poq.md` and `poq.toml` work together | | [How consensus works](/validate/consensus-explained) | How 0-100 rubric answers become a verdict | | [`poq.toml` Specification](/reference/poq-toml) | Field-level reference for `[[validation.evidence]]` and `[[validation.rubric]]` | --- # PoQ Report URL: https://sapien-ai-docs-production.up.railway.app/validate/poq-report Source: docs/current/validate/poq-report.md # PoQ Report A PoQ Report is the durable artifact a PoQ project produces once all required validator inputs are in. It answers: **what was reviewed, by whom, against what criteria, and with what level of agreement.** It is produced in the [Attest](/build/poq-workflow) step as one canonical JSON payload (schema `poq.attestation/v1`), signed once with Ed25519 and delivered as text, HTML, JSON, or JWS — see [Formats](#formats). Text and HTML are **self-verifying**: content and signature travel in one file, verifiable offline. :::figure{src="poq-report-anatomy" title="Anatomy of a Proof Report: a miniature of the report document. The Result section leads with the two headline numbers — Quality Rating 78 / 100 and Consensus Strength 90% — above a customer-band label. Below them, each remaining section answers one question, and the fenced Ed25519-signed payload travels at the bottom of the same file." caption="One document, front-loaded with the two headline numbers; every section below answers one question, and the signature travels in the same file."} ::: > [!TIP] > Hold a real one while you read: the example report as [HTML](/example-report/poq-report.html) or [text](/example-report/poq-report.txt), plus its [signing key (JWKS)](/example-report/poq-report.jwks.json). The project is fictional, but the signature is real — Sapien's production key, the same one published at the `.well-known` endpoint below — and every command on this page works against these files. ## The two headline numbers **Quality Rating** is how good the quorums judged the work, on your rubric. **Consensus Strength** is how strongly they agreed — confidence in the rating, not a property of the work. Any label (for example `Verified · customer band`) is a customer-defined band over these two numbers; PoQ produces no verdict of its own. How they're computed: [How quality is measured](/validate/quality-rating) · [How consensus works](/validate/consensus-explained). ## What it asserts — and what it does not The report certifies that a Validator Pool was assembled per your Assurance Policy, and that a quorum drawn from it — one per datapoint — evaluated the enumerated datapoints against your rubric, reaching the numbers shown. Datapoints added after issuance are not covered. It is **a record of how the work was validated** — not an assertion that the work is objectively correct, safe, complete, or fit for any purpose. The Quality Rating is relative to the rubric you authored. ## Getting a report In the Portal, open the project's report page and pick a format from the download menu (originators and admins, once the project has finalized data). ## Verifying a report Anyone can verify a report **offline**, without trusting Sapien at read time: :::figure{src="poq-verify-checks" title="How poq verify proves a report offline: the artefact is one file with two layers — the readable render a human reads, and the fenced Ed25519-signed payload — joined by a parse/render round trip. The file flows through five checks: envelope, authenticity (against the publisher's key, fetched independently over TLS from the well-known JWKS endpoint), information, presentation, and fidelity — ending in a VERIFIED verdict, with no call to Sapien at read time." caption="One file, two layers, five checks. The parse/render round trip proves the readable layer carries exactly the signed information; the key arrives on an independent channel, so the whole loop closes offline."} ::: ### Verify one right now The panel below runs the real verifier — the same Go code as `poq verify`, compiled to WebAssembly — entirely in your browser. Verify the example report, then tamper with its Quality Rating and watch the `fidelity` check fail and name the field. You can also drop in any PoQ report of your own — it checks against Sapien's live published keys automatically. :::verify-panel ::: ### The signed payload The payload is canonicalized with JCS (RFC 8785) before signing, so the bytes are deterministic; all numerics are carried as strings; the JWS header's `kid` names the signing key. Any change to a covered value — in the JSON, the text, or the HTML — breaks verification. The readable formats declare an **envelope** version so a verifier knows the carrier before applying any grammar: | Envelope | Carrier | | --- | --- | | `poq.envelope/text-v1` | Readable render followed by the fenced JWS | | `poq.envelope/html-v1` | The designed HTML page, embedding the text artefact and tagging visible values | In text, the compact JWS sits between `-----BEGIN POQ SIGNED PAYLOAD-----` / `-----END POQ SIGNED PAYLOAD-----` fences after the render. In HTML, the same text artefact is embedded in a `