# Get Issues

- **Method:** `GET`
- **Path:** `/api/v1/runs/{run_id}/issues`
- **Operation ID:** `get_issues`
- **Tags:** artifact

The product defects the run found, each with its evidence and repro steps, and beside them how each
may be acted on: an issue whose reading says `may_file_ticket_alone` was reproduced by a replay and can
become a ticket as it stands; any other must be reported with its evidence and marked unconfirmed.

Answers from the moment the run exists: an empty list with the run's `status` while it is still going,
and a result only once that status is terminal.

## Effective servers

- `https://api.saram.sh`

  Saram

## Authentication

- **HTTPBearer**: HTTP bearer

  a Saram API key (`sk_saram_<env>_...`) or a person's AuthKit access token, as `Authorization: Bearer <credential>`. Both are told apart by shape and produce the same principal.

## Path parameters

- **`run_id` (required)**: `string`

## Responses

### 200 Successful Response

**Content type:** `application/json`

schema: `IssueList`, no additional properties

A run's issues: product defects the run found, each with its evidence, and beside them how each may be
acted on (`reading`). Only an issue whose reading says `may_file_ticket_alone` is a confirmed bug.

- **`issues` (required)**: `array`

  **Items:**

  schema: `Issue`, no additional properties

  A product defect the run found: what the product did wrong, where, in how many of the sessions that got there, with the evidence and the steps that reproduce it. `claim.verification.status` says what checked it, and only a `verified` issue - `reproducible: true` - may be filed as a ticket on its own. `description` is objective; `persona_rationale` is the persona's voice.
  - **`affected_sessions` (required)**: `array of string`
  - **`confidence` (required)**: `number`, minimum: `0`, maximum: `1`
  - **`description` (required)**: `string`
  - **`evidence` (required)**: `object`, schema: `Evidence1`, no additional properties

    What the issue rests on: the steps where sessions met it (`step_refs`) and, when the run kept them, screenshots, a clip of the session's video, a snapshot of the page, and the network requests and console messages around it.
    - **`step_refs` (required)**: `array`, minItems: `1`

      **Items:**

      schema: `StepRef`

      One step of one session: the session's id and the step's number within it. A finding points at the steps it rests on, and that session's step events say what happened at each.
      - **`session_id` (required)**: `string`
      - **`step_id` (required)**: `integer`
    - **`console`**: `(array of object) | null`
    - **`dom_snapshot`**: `string | null`, format: `uri`, minLength: `1`
    - **`network`**: `(array of object) | null`
    - **`screenshots`**: `array | null`

      **Items:**

      `string`, format: `uri`, minLength: `1`
    - **`video`**: `object | null`, schema: `Video`

      A clip of a session's video that shows the issue: where the video is stored (`ref`), and where the clip starts and ends, in seconds from the start of the recording.
      - **`ref`**: `string | null`
      - **`ts_end_s`**: `number | null`
      - **`ts_start_s`**: `number | null`
  - **`id` (required)**: `string`
  - **`location` (required)**: `object`, schema: `Location1`, no additional properties

    Where the defect is: the page (`route`), the element in words (`element_description`) or as a selector (`selector`), and the screen size it was seen at (`viewport`, WIDTHxHEIGHT).
    - **`route` (required)**: `string`
    - **`element_description`**: `string | null`
    - **`selector`**: `string | null`
    - **`viewport`**: `string | null`
  - **`reproducible` (required)**: `boolean`
  - **`severity` (required)**: `string`, possible values: `"low", "medium", "high", "critical"`

    Schema: `Severity`.

    How much the defect costs the people who meet it, from least to most: `low`, `medium`, `high`, `critical`. Rated by the judge from the sessions, and lowered one step when the replay did not reproduce the issue and it stands as persona-specific friction. The GitHub connector files only issues at or above its `min_severity_for_issue`.
  - **`type` (required)**: `string`

    Schema: `Type`. Known values, open (more may be added): `blocker`, `friction`, `confusion`, `bug`, `contradiction`.

    Defect classes only. A moment that worked well is an opportunity of kind `delight`, never an issue: it has no failure for reproduction to replay.
  - **`affected_count`**: `integer | null`
  - **`affected_fraction`**: `number | null`, minimum: `0`, maximum: `1`
  - **`affected_personas`**: `(array of string) | null`
  - **`baseline_status`**: `string | null`

    Schema: `BaselineStatus`. Known values, open (more may be added): `new`, `persisting`, `resolved`, `unknown`.

    How this finding compares with the run named as the baseline. `new`: the baseline reached the same page and did not have it (for an issue, only one that is `reproducible`). `persisting`: the baseline has it too. `unknown`: nothing could say - no baseline was compared, the baseline never reached the page, or an issue the baseline does not have was not verified. `resolved` is never stamped on a finding of this run: a baseline issue this run no longer has is counted in `summary.issues_resolved_vs_baseline`. More values may be added; read one you do not know as `unknown`.
  - **`claim`**: `object | null`, schema: `Claim`, no additional properties

    What this issue asserts, and what checked it. A replay matching a failure marker at a step does not say the marker was the thing the title is about, and in practice it often is not; since 0.5 that match is `verification.status: marker_matched`, and `verified` is reserved for a claim a second check (`check`) found supported by a verbatim quote from the cited steps and whose failure is the product's (`attribution`). An issue with no `claim` block, or with none of `verification`, is `unverified`: never read the absence of this object as a confirmation.
    - **`action_step`**: `object | null`, schema: `ActionStep`, no additional properties

      The step the claim is about and the replay is judged at - the action that failed, not the look that saw it or the retry after it. Written by reproduction, which picks it (`_judged_path`); absent when nothing replayed this issue.
      - **`session_id` (required)**: `string`
      - **`step_id` (required)**: `integer`
    - **`attribution`**: `string | null`

      Schema: `Attribution`. Known values, open (more may be added): `product`, `tester`, `undetermined`.

      Whose failure this is, asked before an issue is a product finding: could the persona's own action explain it? `product`: no - the failure is the product's to own. `tester`: yes - a mistyped credential, the wrong element, placeholder text read as a value; the record moves to `tester_errors[]` with a `tester_error` block, is never a ticket and never counted as an issue. `undetermined`: the harness could not tell (a persona handed stale credentials by the mission author typed exactly what it was told; an attribution call that failed), and a human must; it caps `status` at `marker_matched`. Absent means never asked - every issue before this release - and a reader treats absent as `undetermined`. A classification: nothing acts on it directly, the producer derives `status` from it, so a later member (`setup`) is additive and an older reader buckets it as `unknown`.
    - **`check`**: `object | null`, schema: `Check`, no additional properties

      The claim check: one narrow question asked of the evidence at the cited steps after a replay matched a marker - does this evidence show the product doing what the title says? Descriptive: nothing acts on it directly; the producer derives `status` from `verdict` and `attribution`. Absent when the check never ran, which is every issue before this release and every issue no marker matched.
      - **`verdict` (required)**: `string`

        Schema: `Verdict1`. Known values, open (more may be added): `supported`, `unsupported`, `ungrounded`, `skipped`.

        `supported`: the checker answered yes with a quote that gates against the ledger text of the cited steps - the only verdict that lets `status` read `verified`. `unsupported`: the checker answered no; the title claims more than the quoted line shows. `ungrounded`: the checker answered yes but its quote is not in the ledger, so the answer is discarded the way an ungrounded diary quote is and recorded in the gate ledger. `skipped`: no marker matched, or the check did not run. A classification: a later verdict is additive.
      - **`checked_by`**: `string | null`

        Schema: `CheckedBy`. Known values, open (more may be added): `judge`, `code`, `manual`.

        Which instrument answered: `judge` for the observer's checker model call under its own instructions, `code` for a mechanical rule, `manual` for a human. A classification.
      - **`quote`**: `string | null`
      - **`quote_step`**: `object | null`, schema: `QuoteStep`, no additional properties

        The step whose ledger block the quote came from.
        - **`session_id` (required)**: `string`
        - **`step_id` (required)**: `integer`
      - **`reason`**: `string | null`
    - **`expected`**: `string | null`
    - **`observed`**: `string | null`
    - **`verification`**: `object | null`, schema: `Verification`, no additional properties

      Whether the claim was checked, and by what. The two are separate questions and were conflated once already: `status` is the answer a reader acts on, `method` only says which instrument produced it. Consumers show `status`.
      - **`status` (required)**: `string`, possible values: `"verified", "marker_matched", "inconclusive", "unverified"`

        Schema: `Status`.

        Best-supported first. `verified`: a replay matched the failure marker at `action_step` AND the claim check answered `supported` with a verbatim quote from the cited steps (`check`) AND the failure is attributed to the product (`attribution`) - or `method` is `assertion` or `manual` and the same two conditions hold. This and only this may file a ticket alone, and `reproducible` is true exactly when this reads `verified`. `marker_matched` (0.5): a replay matched the failure marker at `action_step`; the claim as titled is unchecked, unsupported, or the check could not quote. The step failed again; whether it failed for the stated reason is not established, so it never files alone. `inconclusive`: a check ran and settled nothing (the marker did not appear again, the two attempts disagreed) - not a refutation. `unverified`: nothing checked it, because there was nothing to check, reproduction never ruled, or the finding is a tester error. A wrong total or a select that resets is `unverified` by construction, not disproven. Default and safe reading when the block is absent. This enum drives an action - it is the ticket-filing gate, like `issue.severity` - so it stays closed for readers too and adding a member is a breaking change: a gate must refuse a value it cannot interpret rather than guess at one, which is why `marker_matched` made 0.5 a new family.
      - **`markers`**: `(array of string) | null`
      - **`method`**: `string | null`

        Schema: `Method`. Known values, open (more may be added): `marker`, `assertion`, `manual`.

        Which check ran, when one did; absent when `status` is `unverified`. `marker`: a replay compared the failure marker at `action_step` - name it in `markers`. A marker matching is evidence the step failed again, not that it failed for the reason the title gives, so on its own it produces `marker_matched`, and `verified` only with `check.verdict: supported` and `attribution: product`. `assertion`: a state assertion checked the claim itself (reserved; not produced yet). `manual`: a human checked it. A classification: nothing acts on it - every surface shows `status` - so a reader on an older release buckets an instrument it does not know as `unknown`, and adding one is additive.
      - **`note`**: `string | null`
  - **`connector_refs`**: `object | null`

    **Additional properties:**

    `string`
  - **`contradiction`**: `object | null`, schema: `Contradiction`, no additional properties

    Populated for type=contradiction: the two statements/surfaces that conflict, each pinned to a step.
    - **`a`**: `object | null`, schema: `A`

      The first of the two statements that conflict: what the product said (`text`), and the session and step where it said it.
      - **`session_id`**: `string | null`
      - **`step_id`**: `integer | null`
      - **`text`**: `string | null`
    - **`b`**: `object | null`, schema: `B`

      The second of the two statements that conflict: what the product said (`text`), and the session and step where it said it.
      - **`session_id`**: `string | null`
      - **`step_id`**: `integer | null`
      - **`text`**: `string | null`
  - **`first_seen_step`**: `integer | null`
  - **`persona_rationale`**: `string | null`
  - **`persona_specific`**: `boolean | null`
  - **`preconditions`**: `(array of string) | null`
  - **`reached_sessions`**: `(array of string) | null`
  - **`repro_steps`**: `array | null`

    **Items:**

    schema: `ReproStep`

    One step of a replay a person or a coding agent can run without the persona, in order from an `open` of the entry page. `action` is a browser action such as `click`, `type`, `key`, `scroll`, `back`, `reload`, `upload` or `wait`; `target` is what it acts on (the address for `open`, `x,y` screen coordinates for a `click`); `value` is what it types, presses or scrolls by; `expect` is what should hold after it, such as the address the page should be on.
    - **`action` (required)**: `string`
    - **`expect`**: `string | null`
    - **`replace`**: `boolean | null`
    - **`target`**: `string | null`
    - **`value`**: `string | null`
  - **`reproduction`**: `object | null`, schema: `Reproduction1`, no additional properties

    Whether Saram replayed the issue without the persona, and what the replay showed: whether one was `attempted`, its `result`, how many `attempts` it took, and `notes` on it. A replay that saw the failure again is not on its own enough to file a ticket; `reproducible` says whether this issue may be.
    - **`attempted`**: `boolean | null`
    - **`attempts`**: `integer | null`
    - **`notes`**: `string | null`
    - **`result`**: `string | null`

      Schema: `Result1`. Known values, open (more may be added): `reproduced`, `not_reproduced`, `flaky`, `skipped`.

      What the replay showed. `reproduced`: the failure happened again. `not_reproduced`: it did not. `flaky`: the attempts disagreed. `skipped`: no replay ran. More values may be added; read one you do not know as unknown.
  - **`suggested_owner`**: `string | null`
  - **`tester_error`**: `object | null`, schema: `TesterError`, no additional properties

    What the persona did that explains this failure. Present exactly when `claim.attribution` is `tester`, and such an issue is in `tester_errors[]`, never in `issues[]`. The quote is the evidence line that shows the persona's action - the input echo, the step head with its args, a diary line, a browser line - copied exactly from the ledger and gated the same way a diary quote is; a `tester` answer whose quote does not gate falls back to `undetermined` and this block is not written.
    - **`kind` (required)**: `string`

      Schema: `Kind1`. Known values, open (more may be added): `mistyped_credential`, `mistyped_input`, `wrong_element`, `placeholder_as_value`, `ignored_instruction`, `other`.

      `mistyped_credential`: typed an email or password that differs from the one the account gave it (decided by code, comparing the typed text with the account; no secret enters a prompt or this document). `mistyped_input`: typed something other than what the brief or the screen asked for. `wrong_element`: acted on an element other than the one the title is about, or a non-interactive one. `placeholder_as_value`: read placeholder text as a pre-filled value and tried to clear or fix it. `ignored_instruction`: skipped something the screen visibly asked for first. `other`: something else the persona did that explains it. Not a tester error, by rule: a persona misreading the product's intent when a reasonable customer would misread it the same way - that is `confusion`, and it is the product's. A classification: a later kind is additive.
    - **`quote` (required)**: `string`
    - **`decided_by`**: `string | null`

      Schema: `DecidedBy`. Known values, open (more may be added): `code`, `judge`.

      `code`: a mechanical comparison decided it (the credential check). `judge`: the observer's attribution model call under its own instructions decided it. A classification.
    - **`quote_step`**: `object | null`, schema: `QuoteStep`, no additional properties

      The step whose ledger block the quote came from.

      *Schema `QuoteStep` is shown above.*
    - **`reason`**: `string | null`
  - **`title`**: `string | null`, maxLength: `120`
- **`reading` (required)**: `array`

  One entry per issue, in the same order and naming its `issue_id`. Always present, so a consumer reads
  the gate rather than re-deriving it.

  **Items:**

  schema: `IssueReading`, no additional properties

  How one issue of `IssueList.issues` may be acted on: whether it may be filed as a ticket on its own, and
  which of its fields are the persona's voice rather than observed behaviour.
  - **`issue_id` (required)**: `string`
  - **`may_file_ticket_alone` (required)**: `boolean`

    True only when reproduction cleared this issue to be filed as a confirmed bug on its own. False means
    report it with its evidence and mark it unconfirmed.
  - **`subjective_fields` (required)**: `array of string`

    Fields on the issue that are the persona's voice rather than observed behaviour. Quote, never state.
  - **`advisory`**: `string | null`

    How to read those fields, present only when there are any.
- **`run_id` (required)**: `string`
- **`status` (required)**: `string`

  The run's status. An empty `issues` is only a result once this is terminal.

**Example:**

```json
{
  "run_id": "run_2026-09-26_4f1c2a",
  "status": "completed",
  "issues": [
    {
      "id": "iss_signup_submit_500",
      "type": "bug",
      "severity": "high",
      "reproducible": true,
      "reproduction": {
        "attempted": true,
        "result": "reproduced",
        "attempts": 2,
        "notes": "Both replays filled the sign-up form with a password containing a space and pressed Create account: POST /api/signup answered 500 and the page did not change."
      },
      "persona_specific": false,
      "claim": {
        "action_step": {
          "session_id": "run_2026-09-26_4f1c2a.sess_01_dana_first_timer",
          "step_id": 7
        },
        "expected": "Create account submits the form and signs the new user in.",
        "observed": "POST /api/signup answered 500; the form stayed on screen with every field filled and no message.",
        "verification": {
          "status": "verified",
          "method": "marker",
          "markers": [
            "failed_requests"
          ],
          "note": "The same failed request at the judged step on both attempts; the claim check found the title supported by the network line, and the failure is the product's."
        },
        "attribution": "product",
        "check": {
          "verdict": "supported",
          "quote": "[step 7] click -> button[type=submit]: POST /api/signup 500",
          "quote_step": {
            "session_id": "run_2026-09-26_4f1c2a.sess_01_dana_first_timer",
            "step_id": 7
          },
          "reason": "The request the button sends fails on the server, which is what the title claims.",
          "checked_by": "judge"
        }
      },
      "affected_sessions": [
        "run_2026-09-26_4f1c2a.sess_01_dana_first_timer"
      ],
      "affected_personas": [
        "dana_first_timer@1"
      ],
      "affected_count": 1,
      "affected_fraction": 0.5,
      "reached_sessions": [
        "run_2026-09-26_4f1c2a.sess_01_dana_first_timer",
        "run_2026-09-26_4f1c2a.sess_02_marcus_fast_skimmer"
      ],
      "first_seen_step": 7,
      "location": {
        "route": "/signup",
        "selector": "button[type=submit]",
        "element_description": "Create account button under the sign-up form",
        "viewport": "1440x900"
      },
      "title": "Create account fails with a server error when the password contains a space",
      "description": "On /signup, submitting the form with a password that contains a space sends POST /api/signup, which answers 500. The page shows no error and keeps the form filled, so the persona pressed Create account three more times before giving up.",
      "persona_rationale": "I pressed the button four times and nothing happened, so I assumed the site was broken.",
      "evidence": {
        "step_refs": [
          {
            "session_id": "run_2026-09-26_4f1c2a.sess_01_dana_first_timer",
            "step_id": 7
          },
          {
            "session_id": "run_2026-09-26_4f1c2a.sess_01_dana_first_timer",
            "step_id": 10
          }
        ],
        "screenshots": [
          "s3://saram-evidence/run_2026-09-26_4f1c2a/run_2026-09-26_4f1c2a.sess_01_dana_first_timer/shots/0007.png"
        ]
      },
      "repro_steps": [
        {
          "action": "navigate",
          "target": "https://example.com/signup",
          "expect": "sign-up form visible"
        },
        {
          "action": "fill",
          "target": "form#signup",
          "expect": "a password containing a space"
        },
        {
          "action": "click",
          "target": "button[type=submit]",
          "expect": "a signed-in page"
        }
      ],
      "preconditions": [
        "viewport 1440x900",
        "auth_state anonymous"
      ],
      "baseline_status": "new",
      "confidence": 0.92
    }
  ],
  "reading": [
    {
      "issue_id": "iss_signup_submit_500",
      "may_file_ticket_alone": true,
      "subjective_fields": [
        "persona_rationale"
      ],
      "advisory": "SUBJECTIVE. `persona_rationale` is persona-voiced narration from an affected session, not a statement of observed behaviour. Quote it as the persona's words; the objective claim is `description`."
    }
  ]
}
```

### 403 the API key lacks the required scope

### 422 Validation Error

**Content type:** `application/json`

schema: `HTTPValidationError`

- **`detail`**: `array`

  **Items:**

  schema: `ValidationError`
  - **`loc` (required)**: `array of (string | integer)`
  - **`msg` (required)**: `string`
  - **`type` (required)**: `string`
  - **`ctx`**: `object`
  - **`input`**: `any`

**Example:**

```json
{
  "detail": [
    {
      "loc": [
        ""
      ],
      "msg": "",
      "type": "",
      "input": null,
      "ctx": {}
    }
  ]
}
```

## Schemas

- `A` — shown above.
- `ActionStep` — shown above.

### Attribution

**Type:** `string`

Known values, open (more may be added): `product`, `tester`, `undetermined`.

Whose failure this is, asked before an issue is a product finding: could the persona's own action explain it? `product`: no - the failure is the product's to own. `tester`: yes - a mistyped credential, the wrong element, placeholder text read as a value; the record moves to `tester_errors[]` with a `tester_error` block, is never a ticket and never counted as an issue. `undetermined`: the harness could not tell (a persona handed stale credentials by the mission author typed exactly what it was told; an attribution call that failed), and a human must; it caps `status` at `marker_matched`. Absent means never asked - every issue before this release - and a reader treats absent as `undetermined`. A classification: nothing acts on it directly, the producer derives `status` from it, so a later member (`setup`) is additive and an older reader buckets it as `unknown`.

**Example:**

```json
"product"
```

**Example:**

```json
"tester"
```

**Example:**

```json
"undetermined"
```

- `B` — shown above.

### BaselineStatus

**Type:** `string`

Known values, open (more may be added): `new`, `persisting`, `resolved`, `unknown`.

How this finding compares with the run named as the baseline. `new`: the baseline reached the same page and did not have it (for an issue, only one that is `reproducible`). `persisting`: the baseline has it too. `unknown`: nothing could say - no baseline was compared, the baseline never reached the page, or an issue the baseline does not have was not verified. `resolved` is never stamped on a finding of this run: a baseline issue this run no longer has is counted in `summary.issues_resolved_vs_baseline`. More values may be added; read one you do not know as `unknown`.

**Example:**

```json
"new"
```

**Example:**

```json
"persisting"
```

**Example:**

```json
"resolved"
```

**Example:**

```json
"unknown"
```

- `Check` — shown above.

### CheckedBy

**Type:** `string`

Known values, open (more may be added): `judge`, `code`, `manual`.

Which instrument answered: `judge` for the observer's checker model call under its own instructions, `code` for a mechanical rule, `manual` for a human. A classification.

**Example:**

```json
"judge"
```

**Example:**

```json
"code"
```

**Example:**

```json
"manual"
```

- `Claim` — shown above.
- `Contradiction` — shown above.

### DecidedBy

**Type:** `string`

Known values, open (more may be added): `code`, `judge`.

`code`: a mechanical comparison decided it (the credential check). `judge`: the observer's attribution model call under its own instructions decided it. A classification.

**Example:**

```json
"code"
```

**Example:**

```json
"judge"
```

- `Evidence1` — shown above.
- `HTTPValidationError` — shown above.
- `Issue` — shown above.
- `IssueList` — shown above.
- `IssueReading` — shown above.

### Kind1

**Type:** `string`

Known values, open (more may be added): `mistyped_credential`, `mistyped_input`, `wrong_element`, `placeholder_as_value`, `ignored_instruction`, `other`.

`mistyped_credential`: typed an email or password that differs from the one the account gave it (decided by code, comparing the typed text with the account; no secret enters a prompt or this document). `mistyped_input`: typed something other than what the brief or the screen asked for. `wrong_element`: acted on an element other than the one the title is about, or a non-interactive one. `placeholder_as_value`: read placeholder text as a pre-filled value and tried to clear or fix it. `ignored_instruction`: skipped something the screen visibly asked for first. `other`: something else the persona did that explains it. Not a tester error, by rule: a persona misreading the product's intent when a reasonable customer would misread it the same way - that is `confusion`, and it is the product's. A classification: a later kind is additive.

**Example:**

```json
"mistyped_credential"
```

**Example:**

```json
"mistyped_input"
```

**Example:**

```json
"wrong_element"
```

**Example:**

```json
"placeholder_as_value"
```

**Example:**

```json
"ignored_instruction"
```

**Example:**

```json
"other"
```

- `Location1` — shown above.

### Method

**Type:** `string`

Known values, open (more may be added): `marker`, `assertion`, `manual`.

Which check ran, when one did; absent when `status` is `unverified`. `marker`: a replay compared the failure marker at `action_step` - name it in `markers`. A marker matching is evidence the step failed again, not that it failed for the reason the title gives, so on its own it produces `marker_matched`, and `verified` only with `check.verdict: supported` and `attribution: product`. `assertion`: a state assertion checked the claim itself (reserved; not produced yet). `manual`: a human checked it. A classification: nothing acts on it - every surface shows `status` - so a reader on an older release buckets an instrument it does not know as `unknown`, and adding one is additive.

**Example:**

```json
"marker"
```

**Example:**

```json
"assertion"
```

**Example:**

```json
"manual"
```

- `QuoteStep` — shown above.
- `ReproStep` — shown above.
- `Reproduction1` — shown above.

### Result1

**Type:** `string`

Known values, open (more may be added): `reproduced`, `not_reproduced`, `flaky`, `skipped`.

What the replay showed. `reproduced`: the failure happened again. `not_reproduced`: it did not. `flaky`: the attempts disagreed. `skipped`: no replay ran. More values may be added; read one you do not know as unknown.

**Example:**

```json
"reproduced"
```

**Example:**

```json
"not_reproduced"
```

**Example:**

```json
"flaky"
```

**Example:**

```json
"skipped"
```

### Severity

**Type:** `string`, possible values: `"low", "medium", "high", "critical"`

How much the defect costs the people who meet it, from least to most: `low`, `medium`, `high`, `critical`. Rated by the judge from the sessions, and lowered one step when the replay did not reproduce the issue and it stands as persona-specific friction. The GitHub connector files only issues at or above its `min_severity_for_issue`.

### Status

**Type:** `string`, possible values: `"verified", "marker_matched", "inconclusive", "unverified"`

Best-supported first. `verified`: a replay matched the failure marker at `action_step` AND the claim check answered `supported` with a verbatim quote from the cited steps (`check`) AND the failure is attributed to the product (`attribution`) - or `method` is `assertion` or `manual` and the same two conditions hold. This and only this may file a ticket alone, and `reproducible` is true exactly when this reads `verified`. `marker_matched` (0.5): a replay matched the failure marker at `action_step`; the claim as titled is unchecked, unsupported, or the check could not quote. The step failed again; whether it failed for the stated reason is not established, so it never files alone. `inconclusive`: a check ran and settled nothing (the marker did not appear again, the two attempts disagreed) - not a refutation. `unverified`: nothing checked it, because there was nothing to check, reproduction never ruled, or the finding is a tester error. A wrong total or a select that resets is `unverified` by construction, not disproven. Default and safe reading when the block is absent. This enum drives an action - it is the ticket-filing gate, like `issue.severity` - so it stays closed for readers too and adding a member is a breaking change: a gate must refuse a value it cannot interpret rather than guess at one, which is why `marker_matched` made 0.5 a new family.

- `StepRef` — shown above.
- `TesterError` — shown above.

### Type

**Type:** `string`

Known values, open (more may be added): `blocker`, `friction`, `confusion`, `bug`, `contradiction`.

Defect classes only. A moment that worked well is an opportunity of kind `delight`, never an issue: it has no failure for reproduction to replay.

**Example:**

```json
"blocker"
```

**Example:**

```json
"friction"
```

**Example:**

```json
"confusion"
```

**Example:**

```json
"bug"
```

**Example:**

```json
"contradiction"
```

- `ValidationError` — shown above.

### Verdict1

**Type:** `string`

Known values, open (more may be added): `supported`, `unsupported`, `ungrounded`, `skipped`.

`supported`: the checker answered yes with a quote that gates against the ledger text of the cited steps - the only verdict that lets `status` read `verified`. `unsupported`: the checker answered no; the title claims more than the quoted line shows. `ungrounded`: the checker answered yes but its quote is not in the ledger, so the answer is discarded the way an ungrounded diary quote is and recorded in the gate ledger. `skipped`: no marker matched, or the check did not run. A classification: a later verdict is additive.

**Example:**

```json
"supported"
```

**Example:**

```json
"unsupported"
```

**Example:**

```json
"ungrounded"
```

**Example:**

```json
"skipped"
```

- `Verification` — shown above.
- `Video` — shown above.
