Attested 1440×1800 Chromium capture of the checked-in offline report. No external assets, JavaScript, network, secrets, or host-repository data.
+
Attested 1440×1800 Chromium capture of the checked-in offline report. Provenance: report receipt `2da1ccd8…69c84`; screenshot SHA-256 `e539db11…e17e`. No external assets, JavaScript, network, secrets, or host-repository data.
## Quick start
@@ -15,6 +17,8 @@ Requirements: Python 3.10+ and Git 2.29+. There are no runtime Python dependenci
```bash
python3 -m git_dag_lab verify
python3 -m git_dag_lab inspect
+python3 -m git_dag_lab pack-verify
+python3 -m git_dag_lab pack-inspect
python3 -m unittest discover -s tests -v
```
@@ -34,6 +38,29 @@ The fixture contains three blobs, six trees, and five commits. `merge` stores th
The replay is called **rebase-shaped** because it is constructed directly with `git commit-tree`. The lab does not claim to execute porcelain `git rebase`.
+
+## A second systems slice: verify pack and index bytes
+
+The pack path stores three fixed synthetic blobs in a fresh private SHA-1 repository, invokes real `git pack-objects`, then removes the repository after independently decoding both generated files. The CLI receipt below is actual stdout from that production path:
+
+
+
+The offline report is rendered from the same canonical receipt and captured by digest-pinned Chromium in a read-only, network-disabled container:
+
+
+
+
Attested 1440×1500 Chromium capture. Provenance: pack report receipt `a884aed4…a81b0`; screenshot SHA-256 `ad1f615d…4d63`. Three deterministic synthetic blobs; no delta support, arbitrary-repository compatibility, authentication, network, or host data.
+
+The verifier does not trust the pack filename or Git's index. It parses the variable-length pack entry headers, bounds each zlib stream, reconstructs logical blob IDs, verifies the pack trailer, then parses the 256-entry cumulative fanout table, sorted OIDs, CRC32 rows, 32/64-bit offsets, pack binding, and index checksum.
+
+
+
+
+
+
+
+This is deliberately a closed subset: pack v2 and index v2, at most 64 objects, 1 MiB files, 256 KiB expanded objects, and non-delta entries only. Delta entries (OFS/REF), other object formats, arbitrary repositories, reachability, and pack optimization are not claimed. SHA-1 and CRC32 model Git storage integrity here; neither is presented as authentication, a signature, or collision-resistant security.
+
## The hard part: verify Git without trusting Git
Writing an object with Git and asking Git to identify it would only prove that Git agrees with itself. This lab reads the raw stored bytes and independently computes:
@@ -51,7 +78,7 @@ SHA-1 is used because this scenario models a SHA-1 Git object database. Here it
## Isolation and execution boundaries
- Git is resolved once to an absolute executable and invoked with argument arrays, never a shell.
-- 10 local subcommands are allow-listed, while one fixed isolated `git init` creates the bare database; transport commands and remote-looking arguments are rejected.
+- 11 local subcommands are allow-listed, including the bounded `pack-objects` path, while one fixed isolated `git init` creates each bare database; transport commands and remote-looking arguments are rejected.
- `HOME`, `XDG_CONFIG_HOME`, and `TMPDIR` are private; inherited Git config, hooks, replacement objects, identity, and object-directory redirects are ignored.
- fixed synthetic identity `dag-lab@example.invalid`, fixed UTC timestamps, and fixed LF payloads make object IDs reproducible.
- symlinked workspace components are rejected; stdout/stderr are spooled privately and checked before bounded reads.
@@ -61,24 +88,26 @@ See [SECURITY.md](SECURITY.md) for the threat model and trusted-input boundary.
## Evidence pipeline
-Every README visual begins with the same canonical CLI document. The generator runs fresh experiments twice, requires byte-identical outputs, derives the SVG and offline HTML, and binds each artifact into a hash manifest. Digest-pinned Chromium then captures the report in a read-only container with `--network none`. A separate attestation binds the exact report, rendered DOM, PNG, browser binary/version, container digest, isolation policy, viewport, and capture-script hash; without that attestation, the generator refuses to call the screenshot verified.
+Every README visual begins with a canonical production CLI document. The DAG and pack generators each run fresh experiments twice, require byte-identical outputs, derive their SVGs and offline HTML, and bind every artifact into a hash manifest. Digest-pinned Chromium captures both reports in read-only containers with `--network none`. Separate attestations bind each exact report, rendered DOM, PNG, browser binary/version, container digest, isolation policy, viewport, and capture-script hash; without the matching attestation, a generator refuses to call its screenshot verified.

### Reproduce the checked-in evidence
```bash
-# Verify JSON, transcripts, SVGs, HTML, source hashes, and the existing PNG.
+# Verify both JSON/transcript/visual/report/manifest packages and PNG attestations.
python3 -B tools/generate_evidence.py --check
+python3 -B tools/generate_pack_evidence.py --check
-# Rebuild evidence and recapture the report with the pinned browser container.
+# Rebuild and recapture either offline report with pinned Chromium.
tools/capture_report.sh
+tools/capture_pack_report.sh
-# Run all engine, boundary, CLI, evidence, and provenance tests.
+# Run all parser, boundary, CLI, evidence, and provenance tests.
python3 -W error -m unittest discover -s tests -v
```
-Current verified baseline: **61 tests**, **9/9 graph invariants**, **57 isolated Git invocations**, report receipt `2da1ccd8…69c84`, and screenshot SHA-256 `e539db11…e17e`.
+Current verified baseline: **89 tests**, **9/9 graph invariants**, **7/7 pack/index checks**, **57 isolated Git invocations** in the DAG evidence run, two independently replayed evidence packages, and two attested offline browser captures.
| Artifact | What it proves |
|---|---|
@@ -89,13 +118,22 @@ Current verified baseline: **61 tests**, **9/9 graph invariants**, **57 isolated
| [`rendered-dom.html`](docs/demo/git-dag-v1/rendered-dom.html) | Actual DOM emitted by Chromium during the attested capture |
| [`capture-attestation.json`](docs/demo/git-dag-v1/capture-attestation.json) | Report/DOM/PNG hashes plus verified browser, container, isolation, viewport, and script provenance |
| [`manifest.json`](docs/demo/git-dag-v1/manifest.json) | SHA-256, byte size, role, source hashes, normalized argv, and attestation receipt |
-| [`git-dag-report.png`](docs/assets/git-dag-report.png) | Actual Chromium rendering of the report at 1440×1800 |
+| [`git-dag-report.png`](docs/assets/git-dag-report.png) | Actual Chromium rendering of the DAG report at 1440×1800 |
+| [`evidence/git-pack-index-v1.json`](evidence/git-pack-index-v1.json) | Canonical real pack/index receipt, physical entry order, cross-bound rows, and non-claims |
+| [`git-pack-cli.svg`](docs/assets/git-pack-cli.svg) | Exact production `pack-verify` stdout rendered as an accessible terminal panel |
+| [`git-pack-layout.svg`](docs/assets/git-pack-layout.svg) | Actual pack offsets/sizes and index-table byte counts |
+| [`git-pack-fanout.svg`](docs/assets/git-pack-fanout.svg) | Actual non-empty fanout buckets and sorted OID ranges |
+| [`git-pack-integrity.svg`](docs/assets/git-pack-integrity.svg) | Receipt-derived pack/index checksum and row-binding workflow |
+| [`git-pack-report.png`](docs/assets/git-pack-report.png) | Actual Chromium rendering of the pack/index report at 1440×1500 |
+| [`git-pack-index-v1/manifest.json`](docs/demo/git-pack-index-v1/manifest.json) | Hash/size/source/command/capture inventory for every pack visual and output |
## Test coverage by risk
The standard-library suite exercises more than happy-path graph construction:
- independent blob, tree, and commit envelope hashes;
+- pack v2 headers, bounded zlib streams, logical OIDs, trailer checksum, and explicit delta rejection;
+- index v2 fanout, sorted OIDs, CRC32 rows, small/large offsets, pack binding, and checksum mutations;
- exact object/ref inventories, parent ordering, reachability, and ancestry;
- Git's special `directory/` tree ordering, truncated binary objects, and malformed headers;
- hostile inherited Git environment and fake global identity/config;
diff --git a/SECURITY.md b/SECURITY.md
index e4cc6f4..37c677e 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,6 +1,6 @@
# Security model
-Git DAG Evidence Lab creates a temporary bare repository below the selected workspace and removes it after each run. It does not inspect the repository that contains this source code.
+Git DAG Evidence Lab creates a temporary bare repository below the selected workspace for each DAG or pack experiment and removes it after the run. It does not inspect the repository that contains this source code.
The command boundary is deliberately narrow:
@@ -13,6 +13,12 @@ The command boundary is deliberately narrow:
- temporary roots with symlinked path components are rejected.
- stdout and stderr are captured in private temporary files and rejected before loading into memory when either exceeds 1 MiB.
+## Pack/index closed subset
+
+The pack experiment passes only three fixed synthetic blob IDs to `git pack-objects`; it does not accept a repository path, revision, ref, or caller-provided object list. Generated `.pack` and `.idx` files must be regular, single-link files no larger than 1 MiB and must remain the same inode and size across the bounded read.
+
+The independent parser accepts pack v2 and index v2 only. It rejects OFS/REF deltas, more than 64 objects, objects expanding beyond 256 KiB, invalid or unterminated zlib streams, duplicate logical objects, non-canonical fanout/large-offset tables, and any mismatch among logical object IDs, CRC32 rows, offsets, pack trailer, index pack binding, or index checksum. These checks establish the fixed fixture's storage integrity; they do not establish provenance, authenticity, repository reachability, or safety of arbitrary Git data.
+
## SHA-1 scope
The lab uses SHA-1 because the scenario explicitly models a SHA-1 Git object database. The independent envelope calculation demonstrates deterministic content addressing and detects accidental changes in these fixtures. It is not a signature, authentication mechanism, or claim of modern collision resistance.
diff --git a/docs/assets/git-pack-cli.svg b/docs/assets/git-pack-cli.svg
new file mode 100644
index 0000000..31d1063
--- /dev/null
+++ b/docs/assets/git-pack-cli.svg
@@ -0,0 +1,29 @@
+
diff --git a/docs/assets/git-pack-fanout.svg b/docs/assets/git-pack-fanout.svg
new file mode 100644
index 0000000..9c76cf8
--- /dev/null
+++ b/docs/assets/git-pack-fanout.svg
@@ -0,0 +1,45 @@
+
diff --git a/docs/assets/git-pack-integrity.svg b/docs/assets/git-pack-integrity.svg
new file mode 100644
index 0000000..e51e47b
--- /dev/null
+++ b/docs/assets/git-pack-integrity.svg
@@ -0,0 +1,54 @@
+
diff --git a/docs/assets/git-pack-layout.svg b/docs/assets/git-pack-layout.svg
new file mode 100644
index 0000000..df605e5
--- /dev/null
+++ b/docs/assets/git-pack-layout.svg
@@ -0,0 +1,63 @@
+
diff --git a/docs/assets/git-pack-report.png b/docs/assets/git-pack-report.png
new file mode 100644
index 0000000..cd58cae
Binary files /dev/null and b/docs/assets/git-pack-report.png differ
diff --git a/docs/demo/git-dag-v1/manifest.json b/docs/demo/git-dag-v1/manifest.json
index a57a689..f9504a6 100644
--- a/docs/demo/git-dag-v1/manifest.json
+++ b/docs/demo/git-dag-v1/manifest.json
@@ -130,13 +130,13 @@
"sources": [
{
"path": "git_dag_lab/lab.py",
- "sha256": "8c4bf11d5c7840a7dcbe3f4486246aff9b3a306c6bceb7b15be3fd0040a7bbd4",
- "size": 34652
+ "sha256": "289e688e84024c20b94f3aa2e59be693b81b507b8581fe5547cc8f5eb223879b",
+ "size": 34676
},
{
"path": "git_dag_lab/cli.py",
- "sha256": "4b8b2433e0b613a303b886d08a630ddfeada557702fc47de4cd2f59824e6501d",
- "size": 1684
+ "sha256": "03648331670cdc350fd486b2939e4914e90ee7ca7c2ea2b5cabd4eced21fe766",
+ "size": 2335
},
{
"path": "tools/generate_evidence.py",
diff --git a/docs/demo/git-pack-index-v1/capture-attestation.json b/docs/demo/git-pack-index-v1/capture-attestation.json
new file mode 100644
index 0000000..cbbb156
--- /dev/null
+++ b/docs/demo/git-pack-index-v1/capture-attestation.json
@@ -0,0 +1,60 @@
+{
+ "attestation": {
+ "browser": {
+ "binary_path": "/ms-playwright/chromium_headless_shell-1193/chrome-linux/headless_shell",
+ "sha256": "003728e0b77eb9d52e4d258594bd55ce22ecd245eb6d3b6858fbd844c901ad7d",
+ "version": "Chromium 140.0.7339.186"
+ },
+ "container": {
+ "architecture": "amd64",
+ "image": "mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c"
+ },
+ "input": {
+ "report": {
+ "path": "docs/demo/git-pack-index-v1/report.html",
+ "report_receipt_sha256": "a884aed43dbb027559f6df78ff727863b9b52b145ffb719756b2302a490a81b0",
+ "sha256": "0109d54e1e3f794fe3422ddf7720fd8c322c3ee3d82dc41c8d3ff1207f250624",
+ "size": 5268
+ }
+ },
+ "isolation": {
+ "capabilities": "all-dropped",
+ "demo_mount": "read-only",
+ "network": "none",
+ "no_new_privileges": true,
+ "pull": "never",
+ "root_filesystem": "read-only",
+ "user": "caller-nonroot"
+ },
+ "outputs": {
+ "rendered_dom": {
+ "path": "docs/demo/git-pack-index-v1/rendered-dom.html",
+ "sha256": "736bd86208630f5e1437335e009615bffd8f7bb96932587acad33b3307f1827d",
+ "size": 5268
+ },
+ "screenshot": {
+ "height": 1500,
+ "path": "docs/assets/git-pack-report.png",
+ "sha256": "ad1f615da03d2e0570a4b3b26603c310058964bfbc5dda201d176de8107e4d63",
+ "size": 590359,
+ "width": 1440
+ }
+ },
+ "schema_version": "git-pack-browser-capture-attestation/v1",
+ "script": {
+ "path": "tools/capture_pack_report.sh",
+ "sha256": "3477eeec4a10026fe95b87803f68657069c77f2b491bd69d3cddd56777924f0b",
+ "size": 11083
+ },
+ "viewport": {
+ "device_scale_factor": 1,
+ "height": 1500,
+ "width": 1440
+ }
+ },
+ "receipt": {
+ "algorithm": "sha256",
+ "canonicalization": "UTF-8 JSON; sorted keys; compact separators",
+ "sha256": "9709eafc99c848f825d083b795a9ba2802109d76b21289e2a4f72c445519c35b"
+ }
+}
diff --git a/docs/demo/git-pack-index-v1/inspect.json b/docs/demo/git-pack-index-v1/inspect.json
new file mode 100644
index 0000000..37679af
--- /dev/null
+++ b/docs/demo/git-pack-index-v1/inspect.json
@@ -0,0 +1,127 @@
+{
+ "receipt": {
+ "algorithm": "sha256",
+ "canonicalization": "UTF-8 JSON; sorted keys; compact separators",
+ "sha256": "a884aed43dbb027559f6df78ff727863b9b52b145ffb719756b2302a490a81b0"
+ },
+ "report": {
+ "checks": {
+ "all_fixture_objects_present": true,
+ "delta_entries_absent": true,
+ "index_checksum_verified": true,
+ "index_crc32_matches_pack": true,
+ "index_fanout_matches_sorted_oids": true,
+ "index_offsets_match_pack": true,
+ "pack_trailer_verified": true
+ },
+ "command_trace": [
+ "init",
+ "hash-object",
+ "hash-object",
+ "hash-object",
+ "pack-objects"
+ ],
+ "fixture": {
+ "object_count": 3,
+ "objects": [
+ {
+ "label": "binary-header",
+ "oid": "fefa1cc823e0ec463b7923972b03901b52808fc1",
+ "payload_sha256": "630dcd2966c4336691125448bbb25b4ff412a49c732db2c8abc1b8581bd710dd",
+ "size": 32
+ },
+ {
+ "label": "content-addressing",
+ "oid": "ac0913a01c3a10dbcdf22143ad8f53d015774ff7",
+ "payload_sha256": "218787ebc53eb8b381705f18f614758dc0b2f7e2781da3eb8132a0eda7aef33d",
+ "size": 26
+ },
+ {
+ "label": "index-fanout",
+ "oid": "fda2e7ba229f29298234d2568c24b04c04e603df",
+ "payload_sha256": "5d91ab3e2e99923d07e6f7c38354d19f84f2d1b2bbcc0faa8ceb14a71f9868cc",
+ "size": 60
+ }
+ ]
+ },
+ "index": {
+ "bytes": 1156,
+ "index_sha1": "3cb00d5dd06610c624befb4e9e1b40f9cdbf9dfa",
+ "nonzero_fanout_buckets": [
+ {
+ "cumulative": 1,
+ "prefix": "ac",
+ "range_start": 0
+ },
+ {
+ "cumulative": 2,
+ "prefix": "fd",
+ "range_start": 1
+ },
+ {
+ "cumulative": 3,
+ "prefix": "fe",
+ "range_start": 2
+ }
+ ],
+ "pack_sha1": "146ea7519b9beee2ef83e6c0d5cb80c8cf0593b5",
+ "sha256": "c4f82d0cb1685f3d3b268575152993408c0ee4f00de346a3482b06c6fe59eebc",
+ "version": 2
+ },
+ "object_format": "sha1",
+ "objects_in_pack_order": [
+ {
+ "crc32": "fb8c64c5",
+ "index_crc32": "fb8c64c5",
+ "index_offset": 12,
+ "label": "content-addressing",
+ "object_type": "blob",
+ "offset": 12,
+ "oid": "ac0913a01c3a10dbcdf22143ad8f53d015774ff7",
+ "packed_size": 39,
+ "payload_sha256": "218787ebc53eb8b381705f18f614758dc0b2f7e2781da3eb8132a0eda7aef33d",
+ "size": 26
+ },
+ {
+ "crc32": "c532220c",
+ "index_crc32": "c532220c",
+ "index_offset": 51,
+ "label": "index-fanout",
+ "object_type": "blob",
+ "offset": 51,
+ "oid": "fda2e7ba229f29298234d2568c24b04c04e603df",
+ "packed_size": 73,
+ "payload_sha256": "5d91ab3e2e99923d07e6f7c38354d19f84f2d1b2bbcc0faa8ceb14a71f9868cc",
+ "size": 60
+ },
+ {
+ "crc32": "88dbb9d0",
+ "index_crc32": "88dbb9d0",
+ "index_offset": 124,
+ "label": "binary-header",
+ "object_type": "blob",
+ "offset": 124,
+ "oid": "fefa1cc823e0ec463b7923972b03901b52808fc1",
+ "packed_size": 45,
+ "payload_sha256": "630dcd2966c4336691125448bbb25b4ff412a49c732db2c8abc1b8581bd710dd",
+ "size": 32
+ }
+ ],
+ "pack": {
+ "bytes": 189,
+ "delta_count": 0,
+ "object_count": 3,
+ "sha256": "d8c8d5db126731f265cdcfe17212022001a117d6e7c2300b7939a25b93cb4052",
+ "trailer_sha1": "146ea7519b9beee2ef83e6c0d5cb80c8cf0593b5",
+ "version": 2
+ },
+ "schema_version": "git-pack-index-lab/v1",
+ "scope": {
+ "authentication_claim": false,
+ "delta_entries_supported": false,
+ "fixture_kind": "three deterministic synthetic blobs",
+ "git_pack_objects_executed": true,
+ "network_required": false
+ }
+ }
+}
diff --git a/docs/demo/git-pack-index-v1/manifest.json b/docs/demo/git-pack-index-v1/manifest.json
new file mode 100644
index 0000000..4ecdcdc
--- /dev/null
+++ b/docs/demo/git-pack-index-v1/manifest.json
@@ -0,0 +1,152 @@
+{
+ "artifacts": [
+ {
+ "path": "docs/assets/git-pack-cli.svg",
+ "role": "visualized exact pack-verify transcript",
+ "sha256": "ccd4e4955bcba485bb4bd34d493bde723920dd24b95cbfd465a8373165a38727",
+ "size": 2796
+ },
+ {
+ "path": "docs/assets/git-pack-fanout.svg",
+ "role": "actual index fanout ranges and sorted object IDs",
+ "sha256": "bfb0e720f9e82083803dbebcac46549f2f4725122364efa173cd5007342c0a4f",
+ "size": 3803
+ },
+ {
+ "path": "docs/assets/git-pack-integrity.svg",
+ "role": "pack/index integrity chain derived from the receipt",
+ "sha256": "6733240058cdfbd114163798d7e48df287edb6c380380a40c14f907772f01ee3",
+ "size": 4308
+ },
+ {
+ "path": "docs/assets/git-pack-layout.svg",
+ "role": "actual pack and index byte layout",
+ "sha256": "77703a115b270f49b00d573ede12a9537efe9c33fcadacc21ee1e82284db11cd",
+ "size": 5721
+ },
+ {
+ "path": "docs/assets/git-pack-report.png",
+ "role": "attested pack/index offline report browser capture",
+ "sha256": "ad1f615da03d2e0570a4b3b26603c310058964bfbc5dda201d176de8107e4d63",
+ "size": 590359
+ },
+ {
+ "path": "docs/demo/git-pack-index-v1/capture-attestation.json",
+ "role": "pack capture provenance and isolation attestation",
+ "sha256": "18e5fea29af65a0fd15b2959486b282f75425f1dabb1df20a556b57bf3c22757",
+ "size": 2011
+ },
+ {
+ "path": "docs/demo/git-pack-index-v1/inspect.json",
+ "role": "exact pretty pack-inspect stdout",
+ "sha256": "527650dfc891bb808688ea1cf53198db5aa6321866a3e302f5c70de6193bf921",
+ "size": 3851
+ },
+ {
+ "path": "docs/demo/git-pack-index-v1/rendered-dom.html",
+ "role": "actual DOM emitted during the pack report capture",
+ "sha256": "736bd86208630f5e1437335e009615bffd8f7bb96932587acad33b3307f1827d",
+ "size": 5268
+ },
+ {
+ "path": "docs/demo/git-pack-index-v1/report.html",
+ "role": "dependency-free pack/index offline report",
+ "sha256": "0109d54e1e3f794fe3422ddf7720fd8c322c3ee3d82dc41c8d3ff1207f250624",
+ "size": 5268
+ },
+ {
+ "path": "docs/demo/git-pack-index-v1/verify.txt",
+ "role": "exact pack-verify stdout",
+ "sha256": "ccab273b6f07dc72a28ad3e1065545e6bd535f766d96ad6c3dad273eea432f31",
+ "size": 208
+ },
+ {
+ "path": "evidence/git-pack-index-v1.json",
+ "role": "canonical compact pack/index CLI evidence",
+ "sha256": "a33a5a3a3a4930defec6309013415a18de0527b18a3adcb6e2c5aebce06b4b13",
+ "size": 2770
+ }
+ ],
+ "capture": {
+ "attestation": "docs/demo/git-pack-index-v1/capture-attestation.json",
+ "attestation_receipt_sha256": "9709eafc99c848f825d083b795a9ba2802109d76b21289e2a4f72c445519c35b",
+ "browser_binary": "/ms-playwright/chromium_headless_shell-1193/chrome-linux/headless_shell",
+ "browser_sha256": "003728e0b77eb9d52e4d258594bd55ce22ecd245eb6d3b6858fbd844c901ad7d",
+ "browser_version": "Chromium 140.0.7339.186",
+ "container_image": "mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c",
+ "network": "none",
+ "rendered_dom_sha256": "736bd86208630f5e1437335e009615bffd8f7bb96932587acad33b3307f1827d",
+ "screenshot_sha256": "ad1f615da03d2e0570a4b3b26603c310058964bfbc5dda201d176de8107e4d63",
+ "status": "attested",
+ "viewport": {
+ "height": 1500,
+ "width": 1440
+ }
+ },
+ "commands": [
+ {
+ "argv": [
+ "python3",
+ "-B",
+ "-m",
+ "git_dag_lab",
+ "pack-verify"
+ ],
+ "exit_code": 0,
+ "fresh_runs": 2,
+ "stderr_bytes": 0,
+ "stdout": "docs/demo/git-pack-index-v1/verify.txt"
+ },
+ {
+ "argv": [
+ "python3",
+ "-B",
+ "-m",
+ "git_dag_lab",
+ "pack-inspect",
+ "--compact"
+ ],
+ "exit_code": 0,
+ "fresh_runs": 2,
+ "stderr_bytes": 0,
+ "stdout": "evidence/git-pack-index-v1.json"
+ },
+ {
+ "argv": [
+ "python3",
+ "-B",
+ "-m",
+ "git_dag_lab",
+ "pack-inspect"
+ ],
+ "exit_code": 0,
+ "fresh_runs": 2,
+ "stderr_bytes": 0,
+ "stdout": "docs/demo/git-pack-index-v1/inspect.json"
+ }
+ ],
+ "report_receipt_sha256": "a884aed43dbb027559f6df78ff727863b9b52b145ffb719756b2302a490a81b0",
+ "schema_version": "git-pack-index-evidence-manifest/v1",
+ "sources": [
+ {
+ "path": "git_dag_lab/pack.py",
+ "sha256": "d3882af57ad9b3d85580032b7e5ceccd2c8b443fbee7be30c7452a31aee3f8a8",
+ "size": 20802
+ },
+ {
+ "path": "git_dag_lab/cli.py",
+ "sha256": "03648331670cdc350fd486b2939e4914e90ee7ca7c2ea2b5cabd4eced21fe766",
+ "size": 2335
+ },
+ {
+ "path": "tools/generate_pack_evidence.py",
+ "sha256": "2a85d4e5d3a98cca6e562eae7fad28e5f64d61bd02f973dcffdade274b89514d",
+ "size": 41315
+ },
+ {
+ "path": "tools/capture_pack_report.sh",
+ "sha256": "3477eeec4a10026fe95b87803f68657069c77f2b491bd69d3cddd56777924f0b",
+ "size": 11083
+ }
+ ]
+}
diff --git a/docs/demo/git-pack-index-v1/rendered-dom.html b/docs/demo/git-pack-index-v1/rendered-dom.html
new file mode 100644
index 0000000..03a6b84
--- /dev/null
+++ b/docs/demo/git-pack-index-v1/rendered-dom.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ Git pack/index evidence — verified offline report
+
+
+
+
+
Git pack/index lab · actual offline report
+
Pack v2. Index v2.
+
Real git pack-objects output is decoded independently: bounded zlib entries, logical object IDs, fanout ranges, CRC32 rows, offsets, and both file checksums.