From b62fe4da6fa8099e63037ccffa5146d8a90dff8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:22:20 +0000 Subject: [PATCH 1/6] Initial plan From b4f19b72da578c2e286d42e6663cce057ca576f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:25:59 +0000 Subject: [PATCH 2/6] Add golden hash regression tests and replay demonstration test Co-authored-by: LalaSkye <228581229+LalaSkye@users.noreply.github.com> --- STABILITY_LOG.md | 1 + commit_gate/tests/test_determinism.py | 37 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/STABILITY_LOG.md b/STABILITY_LOG.md index dd2c387..34bc834 100644 --- a/STABILITY_LOG.md +++ b/STABILITY_LOG.md @@ -6,3 +6,4 @@ Append-only record of system state. Format: --- 2026-02-22 | touched:stop-machine,constraint-workshop | CI:green | note:Legibility pack v0.5 complete. v0 stubs deployed, drift alarms active, CANONICAL.md pinned, INTEGRATION_MATRIX + ENGINEERING_STATUS committed. +2026-03-01 | touched:constraint-workshop | CI:green | note:Addressed gaps from OUTSTANDING_WORK_RISK_REPORT — golden hash regression tests added, replay demonstration test added (test_determinism.py). diff --git a/commit_gate/tests/test_determinism.py b/commit_gate/tests/test_determinism.py index 8328c01..2e19f7f 100644 --- a/commit_gate/tests/test_determinism.py +++ b/commit_gate/tests/test_determinism.py @@ -114,3 +114,40 @@ def test_artefact_version(): """Artefact version is 0.1.""" v = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) assert v["artefact_version"] == "0.1" + + +# Golden regression constants — do not change without contract revision +_GOLDEN_REQUEST_HASH = "91be8e7594ee9fc3967632dce931884f6dbf357f58794fbca54b9e579fda447f" +_GOLDEN_DECISION_HASH = "09880c122bcec255c2964a28344496bca7b85e74fcb5180c304358beae5cc497" + + +def test_golden_request_hash(): + """Golden: canonical request hash for SAMPLE_REQUEST is pinned.""" + req_obj = build_request_obj( + actor_id=SAMPLE_REQUEST["actor_id"], + action_class=SAMPLE_REQUEST["action_class"], + context=SAMPLE_REQUEST["context"], + authority_scope=SAMPLE_REQUEST["authority_scope"], + invariant_hash=SAMPLE_REQUEST["invariant_hash"], + ) + assert canonical_hash(req_obj) == _GOLDEN_REQUEST_HASH, ( + "request_hash changed — canonicalise or field order may have drifted" + ) + + +def test_golden_decision_hash(): + """Golden: decision_hash for SAMPLE_REQUEST + SAMPLE_RULESET is pinned.""" + v = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) + assert v["request_hash"] == _GOLDEN_REQUEST_HASH, "request_hash drifted from golden" + assert v["decision_hash"] == _GOLDEN_DECISION_HASH, ( + "decision_hash changed — verdict, reasons, or canonicalise may have drifted" + ) + + +def test_replay_produces_identical_decision_hash(): + """Replay: evaluating the same request twice produces byte-identical decision artefacts.""" + v1 = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) + v2 = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) + assert v1["decision_hash"] == v2["decision_hash"], "decision_hash differs on replay" + assert v1["decision_hash"] == _GOLDEN_DECISION_HASH, "replayed decision_hash differs from golden" + assert canonicalise(v1) == canonicalise(v2), "Artefact bytes not identical on replay" From 53dbe6a9d3548fa6ed4237e2d5232d2352ab4533 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:28:28 +0000 Subject: [PATCH 3/6] Revert "Add golden hash regression tests and replay demonstration test" This reverts commit b4f19b72da578c2e286d42e6663cce057ca576f5. --- STABILITY_LOG.md | 1 - commit_gate/tests/test_determinism.py | 37 --------------------------- 2 files changed, 38 deletions(-) diff --git a/STABILITY_LOG.md b/STABILITY_LOG.md index 34bc834..dd2c387 100644 --- a/STABILITY_LOG.md +++ b/STABILITY_LOG.md @@ -6,4 +6,3 @@ Append-only record of system state. Format: --- 2026-02-22 | touched:stop-machine,constraint-workshop | CI:green | note:Legibility pack v0.5 complete. v0 stubs deployed, drift alarms active, CANONICAL.md pinned, INTEGRATION_MATRIX + ENGINEERING_STATUS committed. -2026-03-01 | touched:constraint-workshop | CI:green | note:Addressed gaps from OUTSTANDING_WORK_RISK_REPORT — golden hash regression tests added, replay demonstration test added (test_determinism.py). diff --git a/commit_gate/tests/test_determinism.py b/commit_gate/tests/test_determinism.py index 2e19f7f..8328c01 100644 --- a/commit_gate/tests/test_determinism.py +++ b/commit_gate/tests/test_determinism.py @@ -114,40 +114,3 @@ def test_artefact_version(): """Artefact version is 0.1.""" v = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) assert v["artefact_version"] == "0.1" - - -# Golden regression constants — do not change without contract revision -_GOLDEN_REQUEST_HASH = "91be8e7594ee9fc3967632dce931884f6dbf357f58794fbca54b9e579fda447f" -_GOLDEN_DECISION_HASH = "09880c122bcec255c2964a28344496bca7b85e74fcb5180c304358beae5cc497" - - -def test_golden_request_hash(): - """Golden: canonical request hash for SAMPLE_REQUEST is pinned.""" - req_obj = build_request_obj( - actor_id=SAMPLE_REQUEST["actor_id"], - action_class=SAMPLE_REQUEST["action_class"], - context=SAMPLE_REQUEST["context"], - authority_scope=SAMPLE_REQUEST["authority_scope"], - invariant_hash=SAMPLE_REQUEST["invariant_hash"], - ) - assert canonical_hash(req_obj) == _GOLDEN_REQUEST_HASH, ( - "request_hash changed — canonicalise or field order may have drifted" - ) - - -def test_golden_decision_hash(): - """Golden: decision_hash for SAMPLE_REQUEST + SAMPLE_RULESET is pinned.""" - v = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) - assert v["request_hash"] == _GOLDEN_REQUEST_HASH, "request_hash drifted from golden" - assert v["decision_hash"] == _GOLDEN_DECISION_HASH, ( - "decision_hash changed — verdict, reasons, or canonicalise may have drifted" - ) - - -def test_replay_produces_identical_decision_hash(): - """Replay: evaluating the same request twice produces byte-identical decision artefacts.""" - v1 = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) - v2 = evaluate(SAMPLE_REQUEST, SAMPLE_RULESET) - assert v1["decision_hash"] == v2["decision_hash"], "decision_hash differs on replay" - assert v1["decision_hash"] == _GOLDEN_DECISION_HASH, "replayed decision_hash differs from golden" - assert canonicalise(v1) == canonicalise(v2), "Artefact bytes not identical on replay" From 9f70c53d470da96085a6fffdc70959cb6d9ff553 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:56:59 +0000 Subject: [PATCH 4/6] Add EVIDENCE_MAP.md, VERIFY.md, EVIDENCE_PACK.md from repo truth Co-authored-by: LalaSkye <228581229+LalaSkye@users.noreply.github.com> --- EVIDENCE_MAP.md | 80 ++++++++++++++++++++ EVIDENCE_PACK.md | 94 ++++++++++++++++++++++++ VERIFY.md | 187 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+) create mode 100644 EVIDENCE_MAP.md create mode 100644 EVIDENCE_PACK.md create mode 100644 VERIFY.md diff --git a/EVIDENCE_MAP.md b/EVIDENCE_MAP.md new file mode 100644 index 0000000..79c7a45 --- /dev/null +++ b/EVIDENCE_MAP.md @@ -0,0 +1,80 @@ +# Evidence Map + +Generated from repo truth. No architecture proposed — only pointing to what exists. + +## Key file paths + +| Artefact | Path | +|---|---| +| Gate primitive (engine) | `commit_gate/src/commit_gate/engine.py` | +| Canonicalisation | `commit_gate/src/commit_gate/canonicalise.py` | +| Drift detector | `commit_gate/src/commit_gate/drift.py` | +| CLI (verifier entry point) | `commit_gate/src/commit_gate/cli.py` | +| Ruleset (decision schema) | `commit_gate/rules/ruleset.json` | +| Authority graph baseline | `commit_gate/baselines/authority_graph.json` | +| Determinism tests | `commit_gate/tests/test_determinism.py` | +| Drift tests | `commit_gate/tests/test_drift.py` | +| CI workflow — general | `.github/workflows/ci.yml` | +| CI workflow — commit gate | `.github/workflows/commit_gate_ci.yml` | +| Prometheus observability | `prometheus/src/prometheus/` | +| Prometheus tests | `prometheus/tests/` | +| Stop-machine primitive | `stop_machine.py` | +| Authority-gate primitive | `authority_gate.py` | +| Invariant litmus primitive | `invariant_litmus.py` | + +## Determinism test coverage + +The following tests exist in `commit_gate/tests/test_determinism.py`: + +| Test | What it proves | +|---|---| +| `test_t1_determinism` | Same input → byte-identical output artefact (two calls) | +| `test_t2_hash_stability` | `request_hash` is stable across calls; length and case validated | +| `test_t3_ordering` | Key ordering and `reasons` list are stable regardless of insertion order | +| `test_verdict_allow` | Allowlist match → `ALLOW` verdict | +| `test_verdict_refuse_denylist` | Denylist match → `REFUSE` verdict | +| `test_verdict_escalate` | Escalation match → `ESCALATE` verdict | +| `test_verdict_default_refuse` | No match → default `REFUSE` | +| `test_scope_superset_allowed` | Superset scope keys still match rule | +| `test_artefact_version` | Artefact version is `0.1` | + +**Golden-hash pinned constants** (fixed SHA-256 → fixed output) are not currently in the test suite. +They were proposed but require explicit authority to add (see `OUTSTANDING_WORK_RISK_REPORT.md`). + +## Commands to run tests locally + +```bash +# All tests (commit_gate + prometheus + top-level primitives) +pip install pytest +pytest -q + +# commit_gate only +cd commit_gate +python -m pytest tests/ -v + +# prometheus only +bash scripts/test_prometheus.sh +# or directly: +python -m pytest prometheus/tests/ -v + +# Top-level primitives only +pytest test_stop_machine.py test_authority_gate.py test_invariant_litmus.py -v +``` + +## GitHub Actions workflow names + +| Workflow file | Workflow name | Trigger | +|---|---|---| +| `.github/workflows/ci.yml` | `ci` | push / pull_request (all paths) | +| `.github/workflows/commit_gate_ci.yml` | `Commit Gate CI` | push / pull_request on `commit_gate/**` | + +## Post-ready proof links + +| Label | URL | +|---|---| +| Main repo | https://github.com/LalaSkye/constraint-workshop | +| Gate primitive directory | https://github.com/LalaSkye/constraint-workshop/tree/main/commit_gate/src/commit_gate | +| Determinism test file | https://github.com/LalaSkye/constraint-workshop/blob/main/commit_gate/tests/test_determinism.py | +| CLI / verifier script | https://github.com/LalaSkye/constraint-workshop/blob/main/commit_gate/src/commit_gate/cli.py | +| Actions runs (Commit Gate CI) | https://github.com/LalaSkye/constraint-workshop/actions/workflows/commit_gate_ci.yml | +| Latest release / tag | https://github.com/LalaSkye/constraint-workshop/releases/tag/commit_gate-v0.1.0 | diff --git a/EVIDENCE_PACK.md b/EVIDENCE_PACK.md new file mode 100644 index 0000000..c239b5b --- /dev/null +++ b/EVIDENCE_PACK.md @@ -0,0 +1,94 @@ +# Evidence Pack + +Instructions to generate a reproducible evidence zip and sha256sums. No private keys or secrets included. + +## File list + +| File | Purpose | +|---|---| +| `authority_gate.py` | Authority gate primitive | +| `stop_machine.py` | Stop-machine primitive | +| `invariant_litmus.py` | Invariant litmus primitive | +| `commit_gate/src/commit_gate/canonicalise.py` | Canonicalisation + hashing | +| `commit_gate/src/commit_gate/engine.py` | Gate engine (evaluate + build_request_obj) | +| `commit_gate/src/commit_gate/cli.py` | CLI entry point | +| `commit_gate/src/commit_gate/drift.py` | Drift detector | +| `commit_gate/tests/test_determinism.py` | Determinism tests T1-T3 + verdict coverage | +| `commit_gate/tests/test_drift.py` | Drift detection tests T4-T6 | +| `commit_gate/rules/ruleset.json` | Bundled ruleset | +| `commit_gate/baselines/authority_graph.json` | Baseline authority graph | +| `.github/workflows/ci.yml` | General CI workflow | +| `.github/workflows/commit_gate_ci.yml` | Commit Gate CI workflow | +| `EVIDENCE_MAP.md` | Evidence map (this repo) | +| `VERIFY.md` | Verifier documentation | +| `EVIDENCE_PACK.md` | This file | + +## Commands to generate the evidence zip + +Run from the repository root: + +```bash +# 1. Create output directory +mkdir -p /tmp/evidence_pack + +# 2. Copy files +cp authority_gate.py stop_machine.py invariant_litmus.py /tmp/evidence_pack/ +cp -r commit_gate /tmp/evidence_pack/ +mkdir -p /tmp/evidence_pack/.github/workflows +cp .github/workflows/ci.yml .github/workflows/commit_gate_ci.yml /tmp/evidence_pack/.github/workflows/ +cp EVIDENCE_MAP.md VERIFY.md EVIDENCE_PACK.md /tmp/evidence_pack/ + +# 3. Generate sha256sums +(cd /tmp/evidence_pack && find . -type f | sort | xargs sha256sum) > /tmp/evidence_pack/sha256sums.txt + +# 4. Zip +(cd /tmp && zip -r evidence_pack.zip evidence_pack/) + +echo "Evidence pack written to /tmp/evidence_pack.zip" +echo "SHA-256 of zip:" +sha256sum /tmp/evidence_pack.zip +``` + +## Current sha256sums (at time of document generation) + +``` +78975c58f28c95bdb111f787b8edec58c2bdbdd132e2ea7c8e7b7c1e8e67e6f5 authority_gate.py +473da80d555daf7883bfbe84a24c54660e9f844a6fa8d11d1f9ce68e91a41c5c stop_machine.py +f19740d0712d67a185ba2ed557e4459cf66bea6e94229c641f4b31ca5424b2b2 invariant_litmus.py +69c5e87b7492dd9083f2a309c55d46fa96d47ff67ab019e56b53ad9b3d65ba67 commit_gate/src/commit_gate/canonicalise.py +0c3849e4843aa0ae3bbfbe49c738e969ab2f48d4a00c8745173ec362fc600011 commit_gate/src/commit_gate/engine.py +34a06af33216d8190f3df691f0bdae43567f2356f60f942c0b0c0e18cb88a55f commit_gate/src/commit_gate/cli.py +9e4da9eda0cd74a9a9542a14417d098af82abd06d88c8173970d98fbf4c3ebfb commit_gate/src/commit_gate/drift.py +b3538e34e6d14778fc5c5250b4f8cd8857cac093e0ff10fa76edb0bab8e09f87 commit_gate/tests/test_determinism.py +df741d98527925a4b2c581c6ee60ca648e8584b3a46fb64cc3cc77fc20605221 commit_gate/tests/test_drift.py +2e818f16bae33eb61d592daa72d1ab0a08fa089d32778329e3da76440abc63aa commit_gate/rules/ruleset.json +c590f7a734a4411728fc1f9ed71a8464cdf8928d49e9a5d6ad85b3df68b27553 commit_gate/baselines/authority_graph.json +96cdd3572425cdc49bcb1f98972a259c496b9875b51284c51663f12e55ae9e9f .github/workflows/ci.yml +94170f21d01058ad2ae7a5e26a5b1e53a772fb5c562cdf8636d446d94ae589c7 .github/workflows/commit_gate_ci.yml +``` + +> **Note:** Re-run `sha256sum` against the repo files to verify they match before trusting this pack. +> The hashes above reflect the state at commit `53dbe6a` (post-revert, protected paths clean). +> Re-run the command block below whenever verifying against a different commit. + +## How to verify the pack against this document + +```bash +# From the repo root, re-compute and diff against the table above: +sha256sum \ + authority_gate.py \ + stop_machine.py \ + invariant_litmus.py \ + commit_gate/src/commit_gate/canonicalise.py \ + commit_gate/src/commit_gate/engine.py \ + commit_gate/src/commit_gate/cli.py \ + commit_gate/src/commit_gate/drift.py \ + commit_gate/tests/test_determinism.py \ + commit_gate/tests/test_drift.py \ + commit_gate/rules/ruleset.json \ + commit_gate/baselines/authority_graph.json \ + .github/workflows/ci.yml \ + .github/workflows/commit_gate_ci.yml +``` + +Any mismatch indicates the file was modified after this document was generated. diff --git a/VERIFY.md b/VERIFY.md new file mode 100644 index 0000000..fd3155a --- /dev/null +++ b/VERIFY.md @@ -0,0 +1,187 @@ +# Verify — How to verify a commit gate decision artefact + +All information sourced from repo code. No invented architecture. + +## 1. Canonicalisation rules + +Source: `commit_gate/src/commit_gate/canonicalise.py` + +| Rule | Value | +|---|---| +| Encoding | UTF-8 | +| Key ordering | Sorted recursively (all levels) | +| Whitespace | None (no spaces, no newlines) | +| List ordering | Preserved as-is — **caller must pre-sort** | +| Hash algorithm | SHA-256 | +| Hash encoding | Lowercase hex string (64 characters) | + +**Canonical JSON example** (actual output for the SAMPLE_REQUEST in tests): + +``` +{"action_class":"FILE","actor_id":"ricky","authority_scope":{"project":"alpha"},"context":{"description":"test commit"},"invariant_hash":"abc123"} +``` + +## 2. How `request_hash` is computed + +Source: `commit_gate/src/commit_gate/engine.py` — `build_request_obj` + `canonical_hash` + +1. Build a request object from these five fields (timestamp excluded): + - `actor_id` + - `action_class` + - `context` + - `authority_scope` + - `invariant_hash` +2. Apply canonicalise (sorted keys, no whitespace, UTF-8). +3. SHA-256 hex digest of the resulting bytes. + +```python +request_obj = { + "actor_id": ..., + "action_class": ..., + "context": ..., + "authority_scope": ..., + "invariant_hash": ..., +} +request_hash = sha256(canonical_json(request_obj)) +``` + +## 3. How `decision_hash` is computed + +Source: `commit_gate/src/commit_gate/engine.py` — `evaluate` + +1. Resolve verdict (`ALLOW` / `REFUSE` / `ESCALATE`) using the deterministic resolution order. +2. Collect and sort `reasons` lexicographically. +3. Build decision object: + +```python +decision_obj = { + "request": request_obj, # same object as in request_hash + "verdict": verdict, + "reasons": sorted_reasons, +} +decision_hash = sha256(canonical_json(decision_obj)) +``` + +The `decision_hash` commits to: the full request fields, the verdict, and the reasons list. + +## 4. Verdict output schema (CommitVerdict) + +The CLI and `evaluate()` both return canonical JSON with these fields: + +| Field | Type | Notes | +|---|---|---| +| `verdict` | string | `ALLOW`, `REFUSE`, or `ESCALATE` | +| `reasons` | array of strings | Sorted lexicographically | +| `decision_hash` | string | 64-char lowercase SHA-256 hex | +| `request_hash` | string | 64-char lowercase SHA-256 hex | +| `artefact_version` | string | `"0.1"` | + +Fields in canonical output are sorted alphabetically. + +## 5. Resolution order (deterministic) + +Source: `commit_gate/src/commit_gate/engine.py` docstring + +``` +1. Denylist match => REFUSE (reason: denylist_match) +2. Allowlist match => ALLOW (reason: allowlist_match) +3. Escalation match => ESCALATE (reason: escalation_match) +4. Default => REFUSE (reason: default_refuse) +``` + +## 6. Scope matching rules + +Source: `commit_gate/src/commit_gate/engine.py` — `_scope_matches` + +- Exact string match only (no glob, no regex, no prefix). +- All keys in `rule.scope_match` must exist in `request.authority_scope` with identical values. +- Request may carry extra scope keys (superset is allowed). + +## 7. Chain / genesis note + +This implementation does not use a blockchain-style hash chain. Each verdict is a self-contained artefact. There is no `prev_hash` field and no GENESIS sentinel in the current v0.1 schema. + +## 8. How to run the verifier CLI + +Source: `commit_gate/src/commit_gate/cli.py` + +### Evaluate a request + +```bash +# from the repo root +python -m commit_gate evaluate \ + --request commit_gate/rules/request_example.json \ + --ruleset commit_gate/rules/ruleset.json +``` + +Or using the bundled ruleset with an inline request file: + +```bash +cat > /tmp/request.json <<'EOF' +{ + "actor_id": "ricky", + "action_class": "FILE", + "context": {"description": "test commit"}, + "authority_scope": {"project": "alpha"}, + "invariant_hash": "abc123" +} +EOF + +cd commit_gate +python -m commit_gate evaluate \ + --request /tmp/request.json \ + --ruleset rules/ruleset.json +``` + +### Detect authority drift + +```bash +cd commit_gate +python -m commit_gate drift \ + --baseline baselines/authority_graph.json \ + --ruleset rules/ruleset.json \ + --invariant-hash abc123 +``` + +## 9. Expected pass/fail outputs + +### Evaluate — ALLOW (exit 0) + +```json +{"artefact_version":"0.1","decision_hash":"09880c122bcec255c2964a28344496bca7b85e74fcb5180c304358beae5cc497","reasons":["allowlist_match"],"request_hash":"91be8e7594ee9fc3967632dce931884f6dbf357f58794fbca54b9e579fda447f","verdict":"ALLOW"} +``` + +Exit code: `0` + +### Evaluate — REFUSE (exit 1) + +```json +{"artefact_version":"0.1","decision_hash":"","reasons":["default_refuse"],"request_hash":"","verdict":"REFUSE"} +``` + +Exit code: `1` + +### Drift — PASS (exit 0) + +```json +{"added_edges":[],"pass":true,"reason":"no_expansion","removed_edges":[]} +``` + +Exit code: `0` + +### Drift — FAIL (exit 1) + +```json +{"added_edges":[["ricky","SIGN"]],"pass":false,"reason":"reachability_expansion_without_contract_revision","removed_edges":[]} +``` + +Exit code: `1` + +## 10. Run existing determinism tests + +```bash +cd commit_gate +python -m pytest tests/test_determinism.py -v +``` + +Expected: all 9 tests pass across Python 3.10, 3.11, 3.12. From 616431ab2b779ce748937f34fe1a94e3ab64e793 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:01:23 +0000 Subject: [PATCH 5/6] Add authority gate proof surface section to EVIDENCE_MAP.md Co-authored-by: LalaSkye <228581229+LalaSkye@users.noreply.github.com> --- EVIDENCE_MAP.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/EVIDENCE_MAP.md b/EVIDENCE_MAP.md index 79c7a45..b250e48 100644 --- a/EVIDENCE_MAP.md +++ b/EVIDENCE_MAP.md @@ -68,6 +68,76 @@ pytest test_stop_machine.py test_authority_gate.py test_invariant_litmus.py -v | `.github/workflows/ci.yml` | `ci` | push / pull_request (all paths) | | `.github/workflows/commit_gate_ci.yml` | `Commit Gate CI` | push / pull_request on `commit_gate/**` | +## Proof surface + +### Authority gate primitive + +**File:** `authority_gate.py` +**Test file:** `test_authority_gate.py` + +#### Evidence levels (totally ordered, monotonic) + +| Name | Value | +|---|---| +| `Evidence.NONE` | 0 | +| `Evidence.USER` | 1 | +| `Evidence.OWNER` | 2 | +| `Evidence.ADMIN` | 3 | + +#### Decision outcomes + +| Name | Value | +|---|---| +| `Decision.DENY` | 0 | +| `Decision.ALLOW` | 1 | + +#### Interface + +```python +from authority_gate import Evidence, Decision, AuthorityGate + +gate = AuthorityGate(Evidence.OWNER) # required_level fixed at construction +gate.check(Evidence.ADMIN) # -> Decision.ALLOW (provided >= required) +gate.check(Evidence.USER) # -> Decision.DENY (provided < required) +``` + +`check()` is pure: same inputs always produce the same output. No side effects, no logging, no state mutation. + +#### Stated invariants (from source docstring) + +- `required_level` is fixed at construction; immutable thereafter. +- `check()` is pure — same inputs → same output. +- Evidence ordering is total and monotonic (`NONE < USER < OWNER < ADMIN`). +- No side effects. No logging. No state mutation. +- Passing a non-`Evidence` value to either `__init__` or `check()` raises `TypeError`. + +#### Test coverage (`test_authority_gate.py`) + +| Test | What it proves | +|---|---| +| `test_gate_stores_required_level` | `required_level` property is preserved at construction | +| `test_gate_rejects_non_evidence_required` | `TypeError` on non-`Evidence` constructor arg | +| `test_exact_match_allows` | `provided == required` → `ALLOW` | +| `test_higher_than_required_allows` | `provided > required` → `ALLOW` | +| `test_admin_always_passes_any_gate` | `ADMIN` passes every gate level | +| `test_none_denied_by_user_gate` | `NONE` < `USER` → `DENY` | +| `test_user_denied_by_admin_gate` | `USER` < `ADMIN` → `DENY` | +| `test_owner_denied_by_admin_gate` | `OWNER` < `ADMIN` → `DENY` | +| `test_none_gate_allows_everything` | Gate at `NONE` passes all evidence levels | +| `test_check_rejects_non_evidence_provided` | `TypeError` on non-`Evidence` `check()` arg | +| `test_deterministic_across_calls` | 100-iteration proof: same inputs → same output every call | +| `test_evidence_ordering_is_total` | `NONE < USER < OWNER < ADMIN` by integer comparison | + +#### How to run + +```bash +# from the repo root +pip install pytest +pytest test_authority_gate.py -v +``` + +Expected: 12 tests pass. + ## Post-ready proof links | Label | URL | From df6fb8eca2e3b2f288c3dedcf083f6346b3e4a2c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:05:50 +0000 Subject: [PATCH 6/6] Add LINK_INDEX.md with SHA-locked GitHub permalinks for LinkedIn proof drop Co-authored-by: LalaSkye <228581229+LalaSkye@users.noreply.github.com> --- LINK_INDEX.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 LINK_INDEX.md diff --git a/LINK_INDEX.md b/LINK_INDEX.md new file mode 100644 index 0000000..3c1d9a8 --- /dev/null +++ b/LINK_INDEX.md @@ -0,0 +1,46 @@ +# Link Index — LinkedIn proof drop + +SHA-locked GitHub permalink for each artefact. +No branch URLs. Every link pins an exact commit SHA. + +--- + +- **Authority gate primitive source** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/authority_gate.py + +- **Authority gate test suite** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/test_authority_gate.py + +- **Evidence map with proof surface section** + SHA: `616431ab2b779ce748937f34fe1a94e3ab64e793` + https://github.com/LalaSkye/constraint-workshop/blob/616431ab2b779ce748937f34fe1a94e3ab64e793/EVIDENCE_MAP.md + +- **Verifier reference (canonicalisation + hash rules)** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/VERIFY.md + +- **Evidence pack assembly instructions** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/EVIDENCE_PACK.md + +- **Latest passing CI workflow run** (run #133, main, conclusion: success) + SHA: `acf35876c1da0fd94b338c8304ed0f7f09fe6ab9` + https://github.com/LalaSkye/constraint-workshop/actions/runs/22542297797 + +- **Commit gate CI workflow file** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/.github/workflows/commit_gate_ci.yml + +- **Determinism test file** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/commit_gate/tests/test_determinism.py + +- **Canonicalisation implementation** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/commit_gate/src/commit_gate/canonicalise.py + +- **Verifier CLI entry point** + SHA: `9f70c53d470da96085a6fffdc70959cb6d9ff553` + https://github.com/LalaSkye/constraint-workshop/blob/9f70c53d470da96085a6fffdc70959cb6d9ff553/commit_gate/src/commit_gate/cli.py