Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jobs:
python: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false # tests only read the repo; no authenticated git ops
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: { python-version: "${{ matrix.python }}" }
- run: uv sync --all-extras
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/public-microbench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false # read-only benchmark harness; no authenticated git ops
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: { python-version: "3.12" }
- run: uv sync --all-extras
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publish-testpypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ inputs.ref }}
persist-credentials: false # build from the tag only; publish is OIDC, not git creds
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with: { python-version: "3.12" }
- name: Build sdist + wheel
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ inputs.ref }}
persist-credentials: false # build from the tag only; publish is OIDC, not git creds
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/release-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ jobs:
with:
ref: ${{ inputs.ref || github.ref }}
fetch-depth: 0
persist-credentials: false # build/test only read the repo; no authenticated git ops
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: { python-version: "${{ matrix.python }}" }
with:
python-version: "${{ matrix.python }}"
enable-cache: false # release validation: no cache, build/test from a clean resolve
- run: uv sync --all-extras
- run: uv run ruff check src tests bench
- run: uv run ruff format --check src tests bench
Expand All @@ -54,6 +57,7 @@ jobs:
with:
ref: ${{ inputs.ref || github.ref }}
fetch-depth: 0
persist-credentials: false # build + Sigstore attest via OIDC; no authenticated git ops
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with: { python-version: "3.12" }
- name: Build sdist + wheel
Expand Down
22 changes: 18 additions & 4 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false # read-only SCA/SAST; no authenticated git ops
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: { python-version: "3.12" }
- run: uv sync --all-extras
# SCA: audit the resolved dependency tree (dev + extras) for known CVEs.
# Runtime deps are [], so the value is the dev/extras transitive trees.
- name: pip-audit (SCA)
run: uvx pip-audit
# SCA: audit DORIAN'S resolved dependency set (runtime + extras + dev), NOT the
# isolated pip-audit tool environment. Export the resolved tree to a requirements
# file (`--no-emit-project` drops the editable `-e .` self-reference) and audit that.
- name: Export project dependency set (runtime + extras + dev)
run: >-
uv export --all-extras --dev --no-hashes --no-emit-project
--format requirements.txt -o /tmp/dorian-audit-requirements.txt
- name: Verify the audit targets the project deps (not pip-audit's own env)
run: |
for dep in duckdb anthropic pytest; do
grep -qE "^${dep}==" /tmp/dorian-audit-requirements.txt \
|| { echo "audit scope regression: ${dep} missing from requirements"; exit 1; }
done
echo "audit scope confirmed: project deps present"
- name: pip-audit (SCA — project dependency set)
run: uvx --python 3.12 pip-audit -r /tmp/dorian-audit-requirements.txt
# SAST: static analysis of first-party source. Excludes the documented,
# policy-gated execution primitives via [tool.bandit] in pyproject.toml.
- name: bandit (SAST)
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ bench/real/
/AUDIT_RELEASE_GATE.md
/GITHUB_RELEASE_NOTES.md
research/
research_packets/
codex_validation/
.bench/
.release/
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with: { fetch-depth: 0 } # revalidate diffs against the PR base sha
- uses: ajaysurya1221/dorian/action@main
with:
fetch-depth: 0 # revalidate diffs against the PR base sha
persist-credentials: false # the Action only reads the diff + posts via GITHUB_TOKEN
- uses: ajaysurya1221/dorian/action@v1.0.2
with:
fail_on: revoked
# until the PyPI release, install from source:
install: 'dorian-vwp @ git+https://github.com/ajaysurya1221/dorian.git'
# install defaults to the published PyPI package (dorian-vwp); pin a
# version or set a git source spec to install unreleased changes
```

Now that `dorian` is installed, the copy-paste runnable demo at the top —
Expand Down Expand Up @@ -508,7 +510,7 @@ work perishable, so you find out when it expired.
**reproducible on those frozen SHAs only** — not a real-world performance claim; the trigger and
truth layers are reported separately.
- **PyPI trusted publishing** — `dorian-vwp` is published to PyPI via a Trusted Publisher
(latest: **`v1.0.0`**); `pip install dorian-vwp` installs the released package.
(latest: **`v1.0.2`**); `pip install dorian-vwp` installs the released package.

Non-goals stay non-goals: no servers, no dashboards, no hosted control plane, no model at check time.
Local-first is the design center.
Expand Down
7 changes: 4 additions & 3 deletions action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ jobs:
with:
fetch-depth: 0 # REQUIRED: revalidate diffs against the PR base
# sha, which a shallow clone does not contain
- uses: ajaysurya1221/dorian/action@v1.0.0
persist-credentials: false # the Action reads the diff + posts via GITHUB_TOKEN
- uses: ajaysurya1221/dorian/action@v1.0.2
with:
fail_on: revoked
# install defaults to the published PyPI package (dorian-vwp);
Expand Down Expand Up @@ -77,7 +78,7 @@ self-attested-verdict problem for *non-executable* checkers — that is what

```yaml
# untrusted / public-fork posture
- uses: ajaysurya1221/dorian/action@v1.0.0
- uses: ajaysurya1221/dorian/action@v1.0.2
with:
deny_exec: "true" # C4/C5 ERROR instead of executing
```
Expand All @@ -93,7 +94,7 @@ executed). Implemented and proven by the

```yaml
# public / forked-PR posture: trusted checker specs + no code execution
- uses: ajaysurya1221/dorian/action@v1.0.0
- uses: ajaysurya1221/dorian/action@v1.0.2
with:
checker_trust: base # run only base-approved checker specs
deny_exec: "true" # and refuse to execute even those (belt and braces)
Expand Down
85 changes: 85 additions & 0 deletions docs/ANNOUNCEMENT_READINESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Announcement readiness — dorian v1.0.2

A modest, evidence-linked checklist for announcing v1.0.2. Keep every public claim inside the
honest scope below. When in doubt, say less.

## Exact install & demo

```bash
pip install dorian-vwp # 1.0.2 on PyPI
```

30-second demo (also pinned by a black-box test):

```bash
tmp=$(mktemp -d) && cd "$tmp" && git init -q
printf 'def handler():\n return 200\n' > app.py
printf '# change note\n\n`handler()` lives in app.py.\n' > note.md
git add -A && git commit -q -m "app + note"
cat > claims.json <<'JSON'
{"claims": [
{"id": "handler-exists", "text": "handler() lives in app.py.",
"kind": "behavior", "load_bearing": true,
"checkers": [{"type": "C3", "program": "symbol:app.py::handler"}]}
]}
JSON
dorian verify note.md --claims claims.json # -> verified 1/1 (exit 0)
printf 'def renamed():\n return 200\n' > app.py
dorian revalidate --since HEAD # -> handler-exists BROKEN; WARRANTED -> REVOKED (exit 4)
```

## Allowed claims (true and evidenced)

- "dorian v1.0.2 is live on GitHub and PyPI." — *only after both are confirmed.*
- "dorian has one documented, reproducible real cross-PR catch on `encode/httpx`." — `docs/REAL_CATCH_LOG.md`.
- "The catch is scoped: it proves one bound claim can be revoked when its watched fact changes; it is not broad validation."
- "dorian is local-first and token-free at check time."
- "dorian is not a sandbox; executable checker policies (`--deny-exec`/`checker_trust: base`) are fail-closed controls, not isolation."

## Forbidden claims (do not say)

"validated on real repos" · "works on real repos" · "production-grade" · "catches all drift" ·
"catches bugs" · "better than CodeRabbit" · "proves dorian works" · "fully solves AI code
verification" · fake users/stars/adoption · "secure for untrusted public forks by default" ·
"in-toto standard" / "official predicate".

## Exact "one real catch" wording

> On the public repo `encode/httpx` (BSD-3, frozen SHAs), a load-bearing claim sealed when
> `requires-python` was `">=3.8"` was flipped `WARRANTED → REVOKED` (exit 4) by a real later
> upstream PR (#3592, "Drop Python 3.8 support") while httpx's own tests stayed green and no
> stateless per-PR review would have re-opened the original claim. One documented catch,
> independently reproduced — not broad validation.

## Evidence checklist (all verified for v1.0.2)

- [x] PyPI `dorian-vwp` serves the announced version (1.0.2) — verify with `pip install dorian-vwp` after publish.
- [x] README first install path provides `suggest-claims` and `export --in-toto`.
- [x] README 30-second demo passes from a fresh install (verify=0, revalidate=4, REVOKED).
- [x] No `dorian/action@main` in public copy-paste (guarded).
- [x] Security workflow audits the project dependency set (guarded).
- [x] Checkout steps drop credentials where unneeded.
- [x] `export` `.warrant` filename and `suggest-claims` PEP 263 bugs fixed + regression-tested.
- [x] Full pytest, ruff, bandit, project-scope pip-audit, build + twine check all green.
- [x] Real catch reproduces on this build (httpx, frozen SHAs).
- [x] Overclaim/secret scans clean.

## Launch post draft (short, honest, evidence-linked)

> **dorian v1.0.2 is live** (PyPI `dorian-vwp`, GitHub release). It's a deterministic, local-first,
> token-free way to hold a change to the explicit claims someone made about it: bind a
> natural-language claim to a checker, seal a `.warrant`, and re-check only what a later change
> touches.
>
> Why it matters: a sealed claim persists across commits, so drift gets caught when a stateless
> per-PR check wouldn't re-open the original claim.
>
> One documented, reproduced real catch: on `encode/httpx` (frozen SHAs), a load-bearing
> `requires-python >=3.8` claim flipped to REVOKED when a later upstream PR raised the floor to
> 3.9 — while httpx's own tests stayed green. Scoped: it proves one bound claim can be revoked,
> not broad validation.
>
> `pip install dorian-vwp` — 30-second demo in the README.
>
> Note on safety: dorian is **not** a sandbox. Executable checker policies (`--deny-exec`,
> `checker_trust: base`) are fail-closed controls, not isolation.
2 changes: 1 addition & 1 deletion docs/ATTESTATION_INTEROP.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ choice.
"predicate": {
"warrantId": "sha256:...",
"specVersion": "...",
"dorianVersion": "1.0.0",
"dorianVersion": "<current dorian version>",
"gitRef": "<commit at seal>",
"sealedAt": "<RFC3339>",
"bornVerifiable": true,
Expand Down
4 changes: 2 additions & 2 deletions docs/BENCHMARK_CURRENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ and are kept as-is for provenance.

| field | value |
| --- | --- |
| dorian version | `1.0.1` |
| dorian version | `1.0.2` |
| metric commit | `33e9eaf` (the benchmark figures were measured here, during the release audit) |
| release commit | `81cebbc` (1.0.1). Changes since the metric commit include checker edge-case fixes (C4 leading-dash nodeid rejection, C5 reconcile per-query timeout), a byte-identical index-once `verify` refactor, and two additive commands (`suggest-claims`, `export --in-toto`); both suites below were **re-run at 1.0.1 and reproduce the metric-commit figures exactly** (binding-lifecycle to the same content-derived `run_id`), so these changes do not move what the suites measure |
| release commit | `81cebbc` (1.0.1) → v1.0.2 announcement hotfix. The 1.0.1 changes (C4 leading-dash nodeid rejection, C5 reconcile per-query timeout, a byte-identical index-once `verify` refactor, the `suggest-claims` / `export --in-toto` commands) plus the v1.0.2 hotfix (export `.warrant` filename disambiguation, `suggest-claims` PEP 263 encoding read, a `symbol_index` non-git `GitError` guard, and CI/SCA/credential/doc hardening) touch no checker numeric behavior; both suites below were **re-run at 1.0.2 and reproduce the metric-commit figures exactly** binding-lifecycle to the same content-derived `run_id` `168b50d9aa631d52` — so these changes do not move what the suites measure |
| Python | 3.12.4 |
| platform | darwin (CI matrix: 3.11 / 3.12 / 3.13) |
| reproduce | `dorian bench large-mutation` · `dorian bench binding-lifecycle` · `dorian bench realworld-usecases` |
Expand Down
85 changes: 85 additions & 0 deletions docs/releases/v1.0.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# dorian 1.0.2

An announcement-readiness hotfix on top of 1.0.1. **No breaking changes**: the warrant format,
checker grammar, exit codes, and trust semantics are unchanged. The point of this release is
public-facing coherence — one version across PyPI, README, the Action docs, and the GitHub
release — plus two edge-case bug fixes, a real SCA-scope fix, and CI credential hardening.

It resolves the post-1.0.1 use-and-see validation findings (Codex GPT-5.5 `HOTFIX_BEFORE_ANNOUNCE`).

## Why this release exists

1.0.1 was real on GitHub but `pip install dorian-vwp` still served **1.0.0**, while the README
documented 1.0.1-only commands (`suggest-claims`, `export --in-toto`). 1.0.2 is published to
PyPI so the documented install path and command surface agree with the package a new user gets.

## Public-trust fixes

- **PyPI coherence (FINDING-01)** — 1.0.2 is published to PyPI via the Trusted-Publisher
workflow, so `pip install dorian-vwp` provides the documented command surface. README,
release docs, and install examples point to one coherent version.
- **Immutable Action ref (FINDING-02)** — the README Getting-Started snippet pinned
`dorian/action@main` (a moving target). It and the action docs now use `@v1.0.2`. A new
version-sync guard fails CI if `dorian/action@main` reappears in public copy-paste.
- **SCA audits the project, not the tool (FINDING-03)** — `security.yml` ran `uvx pip-audit`,
which audited pip-audit's **own** isolated environment, not dorian's dependencies. It now
exports the resolved project set (`uv export --all-extras --dev --no-emit-project`) and audits
that, with a step that asserts the project deps (duckdb/anthropic/pytest) are actually present.
- **Checkout credential hardening (FINDING-04)** — every `actions/checkout` step now sets
`persist-credentials: false`; none of these workflows perform authenticated git operations
(the release/publish lanes mint short-lived OIDC tokens, not git credentials).
- **Release-gate determinism** — the release-gate test job disables the uv cache
(`enable-cache: false`) so release validation runs from a clean resolve.

## Bug fixes

- **`export` of an artifact literally named `*.warrant` (FINDING-05)** — `dorian export`
unconditionally stripped a `.warrant` suffix, so `dorian export foo.warrant` looked for the
wrong sidecar and failed. It now prefers reading the input as the artifact (so `foo.warrant`
exports its own `foo.warrant.warrant` sidecar) and only treats a `.warrant`-suffixed input as
a sidecar path when the artifact has no sidecar of its own. Regression-tested.
- **`suggest-claims` on PEP 263 (non-UTF8) Python (FINDING-06)** — the file was read with a
hardcoded UTF-8 decode, so valid Python declaring e.g. `# -*- coding: latin-1 -*-` was
rejected. It now parses the file's bytes so the encoding cookie is honored; an unknown/declared-
wrong codec surfaces as a clear usage error, not a traceback. Regression-tested.
- **`symbol_index` non-git robustness** — `pyproject_script_definers` reached `git ls-files`
unguarded, so with a precomputed definer map plus a `[project.scripts]` table a non-git
checkout raised `GitError` instead of degrading to `{}` (breaking the documented "non-git
yields {}" contract of `claim_symbol_watch_paths`). The git call is now guarded; the symbol
binding is preserved, only the git-dependent script-target resolution degrades. Regression-tested.

## Docs / guards

- **Attestation-interop example (FINDING-07)** — the in-toto example pinned a fixed
`"dorianVersion": "1.0.0"`; it is now version-neutral, with a guard against a hardcoded value.
- **Stronger determinism test (FINDING-08)** — the in-toto determinism test now asserts both
CLI invocations succeed before comparing output bytes.
- **Stale-wording guard (FINDING-09)** — the version-sync guard now also catches "until the PyPI
release" (the narrower variant that slipped past the "first PyPI release" family).

## Tests & gates

Full suite green at 1.0.2 (874 tracked tests, +5 new regression tests for the fixes above), ruff
clean, bandit clean, project-scope pip-audit clean, wheel/sdist build + `twine check` pass.
Both reproducible benchmark suites were **re-run at 1.0.2 and reproduce the 1.0.1 figures
exactly** (large-mutation P=R=0.93; binding-lifecycle to the same content-derived `run_id`), so
the hotfix touches no checker numeric behavior. The documented `encode/httpx` real catch was
**independently reproduced** on this build (verify exit 0 → revalidate exit 4 → `REVOKED`,
`httpx-python-floor-38` BROKEN).

## Honest scope (unchanged)

dorian has **one documented, reproduced real cross-PR catch** on frozen public SHAs — not broad
real-world validation. The benchmark suites are reproducibility evidence on frozen fixtures only.
`--deny-exec`/`--deny-shell` are fail-closed policies, **not** sandboxes; `checker_trust: base`
is a checker-source trust root, not a sandbox. `suggest-claims` checks existence/value, not
behavior (a gutted body keeps a `symbol:` claim green); the in-toto export is experimental and
not a registered in-toto predicate. A warrant id is content-addressed and **tamper-evident**, but
its body includes the seal timestamp, so a fresh seal yields a different id — what reproduces is
the outcome, not the id.

## Install

```bash
pip install dorian-vwp # 1.0.2 on PyPI
```
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "dorian-vwp"
version = "1.0.1"
version = "1.0.2"
description = "Hold AI agents to what they said they did: deterministic, token-free verification of claims about a change."
readme = "README.md"
requires-python = ">=3.11"
Expand Down
2 changes: 1 addition & 1 deletion src/dorian/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
PyPI distribution: `dorian-vwp`; import package: `dorian`; CLI: `dorian`.
"""

__version__ = "1.0.1"
__version__ = "1.0.2"
Loading