diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a0a60c..77a2230 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project are recorded here. The format follows Keep a ## [Unreleased] +### Added + +- A controlled membership-observation study (#38) enumerates mixed before/after refs for families, semaphore slots and prefix descendants. Real Git transactions leave independent invariant violations in 21 of 84 synthetic cases. The fixture retains exact observations and transaction receipts, calibrates its independent oracle, and returns exit 1 when it exposes a safety failure. No live Git race is claimed and no production fix is included; #45 tracks the unresolved correctness work. + ## [0.7.0] - 2026-09-16 ### Added diff --git a/Makefile b/Makefile index fede374..1865a90 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ SHELL := /usr/bin/env bash # lib/*.sh are fragments of one script and only lint as the whole they build into (bin/git-locks). -SCRIPTS := bin/git-locks test/test.sh scripts/hooks/pre-commit scripts/hooks/pre-push scripts/build.sh +SCRIPTS := bin/git-locks test/test.sh test/observation/git-shim.sh scripts/hooks/pre-commit scripts/hooks/pre-push scripts/build.sh PREFIX ?= $(HOME)/.local -.PHONY: build lint test test-docker install uninstall +.PHONY: build lint test test-docker study-observation test-observation-calibration install uninstall build: # assemble bin/git-locks from lib/*.sh and schema/git-locks.schema.json; commit the result with the lib change bash scripts/build.sh @@ -14,6 +14,17 @@ lint: test: bash test/test.sh + python3 test/observation/study.py --calibrate-only --output "$$(mktemp -d)/observation-calibration" + +# The study deliberately returns 1 if it exposes a production invariant hole. +# Choose a fresh output directory; retained receipts are never overwritten. +OBSERVATION_OUT ?= /tmp/git-locks-observation + +study-observation: + python3 test/observation/study.py --output "$(OBSERVATION_OUT)" + +test-observation-calibration: + python3 test/observation/study.py --calibrate-only --output "$(OBSERVATION_OUT)-calibration" test-docker: # the same suite inside the official bash image, for a wall between the tests and your machine docker run --rm -v "$(CURDIR)":/src -w /src bash:5.2 bash -c 'apk add --no-cache git python3 py3-jsonschema >/dev/null && git config --global user.email t@example.invalid && git config --global user.name t && bash test/test.sh' diff --git a/README.md b/README.md index 64cdd64..69f4ab7 100644 --- a/README.md +++ b/README.md @@ -343,7 +343,7 @@ An outside review of 0.2.1 found the guarantees running ahead of the implementat **What a successful acquisition authorises, and how it is identified.** A claim admits one *acquisition*, and three names apply to it, kept distinct on purpose. The **job id** is a label a person or an orchestrator chooses; it can be reused, and a later claim under the same job is a new acquisition that replaces the old one. The **acquisition id** (`acquisition` on the claim line) is minted by the claim and kept by every rewrite of the record: `extend`, and the family bump a child admission performs on a parent. The **record** (`record`) is the object id of the current version of that record, and changes on every rewrite. `release --job X --acquisition ` releases that acquisition and only that one, across any number of renewals; `--record ` releases only if the record is exactly that version. If the job now holds a different acquisition, the answer is `{"event":"nothing","reason":"superseded"}` and nothing moves. `with` remembers the acquisition it made and releases by it, so an invocation that outlives a re-claim of its job name cannot release someone else's lock, and one whose command renewed the lock still releases it. Semaphore slots carry the same two ids. -**What binds the membership you observed to the decision you commit.** Every write is compiled into one transition per ref with the old value it expects, and sent as one transaction; a stale expectation fails the whole transaction and the command re-reads and re-plans a bounded number of times. Family membership is bound through the parent's own record: admitting a child rewrites the parent's blob with a bumped `family` generation and moves the parent's refs to it, so a release or sweep that planned against the old parent fails when a child was admitted meanwhile, and re-plans with the child in view. Semaphore capacity is bound through the semaphore's generation ref the same way. A snapshot is a cached read taken under one `for-each-ref`; it is never treated as a consistent cut, which is why every write carries expectations. +**What binds the membership you observed to the decision you commit.** Every write is compiled into one transition per ref with the old value it expects, and sent as one transaction; a stale expectation fails the whole transaction and the command re-reads and re-plans a bounded number of times. Family membership is bound through the parent's own record: admitting a child rewrites the parent's blob with a bumped `family` generation and moves the parent's refs to it, so a release or sweep that planned against the old parent fails when a child was admitted meanwhile, and re-plans with the child in view. Semaphore capacity is bound through the semaphore's generation ref the same way. A snapshot is a cached read taken under one `for-each-ref`; it is not a consistent cut. Expected ref values detect stale values, but do not by themselves establish that membership and its generation were observed coherently. The [membership observation study](docs/studies/membership-observation/README.md) exposes synthetic counterexamples in families, semaphores and prefixes; [#45](https://github.com/git-stunts/locks/issues/45) tracks the unresolved correctness fix. A live Git schedule producing those observations has not been reproduced. **What `parent` means.** Ownership plus lifetime, not dependency ordering. A child is admitted only under a live parent held by the same holder. Liveness and holder are checked at planning time; what the generation bump adds at commit time is that the parent's record is unchanged since that check, so a release, a renewal or another child cannot have slipped in between. The bump does not re-check the clock: a parent that expires during the microseconds between planning and commit is still bumped, and its family ends at the next sweep or claim over it. The child is released or swept whenever the parent is, by any command, including a claim that evicts an expired parent. Expiry is not inherited: a child keeps its own `expires`, and a parent's expiry ends the family. Renewing a parent (`extend`) keeps its family. Recreating a job name after its release makes a new record with a fresh family, unrelated to the old one. diff --git a/docs/studies/membership-observation/README.md b/docs/studies/membership-observation/README.md new file mode 100644 index 0000000..56fa827 --- /dev/null +++ b/docs/studies/membership-observation/README.md @@ -0,0 +1,103 @@ +# Membership observation study + +The controlled reader exposed unsafe commits in all three studied domains. Across 84 synthetic per-ref observations, 21 commands returned success and left a family, semaphore-capacity or prefix-exclusivity violation. Production code is unchanged. The corrective work is tracked by [#45](https://github.com/git-stunts/locks/issues/45), an unresolved release correctness gate in [#41](https://github.com/git-stunts/locks/issues/41). + +These are synthetic observation counterexamples executed against real objects and real Git transactions. This study did **not** reproduce a live Git reader/writer schedule. It establishes how the planner behaves when given these mixed observations, and challenges the claim that generation compare-and-swap alone makes any cached observation safe. + +## Question and assumptions + +A generation check can detect a change that happens after a coherent membership scan. Does it also reject a scan that already contains the current generation and incomplete membership? + +Git's [update-ref documentation](https://git-scm.com/docs/git-update-ref), checked on 2026-09-22, says that "a concurrent reader may still see a subset of the modifications." The documentation does not promise a consistent snapshot across refs. That permits concern about mixed observations; it does not prove that every synthetic combination in this study occurs under a particular Git backend or ref-enumeration order. + +The subject is the unchanged executable at `01e39c306362d7de26cec08f149d7f286e3733ce`, with `GIT_LOCKS_NOW=1000000`. Each case creates its own store. A normal command first creates state A. Another normal command adds one family child, one semaphore slot, or one path below a directory, creating state B. Both initial states pass the independent checks. State B is fully committed before the candidate command begins. + +The candidate receives one synthetic `for-each-ref` response. Each changed ref independently takes its value from A or B; absence is also a value. Unchanged refs remain present. Immutable objects are fetched from the actual store. The shim never rewrites object contents or substitutes an `update-ref` result. The candidate's transaction runs against the real, fully committed B. Any retry receives the real current refs. + +This deliberately separates two questions: + +1. Can the planner commit unsafely from this observation? The controlled fixture answers this. +2. Can a live Git reader produce this observation during a supported backend's transaction? This remains unverified. + +## Results + +The complete ref-mix space was enumerated for three deterministic name variants, seeds `38`, `1701` and `20260922`. These seeds change job and directory names; they do not represent random samples of arbitrary family shapes or process schedules. + +| Domain | Changed refs per transition | Cases | Cases with a studied violation | Representative case | +| --- | ---: | ---: | ---: | --- | +| Family child admission | 4 | 48 | 12 | [`family-38-14`](evidence/family-38-14/result.json) | +| Semaphore slot admission | 2 | 12 | 3 | [`semaphore-38-01`](evidence/semaphore-38-01/result.json) | +| Descendant path admission | 3 | 24 | 6 | [`prefix-38-01`](evidence/prefix-38-01/result.json) | +| Total | | 84 | 21 | [Complete result ledger](evidence/report.json) | + +All 21 violating cases returned exit 0 and completed a real transaction. The other 63 cases had no violation of the three studied invariants. That is a bounded result, not a declaration that every ref in those stores is valid. + +### Family + +The mixed observation includes the new parent job record and parent path record, but omits the child job. The reader can also include the child's path ref; family membership is discovered through job refs. + +`release --job p6899` plans only the parent deletions. The transaction expects the current parent record, so its compare-and-swap succeeds. Child job `c6899` and its path ref remain after parent `p6899` is deleted. The independent oracle reports `family-parent` because the child's named parent no longer exists. + +The retained [observed refs](evidence/family-38-14/observed.refs), [transaction input](evidence/family-38-14/transaction-1.stdin), and [final raw state](evidence/family-38-14/final.json) show the missing membership, successful current-generation expectation, and resulting orphan. + +A possible reader-order explanation would read the absent child job before the writer commits and the updated parent job afterward. This is a hypothesis requiring live backend instrumentation, not a reproduced schedule. + +### Semaphore + +The observation retains the new `refs/locks/sem/gpu/gen`, the unchanged capacity of 1, and no slot. In the real store, one live slot is already committed. + +`sem acquire gpu --job z6899 --holder bob` counts zero visible slots and plans a new one. The current generation expectation matches. Its successful transaction leaves two live slots with capacity 1. The [raw final state](evidence/semaphore-38-01/final.json) supplies both slot records and the capacity record to the independent oracle. + +### Prefix + +The observation retains the new directory token but omits the descendant job. A path ref may be omitted or retained; the prefix membership scan enumerates job records. + +The candidate successfully claims `d6899/` while the real store still contains another job's `d6899/child.md`. The [transaction](evidence/prefix-38-01/transaction-1.stdin) compares against the actual current token, and the [final state](evidence/prefix-38-01/final.json) contains both live reservations. The independent oracle compares path strings and reports their overlap across different jobs. + +## Controls and oracle + +The oracle reads raw refs and blob contents through the real Git executable. It does not call production parsing helpers, `doctor`, or `check`. It checks parent existence, holder equality, parent liveness and cycles; live slot count against capacity; and overlapping live paths across different jobs. + +Six hand-checked inputs calibrate it: a healthy state and a deliberately broken state for each domain. The broken family input removes the parent job; the broken semaphore input adds a second slot reference; the broken prefix input adds a covering reservation. These are oracle inputs, not claims about how normal admission creates those states. The [calibration receipt](evidence/calibration.json) retains their exact verdicts. + +Two further controls explain where observation injection belongs. The dispatcher loads a snapshot, but release and semaphore acquisition reload before planning. Injecting only their first read was initially harmless because the planner discarded it. The final fixture retains these discarded-read controls, then injects planner read 2 for release/semaphore and read 1 for prefix claims. Every case records read order, the injected ordinal, and transaction count. If the injection does not execute or the transition's ref shape changes, the study exits 2 as an instrumentation error. + +Coherent A and coherent B observations are included for every domain and seed. Coherent old observations with stale generations retry against real B. For semaphore and prefix admission, old-generation/new-membership observations refuse on visible contention. Current-generation/incomplete-membership observations are the damaging case. + +The small ref-mix spaces are exhausted for these transitions. This is stronger than hoping a repeated concurrent launch encounters a particular mix, but it is not stress evidence about the operating system, Git's actual publication order, or arbitrary histories. The study does not examine ref-backend internals, crashes, network filesystems, semaphore deletion, expiry boundaries, deeper families, or complete job/path-ref consistency. It cannot establish the rate or reachability of a live race. + +## Reproduction and exit status + +Python is used only by this test fixture, alongside the repository's existing Python test dependency. The installed `bin/git-locks` and every `lib/` module are unchanged. + +Run the full study with a fresh retained output directory: + +```bash +make study-observation OBSERVATION_OUT=/tmp/locks-observation-review-run +``` + +The current result is **exit 1**, `production_safety: FAIL`, with 21 violating cases. This is an exposed production safety failure under the injected observations, not an expected-failure assertion converted to a passing test. Exit 0 means the studied invariants held within the tested synthetic cases. Exit 2 means the experiment could not execute reliably. Existing evidence is never overwritten. + +Run only the six oracle cases and two discarded-read controls: + +```bash +make test-observation-calibration OBSERVATION_OUT=/tmp/locks-observation-review-run +``` + +Calibration exits 0 when the fixture is working and explicitly reports `production_safety: NOT_EVALUATED`. `make test` also runs this calibration after the ordinary suite. A green ordinary suite or calibration does not mean the observation study is green. + +Every full run retains before/committed-after/final raw refs and objects, the injected refs, command stdout/stderr, read order, transaction stdin, and a result ledger. The committed evidence includes the complete 84-case ledger and representative violating/coherent cases, with [runtime and executable hashes](evidence/provenance.json). Dynamic object IDs and acquisition IDs vary between executions; the invariant failures and ref-selection categories are the comparison points. + +To verify that the retained evidence is actually committed, run: + +```bash +python3 test/observation/verify-evidence.py +``` + +This checks every manifest path against `git ls-files` and hashes its `HEAD` blob with `git show`. It does not accept an ignored or untracked working-tree file as evidence. Raw read-order receipts use `.txt` because the repository ignores `.log` files. + +## Follow-up boundary + +[#45](https://github.com/git-stunts/locks/issues/45) requires a justified relationship between membership and the witness checked at commit, plus observation-phase regressions in all three domains. The fix should preserve ordinary paths, stale-generation retries, and independent post-run invariants. It must state supported backend and read-order assumptions and distinguish synthetic evidence from any reproduced live schedule. + +An immutable per-semaphore state object in [#20](https://github.com/git-stunts/locks/issues/20) is one comparison, not a selected design. This study does not choose a broad concurrency rewrite, introduce a service, or claim production safety has been restored. diff --git a/docs/studies/membership-observation/evidence/calibration-family/deliberately-bad.json b/docs/studies/membership-observation/evidence/calibration-family/deliberately-bad.json new file mode 100644 index 0000000..af683fd --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-family/deliberately-bad.json @@ -0,0 +1,11 @@ +{ + "objects": { + "005a12f11a301cc61f8cca0be2bc32ac8d90ad29": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 1\nacquisition: 1000000-64553-1118120571\npaths:\nparent.md\n", + "81489983a390665fa6ca55a88f3a63b80b8710a6": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-64700-0612416574\npaths:\nchild.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "81489983a390665fa6ca55a88f3a63b80b8710a6", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "81489983a390665fa6ca55a88f3a63b80b8710a6", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "005a12f11a301cc61f8cca0be2bc32ac8d90ad29" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration-family/healthy.json b/docs/studies/membership-observation/evidence/calibration-family/healthy.json new file mode 100644 index 0000000..a70e418 --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-family/healthy.json @@ -0,0 +1,12 @@ +{ + "objects": { + "005a12f11a301cc61f8cca0be2bc32ac8d90ad29": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 1\nacquisition: 1000000-64553-1118120571\npaths:\nparent.md\n", + "81489983a390665fa6ca55a88f3a63b80b8710a6": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-64700-0612416574\npaths:\nchild.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "81489983a390665fa6ca55a88f3a63b80b8710a6", + "refs/locks/jobs/p6899": "005a12f11a301cc61f8cca0be2bc32ac8d90ad29", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "81489983a390665fa6ca55a88f3a63b80b8710a6", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "005a12f11a301cc61f8cca0be2bc32ac8d90ad29" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration-prefix/deliberately-bad.json b/docs/studies/membership-observation/evidence/calibration-prefix/deliberately-bad.json new file mode 100644 index 0000000..3e4ff3c --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-prefix/deliberately-bad.json @@ -0,0 +1,15 @@ +{ + "objects": { + "7922170d0fdf7866bbb9da109ade70a0306e5d1f": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-64919-2853617685\npaths:\nd6899/child.md\n", + "98ce33526658766b2734f7a9c50c3d448078f530": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-64884-1713932407\npaths:\noutside.md\n", + "calibration-object": "schema: git-locks/1\njob: covering\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-64919-2853617685\npaths:\nd6899/\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "7922170d0fdf7866bbb9da109ade70a0306e5d1f", + "refs/locks/jobs/c6899": "7922170d0fdf7866bbb9da109ade70a0306e5d1f", + "refs/locks/jobs/covering": "calibration-object", + "refs/locks/jobs/unrelated": "98ce33526658766b2734f7a9c50c3d448078f530", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "98ce33526658766b2734f7a9c50c3d448078f530", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "7922170d0fdf7866bbb9da109ade70a0306e5d1f" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration-prefix/healthy.json b/docs/studies/membership-observation/evidence/calibration-prefix/healthy.json new file mode 100644 index 0000000..745b2ef --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-prefix/healthy.json @@ -0,0 +1,13 @@ +{ + "objects": { + "7922170d0fdf7866bbb9da109ade70a0306e5d1f": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-64919-2853617685\npaths:\nd6899/child.md\n", + "98ce33526658766b2734f7a9c50c3d448078f530": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-64884-1713932407\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "7922170d0fdf7866bbb9da109ade70a0306e5d1f", + "refs/locks/jobs/c6899": "7922170d0fdf7866bbb9da109ade70a0306e5d1f", + "refs/locks/jobs/unrelated": "98ce33526658766b2734f7a9c50c3d448078f530", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "98ce33526658766b2734f7a9c50c3d448078f530", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "7922170d0fdf7866bbb9da109ade70a0306e5d1f" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration-semaphore/deliberately-bad.json b/docs/studies/membership-observation/evidence/calibration-semaphore/deliberately-bad.json new file mode 100644 index 0000000..f629a49 --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-semaphore/deliberately-bad.json @@ -0,0 +1,13 @@ +{ + "objects": { + "8d80e89ae956a510d1e79b8b6bf9ae7f26dc77ac": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-64832-2662504987\n", + "a98d184bb4f3130c142ae374f7db260c8031fbe1": "generation 1000000 64832 1027117773\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "a98d184bb4f3130c142ae374f7db260c8031fbe1", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "8d80e89ae956a510d1e79b8b6bf9ae7f26dc77ac", + "refs/locks/sem/gpu/slots/second": "8d80e89ae956a510d1e79b8b6bf9ae7f26dc77ac" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration-semaphore/healthy.json b/docs/studies/membership-observation/evidence/calibration-semaphore/healthy.json new file mode 100644 index 0000000..974a5fe --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration-semaphore/healthy.json @@ -0,0 +1,12 @@ +{ + "objects": { + "8d80e89ae956a510d1e79b8b6bf9ae7f26dc77ac": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-64832-2662504987\n", + "a98d184bb4f3130c142ae374f7db260c8031fbe1": "generation 1000000 64832 1027117773\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "a98d184bb4f3130c142ae374f7db260c8031fbe1", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "8d80e89ae956a510d1e79b8b6bf9ae7f26dc77ac" + } +} diff --git a/docs/studies/membership-observation/evidence/calibration.json b/docs/studies/membership-observation/evidence/calibration.json new file mode 100644 index 0000000..115abdc --- /dev/null +++ b/docs/studies/membership-observation/evidence/calibration.json @@ -0,0 +1,97 @@ +[ + { + "deliberately_bad_violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ], + "domain": "family", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "deliberately_bad_violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ], + "domain": "semaphore", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "deliberately_bad_violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c6899", + "covering" + ], + "paths": [ + "d6899/child.md", + "d6899/" + ] + } + ], + "domain": "prefix", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 1, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 0, + "violations": [] + } +] diff --git a/docs/studies/membership-observation/evidence/family-38-00/before.json b/docs/studies/membership-observation/evidence/family-38-00/before.json new file mode 100644 index 0000000..2105c2e --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "b1eb4a8f914eec35aaa4623066c09808efe25173": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-65718-0420903726\npaths:\nparent.md\n" + }, + "refs": { + "refs/locks/jobs/p6899": "b1eb4a8f914eec35aaa4623066c09808efe25173", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "b1eb4a8f914eec35aaa4623066c09808efe25173" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-00/committed-after.json b/docs/studies/membership-observation/evidence/family-38-00/committed-after.json new file mode 100644 index 0000000..dec8626 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "33b5ca2fdfe4682808a82b1e57e7925191e3faf8": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-65855-3133206299\npaths:\nchild.md\n", + "57bb60ad60200db3b5958f7bcc0395eade9c098e": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 1\nacquisition: 1000000-65718-0420903726\npaths:\nparent.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "33b5ca2fdfe4682808a82b1e57e7925191e3faf8", + "refs/locks/jobs/p6899": "57bb60ad60200db3b5958f7bcc0395eade9c098e", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "33b5ca2fdfe4682808a82b1e57e7925191e3faf8", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "57bb60ad60200db3b5958f7bcc0395eade9c098e" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-00/final.json b/docs/studies/membership-observation/evidence/family-38-00/final.json new file mode 100644 index 0000000..2206b4a --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/final.json @@ -0,0 +1,4 @@ +{ + "objects": {}, + "refs": {} +} diff --git a/docs/studies/membership-observation/evidence/family-38-00/observed.refs b/docs/studies/membership-observation/evidence/family-38-00/observed.refs new file mode 100644 index 0000000..6aae6f8 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/observed.refs @@ -0,0 +1,2 @@ +refs/locks/jobs/p6899 b1eb4a8f914eec35aaa4623066c09808efe25173 +refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 b1eb4a8f914eec35aaa4623066c09808efe25173 diff --git a/docs/studies/membership-observation/evidence/family-38-00/reads.txt b/docs/studies/membership-observation/evidence/family-38-00/reads.txt new file mode 100644 index 0000000..857338b --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/reads.txt @@ -0,0 +1,3 @@ +real +injected +real diff --git a/docs/studies/membership-observation/evidence/family-38-00/result.json b/docs/studies/membership-observation/evidence/family-38-00/result.json new file mode 100644 index 0000000..e03b915 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/result.json @@ -0,0 +1,26 @@ +{ + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/family-38-00/stderr.txt b/docs/studies/membership-observation/evidence/family-38-00/stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/family-38-00/stdout.txt b/docs/studies/membership-observation/evidence/family-38-00/stdout.txt new file mode 100644 index 0000000..e7e2434 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/stdout.txt @@ -0,0 +1 @@ +{"event":"released","job":"p6899","paths":2,"cascaded":["c6899"]} diff --git a/docs/studies/membership-observation/evidence/family-38-00/transaction-1.stdin b/docs/studies/membership-observation/evidence/family-38-00/transaction-1.stdin new file mode 100644 index 0000000..bd8f60c --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/transaction-1.stdin @@ -0,0 +1,5 @@ +start +delete refs/locks/jobs/p6899 b1eb4a8f914eec35aaa4623066c09808efe25173 +delete refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 b1eb4a8f914eec35aaa4623066c09808efe25173 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/family-38-00/transaction-2.stdin b/docs/studies/membership-observation/evidence/family-38-00/transaction-2.stdin new file mode 100644 index 0000000..3049b14 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-00/transaction-2.stdin @@ -0,0 +1,7 @@ +start +delete refs/locks/jobs/p6899 57bb60ad60200db3b5958f7bcc0395eade9c098e +delete refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 57bb60ad60200db3b5958f7bcc0395eade9c098e +delete refs/locks/jobs/c6899 33b5ca2fdfe4682808a82b1e57e7925191e3faf8 +delete refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d 33b5ca2fdfe4682808a82b1e57e7925191e3faf8 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/family-38-14/before.json b/docs/studies/membership-observation/evidence/family-38-14/before.json new file mode 100644 index 0000000..5cd57c4 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "e05ff7614256b4c5260e0b742dc9776397e9be6a": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-71397-2379716744\npaths:\nparent.md\n" + }, + "refs": { + "refs/locks/jobs/p6899": "e05ff7614256b4c5260e0b742dc9776397e9be6a", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "e05ff7614256b4c5260e0b742dc9776397e9be6a" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-14/committed-after.json b/docs/studies/membership-observation/evidence/family-38-14/committed-after.json new file mode 100644 index 0000000..978aca3 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "52270478c4699b5f5b11555ff9656b55d0d44700": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 1\nacquisition: 1000000-71397-2379716744\npaths:\nparent.md\n", + "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-71520-0713314049\npaths:\nchild.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55", + "refs/locks/jobs/p6899": "52270478c4699b5f5b11555ff9656b55d0d44700", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "52270478c4699b5f5b11555ff9656b55d0d44700" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-14/final.json b/docs/studies/membership-observation/evidence/family-38-14/final.json new file mode 100644 index 0000000..b2e8100 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/final.json @@ -0,0 +1,9 @@ +{ + "objects": { + "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-71520-0713314049\npaths:\nchild.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "5cdb7fee4cc7f386861048a1aec8d9ee65db9a55" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-14/observed.refs b/docs/studies/membership-observation/evidence/family-38-14/observed.refs new file mode 100644 index 0000000..4e5db76 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/observed.refs @@ -0,0 +1,3 @@ +refs/locks/jobs/p6899 52270478c4699b5f5b11555ff9656b55d0d44700 +refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d 5cdb7fee4cc7f386861048a1aec8d9ee65db9a55 +refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 52270478c4699b5f5b11555ff9656b55d0d44700 diff --git a/docs/studies/membership-observation/evidence/family-38-14/reads.txt b/docs/studies/membership-observation/evidence/family-38-14/reads.txt new file mode 100644 index 0000000..a54495c --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/reads.txt @@ -0,0 +1,2 @@ +real +injected diff --git a/docs/studies/membership-observation/evidence/family-38-14/result.json b/docs/studies/membership-observation/evidence/family-38-14/result.json new file mode 100644 index 0000000..f85882b --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/result.json @@ -0,0 +1,31 @@ +{ + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ] +} diff --git a/docs/studies/membership-observation/evidence/family-38-14/stderr.txt b/docs/studies/membership-observation/evidence/family-38-14/stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/family-38-14/stdout.txt b/docs/studies/membership-observation/evidence/family-38-14/stdout.txt new file mode 100644 index 0000000..e435098 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/stdout.txt @@ -0,0 +1 @@ +{"event":"released","job":"p6899","paths":1} diff --git a/docs/studies/membership-observation/evidence/family-38-14/transaction-1.stdin b/docs/studies/membership-observation/evidence/family-38-14/transaction-1.stdin new file mode 100644 index 0000000..4417505 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-14/transaction-1.stdin @@ -0,0 +1,5 @@ +start +delete refs/locks/jobs/p6899 52270478c4699b5f5b11555ff9656b55d0d44700 +delete refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 52270478c4699b5f5b11555ff9656b55d0d44700 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/family-38-15/before.json b/docs/studies/membership-observation/evidence/family-38-15/before.json new file mode 100644 index 0000000..26ad1c4 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "a645845b1d4cec45b09cf5bdbb19f710e905c895": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-71777-1867300132\npaths:\nparent.md\n" + }, + "refs": { + "refs/locks/jobs/p6899": "a645845b1d4cec45b09cf5bdbb19f710e905c895", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "a645845b1d4cec45b09cf5bdbb19f710e905c895" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-15/committed-after.json b/docs/studies/membership-observation/evidence/family-38-15/committed-after.json new file mode 100644 index 0000000..ccb9e00 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "65113c9c708f0b64632762042c06323d26c1fc3c": "schema: git-locks/1\njob: p6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 1\nacquisition: 1000000-71777-1867300132\npaths:\nparent.md\n", + "de7a7b3a9a9c1d7140f26d22b6205efe50dff49d": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nparent: p6899\nfamily: 0\nacquisition: 1000000-71896-0512618343\npaths:\nchild.md\n" + }, + "refs": { + "refs/locks/jobs/c6899": "de7a7b3a9a9c1d7140f26d22b6205efe50dff49d", + "refs/locks/jobs/p6899": "65113c9c708f0b64632762042c06323d26c1fc3c", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "de7a7b3a9a9c1d7140f26d22b6205efe50dff49d", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "65113c9c708f0b64632762042c06323d26c1fc3c" + } +} diff --git a/docs/studies/membership-observation/evidence/family-38-15/final.json b/docs/studies/membership-observation/evidence/family-38-15/final.json new file mode 100644 index 0000000..2206b4a --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/final.json @@ -0,0 +1,4 @@ +{ + "objects": {}, + "refs": {} +} diff --git a/docs/studies/membership-observation/evidence/family-38-15/observed.refs b/docs/studies/membership-observation/evidence/family-38-15/observed.refs new file mode 100644 index 0000000..86aef82 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/observed.refs @@ -0,0 +1,4 @@ +refs/locks/jobs/c6899 de7a7b3a9a9c1d7140f26d22b6205efe50dff49d +refs/locks/jobs/p6899 65113c9c708f0b64632762042c06323d26c1fc3c +refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d de7a7b3a9a9c1d7140f26d22b6205efe50dff49d +refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 65113c9c708f0b64632762042c06323d26c1fc3c diff --git a/docs/studies/membership-observation/evidence/family-38-15/reads.txt b/docs/studies/membership-observation/evidence/family-38-15/reads.txt new file mode 100644 index 0000000..a54495c --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/reads.txt @@ -0,0 +1,2 @@ +real +injected diff --git a/docs/studies/membership-observation/evidence/family-38-15/result.json b/docs/studies/membership-observation/evidence/family-38-15/result.json new file mode 100644 index 0000000..afa871b --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/result.json @@ -0,0 +1,25 @@ +{ + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 15, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/family-38-15/stderr.txt b/docs/studies/membership-observation/evidence/family-38-15/stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/family-38-15/stdout.txt b/docs/studies/membership-observation/evidence/family-38-15/stdout.txt new file mode 100644 index 0000000..e7e2434 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/stdout.txt @@ -0,0 +1 @@ +{"event":"released","job":"p6899","paths":2,"cascaded":["c6899"]} diff --git a/docs/studies/membership-observation/evidence/family-38-15/transaction-1.stdin b/docs/studies/membership-observation/evidence/family-38-15/transaction-1.stdin new file mode 100644 index 0000000..514fac4 --- /dev/null +++ b/docs/studies/membership-observation/evidence/family-38-15/transaction-1.stdin @@ -0,0 +1,7 @@ +start +delete refs/locks/jobs/p6899 65113c9c708f0b64632762042c06323d26c1fc3c +delete refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9 65113c9c708f0b64632762042c06323d26c1fc3c +delete refs/locks/jobs/c6899 de7a7b3a9a9c1d7140f26d22b6205efe50dff49d +delete refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d de7a7b3a9a9c1d7140f26d22b6205efe50dff49d +prepare +commit diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/before.json b/docs/studies/membership-observation/evidence/prefix-38-00/before.json new file mode 100644 index 0000000..2897ba0 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "f26eabdbfb5f07231fa54faf7bcce57219e012bc": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-73878-1530626313\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/jobs/unrelated": "f26eabdbfb5f07231fa54faf7bcce57219e012bc", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "f26eabdbfb5f07231fa54faf7bcce57219e012bc" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/committed-after.json b/docs/studies/membership-observation/evidence/prefix-38-00/committed-after.json new file mode 100644 index 0000000..f55173f --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/committed-after.json @@ -0,0 +1,13 @@ +{ + "objects": { + "1809565c881e3b66533366301b017c8cb2fa20c1": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-73999-2163401652\npaths:\nd6899/child.md\n", + "f26eabdbfb5f07231fa54faf7bcce57219e012bc": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-73878-1530626313\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "1809565c881e3b66533366301b017c8cb2fa20c1", + "refs/locks/jobs/c6899": "1809565c881e3b66533366301b017c8cb2fa20c1", + "refs/locks/jobs/unrelated": "f26eabdbfb5f07231fa54faf7bcce57219e012bc", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "f26eabdbfb5f07231fa54faf7bcce57219e012bc", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "1809565c881e3b66533366301b017c8cb2fa20c1" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/final.json b/docs/studies/membership-observation/evidence/prefix-38-00/final.json new file mode 100644 index 0000000..f55173f --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/final.json @@ -0,0 +1,13 @@ +{ + "objects": { + "1809565c881e3b66533366301b017c8cb2fa20c1": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-73999-2163401652\npaths:\nd6899/child.md\n", + "f26eabdbfb5f07231fa54faf7bcce57219e012bc": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-73878-1530626313\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "1809565c881e3b66533366301b017c8cb2fa20c1", + "refs/locks/jobs/c6899": "1809565c881e3b66533366301b017c8cb2fa20c1", + "refs/locks/jobs/unrelated": "f26eabdbfb5f07231fa54faf7bcce57219e012bc", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "f26eabdbfb5f07231fa54faf7bcce57219e012bc", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "1809565c881e3b66533366301b017c8cb2fa20c1" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/observed.refs b/docs/studies/membership-observation/evidence/prefix-38-00/observed.refs new file mode 100644 index 0000000..37972fd --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/observed.refs @@ -0,0 +1,2 @@ +refs/locks/jobs/unrelated f26eabdbfb5f07231fa54faf7bcce57219e012bc +refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404 f26eabdbfb5f07231fa54faf7bcce57219e012bc diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/reads.txt b/docs/studies/membership-observation/evidence/prefix-38-00/reads.txt new file mode 100644 index 0000000..b5cf4e2 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/reads.txt @@ -0,0 +1,2 @@ +injected +real diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/result.json b/docs/studies/membership-observation/evidence/prefix-38-00/result.json new file mode 100644 index 0000000..71df241 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/result.json @@ -0,0 +1,27 @@ +{ + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "before", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/stderr.txt b/docs/studies/membership-observation/evidence/prefix-38-00/stderr.txt new file mode 100644 index 0000000..eda7607 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/stderr.txt @@ -0,0 +1 @@ +{"event":"refused","path":"d6899/","holder":"alice","job":"c6899","via":"d6899/child.md","expires":1014400} diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/stdout.txt b/docs/studies/membership-observation/evidence/prefix-38-00/stdout.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/prefix-38-00/transaction-1.stdin b/docs/studies/membership-observation/evidence/prefix-38-00/transaction-1.stdin new file mode 100644 index 0000000..a60182c --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-00/transaction-1.stdin @@ -0,0 +1,6 @@ +start +create refs/locks/paths/1b83db463a41a8a9c0046855447e179df6c7d72a 1032ea70340a9c6adc39c38d07bd7090c65ffd29 +create refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a 1032ea70340a9c6adc39c38d07bd7090c65ffd29 +create refs/locks/jobs/z6899 1032ea70340a9c6adc39c38d07bd7090c65ffd29 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/before.json b/docs/studies/membership-observation/evidence/prefix-38-01/before.json new file mode 100644 index 0000000..401b94e --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "21a54be03b2af9d2d8de086f84c2533647e267b2": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74307-1493129927\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/jobs/unrelated": "21a54be03b2af9d2d8de086f84c2533647e267b2", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "21a54be03b2af9d2d8de086f84c2533647e267b2" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/committed-after.json b/docs/studies/membership-observation/evidence/prefix-38-01/committed-after.json new file mode 100644 index 0000000..867f725 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/committed-after.json @@ -0,0 +1,13 @@ +{ + "objects": { + "21a54be03b2af9d2d8de086f84c2533647e267b2": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74307-1493129927\npaths:\noutside.md\n", + "34adf68632870555edfd7ded63e49edc9f58648b": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74433-0609617567\npaths:\nd6899/child.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "34adf68632870555edfd7ded63e49edc9f58648b", + "refs/locks/jobs/c6899": "34adf68632870555edfd7ded63e49edc9f58648b", + "refs/locks/jobs/unrelated": "21a54be03b2af9d2d8de086f84c2533647e267b2", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "21a54be03b2af9d2d8de086f84c2533647e267b2", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "34adf68632870555edfd7ded63e49edc9f58648b" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/final.json b/docs/studies/membership-observation/evidence/prefix-38-01/final.json new file mode 100644 index 0000000..6f8f2d7 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/final.json @@ -0,0 +1,16 @@ +{ + "objects": { + "21a54be03b2af9d2d8de086f84c2533647e267b2": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74307-1493129927\npaths:\noutside.md\n", + "34adf68632870555edfd7ded63e49edc9f58648b": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74433-0609617567\npaths:\nd6899/child.md\n", + "9ec88e08651bdd5989a4a95eaa5c77f90e2716bf": "schema: git-locks/1\njob: z6899\nholder: bob\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-74546-1136417607\npaths:\nd6899/\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "9ec88e08651bdd5989a4a95eaa5c77f90e2716bf", + "refs/locks/jobs/c6899": "34adf68632870555edfd7ded63e49edc9f58648b", + "refs/locks/jobs/unrelated": "21a54be03b2af9d2d8de086f84c2533647e267b2", + "refs/locks/jobs/z6899": "9ec88e08651bdd5989a4a95eaa5c77f90e2716bf", + "refs/locks/paths/1b83db463a41a8a9c0046855447e179df6c7d72a": "9ec88e08651bdd5989a4a95eaa5c77f90e2716bf", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "21a54be03b2af9d2d8de086f84c2533647e267b2", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "34adf68632870555edfd7ded63e49edc9f58648b" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/observed.refs b/docs/studies/membership-observation/evidence/prefix-38-01/observed.refs new file mode 100644 index 0000000..ffda42c --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/observed.refs @@ -0,0 +1,3 @@ +refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a 34adf68632870555edfd7ded63e49edc9f58648b +refs/locks/jobs/unrelated 21a54be03b2af9d2d8de086f84c2533647e267b2 +refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404 21a54be03b2af9d2d8de086f84c2533647e267b2 diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/reads.txt b/docs/studies/membership-observation/evidence/prefix-38-01/reads.txt new file mode 100644 index 0000000..a7557cd --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/reads.txt @@ -0,0 +1 @@ +injected diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/result.json b/docs/studies/membership-observation/evidence/prefix-38-01/result.json new file mode 100644 index 0000000..3d87984 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/result.json @@ -0,0 +1,38 @@ +{ + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c6899", + "z6899" + ], + "paths": [ + "d6899/child.md", + "d6899/" + ] + } + ] +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/stderr.txt b/docs/studies/membership-observation/evidence/prefix-38-01/stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/stdout.txt b/docs/studies/membership-observation/evidence/prefix-38-01/stdout.txt new file mode 100644 index 0000000..3ed99a7 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/stdout.txt @@ -0,0 +1 @@ +{"event":"claimed","job":"z6899","holder":"bob","claimed":1000000,"expires":1014400,"paths":["d6899/"],"record":"9ec88e08651bdd5989a4a95eaa5c77f90e2716bf","acquisition":"1000000-74546-1136417607"} diff --git a/docs/studies/membership-observation/evidence/prefix-38-01/transaction-1.stdin b/docs/studies/membership-observation/evidence/prefix-38-01/transaction-1.stdin new file mode 100644 index 0000000..befa14b --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-01/transaction-1.stdin @@ -0,0 +1,6 @@ +start +create refs/locks/paths/1b83db463a41a8a9c0046855447e179df6c7d72a 9ec88e08651bdd5989a4a95eaa5c77f90e2716bf +update refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a 9ec88e08651bdd5989a4a95eaa5c77f90e2716bf 34adf68632870555edfd7ded63e49edc9f58648b +create refs/locks/jobs/z6899 9ec88e08651bdd5989a4a95eaa5c77f90e2716bf +prepare +commit diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/before.json b/docs/studies/membership-observation/evidence/prefix-38-07/before.json new file mode 100644 index 0000000..b8c5a53 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/before.json @@ -0,0 +1,9 @@ +{ + "objects": { + "52fdad7b7d925c453626e3687d144de4b0768bde": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-76653-2429500104\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/jobs/unrelated": "52fdad7b7d925c453626e3687d144de4b0768bde", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "52fdad7b7d925c453626e3687d144de4b0768bde" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/committed-after.json b/docs/studies/membership-observation/evidence/prefix-38-07/committed-after.json new file mode 100644 index 0000000..c347b31 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/committed-after.json @@ -0,0 +1,13 @@ +{ + "objects": { + "35002b9a00455d899ea92c58652f132f9eaffc2f": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-76794-2913024483\npaths:\nd6899/child.md\n", + "52fdad7b7d925c453626e3687d144de4b0768bde": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-76653-2429500104\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "35002b9a00455d899ea92c58652f132f9eaffc2f", + "refs/locks/jobs/c6899": "35002b9a00455d899ea92c58652f132f9eaffc2f", + "refs/locks/jobs/unrelated": "52fdad7b7d925c453626e3687d144de4b0768bde", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "52fdad7b7d925c453626e3687d144de4b0768bde", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "35002b9a00455d899ea92c58652f132f9eaffc2f" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/final.json b/docs/studies/membership-observation/evidence/prefix-38-07/final.json new file mode 100644 index 0000000..c347b31 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/final.json @@ -0,0 +1,13 @@ +{ + "objects": { + "35002b9a00455d899ea92c58652f132f9eaffc2f": "schema: git-locks/1\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-76794-2913024483\npaths:\nd6899/child.md\n", + "52fdad7b7d925c453626e3687d144de4b0768bde": "schema: git-locks/1\njob: unrelated\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nfamily: 0\nacquisition: 1000000-76653-2429500104\npaths:\noutside.md\n" + }, + "refs": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "35002b9a00455d899ea92c58652f132f9eaffc2f", + "refs/locks/jobs/c6899": "35002b9a00455d899ea92c58652f132f9eaffc2f", + "refs/locks/jobs/unrelated": "52fdad7b7d925c453626e3687d144de4b0768bde", + "refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404": "52fdad7b7d925c453626e3687d144de4b0768bde", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "35002b9a00455d899ea92c58652f132f9eaffc2f" + } +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/observed.refs b/docs/studies/membership-observation/evidence/prefix-38-07/observed.refs new file mode 100644 index 0000000..49cc4c7 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/observed.refs @@ -0,0 +1,5 @@ +refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a 35002b9a00455d899ea92c58652f132f9eaffc2f +refs/locks/jobs/c6899 35002b9a00455d899ea92c58652f132f9eaffc2f +refs/locks/jobs/unrelated 52fdad7b7d925c453626e3687d144de4b0768bde +refs/locks/paths/47d6eb1ca50557ab8a92e6ba51b93c86a74ee404 52fdad7b7d925c453626e3687d144de4b0768bde +refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee 35002b9a00455d899ea92c58652f132f9eaffc2f diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/reads.txt b/docs/studies/membership-observation/evidence/prefix-38-07/reads.txt new file mode 100644 index 0000000..a7557cd --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/reads.txt @@ -0,0 +1 @@ +injected diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/result.json b/docs/studies/membership-observation/evidence/prefix-38-07/result.json new file mode 100644 index 0000000..f3d0dbf --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/result.json @@ -0,0 +1,26 @@ +{ + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "after", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "after" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/stderr.txt b/docs/studies/membership-observation/evidence/prefix-38-07/stderr.txt new file mode 100644 index 0000000..eda7607 --- /dev/null +++ b/docs/studies/membership-observation/evidence/prefix-38-07/stderr.txt @@ -0,0 +1 @@ +{"event":"refused","path":"d6899/","holder":"alice","job":"c6899","via":"d6899/child.md","expires":1014400} diff --git a/docs/studies/membership-observation/evidence/prefix-38-07/stdout.txt b/docs/studies/membership-observation/evidence/prefix-38-07/stdout.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/provenance.json b/docs/studies/membership-observation/evidence/provenance.json new file mode 100644 index 0000000..1904afa --- /dev/null +++ b/docs/studies/membership-observation/evidence/provenance.json @@ -0,0 +1,8 @@ +{ + "bash": "GNU bash, version 5.3.9(1)-release (aarch64-apple-darwin24.6.0)", + "binary_sha256": "fc686ce320cdebba1420f2bb6e7d56f2cd79c1e40ecdd7b31178a9d2cf27aae3", + "fixture_sha256": "c27436023ac521ef47ce3a5154b434b425ef088038cc04a2ef58d2b0cebb7941", + "git": "git version 2.54.0 (Apple Git-157)", + "python": "3.14.6 (main, Jun 10 2026, 10:03:53) [Clang 21.0.0 (clang-2100.0.123.102)]", + "shim_sha256": "99aebd2f43376bfe9d1020b0b598913e1a899296fdb1a201aceb16d677542262" +} diff --git a/docs/studies/membership-observation/evidence/report.json b/docs/studies/membership-observation/evidence/report.json new file mode 100644 index 0000000..f07689a --- /dev/null +++ b/docs/studies/membership-observation/evidence/report.json @@ -0,0 +1,2452 @@ +{ + "calibration": [ + { + "deliberately_bad_violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ], + "domain": "family", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "deliberately_bad_violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ], + "domain": "semaphore", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "deliberately_bad_violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c6899", + "covering" + ], + "paths": [ + "d6899/child.md", + "d6899/" + ] + } + ], + "domain": "prefix", + "healthy_violations": [], + "kind": "hand-constructed-oracle-input" + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 1, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 0, + "violations": [] + } + ], + "cases": 84, + "live_git_race_reproduced": false, + "observation": "synthetic-per-ref-before-after", + "production_safety": "FAIL", + "results": [ + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 8, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 9, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 10, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 11, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 12, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 13, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c6899": "before", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c6899", + "parent": "p6899" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c6899": "after", + "refs/locks/jobs/p6899": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p6899" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 15, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c6899": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "before", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c6899", + "z6899" + ], + "paths": [ + "d6899/child.md", + "d6899/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "before", + "refs/locks/jobs/c6899": "after", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "after", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "before" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "before", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "after" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "before", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "after" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c6899", + "z6899" + ], + "paths": [ + "d6899/child.md", + "d6899/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "before", + "refs/locks/jobs/c6899": "after", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "after" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/1b83db463a41a8a9c0046855447e179df6c7d72a": "after", + "refs/locks/jobs/c6899": "after", + "refs/locks/paths/593d8373f5ee9200667683d1fef95ccdd9a8d7ee": "after" + }, + "command": [ + "claim", + "--job", + "z6899", + "--holder", + "bob", + "d6899/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c8059", + "parent": "p8059" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c8059", + "parent": "p8059" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 8, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 9, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 10, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c8059", + "parent": "p8059" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 11, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 12, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 13, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c8059": "before", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c8059", + "parent": "p8059" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c8059": "after", + "refs/locks/jobs/p8059": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p8059" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 15, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c8059": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z8059", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c8059": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z8059", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c8059": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z8059", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c8059": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z8059", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "before", + "refs/locks/jobs/c8059": "before", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "before" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "after", + "refs/locks/jobs/c8059": "before", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "before" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c8059", + "z8059" + ], + "paths": [ + "d8059/child.md", + "d8059/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "before", + "refs/locks/jobs/c8059": "after", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "before" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "after", + "refs/locks/jobs/c8059": "after", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "before" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "before", + "refs/locks/jobs/c8059": "before", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "after" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 1701, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "after", + "refs/locks/jobs/c8059": "before", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "after" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c8059", + "z8059" + ], + "paths": [ + "d8059/child.md", + "d8059/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "before", + "refs/locks/jobs/c8059": "after", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "after" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/bbf6905444361e0cfe529abfb01a9ad467af336f": "after", + "refs/locks/jobs/c8059": "after", + "refs/locks/paths/4c35ac718d55331e9b0eef30b25a559526495bf6": "after" + }, + "command": [ + "claim", + "--job", + "z8059", + "--holder", + "bob", + "d8059/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 1701, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c5916", + "parent": "p5916" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c5916", + "parent": "p5916" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "before" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 8, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 9, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 10, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c5916", + "parent": "p5916" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "before", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 11, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 12, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "before", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 13, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 2, + "violations": [] + }, + { + "changed": { + "refs/locks/jobs/c5916": "before", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 14, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "family-parent", + "job": "c5916", + "parent": "p5916" + } + ] + }, + { + "changed": { + "refs/locks/jobs/c5916": "after", + "refs/locks/jobs/p5916": "after", + "refs/locks/paths/a5ebebe3ae94634c6b2d92cd7780568808528f9d": "after", + "refs/locks/paths/cced43569853e52bd80802cb39d057c3f9e9c9e9": "after" + }, + "command": [ + "release", + "--job", + "p5916" + ], + "domain": "family", + "exit": 0, + "injected_read": 2, + "mask": 15, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c5916": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z5916", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c5916": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z5916", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c5916": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z5916", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c5916": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z5916", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "before", + "refs/locks/jobs/c5916": "before", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "before" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "after", + "refs/locks/jobs/c5916": "before", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "before" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c5916", + "z5916" + ], + "paths": [ + "d5916/child.md", + "d5916/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "before", + "refs/locks/jobs/c5916": "after", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "before" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 2, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "after", + "refs/locks/jobs/c5916": "after", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "before" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "before", + "refs/locks/jobs/c5916": "before", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "after" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 4, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected", + "real" + ], + "seed": 20260922, + "transactions": 1, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "after", + "refs/locks/jobs/c5916": "before", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "after" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 0, + "injected_read": 1, + "mask": 5, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 1, + "violations": [ + { + "invariant": "prefix-exclusivity", + "jobs": [ + "c5916", + "z5916" + ], + "paths": [ + "d5916/child.md", + "d5916/" + ] + } + ] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "before", + "refs/locks/jobs/c5916": "after", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "after" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 6, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + }, + { + "changed": { + "refs/locks/dirs/3a7f82e712dd0fa159a0d93d34e95ff5861a5b33": "after", + "refs/locks/jobs/c5916": "after", + "refs/locks/paths/82882b5602629d6aee3563746af423c8ec6350da": "after" + }, + "command": [ + "claim", + "--job", + "z5916", + "--holder", + "bob", + "d5916/" + ], + "domain": "prefix", + "exit": 1, + "injected_read": 1, + "mask": 7, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "injected" + ], + "seed": 20260922, + "transactions": 0, + "violations": [] + } + ], + "violating_cases": 21 +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/before.json b/docs/studies/membership-observation/evidence/semaphore-38-00/before.json new file mode 100644 index 0000000..086ba34 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/before.json @@ -0,0 +1,10 @@ +{ + "objects": { + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n", + "e21befc7e607d7482c89318423771d9f07543bb4": "generation 1000000 72171 369811056\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "e21befc7e607d7482c89318423771d9f07543bb4", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/committed-after.json b/docs/studies/membership-observation/evidence/semaphore-38-00/committed-after.json new file mode 100644 index 0000000..073428b --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "c17481df65ade87fa801c7ab3eeba865037a5589": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-72305-0869712983\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n", + "dcd43b0cab59681f39b173e0c006f2b8d4ad09a9": "generation 1000000 72305 325615531\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "dcd43b0cab59681f39b173e0c006f2b8d4ad09a9", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "c17481df65ade87fa801c7ab3eeba865037a5589" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/final.json b/docs/studies/membership-observation/evidence/semaphore-38-00/final.json new file mode 100644 index 0000000..073428b --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/final.json @@ -0,0 +1,12 @@ +{ + "objects": { + "c17481df65ade87fa801c7ab3eeba865037a5589": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-72305-0869712983\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n", + "dcd43b0cab59681f39b173e0c006f2b8d4ad09a9": "generation 1000000 72305 325615531\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "dcd43b0cab59681f39b173e0c006f2b8d4ad09a9", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "c17481df65ade87fa801c7ab3eeba865037a5589" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/observed.refs b/docs/studies/membership-observation/evidence/semaphore-38-00/observed.refs new file mode 100644 index 0000000..b7508ba --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/observed.refs @@ -0,0 +1,2 @@ +refs/locks/sem/gpu/gen e21befc7e607d7482c89318423771d9f07543bb4 +refs/locks/sem/gpu/meta cdf44de3eba0e9ea943f0378c493f82ea467da90 diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/reads.txt b/docs/studies/membership-observation/evidence/semaphore-38-00/reads.txt new file mode 100644 index 0000000..857338b --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/reads.txt @@ -0,0 +1,3 @@ +real +injected +real diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/result.json b/docs/studies/membership-observation/evidence/semaphore-38-00/result.json new file mode 100644 index 0000000..a7bae4a --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/result.json @@ -0,0 +1,28 @@ +{ + "changed": { + "refs/locks/sem/gpu/gen": "before", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 0, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected", + "real" + ], + "seed": 38, + "transactions": 1, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/stderr.txt b/docs/studies/membership-observation/evidence/semaphore-38-00/stderr.txt new file mode 100644 index 0000000..744e0ff --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/stderr.txt @@ -0,0 +1 @@ +{"event":"refused","reason":"capacity","semaphore":"gpu","capacity":1,"live":1} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/stdout.txt b/docs/studies/membership-observation/evidence/semaphore-38-00/stdout.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/semaphore-38-00/transaction-1.stdin b/docs/studies/membership-observation/evidence/semaphore-38-00/transaction-1.stdin new file mode 100644 index 0000000..109dea7 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-00/transaction-1.stdin @@ -0,0 +1,6 @@ +start +create refs/locks/sem/gpu/slots/z6899 420f7379496b3516c6d2ad2e22e2d98f5be8b894 +update refs/locks/sem/gpu/gen 25c5ce89fc7c982ae485efaa23061307f1ad9b0f e21befc7e607d7482c89318423771d9f07543bb4 +verify refs/locks/sem/gpu/meta cdf44de3eba0e9ea943f0378c493f82ea467da90 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/before.json b/docs/studies/membership-observation/evidence/semaphore-38-01/before.json new file mode 100644 index 0000000..ad0fbbe --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/before.json @@ -0,0 +1,10 @@ +{ + "objects": { + "64e168e3a917fd6c832ed36a25d72adaecea30c4": "generation 1000000 72696 156482452\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "64e168e3a917fd6c832ed36a25d72adaecea30c4", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/committed-after.json b/docs/studies/membership-observation/evidence/semaphore-38-01/committed-after.json new file mode 100644 index 0000000..64f3f0f --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "21fdd4c4aadbbe74f49a80b53f6e64911d168c49": "generation 1000000 72823 2147613061\n", + "38c33b278378aa090161dcea8eb178ee0140d8e4": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-72823-1648515807\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "21fdd4c4aadbbe74f49a80b53f6e64911d168c49", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "38c33b278378aa090161dcea8eb178ee0140d8e4" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/final.json b/docs/studies/membership-observation/evidence/semaphore-38-01/final.json new file mode 100644 index 0000000..4554029 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/final.json @@ -0,0 +1,14 @@ +{ + "objects": { + "1eee8997e1fb251d9aee0c1557dffe2aaa3c3705": "schema: git-locks-slot/1\nsemaphore: gpu\njob: z6899\nholder: bob\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-72967-0367710226\n", + "38c33b278378aa090161dcea8eb178ee0140d8e4": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-72823-1648515807\n", + "be7ac99121ca98ca0f937528f93341b79fe0d3e6": "generation 1000000 72967 3188820537\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "be7ac99121ca98ca0f937528f93341b79fe0d3e6", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "38c33b278378aa090161dcea8eb178ee0140d8e4", + "refs/locks/sem/gpu/slots/z6899": "1eee8997e1fb251d9aee0c1557dffe2aaa3c3705" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/observed.refs b/docs/studies/membership-observation/evidence/semaphore-38-01/observed.refs new file mode 100644 index 0000000..1c3cc80 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/observed.refs @@ -0,0 +1,2 @@ +refs/locks/sem/gpu/gen 21fdd4c4aadbbe74f49a80b53f6e64911d168c49 +refs/locks/sem/gpu/meta cdf44de3eba0e9ea943f0378c493f82ea467da90 diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/reads.txt b/docs/studies/membership-observation/evidence/semaphore-38-01/reads.txt new file mode 100644 index 0000000..a54495c --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/reads.txt @@ -0,0 +1,2 @@ +real +injected diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/result.json b/docs/studies/membership-observation/evidence/semaphore-38-01/result.json new file mode 100644 index 0000000..94cd5be --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/result.json @@ -0,0 +1,34 @@ +{ + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "before" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 0, + "injected_read": 2, + "mask": 1, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 1, + "violations": [ + { + "capacity": 1, + "invariant": "semaphore-capacity", + "live": 2, + "semaphore": "gpu" + } + ] +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/stderr.txt b/docs/studies/membership-observation/evidence/semaphore-38-01/stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/stdout.txt b/docs/studies/membership-observation/evidence/semaphore-38-01/stdout.txt new file mode 100644 index 0000000..3f3bbb3 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/stdout.txt @@ -0,0 +1 @@ +{"event":"acquired","semaphore":"gpu","job":"z6899","holder":"bob","claimed":1000000,"expires":1014400,"live":1,"capacity":1,"record":"1eee8997e1fb251d9aee0c1557dffe2aaa3c3705","acquisition":"1000000-72967-0367710226"} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-01/transaction-1.stdin b/docs/studies/membership-observation/evidence/semaphore-38-01/transaction-1.stdin new file mode 100644 index 0000000..577628f --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-01/transaction-1.stdin @@ -0,0 +1,6 @@ +start +create refs/locks/sem/gpu/slots/z6899 1eee8997e1fb251d9aee0c1557dffe2aaa3c3705 +update refs/locks/sem/gpu/gen be7ac99121ca98ca0f937528f93341b79fe0d3e6 21fdd4c4aadbbe74f49a80b53f6e64911d168c49 +verify refs/locks/sem/gpu/meta cdf44de3eba0e9ea943f0378c493f82ea467da90 +prepare +commit diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/before.json b/docs/studies/membership-observation/evidence/semaphore-38-03/before.json new file mode 100644 index 0000000..1a6dd4c --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/before.json @@ -0,0 +1,10 @@ +{ + "objects": { + "70dcc0aa3669c035ba93ca2c3a57e358b6bcdcc9": "generation 1000000 73510 492926171\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "70dcc0aa3669c035ba93ca2c3a57e358b6bcdcc9", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/committed-after.json b/docs/studies/membership-observation/evidence/semaphore-38-03/committed-after.json new file mode 100644 index 0000000..6849b88 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/committed-after.json @@ -0,0 +1,12 @@ +{ + "objects": { + "7d7fc717f7a2339d1f62c228233e92542f997b0f": "generation 1000000 73631 488010567\n", + "9eb16c570beb298bdd6fa85bceb4b436ec491344": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-73631-1829015018\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "7d7fc717f7a2339d1f62c228233e92542f997b0f", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "9eb16c570beb298bdd6fa85bceb4b436ec491344" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/final.json b/docs/studies/membership-observation/evidence/semaphore-38-03/final.json new file mode 100644 index 0000000..6849b88 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/final.json @@ -0,0 +1,12 @@ +{ + "objects": { + "7d7fc717f7a2339d1f62c228233e92542f997b0f": "generation 1000000 73631 488010567\n", + "9eb16c570beb298bdd6fa85bceb4b436ec491344": "schema: git-locks-slot/1\nsemaphore: gpu\njob: c6899\nholder: alice\nclaimed: 1000000\nexpires: 1014400\nacquisition: 1000000-73631-1829015018\n", + "cdf44de3eba0e9ea943f0378c493f82ea467da90": "schema: git-locks-sem/1\nsemaphore: gpu\ncapacity: 1\ncreated: 1000000\n" + }, + "refs": { + "refs/locks/sem/gpu/gen": "7d7fc717f7a2339d1f62c228233e92542f997b0f", + "refs/locks/sem/gpu/meta": "cdf44de3eba0e9ea943f0378c493f82ea467da90", + "refs/locks/sem/gpu/slots/c6899": "9eb16c570beb298bdd6fa85bceb4b436ec491344" + } +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/observed.refs b/docs/studies/membership-observation/evidence/semaphore-38-03/observed.refs new file mode 100644 index 0000000..bb429b1 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/observed.refs @@ -0,0 +1,3 @@ +refs/locks/sem/gpu/gen 7d7fc717f7a2339d1f62c228233e92542f997b0f +refs/locks/sem/gpu/meta cdf44de3eba0e9ea943f0378c493f82ea467da90 +refs/locks/sem/gpu/slots/c6899 9eb16c570beb298bdd6fa85bceb4b436ec491344 diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/reads.txt b/docs/studies/membership-observation/evidence/semaphore-38-03/reads.txt new file mode 100644 index 0000000..a54495c --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/reads.txt @@ -0,0 +1,2 @@ +real +injected diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/result.json b/docs/studies/membership-observation/evidence/semaphore-38-03/result.json new file mode 100644 index 0000000..0de7f95 --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/result.json @@ -0,0 +1,27 @@ +{ + "changed": { + "refs/locks/sem/gpu/gen": "after", + "refs/locks/sem/gpu/slots/c6899": "after" + }, + "command": [ + "sem", + "acquire", + "gpu", + "--job", + "z6899", + "--holder", + "bob" + ], + "domain": "semaphore", + "exit": 1, + "injected_read": 2, + "mask": 3, + "observation": "synthetic-per-ref-before-after", + "reads": [ + "real", + "injected" + ], + "seed": 38, + "transactions": 0, + "violations": [] +} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/stderr.txt b/docs/studies/membership-observation/evidence/semaphore-38-03/stderr.txt new file mode 100644 index 0000000..744e0ff --- /dev/null +++ b/docs/studies/membership-observation/evidence/semaphore-38-03/stderr.txt @@ -0,0 +1 @@ +{"event":"refused","reason":"capacity","semaphore":"gpu","capacity":1,"live":1} diff --git a/docs/studies/membership-observation/evidence/semaphore-38-03/stdout.txt b/docs/studies/membership-observation/evidence/semaphore-38-03/stdout.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/studies/membership-observation/evidence/sha256.json b/docs/studies/membership-observation/evidence/sha256.json new file mode 100644 index 0000000..8a0d348 --- /dev/null +++ b/docs/studies/membership-observation/evidence/sha256.json @@ -0,0 +1,91 @@ +{ + "calibration-family/deliberately-bad.json": "57118360c68aed705b8165355b4ef94f3b7238aa7cc5cbd2dfa134869313965f", + "calibration-family/healthy.json": "7e29bbc618b17be2fc50266605c5c4a8ae4dc08f205f62cd2e09c4e2ffac403e", + "calibration-prefix/deliberately-bad.json": "466e3bdab44973cec6926cec1fe214d025da7432cdecce22ae5077bbfaf44ec8", + "calibration-prefix/healthy.json": "f04ca99993c5de70e7403fcc3cc2c4e9cdae1e4e883d3a8d24109dc6fd366e6e", + "calibration-semaphore/deliberately-bad.json": "7af28772c4c1e912e8ca8cf299e8ac7f33a10712fda98661be132575d827cb95", + "calibration-semaphore/healthy.json": "c47d665da71467379d614bf79cac10e1d332eacaa8d895f1af02537ae3ad8369", + "calibration.json": "4d993cb47c625f2ade2230a2da9c3798be3a326b3d2a47e9705a1b86f1db21be", + "family-38-00/before.json": "8b7983e314b035e5e9d745862f691a8143591180590ff392f6bdd51c693e5c14", + "family-38-00/committed-after.json": "9aad27a3d4c6fa99585e571e96df9c310b29ea376bbe07a06436f38643c49c2e", + "family-38-00/final.json": "cebd78bb35e0cfe9358c61f8c5977c770dd55e368bb26b10823012825997e405", + "family-38-00/observed.refs": "028f294e240c60b3fdd3c98494264bacdb08440cc73dcfd1b66a8e9a2f47b984", + "family-38-00/reads.txt": "53d5df6f6feaf260c58b910e1a8318f72467e1466d60ec5bdd33877972bfb3bc", + "family-38-00/result.json": "7459b263b5db6801c8c28423f8cf891e577b478828db2277530af8797da02375", + "family-38-00/stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "family-38-00/stdout.txt": "5a76fb9be6f4492e5fc63c8979832c5e8e0b758d73bbf8b0ee64852e22ce33bf", + "family-38-00/transaction-1.stdin": "6e03f6685cea9311b6c3f7b7b483d67160f8d647552aa7de5efc8772413bb5e8", + "family-38-00/transaction-2.stdin": "3d92841b718066b6bbc021737ff2b62d4c99ca6e4491991fd270790cd7d26bda", + "family-38-14/before.json": "ab62955f71ab8a8394e640578fb643ece219afacf057fff54bc59ebb80ca3f22", + "family-38-14/committed-after.json": "b26565cf1f935d80cd973c5488a833594633f2fe9da86b392b9d1377147bec5e", + "family-38-14/final.json": "a70a11416bd019091c00100fa2b94c65198770da48b8467ccb36a47a0a886711", + "family-38-14/observed.refs": "d20164525dcfea3b69577bb043799990516a6802aa8a648be864a9ca1d97e3ba", + "family-38-14/reads.txt": "950cd8ee7623088546f203c46aac35535d78d2e935467ef701019c52eccbf08b", + "family-38-14/result.json": "b0950cbd07c5625d2a83c4acc832fc6ed52e78ab9f0efd26556f28394300047b", + "family-38-14/stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "family-38-14/stdout.txt": "d8be0041002c7f795b3668a724fd6f2853fac15c7b161dd4a765bb8b302dcdfa", + "family-38-14/transaction-1.stdin": "1d57d9c22ca27c8fd316f5bca1b7bbb992fa5e4f23d9461a0a2e633ede34e122", + "family-38-15/before.json": "10f5dfa970c2e48a38fd5c6de63cdf36d1f953c5925a24465621246f31a7740a", + "family-38-15/committed-after.json": "1a9c76a2c241e44c0c58f00520113c0698c8a5d582112c9f671ecbecebb14dd2", + "family-38-15/final.json": "cebd78bb35e0cfe9358c61f8c5977c770dd55e368bb26b10823012825997e405", + "family-38-15/observed.refs": "ac52eb460e4de0e8388370f84214dd4e5c18f81c79417b7014e3b69e0e6fc0af", + "family-38-15/reads.txt": "950cd8ee7623088546f203c46aac35535d78d2e935467ef701019c52eccbf08b", + "family-38-15/result.json": "20f67b8fce2126e9a9e6136a91f5f6ee2defe32a3628cf1eba9a57aa6755a08e", + "family-38-15/stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "family-38-15/stdout.txt": "5a76fb9be6f4492e5fc63c8979832c5e8e0b758d73bbf8b0ee64852e22ce33bf", + "family-38-15/transaction-1.stdin": "d1fd8daee76a6b49412eb4f7b924cc672ed2550f66af449d35d3e9b5d9334a53", + "prefix-38-00/before.json": "585bbd114c68c27c0c9734f85de0c9d3bd96162fb47fee1f976397a2bae61e6b", + "prefix-38-00/committed-after.json": "f42b9a79567911de6d8f2a113a2fae17c3aa5180b9facee808cb7281f3e12376", + "prefix-38-00/final.json": "f42b9a79567911de6d8f2a113a2fae17c3aa5180b9facee808cb7281f3e12376", + "prefix-38-00/observed.refs": "13c74fa8527d90f153763723070fdeb43796cd0d2b1377152559e47fe7b4d2af", + "prefix-38-00/reads.txt": "8fb530f0def1447ee9746cc4172e043154a7078f028a2baf1acd7c981762e70b", + "prefix-38-00/result.json": "f4131863593f449f8d6a3cc255ffa627750ce839ebcde8f92d87b729540bd152", + "prefix-38-00/stderr.txt": "8b43e3415ffcc0209002ea54371038ace587ae3e83d20a0546897d9ce27442ef", + "prefix-38-00/stdout.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "prefix-38-00/transaction-1.stdin": "49f1aad0290bddab796215fc9deb1bfa02f77853b76aeb477ddb2dfd5530ef2c", + "prefix-38-01/before.json": "0ede1196d0a4d64dfc4f45cb86fd806b313e57bd532d9618e7c82d9f83634365", + "prefix-38-01/committed-after.json": "47a9d2335a87f55f8c229252a0b8a8ee6811ed2269991d8b35545a9a6e05b98f", + "prefix-38-01/final.json": "54a8e32f98d8c763abf7c3fa66dfe9935bf971cdac608a863617bfb6190db6e1", + "prefix-38-01/observed.refs": "9e44839107f0bfb14f7d2f0de9dc26387251dc7c8975fbe77aac0f542839cde9", + "prefix-38-01/reads.txt": "ca14a1137a0cec7f58cd4b6f319917367b61a6a7e1f5efc714e1f54cb16c4b90", + "prefix-38-01/result.json": "6b151eaa56c3f3159efaa5c1460e268265d2fdb0fda23c3c0e65ff41ebe83d90", + "prefix-38-01/stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "prefix-38-01/stdout.txt": "0e2df41990e0cda41abd48be1d27c1a68162707866e299ad93c81002c913a31a", + "prefix-38-01/transaction-1.stdin": "72d95c1ea0d3eff4e1d17089a1b93f68949a4379fc30abfe5e8fc3a93b133ae5", + "prefix-38-07/before.json": "2b12ec8e9d76fed385bd7b603ad36ae8af7df1b6531b3304cd95a4f879703719", + "prefix-38-07/committed-after.json": "59200c82dcd2b36abb04c7aae2dce1b27996049010950dad96c5960ff08347a5", + "prefix-38-07/final.json": "59200c82dcd2b36abb04c7aae2dce1b27996049010950dad96c5960ff08347a5", + "prefix-38-07/observed.refs": "0773e6751fe02c746abd8bdb0765d0a79fe82ce5a99b13314a072509056fb895", + "prefix-38-07/reads.txt": "ca14a1137a0cec7f58cd4b6f319917367b61a6a7e1f5efc714e1f54cb16c4b90", + "prefix-38-07/result.json": "6e70a6eb8a4102b684e9de0cb0c82dae16e298469c06f687b29549f4dd21c610", + "prefix-38-07/stderr.txt": "8b43e3415ffcc0209002ea54371038ace587ae3e83d20a0546897d9ce27442ef", + "prefix-38-07/stdout.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "provenance.json": "b492bdfdae818000ca35ca112da09a6bac7eca10eeb8b45fee6eb211db3c74fb", + "report.json": "07c2aeea1b9589bed30ed3c01947e2d09984acb507823bf471435a30633418cb", + "semaphore-38-00/before.json": "a1c351f5b37001c34b42d096b466f5ff4f241d3e97b36d5e0ebc87bb118b6c15", + "semaphore-38-00/committed-after.json": "1dc105038b12f46a2e4867cd9dc9d5ef5fc632f975e683bdd8732369a105a9f3", + "semaphore-38-00/final.json": "1dc105038b12f46a2e4867cd9dc9d5ef5fc632f975e683bdd8732369a105a9f3", + "semaphore-38-00/observed.refs": "51ffe8ce3ced795d66a97a7e3826cb9fc5800219083d6e5f61b347f121bd5202", + "semaphore-38-00/reads.txt": "53d5df6f6feaf260c58b910e1a8318f72467e1466d60ec5bdd33877972bfb3bc", + "semaphore-38-00/result.json": "6bc469e7a7adcac6da8c22701d5fc6804bbd8a7abde81395181c749e48f1be43", + "semaphore-38-00/stderr.txt": "14afb75549c5f580652f3392aec02034f3e58da8590b119dc6a632792211bd92", + "semaphore-38-00/stdout.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "semaphore-38-00/transaction-1.stdin": "5e7ba7686f3c8ad76fed829ab0a60a039c6d91c02fa765eb095b7ba86e8b2ead", + "semaphore-38-01/before.json": "2b20467a68007da040ef2949cc27b45fb79b53b444ead81221cc56e3510d4d07", + "semaphore-38-01/committed-after.json": "28192fd052a3d83defa185607c06cb4afb35565d8ee9b24a2c3e0f7b49e07ad6", + "semaphore-38-01/final.json": "da90c9dcdbee43978fc46c08dacb095e702a1ca91549a8544eb6082f0a1d8389", + "semaphore-38-01/observed.refs": "0152ee4bfb967bd3464e860eacc909509a7f72a84971792c3006964185810f14", + "semaphore-38-01/reads.txt": "950cd8ee7623088546f203c46aac35535d78d2e935467ef701019c52eccbf08b", + "semaphore-38-01/result.json": "81ba1381a78953ab4ac634ebaaae5e1b025cd7abc99dfbfac1524433057a969f", + "semaphore-38-01/stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "semaphore-38-01/stdout.txt": "5c7e26b47caf7cc784c4e6b41bb5a373751f8aedb0779ae8f197e45ac1d20431", + "semaphore-38-01/transaction-1.stdin": "bd4b241cb21fc533b4a8bf31cf577c4dd196f68ddf3c3695cfcc50b677bcf783", + "semaphore-38-03/before.json": "7ace85ab301548a84e2a07c823008195c389c341a92dd12af329e5264a8c0a6c", + "semaphore-38-03/committed-after.json": "a82cc94e2378db944a45750a4d1d93044eb7bbcf892a4786b9a4090518ddb4b4", + "semaphore-38-03/final.json": "a82cc94e2378db944a45750a4d1d93044eb7bbcf892a4786b9a4090518ddb4b4", + "semaphore-38-03/observed.refs": "560c54bfa630d01a3e95045e4a89347ecc065c233d0e6bcbe027ee82ba827538", + "semaphore-38-03/reads.txt": "950cd8ee7623088546f203c46aac35535d78d2e935467ef701019c52eccbf08b", + "semaphore-38-03/result.json": "bf6cb39b3ee2b6d9ab97607878beba2f5da25763747e674c70e7a4ba7c0dafeb", + "semaphore-38-03/stderr.txt": "14afb75549c5f580652f3392aec02034f3e58da8590b119dc6a632792211bd92", + "semaphore-38-03/stdout.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +} diff --git a/test/observation/git-shim.sh b/test/observation/git-shim.sh new file mode 100644 index 0000000..efc79bc --- /dev/null +++ b/test/observation/git-shim.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Inject exactly one synthetic ref observation; retries use real Git reads. +# Objects and update-ref transactions always use real Git in the isolated store. +set -euo pipefail +OBS_CASE="${OBS_CASE:?set the isolated case directory}" +OBS_INJECT_READ="${OBS_INJECT_READ:?set the read ordinal}" +OBS_REAL_GIT="${OBS_REAL_GIT:?set the real Git executable}" +for arg in "$@"; do + if [[ "${arg}" == for-each-ref ]]; then + read_number=0 + [[ ! -f "${OBS_CASE}/read-count" ]] || read -r read_number <"${OBS_CASE}/read-count" + read_number=$((read_number + 1)) + printf '%s\n' "${read_number}" >"${OBS_CASE}/read-count" + if [[ "${read_number}" == "${OBS_INJECT_READ}" ]]; then + : >"${OBS_CASE}/injected" + cat "${OBS_CASE}/observed.refs" + printf 'injected\n' >>"${OBS_CASE}/reads.log" + exit 0 + fi + printf 'real\n' >>"${OBS_CASE}/reads.log" + elif [[ "${arg}" == update-ref ]]; then + n=0 + [[ ! -f "${OBS_CASE}/transaction-count" ]] || read -r n <"${OBS_CASE}/transaction-count" + n=$((n + 1)) + printf '%s\n' "${n}" >"${OBS_CASE}/transaction-count" + cat >"${OBS_CASE}/transaction-${n}.stdin" + "${OBS_REAL_GIT}" "$@" <"${OBS_CASE}/transaction-${n}.stdin" + exit "$?" + fi +done +exec "${OBS_REAL_GIT}" "$@" diff --git a/test/observation/study.py b/test/observation/study.py new file mode 100644 index 0000000..f17b952 --- /dev/null +++ b/test/observation/study.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +"""Synthetic observation-phase safety study; no live Git race is claimed. + +The default command exits 1 when production leaves an invariant violation. +Experiment calibration failures exit 2. Output retains the actual failure, +not an expected-failure test result. +""" + +import argparse +import copy +import itertools +import hashlib +import json +import os +from pathlib import Path +import random +import shutil +import subprocess +import sys + +NOW = 1000000 +ROOT = Path(__file__).resolve().parents[2] +GIT = shutil.which("git") + + +def execute(args, cwd, env=None, data=None): + return subprocess.run(args, cwd=cwd, env=env, input=data, text=True, capture_output=True, timeout=30) + + +def git(store, *args, data=None): + result = execute([GIT, f"--git-dir={store}", *args], store.parent, data=data) + if result.returncode: + raise RuntimeError((args, result.stderr)) + return result.stdout + + +def refmap(store): + return dict(line.split() for line in git(store, "for-each-ref", "--format=%(refname) %(objectname)", "refs/locks/").splitlines()) + + +def fields(body): + header, sep, paths = body.partition("\npaths:\n") + record = dict(line.split(": ", 1) for line in header.splitlines() if ": " in line) + record["paths"] = paths.splitlines() if sep else [] + return record + + +def read_state(store): + refs = refmap(store) + objects = {oid: git(store, "cat-file", "blob", oid) for oid in set(refs.values())} + return {"refs": refs, "objects": objects} + + +def violations(state): + records = {ref: fields(state["objects"][oid]) for ref, oid in state["refs"].items()} + jobs = {ref.removeprefix("refs/locks/jobs/"): r for ref, r in records.items() if ref.startswith("refs/locks/jobs/")} + failures = [] + for name, record in jobs.items(): + parent = record.get("parent") + if parent and (parent not in jobs or jobs[parent].get("holder") != record.get("holder") or int(jobs[parent]["expires"]) <= NOW): + failures.append({"invariant": "family-parent", "job": name, "parent": parent}) + seen, ancestor = {name}, parent + while ancestor in jobs: + if ancestor in seen: + failures.append({"invariant": "family-cycle", "job": name}) + break + seen.add(ancestor) + ancestor = jobs[ancestor].get("parent") + for ref, record in records.items(): + if ref.startswith("refs/locks/sem/") and ref.endswith("/meta"): + prefix = ref[:-4] + "slots/" + live = sum(int(r["expires"]) > NOW for key, r in records.items() if key.startswith(prefix)) + if live > int(record["capacity"]): + failures.append({"invariant": "semaphore-capacity", "semaphore": ref.split("/")[3], "live": live, "capacity": int(record["capacity"])}) + for (left, a), (right, b) in itertools.combinations(jobs.items(), 2): + if min(int(a["expires"]), int(b["expires"])) <= NOW: + continue + for p, q in itertools.product(a["paths"], b["paths"]): + if p == q or (p.endswith("/") and q.startswith(p)) or (q.endswith("/") and p.startswith(q)): + failures.append({"invariant": "prefix-exclusivity", "jobs": [left, right], "paths": [p, q]}) + return failures + + +def write_json(path, obj): + path.write_text(json.dumps(obj, indent=2, sort_keys=True) + "\n") + + +def write_refs(path, refs): + path.write_text("".join(f"{ref} {oid}\n" for ref, oid in sorted(refs.items()))) + + +def scenario(case, domain, seed, binary): + case.mkdir(parents=True) + store = case / "store.git" + env = dict(os.environ, HOME=str(case / "home"), GIT_LOCKS_STORE=str(store), GIT_LOCKS_NOW=str(NOW)) + env.pop("GIT_LOCKS_HOME", None) + for key in ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_COMMON_DIR", "GIT_PREFIX", "GIT_OBJECT_DIRECTORY", "GIT_NAMESPACE"): + env.pop(key, None) + Path(env["HOME"]).mkdir() + rng = random.Random(seed) + suffix = str(rng.randrange(10000)) + parent, child, contender = "p" + suffix, "c" + suffix, "z" + suffix + directory = "d" + suffix + "/" + + def locks(*args): + result = execute([binary, *args], case, env) + if result.returncode: + raise RuntimeError((args, result.stdout, result.stderr)) + return result + + if domain == "family": + locks("claim", "--job", parent, "--holder", "alice", "parent.md") + before = read_state(store) + locks("claim", "--job", child, "--holder", "alice", "--parent", parent, "child.md") + action = ["release", "--job", parent] + elif domain == "semaphore": + locks("sem", "create", "gpu", "--capacity", "1") + before = read_state(store) + locks("sem", "acquire", "gpu", "--job", child, "--holder", "alice") + action = ["sem", "acquire", "gpu", "--job", contender, "--holder", "bob"] + else: + locks("claim", "--job", "unrelated", "--holder", "alice", "outside.md") + before = read_state(store) + locks("claim", "--job", child, "--holder", "alice", directory + "child.md") + action = ["claim", "--job", contender, "--holder", "bob", directory] + after = read_state(store) + if violations(before) or violations(after): + raise RuntimeError("unhealthy setup") + return store, env, before, after, action + + +def run_case(case, domain, seed, mask, binary, shim, inject_read=None): + store, env, before, after, action = scenario(case, domain, seed, binary) + changed = sorted(ref for ref in before["refs"].keys() | after["refs"].keys() if before["refs"].get(ref) != after["refs"].get(ref)) + expected_count = {"family": 4, "semaphore": 2, "prefix": 3}[domain] + if len(changed) != expected_count: + raise RuntimeError(("fixture transition shape changed", domain, changed)) + observed = dict(before["refs"]) + selection = {} + for index, ref in enumerate(changed): + source = after if mask & (1 << index) else before + selection[ref] = "after" if source is after else "before" + if ref in source["refs"]: + observed[ref] = source["refs"][ref] + else: + observed.pop(ref, None) + write_refs(case / "observed.refs", observed) + write_json(case / "before.json", before) + write_json(case / "committed-after.json", after) + env.update(PATH=str(shim) + os.pathsep + env["PATH"], OBS_CASE=str(case), OBS_REAL_GIT=GIT, OBS_INJECT_READ=str(inject_read or (1 if domain == "prefix" else 2))) + result = execute([binary, *action], case, env) + (case / "stdout.txt").write_text(result.stdout) + (case / "stderr.txt").write_text(result.stderr) + if result.returncode not in (0, 1): + raise RuntimeError(("unexpected command failure", action, result.returncode, result.stderr)) + if not (case / "injected").exists(): + raise RuntimeError(("planner injection did not run", domain, action)) + final = read_state(store) + bad = violations(final) + write_json(case / "final.json", final) + record = {"domain": domain, "seed": seed, "mask": mask, "changed": selection, "observation": "synthetic-per-ref-before-after", "command": action, "exit": result.returncode, "violations": bad, "reads": (case / "reads.log").read_text().splitlines(), "injected_read": inject_read or (1 if domain == "prefix" else 2), "transactions": int((case / "transaction-count").read_text()) if (case / "transaction-count").exists() else 0} + write_json(case / "result.json", record) + return record + + +def calibrate(output, binary, shim): + evidence = [] + for domain in ("family", "semaphore", "prefix"): + case = output / ("calibration-" + domain) + _, _, _, healthy, _ = scenario(case, domain, 38, binary) + bad = copy.deepcopy(healthy) + if domain == "family": + del bad["refs"]["refs/locks/jobs/p6899"] + expected = "family-parent" + elif domain == "semaphore": + slot = "refs/locks/sem/gpu/slots/c6899" + bad["refs"]["refs/locks/sem/gpu/slots/second"] = bad["refs"][slot] + expected = "semaphore-capacity" + else: + child_ref = "refs/locks/jobs/c6899" + body = bad["objects"][bad["refs"][child_ref]] + body = body.replace("job: c6899\n", "job: covering\n").replace("d6899/child.md\n", "d6899/\n") + bad["objects"]["calibration-object"] = body + bad["refs"]["refs/locks/jobs/covering"] = "calibration-object" + expected = "prefix-exclusivity" + if violations(healthy) or [v["invariant"] for v in violations(bad)] != [expected]: + raise RuntimeError(("oracle calibration failed", domain, violations(healthy), violations(bad))) + write_json(case / "healthy.json", healthy) + write_json(case / "deliberately-bad.json", bad) + evidence.append({"domain": domain, "healthy_violations": [], "deliberately_bad_violations": violations(bad), "kind": "hand-constructed-oracle-input"}) + # release/sem discard the dispatcher's initial snapshot before planning. + # Injecting there is a negative instrumentation control, not a safe planner. + for domain, mask in (("family", 14), ("semaphore", 1)): + result = run_case(output / ("discarded-bootstrap-" + domain), domain, 38, mask, binary, shim, inject_read=1) + if result["violations"] or result["reads"][:2] != ["injected", "real"]: + raise RuntimeError(("discarded-read control failed", result)) + evidence.append(result) + write_json(output / "calibration.json", evidence) + return evidence + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--binary", default=str(ROOT / "bin/git-locks")) + parser.add_argument("--seeds", nargs="+", type=int, default=[38, 1701, 20260922]) + parser.add_argument("--domains", nargs="+", choices=["family", "semaphore", "prefix"], default=["family", "semaphore", "prefix"]) + parser.add_argument("--calibrate-only", action="store_true", help="check the oracle and discarded-read controls, not production safety") + args = parser.parse_args() + output = args.output.resolve() + output.mkdir(parents=True, exist_ok=False) + shim = output / "shim" + shim.mkdir() + shutil.copy(ROOT / "test/observation/git-shim.sh", shim / "git") + (shim / "git").chmod(0o755) + calibration = calibrate(output, str(Path(args.binary).resolve()), shim) + if args.calibrate_only: + print(json.dumps({"calibration": "PASS", "oracle_cases": 6, "discarded_read_controls": 2, "production_safety": "NOT_EVALUATED"})) + return 0 + provenance = { + "binary_sha256": hashlib.sha256(Path(args.binary).read_bytes()).hexdigest(), + "fixture_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), + "shim_sha256": hashlib.sha256((ROOT / "test/observation/git-shim.sh").read_bytes()).hexdigest(), + "git": execute([GIT, "--version"], ROOT).stdout.strip(), + "bash": execute(["bash", "--version"], ROOT).stdout.splitlines()[0], + "python": sys.version.splitlines()[0], + } + write_json(output / "provenance.json", provenance) + results = [] + for seed in args.seeds: + for domain in args.domains: + size = {"family": 16, "semaphore": 4, "prefix": 8}[domain] + for mask in range(size): + result = run_case(output / f"{domain}-{seed}-{mask:02d}", domain, seed, mask, str(Path(args.binary).resolve()), shim) + results.append(result) + print(json.dumps(result), flush=True) + report = {"observation": "synthetic-per-ref-before-after", "live_git_race_reproduced": False, "cases": len(results), "violating_cases": sum(bool(r["violations"]) for r in results), "results": results, "calibration": calibration} + report["production_safety"] = "FAIL" if report["violating_cases"] else "PASS_WITHIN_TESTED_SYNTHETIC_CASES" + write_json(output / "report.json", report) + print(json.dumps({key: value for key, value in report.items() if key not in ("results", "calibration")}), flush=True) + return 1 if report["violating_cases"] else 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except (AssertionError, RuntimeError, subprocess.TimeoutExpired, OSError, ValueError, KeyError) as exc: + print(f"STUDY ERROR: {exc}", file=sys.stderr) + sys.exit(2) diff --git a/test/observation/verify-evidence.py b/test/observation/verify-evidence.py new file mode 100644 index 0000000..287047a --- /dev/null +++ b/test/observation/verify-evidence.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +"""Verify the committed receipt manifest, without trusting untracked files.""" + +import hashlib +import json +from pathlib import Path +import subprocess +import sys + +root = Path(__file__).resolve().parents[2] +prefix = "docs/studies/membership-observation/evidence/" + + +def git(*args): + return subprocess.check_output(["git", *args], cwd=root) + + +manifest = json.loads(git("show", "HEAD:" + prefix + "sha256.json")) +tracked = set(git("ls-files", "-z", "--", prefix).decode().split("\0")) +failures = [] +for name, expected in manifest.items(): + path = prefix + name + if path not in tracked: + failures.append(f"not tracked: {path}") + continue + actual = hashlib.sha256(git("show", "HEAD:" + path)).hexdigest() + if actual != expected: + failures.append(f"committed checksum differs: {path}") +if failures: + print("\n".join(failures), file=sys.stderr) + sys.exit(1) +print(f"Verified {len(manifest)} committed receipt paths and SHA-256 hashes at " + git("rev-parse", "HEAD").decode().strip())