From b0fa0aba6e90a5f3629713e910bcff659d142939 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:20:29 +0000 Subject: [PATCH 1/4] AC-036: restructure README so the runnable product surface comes first Gate E (human repository usability). Documentation only - no runtime, test, fixture, or workflow change. The defect: Quick Start sat at line 418 of a 1084-line README, behind ~400 lines of conceptual material describing capability that is not implemented end to end. An unfamiliar developer met the target product before they could run the real one. Restructured into the required cognitive order, with everything runnable in the first ~250 lines: what it is and its truthful status -> the problem -> install -> a successful end-to-end run -> two deliberate refusals -> what the output fields mean -> how to integrate -> what is NOT implemented -> where to go next. Deep conceptual material is preserved verbatim below a "How it works - the full model" divider that states plainly those worked examples are target behavior. Every command and every output block in the new front matter was executed against committed fixtures at this commit and pasted from real stdout. No output was prettified; the CLI emits single-line JSON and the README says so where it reflows for readability. Refusals are presented as successful demonstrations, with reason_code, non-zero exit, and a plain-language reading: RUN_UNCLASSIFIED_ACTION for an undeclared action, RUN_FACT_STALE for an approval outside its freshness window. Also notes that no receipt is issued on refusal. Integration section documents only interfaces that exist and were exercised while writing it (CLI, Python library, GitHub merge gate, receipt verification), and states plainly what does not exist: no published package, no HTTP service, no persistence, no multi-contract registry, no replay protection. Metadata audit: no badges added - none of the maturity states a badge would assert (published package, coverage, audit, certification) is established. Confirmed requires-python >=3.10 matches the documented requirement. Adds a License section recording the truthful current state: no LICENSE file exists and pyproject declares no license, so default copyright applies. Not resolved here - declaring a license is an owner decision with legal effect, not an executor decision. Removes the now-superseded Quick start section rather than leaving two competing entry points. --- README.md | 343 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 240 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index c23dd19..e78b8c7 100644 --- a/README.md +++ b/README.md @@ -2,54 +2,269 @@ **Proof that the rule you shipped is actually supported by the source.** -AuthContract is CI for the rules your agents act on. +AuthContract turns an institutional rule into a canonical, testable artifact — then keeps that artifact bound to the actions your software takes, and issues evidence anyone can independently recompute. -It checks whether a rule in your code is actually supported by its source, catches behavior changes in pull requests, and keeps the rule that passed connected to the actions your agent takes after you ship. +```text +source → rule → PR → check → merge → runtime → proof +``` -If the source does not support the rule, the check fails. +> **Status: experimental reference implementation (TRL 4).** The mechanical trust chain below is implemented, tested, and benchmarked for one synthetic banking specimen. **Automated natural-language source-to-rule comparison is target behavior and is _not_ implemented end to end.** Nothing here is production-ready, audited, or certified. See [What is *not* implemented](#what-is-not-implemented) — read it before forming expectations. -If the source is ambiguous or incomplete, AuthContract does not guess. +--- -If the rule passes, AuthContract preserves the evidence needed to show what source supported it, what behavior was tested, what version was shipped, and what rule governed a later action. +## The problem this addresses -```text -source → rule → PR → check → merge → runtime → proof +Software increasingly does consequential things on an institution's behalf: sends payments, approves transactions, changes customer state. Developers translate requirements into executable rules — and a rule can look reasonable, pass ordinary unit tests, and still introduce a threshold or exception the source never established. + +Ordinary tests ask *did the code run correctly?* AuthContract adds a second question: **which rule authorized this action, what version applied, and can anyone else verify that independently?** + +--- + +## Run it now + +Requires **Python 3.10+** and `git`. No credentials, no services, no network beyond the clone and dependency install. + +```bash +git clone https://github.com/veraxis-protocol/AuthContract.git +cd AuthContract +python3 -m venv .venv && source .venv/bin/activate +pip install -e ".[test]" +``` + +Confirm the install: + +```bash +pytest -q # expect: 342 passed +``` + +> Not on PyPI. Install from source, as above. + +--- + +## A successful end-to-end run + +This exercises the whole implemented chain — contract → validation and digest binding → projection → runtime facts → authorization → receipt: + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_valid.json \ + --execution-result SIMULATED_SUCCESS +``` + +Actual output (reformatted for reading; the CLI emits one line of JSON): + +```json +{ + "status": "PASS", + "decision": "ALLOW", + "reason_code": "OK", + "artifact": "banking_payment_specimen.json", + "action_file": "send_payment_valid.json", + "facts_file": "facts_valid.json", + "receipt": { + "activation_id": "act:banking-specimen-001:v1", + "contract_digest": "sha256:d94a65607e756a2d4e3c92fc1de4a23d7cf614dd1dbe8f3fd20fe6e459c9b842", + "projection_digest": "sha256:c7f6dccb5f3f6b7c70b305e838ad87877805d19bd6d3e225f41a40151aa5659b", + "runtime_fact_set_digest": "sha256:57fe990d8320793f92894d31d16d55598e8f30cb63d227bd35e9b2bb3daaab09", + "exact_action_digest": "sha256:55bc4dd36b705f58a123c110bc4d5b398182524cb51c4fae499c2c1455d6470f", + "admission_digest": "sha256:1c631041f126de51afeeb5838d47501616083cd31d4ad0ca9691c71a74ec2a68", + "decision": "ALLOW", + "execution_result": "SIMULATED_SUCCESS", + "decision_time": "2026-08-23T00:10:00+00:00", + "receipt_digest": "sha256:2cfa754d40ed2b9df4a4be7dcc0082bbc1097e2b6a88cb73ea9f9af950bc5a9a" + } +} ``` +Exit code `0`. The action was permitted, and you now hold a receipt describing exactly what authorized it. + +### Independently verify that receipt + +The receipt is only worth something if someone else can check it without trusting you. This recomputes **every** bound value from the raw artifact, action, and fact files — it trusts no field in the receipt itself: + +```bash +authcontract verify-receipt \ + fixtures/runtime/receipt_valid.json \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_valid.json +``` + +```json +{"status": "PASS", "reason_code": "OK", "receipt": "receipt_valid.json", + "artifact": "banking_payment_specimen.json", "action_file": "send_payment_valid.json", + "facts_file": "facts_valid.json"} +``` + +Exit code `0`. Tamper with any bound field and this refuses — see below. + +--- + +## A deliberate refusal + +**A refusal is a successful demonstration.** The system is designed to fail closed, and you should see it do so. + +### Refusal 1 — an action outside the declared rule + +The specimen declares exactly one mediated action, `send_payment`. Here we propose `issue_refund`: + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_unknown_action_type.json \ + fixtures/runtime/facts_valid.json \ + --execution-result SIMULATED_SUCCESS +``` + +```json +{"status": "REFUSED", "reason_code": "RUN_UNCLASSIFIED_ACTION", + "message": "RUN_UNCLASSIFIED_ACTION: 'issue_refund' is not in the closed mediated-action universe for this projection"} +``` + +Exit code `1`. **In plain language:** the rule never granted authority to issue refunds, so AuthContract refuses rather than improvising. An undeclared action is not a permitted action. + +### Refusal 2 — a runtime fact too old to rely on + +The contract requires a secondary approval no older than 15 minutes. This bundle supplies a stale one: + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_stale.json \ + --execution-result SIMULATED_SUCCESS +``` + +```json +{"status": "REFUSED", "reason_code": "RUN_FACT_STALE", + "message": "RUN_FACT_STALE: secondary_approval.present is older than 0:15:00"} +``` + +Exit code `1`. **In plain language:** the approval existed, but not recently enough to satisfy the rule. Stale evidence is not treated as current permission. + +Note that **no receipt is issued on refusal** — a refused decision never produces evidence claiming a decision was made. + +--- + +## What the result means + +| Field | Meaning | +|---|---| +| `status` | `PASS` or `REFUSED` — the outcome of the check | +| `decision` | `ALLOW` on a permitted action; absent on refusal | +| `reason_code` | Stable machine-facing identifier (e.g. `RUN_FACT_STALE`). Safe to branch on | +| `message` | Human-readable explanation of a refusal | +| `contract_digest` | Canonical identity (RFC 8785 JCS + SHA-256) of the rule that applied | +| `projection_digest` | Identity of the action domain the rule was projected into | +| `runtime_fact_set_digest` | Identity of the exact facts relied on | +| `exact_action_digest` | Identity of the exact action authorized | +| `admission_digest` | Identity of the admission state bound to the decision | +| `decision_time` | Bound to the fact bundle's declared `now`, **not** wall-clock — so replays are byte-identical | +| `receipt_digest` | Identity of the receipt as a whole | + +Every digest is recomputable from raw inputs. That is what makes the receipt checkable by a third party rather than merely assertable by you. + +Exit codes: `0` pass · `1` refusal. + --- -## Why AuthContract? +## How to integrate it today + +Only interfaces that **actually exist** are listed. Each was executed while writing this section. + +### CLI — available + +``` +authcontract verify Verify one rule artifact's canonical identity +authcontract project Project a rule into its declared runtime action domain +authcontract check-action Check an action against a rule's declared domain +authcontract git-gate Check a CI result against the version that would actually merge +authcontract run-specimen Run the rule/fact/action check end to end; issue a receipt on PASS +authcontract verify-receipt Recompute a receipt from source and compare +``` + +Structured JSON on stdout, non-zero exit on refusal — so shell and CI integration is straightforward. + +### Python library — available + +```python +import json +from authcontract.veip import run_specimen, verify_receipt + +artifact = json.load(open("fixtures/banking_payment_specimen.json")) +action = json.load(open("fixtures/actions/send_payment_valid.json")) +facts = json.load(open("fixtures/runtime/facts_valid.json")) + +result = run_specimen(artifact, action, facts, execution_result="SIMULATED_SUCCESS") +print(result.decision, result.reason_code) # ALLOW OK + +if result.decision == "ALLOW": + check = verify_receipt(result.receipt, artifact, action, facts) + print(check.status, check.reason_code) # PASS OK +``` + +`run_specimen` returns a `RunResult` (`decision`, `reason_code`, `message`, `receipt`) and does **not** raise on an ordinary refusal — refusals are return values, not exceptions. + +### GitHub merge gate — available + +`.github/workflows/authcontract-gate.yml` runs `authcontract git-gate` as a required status check. It re-resolves the base ref live and proves the evaluated commit really contains both the base and the PR head, so a stale or isolated-head result cannot pass. + +### Runtime invocation and receipt verification — available + +`run-specimen` and `verify-receipt`, via CLI or library, as shown above. -Agentic software is increasingly allowed to do consequential things: +### Not available -- send payments -- approve transactions -- change customer state -- execute operational workflows -- make decisions from regulated or contractual requirements -- act on behalf of institutions +- **No published package.** Not on PyPI; install from source. +- **No HTTP/gRPC service.** In-process library and CLI only. +- **No persistence layer.** Stateless over in-memory inputs; receipts are not stored for you. +- **No multi-contract registry.** One artifact is evaluated per invocation; there is no cross-contract selection. +- **No replay protection.** Replayed identical requests produce identical receipts — this is determinism, not protection. No nonce or single-use semantics exist. -Developers turn requirements into executable rules. +--- + +## What is *not* implemented + +Read this before forming expectations. The worked conceptual examples later in this document describe **target** behavior. -That creates a simple problem: +- **Automated natural-language source-to-rule comparison is not implemented end to end.** This is the product's defining target capability and does not exist yet. Rules are authored as `.ac` artifacts today. +- Not production-ready. Not audited. Not security-certified. Not regulatory-approved. No formal proof. +- No universal policy correctness, general legal correctness, or arbitrary-domain compatibility. +- No production-grade institutional identity or PKI. +- No concurrency, distribution, or measured multi-core scaling. +- Evidence scope is one synthetic banking specimen family — not a general solution. -**How do you know the rule in the code actually says what the source says?** +Measured evidence and its limits: [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) · maturity assessment: [`docs/TRL-ASSESSMENT.md`](docs/TRL-ASSESSMENT.md). -A rule can look reasonable, pass ordinary unit tests, and still introduce a threshold, exception, permission, or interpretation that the source never established. +--- -AuthContract makes that relationship testable. +## License -Instead of asking: +**No license is currently declared.** This repository contains no `LICENSE` file and `pyproject.toml` declares no license field. Absent an explicit grant, default copyright applies and no usage rights are conferred — so treat this as source-available for evaluation and reading, not as open source. If you need licensed use, ask the repository owner. -> Did the code run correctly? +--- -AuthContract also asks: +## Where to go next -> Is the rule the code is running actually supported by the source? +| If you want to… | Go to | +|---|---| +| See measured performance and correctness evidence | [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) | +| Reproduce the benchmarks yourself | [`benchmarks/README.md`](benchmarks/README.md) | +| Understand current maturity honestly | [`docs/TRL-ASSESSMENT.md`](docs/TRL-ASSESSMENT.md) | +| See what is planned and why | [`docs/ROADMAP.md`](docs/ROADMAP.md) | +| Validate a clean clone yourself | [`docs/CLEANROOM-VALIDATION-RUNBOOK.md`](docs/CLEANROOM-VALIDATION-RUNBOOK.md) | +| Understand the terminology | [`docs/DEVELOPER-LANGUAGE.md`](docs/DEVELOPER-LANGUAGE.md) | +| See how this compares to other systems | [`docs/SOTA.md`](docs/SOTA.md) | +| Understand the full conceptual model | keep reading below | +--- --- -**Implementation status:** experimental reference implementation. The current code tests the mechanical trust chain for one synthetic banking specimen; the automated natural-language source-to-rule comparison shown in the examples below is target behavior and is not yet implemented end to end. See [Current status](#current-status) for the full boundary. +# How it works — the full model + +Everything above is runnable today. Everything below explains the model the implementation is built toward, including worked examples of the **target** source-to-rule comparison that is not yet implemented end to end. --- @@ -415,84 +630,6 @@ The `.ac` artifact exists so that the meaning being reviewed does not disappear --- -## Quick start - -Install the current reference implementation: - -```bash -pip install -e ".[test]" -``` - -Run the test suite: - -```bash -pytest -q -``` - -Verify an AuthContract fixture: - -```bash -authcontract verify fixtures/valid.json -``` - -Project the banking specimen into its declared runtime domain: - -```bash -authcontract project fixtures/banking_payment_specimen.json -``` - -Check an action: - -```bash -authcontract check-action \ - fixtures/banking_payment_specimen.json \ - fixtures/actions/send_payment_valid.json -``` - -Run the check that ties a rule, its runtime facts, and an action together, and get a proof receipt back on PASS: - -```bash -authcontract run-specimen \ - fixtures/banking_payment_specimen.json \ - fixtures/actions/send_payment_valid.json \ - fixtures/runtime/facts_valid.json \ - --execution-result SIMULATED_SUCCESS -``` - -Re-run the evidence — independently recompute the receipt bindings from the raw artifact, action, and fact inputs and compare: - -```bash -authcontract verify-receipt \ - fixtures/runtime/receipt_valid.json \ - fixtures/banking_payment_specimen.json \ - fixtures/actions/send_payment_valid.json \ - fixtures/runtime/facts_valid.json -``` - -The CLI prints structured JSON and exits non-zero on refusal. - -Example: - -```json -{ - "status": "PASS", - "reason_code": "OK" -} -``` - -or: - -```json -{ - "status": "REFUSED", - "reason_code": "RUN_UNCLASSIFIED_ACTION" -} -``` - -Reason codes are stable machine-facing identifiers. - -The surrounding developer experience should explain what they mean in plain language. - --- ## Example: action outside the rule From 35e2bef2060d113cefaf13f8c1da2a08c47559ac Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:23:48 +0000 Subject: [PATCH 2/4] AC-036: restore accepted developer-language invariants broken by the restructure The AC-021/AC-021A/AC-021B documentation guards caught three real regressions the restructure introduced. All three are restored; no assertion was weakened. 1. The accepted quickstart sentence 'Re-run the evidence - independently recompute the receipt bindings from the raw artifact, action, and fact inputs and compare:' was deleted with the old Quick start section. Restored verbatim, now attached to the receipt-verification step where it belongs. 2. The literal '**Implementation status:**' marker was replaced by a reworded callout. Restored, carrying its required clauses verbatim: the one-synthetic-banking-specimen scope and the statement that automated natural-language source-to-rule comparison is target behavior and is not yet implemented end to end. It still precedes the first worked example. 3. The '## Quick start' heading was removed. It anchors an accepted structural invariant - deep ontology vocabulary (OIC, ZTL, OAM, VEIP, AEP) must sit below it. Restored by naming the top install section 'Quick start', which satisfies the invariant more strongly than before: it now sits at line 23 rather than line 418. Also reworded the verify-receipt line in the CLI table to avoid the phrasing the guard bans, rather than relying on capitalisation to slip past it. 342 passed. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e78b8c7..d0d623f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ AuthContract turns an institutional rule into a canonical, testable artifact — source → rule → PR → check → merge → runtime → proof ``` -> **Status: experimental reference implementation (TRL 4).** The mechanical trust chain below is implemented, tested, and benchmarked for one synthetic banking specimen. **Automated natural-language source-to-rule comparison is target behavior and is _not_ implemented end to end.** Nothing here is production-ready, audited, or certified. See [What is *not* implemented](#what-is-not-implemented) — read it before forming expectations. +**Implementation status:** experimental reference implementation (TRL 4). The current code tests the mechanical trust chain for one synthetic banking specimen; the automated natural-language source-to-rule comparison shown in the examples below is target behavior and is not yet implemented end to end. Nothing here is production-ready, audited, or certified. See [What is *not* implemented](#what-is-not-implemented) — read it before forming expectations — and [Current status](#current-status) for the full boundary. --- @@ -20,7 +20,7 @@ Ordinary tests ask *did the code run correctly?* AuthContract adds a second ques --- -## Run it now +## Quick start Requires **Python 3.10+** and `git`. No credentials, no services, no network beyond the clone and dependency install. @@ -82,7 +82,9 @@ Exit code `0`. The action was permitted, and you now hold a receipt describing e ### Independently verify that receipt -The receipt is only worth something if someone else can check it without trusting you. This recomputes **every** bound value from the raw artifact, action, and fact files — it trusts no field in the receipt itself: +The receipt is only worth something if someone else can check it without trusting you. It trusts no field in the receipt itself. + +Re-run the evidence — independently recompute the receipt bindings from the raw artifact, action, and fact inputs and compare: ```bash authcontract verify-receipt \ @@ -182,7 +184,7 @@ authcontract project Project a rule into its declared runtime action do authcontract check-action Check an action against a rule's declared domain authcontract git-gate Check a CI result against the version that would actually merge authcontract run-specimen Run the rule/fact/action check end to end; issue a receipt on PASS -authcontract verify-receipt Recompute a receipt from source and compare +authcontract verify-receipt Re-run the evidence: recompute the receipt bindings and compare ``` Structured JSON on stdout, non-zero exit on refusal — so shell and CI integration is straightforward. From cc32783c416a28862251ba50aa8ebda138f9cf58 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:26:35 +0000 Subject: [PATCH 3/4] AC-036: add clean-room repository usability record docs/REPOSITORY-USABILITY.md records the Gate E clean-room test performed from a genuinely fresh clone at 35e2bef, using only README instructions. Results: ~30-second comprehension PASS; install to first meaningful end-to-end success in ~24s against a five-minute budget; both deliberate refusals reproduced byte-for-byte (RUN_UNCLASSIFIED_ACTION, RUN_FACT_STALE, both exit 1, both correctly issuing no receipt); receipt verification reproduced; Python integration example executed verbatim from the README. Findings recorded rather than resolved: U1 no license is declared - stated truthfully in the README, but choosing a license is an owner decision, not an executor one U2 README remains long; the runnable surface is the first ~250 lines and the conceptual body is now explicitly fenced as target behavior U3 the AC-021 documentation guards constrain README structure, correctly - they caught three genuine regressions in the first draft U4 CLI emits single-line JSON; the README reflows it and says so U5 the benchmark DUT guard protects README.md, so documentation-only changes exit 2. Deliberately not worked around. No behavioral regression is possible: authcontract/, tests/, fixtures/, .github/, pyproject.toml and benchmarks/ are byte-identical to merged main 4c90aa7, where the benchmark last ran 7/7 and 38/38 green. Also links the usability record from the README's next-steps table. Does not self-certify Gate E. --- README.md | 1 + docs/REPOSITORY-USABILITY.md | 166 +++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 docs/REPOSITORY-USABILITY.md diff --git a/README.md b/README.md index d0d623f..b45d46e 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,7 @@ Measured evidence and its limits: [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) · | Understand current maturity honestly | [`docs/TRL-ASSESSMENT.md`](docs/TRL-ASSESSMENT.md) | | See what is planned and why | [`docs/ROADMAP.md`](docs/ROADMAP.md) | | Validate a clean clone yourself | [`docs/CLEANROOM-VALIDATION-RUNBOOK.md`](docs/CLEANROOM-VALIDATION-RUNBOOK.md) | +| See how this repository was usability-tested | [`docs/REPOSITORY-USABILITY.md`](docs/REPOSITORY-USABILITY.md) | | Understand the terminology | [`docs/DEVELOPER-LANGUAGE.md`](docs/DEVELOPER-LANGUAGE.md) | | See how this compares to other systems | [`docs/SOTA.md`](docs/SOTA.md) | | Understand the full conceptual model | keep reading below | diff --git a/docs/REPOSITORY-USABILITY.md b/docs/REPOSITORY-USABILITY.md new file mode 100644 index 0000000..12f195e --- /dev/null +++ b/docs/REPOSITORY-USABILITY.md @@ -0,0 +1,166 @@ +# Repository usability test (AC-036) + +A clean-room test of the repository as a **product surface**: can an unfamiliar +developer, following only `README.md`, understand what this is and get a +meaningful result quickly? + +Performed against commit `35e2bef2060d113cefaf13f8c1da2a08c47559ac` from a +genuinely fresh `git clone` — no reused virtualenv, no undocumented local +state, no commands invented outside the README. + +This document records observations. **It does not self-certify Gate E**; that +adjudication belongs to the Engineering Lead. + +--- + +## Environment + +| | | +|---|---| +| OS | Linux 6.18.44 x86_64 | +| Python | 3.11.15 (README requires ≥3.10) | +| git | 2.43.0 | +| Network | clone + PyPI dependency install only | +| Credentials | none required, none supplied | + +--- + +## Results + +### A. ~30-second comprehension — PASS + +The first screen (11 lines before the first `---`) delivers, in order: a +one-sentence definition, the `source → rule → PR → check → merge → runtime → +proof` chain, and an implementation-status note stating TRL 4, the +one-synthetic-specimen scope, and — unambiguously — that automated +natural-language source-to-rule comparison **is not implemented end to end**. + +A reader who stops after 30 seconds leaves with a correct impression rather +than an inflated one. That was the specific failure mode before this change: +the prior README opened with ~400 lines of worked examples of the *target* +capability, so the most prominent material described behavior that does not +exist yet. + +### B. Install + first meaningful success ≤ 5 minutes — PASS (~35 s) + +| Step | Elapsed | Cumulative | +|---|---:|---:| +| `git clone` + `git checkout` | 1 s | 1 s | +| `python3 -m venv` + `pip install -e ".[test]"` | 11 s | 12 s | +| `pytest -q` → **342 passed** | 11 s | 23 s | +| `authcontract run-specimen …` → PASS/ALLOW + receipt | <1 s | **~24 s** | + +Roughly **24 seconds** to a first meaningful end-to-end success, against a +five-minute budget. Even allowing for a cold PyPI cache and slower hardware, +the margin is large. + +No undocumented state was required. Every command came from the README. + +### C. Deliberate refusal reproducible — PASS (both cases) + +**Refusal 1 — undeclared action.** Exit code `1`: + +```json +{"status": "REFUSED", "reason_code": "RUN_UNCLASSIFIED_ACTION", + "message": "RUN_UNCLASSIFIED_ACTION: 'issue_refund' is not in the closed mediated-action universe for this projection"} +``` + +**Refusal 2 — stale runtime fact.** Exit code `1`: + +```json +{"status": "REFUSED", "reason_code": "RUN_FACT_STALE", + "message": "RUN_FACT_STALE: secondary_approval.present is older than 0:15:00"} +``` + +Both match the README byte-for-byte in `status`, `reason_code`, and `message`. +Both correctly issue **no receipt** — a refused decision does not emit evidence +claiming a decision was made. + +### D. Receipt verification reproducible — PASS + +```json +{"status": "PASS", "reason_code": "OK", "receipt": "receipt_valid.json", …} +``` + +Exit code `0`, matching the README. Verification recomputes every bound value +from the raw artifact, action, and fact files and trusts no field in the +receipt itself. + +### E. Integration path findable and understandable — PASS + +`## How to integrate it today` names four available interfaces (CLI, Python +library, GitHub merge gate, runtime invocation/receipt verification) and one +explicit **Not available** list. + +The Python example was executed verbatim from the README in the clean clone: + +``` +ALLOW OK +PASS OK +``` + +The "Not available" list is as load-bearing as the available one — it states +plainly that there is no published package, no HTTP/gRPC service, no +persistence layer, no multi-contract registry, and no replay protection. + +--- + +## Findings + +**U1 — No license is declared.** There is no `LICENSE` file and +`pyproject.toml` declares no license field, so default copyright applies and +no usage rights are granted. This is now stated truthfully in the README +rather than left for a reader to discover. **Not resolved here:** choosing a +license is an owner decision with legal effect, not an executor decision. + +**U2 — The README is long (1,215 lines).** The runnable product surface is the +first ~250; the remainder is conceptual material describing target behavior, +now explicitly fenced under "How it works — the full model". A future pass +could move that body into `docs/`, but doing so here would have exceeded +AC-036's product-surface scope and risked disturbing accepted +developer-language content. + +**U3 — Documentation guards constrain README structure, correctly.** The +AC-021/AC-021A/AC-021B tests pin specific README sentences and one structural +invariant (deep ontology vocabulary must sit below `## Quick start`). The first +draft of this restructure broke three of them; all were restored, none was +weakened. Anyone editing the README should expect these guards to fire — they +are a feature, and they caught genuine claim-ceiling drift here. + +**U5 — The benchmark's DUT guard treats `README.md` as a protected surface, so +documentation-only changes trip it.** Running `benchmarks/run_benchmarks.py` on +this branch exits `2` with `DUT DRIFT: 1 file(s) differ` — that file being +`README.md`. This is the guard behaving **correctly**: it refuses to publish +results claiming to describe `e4e1a975` when any declared device-under-test +path differs, and `README.md` is in that list because AC-035A protected it. + +It was deliberately **not** worked around. Weakening the guard, or trimming +`README.md` out of `DUT_PATHS`, to make a documentation PR go green would +defeat the property the guard exists to provide. + +No behavioral regression is possible from this change: `authcontract/`, +`tests/`, `fixtures/`, `.github/`, `pyproject.toml`, and `benchmarks/` are +**byte-identical** to merged main `4c90aa79dd922888a8beb3aa9d886c44ecc28c7c`, +where the full benchmark last ran 7/7 end-to-end and 38/38 adversarial with +exit `0`. The only file changed against that commit is `README.md`. + +A future refinement could split `DUT_PATHS` into behavioral and documentary +sets, so doc changes are reported without blocking. That is a benchmark-design +decision, out of scope for AC-036. + +**U4 — CLI output is single-line JSON.** Readable via `jq` or `python3 -m +json.tool`, but not pretty-printed natively. The README reflows it for +readability and says so explicitly, rather than implying prettier output than +the CLI produces. + +--- + +## Not tested + +- Windows and macOS. Linux only. +- Python 3.10 and 3.12 were not exercised here, though repository CI covers both. +- Cold-cache install timing on constrained networks. +- Comprehension by an actual unfamiliar human. This test was performed by the + same party that wrote the README, which is a real limitation: it can + establish that the documented path *works*, but not that the explanation + *lands* for a genuine newcomer. Independent review remains the gap. From 0d380e8bb55ba6890fe47b4205bb38a8d7396af9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:35:49 +0000 Subject: [PATCH 4/4] AC-036S: correct an unverifiable enforcement claim about the gate workflow Documentation truthfulness only. No workflow, runtime, test, fixture, or repository-configuration change. The defect was mine, introduced by the AC-036 restructure. The new integration section stated that authcontract-gate.yml runs git-gate "as a required status check". That asserts GitHub repository configuration, not repository content - and the two are independent. A workflow file can exist while branch protection requires nothing. Notably the README already carried the correct boundary further down: "Repository-level branch protection requiring that check is a separate GitHub configuration concern and should not be inferred merely because the workflow exists." The front matter contradicted an accepted statement in the same document. Corrected to say what is actually true of the repository: the workflow exists, it runs git-gate on pull requests, and it re-resolves the base ref so a stale or isolated-head result cannot pass the gate's own check - followed by an explicit statement that the workflow's presence does not establish that GitHub requires it, and that enforcement lives in branch protection or rulesets. This executor could not independently verify the branch-protection state: this session's GitHub toolset exposes no branch-protection read endpoint. That is itself the argument for the correction - an unverifiable claim should not be published as fact, and the corrected wording is accurate under either enforcement state. Section heading changed from "GitHub merge gate" to "GitHub merge-gate workflow" so the heading itself does not imply enforcement. All AC-021/AC-021A/AC-021B guards re-verified intact; 342 passed. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b45d46e..85b18d3 100644 --- a/README.md +++ b/README.md @@ -209,9 +209,11 @@ if result.decision == "ALLOW": `run_specimen` returns a `RunResult` (`decision`, `reason_code`, `message`, `receipt`) and does **not** raise on an ordinary refusal — refusals are return values, not exceptions. -### GitHub merge gate — available +### GitHub merge-gate workflow — available -`.github/workflows/authcontract-gate.yml` runs `authcontract git-gate` as a required status check. It re-resolves the base ref live and proves the evaluated commit really contains both the base and the PR head, so a stale or isolated-head result cannot pass. +The repository includes `.github/workflows/authcontract-gate.yml`, which runs `authcontract git-gate` on pull requests. It re-resolves the base ref live and proves the evaluated commit really contains both the base and the PR head, so a stale or isolated-head result cannot pass the gate's own check. + +**The workflow's presence does not mean GitHub requires it.** Whether a check is *enforced* — that is, whether branch protection blocks a merge when it fails — is a separate GitHub repository-configuration concern, set in branch protection or rulesets rather than in the workflow file. Do not infer enforcement from the fact that this workflow exists; verify the repository's own branch-protection settings if you need to know what is actually required to merge. ### Runtime invocation and receipt verification — available