unaltraweb 0.5.0 → 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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +18 -11
  3. data/README.md +4 -4
  4. data/_plugins/retained_documents.rb +62 -0
  5. data/docs/_documentation/en/02-tools.md +3 -3
  6. data/docs/_documentation/en/32-development.md +1 -1
  7. data/docs/_documentation/en/40-distribution.md +157 -12
  8. data/docs/_documentation/en/42-docker-image.md +7 -7
  9. data/docs/_documentation/en/45-retained-documents.md +138 -0
  10. data/docs/agents/mcp-contract.md +64 -2
  11. data/docs/agents/owner-closeout-76.md +205 -0
  12. data/docs/agents/owner-followup-76.md +144 -0
  13. data/docs/agents/owner-preparation-2026-09-29.md +254 -0
  14. data/docs/agents/retained-letter-import.md +231 -0
  15. data/docs/agents/visual-companions-0.4.0.md +5 -0
  16. data/lib/unaltraweb.rb +1 -0
  17. data/requirements.txt +2 -0
  18. data/scripts/manual/Dockerfile +7 -4
  19. data/scripts/manual/build_pdf.py +28 -0
  20. data/scripts/manual/templates/manual.tex +1 -0
  21. data/scripts/test_gem_build.py +28 -1
  22. data/scripts/test_wheel_install.py +51 -0
  23. data/scripts/unaltraweb-mcp-bootstrap.sh +33 -6
  24. data/scripts/validate_distribution.py +21 -2
  25. data/src/unaltraweb_mcp/__init__.py +4 -0
  26. data/src/unaltraweb_mcp/artifact-handoff-v1.schema.json +102 -0
  27. data/src/unaltraweb_mcp/artifact_handoff_v1.py +435 -0
  28. data/src/unaltraweb_mcp/artifact_imports.py +368 -0
  29. data/src/unaltraweb_mcp/bundler_runtime.py +214 -0
  30. data/src/unaltraweb_mcp/component-contract.json +20 -20
  31. data/src/unaltraweb_mcp/distribution.py +887 -0
  32. data/src/unaltraweb_mcp/letter_bundle.py +223 -0
  33. data/src/unaltraweb_mcp/pdf_probe.py +63 -0
  34. metadata +16 -2
@@ -16,13 +16,34 @@ MCP_CONSUMER_WORKSPACE="$PWD" make --silent --no-print-directory -C /path/to/una
16
16
 
17
17
  Replace `/path/to/unaltraweb` with the checkout's absolute path. The bootstrap canonicalizes the inherited environment value after process launch; neither Make nor generated shell source evaluates consumer path text. The declared launcher remains `make`, which gContExt permits for a container runtime without a `runtime.allowed_host_launchers` exception. Restart clients such as OpenCode after changing their MCP registration.
18
18
 
19
+ Released 0.5.1 wheels also install this native descriptor and its complete host
20
+ helper closure under `share/unaltraweb-launcher`. For that installed profile,
21
+ `${factoryRoot}` is the path returned by `unaltraweb-mcp-docker path`, rather than
22
+ a core checkout. Its small Makefile implements `mcp-build`, `mcp-check`,
23
+ `mcp-smoke`, `mcp-stdio` and `mcp-down` against the selected released image;
24
+ it cannot build checkout images. `unaltraweb-mcp-docker serve --project PATH`
25
+ is the direct installed entry point. Preparation may pull, whereas check/smoke
26
+ require a locally prepared image and use no consumer or Docker socket mount.
27
+ The copied schema-v1 descriptor retains the same server, workspace, inventory
28
+ and dependency identities. The released 0.5.0 wheel lacks these host assets;
29
+ the full 0.5.0 GHCR runtime already supports the operations they launch.
30
+ The installed profile selects its own BOM release image by default and resolves
31
+ it to an image ID before execution. The source checkout's digest pin is separate:
32
+ it advances only after a new receipt exists. Explicit `--image` (or the console
33
+ adapter's `UNALTRAWEB_MCP_IMAGE`) permits a reviewed immutable selection.
34
+
35
+ The post-release checkout pin selects published 0.5.1 MCP digest
36
+ `sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692`.
37
+ Existing processes keep their running image until clients reconnect. Site build
38
+ defaults and customized Makefiles remain separate, explicitly reviewed selections.
39
+
19
40
  gContExt dependency preparation ensures the selected MCP release image and prepares required companions but does not initialize consumer content. The transport passes `${workspaceFolder}` only through `MCP_CONSUMER_WORKSPACE`; it never sets `transport.cwd` or embeds the consumer path in a Make assignment. The factory command may therefore use `make -C` without changing or reparsing the selected consumer root. Companion-aware checks and smoke tests include both required providers, while provider updates remain explicit. The manifest does not advertise an `init` command, and both companion dependencies set `init: false`. Use `new_web` explicitly when a new consumer site should be created. Restart long-lived MCP clients after registration, release-pin changes, or provider upgrades so their stdio processes use the selected releases.
20
41
 
21
42
  Repository editing coordination remains a control-plane responsibility rather than an `unaltraweb` runtime feature. Request one top-level MCP and let the control plane select its declared dependency closure; unrelated user registrations remain configured until explicitly removed and clients reconnect. Before editing, the control plane runs its read-only checkout preflight against the one primary mutable checkout and, when required, holds a process-scoped cooperative lease through its `exec` wrapper. Only one editing session may be active per repository. The control plane must never create, switch to, move, prune, repair, or remove Git worktrees implicitly.
22
43
 
23
44
  For a new agent-driven workspace, create or select the empty Git repository first, open that directory in the IDE, register the factory, restart the client, and then call `new_web`. The tool remains confined to the configured project root and does not accept an arbitrary destination. Generated sites include user-owned `README.md` and `AGENTS.md`, profile-specific source directories, and a managed runtime baseline; `scaffold_sync` never rewrites those user-owned guidance or content files.
24
45
 
25
- The Python wheel remains modular. Without a factory checkout it supports `version`, `new-web`, top-level `doctor`, the host-only `import-calibre` command, and the exact package-only MCP inventory declared in `component-contract.json`. The complementary exact inventory fails clearly with `UNALTRAWEB_FACTORY_DIR` remediation. The BOM selects the published `diavisuals v0.3.1` and `vegavisuals v0.3.1` releases. Its `consumer_integration` object is also the single source for the immutable core, workflow, PDF worker, and Vega revisions rendered into consumer scaffolds. Neither companion is bundled in the wheel or MCP server namespace.
46
+ The native Python CLI remains modular. Without a factory checkout it supports `version`, `new-web`, top-level `doctor`, the host-only `import-calibre` command, and the exact package-only MCP inventory declared in `component-contract.json`. The complementary exact inventory fails clearly with `UNALTRAWEB_FACTORY_DIR` remediation. The separate Docker adapter delegates to the full image and does not expand that native inventory. The BOM selects the published `diavisuals v0.4.0` and `vegavisuals v0.4.0` releases. Its `consumer_integration` object is also the single source for the immutable core, workflow, PDF worker, and Vega revisions rendered into consumer scaffolds. Neither companion is bundled in the wheel or MCP server namespace.
26
47
 
27
48
  Static Vega-Lite and Vega rendering remains owned by the required companion `vegavisuals` MCP dependency. Use its `visualization_status`, `visualization_check`, `render_visualizations`, and `vegavisuals://project/*` resources directly; `unaltraweb` exposes the authoring syntax but does not proxy those tools into the `web://` server.
28
49
 
@@ -81,6 +102,7 @@ baseline format nor runtime cleanup changes.
81
102
  | `web://manual-authoring-components` | Supported prose structures and component syntax, including callouts, definition lists, figure layouts, tables, diagrams, citations, and web/PDF compatibility. |
82
103
  | `web://manual-computations` | Executable manual sources, selected runtime images, generated outputs, and freshness state. |
83
104
  | `web://web-captures` | Selector-based screenshot recipes, original PNGs, editable SVG layers, edited overrides, and freshness. |
105
+ | `web://artifact-imports` | Native retained-letter bindings, complete seal/mapping integrity and source references; read-only. |
84
106
  | `web://new-web-scaffolds` | Package-owned scaffold availability and contract paths for every supported site profile. |
85
107
 
86
108
  ## Tools
@@ -95,6 +117,8 @@ baseline format nor runtime cleanup changes.
95
117
  | `site_context` | Read the main local state plus `update_status`: current/target package versions, planned paths, preserved customizations, conflicts and a reviewed-plan digest. |
96
118
  | `site_doctor` | Combine distribution doctor with strict project config, identity/language, generated Make contract, scaffold drift, required generated-output/receipt status, existing HTML audit, companion actions, and core override inventory. Unknown required status is blocking. Read-only and offline. |
97
119
  | `site_check` | Run profile, publication-copy source diagnostics, freshness, companion visualization/diagram receipt, bibliography, bibliometrics, and build-state checks without network. |
120
+ | `import_artifact_bundle` | Plan or explicitly apply a create-only Carta 0.3.0rc1 `letter-pdf-v1` import with the sender SHA-256, complete retained seal, standard v1 integration record and native content binding. Defaults to dry-run; apply requires `confirm_import=true`. |
121
+ | `artifact_import_check` | Verify retained domains, mappings and native source references; optional `output_folder` checks the bound rendered page and exact emitted PDF bytes. |
98
122
  | `site_source_read` | Read one allowed UTF-8 site source and return its exact SHA-256. |
99
123
  | `site_source_write` | Dry-run or atomically create/update one allowed source. Creates require `create_only`; updates require the exact SHA-256 returned by a read. |
100
124
  | `site_source_delete` | Dry-run or delete one allowed source with exact SHA-256 and explicit confirmation. It never deletes `_config.yml` or directories. |
@@ -156,6 +180,33 @@ Manual PDF publication is a local workspace operation: it copies reviewed artefa
156
180
 
157
181
  ## New Site Initialization
158
182
 
183
+ ### Retained Letter Integration
184
+
185
+ The 0.6.0 development increment adds package-only import/check commands and the
186
+ `web://artifact-imports` resource. Web rendering needs its containing Jekyll core;
187
+ manual inclusion also needs the matching PDF worker. Published 0.5.1 components
188
+ do not acquire this capability from a launcher-pin change.
189
+
190
+ The complete seal lives at `.unaltraweb/artifacts/<id>/bundle/`, alongside an
191
+ unchanged-schema v1 integration record and a separate native `binding.json`.
192
+ Only the byte-identical mapped PDF under `assets/documents/` is public. A new
193
+ draft page/chapter binds it using the `retained_document` Liquid tag and a literal
194
+ permalink. `site_check`, `site_doctor`, Jekyll and manual PDF preparation verify
195
+ the corresponding domain, seal, mapping and native reference; the PDF fingerprint
196
+ includes every retained dependency and checker. Producer sources are never run.
197
+
198
+ Writes require the consumer Git root, ignored/untracked recovery staging and
199
+ non-ignored durable paths. They are descriptor-relative and create-only, with
200
+ preflight and final integrity checks. The project/import locks coordinate with
201
+ native readers and the PDF controller. An interrupted operation retains its
202
+ prepared tree and partial files, without destructive rollback. An explicit retry
203
+ may adopt identical bytes; conflicts preserve existing content. Successful
204
+ identical reimport preserves authored prose. See the
205
+ [author reference](../_documentation/en/45-retained-documents.md) and
206
+ [owner acceptance record](retained-letter-import.md) for bounds and evidence.
207
+
208
+ ### Package-Owned Initialization
209
+
159
210
  `new_web` is intended for empty or nearly-empty website repositories. It creates common runtime files, profile-specific configuration, localized home pages, the content paths required by the selected profile, and `.unaltraweb/scaffold.json`. All scaffold assets are shipped inside the `unaltraweb_mcp` Python package and MCP Docker image; environment variables, sibling checkouts, and arbitrary template paths are not consulted.
160
211
 
161
212
  The `unaltremanual` scaffold also creates `context/writing-profile.md` with a usable default editorial policy and `.unaltraweb/computations.yml` with both BOM-selected workers, `_chapters` and `assets/quarto` source roots, and a generated-asset root. Customize the writing profile for the manual's audience, voice, terminology, evidence policy, language workflow, and review requirements. Computation configuration is consumer-owned rather than scaffold-managed so a project can add lockfiles, dependency paths, or extension Dockerfiles without creating scaffold-sync conflicts. PDF generation and Vega manifests remain opt-in project configuration.
@@ -226,7 +277,7 @@ For companion linking, compare the selected BOM and dependency capabilities with
226
277
  each running provider's `factory_manifest`, `compatibility_status` and release
227
278
  evidence. A development checkout announcing a future version is not a published
228
279
  release or evidence that a long-lived MCP process has upgraded. The current
229
- published companion selections are `diavisuals v0.3.1` and `vegavisuals v0.3.1`.
280
+ published companion selections are `diavisuals v0.4.0` and `vegavisuals v0.4.0`.
230
281
  Advance them only after their immutable releases exist and their receipt/tool
231
282
  contracts have been verified; source-checkout version drift remains an explicit
232
283
  control-plane finding, not a reason to weaken receipt validation.
@@ -247,6 +298,17 @@ Translations are a pre-publication task. They should preserve `ref`, citations,
247
298
 
248
299
  Run `site_doctor` and `site_check`, then resolve any blocking validation result before compiling. `build_site` reuses the active MCP container and the consumer's `build-native` target, and runs the local HTML audit after a successful Jekyll process. The generated `test-native` target also runs `html_audit`. This is intentionally different from the consumer's normal host-side `make build`, which starts a Jekyll container and would create a nested runtime when called from MCP.
249
300
 
301
+ In 0.5.1, `bundler_runtime` prepares offline, identity-keyed generated locks under
302
+ `tmp/unaltraweb-bundle`, verifying their receipts on reuse and retaining edited
303
+ or incomplete caches. Identity includes the actual Ruby/Bundler/gem inventory,
304
+ core inputs and hashed Bundler configuration. Updated native targets use private
305
+ invocation copies; an explicit author `LOCAL_GEMFILE` requires its own existing frozen lock.
306
+ For unchanged historical package Makefiles, `build_site` and the same-image
307
+ preview pass invocation-owned copies through `LOCAL_GEMFILE`, preserving the old
308
+ generated lock and all author sources. A modified Makefile is not overridden.
309
+ The fix requires a containing runtime, and does not mutate released 0.5.0 images
310
+ or real consumers. See [the populated-cache follow-up](owner-followup-76.md).
311
+
250
312
  Make delegation and feasible Docker control calls use one bounded subprocess runner. Status and control commands have short deadlines, builds/renders have target-specific longer deadlines, timeout terminates the process group and returns code `124`, and retained stdout/stderr is capped with explicit truncation fields. Factory commands that promise JSON fail closed when output is empty, malformed, non-object, non-finite, or truncated. Every bind source and target is encoded as a quoted Docker CSV field, so commas or quotes in host paths cannot introduce duplicate mount fields; carriage-return and newline path characters are rejected before canonicalization or mount construction. Computation, capture, and PDF containers carry factory, worker-role, project, and invocation-token labels plus cidfiles; after timeout cleanup selects all four labels and cannot remove unrelated containers.
251
313
 
252
314
  A preview must outlive one MCP tool invocation, so it runs in a separate container made from the same MCP/Jekyll image. Its deterministic name is derived from the canonical host project path and it carries the factory, role, and project labels. Its isolated container always listens on port `4000`; the default host port is allocated atomically by Docker on loopback and is reported as `preview_status.port`, preventing the old cross-project collision on host port `4000`. Starting an already-running preview probes it again instead of creating a duplicate. A preview created under the former fixed-port default is accepted as compatible with the new automatic default until it is stopped; its next start uses dynamic allocation. Changing an explicit requested port or profile still requires stopping first. Stdio session containers intentionally have Docker-generated names so independent clients can run simultaneously, but carry the same stable project ID and labels as previews and capture resources. That process-level capability does not authorize concurrent editing sessions in one repository. Stop and cleanup operations select ownership labels before removing anything.
@@ -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,144 @@
1
+ # Owner follow-up 76: populated Bundler transitions and 0.5.1 preparation
2
+
3
+ This follows the immutable historical intake in
4
+ [owner-preparation-2026-09-29.md](owner-preparation-2026-09-29.md) and the hub's
5
+ `owner-followups/05-unaltraweb.txt`. Tracking and final execution results:
6
+ [issue 76](https://github.com/dosquartsdedocs/unaltraweb/issues/76).
7
+
8
+ ## Correction and source identity
9
+
10
+ Implementation commit: `c23e12b0e1567d18a7f9dd225dc062ddc77dad8b`, on the existing
11
+ `feat/76-distributed-mcp-launcher` primary checkout. Local commits were explicitly
12
+ authorized. The following integration commit pins `consumer_integration.core_sha`
13
+ to this real 0.5.1 core, so the generated Gemfile/lock/workflow tuple no longer
14
+ combines a 0.5.1 gem version with a 0.5.0 source revision.
15
+
16
+ The correction lives in `src/unaltraweb_mcp/bundler_runtime.py` and is included in
17
+ both wheel and gem. It keys generated state by the actual Ruby/platform, Bundler,
18
+ installed gem inventory, core dependency inputs and hashed Bundler configuration.
19
+ No mutable Docker alias or project build default acts as the cache identity.
20
+
21
+ - Offline `bundle lock --local` and `bundle check` prepare a new identity cache
22
+ under `tmp/unaltraweb-bundle/<hash>/` and record exact Gemfile/lock hashes.
23
+ - Reuse verifies that receipt. Edited, unsafe or incomplete caches are retained
24
+ and rejected rather than silently reset. No old generated tree is removed.
25
+ - Each build/preview gets private invocation copies. This also accommodates
26
+ Bundler 4's local default-gem checksum completion without disabling checksums
27
+ or changing a cached or authored lock. An initially attempted frozen generated
28
+ lock exposed empty `rake` CHECKSUMS entries in the owner runtime; private copies
29
+ fixed that additional regression. Explicit author Gemfiles require an existing
30
+ lock and run with `BUNDLE_FROZEN=true`.
31
+ - Updated package scaffolds use the helper in native build/test/serve targets.
32
+ - MCP build and same-image preview adapt unchanged historical Makefiles only
33
+ when their bytes match the recorded package scaffold baseline. They pass
34
+ `LOCAL_GEMFILE` pointing to an invocation copy. The original
35
+ `tmp/Gemfile.local.lock`, project Gemfile/lock, Makefile and scaffold manifest
36
+ remain byte-identical. Custom Makefiles retain their own dependency policy;
37
+ adopting the new native targets remains an explicit scaffold update.
38
+
39
+ The already-published 0.5.0 image is still unpatched. The roundtrip fixture retains
40
+ its exact Ruby/gem layers and adds the new owner controls as a separately named
41
+ test image; this proves the correction against the problematic 0.5.0 inventory,
42
+ not a new empty cache or an unrelated fresh Ruby installation.
43
+
44
+ ## Component decision
45
+
46
+ | Component | 0.5.1 preparation |
47
+ | --- | --- |
48
+ | Core gem | New 0.5.1: ships the runtime helper and updated controls/docs. |
49
+ | Python wheel | New 0.5.1: installed Docker launcher, cache orchestration, scaffolds and integration tuple. |
50
+ | Full MCP image | New 0.5.1: required to run the correction without a local core. |
51
+ | Base Ruby/Jekyll image | Coordinated 0.5.1 candidate under the existing image workflow. The Dockerfile/toolchain recipe itself is unchanged. |
52
+ | Manual PDF | Reuse published 0.5.0 digest `sha256:9e0b3a45753c170b795e9a9d6df61580085c113436beac5bf6c8de69b6562097`. |
53
+ | Python/R computation, web capture | Retain their published 0.4.0 versions/digests. |
54
+ | Diavisuals/Vegavisuals | Retain published hashed 0.4.0 wheels and current receipt contract. |
55
+
56
+ The native validator now permits a released, digest-pinned PDF to retain its
57
+ actual version across a coordinated core patch. Pending/ready PDF candidates,
58
+ mutable aliases and other repositories do not receive that exception. The
59
+ existing source image workflow may build a PDF verification candidate; it does
60
+ not thereby replace the selected released worker or put it in the new receipt.
61
+ The new receipt must contain exactly `gem`, `wheel`, `runtime`, `mcp` when those
62
+ four components remain `ready`.
63
+
64
+ The 0.5.0 receipt is unchanged, SHA-256
65
+ `e57a9dbb041c1e7fcd781cd1524f4de0317382e0f7303bb36bfa59c0b6d1cb9b`.
66
+ Historical tags and published packages are untouched. The launcher retains the
67
+ last published MCP digest until a separately reviewed post-release selection.
68
+ Local 0.5.1 artifacts have new names and are not registry-published candidates.
69
+
70
+ ## Regressions and pre-integration owner gates
71
+
72
+ Executed on Linux/amd64:
73
+
74
+ - All four historical profiles: successful 0.4.0 host build first, containing
75
+ `google-protobuf (4.36.1-x86_64-linux-gnu)` in the retained generated lock.
76
+ - Unpatched 0.5.0 fails with the known missing `google-protobuf (4.36.1)` on a
77
+ disposable copy of each populated consumer; this negative control is required.
78
+ - Corrected controls on 0.5.0 Ruby layers: two builds, preview and HTTP pass.
79
+ - Return to unchanged published 0.4.0: two builds, preview and HTTP pass.
80
+ - Hash comparisons verify preservation of both authored and retained generated
81
+ Gemfile/lock pairs, Makefile and scaffold baseline across the roundtrip.
82
+ - The manual additionally builds/stages real PDFs and performs receipt-bound
83
+ preview cleanup. No source mount or real manual is used.
84
+ - Unit regressions cover populated A→B→A cache reuse, modified generated locks,
85
+ symlink ancestors, author Makefile overrides, frozen author locks, credential
86
+ hashing, and private checksum-completion copies.
87
+
88
+ Initial evidence is retained under
89
+ `/tmp/opencode/unaltraweb-followup-76/all-profiles-first/` (three completed
90
+ profiles) and `manual-first-roundtrip/` (completed manual). The first combined
91
+ run reached its 20-minute terminal limit during the final historical preview;
92
+ the manual was rerun to completion. No test container remained from that timeout.
93
+
94
+ Before integration: **562 unit tests, 30 optional skips**; distribution, workflow,
95
+ wheel, gem, MCP CLI, MCP stdio/manual-preview, prose and docs-build gates passed.
96
+ The final native smoke passed using `unaltraweb-followup-76-mcp:precommit3`; the
97
+ earlier frozen-generated-lock attempts remain failed intermediate evidence.
98
+ The old report's 0.5.0-labelled local wheel is not a release artifact.
99
+
100
+ ## Final-version artifact gate protocol
101
+
102
+ After pinning the corrected core, build the final 0.5.1 wheel and gem from that
103
+ clean integration commit, retain their hashes, install the wheel non-editably,
104
+ and repeat the gates against those bytes. Retain final outcomes and immutable
105
+ local image IDs in issue 76 rather than inserting a self-referential artifact
106
+ digest into its own source. Evidence belongs under
107
+ `/tmp/opencode/unaltraweb-followup-76/final-artifacts/` and
108
+ `/tmp/opencode/unaltraweb-followup-76/final-roundtrip/`.
109
+
110
+ The reproducible populated-cache command is:
111
+
112
+ ```bash
113
+ python3 test/bundler_transition_smoke.py \
114
+ --launcher /tmp/opencode/unaltraweb-followup-76/final-venv/bin/unaltraweb-mcp-docker \
115
+ --legacy-image ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:389bc585cdb4fc89d3372f4896a55fe26e15df38b46bc114ce44fdb3f1c8deb9 \
116
+ --broken-image ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:36d17edbade77edb40a687f6a744203c6329acb33fbc2eb255e88d9ff1a42c98 \
117
+ --fixed-image unaltraweb-followup-76:051-on-050-final \
118
+ --output /tmp/opencode/unaltraweb-followup-76/final-roundtrip
119
+ ```
120
+
121
+ Use a fresh output directory and a sufficiently long outer deadline; the driver
122
+ never clears a populated fixture to obtain a pass. The test overlay is built
123
+ with `test/bundler_transition.Dockerfile`, the exact published 0.5.0 base digest,
124
+ and a named `wheel` build context containing the final wheel. Installation uses
125
+ `--no-index --no-deps`, and the build uses `--network none`. Ordinary owner
126
+ `mcp-check`/`mcp-smoke` also run against separate test tags and fresh fixtures.
127
+
128
+ ## Publication status and next gate
129
+
130
+ Issue 76 stays open until integration and release. No PR, push, tag, workflow
131
+ dispatch, registry upload or consumer activation is authorized by the local
132
+ commit approval. The native schema remains unchanged; H1 range/catalogue fields
133
+ are not invented here. Tested points are the explicit tuples above, not a
134
+ continuous semver compatibility interval.
135
+
136
+ The strict `distribution-release-check` is mandatory and must remain blocking
137
+ until there is a new 0.5.1 receipt-only child commit with the correct default-branch
138
+ candidate ancestry, signed image digests and verified package checksums. The
139
+ retained 0.5.0 receipt cannot satisfy that gate and is not rewritten to do so.
140
+ Next: reviewed branch integration (preserving or deliberately refreshing the
141
+ core pin), approved signed candidate/package preparation on the resulting source,
142
+ new receipt-only commit, strict gate, then separately approved promotion and
143
+ post-release launcher selection. TIG, TIGIT, Geodisseny, their active registrations
144
+ and their image/worker selections are outside this test and adoption scope.