unaltraweb 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,205 @@
1
+ # unaltraweb 0.5.1 delivery closeout
2
+
3
+ Publication: **2026-09-30**, [v0.5.1](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.5.1).
4
+ Owner coordination: [issue 76](https://github.com/dosquartsdedocs/unaltraweb/issues/76).
5
+ This supersedes the pending-publication status of the retained preparation and
6
+ follow-up reports without changing their historical bytes.
7
+
8
+ ## Revisions, review and integration
9
+
10
+ | Role | Revision / evidence |
11
+ | --- | --- |
12
+ | Initial accepted local source | `217340cadc9db85aa717e020682068b9ce0ef379` |
13
+ | Bundler/core implementation, retained consumer pin | `c23e12b0e1567d18a7f9dd225dc062ddc77dad8b` |
14
+ | Closeout installed-launcher default correction | `1640572ccd9156037b9a4c0018b4c849a027296f` |
15
+ | Integrated source producing the release artifacts | `aab5a7b030cd711b40770a3f44ad3a356eab90da`, [PR 77](https://github.com/dosquartsdedocs/unaltraweb/pull/77) |
16
+ | Receipt-only branch commit | `8a0b6ce0d0c875ac6a8b86d9e354b8a388b5d038`, direct child of the source above |
17
+ | Receipt integration and release tag target | `e842c733c8a274279dd5efdc3618e20669f29037`, [PR 78](https://github.com/dosquartsdedocs/unaltraweb/pull/78) |
18
+ | Annotated `v0.5.1` tag object | `c4901b583c777a050cd53e1e96643ad53b7c0f64` |
19
+
20
+ Both integrations used merge commits, preserving the approved core's ancestry.
21
+ The receipt integration's first parent is exactly the artifact source; its diff
22
+ from that parent contains only `release-candidates.json`. The source pin still
23
+ names the real approved core implementation. The later closeout correction
24
+ changes host-launcher selection, not that Jekyll/Bundler core implementation.
25
+
26
+ All preparation commits and the complete base diff were reviewed. The remaining
27
+ delivery finding was that the installed 0.5.1 launcher still selected the older
28
+ 0.5.0 MCP. Commit `1640572` fixes that: the console adapter uses explicit
29
+ `--image`, then `UNALTRAWEB_MCP_IMAGE`, then its own BOM release image. The installed
30
+ Make profile also defaults to its own release. The checkout's stricter digest
31
+ pin remains a separate post-release operation. Default and override precedence
32
+ are exercised by the factory-free wheel gate.
33
+
34
+ Agent review records are attached to both PRs; they do not claim human review.
35
+ Copilot could not review because of quota exhaustion and was not counted as a
36
+ completed review. Explicit owner authorization covered integration and, in two
37
+ later approvals, credentialed candidate preparation and final publication.
38
+ All protected checks and conversation requirements passed without bypass.
39
+
40
+ ## Published receipt and artifacts
41
+
42
+ [Tagged native receipt](https://github.com/dosquartsdedocs/unaltraweb/blob/v0.5.1/release-candidates.json):
43
+
44
+ ```text
45
+ schema_version: 1
46
+ release: v0.5.1
47
+ source_commit: aab5a7b030cd711b40770a3f44ad3a356eab90da
48
+ receipt SHA-256: 0e9d8f0589fa1ebf3aa067f0558523868fec29210927d1715f22e16e72cb30ec
49
+ ```
50
+
51
+ Exactly four ready components are recorded:
52
+
53
+ | Component | Published name / repository | SHA-256 / OCI repository digest |
54
+ | --- | --- | --- |
55
+ | Gem | `unaltraweb-0.5.1.gem` | `818bfbb53af4de16383a211e4224ab7ab77a2647afe8703f9c3f7c1ebd123c64` |
56
+ | Wheel | `unaltraweb_mcp-0.5.1-py3-none-any.whl` | `354bff5894073d66e064b5bcd0887c5963f58035ee2b1751b541722f345cf08f` |
57
+ | Base runtime | `ghcr.io/dosquartsdedocs/unaltraweb` | `sha256:3712453bf30289f02181cff0c095ecda563306e1d8a8f2a0e087c65ea9c8d730` |
58
+ | Full MCP | `ghcr.io/dosquartsdedocs/unaltraweb-mcp` | `sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692` |
59
+
60
+ The GitHub Release retains both packages and `SHA256SUMS`; that checksum file's
61
+ SHA-256 is `5cd3be237015841b65583b9b54b9df37c8a4b642e9231e6ee522d8d37d90821a`.
62
+ These are the newly downloaded workflow/publication bytes, not the earlier local
63
+ 0.5.1 candidates whose hashes appear in the follow-up report.
64
+
65
+ Native component selections retained unchanged:
66
+
67
+ - PDF 0.5.0:
68
+ `ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:9e0b3a45753c170b795e9a9d6df61580085c113436beac5bf6c8de69b6562097`.
69
+ - Python 0.4.0:
70
+ `ghcr.io/dosquartsdedocs/unaltraweb-compute-python@sha256:18cb269811bd4005800382da25a480ec2bca7eac8d0501ad1ef36bad1c0f8cd9`.
71
+ - R 0.4.0:
72
+ `ghcr.io/dosquartsdedocs/unaltraweb-compute-r@sha256:928ffb93f221e09e8b929157dee473b838e061915a2eb67224e4124b85f81837`.
73
+ - Web capture 0.4.0:
74
+ `ghcr.io/dosquartsdedocs/unaltraweb-web-capture@sha256:0bf1bc67fe63e1440bffe708a168beefa11c54441650a871ab99380d362f7c1e`.
75
+ - Diavisuals/Vegavisuals 0.4.0: the same BOM-selected hashed wheels and provider
76
+ receipt contract. Their exact references remain in `component-contract.json`.
77
+
78
+ The image workflow additionally built/tested a PDF verification candidate
79
+ `sha256:55c88a6e805f0612b8dced992868aab8443f077d72ecc9aaf7ff1bf862a154a6`.
80
+ It is not selected by the BOM, not included in this receipt, and was not promoted
81
+ as a 0.5.1 PDF component. The original 0.5.0 receipt remains at its existing tag,
82
+ with SHA-256 `e57a9dbb041c1e7fcd781cd1524f4de0317382e0f7303bb36bfa59c0b6d1cb9b`.
83
+
84
+ ## CI, signing and publication gates
85
+
86
+ | Gate | Successful run |
87
+ | --- | --- |
88
+ | Integration PR CI | [36780877307](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36780877307) |
89
+ | Integration PR CodeQL | [36780877311](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36780877311) |
90
+ | Integrated-source CI | [36785554970](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36785554970) |
91
+ | Signed image build, verification, tests | [36785858325](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36785858325) |
92
+ | Package preparation | [36785861424](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36785861424) |
93
+ | Receipt PR CI | [36788752930](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36788752930) |
94
+ | Receipt/tag target CI | [36789293544](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36789293544) |
95
+ | Tag CI | [36791298216](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36791298216) |
96
+ | Semver image promotion | [36791298413](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36791298413) |
97
+ | PyPI and RubyGems Trusted Publishing | [36791301396](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/36791301396) |
98
+
99
+ GitHub-signed OCI provenance was verified against the owner workflow and exact
100
+ source digest in the candidate and promotion jobs. Local inspection additionally
101
+ confirmed the OCI digests and source revision labels. The package workflow's
102
+ immutable artifact ID is `11129633290`, archive digest
103
+ `sha256:60a68862dcedec3747ed49112b66d10e697765a0ab5d6f249b33690aa5c5a3c5`.
104
+ The publication verifier bound that run, source, artifact inventory and checksums
105
+ to the receipt and annotated tag object before granting OIDC publishing authority.
106
+
107
+ Before promotion, both the actual receipt-only branch and merged tag target
108
+ passed `make distribution-release-check`. The merged `main` and then the annotated
109
+ tag passed `--require-release-ready --validate-publish-ref --components
110
+ gem,wheel,runtime,mcp,manual_pdf`. `verify_package_publish.py release` and exact
111
+ package staging also passed. The old receipt was never substituted as evidence
112
+ for the new version. Strict release validation refers to this receipt/tag
113
+ revision, not to later ordinary post-release source commits.
114
+
115
+ ## Populated-cache evidence
116
+
117
+ The previous final evidence was first rehashed at intake: gem, wheel and
118
+ `final-roundtrip/evidence.json` matched the follow-up report. All six preserved
119
+ files still matched in every profile, and the manual PDF matched its manifest.
120
+
121
+ The actual signed candidate and downloaded CI wheel then passed a new full
122
+ roundtrip in **all four profiles**: `unaltreselfie`, `unaltreprojecte`,
123
+ `unaltredocs`, `unaltremanual`.
124
+
125
+ 1. A real 0.4.0 build populated the generated lock with `google-protobuf 4.36.1`.
126
+ 2. Unpatched 0.5.0 failed as expected on a separate populated copy.
127
+ 3. The signed corrected full MCP passed two builds, preview and HTTP.
128
+ 4. Returning to the unchanged published 0.4.0 passed two builds, preview and HTTP.
129
+ 5. Gemfile, Gemfile.lock, Makefile, scaffold baseline and both historical generated
130
+ Gemfile/lock files retained their original SHA-256 values throughout.
131
+
132
+ New evidence:
133
+ `/tmp/opencode/unaltraweb-closeout-051/candidate-roundtrip/evidence.json`, SHA-256
134
+ `b5a2935359103983ff497760d8e9c367318ed9f77741ae1c5404a56449547179`.
135
+ An external recording wrapper ran the unchanged owner driver and retained the
136
+ manual tool responses plus PDF/cover bytes for both stages; it did not change
137
+ arguments, caches or runtime behavior.
138
+
139
+ | Manual artifact | SHA-256 |
140
+ | --- | --- |
141
+ | Corrected stage PDF | `203b39def968b644d1d0d3999827516e0e00aa8dd6b85202b33167d68dcb150e` |
142
+ | Return-0.4 PDF | `aba2802d4e0d978c8acc0cfbfc26a84607739b0953756a6bdb16fabbc43defa0` |
143
+ | Both stage covers | `afc3ba16ca919a7879f4629023e6316b77e31e56403e82edb7168f3181a3dc9d` |
144
+
145
+ The responses report `ok: true`, `publishes: false`; preview cleanup remained
146
+ receipt-bound. No cache was emptied to obtain a pass. The historical image
147
+ selections and reproduction command remain in `owner-followup-76.md`; this run
148
+ used the receipt's full MCP digest as `--fixed-image` and the downloaded CI wheel.
149
+
150
+ ## Public-download and installed acceptance
151
+
152
+ Artifacts are retained under `/tmp/opencode/unaltraweb-closeout-051/`:
153
+ `packages/`, `verified-packages/`, `published/`, `github-release/`,
154
+ `installed-candidate/`, `installed-published/`, and `candidate-roundtrip/`.
155
+
156
+ - Anonymous PyPI and RubyGems downloads match the receipt exactly; metadata and
157
+ downloaded bytes were independently compared.
158
+ - Both `0.5.1` and `v0.5.1` GHCR aliases were checked with an empty Docker client
159
+ configuration and match the expected OCI index digests.
160
+ - GitHub Release assets were downloaded again and pass their `SHA256SUMS`.
161
+ - The public wheel was installed non-editably in a new venv. Its default
162
+ `prepare`/`check` selects and runs MCP 0.5.1 without a local core.
163
+ - The public gem installs into an isolated gem home and activates as 0.5.1 using
164
+ the image's preinstalled Ruby dependencies. An initial probe artificially
165
+ omitted standard gem paths and failed to find `rexml`; retaining `Gem.path`
166
+ corrected the probe. This is not a claim of a network-fresh dependency install.
167
+ - The host's older Buildx did not render the requested digest-only template;
168
+ anonymous verification instead checked the exact top-level `Digest:` field.
169
+ - Closeout source tests reported **562 cases, 532 passed, 30 optional skips**;
170
+ distribution, workflow, wheel and prose checks passed. CI additionally ran its
171
+ Python matrix, Ruby, PDF, MCP, reproducibility and docs gates.
172
+ - The post-pin local recheck reported **562 cases, 533 passed, 29 optional skips**
173
+ after the public image became available. Distribution, workflow, wheel,
174
+ `mcp-check`, `mcp-smoke`, docs build and diff gates passed with isolated
175
+ `unaltraweb-closeout-051-*:post-pin` tags and a fresh smoke fixture. The smoke
176
+ used the selected published PDF digest. These local development builds do not
177
+ replace the published release artifacts.
178
+
179
+ Observed local configuration IDs (distinct from OCI repository digests):
180
+ runtime `sha256:5c406a7981118203070517b6689f2f4f03ac7fd2b5626b52ed96fe14009d67b9`;
181
+ full MCP `sha256:e7b2bd34751c2d3a30f9974f46c64e30a1a2fbd9ba412279234a5f24ff197eda`.
182
+
183
+ ## Post-release pin and remaining adoption scope
184
+
185
+ The post-release source change on `chore/76-pin-published-mcp-0.5.1` accompanies
186
+ this report. `Makefile` and `scripts/unaltraweb-mcp-bootstrap.sh` select
187
+ `ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692`;
188
+ the pin regression and current documentation are updated. Its PR/merge and final
189
+ clean-main confirmation are recorded in issue 76 after protected CI completes.
190
+ Published packages, receipt and tag are not rebuilt by this source update.
191
+
192
+ An actual `MCP_CONSUMER_WORKSPACE`-bound `make mcp-stdio` session was launched from
193
+ the post-pin checkout against a new empty synthetic consumer. Initialize and
194
+ `detect_site` succeeded, and Docker inspection proved the session used the public
195
+ MCP configuration ID `sha256:e7b2bd34751c2d3a30f9974f46c64e30a1a2fbd9ba412279234a5f24ff197eda`.
196
+ The temporary session exited cleanly. The post-pin `mcp-build` and bootstrap
197
+ `--check` also selected the published image without rebuilding it.
198
+
199
+ The installed package already selects its own release; existing MCP processes
200
+ keep their image until reconnected. No real manual, client registration or shared
201
+ authoring worker was migrated. Historical Makefile adaptation remains restricted
202
+ to matching baselines; customized Makefiles require explicit owner integration.
203
+ The accepted evidence covers these exact Linux/amd64 tuples, not an untested
204
+ version interval or architecture. No new H1 fields were introduced. Consumer
205
+ adoption and central catalogue integration remain their own later sessions.
@@ -0,0 +1,231 @@
1
+ # Native retained-letter import — issue 80
2
+
3
+ ## Scope and release state
4
+
5
+ This is a separate 0.6.0 development increment after the administrative closeout
6
+ of issue 76. Gem, wheel, runtime, MCP and PDF worker are pending. The 0.5.1 release,
7
+ receipt and active checkout launcher pin remain unchanged. Consumer core/PDF
8
+ integration and publication need their own reviewed immutable selections. The
9
+ tested computation, capture and visual companion selections remain 0.4.0.
10
+
11
+ The native receiver accepts Carta 0.3.0rc1 leaf `letter-pdf-v1` units. It retains
12
+ the entire bundle, maps the original PDF byte for byte, creates a native draft
13
+ page/chapter and checks its source and rendered references. The manual PDF
14
+ builder includes all pages with `pdfpages`; every retained dependency and checker
15
+ contributes to freshness. Nothing executes the retained producer recipe.
16
+ Composite profiles, edited PDF variants and Diapora are outside this acceptance.
17
+
18
+ ## Protocol and provenance
19
+
20
+ The wire v1 verifier and schema are byte-identical copies pinned to hub revision
21
+ `9167e3efb5968a64bb9100792163a179c1491860` (integration
22
+ `fc8745db950b04013c73eb49acf6781a26eb83f8`). Their respective SHA-256 values are
23
+ `48368035f242f4d4446cbbe1363f8a01a7c17fa164ffef21abadd878b288d82d` and
24
+ `b52a32b3bcfeed28cf34a9ec1557665a94466b51c451ccad47d2e87f6e23f9aa`.
25
+ No envelope fields were added. `binding.json` is a separate native record.
26
+ The integration actor identifies the importer by a hash of its code inventory,
27
+ not an invented or uncommitted Git revision.
28
+
29
+ Acceptance uses the final published
30
+ [Carta v0.3.0rc1 packet](https://github.com/dosquartsdedocs/unaltracarta/releases/tag/v0.3.0rc1),
31
+ revision `84258b6869689ea5f1a49a55abc2b865573fb512`:
32
+
33
+ | Artifact | SHA-256 |
34
+ | --- | --- |
35
+ | `distribution.json` | `9d94b918db086b445e4d8a3ece2435622e0f9f9893bcd50708b4d13f5ca0ad44` |
36
+ | `acceptance-0.3.0rc1.json` | `1bc7c467f3e35abf9fa5c27583dd8cc3ad4d4372f930c4be60ed142122158504` |
37
+ | `acceptance-0.3.0rc1.tar.gz` | `8764a717bda33e15b48b3a06fe6fbe5dc075abedf4fd52bd37fdf4ed70896179` |
38
+ | Published wheel | `0afab176ea0815d242f6e19021232bafdc63f9bb68cbacbd63b73f99b666b7c3` |
39
+ | Wheel bundle manifest | `aeaa757ee1be19bfe56dc9af8dd1178032929b4a2bec2dad2ebb621b158ad999` |
40
+ | Retained original PDF | `4a661740a18fe1cf75b84aa0d8532511fd105eb5484a5af700e11e8e30828ea4` |
41
+
42
+ The original producer job was
43
+ `.unaltracarta-handoff/jobs/a0794f7909a943eb844c87bb14002691/bundle/`.
44
+ Its renderer identity is
45
+ `sha256:ba2453fb42542433f68efd8888d628b95f256cefb9c545b3b35034d33296e340`.
46
+ The installed test authenticates the packet before bounded extraction and checks
47
+ every declared evidence file. Earlier release-candidate bytes are not inputs.
48
+
49
+ ## Installed acceptance
50
+
51
+ `test/artifact_import_smoke.py` uses a wheel-installed CLI and Docker launcher,
52
+ without a host factory dependency. It creates a synthetic manual, imports the
53
+ published wheel bundle, edits surrounding prose, verifies an identical reimport
54
+ preserves that prose and removes both the extracted producer copy and incoming
55
+ copy. It then builds the web and PDF, checks the served page/PDF, moves the
56
+ receiver, runs both native and generic v1 checks, and explicitly rebuilds the
57
+ PDF in the moved receiver. Every original page must occur in order in the
58
+ composed PDF; comparison uses the original font encoding, including ligatures.
59
+
60
+ The passing local run is retained at
61
+ `/tmp/opencode/unaltraweb-import-80/installed-proof-final/evidence.json`.
62
+ Its receiver is `relocated-receiver/` in that directory. This is local owner
63
+ evidence from development images, not a signed release receipt.
64
+
65
+ | Tested identity | Value |
66
+ | --- | --- |
67
+ | Installed unaltraweb wheel SHA-256 | `407b1275d1de558da891f391454287d1b3e76fbef0e45460695e9731932b9e39` |
68
+ | Controller image ID | `sha256:81f1da616455c7378ba3400b9d638eb8e67fce9605f18353d49a796020d9b6fa` |
69
+ | PDF worker image ID | `sha256:b7b8f5b774a528cadb2ab7aa313b9ddbffa6d54c9d3b42bd6ff59a664be8ccf6` |
70
+ | Integration record SHA-256 | `79ede9c8701eedf6ca4f182dc4fd1c9df3b56581138c677e0315310d8b998d1c` |
71
+ | Composed PDF before and after relocation | `14b0ef586874704b6d1b045d6dde1f32ee08c8a9107006e06cfe2e8147f54621` |
72
+
73
+ The receiver retains all 12 seal files under
74
+ `.unaltraweb/artifacts/carta/bundle/`. Its mapping is
75
+ `payload/output/letter.pdf` → `assets/documents/carta.pdf`, with native content at
76
+ `_chapters/en/carta.md` and permalink `/en/retained/carta/` under `/letter-proof`.
77
+ The original one-page letter appears on page 10 of the 11-page composed manual.
78
+ Both web/HTTP checks passed; the non-web archive was absent from `_site`.
79
+ Generic verification after relocation passed with one bundle, one mapping and
80
+ 14 verified files. Preview copies were cleaned through their exact receipts.
81
+
82
+ Intermediate failures are retained separately: missing explicit gem plugin
83
+ registration, an overly broad rendered-HTML scan, mismatched controller/worker
84
+ checker bytes, and an assertion that ignored the original PDF's ligature
85
+ encoding. Corrections preserve strict integrity/freshness gates. In particular,
86
+ the installed-image fixture force-reinstalls its supplied wheel even when its
87
+ development version equals the base image's version.
88
+
89
+ ## Reproduction and boundaries
90
+
91
+ Prepare an installed wheel, the matching source-containing MCP image, and a PDF
92
+ worker built from the repository root with `scripts/manual/Dockerfile`. The test
93
+ controller in `test/artifact_import.Dockerfile` binds `MANUAL_PDF_IMAGE` to the
94
+ worker image ID. Then run:
95
+
96
+ ```bash
97
+ python test/artifact_import_smoke.py \
98
+ --packet "$PUBLISHED_CARTA_PACKET" --output "$NEW_EVIDENCE_DIRECTORY" \
99
+ --cli "$INSTALLED/bin/unaltraweb-mcp" \
100
+ --launcher "$INSTALLED/bin/unaltraweb-mcp-docker" \
101
+ --image "$TEST_CONTROLLER" --pdf-image "$TEST_PDF_WORKER"
102
+ ```
103
+
104
+ The output directory must not exist. Only copies created by the test are retired.
105
+ Unit-test bundles in `test/test_artifact_imports.py` are synthetic security and
106
+ transaction fixtures, not published-producer acceptance. They cover tampering,
107
+ incomplete resources, hidden references, symlinks/hardlinks, no-overwrite,
108
+ interruption/retry, generated-source ownership, PDF action aliases/chains,
109
+ rendered URL binding, native PDF inclusion and dependency closure.
110
+
111
+ The imported unit is portable because its seal, record, mapped PDF and content
112
+ all use receiver-relative paths. The integration does not depend on the incoming
113
+ directory, producer process, absolute source location or ignored recovery tree.
114
+ Failed publication retains prepared and partial files; there is no destructive
115
+ rollback. Reimport adopts only identical existing bytes and preserves authored
116
+ prose when the binding remains valid.
117
+
118
+ Final release gates must additionally bind the reviewed core/PDF consumer tuple
119
+ and same-source package/image candidates. A local acceptance run does not update
120
+ those pins, authenticate a public 0.6.0 release, authorize real-manual adoption,
121
+ or grant author approval to the draft content.
122
+
123
+ The gem and PDF worker include a regular Python package initializer and its
124
+ stdlib-only version/contract module. This prevents an unrelated installed wheel
125
+ from shadowing the gem's helpers. The extracted-gem gate asserts the actual
126
+ module paths. Checker code and schemas enter PDF freshness; the validated BOM's
127
+ worker/self pins do not, avoiding a worker that would need to contain its own
128
+ future digest. The integration actor separately hashes the full BOM metadata.
129
+
130
+ ## Owner regression gates
131
+
132
+ - Python suite: 584 tests, 30 environment-dependent skips, no failures. The
133
+ focused importer suite covers 22 cases; the PDF builder suite covers 88.
134
+ - Ruby plugin suites: 64 tests and 334 assertions, no failures.
135
+ - Actual PDF toolchain integrations: 16 tests, no failures.
136
+ - `distribution-check`, `workflow-check`, `wheel-check`, `gem-check`,
137
+ `mcp-check`, `mcp-smoke`, `docs-build`, and fixed-epoch
138
+ `reproducible-site-check` passed on local owner resources. Distribution remains
139
+ structurally valid and explicitly not release-ready.
140
+ - The extracted-gem package gate exercises synthetic native retention using only
141
+ the gem's Python helper closure, with isolated Python and no wheel/core path.
142
+ Native deployment installs its parser dependencies before PDF/Jekyll checks.
143
+ - Populated Bundler roundtrip passed for `unaltreselfie`, `unaltreprojecte`,
144
+ `unaltredocs` and `unaltremanual`, with two builds and a preview per runtime.
145
+ It first reproduces the published unpatched 0.5.0 `google-protobuf (4.36.1)`
146
+ failure on a separate copy, then tests 0.4.0 → development 0.6.0 → 0.4.0.
147
+ The historical driver labels its patched step `fixed-050`; the recorded
148
+ image is the 0.6.0 test controller. All six retained author/cache paths keep
149
+ their initial hashes; no cache cleaning is used to obtain a pass.
150
+
151
+ Roundtrip evidence is retained at
152
+ `/tmp/opencode/unaltraweb-import-80/bundler-roundtrip-final/evidence.json`, using
153
+ the same final controller and worker IDs as the installed letter acceptance.
154
+ The source discovery descriptor additionally declares `.unaltraweb/artifacts`
155
+ as optional versioned source state with `cleanup: never`; `tmp` keeps its existing
156
+ ignored, explicit-cleanup policy. This final metadata-only addition is checked by
157
+ the path-policy and fresh-wheel gates and does not alter the tested import code.
158
+
159
+ ## Closeout review — 2026-10-02
160
+
161
+ The owner explicitly authorized the full 0.6.0 commit/PR/integration, signed
162
+ candidate, gated publication and post-release pin flow. The session preflight
163
+ reported only the known unit-80 working tree and no competing session. Review
164
+ covered every tracked/untracked unit path; no unrelated changes were identified.
165
+
166
+ The two vendored protocol files match the exact established Git pin. The pinned
167
+ reference tests and fixture payloads were also checked (the later fixture README
168
+ only renames the integrated contract), and all 26 conformance tests pass. These
169
+ generic synthetic tests do not add a composite domain to the native importer.
170
+ The retained installed wheel/PDF hashes above and the moved receiver's native
171
+ web/PDF mapping were independently rechecked before editing.
172
+
173
+ Resolved review findings:
174
+
175
+ - Metadata could contain a local link or image while retained Pandoc evidence
176
+ remained stale. Renderable metadata now receives the independent text-reference
177
+ check; effective metadata rejects render-option fields outside the supported
178
+ author/stamp projection. Malformed Pandoc link evidence returns a structured
179
+ domain failure instead of an uncaught indexing error.
180
+ - A PDF OpenAction internal destination array was treated as an action array.
181
+ Internal destinations are supported while chained action arrays retain their
182
+ stricter checks. Regression tests cover both cases.
183
+ - The acceptance driver required a derived test-controller image. It now also
184
+ verifies the immutable PDF selection declared by the actual installed MCP image
185
+ and records the exact image references and source label, allowing signed bytes
186
+ to be exercised directly.
187
+
188
+ The corrected source passes 587 Python tests (30 optional skips), including 25
189
+ native import cases, plus distribution/workflow/fresh-wheel gates. The historical
190
+ local evidence above remains retained; signed-candidate and public-download
191
+ acceptance must record their own revisions and hashes. The consumer core/PDF
192
+ tuple is closed only after the reviewed integrated core and signed PDF digest
193
+ exist; no guessed source or self-digest is inserted into the BOM.
194
+
195
+ ## Reviewed immutable consumer tuple
196
+
197
+ PR [81](https://github.com/dosquartsdedocs/unaltraweb/pull/81) integrated reviewed
198
+ implementation `7af652fb83629e959af05c407a34a2f5a15f7936` as
199
+ `5cf9817489c8dc47cee726bfe42fe3071cd32b85`. Protected PR CI
200
+ [37027921742](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37027921742)
201
+ and CodeQL [37027922332](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37027922332)
202
+ passed, followed by integrated-source CI
203
+ [37028677932](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37028677932)
204
+ and CodeQL [37028678347](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37028678347).
205
+ The PR contains an explicit agent review, not an attributed human approval.
206
+
207
+ Signed image workflow
208
+ [37029374441](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37029374441)
209
+ then published, attested and tested the PDF from that exact source. Its read-only
210
+ test job verified the signer workflow/source digest before executing the exact
211
+ image, including 16 PDF integrations and real MCP preparation. The selected
212
+ PDF 0.6.0 identity is
213
+ `ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed`.
214
+ The BOM and Make contract now select that same digest and integrated core SHA.
215
+
216
+ That public signed PDF is recorded as `released` and reused by digest. The four
217
+ core/package components are `ready` for final same-commit candidates; their strict
218
+ gate still requires a new receipt-only child of the final artifact source.
219
+ Subsequent verification-only PDF builds are not substituted for this selected
220
+ worker or promoted under an assumed identity. The earlier 0.5.1 receipt and
221
+ active launcher pin remain intact until the authorized 0.6.0 closeout completes.
222
+
223
+ The tuple was exercised before its pin PR using an installed wheel and a local
224
+ MCP containing the new BOM with the actual signed PDF above. Evidence is retained
225
+ at `/tmp/opencode/unaltraweb-closeout-060/tuple-letter-proof/evidence.json`:
226
+ integration `ebe07ee10ad740a2bbbd36d532f336374cf4bb19ccb373b6590b2279f664a222`,
227
+ composed PDF `416e96f66bb6608b1e20bf5e36b6b16133bd4018c17e6c079e8987b736fe9cae`
228
+ both before and after the forced relocated rebuild. The PDF's inspected local
229
+ image ID is `sha256:d7e7d3243616270fc9e6eed7f8238c412dbe3d9ffc18d2832d17d66ca630d139`,
230
+ with the exact integrated source revision label. This preparation proof does not
231
+ substitute for the final signed MCP and downloaded package acceptance.
data/lib/unaltraweb.rb CHANGED
@@ -21,6 +21,7 @@ require_relative "unaltraweb/version"
21
21
  content_search_index
22
22
  manual_release_metadata
23
23
  reproducible_build_time
24
+ retained_documents
24
25
  profile-pages
25
26
  remove-accents
26
27
  search-data
data/requirements.txt CHANGED
@@ -3,3 +3,5 @@ scholarly
3
3
  requests
4
4
  bibtexparser
5
5
  rdata
6
+ pypdf>=6,<7
7
+ markdown-it-py>=3,<5
@@ -23,9 +23,12 @@ RUN printf '%s\n' \
23
23
  && rm -rf /var/lib/apt/lists/* \
24
24
  && pip install --no-cache-dir PyYAML==6.0.2
25
25
 
26
- COPY build_pdf.py /opt/unaltraweb/manual/build_pdf.py
27
- COPY Dockerfile /opt/unaltraweb/manual/Dockerfile
28
- COPY filters /opt/unaltraweb/manual/filters
29
- COPY templates /opt/unaltraweb/manual/templates
26
+ RUN pip install --no-cache-dir 'pypdf>=6,<7' 'markdown-it-py>=3,<5'
27
+ COPY scripts/manual/build_pdf.py /opt/unaltraweb/manual/build_pdf.py
28
+ COPY scripts/manual/Dockerfile /opt/unaltraweb/manual/Dockerfile
29
+ COPY scripts/manual/filters /opt/unaltraweb/manual/filters
30
+ COPY scripts/manual/templates /opt/unaltraweb/manual/templates
31
+ COPY src/unaltraweb_mcp/__init__.py src/unaltraweb_mcp/distribution.py src/unaltraweb_mcp/component-contract.json src/unaltraweb_mcp/component-contract.schema.json src/unaltraweb_mcp/artifact_handoff_v1.py src/unaltraweb_mcp/artifact-handoff-v1.schema.json src/unaltraweb_mcp/artifact_imports.py src/unaltraweb_mcp/letter_bundle.py src/unaltraweb_mcp/pdf_probe.py src/unaltraweb_mcp/processes.py /opt/unaltraweb/src/unaltraweb_mcp/
32
+ ENV PYTHONPATH=/opt/unaltraweb/src
30
33
 
31
34
  ENTRYPOINT ["python3", "/opt/unaltraweb/manual/build_pdf.py"]
@@ -26,6 +26,10 @@ except ImportError as exc: # pragma: no cover - supplied by the builder image
26
26
 
27
27
 
28
28
  SCRIPT_ROOT = Path(__file__).resolve().parent
29
+ for _source_root in (SCRIPT_ROOT.parent.parent / "src", SCRIPT_ROOT.parent / "src"):
30
+ if (_source_root / "unaltraweb_mcp" / "artifact_imports.py").is_file():
31
+ sys.path.insert(0, str(_source_root))
32
+ break
29
33
  DEFAULT_DOCKERFILE = SCRIPT_ROOT / "Dockerfile"
30
34
  DEFAULT_TEMPLATE = SCRIPT_ROOT / "templates" / "manual.tex"
31
35
  DEFAULT_BIBLIOGRAPHY_FILTER = SCRIPT_ROOT / "filters" / "bibliography.lua"
@@ -36,6 +40,7 @@ BIB_CUSTOM_URL_RE = re.compile(r'(?im)^\s*(?:manual_url|website)\s*=\s*(?:\{([^}
36
40
  FRONT_MATTER_RE = re.compile(r"\A---[ \t]*\r?\n(.*?)^---[ \t]*(?:\r?\n|\Z)", re.MULTILINE | re.DOTALL)
37
41
  CITE_RE = re.compile(r"{%\s*cite\s+([^%]+?)\s*%}")
38
42
  INCLUDE_RE = re.compile(r"{%\s*include\s+([^%]+?)\s*%}")
43
+ RETAINED_DOCUMENT_RE = re.compile(r"{%\s*retained_document\s+([a-z][a-z0-9-]{0,63})\s*%}")
39
44
  LIQUID_RE = re.compile(r"({[{%].*?[}%]})", re.DOTALL)
40
45
  INLINE_CODE_RE = re.compile(r"<code>(.*?)</code>", re.IGNORECASE | re.DOTALL)
41
46
  FENCED_CODE_BLOCK_RE = re.compile(r"^[ \t]*(`{3,}|~{3,})[^\n]*\n.*?^[ \t]*\1[ \t]*$", re.MULTILINE | re.DOTALL)
@@ -947,6 +952,17 @@ def transform_markdown(
947
952
  citation_keys.extend(key for key in keys if key not in citation_keys)
948
953
  return "[" + "; ".join(f"@{key}" for key in keys) + "]"
949
954
 
955
+ def retained_document(match: re.Match[str]) -> str:
956
+ from unaltraweb_mcp.artifact_imports import check_imports
957
+
958
+ result = check_imports(project, match.group(1))
959
+ if result.get("ok") is not True:
960
+ raise ManualPdfError(f"Retained document verification failed: {result.get('error')}")
961
+ path = result["imports"][0]["pdf"]
962
+ # The native import layout uses an ASCII slug and fixed project-relative
963
+ # path; no bundle text is interpolated into TeX or executed.
964
+ return protect("```{=latex}\n\\includepdf[pages=-,pagecommand={}]" + "{" + path + "}\n```")
965
+
950
966
  def table(match: re.Match[str]) -> str:
951
967
  body = match.group("body").strip()
952
968
  credit, _ = caption_source_attribute(match.group("attrs") or "")
@@ -1137,6 +1153,7 @@ def transform_markdown(
1137
1153
  transformed = transformed.replace(r"\begin{equation\*}", r"\begin{equation*}")
1138
1154
  transformed = transformed.replace(r"\end{equation\*}", r"\end{equation*}")
1139
1155
  transformed = BASEURL_RE.sub("", transformed)
1156
+ transformed = RETAINED_DOCUMENT_RE.sub(retained_document, transformed)
1140
1157
  transformed = transformed.replace("{% include manual-bibliography.liquid %}", "::: {#refs}\n:::")
1141
1158
  transformed = CITE_RE.sub(citations, transformed)
1142
1159
  transformed = CALLOUT_BLOCK_RE.sub(callout, transformed)
@@ -1481,6 +1498,17 @@ def build_dependencies(project: Path, metadata: dict[str, Any], source_paths: li
1481
1498
  ]
1482
1499
  for path in source_paths:
1483
1500
  dependencies.append((f"source:{path.relative_to(project)}", path))
1501
+ if any(RETAINED_DOCUMENT_RE.search(path.read_text(encoding="utf-8")) for path in source_paths if path.suffix.lower() == ".md"):
1502
+ from unaltraweb_mcp import artifact_imports
1503
+
1504
+ imports = artifact_imports.check_imports(project)
1505
+ if imports.get("ok") is not True:
1506
+ raise ManualPdfError(f"Retained document verification failed: {imports.get('error')}")
1507
+ for item in imports["imports"]:
1508
+ dependencies.extend((f"retained:{relative}", project / relative) for relative in item["inputs"])
1509
+ checker_root = Path(artifact_imports.__file__).parent
1510
+ for name in artifact_imports.CHECKER_FILES:
1511
+ dependencies.append((f"import-check:{name}", checker_root / name))
1484
1512
  if csl:
1485
1513
  dependencies.append((f"csl:{csl.relative_to(project)}", csl))
1486
1514
  for key in ["cover-image", "cover-logo", "series-logo"]:
@@ -10,6 +10,7 @@
10
10
  \usepackage{float}
11
11
  \usepackage{framed}
12
12
  \usepackage{graphicx}
13
+ \usepackage{pdfpages}
13
14
  \usepackage{grffile}
14
15
  \usepackage{longtable}
15
16
  \usepackage{array}
@@ -64,6 +64,9 @@ def inspect_gem(path: Path) -> None:
64
64
  editorial_files = ["scripts/editorial_check.py", "src/unaltraweb_mcp/editorial.py", "src/unaltraweb_mcp/editorial_sources.py"]
65
65
  inspection_files = editorial_files + ["src/unaltraweb_mcp/bundler_runtime.py", "scripts/image_background_check.py", "src/unaltraweb_mcp/image_backgrounds.py",
66
66
  "src/unaltraweb_mcp/image_probe.py", "src/unaltraweb_mcp/processes.py"]
67
+ inspection_files += [f"src/unaltraweb_mcp/{name}" for name in (
68
+ "__init__.py", "distribution.py", "component-contract.json", "component-contract.schema.json",
69
+ "artifact_imports.py", "artifact_handoff_v1.py", "artifact-handoff-v1.schema.json", "letter_bundle.py", "pdf_probe.py")]
67
70
  with tarfile.open(path, mode="r") as package:
68
71
  data_member = package.extractfile("data.tar.gz")
69
72
  if data_member is None:
@@ -83,6 +86,7 @@ def inspect_gem(path: Path) -> None:
83
86
  "_plugins/figure_captions.rb",
84
87
  "_plugins/manual_release_metadata.rb",
85
88
  "_plugins/reproducible_build_time.rb",
89
+ "_plugins/retained_documents.rb",
86
90
  "assets/js/content-search-match.js",
87
91
  "assets/js/content-search.js",
88
92
  "_config.yml",
@@ -134,6 +138,29 @@ def inspect_gem(path: Path) -> None:
134
138
  inspection = json.loads(run(image_command, cwd=site).stdout)
135
139
  if not inspection["ok"] or inspection["images"][0]["state"] != "transparent" or not inspection["warnings"]:
136
140
  raise RuntimeError(f"Gem-native SVG background inspection failed: {inspection}")
141
+ # This is the synthetic domain fixture, not published-Carta acceptance.
142
+ # Only its data crosses into the isolated extracted-gem subprocess.
143
+ sys.path.insert(0, str(ROOT / "test"))
144
+ from test_artifact_imports import fixture
145
+
146
+ bundle_sha, template_sha = fixture(site / "incoming/letter")
147
+ (site / ".gitignore").write_text("tmp/\n", encoding="utf-8")
148
+ run(["git", "init", "--quiet"], cwd=site)
149
+ isolated = """
150
+ import json, sys
151
+ from pathlib import Path
152
+ sys.path.insert(0, sys.argv[1])
153
+ from unaltraweb_mcp import artifact_imports, letter_bundle, artifact_handoff_v1, distribution, processes
154
+ for module in (artifact_imports, letter_bundle, artifact_handoff_v1, distribution, processes):
155
+ assert Path(module.__file__).is_relative_to(Path(sys.argv[1])), module.__file__
156
+ letter_bundle.TEMPLATES['default-letter.latex'] = sys.argv[4]
157
+ project = Path(sys.argv[2])
158
+ result = artifact_imports.import_bundle(project, 'incoming/letter/bundle.json', sys.argv[3],
159
+ 'letter', '_pages/en/letter.md', dry_run=False, confirm_import=True)
160
+ print(json.dumps(result))
161
+ raise SystemExit(0 if result['ok'] else 1)
162
+ """
163
+ run([sys.executable, "-I", "-c", isolated, str(core / "src"), str(site), bundle_sha, template_sha], cwd=site)
137
164
 
138
165
 
139
166
  def main() -> int:
@@ -90,6 +90,11 @@ def main() -> int:
90
90
  required = [
91
91
  "unaltraweb_mcp/calibre_import.py",
92
92
  "unaltraweb_mcp/bundler_runtime.py",
93
+ "unaltraweb_mcp/artifact_imports.py",
94
+ "unaltraweb_mcp/artifact_handoff_v1.py",
95
+ "unaltraweb_mcp/artifact-handoff-v1.schema.json",
96
+ "unaltraweb_mcp/letter_bundle.py",
97
+ "unaltraweb_mcp/pdf_probe.py",
93
98
  "unaltraweb_mcp/component-contract.json",
94
99
  "unaltraweb_mcp/component-contract.schema.json",
95
100
  "unaltraweb_mcp/manual_pdf_preview.py",
@@ -12,7 +12,7 @@ If --project is omitted, MCP_CONSUMER_WORKSPACE is used, then the current direct
12
12
  USAGE
13
13
  }
14
14
 
15
- image="${UNALTRAWEB_MCP_IMAGE:-ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:36d17edbade77edb40a687f6a744203c6329acb33fbc2eb255e88d9ff1a42c98}"
15
+ image="${UNALTRAWEB_MCP_IMAGE:-ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692}"
16
16
  project="${MCP_CONSUMER_WORKSPACE:-${UNALTRAWEB_PROJECT:-}}"
17
17
  operation=serve
18
18
 
@@ -0,0 +1,4 @@
1
+ from .distribution import distribution_version
2
+
3
+
4
+ __version__ = distribution_version()