unaltraweb 0.5.1 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be599804b31390cca31133227e0e15f4ba623339a1072a441c74960b79c039fa
4
- data.tar.gz: d70f999b0d814f6a579dbb06534c611034792a1cd29972b3015ecce5e21522a4
3
+ metadata.gz: 2ed24da568933de15be12350ea7b867a6aa7e14abac71ec303755f5b808e1837
4
+ data.tar.gz: a4176d255c14de252144d7669db6479bc43ee033342332cd596870eea1ddf71b
5
5
  SHA512:
6
- metadata.gz: cb11d05e8660d167d311c7a9e1d03f895918d02c754e7189f52b25f1403f0056731aa94f77116b11cf30049c9d54b1ca6ffcae312c08d3127f942c756a1ed222
7
- data.tar.gz: c7c798ce0e589fbd2fdaddfa9c4d632afd043ccfca6ecd65c780dfcae33932f6314da270968c665dfcdbac080f48e67022c66344b45961c8b87c1cfe0704ff9a
6
+ metadata.gz: 768943c9b012a7e165ab9136d364783203c35caaaae62c2715f95361107f63377dbac30e45252ebeff78b0707d71dd14eb0481cecca18f52b15688c82f4c8c10
7
+ data.tar.gz: 49edeb75312f6d45e53db50a55a65f25ddb81f7ad8cc8438c9568ada3c9d699c9c00f0a329ea9b8cc2fb5812b5e48acd254e0e967b659d16650a0ea8612dad16
data/Makefile CHANGED
@@ -1,9 +1,9 @@
1
1
  PYTHON ?= python3
2
2
  override PROJECT := $${MCP_CONSUMER_WORKSPACE:?MCP_CONSUMER_WORKSPACE is required}
3
3
  override PROJECT_ROOT := $(PROJECT)
4
- MCP_RUNTIME_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.5.1
5
- MCP_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.5.1
6
- MCP_RELEASE_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:36d17edbade77edb40a687f6a744203c6329acb33fbc2eb255e88d9ff1a42c98
4
+ MCP_RUNTIME_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.7.0
5
+ MCP_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.7.0
6
+ MCP_RELEASE_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:736c4ddd0a543454e3edaeac2e9cfd97a1279ce472923ac54e326c1281b2ba05
7
7
  MCP_DOCKER_BUILD_NETWORK ?= default
8
8
  INIT_SITE_PROFILE ?= unaltreselfie
9
9
  NEW_WEB_PROFILE ?= unaltreselfie
@@ -40,8 +40,8 @@ WEB_CAPTURE_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-web-capture@sha256:0bf1b
40
40
  WEB_CAPTURE_DEV_IMAGE ?= unaltraweb-web-capture:dev
41
41
  WEB_CAPTURE_DOCKER_BUILD_NETWORK ?= default
42
42
  VEGAVISUALS_CLI ?=
43
- DOCKER_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.5.1
44
- MANUAL_PDF_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:9e0b3a45753c170b795e9a9d6df61580085c113436beac5bf6c8de69b6562097
43
+ DOCKER_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.7.0
44
+ MANUAL_PDF_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed
45
45
  MANUAL_PDF_DEV_IMAGE ?= unaltraweb-manual-pdf:dev
46
46
  MCP_SMOKE_MANUAL_PDF_IMAGE ?= $(MANUAL_PDF_IMAGE)
47
47
  MCP_SMOKE_PROJECT ?=
@@ -71,7 +71,7 @@ export MANUAL_RELEASE_SELECTOR MANUAL_PDF_LANG MANUAL_PDF_PUBLISH_DRY_RUN MANUAL
71
71
  UNALTRAWEB_WORKER_ROLE ?=
72
72
  UNALTRAWEB_WORKER_PROJECT ?=
73
73
  UNALTRAWEB_WORKER_TOKEN ?=
74
- WORKER_LABEL_ARGS = $(if $(strip $(UNALTRAWEB_WORKER_TOKEN)),--label "io.context.mcp-factory=unaltraweb" --label "io.context.mcp-role=$(UNALTRAWEB_WORKER_ROLE)" --label "io.context.mcp-project=$(UNALTRAWEB_WORKER_PROJECT)" --label "io.context.mcp-worker-token=$(UNALTRAWEB_WORKER_TOKEN)",)
74
+ WORKER_LABEL_ARGS = $(if $(strip $(UNALTRAWEB_WORKER_TOKEN)),--label "io.context.mcp-factory=unaltraweb" --label "io.context.mcp-role=$(UNALTRAWEB_WORKER_ROLE)" --label "io.context.mcp-project=$(UNALTRAWEB_WORKER_PROJECT)" --label "io.context.mcp-worker-token=$(UNALTRAWEB_WORKER_TOKEN)",) $(if $(strip $(UNALTRAWEB_RUNTIME_SESSION)),--label "io.context.mcp-session=$(UNALTRAWEB_RUNTIME_SESSION)",)
75
75
  DOCS_CONTAINER ?= unaltraweb-docs-local
76
76
  DOCS_HOST ?= 0.0.0.0
77
77
  DOCS_PORT ?= 4000
@@ -295,17 +295,18 @@ manual-compute-render: ## Execute sources and atomically publish Markdown and fi
295
295
  python_image="$(COMPUTE_PYTHON_IMAGE)"; r_image="$(COMPUTE_R_IMAGE)"; \
296
296
  if test "$$engine" = "r"; then r_image="$$image"; else python_image="$$image"; fi; \
297
297
  if ! docker image inspect "$$image" >/dev/null 2>&1; then \
298
+ if test "$${UNALTRAWEB_MANAGED_RUNTIME:-0}" = 1; then printf '%s\n' 'Selected computation image is not prepared; managed execution never builds or pulls' >&2; exit 1; fi; \
298
299
  COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" COMPUTE_DOCKER_BUILD_NETWORK="$(COMPUTE_DOCKER_BUILD_NETWORK)" $(PYTHON) "$(COMPUTE_SCRIPT)" image --project "$(PROJECT_ROOT)" --engine "$$engine" >/dev/null; \
299
300
  fi; \
300
301
  identity=$$(docker image inspect "$$image" --format '{{.Id}}'); \
301
302
  digest=$$(docker image inspect "$$image" --format '{{join .RepoDigests ","}}'); \
302
303
  set --; if test -n "$(UNALTRAWEB_WORKER_TOKEN)"; then cidfile="$$runtime_dir/worker-$(UNALTRAWEB_WORKER_TOKEN)-$$engine.cid"; rm -f "$$cidfile"; cidfiles="$$cidfiles $$cidfile"; set -- --cidfile "$$cidfile"; fi; \
303
- docker run --rm "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" --network none --read-only --cap-drop ALL --security-opt no-new-privileges --pids-limit "$(COMPUTE_PIDS_LIMIT)" --cpus "$(COMPUTE_CPUS)" --memory "$(COMPUTE_MEMORY)" --tmpfs /tmp:rw,noexec,nosuid,size=1g \
304
+ docker run --rm --pull never "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" --network none --read-only --cap-drop ALL --security-opt no-new-privileges --pids-limit "$(COMPUTE_PIDS_LIMIT)" --cpus "$(COMPUTE_CPUS)" --memory "$(COMPUTE_MEMORY)" --tmpfs /tmp:rw,noexec,nosuid,size=1g \
304
305
  -e HOME=/tmp -e COMPUTE_PYTHON_IMAGE="$$python_image" -e COMPUTE_R_IMAGE="$$r_image" \
305
306
  -e UNALTRAWEB_COMPUTE_IMAGE_ID="$$identity" -e UNALTRAWEB_COMPUTE_IMAGE_DIGEST="$$digest" \
306
307
  --mount "$$project_mount" \
307
308
  --mount "$$runtime_mount" \
308
- -w /project --entrypoint python3 "$$image" \
309
+ -w /project --entrypoint python3 "$$identity" \
309
310
  /opt/unaltraweb/computations/render.py render --project /project --engine "$$engine" $(if $(strip $(COMPUTE_SOURCE)),--source "$(COMPUTE_SOURCE)",) $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_CONFIRM_OVERWRITE)),--confirm-overwrite,) $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_STALE_ONLY)),--stale-only,) $(if $(strip $(COMPUTE_MODE)),--mode "$(COMPUTE_MODE)",) >> "$$results"; \
310
311
  done; \
311
312
  if test -z "$(strip $(COMPUTE_SOURCE))"; then $(PYTHON) "$(COMPUTE_SCRIPT)" prune --project "$(PROJECT_ROOT)" >/dev/null; fi; \
@@ -375,20 +376,21 @@ manual-pdf-image: ## Ensure the selected versioned Pandoc/XeLaTeX image is prese
375
376
  @docker image inspect "$(MANUAL_PDF_IMAGE)" >/dev/null 2>&1 || docker pull "$(MANUAL_PDF_IMAGE)"
376
377
 
377
378
  manual-pdf-image-dev: ## Build the explicitly named maintainer PDF development image
378
- docker build -f scripts/manual/Dockerfile -t "$(MANUAL_PDF_DEV_IMAGE)" scripts/manual
379
+ docker build -f scripts/manual/Dockerfile -t "$(MANUAL_PDF_DEV_IMAGE)" .
379
380
 
380
381
  define run_manual_pdf_worker
381
382
  @set -e; set --; cidfile=""; \
382
383
  if test -n "$(UNALTRAWEB_WORKER_TOKEN)"; then runtime_dir="$(PROJECT_ROOT)/tmp/.unaltraweb/manual-pdf"; mkdir -p "$$runtime_dir"; cidfile="$$runtime_dir/worker-$(UNALTRAWEB_WORKER_TOKEN).cid"; rm -f "$$cidfile"; set -- --cidfile "$$cidfile"; fi; \
383
384
  mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$(PROJECT_ROOT)" /project); \
384
385
  trap 'test -z "$$cidfile" || rm -f "$$cidfile"' EXIT; \
385
- docker run --rm "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp -e "UNALTRAWEB_MANUAL_RELEASE_SELECTOR=$${MANUAL_RELEASE_SELECTOR}" --mount "$$mount" -w /project "$(MANUAL_PDF_IMAGE)" $(1) --project /project $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",) $(2)
386
+ identity=$$(docker image inspect "$(MANUAL_PDF_IMAGE)" --format '{{.Id}}'); \
387
+ docker run --rm --pull never --network none --cpus 2 --memory 2g --pids-limit 256 "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp -e "UNALTRAWEB_MANUAL_RELEASE_SELECTOR=$${MANUAL_RELEASE_SELECTOR}" --mount "$$mount" -w /project "$$identity" $(1) --project /project $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",) $(2)
386
388
  endef
387
389
 
388
390
  manual-pdf-preflight: ## Run required PDF gates without contaminating the worker JSON stream
389
391
  @$(MAKE) --silent --no-print-directory manual-compute-check >/dev/null
390
392
  @$(MAKE) --silent --no-print-directory web-capture-check >/dev/null
391
- @docker image inspect "$(MANUAL_PDF_IMAGE)" >/dev/null 2>&1 || docker pull "$(MANUAL_PDF_IMAGE)" >/dev/null
393
+ @docker image inspect "$(MANUAL_PDF_IMAGE)" >/dev/null 2>&1 || { if test "$${UNALTRAWEB_MANAGED_RUNTIME:-0}" = 1; then printf '%s\n' 'Selected PDF image is not prepared; managed execution never pulls' >&2; exit 1; fi; docker pull "$(MANUAL_PDF_IMAGE)" >/dev/null; }
392
394
 
393
395
  manual-pdf-status: ## Inspect manual PDF configuration and artefacts without Docker, network, or writes
394
396
  @UNALTRAWEB_MANUAL_RELEASE_SELECTOR="$${MANUAL_RELEASE_SELECTOR}" $(PYTHON) "$(CURDIR)/scripts/manual/build_pdf.py" status --project "$(PROJECT_ROOT)" $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",)
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+ require "json"
5
+ require "open3"
6
+ require "timeout"
7
+
8
+ module UnaltrawebRetainedDocuments
9
+ def self.verify(site, output = nil)
10
+ return { "imports" => [] } unless File.exist?(File.join(site.source, ".unaltraweb", "artifacts"))
11
+
12
+ source = File.expand_path("../src", __dir__)
13
+ command = ["python3", "-m", "unaltraweb_mcp.artifact_imports", "--project", File.expand_path(site.source)]
14
+ command += ["--output-folder", output] if output
15
+ stdout, stderr, status = Timeout.timeout(120) { Open3.capture3({ "PYTHONPATH" => source }, *command) }
16
+ result = JSON.parse(stdout)
17
+ raise Jekyll::Errors::FatalException, "Retained document check failed: #{result['error'] || stderr}" unless status.success? && result["ok"] == true
18
+
19
+ result
20
+ end
21
+
22
+ class Generator < Jekyll::Generator
23
+ safe true
24
+ priority :highest
25
+
26
+ def generate(site)
27
+ site.config["unaltraweb_retained_documents"] = UnaltrawebRetainedDocuments.verify(site)["imports"].to_h { |item| [item["id"], item] }
28
+ end
29
+ end
30
+
31
+ class DocumentTag < Liquid::Tag
32
+ def initialize(name, markup, tokens)
33
+ super
34
+ @id = markup.strip
35
+ raise ArgumentError, "retained_document requires one import ID" unless @id.match?(/\A[a-z][a-z0-9-]{0,63}\z/)
36
+ end
37
+
38
+ def render(context)
39
+ site = context.registers[:site]
40
+ item = (site.config["unaltraweb_retained_documents"] || {})[@id]
41
+ raise Jekyll::Errors::FatalException, "Unverified retained document #{@id}" unless item
42
+
43
+ path = site.config["baseurl"].to_s.sub(%r{/\z}, "") + "/" + item.fetch("pdf")
44
+ url = CGI.escapeHTML(path)
45
+ page = context["page"]
46
+ title = CGI.escapeHTML(((page && page["title"]) || @id).to_s)
47
+ %(<figure class="retained-document"><object data-retained-document="#{@id}" data="#{url}" type="application/pdf" aria-label="#{title}" style="width:100%;height:70vh"><a href="#{url}">#{title}</a></object><figcaption><a href="#{url}">#{title} (PDF)</a></figcaption></figure>)
48
+ end
49
+ end
50
+ end
51
+
52
+ Liquid::Template.register_tag("retained_document", UnaltrawebRetainedDocuments::DocumentTag)
53
+
54
+ Jekyll::Hooks.register :site, :post_write do |site|
55
+ source = File.expand_path(site.source)
56
+ destination = File.expand_path(site.dest)
57
+ if destination.start_with?(source + "/")
58
+ UnaltrawebRetainedDocuments.verify(site, destination.delete_prefix(source + "/"))
59
+ elsif !(site.config["unaltraweb_retained_documents"] || {}).empty?
60
+ raise Jekyll::Errors::FatalException, "Retained documents require a project-confined site destination"
61
+ end
62
+ end
@@ -25,9 +25,63 @@ The template is the better place to validate gem consumption, centralized styles
25
25
 
26
26
  ## Component Contract
27
27
 
28
- ### Published 0.5.0 release
29
-
30
- The coordinated core release is [**0.5.0**](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.5.0). It groups the integrated editorial
28
+ ### 0.7.0 D0 runtime increment
29
+
30
+ The next containing runtime adds [live instance identity and session-scoped
31
+ resource control]({{ '/live-runtime/' | relative_url }}). Preparation is explicit,
32
+ launch is pull-never, and startup identity remains distinct from current disk
33
+ metadata. The owner-tested rendering closure selects Diavisuals 0.5.0 and Vega
34
+ 0.5.1 with exact artifacts; old 0.4.0 static receipts remain integrity-checked.
35
+ Diavisuals' separate live-process identity correction still gates the full
36
+ managed coordinator closure. Publication and activation evidence belong to the
37
+ [D0 owner record](https://github.com/dosquartsdedocs/unaltraweb/blob/main/docs/agents/d0-runtime-identity.md).
38
+
39
+ ### Published 0.6.0 release
40
+
41
+ [**0.6.0**](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.6.0)
42
+ delivers native [retained-letter import]({{ '/retained-documents/' | relative_url }}).
43
+ Gem, wheel, base runtime and MCP were published from
44
+ `de52db351490e94939aac20c6af264f22a6a1678`; receipt-only integration and tag target
45
+ `ec6dcb28e890d32718aa173934527a7b4213a042` bind their verified bytes.
46
+ The consumer core selects reviewed integration
47
+ `5cf9817489c8dc47cee726bfe42fe3071cd32b85`; the PDF 0.6.0 worker is already
48
+ published, signed and tested at immutable digest
49
+ `sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed`.
50
+ The PDF worker changes to include complete retained documents and the same
51
+ integrity checkers used by its controller. Computation, capture and visual
52
+ companions retain their tested 0.4.0 selections.
53
+
54
+ The post-release checkout launcher selects published MCP digest
55
+ `sha256:736c4ddd0a543454e3edaeac2e9cfd97a1279ce472923ac54e326c1281b2ba05`.
56
+ Signed candidates, protected CI, strict receipt/ancestry gates, registry promotion
57
+ and Trusted Publishing passed. Anonymous downloads match the receipt. The
58
+ [delivery report](https://github.com/dosquartsdedocs/unaltraweb/blob/main/docs/agents/owner-closeout-80.md)
59
+ records the installed Carta relocation proof and four-profile populated-cache
60
+ roundtrip against those exact bytes. Existing clients keep their loaded image
61
+ until reconnecting; real consumer adoption remains explicit.
62
+
63
+ ### Published 0.5.1 release
64
+
65
+ [**0.5.1**](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.5.1)
66
+ delivers the installed Docker launcher and runtime-specific generated Bundler
67
+ state. Source `aab5a7b030cd711b40770a3f44ad3a356eab90da` produced the signed
68
+ images and verified gem/wheel. Receipt/tag commit
69
+ `e842c733c8a274279dd5efdc3618e20669f29037` changes only the receipt from that
70
+ first parent. Strict release/publication gates passed before promotion, and
71
+ anonymous registry downloads match the receipt. That release's launcher selected
72
+ `ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692`.
73
+
74
+ The four-profile populated-cache roundtrip also passed against the actual signed
75
+ candidate. The selected PDF stays at its published 0.5.0 digest, and computation,
76
+ capture and visual companions retain 0.4.0. See the
77
+ [delivery report](https://github.com/dosquartsdedocs/unaltraweb/blob/main/docs/agents/owner-closeout-76.md)
78
+ and [issue 76](https://github.com/dosquartsdedocs/unaltraweb/issues/76).
79
+ Strict release validation applies to the receipt/tag revision; subsequent
80
+ post-release launcher changes are ordinary source revisions, not new receipts.
81
+
82
+ ### Previous 0.5.0 release
83
+
84
+ The previous coordinated core release is [**0.5.0**](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.5.0). It groups the integrated editorial
31
85
  review, guided scaffold updates, caption-credit/image behavior and published
32
86
  Diavisuals/Vegavisuals 0.4.0 acceptance. Source-bound image/package workflows,
33
87
  tag promotion and both Trusted Publishing jobs passed. Anonymous package downloads
@@ -42,7 +96,7 @@ at source `d857f8c9f5fea90cf450c0b30b4e77a37b541275` and is selected by digest
42
96
  `sha256:9e0b3a45753c170b795e9a9d6df61580085c113436beac5bf6c8de69b6562097` in
43
97
  both the factory and the consumer tuple. It is already published and tested, so
44
98
  final candidate receipts cover the remaining ready package/core components.
45
- The post-release factory launcher selects the MCP digest recorded in receipt
99
+ The 0.5.0 post-release factory launcher selected the MCP digest recorded in receipt
46
100
  `3fa855378dcc61dc7b84b8b03812698042e02fed`:
47
101
  `sha256:36d17edbade77edb40a687f6a744203c6329acb33fbc2eb255e88d9ff1a42c98`.
48
102
  See [issue 69](https://github.com/dosquartsdedocs/unaltraweb/issues/69) for the
@@ -50,27 +104,27 @@ candidate, receipt, tag and package evidence.
50
104
 
51
105
  `src/unaltraweb_mcp/component-contract.json` is the canonical versioned bill of materials. Its `consumer_integration` object is the sole source for the reviewed core Git revision, reusable deploy workflow, manual PDF image digest, and Vega renderer revision. Scaffold templates render that tuple atomically into consumer `Gemfile`, `Gemfile.lock`, and deploy workflow files. `component-contract.schema.json` defines schema version 1. Runtime loading and `scripts/validate_distribution.py` validate the complete document against that schema, then enforce semantic parity between versions, release tags, repositories, references, wheel contents, CLI availability, and consumer integration pins.
52
106
 
53
- The BOM is an interoperability contract, not a bundle. The wheel contains its Python control/inspection modules, schema/BOM, and clean package-owned scaffolds. Next-release source also packages a small host Docker launcher, described below. Neither includes Ruby theme assets, Docker image layers, the factory's build/worker implementations, TeX, Chromium, computation environments, `diavisuals`, or `vegavisuals`.
107
+ The BOM is an interoperability contract, not a bundle. The wheel contains its Python control/inspection modules, schema/BOM, clean package-owned scaffolds and a small host Docker launcher, described below. It does not include Ruby theme assets, Docker image layers, the factory's build/worker implementations, TeX, Chromium, computation environments, `diavisuals`, or `vegavisuals`.
54
108
 
55
- The selected public core release is `0.5.0`; earlier distributions remain immutable. Its BOM reuses immutable compute and web-capture worker digests and selects published `diavisuals v0.4.0` and `vegavisuals v0.4.0` through SHA-256-pinned wheel URLs. Companion references can describe either a provider/release-matching Git reference or a provider/release/version-matching wheel with its content hash. The wheel boundary remains external. The scaffold's Vega revision is the published `68c0b231402ae9485cc34ce530dc5239cb0ec194` commit. `distribution-check` validates structural integrity for normal CI. `distribution-release-check` blocks coordinated publication while any component is `pending` or `unavailable`; reviewed source authorized to produce final same-commit candidates is `ready`, while an already-published component is `released`. Final receipt values remain immutable after publication.
109
+ The selected public core release is `0.6.0`; earlier distributions remain immutable. Its BOM reuses immutable PDF, compute and web-capture worker digests and selects published `diavisuals v0.4.0` and `vegavisuals v0.4.0` through SHA-256-pinned wheel URLs. Companion references can describe either a provider/release-matching Git reference or a provider/release/version-matching wheel with its content hash. The wheel boundary remains external. The scaffold's Vega revision is the published `68c0b231402ae9485cc34ce530dc5239cb0ec194` commit. `distribution-check` validates structural integrity for normal CI. `distribution-release-check` blocks coordinated publication while any component is `pending` or `unavailable`; reviewed source authorized to produce final same-commit candidates is `ready`, while an already-published component is `released`. Final receipt values remain immutable after publication.
56
110
 
57
111
  ## Docker-First Hybrid Policy
58
112
 
59
- ### 0.5.1 preparation
113
+ ### 0.6.0 component selection
60
114
 
61
- The next coordinated core identity is **0.5.1**: gem, wheel, base runtime and MCP
62
- image candidates change together. The installed host launcher and runtime-aware
63
- generated Bundler state are included. The unchanged PDF worker retains its
64
- published 0.5.0 digest, alongside the 0.4.0 computation/capture workers and visual
115
+ The coordinated core identity is **0.6.0**: gem, wheel, base runtime and MCP
116
+ images were published together. The installed host launcher and runtime-aware
117
+ generated Bundler state are included. The PDF worker uses its reviewed, signed
118
+ 0.6.0 digest, alongside the 0.4.0 computation/capture workers and visual
65
119
  companions. A released PDF can be reused only by full digest; new/pending workers
66
120
  still require the coordinated version. The historical 0.5.0 receipt remains
67
- unchanged. Final signed image/package receipts and promotion are later gates;
68
- the launcher continues selecting the last published MCP digest until its normal
69
- post-release update.
121
+ unchanged. Signed image/package evidence is recorded in the 0.6.0 receipt;
122
+ promotion and anonymous-download checks passed before the post-release launcher
123
+ pin was advanced.
70
124
 
71
125
  ### Local delivery
72
126
 
73
- GHCR is the canonical delivery channel for normal local use. The released package scaffold selects `ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.5.0`; existing sites can remain on their immutable previous release until deliberately updated. Its `make build`, `make serve` and `make test` targets mount the thin child site and run inside that image. The image contains both the installed Python control plane and the reviewed factory source at `/opt/unaltraweb`, so those targets load the theme as a path gem without downloading PyPI or RubyGems packages.
127
+ GHCR is the canonical delivery channel for normal local use. The released package scaffold selects `ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.6.0`; existing sites can remain on their immutable previous release until deliberately updated. Its `make build`, `make serve` and `make test` targets mount the thin child site and run inside that image. The image contains both the installed Python control plane and the reviewed factory source at `/opt/unaltraweb`, so those targets load the theme as a path gem without downloading PyPI or RubyGems packages.
74
128
 
75
129
  Factory registration uses a stricter pin. gContExt runs `mcp-build`, which inspects or pulls the full `MCP_RELEASE_IMAGE` digest, and `mcp-stdio` launches that exact image. Checkout builds use local `:dev` names by default through `mcp-image`, `mcp-check` and `mcp-smoke`, so they do not shadow public semver references unless a maintainer explicitly overrides them. The digest is advanced in a separate post-release change after each new receipt exists; candidate source continues to select the last completed release instead of attempting to embed an unknown self-digest.
76
130
 
@@ -86,7 +140,7 @@ These remain real package boundaries: the MCP image installs the Python package
86
140
 
87
141
  ### Installed Docker launcher
88
142
 
89
- 0.5.1 source adds **`unaltraweb-mcp-docker`** and a complete host launcher
143
+ 0.5.1 ships **`unaltraweb-mcp-docker`** and a complete host launcher
90
144
  under the installation prefix's `share/unaltraweb-launcher/`. The published 0.5.0
91
145
  wheel predates this addition; its receipt and bytes remain unchanged. An installed
92
146
  wheel containing the launcher can use the already-published full GHCR runtime
@@ -100,7 +154,7 @@ unaltraweb-mcp-docker serve --project /absolute/consumer
100
154
  ```
101
155
 
102
156
  The installed default selects its package's full MCP release image, currently
103
- `ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.5.1`. It resolves that selection to the
157
+ `ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.6.0`. It resolves that selection to the
104
158
  local immutable image ID before executing. The checkout's `MCP_RELEASE_IMAGE`
105
159
  is a separate digest pin advanced only after publication; it is not the installed
106
160
  wheel's default. This avoids sending a new package back to an older MCP while
@@ -132,7 +186,7 @@ the host, register a client, update a consumer scaffold, or change an active MCP
132
186
  The site Makefile's `MCP_IMAGE`, native Gem/core revision, PDF worker, global MCP
133
187
  registration and companion selections are separate parts of an effective tuple.
134
188
  TIG/TIGIT retain build defaults 0.4.0; Geodisseny retains 0.5.0. A global MCP
135
- selection of 0.5.0 does not rewrite those defaults. Tests use synthetic sites,
189
+ selection does not rewrite those defaults. Tests use synthetic sites,
136
190
  image-specific test resources and dynamically allocated loopback preview ports.
137
191
 
138
192
  Compatibility evidence is a set of tested tuples, not a continuous version range.
@@ -245,7 +299,7 @@ For that reason:
245
299
 
246
300
  ## Docker Runtime
247
301
 
248
- Release `0.5.0` publishes the selected base/MCP runtime and packages while pinning the verified PDF worker and reusing unchanged specialized workers. Local maintainers continue to use explicit development names such as `unaltraweb:dev`; generated sites select the reviewed semver MCP image rather than `main` or `latest`.
302
+ Release `0.6.0` publishes the selected base/MCP runtime and packages while pinning the verified PDF worker and reusing unchanged specialized workers. Local maintainers continue to use explicit development names such as `unaltraweb:dev`; generated sites select the reviewed semver MCP image rather than `main` or `latest`.
249
303
 
250
304
  The base runtime owns Ruby, Jekyll and system dependencies. The MCP image builds on its exact candidate digest and adds the full reviewed factory plus the Python package. Specialized workers remain separate. This keeps each layer focused without adding Chromium, TeX or computation stacks to every site; the coordinated core-image workflow still rebuilds and verifies runtime, MCP and manual PDF candidates together.
251
305
 
@@ -0,0 +1,138 @@
1
+ ---
2
+ title: Import A Retained Letter
3
+ description: Verify and retain a Carta letter bundle, display its PDF on the web and include it in a manual.
4
+ lang: en
5
+ ref: retained_documents
6
+ profiles:
7
+ - unaltredocs
8
+ documentation_profiles:
9
+ - local-authors
10
+ - core-developers
11
+ section: Build A Site
12
+ weight: 240
13
+ permalink: /retained-documents/
14
+ nav_title: Retained Documents
15
+ ---
16
+
17
+ A retained letter combines its original PDF with the source, rendering inputs and
18
+ provenance needed to inspect its origin. The importer keeps that complete unit in
19
+ the receiving repository and creates a native page or chapter referencing the PDF.
20
+ The website displays the original; a manual PDF includes all its pages.
21
+
22
+ This capability ships in **0.6.0**. It requires a
23
+ containing Python package and Jekyll core, plus the matching PDF worker for manual
24
+ output. The published 0.5.1 runtime predates it. Changing the global MCP selection
25
+ does not update a site's Gemfile, Makefile or PDF-worker selection.
26
+
27
+ Native gem builds need Python with `PyYAML>=6,<7`, `pypdf>=6,<7` and
28
+ `markdown-it-py>=3,<5`. The containing MCP/PDF images provide these dependencies;
29
+ the containing reusable deployment workflow installs the PDF/text parsers when
30
+ retained imports are present.
31
+
32
+ ## Supported Input
33
+
34
+ The receiving profile accepts leaf `letter-pdf-v1` bundles from **Carta
35
+ 0.3.0rc1**, using the existing artifact handoff v1 envelope. Verification covers
36
+ the supplied sender SHA-256, complete file inventory, retained render recipe,
37
+ templates, source references, drawable resources and renderer identity. PDF
38
+ inspection is bounded and rejects encrypted files, embedded or external files,
39
+ JavaScript and unsupported actions. Internal destinations and textual HTTP,
40
+ HTTPS and email links are supported.
41
+
42
+ Renderable metadata is checked independently of the retained Pandoc AST. A
43
+ resealed bundle with an unretained local link in a subject or author field is
44
+ rejected even when its older parsing evidence does not mention that link.
45
+
46
+ Limits are 64 MiB for the payload unit, 32 MiB for the PDF and 1–64 pages. The
47
+ supported source subset excludes body images, raw markup, TeX, math and citations;
48
+ attachments remain text labels. Composite bundles, edited PDF variants and
49
+ Diapora composition require separate receiving profiles.
50
+
51
+ Obtain the bundle's expected SHA-256 through the sender's trusted handoff. A hash
52
+ computed only from an unknown local manifest establishes consistency, not its
53
+ origin. Importing never executes the retained recipe or contacts the producer.
54
+
55
+ ## Import Into A Consumer
56
+
57
+ Start with an initialized consumer Git repository. Place the complete incoming
58
+ bundle under a workspace-relative directory such as `tmp/incoming/letter/`.
59
+ The recovery area under `tmp/` must be ignored and untracked; durable destinations
60
+ must be eligible for version control.
61
+
62
+ Review a plan using the installed CLI. Here `BUNDLE_SHA` is the sender's verified
63
+ manifest digest:
64
+
65
+ ```bash
66
+ unaltraweb-mcp --project /absolute/consumer mcp import-artifact-bundle \
67
+ --path tmp/incoming/letter/bundle.json --sha256 "$BUNDLE_SHA" \
68
+ --import-id correspondence --content-path _chapters/en/correspondence.md \
69
+ --title "Retained correspondence"
70
+ ```
71
+
72
+ To apply the reviewed request, repeat it with `--apply --confirm-import`.
73
+ The MCP equivalent is `import_artifact_bundle` with `dry_run=false` and
74
+ `confirm_import=true`; its default is a read-only plan.
75
+
76
+ Choose a new Markdown destination under `_pages/`, or `_chapters/` for a manual,
77
+ or `_documentation/` for a documentation site. An executable source owning the
78
+ same Markdown basename blocks creation. The generated document starts as a draft
79
+ in the consumer's default language, with a literal local permalink.
80
+
81
+ The resulting paths are:
82
+
83
+ | Path | Purpose |
84
+ | --- | --- |
85
+ | `.unaltraweb/artifacts/correspondence/bundle/` | Complete, unchanged incoming seal, outside the web output |
86
+ | `.unaltraweb/artifacts/correspondence/integration.json` | Standard v1 integration record and byte-preserving PDF mapping |
87
+ | `.unaltraweb/artifacts/correspondence/binding.json` | Native content path and integration-record digest |
88
+ | `assets/documents/correspondence.pdf` | Public PDF, identical to the retained original |
89
+ | `_chapters/en/correspondence.md` | Native chapter with the retained-document component |
90
+
91
+ Version the complete durable unit together. The incoming directory and ignored
92
+ recovery journal are not runtime dependencies. The retained archive is excluded
93
+ from website output, but remains ordinary repository content.
94
+
95
+ ## Edit And Render The Native Document
96
+
97
+ Add explanatory prose to the generated page or chapter while preserving its
98
+ literal permalink and component:
99
+
100
+ {% raw %}
101
+ ```liquid
102
+ {% retained_document correspondence %}
103
+ ```
104
+ {% endraw %}
105
+
106
+ On the web, the component renders a PDF object with a labelled download link.
107
+ The build checks the bound page's exact local PDF URL and the emitted PDF bytes.
108
+ Exposing the retained archive in the website is an error. In a manual, the PDF
109
+ builder includes every original page and fingerprints the entire retained unit
110
+ and its checker implementation. A controller/worker mismatch therefore fails
111
+ freshness verification rather than silently accepting an older checker.
112
+
113
+ Run `artifact_import_check` or the CLI equivalent before building:
114
+
115
+ ```bash
116
+ unaltraweb-mcp --project /absolute/consumer mcp artifact-import-check
117
+ unaltraweb-mcp --project /absolute/consumer mcp artifact-import-check --output-folder _site
118
+ ```
119
+
120
+ `site_check` and `site_doctor` include the native integrity check. For a local
121
+ manual review, use `manual_pdf_preview_prepare`, then `build_site` and
122
+ `preview_start`. Review the web page and composed PDF, then clean only the
123
+ receipt-owned preview copies through `manual_pdf_preview_clean`.
124
+
125
+ ## Preservation And Recovery
126
+
127
+ An identical reimport preserves authored prose. A changed mapped PDF, conflicting
128
+ destination, unsafe path or modified seal blocks the operation; existing files
129
+ are never overwritten. After an interrupted import, unchanged partial files may
130
+ be adopted by an explicit retry of the same request. Differing partial files
131
+ require inspection. The operation retains its prepared tree and journal under
132
+ `tmp/unaltraweb-artifact-imports/` and performs no destructive rollback.
133
+
134
+ The native check verifies references and content after the incoming producer copy
135
+ has been removed or the receiving repository has moved. It also detects missing
136
+ content, incomplete retention and altered mappings. The generic v1 verifier can
137
+ independently inspect `integration.json`; it does not replace the native source
138
+ and rendered-output checks.
@@ -0,0 +1,89 @@
1
+ ---
2
+ title: Inspect And Close A Live MCP Session
3
+ description: Startup identity, exact prepared images and session-scoped resource release.
4
+ lang: en
5
+ ref: live_runtime_identity
6
+ profiles:
7
+ - unaltredocs
8
+ documentation_profiles:
9
+ - local-authors
10
+ - core-developers
11
+ section: Core Development
12
+ weight: 635
13
+ permalink: /live-runtime/
14
+ nav_title: Live Runtime
15
+ ---
16
+
17
+ The 0.7.0 runtime increment distinguishes the process serving a connection from
18
+ the installed package, source checkout and rendering workers. Call
19
+ `runtime_identity` or read `web://runtime-identity` through that live MCP
20
+ connection. Both report the same backend instance and startup information.
21
+
22
+ The observation includes the loaded package version, startup code fingerprint,
23
+ current disk fingerprint, interpreter, PID/start information, workspace mapping
24
+ and selected versus observed image identities. A disk edit is reported as drift;
25
+ it does not upgrade an already-running process. Docker-host and container PID
26
+ namespaces are reported separately. Identity checks read engine/runtime metadata,
27
+ not website prose, private records or arbitrary environment variables.
28
+
29
+ ## Prepare Explicitly, Then Launch
30
+
31
+ Use `unaltraweb-mcp-docker prepare --image REF` to acquire a selected release.
32
+ Launch, check, smoke and identity observations do not build or pull missing images.
33
+ For a managed launch, supply a full image ID or repository digest, or bind a local
34
+ reference to its independently verified configuration ID:
35
+
36
+ ```bash
37
+ unaltraweb-mcp-docker serve --project /absolute/site \
38
+ --image "$PREPARED_REFERENCE" --expected-image-id "$EXPECTED_IMAGE_ID" --managed
39
+ ```
40
+
41
+ The expected value is Docker's full `sha256:` configuration ID, not the archive
42
+ checksum or OCI index digest. A missing or mismatched selection is an error.
43
+ Execution uses that inspected ID with `--pull never`; existing aliases are not
44
+ rewritten. Add `--offline` for a controller without networking. The declared
45
+ Docker socket remains available for local inspection and prepared workers.
46
+
47
+ The normal host launcher mounts the canonical site path and a `/workspace` alias.
48
+ A launcher itself running in a container must supply its explicit daemon-host
49
+ mapping using `--host-project`. Unsupported direct controller mappings require
50
+ inspection rather than guessing a host path from `/workspace`.
51
+
52
+ ## Close One Connection Safely
53
+
54
+ 1. Retain the identity's consumer binding, session ID and exact container ID.
55
+ 2. Call `runtime_drain(confirm=true)`. The backend stops admitting new operations.
56
+ 3. Close that stdio connection. Bounded active work finishes before its idle
57
+ session resources are released.
58
+ 4. Use the installed `session-status` command to confirm resource termination.
59
+
60
+ ```bash
61
+ unaltraweb-mcp-docker session-status --project /absolute/site \
62
+ --session-id "$SESSION_ID" --container-id "$CONTAINER_ID"
63
+ ```
64
+
65
+ `connected`, `busy`, `orphaned` and `unknown` do not mean resources are free.
66
+ Only `stopped` with `resources_released=true` establishes observed absence.
67
+ After a crash, `reap-session` with the same retained tuple can recover eligible
68
+ idle leftovers. It preserves live backends, active jobs, other sessions, prepared
69
+ images, volumes and authored files. Disk cleanup remains explicit and separate.
70
+
71
+ The older `down` command is workspace-wide, and `mcp-down-all` is factory-wide.
72
+ Use them only for those intended scopes, not as a substitute for closing one
73
+ client. The managed stdio profile has one connection per backend; it does not
74
+ claim shared-HTTP backend reattachment semantics.
75
+
76
+ ## Workers And Helpers
77
+
78
+ Worker references are fixed at startup. Managed rendering requires those exact
79
+ images to be prepared; it refuses a fallback pull/build or a conflicting authored
80
+ computation-image choice. The identity reports resource bounds and image
81
+ observations without running a renderer.
82
+
83
+ Visual helpers are separate MCP processes. Their versions and immutable package
84
+ selections describe the accepted rendering closure, not their current live
85
+ instances. The composing controller must obtain each helper's own live identity.
86
+ The selected Diavisuals 0.5.0 still requires its separately tracked D0 identity
87
+ correction before the entire coordinator closure can be marked managed-ready.
88
+ Existing 0.4.0 static provider receipts remain subject to full integrity checks
89
+ and do not force regeneration of authored figures during an upgrade.