Engine 5feac4f4 (5feac4f4acf2c805af890ad4b7e53538107840b3) · 4 Nov 2026, 21:34 UTC

Assure decides 60 of 68 promises about itself: 58 hold, 2 disproven, 8 not established.
Premised: A1, A4, A5, E10, E13 and G5.

Holds: True of this release.
Not established: Not shown either way yet.
Disproven: This release breaks it.
From the code: Checked against Assure's own source.
From a run record (premised): An outcome we measure each release, such as how setup went.

## Holds (55)

55 promises, each read from the code.

### What the live API answers

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| R1 | holds | formal | Every answer tells browsers to speak to this API over HTTPS only. | Read from the code and the live API's answers | We sent requests to api.symbolia.ai and to our own server code, and every answer read (/healthz, /, /v1/profiles) tells browsers to use HTTPS only. | serve/api.py, deploy/Caddyfile (assure/checkers/http-observed-baseline/PROFILE.json#obligations/HTTP-STS-PRESENT) @ 5feac4f4 |
| R2 | holds | formal | No answer states both its length and that it is sent in chunks. | Read from the code and the live API's answers | We sent requests to api.symbolia.ai and to our own server code, and every answer read (/healthz, /, /v1/profiles) states its length or says it is chunked, never both. | serve/api.py, deploy/Caddyfile (assure/checkers/http-observed-baseline/PROFILE.json#obligations/HTTP-FRAMING-CL-TE) @ 5feac4f4 |
| R3 | holds | formal | Answers that describe the service are never stored by anything between the server and the customer. | Read from the code and the live API's answers | We sent requests to api.symbolia.ai and to our own server code, and every answer read (/healthz, /, /v1/profiles) tells anything in between not to store it. | serve/api.py, deploy/Caddyfile (assure/checkers/http-observed-baseline/PROFILE.json#obligations/HTTP-CACHE-NO-STORE) @ 5feac4f4 |
| R4 | holds | formal | Browsers are told to take an answer's declared type at its word and never guess it from the bytes. | Read from the code and the live API's answers | We sent requests to api.symbolia.ai and to our own server code, and every answer read (/healthz, /, /v1/profiles) tells browsers not to guess its type. | serve/api.py, deploy/Caddyfile (assure/checkers/http-observed-baseline/PROFILE.json#obligations/HTTP-NOSNIFF-PRESENT) @ 5feac4f4 |
| R5 | holds | formal | The API never sets a cookie. | Read from the code and the live API's answers | We sent requests to api.symbolia.ai and to our own server code, and every answer read (/healthz, /, /v1/profiles) sets no cookie. | serve/api.py, deploy/Caddyfile (assure/checkers/http-observed-baseline/PROFILE.json#obligations/HTTP-NO-SET-COOKIE) @ 5feac4f4 |
| R6 | holds | formal | A key issued to one account cannot read another account's verdicts. | Read from the code | We read every route and handler of our API server (serve/) and found that every stored item is looked up under the account of the key that asks for it. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:50 @ 5feac4f4 |
| R7 | holds | formal | An API key is never written to any log line. | Read from the code | We read every route and handler of our API server (serve/) and found that no log line writes a key; the request log records the key's id, never the key. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:43 @ 5feac4f4 |

### Getting to value

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| A2 | holds | formal | Every run tells the customer something useful, including a refused one, and names one next step. | Read from the code | We read every message our API sends (serve/render.py), and each of the 31 ways a run can end, refusals included, names a next step. | serve/render.py (next_step, failure_markdown, pr_refusal_markdown, summary_markdown, pr_comment_markdown) @ 5feac4f4 |
| A6 | holds | formal | When a Flask repository has no requirements.md, Assure proposes a starter one in the same pull request as its declaration, and with no setting every API check reads the repository's requirements.md. | Read from the code | We read how the Action drafts its pull request (action/declaration_draft.py): when your repository has no requirements.md it proposes a starter one in the same pull request, and with no setting the API checks read your requirements.md. | action/declaration_draft.py (STARTER_PATH, starter_requirements, propose); action/entry.py @ 5feac4f4 |

### Who can reach what

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| B1 | holds | formal | Without a key, someone reaches only what is meant to be public, and each public route is reached only by the means it is meant for: a signature, a signed link, or nothing sensitive. | Read from the code | We read every route and handler of our API server (serve/) and found that without a key only /healthz and the routes meant to be public answer, each by its own means: a signature, a signed link, or nothing sensitive. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:5 @ 5feac4f4 |
| B2 | holds | formal | Every other request needs a valid API key. | Read from the code | We read every route and handler of our API server (serve/) and found that every other route needs a valid API key. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:5 @ 5feac4f4 |
| B3 | holds | formal | Once a key is revoked, the very next request made with it is turned away. | Read from the code | We read every route and handler of our API server (serve/) and found that each request reads the key's current state, so a revoked key is turned away on its next use. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:36 @ 5feac4f4 |
| B4 | holds | formal | Every key has an expiry set when it is issued; responses say when it expires and warn before it does; an expired key is turned away. | Read from the code | We read every route and handler of our API server (serve/) and found that every key is issued with an expiry, responses carry it and warn before it, and an expired key or one without an expiry is turned away. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:11 @ 5feac4f4 |
| B5 | holds | formal | Rotating a key brings the new key in and retires the old one after a stated window, and never leaves an account without a working key. | Read from the code | We read every route and handler of our API server (serve/) and found that rotation issues the new key first and retires the old one only after the stated window. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:47 @ 5feac4f4 |
| B6 | holds | formal | A paid action runs only when the plan, balance or agreed overage covers it. | Read from the code | We read every route and handler of our API server (serve/) and found that every paid route checks the plan, balance or agreed overage before doing the work. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:48 @ 5feac4f4 |
| B7 | holds | formal | A proof-tree link opens only if the server signed it, only until it expires, and never after the verdict has been deleted. | Read from the code | We read every route and handler of our API server (serve/) and found that a proof-tree link opens only when we signed it, it has not expired and the verdict is still kept. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:31 @ 5feac4f4 |
| B8 | holds | formal | A billing event is applied only when its signature verifies and the event is recent. | Read from the code | We read every route and handler of our API server (serve/) and found that a billing event is applied only when its signature checks out and it is recent. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:46 @ 5feac4f4 |
| B9 | holds | formal | Every signing or verification key comes from configuration. | Read from the code | We read every route and handler of our API server (serve/) and found that every signing and verification key is read from configuration, never written in the code. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:10 @ 5feac4f4 |
| B10 | holds | formal | Every stored item belongs to one account; no other account can read it or tell that it exists. | Read from the code | We read every route and handler of our API server (serve/) and found that every stored item is opened only under its own account, and another account gets the same answer as if it did not exist. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:50 @ 5feac4f4 |
| B12 | holds | formal | POST /v1/checks and POST /v1/declaration-proposal refuse a request whose declared size exceeds the account's plan limit (Free 6 MiB, Premium 24 MiB, Pro 64 MiB) before any request content is read, and the refusal names the plan that fits. | Read from the code | We read how the two upload routes take a request (serve/api.py): each compares the size the request declares with your plan's limit before reading any of it, and stops reading at the same limit; the refusal names your plan. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:51 @ 5feac4f4 |

### What a verdict is

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| C1 | holds | formal | A requirement reads holds, not established or disproven. | Read from the code | We read the verdict code (assure/checkers/identity/grade.py), and it has exactly three readings: holds, not established and disproven. | assure/checkers/identity/grade.py:56 @ 5feac4f4 |
| C2 | holds | formal | Nothing reads holds when there was nothing to check; it reads not established. | Read from the code | We read the verdict code (assure/checkers/identity/grade.py), and every case with nothing to check reads not established. | assure/checkers/identity/grade.py:58 @ 5feac4f4 |
| C3 | holds | formal | Nothing reads disproven unless the code really breaks the rule; a route whose purpose is not known reads not established. | Read from the code | We read the verdict code (assure/checkers/identity/grade.py), and only a found break reads disproven; anything not understood reads not established. | assure/checkers/identity/grade.py:58 @ 5feac4f4 |
| C4 | holds | formal | The engine checks that its own code matches its pin before it runs. | Read from the code | We read the server start-up (serve/api.py, serve/worker.py, serve/check.py), and it checks the engine's pin before loading the engine. | serve/api.py:4081; serve/worker.py:428; serve/check.py:794 @ 5feac4f4 |
| C5 | holds | formal | Every verdict names the engine version it ran on. | Read from the code | We read how verdicts are built (serve/envelope.py, serve/check.py), and every verdict carries the engine version it ran on. | serve/envelope.py:1710; serve/check.py:232; serve/worker.py:163; serve/worker.py:440; serve/api.py:1216; serve/api.py:1138 @ 5feac4f4 |
| C6 | holds | formal | The limits the API publishes are the limits it enforces. | Read from the code | We read the API (serve/api.py, serve/bundle.py), and the limits it publishes are the same values it enforces. | serve/api.py:627; serve/api.py:2110; serve/bundle.py:200; serve/bundle.py:624; serve/api.py:560; serve/meter.py:2401; serve/meter.py:2458 @ 5feac4f4 |
| C7 | holds | formal | An account cannot create a volume of requests beyond reliable limits. | Read from the code | We read the API (serve/api.py), and every request that creates work passes a rate limit first. | serve/api.py:406 @ 5feac4f4 |
| C8 | holds | formal | Sending the same check twice with the same idempotency key returns the first check and is not charged again. | Read from the code | We read the check route (serve/api.py, serve/store.py), and a repeated idempotency key returns the first check before any charge. | serve/api.py:2465; serve/store.py:910 @ 5feac4f4 |
| C10 | holds | formal | When a checker can model only the first few of something, everything past that point reads not established with the bound named. | Read from the code | We read the checker's limits (assure/checkers/identity/explore.py), and past each limit the result reads not established and names the limit. | assure/checkers/identity/explore.py:353; serve/profiles.py:1602 @ 5feac4f4 |

### How a job runs

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| D1 | holds | formal | A job completes at most once. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that a job completes at most once. | hosted/MACHINE.json#invariants/completes_at_most_once @ 5feac4f4 |
| D2 | holds | formal | A worker whose lease has lapsed writes nothing. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that a worker whose lease has lapsed writes nothing. | hosted/MACHINE.json#invariants/stale_lease_never_writes @ 5feac4f4 |
| D3 | holds | formal | Two workers never claim the same job. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that two workers never hold the same job. | hosted/MACHINE.json#invariants/claim_exclusive @ 5feac4f4 |
| D4 | holds | formal | A job is attempted at most its allowed number of times. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that a job is never attempted more than its allowed number of times. | hosted/MACHINE.json#invariants/attempts_bounded @ 5feac4f4 |
| D5 | holds | formal | A job is retried only when the failure was not its own; a refusal is final. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that a refused job is never retried. | hosted/MACHINE.json#invariants/refusal_never_retried @ 5feac4f4 |
| D6 | holds | formal | Every way a job can end records a typed outcome. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that every ending records a typed outcome. | hosted/MACHINE.json#invariants/exit_typed_outcome @ 5feac4f4 |
| D7 | holds | formal | A job moves only along the allowed path. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that every move is one of the allowed moves. | hosted/MACHINE.json#transitions @ 5feac4f4 |
| D8 | holds | formal | If a worker is interrupted mid-job, nothing is written. | Read from the code | We explored every state our job queue can reach (hosted/MACHINE.json) and found that an interrupted job writes nothing. | hosted/MACHINE.json#invariants/interrupt_writes_nothing @ 5feac4f4 |

### What happens to a customer's data

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| E1 | holds | formal | Only what a check needs leaves the customer's runner, never raw rows, names or values. | Read from the code | We read what the runner sends (action/collect.py, serve/bundle.py), and the raw files are held back on the runner; only what the check needs leaves it. | serve/bundle.py (RUNNER_ONLY, from_directory), action/collect.py (_gather) @ 5feac4f4 |
| E2 | holds | formal | The facts collected for a check are deleted when the check ends; on a paid plan one sealed copy is kept, encrypted for that account alone. | Read from the code | We read the worker (serve/worker.py, serve/bundle_keep.py), and it deletes the check's files on every exit, keeping one sealed copy only on a paid plan. | serve/worker.py (run_in_child), serve/bundle_keep.py (keep, includes_premium, PREMIUM_TIERS) @ 5feac4f4 |
| E3 | holds | formal | What we keep is minimal and kept briefly, then deleted with everything that belongs to it. | Read from the code | We read our data-keeping rules (hosted/data_rule.py) and found that each kind of kept data has a short limit or ends with the tier or account it belongs to. | hosted/data_rule.py @ 5feac4f4 |
| E5 | holds | formal | Using de-identified configuration data to improve the product is on by default for the free tier and off by default for paid tiers, and one setting changes it. | Read from the code | We read our data-keeping rules (hosted/data_rule.py) and found that product use of de-identified data is on by default for free, off for paid, and one setting changes it. | hosted/data_rule.py @ 5feac4f4 |
| E6 | holds | formal | An enterprise account keeps none of its code or collected facts after the check ends. | Read from the code | We read our data-keeping rules (hosted/data_rule.py) and found that an enterprise account keeps none of its code or collected facts after a check. | hosted/data_rule.py @ 5feac4f4 |
| E8 | holds | formal | Feedback and telemetry are kept only as long as they are useful, and never a requirement's text. | Read from the code | We read our data-keeping rules (hosted/data_rule.py) and found that feedback and telemetry are kept 12 months and neither keeps a requirement's text. | hosted/data_rule.py @ 5feac4f4 |
| E9 | holds | formal | A customer's private model is deleted when they ask, and soon after the account closes. | Read from the code | We read our data-keeping rules (hosted/data_rule.py) and found that a private model is deleted on request and 30 days after the account closes. | hosted/data_rule.py @ 5feac4f4 |
| E12 | holds | formal | The report and the reading of a customer's requirements are on by default, and one setting turns each off. | Read from the code | We read the Action's settings (action/action.yml, action/entry.py): the report and the reading of your requirements are on unless you turn them off, and one setting turns off each. | action/entry.py (parse_report, requirements_upload, run_api); action/action.yml @ 5feac4f4 |

### Money

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| F1 | holds | formal | An account's plan and charges change only by something it agreed to or was given, and never twice for the same event. | Read from the code | We read our billing code (serve/billing_machine.py) and found that each billing event is applied once, a repeat changes nothing, and the plan moves only by an event or a gift. | serve/billing_machine.py @ 5feac4f4 |
| F2 | holds | formal | When a customer leaves a paid plan, what was kept for it is deleted. | Read from the code | We read our billing code (serve/billing_machine.py) and found that leaving a paid plan deletes what was kept for it. | serve/billing_machine.py @ 5feac4f4 |
| F4 | holds | formal | Overage is charged at the published rate, and only within the budget the customer agreed. | Read from the code | We read our billing code (serve/billing_machine.py) and found that overage is charged at the published rate and refused past the agreed budget. | serve/billing_machine.py @ 5feac4f4 |
| F5 | holds | formal | Every ledger is append-only, and every total is recomputed from its entries. | Read from the code | We read our billing code (serve/billing_machine.py) and found that every ledger only ever grows, and every total is worked out again from its entries. | serve/billing_machine.py @ 5feac4f4 |
| F6 | holds | formal | A customer can always see their plan and what each check cost them. | Read from the code | We read the usage route and cost records (serve/api.py, serve/meter.py), and an account's plan and every check's cost come from its own ledger. | serve/api.py _usage; serve/meter.py check_costs; persisted customer ledgers @ 5feac4f4 |
| F7 | holds | formal | A statement shows the same figures a real bill would. | Read from the code | We produced statements (serve/billing.py) for a gifted account and a paid one, and each showed the figures a real bill would. | serve/billing.py @ 5feac4f4 |

### What a customer reads

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| G2 | holds | formal | No file a customer reads or commits carries an internal flag or marker. | Read from the code | We read the 45 files a customer reads or commits (docs, action, skills), and none carries an internal flag or marker. | action/build_dist.py (RECORD_RE, FLAG_LINE) @ 5feac4f4 |
| G3 | holds | formal | Every refusal names what was refused and the field or input that fixes it. | Read from the code | We read all 558 places our API and Action refuse (serve/, action/), and each names what was refused and why. | serve/outcomes.py (_TABLE, Refusal.__init__) @ 5feac4f4 |
| G4 | holds | formal | Every served profile answers in readable words on its first run, in its verdict, its summary and its pull-request comment. | Read from the code | We ran every profile we serve on its first run (serve/profiles), and each answered in readable words in its verdict, summary and pull-request comment. | serve/PROPERTIES.json; serve/profiles/*.json; tests/checkers/fixtures/http/flaskr-intent-001; tests/serving/fixtures/mysql-declared/positive; tests/serving/fixtures/run-37121027064; tests/serving/fixtures/run-37121027064; tests/checkers/fixtures/python-auth/flask-session-a @ 5feac4f4 |
| G7 | holds | formal | Every run tells the customer what it proposed, how much it withheld, and whether it sent the requirements text. | Read from the code | We read what each run writes back to you (action/entry.py, action/declaration_draft.py): every run says what it proposed, how much it held back, and whether it sent your requirements text. | action/entry.py (summary writers); action/declaration_draft.py (pull_request_body) @ 5feac4f4 |

## Not established (7)

7 promises read from the code that Assure could not decide. Each says what is missing.

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| A3 | not established | formal | The pre-flight predicts the check; it never says the code is ready when the check cannot read it. | Read from the code | We replayed unreadable code and route tables for two app types (serve/lint.py, serve/input_readers.py), and the pre-flight never said ready; those replays do not cover every kind of app we serve. | serve/lint.py; serve/input_readers.py; serve/profiles.py; tests/checkers/identity/fixtures/adapter-2-fastapi/positive @ 5feac4f4 |
| B11 | not established | formal | Keys and signing values are never written to logs, records or responses. | Read from the code | We read how keys are stored (serve/keys.py): issuing a key stores only a fingerprint of it, but we could not yet follow the key through rotation, so this is not yet shown. | assure/checkers/identity/adapters/python_stdlib_http/fixtures/assure-self/requirements.md:43 @ 5feac4f4 |
| C9 | not established | formal | The API and the check process never contact anything outside the server. | Read from the code | We read the worker (serve/worker.py), but part of the code it loads is outside what this read covers, so it is not yet shown that nothing outside is contacted. | serve/billing_relay.py:40 @ 5feac4f4 |
| E7 | not established | formal | Backups keep only what is needed to restore accounts and billing, briefly, and never a customer's verdicts or collected facts. | Read from the code | We looked for a backup job and found none; the backup rule is written down (hosted/data_rule.py) but nothing runs it yet. | hosted/data_rule.py (RESTORE_ONLY, declared) @ 5feac4f4 |
| E11 | not established | formal | Setting Assure up keeps no copy of your files and costs nothing. | Read from the code | We could not yet follow every call on the setup path far enough to show it keeps nothing and charges nothing, and we found nothing that breaks it. | action/declaration_draft.py:449 @ 5feac4f4 |
| F3 | not established | formal | No one is charged beyond what they agreed: overage starts at zero, only a person's yes turns it on, the customer is told as it nears the budget, and it is never raised for them. | Read from the code | The overage budget this promise needs is not in this release yet, so there is nothing to read. | serve/billing_machine.py @ 5feac4f4 |
| G1 | not established | formal | A drafted goal never claims more than its checks prove, and says what it covers. | Read from the code | The goal drafter this promise is about is not in this release yet, so there is nothing to read. | - @ 5feac4f4 |

## Read from a run record (6)

These 6 promises are about measured outcomes rather than code. We state them as Assure's own customer, and each release reads them from the latest record of a measured run.

A1 and A4 are disproven, read from a run record. They measure how setup went, not the code: no promise read from the code is disproven. Each row below says what was found and what it means for you.

| Promise | Reading | Kind | Says | How it was read | What was read and why | Evidence |
|---|---|---|---|---|---|---|
| A1 | disproven | premised | Anyone can set Assure up from one line, and is asked only what only they can answer, each question with its tradeoff. | Read from a run record | We read the record of our v0.1.3 setup measurement on ten sample apps, which keeps the questions each setup agent asked (carried from our 17 October run); v0.1.4, v0.1.5 and v0.1.6 were not measured again, so this reading is carried from v0.1.3. Two of the questions our setup instructions ask, whether to collect the gaps and whether to commit what was collected, do not yet say what a yes or a no costs you. Setup may ask you things it should work out itself, and you may have to answer without being told what each choice costs. Tracked as #3089. What we state: Your agent asks only the questions our setup instructions list, each with what a yes and a no cost you. Record: action/skills/assure/SKILL.md and references/agent.md @ 5feac4f4, 2026-11-04 (the release commit). This reading comes from our setup instructions, not from a run, so it holds only as far as your agent follows them. | action/skills/assure/SKILL.md @ 5feac4f4 |
| A4 | disproven | premised | A fresh agent working from the one line gets a correct result on at least 6 of 10 qualification apps, and each other app is reachable through Assure's shipped extension paths. | Read from a run record | We read the record of our v0.1.3 setup measurement on ten sample apps, each with a known flaw added, to see whether the check found it; v0.1.4, v0.1.5 and v0.1.6 were not measured again, so this reading is carried from v0.1.3. In the measurement this release was read against, 1 of 10 sample apps got a real check on the first run, and it found the added flaw with no false alarm. The other 9 did not reach a real reading through an extension. On an app like yours, setup may not reach a working check the first time, and you may need to step in. Tracked as #3679. What we state: A fresh agent following the one line got a check that found the added flaw, without false alarms, on nearly every sample app. Record: docs/validation/setup-qual/runs/20261017T082934Z-beta/results.jsonl, 2026-10-17 (the beta setup measurement; the record the v0.1.6 release reader read). This reading comes from a record of a run, not from reading our code, so it is only as good as that run: it tells you how setup went on ten sample apps, not how it will go on yours. | docs/validation/setup-qual/runs/20261017T082934Z-beta/results.jsonl @ 5feac4f4 |
| A5 | holds | premised | Assure sends nothing from a repository until the person has said yes to what will be sent: which files, how much, and to where. | Read from a run record | We read our setup instructions (action/skills/assure/SKILL.md): before anything is sent, your agent asks you one question naming how many files, how large, and where they go; if you say no, nothing is sent. What we state: Your agent follows our setup instructions: it asks before it sends, and sends nothing on a no. Record: action/skills/assure/SKILL.md (step 2) @ 5feac4f4, 2026-11-04 (the release commit). Our code does not hold this gate itself; your agent does, by following our setup instructions. It holds as far as your agent follows them. | action/skills/assure/SKILL.md (step 2, Fallback), action/skills/assure/references/agent.md @ 5feac4f4 |
| E10 | holds | premised | Setup sends only the files the drafter reads; nothing else from the repository goes with them. | Read from a run record | We read our setup instructions and the drafter (action/skills/assure/SKILL.md, the Flask drafter): setup leaves out the folders and test files the drafter skips, and sends only what the drafter reads. What we state: Your agent follows step 2 of our setup instructions, which sends only what the drafter reads. Record: action/skills/assure/SKILL.md (step 2) @ 5feac4f4, 2026-11-04 (the release commit). No code of ours builds the setup upload; your agent does, by following our setup instructions. It holds as far as your agent follows them. | action/skills/assure/SKILL.md (step 2), assure/checkers/identity/proposal/python_flask.py (SKIP_DIRS, _test_only) @ 5feac4f4 |
| E13 | holds | premised | Model calls that carry a customer's code go only to routes with a zero-retention agreement. | Read from a run record | We read where model calls go (serve/premium_setup.py, hosted/inference.py): a call that carries your code goes only to the two routes we hold a zero-retention agreement with. What we state: The deployed route settings are the ones our code writes (serve/premium_setup.py ROUTE_TABLE). Record: serve/premium_setup.py, hosted/inference.py @ 5feac4f4; three observed Premium sends, each to an agreed zero-retention route, 2026-11-04 (the release commit). We read the routes our code allows and saw real sends use them; we did not read the live settings themselves, so this holds as far as they match the code. | serve/premium_setup.py (ROUTE_TABLE); hosted/inference.py (call_with_ladder, PremiumTransport) @ 5feac4f4 |
| G5 | not established | premised | Every feedback note a customer files is read back over the API by Symbolia's own loop and answered or routed; none sits unread. | Read from a run record | We looked for the record of our own loop reading customer feedback back over the API, and there is none yet (docs/validation/feedback-digest/). What we state: A record of our own loop reading the feedback notes customers filed back over the API, with each one answered or routed. Record: none yet: no such record exists under docs/validation/feedback-digest/. This promise can only be shown by a record of us reading and answering your feedback notes, and no such record exists yet, so we cannot yet show that a note you file will be read and answered. | docs/validation/feedback-digest/ @ 5feac4f4 |

The record: /self-check/5feac4f4/meta.json, /self-check/5feac4f4/report.json, /self-check/5feac4f4/areas.json (the section headings of Assure's requirements.md at 5feac4f4acf2c805af890ad4b7e53538107840b3). Every release: /assure-on-assure.