From 442e61bce4477decd58ced99f1a55aabef5c9430 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 22:45:49 -0400 Subject: [PATCH 1/7] docs: design post-v0.2.3 development identity --- ...9-post-v023-development-identity-design.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-09-post-v023-development-identity-design.md diff --git a/docs/superpowers/specs/2026-08-09-post-v023-development-identity-design.md b/docs/superpowers/specs/2026-08-09-post-v023-development-identity-design.md new file mode 100644 index 0000000..dcef84b --- /dev/null +++ b/docs/superpowers/specs/2026-08-09-post-v023-development-identity-design.md @@ -0,0 +1,107 @@ +# Post-v0.2.3 Development Identity Design + +## Context + +ScopeProof v0.2.3 is published from the immutable release commit +`448c42758ea139bf9203cbf1bb04b02b02ae412c`. The current development tree contains later merged +engineering work for CLI lifecycle parity, strict saved-record validation, installed-wheel browser +coverage, Python 3.13, bounded keyboard/focus and zoom checks, and verified-public provenance. The +single checked-in version source still reports `0.2.3`, and the Unreleased changelog section is +empty. A wheel built from current `main` can therefore have different bytes and behavior while +presenting the same final version as the published release. + +This work restores package and documentation identity only. It does not alter evidence evaluation, +gate behavior, persistence, exports, GitHub ingestion, or the published v0.2.3 tag and assets. + +## Decision + +Advance the single development version source to `0.2.4.dev0`. That is the next PEP 440 +development line after the published `0.2.3` release and matches ScopeProof's established +post-release convention. + +Add a repository contract that binds every final version named in its published-release ledger to +the exact Git tree recorded for that release. When the working tree reports a published final +version, the committed tree must match the corresponding release tag tree. A later committed tree +that still reports `0.2.3` therefore fails closed; a development version such as `0.2.4.dev0` is not +mistaken for a published final release. + +Reconcile current-facing documentation so it distinguishes: + +- the immutable, publicly installable v0.2.3 release; +- the current `0.2.4.dev0` source line and its post-release engineering evidence; +- historical audits bound to their named commits and versions; and +- unsupported real-environment and external-validation claims. + +## Version and release contract + +`scopeproof_core/version.py` remains the only package-version source. Hatch metadata, imported +module identity, both CLI version commands, and new review provenance continue to derive from it. + +The repository contract keeps an explicit mapping from published final version `0.2.3` to tag +`v0.2.3`. It resolves the current committed tree and release-tag tree with Git and requires equality +only when the current source identifies as that published final version. The contract also requires +the expected release constants and the development version, making a silent reuse of the final +version fail in CI before packaging can be accepted. + +The tag, GitHub Release, checksums, and historical candidate/audit artifacts remain unchanged. This +branch does not create or publish a `0.2.4` artifact. + +## Documentation model + +The authoritative active surfaces are updated together: + +- `CHANGELOG.md` records all work merged after v0.2.3 under `Unreleased`. +- `README.md` names v0.2.3 as the public install and `0.2.4.dev0` as unreleased source. +- `ROADMAP.md` records completed post-release engineering separately from Stage 1 progress. +- `docs/development-environment.md` describes the development identity and verified Python 3.11, + 3.12, and 3.13 engineering lanes without implying desktop-platform support. +- The v0.2.3 status page and platform/package matrix retain historical release evidence while adding + a dated post-release status boundary. +- The market comparison removes CLI lifecycle parity and keyboard/focus from current gaps, while + preserving screen-reader, Windows desktop, Linux desktop, non-Chromium, and WCAG limitations. +- Superseded verification audits receive explicit historical-boundary notices where a reader could + otherwise mistake their version or unsupported-environment statements for current truth. Their + original measurements, hashes, and commit-specific conclusions are not rewritten. + +All active surfaces retain the exact Stage 1 counts at zero and state that engineering evidence +earns no Stage 1 credit. + +## Alternatives considered + +- Keep `0.2.3`: rejected because post-release source and wheel bytes would remain ambiguous with the + published final release. +- Use `0.2.3.post1`: rejected because no post-release distribution is being published and the tree + is the next development line, not a corrective published artifact. +- Use `0.2.4`: rejected because that would present the branch as a final release before an owner + release gate. +- Assert only the literal expected version in a test: insufficient by itself because the same + ambiguity could recur after a future release. The release-tree binding makes the invariant + reusable. +- Rewrite historical audits to current wording: rejected because that would destroy exact-head + provenance. Additive supersession notes preserve both historical evidence and current clarity. + +## Verification + +Start with a focused repository-contract regression that fails while current source still reports +`0.2.3`, then change the version and make it pass. Add documentation contracts for the development +identity, Unreleased ledger, completed engineering evidence, unsupported environments, and unchanged +Stage 1 counts. + +The final head must pass Ruff, the complete suite with at least 95 percent combined coverage, +repository contracts, both deterministic benchmarks, two reproducible wheel builds with identical +SHA-256, artifact-inventory inspection, clean installation and dependency validation, installed and +source version equality, both CLI versions, installed benchmarks, exact loopback health, the +installed-wheel Chromium regression, every currently supported Python/CI lane, diff and commit +audit, independent review, and all available GitHub checks. + +These results are controlled engineering evidence only. They do not execute target-repository code, +prove correctness, establish accessibility conformance or desktop-platform support, or advance +Stage 1. + +## Boundaries + +No release, tag, package publication, merge, issue mutation, participant contact, outreach, R-002 +retuning, R-003 generation, beta activation, private-repository support, paid API, or product-scope +expansion is authorized. The GitHub Action remains opt-in and informational. Reviewer and +source-owner identity remain asserted, not authenticated. Real screen-reader operation, Windows +desktop, Linux desktop, non-Chromium browsers, and WCAG conformance remain unsupported. From 511c3220f72c802cc42cd47e2bd54ec43a92fbd9 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 22:47:00 -0400 Subject: [PATCH 2/7] docs: plan post-v0.2.3 development identity --- ...26-08-09-post-v023-development-identity.md | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 docs/superpowers/plans/2026-08-09-post-v023-development-identity.md diff --git a/docs/superpowers/plans/2026-08-09-post-v023-development-identity.md b/docs/superpowers/plans/2026-08-09-post-v023-development-identity.md new file mode 100644 index 0000000..2732d12 --- /dev/null +++ b/docs/superpowers/plans/2026-08-09-post-v023-development-identity.md @@ -0,0 +1,143 @@ +# Post-v0.2.3 Development Identity Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this +> plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Give the post-v0.2.3 source line an unambiguous development identity and reconcile active +documentation without changing published release evidence or product behavior. + +**Architecture:** Keep `scopeproof_core/version.py` as the single runtime and package version source. +Extend repository contracts with a published-final-version-to-tag ledger and a real Git-tree +comparison so a divergent committed tree cannot reuse a published final version. Update only active +status surfaces or add historical-boundary notices; never rewrite commit-bound measurements. + +**Tech Stack:** Python 3.12, Hatchling, pytest, Ruff, Git, uv, Playwright Chromium. + +## Global constraints + +- Development version is exactly `0.2.4.dev0`; public install remains v0.2.3. +- Published tag `v0.2.3`, release assets, checksums, and historical evidence remain unchanged. +- No schema, gate, lifecycle, persistence, export, ingestion, dependency, or workflow behavior + changes. +- Stage 1 remains exactly 0/5, 0/3, 0/3, 0/3, and 0/2; engineering work earns zero credit. +- Real screen-reader, Windows desktop, Linux desktop, non-Chromium, and WCAG evidence remain + unsupported. +- Stage named files only. Preserve `.coverage 2`. Do not merge, release, tag, publish, or contact + participants. + +--- + +### Task 1: Add the published-version tree guard test-first + +**Files:** +- Modify: `tests/test_repository_contracts.py` +- Modify: `scopeproof_core/version.py` + +- [ ] Add a focused repository contract that maps final version `0.2.3` to `v0.2.3`, resolves the + actual Git trees, and rejects the current divergent tree while it still identifies as `0.2.3`. +- [ ] Run the focused test and require RED for the specific published-version/tree mismatch. +- [ ] Change only `scopeproof_core/version.py` to `__version__ = "0.2.4.dev0"`. +- [ ] Rerun the focused contract and existing CLI/version provenance tests; require GREEN. +- [ ] Mentally mutate the version back to `0.2.3` and confirm the new contract is the test that + would fail. + +### Task 2: Record the complete Unreleased engineering ledger + +**Files:** +- Modify: `CHANGELOG.md` +- Modify: `tests/test_repository_contracts.py` + +- [ ] Add a focused documentation contract for an `Unreleased` section that distinguishes the + current development version from v0.2.3 and records CLI lifecycle parity, strict saved-record + envelope validation, packaged Chromium regression, Python 3.13, keyboard/focus and bounded zoom, + verified-public provenance, and private/ambiguous/malformed/legacy-unverified fail-closed paths. +- [ ] Run that contract and require RED because the current section says no changes are recorded. +- [ ] Replace the empty section with the smallest complete post-release ledger and explicit + zero-Stage-1 and unsupported-environment boundaries. +- [ ] Rerun the focused contract and require GREEN. + +### Task 3: Reconcile current product and roadmap surfaces + +**Files:** +- Modify: `README.md` +- Modify: `ROADMAP.md` +- Modify: `docs/development-environment.md` +- Modify: `docs/releases/v0.2.3-status-and-next-stages.md` +- Modify: `docs/releases/v0.2.3-platform-package-matrix.md` +- Modify: `docs/commercialization/market-comparison-2026-07-26.md` +- Modify: `tests/test_repository_contracts.py` + +- [ ] Add focused contracts for the public-release/development-line distinction, completed CLI + lifecycle and Python 3.13/keyboard evidence, exact Stage 1 counts, and unsupported real + environments. +- [ ] Run the new contracts and require RED on stale current-facing statements. +- [ ] Update the README and development guide with v0.2.3 public-install versus `0.2.4.dev0` + source identity and Python 3.11/3.12/3.13 engineering-lane wording. +- [ ] Update the roadmap and status page with merged PR #185/#187/#188 post-release engineering, + remove CLI lifecycle parity from future work, retain passive Stage 1 intake, and preserve every + product-stage gate. +- [ ] Add a dated post-release boundary to the platform/package matrix. Preserve all historical + artifact hashes and measurements while recording current Python 3.13 and keyboard/focus evidence + and the unsupported environment list. +- [ ] Update the market comparison's implemented/gap ledger without changing the product category + or adding competitor-parity work. +- [ ] Rerun the focused contracts and require GREEN. + +### Task 4: Mark superseded audits without rewriting evidence + +**Files:** +- Modify only audits whose unqualified status can be mistaken for current truth under + `docs/audits/` +- Modify: `tests/test_repository_contracts.py` + +- [ ] Identify commit-bound audits that describe CLI parity, Python 3.13, keyboard/focus, or public + provenance as future or unsupported after later merged evidence. +- [ ] Add a contract requiring an explicit historical/superseded notice and a link to the active + status page; require RED before editing audit prose. +- [ ] Add notices only. Do not alter original SHAs, hashes, counts, versions, results, or limitations. +- [ ] Rerun focused repository contracts and require GREEN. + +### Task 5: Verify source, package, and deterministic behavior + +**Files:** +- Modify only confirmed in-scope defects found by verification, with a regression first + +- [ ] Run `uv run ruff check .` and `git diff --check`. +- [ ] Run `uv run pytest -q tests/test_repository_contracts.py`. +- [ ] Run the complete suite with combined coverage over `scopeproof_core` and `apps` and + `--cov-fail-under=95`; record exact tests, skips, and coverage. +- [ ] Run `uv run scopeproof benchmark`; require zero mismatches, zero must-have False Ready, + zero false blockers, and zero unexecuted categories. +- [ ] Run `uv run scopeproof comparison-benchmark`; require zero mismatches. +- [ ] Build the final committed tree twice into separate temporary directories with normalized + build conditions; require identical wheel SHA-256 values. +- [ ] Inspect wheel and source-distribution inventories for Git state, local review storage, + coverage, virtual environments, caches, bytecode, or secrets; require zero forbidden matches. +- [ ] Install the wheel into a fresh external virtual environment, run dependency validation, + require metadata/module/new-review identity equality at `0.2.4.dev0`, run both CLI versions and + both installed benchmarks, and require exact loopback workbench health `ok`. +- [ ] Install the exact Playwright Chromium required by the lock if needed and run + `uv run pytest -q -m browser tests/browser`; require loopback-only networking and zero console or + page errors at both viewports. +- [ ] Confirm the protected CI definition still covers Python 3.11, Python 3.13, the locked + environment, full verification, packaged browser, CodeQL, and Pages. Classify unsupported desktop + and browser environments once. + +### Task 6: Review, publish the branch, and stop at the owner gate + +**Files:** +- Modify only confirmed in-scope defects found by review, with regression coverage where behavioral + +- [ ] Audit `git status`, the full diff against `origin/main`, commit contents, dependency/lock + state, and preserved `.coverage 2` fingerprint. +- [ ] Obtain independent review of the exact head. Resolve every actionable Critical or Important + finding; challenge incorrect findings with repository evidence. +- [ ] Rerun affected checks and the complete final verification matrix after every repair. +- [ ] Commit named files intentionally with no unrelated files, generated reports, or local state. +- [ ] Push `codex/post-v023-development-identity` to `origin`. +- [ ] Open a ready-for-review PR against `main` titled + `chore: restore post-v0.2.3 development identity` with exact evidence and limitations. +- [ ] Monitor every available check to a terminal conclusion. Diagnose and repair only confirmed + in-scope failures on the same branch. +- [ ] Recheck final head/base SHAs, commits, diff, review threads, mergeability, and check + conclusions. Do not merge; stop for the exact owner merge-or-hold decision. From 1ecffc4e67d5c0ea9a4ae4d935c0ea9d3db34989 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 22:54:59 -0400 Subject: [PATCH 3/7] chore: restore post-v0.2.3 development identity --- CHANGELOG.md | 23 ++- README.md | 6 + ROADMAP.md | 9 ++ .../verification.md | 4 + .../verification.md | 4 + .../post-release-cli-browser/verification.md | 4 + .../verification.md | 4 + .../verification.md | 4 + .../accessibility-and-first-use-audit.md | 4 + .../verification.md | 4 + .../market-comparison-2026-07-26.md | 15 +- docs/development-environment.md | 17 ++- .../v0.2.3-platform-package-matrix.md | 17 ++- .../releases/v0.2.3-status-and-next-stages.md | 24 ++-- scopeproof_core/version.py | 2 +- tests/test_repository_contracts.py | 134 +++++++++++++++++- 16 files changed, 256 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b03a499..717d485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,28 @@ its linked release entry for the exact published source and assets. ## Unreleased -No changes currently recorded. +Development version: `0.2.4.dev0`. Public install remains the immutable v0.2.3 release. + +### Post-release engineering + +- Added CLI lifecycle parity for criterion resolution, atomic external E3/E4 runtime-evidence + recording, final acceptance, and changed-head comparison over validated local records. +- Enforced a strict saved-record envelope and lifecycle-output validation. Failed commands do not + mutate saved records, and low-evidence acceptance notes share one fail-closed core policy across + CLI and Streamlit. +- Added an installed-wheel packaged Chromium regression at 1280×720 and 390×844 with exact + Playwright 1.62.0, isolated local storage, loopback-only networking, and console/page-error + assertions. +- Added Python 3.13 package, CLI, deterministic-benchmark, and exact workbench-health engineering + coverage in both a genuine local CPython 3.13 environment and protected CI. +- Added a keyboard-only installed-workbench path with visible-focus assertions and + bounded native 200% zoom evidence on the tested macOS/Chrome configuration. +- Enforced verified-public provenance before a live GitHub source can be persisted, exported, or + counted toward Alpha. Private, ambiguous, malformed, and legacy-unverified sources fail closed. + +These changes are ScopeProof engineering evidence only and earn zero Stage 1 credit. Real +screen-reader operation, Windows desktop, Linux desktop, non-Chromium browser behavior, and WCAG +conformance remain unsupported. ## 0.2.3 — Evidence integrity and reviewer loop diff --git a/README.md b/README.md index 133e6e4..028af1d 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,12 @@ at zero. The [exact-head verification audit](docs/audits/exact-head-runtime-evidence/verification.md) records the product-tree engineering evidence and remaining gaps. +The repository's current source line is the unreleased development version `0.2.4.dev0`; it is +not a replacement release asset. Post-v0.2.3 engineering merged CLI lifecycle commands, strict +saved-record validation, installed Chromium coverage, Python 3.13 and bounded keyboard/focus +evidence, and verified-public provenance enforcement. Those changes remain engineering evidence +only. The public install continues to be the immutable v0.2.3 release, and Stage 1 remains zero. + GitHub exposes visible check runs but does not reliably expose every repository's required-check policy to anonymous clients. ScopeProof therefore labels this value **Observed CI state** and counts only explicit success as passing. diff --git a/ROADMAP.md b/ROADMAP.md index 54a75f7..9590c55 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -18,6 +18,7 @@ which provides the wheel, source archive, and checksum manifest. | Area | Current state | |---|---| | Published install | v0.2.3 GitHub Release with wheel, source archive, and checksum manifest | +| Active source line | Unreleased `0.2.4.dev0`; no v0.2.4 release, tag, or package publication exists | | Verified product baseline | PR #184 release integration landed on `main` at `448c42758ea139bf9203cbf1bb04b02b02ae412c` | | Product verification | Full product-code verification is bound to `fb74d4bbb402f4de3e2fabb56ce28c948214f8c2`; package, install, installed-benchmark, and health artifacts are bound to `81598899fcd85df58ab22f9212f2e8382f4a5e5f`. | | Release integration evidence | PR #184 release integration at `448c42758ea139bf9203cbf1bb04b02b02ae412c`; exact-main CI, CodeQL, and Pages all succeeded, and `origin/main` matched at the 2026-08-08 branch-start snapshot | @@ -28,6 +29,14 @@ which provides the wheel, source archive, and checksum manifest. Verify live GitHub and current release records before relying on publication state. Engineering milestones can proceed while Stage 1 waits, but they do not advance product-validation stages. +After the v0.2.3 release, PR #185 merged core-backed CLI lifecycle parity and packaged Chromium +proof at `30177733ef312ced22e6a2e57e3df6fdb1e92507`; PR #187 merged Python 3.13 plus bounded +keyboard/focus and zoom engineering evidence at `c548759b5464ad5bb98baf1e996397f241dfc455`; and +PR #188 merged verified-public provenance enforcement at +`077f9351283b319b82854ad1df95eac7ce614e21`. CLI lifecycle parity is implemented; +verified-public provenance enforcement is implemented. These changes form the `0.2.4.dev0` +development line and earn no Stage 1 credit. + ## Stage 0 — Reviewer-first product reset Status: prior PR #177 repairs remain historical engineering evidence. PR #180 diff --git a/docs/audits/accessibility-platform-evidence/verification.md b/docs/audits/accessibility-platform-evidence/verification.md index add5589..a866cd1 100644 --- a/docs/audits/accessibility-platform-evidence/verification.md +++ b/docs/audits/accessibility-platform-evidence/verification.md @@ -1,5 +1,9 @@ # Accessibility and platform evidence verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + ## Evidence boundary - Date: 2026-08-09 (America/Toronto). diff --git a/docs/audits/exact-head-runtime-evidence/verification.md b/docs/audits/exact-head-runtime-evidence/verification.md index a57355e..73c6e02 100644 --- a/docs/audits/exact-head-runtime-evidence/verification.md +++ b/docs/audits/exact-head-runtime-evidence/verification.md @@ -1,5 +1,9 @@ # Exact-head merged-product runtime-evidence verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + Machine-readable evidence manifest: [`verification.json`](verification.json). The manifest is the structured repository-contract input; this document remains the human-readable audit. diff --git a/docs/audits/post-release-cli-browser/verification.md b/docs/audits/post-release-cli-browser/verification.md index 0dabca5..c4246d7 100644 --- a/docs/audits/post-release-cli-browser/verification.md +++ b/docs/audits/post-release-cli-browser/verification.md @@ -1,5 +1,9 @@ # Post-release truth, CLI parity, and packaged-browser verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + ## Evidence boundary - Date: 2026-08-08 (America/Toronto). diff --git a/docs/audits/v0.2.3-integrity-reviewer-loop/verification.md b/docs/audits/v0.2.3-integrity-reviewer-loop/verification.md index 127c1ef..d48323c 100644 --- a/docs/audits/v0.2.3-integrity-reviewer-loop/verification.md +++ b/docs/audits/v0.2.3-integrity-reviewer-loop/verification.md @@ -1,5 +1,9 @@ # ScopeProof v0.2.3 integrity and reviewer-loop verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + ## Evidence identity and boundary - Date: 2026-08-03 (America/Toronto) diff --git a/docs/audits/v0.2.3-product-convergence/verification.md b/docs/audits/v0.2.3-product-convergence/verification.md index bea14dd..b776c19 100644 --- a/docs/audits/v0.2.3-product-convergence/verification.md +++ b/docs/audits/v0.2.3-product-convergence/verification.md @@ -1,5 +1,9 @@ # ScopeProof v0.2.3 product-convergence verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + ## Evidence identity and boundary - Date: 2026-08-02 (America/Toronto) diff --git a/docs/audits/v0.2.3-workbench/accessibility-and-first-use-audit.md b/docs/audits/v0.2.3-workbench/accessibility-and-first-use-audit.md index b1c359e..67539a5 100644 --- a/docs/audits/v0.2.3-workbench/accessibility-and-first-use-audit.md +++ b/docs/audits/v0.2.3-workbench/accessibility-and-first-use-audit.md @@ -1,5 +1,9 @@ # v0.2.3 Workbench Accessibility and First-Use Audit +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + Status: internal engineering audit Date: 2026-07-26 Environment: macOS, Streamlit local server, in-app Chromium browser diff --git a/docs/audits/workbench-ux-simplification/verification.md b/docs/audits/workbench-ux-simplification/verification.md index 345ea1a..0ce1a8d 100644 --- a/docs/audits/workbench-ux-simplification/verification.md +++ b/docs/audits/workbench-ux-simplification/verification.md @@ -1,5 +1,9 @@ # Workbench UX simplification verification +> **Historical evidence boundary:** This audit remains bound to its named commit, tree, version, +> and environment. The [current status](../../releases/v0.2.3-status-and-next-stages.md) supersedes +> unqualified present-state inferences and does not rewrite the results below. + ## Scope and evidence boundary - Date: 2026-08-01 (America/Toronto) diff --git a/docs/commercialization/market-comparison-2026-07-26.md b/docs/commercialization/market-comparison-2026-07-26.md index f62c0c1..b2cd593 100644 --- a/docs/commercialization/market-comparison-2026-07-26.md +++ b/docs/commercialization/market-comparison-2026-07-26.md @@ -6,6 +6,9 @@ Boundary: competitor capabilities below are vendor-advertised unless explicitly labelled as a ScopeProof implementation fact. This document is not customer or market validation. +Version boundary: public install remains v0.2.3; current source is the unreleased `0.2.4.dev0` +development line. Post-release engineering changes do not constitute market validation. + ## Product category ScopeProof is not a general AI code reviewer, test-management system, or static @@ -87,6 +90,10 @@ criterion is supported at this exact head.” - Conservative False Ready posture and inspectable missing-evidence explanations. - Portable exports and versioned local records. +- CLI lifecycle parity is implemented for core-backed resolution, external runtime verification, + final acceptance, and changed-head comparison. +- Bounded keyboard-only and visible-focus engineering evidence is implemented for the installed + Chromium path; it is not accessibility conformance. ### Where ScopeProof is immature @@ -97,8 +104,9 @@ criterion is supported at this exact head.” integration with an issue or test-management source. - Retrieval coverage is intentionally conservative and the completed R-002 baseline found candidates for only 5 of 20 research criteria. -- Accessibility is not yet verified with keyboard-only completion, a screen - reader, 200% zoom, Windows, or Linux. +- Real screen-reader operation, Windows desktop, Linux desktop, non-Chromium browser behavior, and + WCAG conformance remain unsupported. The bounded keyboard/focus and native-zoom checks do not + establish those broader claims. - There is no evidence yet that users will repeat the workflow or pay for a team product. @@ -112,7 +120,8 @@ criterion is supported at this exact head.” 2. Preserve retrieval diagnostics as explanations, never verdict evidence. 3. Improve conservative retrieval only through new constructed regressions and a prospectively frozen holdout; do not retune on R-002. -4. Finish keyboard, zoom, assistive-technology, and available-platform checks. +4. Attempt real assistive-technology and available desktop-platform checks only in genuine, + observable environments; keep unavailable rows unsupported. 5. Keep export, changed-head re-review, and missing-evidence explanations clear. ### Design now, implement only after genuine use evidence diff --git a/docs/development-environment.md b/docs/development-environment.md index a7326a8..662582d 100644 --- a/docs/development-environment.md +++ b/docs/development-environment.md @@ -1,6 +1,14 @@ # Reproducible development environment -ScopeProof supports Python 3.11 and newer. The contributor baseline is Python 3.12 with dependencies resolved by the checked-in `uv.lock`. This path uses only local and free open-source tooling; it does not require an OpenAI or other paid LLM API. +The public install remains v0.2.3; the current repository source is the unreleased `0.2.4.dev0` +development line. Python 3.11, Python 3.12, and Python 3.13 have current package/CLI engineering +coverage. Python 3.11 is the declared floor, Python 3.12 is the locked contributor baseline, and +Python 3.13 is exercised in protected compatibility CI and a genuine local interpreter check. +Python 3.14 is unverified pending a clean, genuine compatibility run; the current `>=3.11` +metadata must not be read as verified 3.14 support. + +Dependencies are resolved by the checked-in `uv.lock`. This path uses only local and free +open-source tooling; it does not require an OpenAI or other paid LLM API. ## Create or refresh the environment @@ -68,7 +76,12 @@ Run the local workbench with: uv run scopeproof-web --host 127.0.0.1 --port 8501 ``` -The Python 3.11 CI lane remains the compatibility floor. A separate locked Python 3.12 lane verifies that the committed resolution can be recreated and runs repository contracts plus the deterministic benchmark before the required `verify` job. +The Python 3.11 CI lane remains the compatibility floor. A separate locked Python 3.12 lane +verifies that the committed resolution can be recreated and runs repository contracts plus both +deterministic benchmarks. The Python 3.13 lane runs the complete suite, builds and installs a wheel, +checks dependencies and both CLI versions, runs both installed benchmarks, and requires exact +loopback workbench health before the required `verify` job. These Linux-runner checks are package +and CLI evidence, not Linux desktop evidence. ## Known-good UI baseline diff --git a/docs/releases/v0.2.3-platform-package-matrix.md b/docs/releases/v0.2.3-platform-package-matrix.md index 5b98b6a..0e25e43 100644 --- a/docs/releases/v0.2.3-platform-package-matrix.md +++ b/docs/releases/v0.2.3-platform-package-matrix.md @@ -5,12 +5,27 @@ Merged product commit: `2a320df966eff30c05a2b1dce607a247201fa165` (PR #180) Merged product tree: `add81a2d0ba7e64f8e4318a1959bbe7e6e4acfc8` Independently verified PR head: `ed9f9c0cf6b7cf7cc25403d6138e7a8391f55e0f` Verified PR-head tree: `add81a2d0ba7e64f8e4318a1959bbe7e6e4acfc8` -Public install and latest release: v0.2.1 +Historical public install at the 2026-08-02 audit time: v0.2.1 +Current public install: v0.2.3 Historical local checkout verification head: `87e95a76ca4100458465da520049992e8b39af5c` Historical package build base: `482d1a78f5d3345029d35d33a518ca36bc2f8e29` Classification: internal engineering evidence only +## 2026-08-09 post-release development boundary + +The public package and every historical hash below remain bound to v0.2.3 and their named source +trees. Current repository source is the unreleased `0.2.4.dev0` development line. Later merged +engineering work added an installed-wheel Chromium lifecycle regression, a keyboard-only path with +visible-focus assertions at 1280×720 and 390×844, bounded native 200% zoom on one macOS/Chrome +configuration, and clean Python 3.13 package, CLI, benchmark, and loopback-health checks. + +Those results do not establish real screen-reader operation, Windows desktop, Linux desktop, +non-Chromium browser behavior, or WCAG conformance. Hosted Linux CI is package/runtime evidence, +not Linux desktop evidence. This additive boundary supersedes only unqualified current-status +inferences; it does not rewrite any earlier measurement, artifact identity, or limitation below. +All engineering evidence adds zero Stage 1 credit. + ## 2026-08-02 merged product-tree package verification PR #180 merged the independently verified head's exact product tree as diff --git a/docs/releases/v0.2.3-status-and-next-stages.md b/docs/releases/v0.2.3-status-and-next-stages.md index 11b1cdf..4a1e13c 100644 --- a/docs/releases/v0.2.3-status-and-next-stages.md +++ b/docs/releases/v0.2.3-status-and-next-stages.md @@ -1,8 +1,9 @@ # ScopeProof v0.2.3 status, gaps, and next stages -Date: 2026-08-03 +Release-baseline date: 2026-08-03; current development alignment: 2026-08-09 Current release baseline: PR #184 release integration at `448c42758ea139bf9203cbf1bb04b02b02ae412c` +Current development line: unreleased `0.2.4.dev0` after merged PR #185, PR #187, and PR #188 Exact-main engineering checks: CI run `30854382641`, CodeQL run `30854382413`, and Pages run `30854382659`; exact-main CI, CodeQL, and Pages all succeeded Historical source integration: PR #183 at @@ -18,6 +19,15 @@ which contains the wheel, source archive, and checksum manifest. Product-validation state: Stage 0 source integration is complete; release and test work do not change Stage 1, which remains at zero. Stages 2–4 remain gated. +PR #185 merged CLI lifecycle parity, the strict saved-record envelope, and packaged Chromium +regression at `30177733ef312ced22e6a2e57e3df6fdb1e92507`. PR #187 merged Python 3.13 plus bounded +keyboard/focus and native-zoom engineering evidence at +`c548759b5464ad5bb98baf1e996397f241dfc455`. PR #188 merged verified-public provenance enforcement +at `077f9351283b319b82854ad1df95eac7ce614e21`, so private, ambiguous, malformed, and +legacy-unverified live sources fail closed. CLI lifecycle parity is implemented; +verified-public provenance enforcement is implemented. These post-release changes belong to +`0.2.4.dev0`, not the immutable v0.2.3 assets, and add zero Stage 1 credit. + PR #174 head `e96d9929e651ca36bf178a6fedff0e89e8df3675` passed Python 3.11 compatibility, locked-environment, `verify`, and CodeQL before it was merged to `main` as `178df8a1c8034edc4d3240d790e3e4c668dfa82a`. The merged source includes @@ -120,7 +130,7 @@ code-review comments, scan security, or automatically fix a PR. | Exports | Pydantic-backed JSON, Markdown, CSV, and HTML with runtime identity, linked/unlinked state, and exact criteria-source provenance | Exported content is a review record, not certification | | Alpha evidence | One-time outcome capture only from a fully revalidated saved review with matching public-GitHub origin, PR, exact head, criteria, and provenance | Demo, fixture, research, legacy-unknown, mutated, or non-public origins contribute zero qualifying alpha evidence | | Engineering benchmarks | 12-case constructed acceptance benchmark, two-case comparison benchmark, R-001 research case, and frozen 20-case R-002 research baseline | All contribute zero Stage 1 credit | -| Local workbench and CLI | Cleaner five-stage Streamlit hierarchy plus offline source-confirmation preparation, review, export, list, delete, benchmark, and comparison commands | Local owner operation and UI tests are not participant or accessibility validation | +| Local workbench and CLI | Cleaner five-stage Streamlit hierarchy plus offline source-confirmation preparation; review, resolve, atomic runtime verification, final acceptance, export, list, delete, benchmark, and changed-head comparison commands | Local owner operation and UI tests are not participant or accessibility validation | ## Primary use cases @@ -250,20 +260,14 @@ target repository code. current PR head, invalidate stale prior conclusions on `synchronize`, and keep the current Action informational until independent use justifies promotion. -2. **CLI lifecycle parity:** expose resolution, atomic external verification, - final acceptance, and changed-head comparison through the core-backed CLI - without weakening Streamlit or schema boundaries. -3. **Non-executing evidence adapters:** design validated import records for +2. **Non-executing evidence adapters:** design validated import records for JUnit-style results, coverage summaries, contract reports, build/deployment records, and externally supplied runtime attestations. Imported data remains evidence with provenance, not proof of correctness. -4. **Authenticated reviewer identity:** current runtime records now retain +3. **Authenticated reviewer identity:** current runtime records now retain review-scoped identity and attribution, but authentication, optional expiry, and externally signed attestations remain future decisions without accounts, silent overrides, or automatic approval. -5. **Real-browser regression coverage:** automate the packaged pointer path - first, then add keyboard, responsive viewport, and zoom checks only where - the execution environment provides trustworthy control. ### Demand-gated candidates diff --git a/scopeproof_core/version.py b/scopeproof_core/version.py index 333167d..1bcd547 100644 --- a/scopeproof_core/version.py +++ b/scopeproof_core/version.py @@ -1,3 +1,3 @@ """Single checked-in source for ScopeProof package and review provenance.""" -__version__ = "0.2.3" +__version__ = "0.2.4.dev0" diff --git a/tests/test_repository_contracts.py b/tests/test_repository_contracts.py index 67b0645..9922211 100644 --- a/tests/test_repository_contracts.py +++ b/tests/test_repository_contracts.py @@ -1,5 +1,6 @@ import json import re +import subprocess import tomllib from hashlib import sha256 from html.parser import HTMLParser @@ -21,9 +22,11 @@ load_source_manifest, ) from scopeproof_core.reviews.comparison import EvidenceChangeKind +from scopeproof_core.version import __version__ PUBLIC_RELEASE_VERSION = "0.2.3" PUBLIC_RELEASE_TAG = "v0.2.3" +DEVELOPMENT_VERSION = "0.2.4.dev0" PUBLIC_RELEASE_WHEEL_FILENAME = "scopeproof-0.2.3-py3-none-any.whl" PUBLIC_RELEASE_DOWNLOAD_ROOT = ( "https://github.com/YuzeJ21/Scope-Proof/releases/download/v0.2.3" @@ -647,7 +650,34 @@ def test_hatch_and_reviews_share_one_version_source() -> None: assert config["project"]["dynamic"] == ["version"] assert "version" not in config["project"] assert config["tool"]["hatch"]["version"]["path"] == "scopeproof_core/version.py" - assert f'__version__ = "{PUBLIC_RELEASE_VERSION}"' in version_source + assert f'__version__ = "{DEVELOPMENT_VERSION}"' in version_source + + +def test_divergent_tree_cannot_reuse_a_published_final_version() -> None: + published_final_tags = {PUBLIC_RELEASE_VERSION: PUBLIC_RELEASE_TAG} + published_tag = published_final_tags.get(__version__) + + if published_tag is None: + assert __version__ == DEVELOPMENT_VERSION + return + + current_tree = subprocess.run( + ["git", "rev-parse", "HEAD^{tree}"], + check=True, + capture_output=True, + text=True, + ).stdout.strip() + published_tree = subprocess.run( + ["git", "rev-parse", f"{published_tag}^{{tree}}"], + check=True, + capture_output=True, + text=True, + ).stdout.strip() + + assert current_tree == published_tree, ( + f"version {__version__} is already published from {published_tag}, but the current " + "committed tree differs; advance the development version before packaging" + ) class _StrictVerificationModel(BaseModel): @@ -1259,6 +1289,34 @@ def test_changelog_points_to_authoritative_release_history() -> None: assert "does not reconstruct" in changelog +def test_unreleased_ledger_records_post_v023_engineering_without_stage_credit() -> None: + changelog = Path("CHANGELOG.md").read_text(encoding="utf-8") + unreleased = changelog.split("## Unreleased", maxsplit=1)[1].split( + "## 0.2.3", maxsplit=1 + )[0] + normalized_unreleased = " ".join(unreleased.split()) + + for expected in ( + "Development version: `0.2.4.dev0`", + "CLI lifecycle parity", + "strict saved-record envelope", + "packaged Chromium", + "Python 3.13", + "keyboard-only", + "bounded native 200% zoom", + "verified-public provenance", + "Private, ambiguous, malformed, and legacy-unverified", + "zero Stage 1 credit", + "screen-reader", + "Windows desktop", + "Linux desktop", + "non-Chromium", + "WCAG conformance", + ): + assert expected in normalized_unreleased + assert "No changes currently recorded" not in unreleased + + def test_changelog_discloses_v021_rereview_evidence_boundaries() -> None: changelog = Path("CHANGELOG.md").read_text(encoding="utf-8") @@ -1360,6 +1418,80 @@ def test_active_public_release_surfaces_align_to_v023_without_rewriting_history( ) in site +def test_active_docs_distinguish_post_v023_engineering_from_release_and_stage_progress() -> None: + readme = Path("README.md").read_text(encoding="utf-8") + roadmap = Path("ROADMAP.md").read_text(encoding="utf-8") + environment = Path("docs/development-environment.md").read_text(encoding="utf-8") + status = Path("docs/releases/v0.2.3-status-and-next-stages.md").read_text( + encoding="utf-8" + ) + platform = Path("docs/releases/v0.2.3-platform-package-matrix.md").read_text( + encoding="utf-8" + ) + market = Path("docs/commercialization/market-comparison-2026-07-26.md").read_text( + encoding="utf-8" + ) + + for active_surface in (readme, roadmap, environment, status, platform, market): + assert "0.2.4.dev0" in active_surface + assert "v0.2.3" in active_surface + + for active_status in (roadmap, status): + assert all(pr in active_status for pr in ("PR #185", "PR #187", "PR #188")) + assert "CLI lifecycle parity is implemented" in active_status + assert "verified-public provenance enforcement" in active_status + for count in ("0/5", "0/3", "0/2"): + assert count in active_status + + prioritized = status.split("## Prioritized post-release decision candidates", maxsplit=1)[1] + assert "**CLI lifecycle parity:**" not in prioritized + assert "**Real-browser regression coverage:**" not in prioritized + + assert "Python 3.11, Python 3.12, and Python 3.13" in environment + assert "Python 3.14" in environment + python_314_line = environment.split("Python 3.14", maxsplit=1)[1].split( + "\n", maxsplit=1 + )[0] + assert "unverified" in python_314_line + + normalized_market = " ".join(market.split()) + assert ( + "keyboard-only and visible-focus engineering evidence is implemented" + in normalized_market + ) + assert "CLI lifecycle parity is implemented" in normalized_market + assert "not yet verified with keyboard-only completion" not in normalized_market + assert "Finish keyboard, zoom" not in normalized_market + + for unsupported in ( + "real screen-reader", + "Windows desktop", + "Linux desktop", + "non-Chromium", + "WCAG conformance", + ): + assert unsupported in platform + + +def test_superseded_audits_preserve_historical_results_and_link_current_status() -> None: + historical_audits = ( + Path("docs/audits/exact-head-runtime-evidence/verification.md"), + Path("docs/audits/v0.2.3-integrity-reviewer-loop/verification.md"), + Path("docs/audits/v0.2.3-product-convergence/verification.md"), + Path("docs/audits/workbench-ux-simplification/verification.md"), + Path("docs/audits/post-release-cli-browser/verification.md"), + Path("docs/audits/accessibility-platform-evidence/verification.md"), + Path("docs/audits/v0.2.3-workbench/accessibility-and-first-use-audit.md"), + ) + + for audit in historical_audits: + text = audit.read_text(encoding="utf-8") + opening = "\n".join(text.splitlines()[:10]) + assert "Historical evidence boundary" in opening + assert "../../releases/v0.2.3-status-and-next-stages.md" in opening + assert "does not rewrite" in opening + + def test_public_contribution_templates_preserve_evidence_boundaries() -> None: defect = Path(".github/ISSUE_TEMPLATE/defect.yml").read_text(encoding="utf-8") feedback = Path(".github/ISSUE_TEMPLATE/public-alpha-feedback.yml").read_text(encoding="utf-8") From 885eddc1f71c57250e860bd361e869a906d1e8f4 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 23:01:44 -0400 Subject: [PATCH 4/7] test: harden published-version identity guard --- .../releases/v0.2.3-status-and-next-stages.md | 2 +- tests/test_repository_contracts.py | 63 +++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/docs/releases/v0.2.3-status-and-next-stages.md b/docs/releases/v0.2.3-status-and-next-stages.md index 4a1e13c..488e2fb 100644 --- a/docs/releases/v0.2.3-status-and-next-stages.md +++ b/docs/releases/v0.2.3-status-and-next-stages.md @@ -176,7 +176,7 @@ remains zero independent use. | 200% zoom | Supported bounded local evidence | Installed Chrome 151.0.7922.77 reported native `Zoom: 200%`, device pixel ratio changed from 1 to 2, the exact-head keyboard path completed, and no named control was horizontally clipped on the tested macOS/display configuration. This is not responsive resizing or a broad browser/platform claim. | | VoiceOver or another real screen reader | Unsupported current evidence | The installed VoiceOver service was detectable, but bounded control attempts exposed no observable screen-reader state, speech, caption, focus announcement, or reading-order result. | | Python 3.11 | Remote CI evidence only | Python 3.11 CI passed at the exact merged PR head; no local Python 3.11 desktop flow was executed | -| Python 3.13 | Supported local engineering evidence | A genuine CPython 3.13.14 environment passed clean wheel installation, `pip check`, both versioned CLIs, both deterministic benchmarks, and exact workbench health. The new hosted 3.13 job must pass before its Linux-runner result is claimed. | +| Python 3.13 | Supported package/runtime engineering evidence | A genuine local CPython 3.13.14 environment passed clean wheel installation, `pip check`, both versioned CLIs, both deterministic benchmarks, and exact workbench health. Protected Python 3.13 CI passed on PR #187 and resulting `main`; this is package/runtime evidence, not Linux desktop evidence. | | Windows and Linux desktop | Unavailable environment | Build, install, launch, and complete representative workflows on those operating systems | | Stage 1 | External evidence gate | A non-owner supplies a real public PR, public requirements, source-owner confirmation, exact head SHA, saved review, and genuine outcome | | Stage 2 | Stage gate | Every Stage 1 target passes before repeat-use and commercial-discovery evidence is collected | diff --git a/tests/test_repository_contracts.py b/tests/test_repository_contracts.py index 9922211..371f914 100644 --- a/tests/test_repository_contracts.py +++ b/tests/test_repository_contracts.py @@ -9,6 +9,7 @@ from typing import Literal from urllib.parse import urlsplit +import pytest from PIL import Image from pydantic import BaseModel, ConfigDict, Field @@ -653,31 +654,80 @@ def test_hatch_and_reviews_share_one_version_source() -> None: assert f'__version__ = "{DEVELOPMENT_VERSION}"' in version_source -def test_divergent_tree_cannot_reuse_a_published_final_version() -> None: +def _assert_published_version_matches_repository( + *, repository: Path, current_version: str +) -> None: published_final_tags = {PUBLIC_RELEASE_VERSION: PUBLIC_RELEASE_TAG} - published_tag = published_final_tags.get(__version__) + published_tag = published_final_tags.get(current_version) if published_tag is None: - assert __version__ == DEVELOPMENT_VERSION + assert current_version == DEVELOPMENT_VERSION return current_tree = subprocess.run( ["git", "rev-parse", "HEAD^{tree}"], + cwd=repository, check=True, capture_output=True, text=True, ).stdout.strip() published_tree = subprocess.run( ["git", "rev-parse", f"{published_tag}^{{tree}}"], + cwd=repository, check=True, capture_output=True, text=True, ).stdout.strip() assert current_tree == published_tree, ( - f"version {__version__} is already published from {published_tag}, but the current " + f"version {current_version} is already published from {published_tag}, but the current " "committed tree differs; advance the development version before packaging" ) + tracked_diff = subprocess.run( + ["git", "diff", "--quiet", published_tag, "--"], + cwd=repository, + check=False, + ) + assert tracked_diff.returncode in {0, 1}, "Git could not compare tracked package inputs" + assert tracked_diff.returncode == 0, ( + f"version {current_version} is already published from {published_tag}, but the tracked " + "working tree differs; advance the development version before packaging" + ) + + +def test_divergent_tree_cannot_reuse_a_published_final_version() -> None: + _assert_published_version_matches_repository( + repository=Path.cwd(), + current_version=__version__, + ) + + +def test_published_final_contract_rejects_dirty_tracked_tree(tmp_path: Path) -> None: + repository = tmp_path / "repository" + repository.mkdir() + subprocess.run(["git", "init", "-q"], cwd=repository, check=True) + subprocess.run( + ["git", "config", "user.email", "scopeproof-contract@example.test"], + cwd=repository, + check=True, + ) + subprocess.run( + ["git", "config", "user.name", "ScopeProof contract"], + cwd=repository, + check=True, + ) + tracked = repository / "versioned.txt" + tracked.write_text("published\n", encoding="utf-8") + subprocess.run(["git", "add", "versioned.txt"], cwd=repository, check=True) + subprocess.run(["git", "commit", "-q", "-m", "published"], cwd=repository, check=True) + subprocess.run(["git", "tag", "v0.2.3"], cwd=repository, check=True) + tracked.write_text("different package bytes\n", encoding="utf-8") + + with pytest.raises(AssertionError, match="tracked working tree differs"): + _assert_published_version_matches_repository( + repository=repository, + current_version="0.2.3", + ) class _StrictVerificationModel(BaseModel): @@ -1443,6 +1493,11 @@ def test_active_docs_distinguish_post_v023_engineering_from_release_and_stage_pr for count in ("0/5", "0/3", "0/2"): assert count in active_status + python_313_row = next(line for line in status.splitlines() if "| Python 3.13 |" in line) + assert "Protected Python 3.13 CI passed" in python_313_row + assert "not Linux desktop evidence" in python_313_row + assert "must pass" not in python_313_row + prioritized = status.split("## Prioritized post-release decision candidates", maxsplit=1)[1] assert "**CLI lifecycle parity:**" not in prioritized assert "**Real-browser regression coverage:**" not in prioritized From 1369a1cc67926a93b3c1a4aa2913b3d0e38492f7 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 23:06:09 -0400 Subject: [PATCH 5/7] test: reject untracked release package inputs --- tests/test_repository_contracts.py | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/test_repository_contracts.py b/tests/test_repository_contracts.py index 371f914..a5dac5a 100644 --- a/tests/test_repository_contracts.py +++ b/tests/test_repository_contracts.py @@ -693,6 +693,18 @@ def _assert_published_version_matches_repository( f"version {current_version} is already published from {published_tag}, but the tracked " "working tree differs; advance the development version before packaging" ) + untracked_package_inputs = subprocess.run( + ["git", "ls-files", "--others", "--exclude-standard"], + cwd=repository, + check=True, + capture_output=True, + text=True, + ).stdout.splitlines() + assert not untracked_package_inputs, ( + f"version {current_version} is already published from {published_tag}, but untracked " + f"package inputs exist: {', '.join(untracked_package_inputs)}; track them and advance " + "the development version before packaging" + ) def test_divergent_tree_cannot_reuse_a_published_final_version() -> None: @@ -730,6 +742,40 @@ def test_published_final_contract_rejects_dirty_tracked_tree(tmp_path: Path) -> ) +def test_published_final_contract_rejects_untracked_package_input(tmp_path: Path) -> None: + repository = tmp_path / "repository" + package = repository / "scopeproof_core" + package.mkdir(parents=True) + subprocess.run(["git", "init", "-q"], cwd=repository, check=True) + subprocess.run( + ["git", "config", "user.email", "scopeproof-contract@example.test"], + cwd=repository, + check=True, + ) + subprocess.run( + ["git", "config", "user.name", "ScopeProof contract"], + cwd=repository, + check=True, + ) + (repository / ".gitignore").write_text(".coverage*\n", encoding="utf-8") + (package / "__init__.py").write_text("published = True\n", encoding="utf-8") + subprocess.run(["git", "add", ".gitignore", "scopeproof_core"], cwd=repository, check=True) + subprocess.run(["git", "commit", "-q", "-m", "published"], cwd=repository, check=True) + subprocess.run(["git", "tag", "v0.2.3"], cwd=repository, check=True) + (repository / ".coverage 2").write_text("preserve me\n", encoding="utf-8") + untracked_package_input = package / "untracked_probe.py" + untracked_package_input.write_text("different_package_bytes = True\n", encoding="utf-8") + + with pytest.raises(AssertionError, match="untracked package inputs") as error: + _assert_published_version_matches_repository( + repository=repository, + current_version="0.2.3", + ) + + assert "scopeproof_core/untracked_probe.py" in str(error.value) + assert ".coverage 2" not in str(error.value) + + class _StrictVerificationModel(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True, strict=True) From eb7df35183d9c1fffca75deefed907f0e34b50c0 Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 23:07:56 -0400 Subject: [PATCH 6/7] test: preserve excluded local coverage state --- tests/test_repository_contracts.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/test_repository_contracts.py b/tests/test_repository_contracts.py index a5dac5a..4b6e81a 100644 --- a/tests/test_repository_contracts.py +++ b/tests/test_repository_contracts.py @@ -693,13 +693,24 @@ def _assert_published_version_matches_repository( f"version {current_version} is already published from {published_tag}, but the tracked " "working tree differs; advance the development version before packaging" ) - untracked_package_inputs = subprocess.run( + untracked_paths = subprocess.run( ["git", "ls-files", "--others", "--exclude-standard"], cwd=repository, check=True, capture_output=True, text=True, ).stdout.splitlines() + untracked_package_inputs = [ + path + for path in untracked_paths + if not ( + path.startswith(".coverage") + or path == ".scopeproof" + or path.startswith(".scopeproof/") + or path == ".superpowers" + or path.startswith(".superpowers/") + ) + ] assert not untracked_package_inputs, ( f"version {current_version} is already published from {published_tag}, but untracked " f"package inputs exist: {', '.join(untracked_package_inputs)}; track them and advance " @@ -757,9 +768,8 @@ def test_published_final_contract_rejects_untracked_package_input(tmp_path: Path cwd=repository, check=True, ) - (repository / ".gitignore").write_text(".coverage*\n", encoding="utf-8") (package / "__init__.py").write_text("published = True\n", encoding="utf-8") - subprocess.run(["git", "add", ".gitignore", "scopeproof_core"], cwd=repository, check=True) + subprocess.run(["git", "add", "scopeproof_core"], cwd=repository, check=True) subprocess.run(["git", "commit", "-q", "-m", "published"], cwd=repository, check=True) subprocess.run(["git", "tag", "v0.2.3"], cwd=repository, check=True) (repository / ".coverage 2").write_text("preserve me\n", encoding="utf-8") From d4343fccede5f76fea7c088d5a9a3973f131650b Mon Sep 17 00:00:00 2001 From: davidjiang8888 Date: Sun, 9 Aug 2026 23:39:13 -0400 Subject: [PATCH 7/7] test: guard ignored force-included package inputs --- tests/test_repository_contracts.py | 74 +++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/tests/test_repository_contracts.py b/tests/test_repository_contracts.py index 4b6e81a..93c4e64 100644 --- a/tests/test_repository_contracts.py +++ b/tests/test_repository_contracts.py @@ -700,7 +700,7 @@ def _assert_published_version_matches_repository( capture_output=True, text=True, ).stdout.splitlines() - untracked_package_inputs = [ + untracked_package_inputs = { path for path in untracked_paths if not ( @@ -710,7 +710,39 @@ def _assert_published_version_matches_repository( or path == ".superpowers" or path.startswith(".superpowers/") ) - ] + } + build_config_path = repository / "pyproject.toml" + build_config = ( + tomllib.loads(build_config_path.read_text(encoding="utf-8")) + if build_config_path.exists() + else {} + ) + force_included_sources = list( + build_config.get("tool", {}) + .get("hatch", {}) + .get("build", {}) + .get("targets", {}) + .get("wheel", {}) + .get("force-include", {}) + ) + if force_included_sources: + ignored_force_included_paths = subprocess.run( + [ + "git", + "ls-files", + "--others", + "--ignored", + "--exclude-standard", + "--", + *force_included_sources, + ], + cwd=repository, + check=True, + capture_output=True, + text=True, + ).stdout.splitlines() + untracked_package_inputs.update(ignored_force_included_paths) + untracked_package_inputs = sorted(untracked_package_inputs) assert not untracked_package_inputs, ( f"version {current_version} is already published from {published_tag}, but untracked " f"package inputs exist: {', '.join(untracked_package_inputs)}; track them and advance " @@ -786,6 +818,44 @@ def test_published_final_contract_rejects_untracked_package_input(tmp_path: Path assert ".coverage 2" not in str(error.value) +def test_published_final_contract_rejects_ignored_force_included_input( + tmp_path: Path, +) -> None: + repository = tmp_path / "repository" + force_included = repository / "evals" + force_included.mkdir(parents=True) + subprocess.run(["git", "init", "-q"], cwd=repository, check=True) + subprocess.run( + ["git", "config", "user.email", "scopeproof-contract@example.test"], + cwd=repository, + check=True, + ) + subprocess.run( + ["git", "config", "user.name", "ScopeProof contract"], + cwd=repository, + check=True, + ) + (repository / ".gitignore").write_text("*.py[cod]\n", encoding="utf-8") + (repository / "pyproject.toml").write_text( + '[tool.hatch.build.targets.wheel.force-include]\n"evals" = "evals"\n', + encoding="utf-8", + ) + (force_included / "README.md").write_text("published\n", encoding="utf-8") + subprocess.run(["git", "add", "."], cwd=repository, check=True) + subprocess.run(["git", "commit", "-q", "-m", "published"], cwd=repository, check=True) + subprocess.run(["git", "tag", "v0.2.3"], cwd=repository, check=True) + ignored_package_input = force_included / "probe.pyc" + ignored_package_input.write_bytes(b"different package bytes\n") + + with pytest.raises(AssertionError, match="untracked package inputs") as error: + _assert_published_version_matches_repository( + repository=repository, + current_version="0.2.3", + ) + + assert "evals/probe.pyc" in str(error.value) + + class _StrictVerificationModel(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True, strict=True)