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.
- checksums.yaml +4 -4
- data/Makefile +6 -6
- data/_plugins/retained_documents.rb +62 -0
- data/docs/_documentation/en/40-distribution.md +55 -16
- data/docs/_documentation/en/45-retained-documents.md +138 -0
- data/docs/agents/mcp-contract.md +36 -1
- data/docs/agents/owner-closeout-76.md +205 -0
- data/docs/agents/retained-letter-import.md +231 -0
- data/lib/unaltraweb.rb +1 -0
- data/requirements.txt +2 -0
- data/scripts/manual/Dockerfile +7 -4
- data/scripts/manual/build_pdf.py +28 -0
- data/scripts/manual/templates/manual.tex +1 -0
- data/scripts/test_gem_build.py +27 -0
- data/scripts/test_wheel_install.py +5 -0
- data/scripts/unaltraweb-mcp-bootstrap.sh +1 -1
- data/src/unaltraweb_mcp/__init__.py +4 -0
- data/src/unaltraweb_mcp/artifact-handoff-v1.schema.json +102 -0
- data/src/unaltraweb_mcp/artifact_handoff_v1.py +435 -0
- data/src/unaltraweb_mcp/artifact_imports.py +368 -0
- data/src/unaltraweb_mcp/component-contract.json +20 -20
- data/src/unaltraweb_mcp/distribution.py +887 -0
- data/src/unaltraweb_mcp/letter_bundle.py +223 -0
- data/src/unaltraweb_mcp/pdf_probe.py +63 -0
- metadata +13 -2
|
@@ -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
data/requirements.txt
CHANGED
data/scripts/manual/Dockerfile
CHANGED
|
@@ -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
|
-
|
|
27
|
-
COPY
|
|
28
|
-
COPY
|
|
29
|
-
COPY
|
|
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"]
|
data/scripts/manual/build_pdf.py
CHANGED
|
@@ -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"]:
|
data/scripts/test_gem_build.py
CHANGED
|
@@ -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:
|
|
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
|
|