unaltraweb 0.6.0 → 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 +4 -4
- data/Makefile +11 -9
- data/docs/_documentation/en/40-distribution.md +37 -22
- data/docs/_documentation/en/45-retained-documents.md +1 -1
- data/docs/_documentation/en/46-live-runtime.md +89 -0
- data/docs/agents/d0-runtime-identity.md +200 -0
- data/docs/agents/mcp-contract.md +12 -4
- data/docs/agents/owner-closeout-80.md +185 -0
- data/docs/agents/retained-letter-import.md +4 -0
- data/scripts/test_wheel_install.py +2 -2
- data/scripts/unaltraweb-mcp-bootstrap.sh +90 -9
- data/scripts/unaltraweb-mcp-cleanup.sh +41 -9
- data/scripts/web_captures/render.py +8 -1
- data/src/unaltraweb_mcp/component-contract.json +22 -22
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ed24da568933de15be12350ea7b867a6aa7e14abac71ec303755f5b808e1837
|
|
4
|
+
data.tar.gz: a4176d255c14de252144d7669db6479bc43ee033342332cd596870eea1ddf71b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
MCP_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.
|
|
6
|
-
MCP_RELEASE_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:
|
|
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,7 +40,7 @@ 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.
|
|
43
|
+
DOCKER_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.7.0
|
|
44
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)
|
|
@@ -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 "$$
|
|
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; \
|
|
@@ -382,13 +383,14 @@ define run_manual_pdf_worker
|
|
|
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
|
|
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)",)
|
|
@@ -25,12 +25,25 @@ The template is the better place to validate gem consumption, centralized styles
|
|
|
25
25
|
|
|
26
26
|
## Component Contract
|
|
27
27
|
|
|
28
|
-
###
|
|
29
|
-
|
|
30
|
-
The
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
34
47
|
`5cf9817489c8dc47cee726bfe42fe3071cd32b85`; the PDF 0.6.0 worker is already
|
|
35
48
|
published, signed and tested at immutable digest
|
|
36
49
|
`sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed`.
|
|
@@ -38,12 +51,14 @@ The PDF worker changes to include complete retained documents and the same
|
|
|
38
51
|
integrity checkers used by its controller. Computation, capture and visual
|
|
39
52
|
companions retain their tested 0.4.0 selections.
|
|
40
53
|
|
|
41
|
-
The checkout
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
[
|
|
46
|
-
records the
|
|
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.
|
|
47
62
|
|
|
48
63
|
### Published 0.5.1 release
|
|
49
64
|
|
|
@@ -53,7 +68,7 @@ state. Source `aab5a7b030cd711b40770a3f44ad3a356eab90da` produced the signed
|
|
|
53
68
|
images and verified gem/wheel. Receipt/tag commit
|
|
54
69
|
`e842c733c8a274279dd5efdc3618e20669f29037` changes only the receipt from that
|
|
55
70
|
first parent. Strict release/publication gates passed before promotion, and
|
|
56
|
-
anonymous registry downloads match the receipt.
|
|
71
|
+
anonymous registry downloads match the receipt. That release's launcher selected
|
|
57
72
|
`ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:908b4ce54c7bdf355e14ed55b31ed4b9baae319e211af90004a680d1d1cb8692`.
|
|
58
73
|
|
|
59
74
|
The four-profile populated-cache roundtrip also passed against the actual signed
|
|
@@ -91,25 +106,25 @@ candidate, receipt, tag and package evidence.
|
|
|
91
106
|
|
|
92
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`.
|
|
93
108
|
|
|
94
|
-
The selected public core release is `0.
|
|
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.
|
|
95
110
|
|
|
96
111
|
## Docker-First Hybrid Policy
|
|
97
112
|
|
|
98
|
-
### 0.
|
|
113
|
+
### 0.6.0 component selection
|
|
99
114
|
|
|
100
|
-
The coordinated core identity is **0.
|
|
115
|
+
The coordinated core identity is **0.6.0**: gem, wheel, base runtime and MCP
|
|
101
116
|
images were published together. The installed host launcher and runtime-aware
|
|
102
|
-
generated Bundler state are included. The
|
|
103
|
-
|
|
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
|
|
104
119
|
companions. A released PDF can be reused only by full digest; new/pending workers
|
|
105
120
|
still require the coordinated version. The historical 0.5.0 receipt remains
|
|
106
|
-
unchanged. Signed image/package evidence is recorded in the 0.
|
|
121
|
+
unchanged. Signed image/package evidence is recorded in the 0.6.0 receipt;
|
|
107
122
|
promotion and anonymous-download checks passed before the post-release launcher
|
|
108
123
|
pin was advanced.
|
|
109
124
|
|
|
110
125
|
### Local delivery
|
|
111
126
|
|
|
112
|
-
GHCR is the canonical delivery channel for normal local use. The released package scaffold selects `ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.
|
|
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.
|
|
113
128
|
|
|
114
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.
|
|
115
130
|
|
|
@@ -139,7 +154,7 @@ unaltraweb-mcp-docker serve --project /absolute/consumer
|
|
|
139
154
|
```
|
|
140
155
|
|
|
141
156
|
The installed default selects its package's full MCP release image, currently
|
|
142
|
-
`ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.
|
|
157
|
+
`ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.6.0`. It resolves that selection to the
|
|
143
158
|
local immutable image ID before executing. The checkout's `MCP_RELEASE_IMAGE`
|
|
144
159
|
is a separate digest pin advanced only after publication; it is not the installed
|
|
145
160
|
wheel's default. This avoids sending a new package back to an older MCP while
|
|
@@ -284,7 +299,7 @@ For that reason:
|
|
|
284
299
|
|
|
285
300
|
## Docker Runtime
|
|
286
301
|
|
|
287
|
-
Release `0.
|
|
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`.
|
|
288
303
|
|
|
289
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.
|
|
290
305
|
|
|
@@ -19,7 +19,7 @@ provenance needed to inspect its origin. The importer keeps that complete unit i
|
|
|
19
19
|
the receiving repository and creates a native page or chapter referencing the PDF.
|
|
20
20
|
The website displays the original; a manual PDF includes all its pages.
|
|
21
21
|
|
|
22
|
-
This capability
|
|
22
|
+
This capability ships in **0.6.0**. It requires a
|
|
23
23
|
containing Python package and Jekyll core, plus the matching PDF worker for manual
|
|
24
24
|
output. The published 0.5.1 runtime predates it. Changing the global MCP selection
|
|
25
25
|
does not update a site's Gemfile, Makefile or PDF-worker selection.
|
|
@@ -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.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# D0 native runtime identity and lifecycle — issue 85
|
|
2
|
+
|
|
3
|
+
Requirements: gaContExt
|
|
4
|
+
`5634ea2e3e42122bb365992dfca9f248feb89dec`,
|
|
5
|
+
[NATIVE_RUNTIME_REQUIREMENTS.md](https://github.com/dosquartsdedocs/gacontext/blob/5634ea2e3e42122bb365992dfca9f248feb89dec/src/bash/mcp_factories/NATIVE_RUNTIME_REQUIREMENTS.md).
|
|
6
|
+
Owner issue: [85](https://github.com/dosquartsdedocs/unaltraweb/issues/85).
|
|
7
|
+
Coordination: [gaContExt 15](https://github.com/dosquartsdedocs/gacontext/issues/15).
|
|
8
|
+
|
|
9
|
+
## Native API mapping
|
|
10
|
+
|
|
11
|
+
The containing 0.7.0 increment adds `runtime_identity` and
|
|
12
|
+
`web://runtime-identity` on the actual serving MCP instance. Both use one
|
|
13
|
+
startup-created object, not a helper CLI. It records a random backend instance,
|
|
14
|
+
process PID/start ticks/PID namespace, start time, interpreter, loaded package
|
|
15
|
+
version and startup package fingerprint. Current bounded package bytes and
|
|
16
|
+
metadata are separate observations; changing metadata cannot rename the loaded
|
|
17
|
+
version. Only engine code/contracts and allowlisted runtime selections are read,
|
|
18
|
+
not site content or arbitrary environment values.
|
|
19
|
+
|
|
20
|
+
The identity's component/profile/selection hashes bind the fixed requirements,
|
|
21
|
+
startup BOM, behavioral profile, worker selections and consumer mapping. The
|
|
22
|
+
package fingerprint is a startup code-content observation, not a wheel checksum
|
|
23
|
+
or a permanent process attestation. The live container's image ID, source label,
|
|
24
|
+
limits and mount mapping are inspected separately. Its daemon-host init PID is
|
|
25
|
+
not compared numerically with the inner serving PID. Session ID, exact container
|
|
26
|
+
ID, factory/role/project labels and mapping correlate those namespaces.
|
|
27
|
+
|
|
28
|
+
`runtime_drain(confirm=true)` freezes admission on that connection. Ordinary
|
|
29
|
+
tools execute in a bounded one-operation lane, leaving identity/drain responsive
|
|
30
|
+
while a worker runs. Closing stdio waits for active work and releases that
|
|
31
|
+
session's idle preview/capture resources. A new connection creates a new backend
|
|
32
|
+
instance. This profile is **one stdio connection per backend**, not a shared HTTP
|
|
33
|
+
service: shared-backend reattachment/idle leases are not claimed.
|
|
34
|
+
|
|
35
|
+
Host-side installed API:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
unaltraweb-mcp-docker prepare --image REF [--expected-image-id SHA256_ID]
|
|
39
|
+
unaltraweb-mcp-docker serve --project ROOT --image REF --expected-image-id SHA256_ID --managed
|
|
40
|
+
unaltraweb-mcp-docker session-status --project ROOT --session-id SESSION --container-id CONTAINER
|
|
41
|
+
unaltraweb-mcp-docker reap-session --project ROOT --session-id SESSION --container-id CONTAINER
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Preparation may acquire the explicitly selected image. Launch/check/smoke never
|
|
45
|
+
build or pull; execution uses its inspected exact configuration ID with
|
|
46
|
+
`--pull never`. Managed mutable aliases require the expected full image ID.
|
|
47
|
+
Full local IDs and repository digests are immutable selections. Ordinary mutable
|
|
48
|
+
local selections without an expected ID remain an explicitly weaker mode.
|
|
49
|
+
Archive hashes, repository/index digests and Docker configuration IDs are distinct.
|
|
50
|
+
|
|
51
|
+
`--offline` disables controller networking; the explicitly mounted local Docker
|
|
52
|
+
socket still permits image/owned-container inspection. Preview HTTP probing and
|
|
53
|
+
intentional external metrics calls need their documented network access.
|
|
54
|
+
`--worker-images` accepts bounded JSON mapping supported worker names to exact
|
|
55
|
+
`reference` / `expected_image_id` pairs. Otherwise startup BOM/dedicated image
|
|
56
|
+
environment selections apply. Managed execution refuses missing/mismatched
|
|
57
|
+
workers and never substitutes a preparation build/pull. Authored computation
|
|
58
|
+
image choices must match the approved startup identity before execution.
|
|
59
|
+
|
|
60
|
+
The normal host launcher canonicalizes the consumer and binds it at its canonical
|
|
61
|
+
path and `/workspace`. A containerized launcher must supply `--host-project` (or
|
|
62
|
+
its explicit inherited daemon mapping); the child uses that verified canonical
|
|
63
|
+
mirror. Identity reports launcher-visible, daemon-host and effective paths.
|
|
64
|
+
Other direct controller layouts are not silently inferred. In particular,
|
|
65
|
+
[issue 31](https://github.com/dosquartsdedocs/unaltraweb/issues/31) remains a separate
|
|
66
|
+
boundary for arbitrary direct `/workspace` controllers and is not automatically
|
|
67
|
+
closed by this profile.
|
|
68
|
+
|
|
69
|
+
## Resource ownership
|
|
70
|
+
|
|
71
|
+
Each launch has a 32-hex session ID and a uniquely named owned stdio container.
|
|
72
|
+
Previews are per-session for these backends. Worker invocation tokens are retained
|
|
73
|
+
and augmented with session labels. Cleanup validates full IDs and ownership and
|
|
74
|
+
confirms absence before claiming release. Image and volume removal is outside
|
|
75
|
+
these APIs.
|
|
76
|
+
|
|
77
|
+
After EOF or a crash, the caller uses the **retained** binding/session/container
|
|
78
|
+
tuple with `session-status`. A live backend is `connected`; a running one-shot
|
|
79
|
+
worker is `busy`; idle leftovers are `orphaned`; only proven absence is `stopped`
|
|
80
|
+
with `resources_released=true`. Unavailable/changed ownership is `unknown` and
|
|
81
|
+
does not authorize removal. `reap-session` preserves a live backend or running
|
|
82
|
+
job, and recovers only that retired session's idle resources. Occupied or foreign
|
|
83
|
+
networks fail closed. No fresh-helper PID is presented as the backend's PID.
|
|
84
|
+
|
|
85
|
+
The legacy `down` / `make mcp-down` is an explicit **workspace-wide** shutdown;
|
|
86
|
+
`mcp-down-all` is maintainer/factory-wide. Neither is the hub's per-client toggle
|
|
87
|
+
operation. The managed sequence is live drain, close this transport, inspect its
|
|
88
|
+
exact retained identity, and recover eligible orphans when necessary.
|
|
89
|
+
|
|
90
|
+
The profile reports controller limits (2 CPUs, 4 GiB, 512 PIDs), preview/PDF/capture
|
|
91
|
+
limits (2 CPUs, 2 GiB, 256 PIDs), and managed computation limits (4 CPUs, 8 GiB,
|
|
92
|
+
512 PIDs). Existing per-invocation time bounds remain 1800 seconds for PDF/compute
|
|
93
|
+
and 900 for captures; requests may compose several bounded jobs. Per-backend
|
|
94
|
+
operation concurrency is one. A drain does not falsely claim immediate RAM/CPU
|
|
95
|
+
release while a job continues.
|
|
96
|
+
|
|
97
|
+
## Accepted visual-helper points and remaining closure blocker
|
|
98
|
+
|
|
99
|
+
The candidate selects the published Diavisuals 0.5.0 and Vega 0.5.1 packages:
|
|
100
|
+
|
|
101
|
+
| Helper | Wheel SHA-256 | Renderer configuration ID |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| Diavisuals 0.5.0 | `f52e20f20f1fb3a2418f07adb8d6a68a5567d0c321fb7c0ccc0f4db04917b96b` | `sha256:5a6887b372a0e1c386a7b54981d11ae1910215baeb6a12dfd0706b3e85ef0846` |
|
|
104
|
+
| Vega 0.5.1 | `5aba4f267a37179c520b3cd164e1cec62ac5561872aa33b069cce73442dc52b1` | `sha256:695125943d0fbc3aa7c877babb9a11a6501bbc7ac265b0975bb5657c60439d98` |
|
|
105
|
+
|
|
106
|
+
Native selector mapping is Diavisuals `--runtime-image` plus
|
|
107
|
+
`--runtime-expected-id`, and Vega `--renderer-image-id`. Published metadata,
|
|
108
|
+
wheel/acceptance hashes and locally prepared renderer IDs were verified. Actual
|
|
109
|
+
Mermaid, PlantUML, Vega-Lite/CSV and Vega rendering passed native receipt checks,
|
|
110
|
+
tamper refusal and consumer relocation without rewriting renderer aliases.
|
|
111
|
+
Retained evidence: `/tmp/opencode/unaltraweb-d0-85/helpers-proof/evidence.json`.
|
|
112
|
+
|
|
113
|
+
Previously accepted **0.4.0 static receipts remain valid** under the unchanged
|
|
114
|
+
input/output/request integrity rules. This is an exact legacy point, not a
|
|
115
|
+
continuous version interval or permission to overwrite edited outputs. New work
|
|
116
|
+
uses the selected helper points. No existing client or real consumer is migrated
|
|
117
|
+
by this source change.
|
|
118
|
+
|
|
119
|
+
The coordinator does not claim to observe another MCP's serving process. Its live
|
|
120
|
+
identity returns the helper selections and requires their independent connection
|
|
121
|
+
observations. **Diavisuals 0.5.0 still lacks the full live-instance identity**;
|
|
122
|
+
[Diavisuals 14](https://github.com/dosquartsdedocs/diavisuals/issues/14) is therefore
|
|
123
|
+
an external D0 managed-closure blocker. Rendering compatibility alone does not
|
|
124
|
+
close that gate or make the whole coordinator dependency graph managed-ready.
|
|
125
|
+
|
|
126
|
+
## Acceptance and delivery state
|
|
127
|
+
|
|
128
|
+
`test/d0_runtime_smoke.py` exercises installed launchers, actual images, tool/resource
|
|
129
|
+
agreement, independent consumers, reconnect, running-container metadata drift,
|
|
130
|
+
busy drain, offline launch, wrong/missing image refusal, manual/web work and
|
|
131
|
+
0.6.0 → containing 0.7.0 → 0.6.0 activation with retained authored/generated state.
|
|
132
|
+
The published 0.6.0 point accurately remains **partial** for live identity; no
|
|
133
|
+
fixture or relabelled package is counted as a second D0-capable release.
|
|
134
|
+
Backend-crash/orphan recovery is exercised separately from graceful disconnect.
|
|
135
|
+
The existing Carta and populated Bundler acceptance drivers remain release gates.
|
|
136
|
+
|
|
137
|
+
This is owner development evidence until reviewed source, containing release
|
|
138
|
+
receipts, installed signed-byte acceptance and remaining blockers are returned to
|
|
139
|
+
the central issue. Published 0.6.0 and its active checkout launcher pin remain
|
|
140
|
+
unchanged during candidate development. The worker/data choices and external
|
|
141
|
+
Diavisuals identity blocker must remain visible in the hub's adapter decision.
|
|
142
|
+
|
|
143
|
+
## Retained local acceptance — 2026-10-05
|
|
144
|
+
|
|
145
|
+
The owner explicitly authorized the full 0.7.0 review/PR/integration, gated
|
|
146
|
+
publication and post-release pin flow. No other checkout is a write workspace.
|
|
147
|
+
|
|
148
|
+
The installed local wheel
|
|
149
|
+
`67689b76225511439175c82b6df033005d84e990b147b8fa4875f3adbd7d684f` and owned MCP
|
|
150
|
+
image `sha256:d8eafba61a2e1f02bc22b244610d8174879e04d9ea36b47a71e8cd7f993a54b1`
|
|
151
|
+
passed eight stages: reconnect/scope, loaded-versus-disk, busy drain, backend
|
|
152
|
+
crash recovery, offline launch, explicit daemon mapping, wrong worker and missing
|
|
153
|
+
worker. The crash record observed a real PDF job still **busy** after backend
|
|
154
|
+
death, then confirmed eligible recovery and resource absence. The other live
|
|
155
|
+
instance was preserved. The published 0.6.0 A/B/A point remained explicitly
|
|
156
|
+
partial for live identity; authored files and its old cache entries kept their
|
|
157
|
+
hashes. This is prepared development evidence, not a signed release identity.
|
|
158
|
+
|
|
159
|
+
| Local retained evidence under `/tmp/opencode/unaltraweb-d0-85/` | SHA-256 |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| `acceptance-final/evidence.json` | `e35457153c5ffe98b4bd231f608735a2c4ad07e9db756699d7446e06e6b0b9c7` |
|
|
162
|
+
| `helpers-proof/evidence.json` | `df994ccd8afaff45a7e3cfa9b6a29b650c9d01d63db2c9c36e59c31834273473` |
|
|
163
|
+
| `carta-proof/evidence.json` | `ac305ad222a792291ebd27679a72a37a3ff29ab4746301ed9db7f64705ca4755` |
|
|
164
|
+
| `bundler-proof/evidence.json` | `b304c4c5abe45ae9295f6eba86eae36be92e348e6be33463fcb50e119550d341` |
|
|
165
|
+
|
|
166
|
+
The Carta proof retains the published sender seal and unchanged original PDF,
|
|
167
|
+
removes the copied producer, relocates the receiver and forces another PDF build.
|
|
168
|
+
Both 11-page manuals have SHA-256
|
|
169
|
+
`46e50f815c007a97ac59898194023de3fa4e916e77e7eac21b73f8792244713c`; the letter is
|
|
170
|
+
on page 10. The four-profile populated Bundler regression passed 0.4.0 → prepared
|
|
171
|
+
0.7.0 → 0.4.0, preserving all six tracked author/cache checksums and separately
|
|
172
|
+
reproducing the known unpatched 0.5.0 failure. No caches were cleared.
|
|
173
|
+
|
|
174
|
+
Review additionally tightened Docker absence classification: an unavailable
|
|
175
|
+
daemon socket is **unknown**, not evidence that a container was removed. That
|
|
176
|
+
source-only correction has a dedicated regression; final release acceptance must
|
|
177
|
+
be repeated against the actual source-bound candidates after integration.
|
|
178
|
+
|
|
179
|
+
The local suite passes 608 tests with 30 optional/environment skips. Distribution,
|
|
180
|
+
workflow, fresh-wheel and extracted-gem gates pass, as do the real MCP smoke,
|
|
181
|
+
manual preparation, docs build, prose checks and whitespace checks. These checks
|
|
182
|
+
do not override the separate signed-candidate/publication gates or the external
|
|
183
|
+
helper-process blocker.
|
|
184
|
+
|
|
185
|
+
## Reviewed core selection
|
|
186
|
+
|
|
187
|
+
Implementation `0c87e8c276e58ac9c747833df69cdb439aa6132b` was reviewed and
|
|
188
|
+
integrated through [PR 87](https://github.com/dosquartsdedocs/unaltraweb/pull/87)
|
|
189
|
+
as `216ab2e8b6b8b45a5bb7da0a54bffd10edee895d`. Protected PR CI
|
|
190
|
+
[37271200816](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37271200816)
|
|
191
|
+
and CodeQL [37271200817](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37271200817)
|
|
192
|
+
passed. The recorded review is agent-attributed.
|
|
193
|
+
|
|
194
|
+
The next candidate source pins that integrated core and authorizes gem, wheel,
|
|
195
|
+
runtime and MCP as `ready` for same-source candidate preparation. The selected
|
|
196
|
+
signed PDF 0.6.0 and computation/capture 0.4.0 workers remain unchanged: the new
|
|
197
|
+
selection/lifecycle behavior is controller-owned. Strict receipt, ancestry,
|
|
198
|
+
candidate, installed-byte and publication gates still apply. This readiness is
|
|
199
|
+
for the containing owner release, not approval of the full managed coordinator
|
|
200
|
+
closure while the external Diavisuals identity gap remains.
|
data/docs/agents/mcp-contract.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# MCP Contract
|
|
2
2
|
|
|
3
|
+
The D0 additions require a containing 0.7.0 runtime. Their pinned requirements,
|
|
4
|
+
exact API mapping, lifecycle scopes and external helper-identity blocker are
|
|
5
|
+
documented in [the owner contract](d0-runtime-identity.md). A source descriptor
|
|
6
|
+
does not upgrade an already-running 0.6.0 connection.
|
|
7
|
+
|
|
3
8
|
`unaltraweb` exposes one global, on-demand stdio MCP server for website workspaces. Every client session starts an independently named Dockerized MCP process and mounts its current consumer project at `/workspace` and at its canonical host path. Stable factory, role, and project labels preserve project-scoped lifecycle control without forcing concurrent sessions to share a deterministic container name. The image includes both FastMCP and the Jekyll runtime, so the host does not need Python, the optional `mcp` package, Ruby, or Bundler.
|
|
4
9
|
|
|
5
10
|
The client registration should launch:
|
|
@@ -32,8 +37,8 @@ it to an image ID before execution. The source checkout's digest pin is separate
|
|
|
32
37
|
it advances only after a new receipt exists. Explicit `--image` (or the console
|
|
33
38
|
adapter's `UNALTRAWEB_MCP_IMAGE`) permits a reviewed immutable selection.
|
|
34
39
|
|
|
35
|
-
The post-release checkout pin selects published 0.
|
|
36
|
-
`sha256:
|
|
40
|
+
The post-release checkout pin selects published 0.6.0 MCP digest
|
|
41
|
+
`sha256:736c4ddd0a543454e3edaeac2e9cfd97a1279ce472923ac54e326c1281b2ba05`.
|
|
37
42
|
Existing processes keep their running image until clients reconnect. Site build
|
|
38
43
|
defaults and customized Makefiles remain separate, explicitly reviewed selections.
|
|
39
44
|
|
|
@@ -43,7 +48,7 @@ Repository editing coordination remains a control-plane responsibility rather th
|
|
|
43
48
|
|
|
44
49
|
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.
|
|
45
50
|
|
|
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
|
|
51
|
+
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 0.7.0 BOM selects owner-tested `diavisuals v0.5.0` and `vegavisuals v0.5.1`; existing 0.4.0 static receipts retain their exact integrity-checked compatibility point. 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.
|
|
47
52
|
|
|
48
53
|
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.
|
|
49
54
|
|
|
@@ -81,6 +86,7 @@ baseline format nor runtime cleanup changes.
|
|
|
81
86
|
|
|
82
87
|
| Resource | Description |
|
|
83
88
|
| --- | --- |
|
|
89
|
+
| `web://runtime-identity` | Bounded identity of this serving process: startup/current code, instance/PID namespaces, binding, runtime selections and cooperative lifecycle. |
|
|
84
90
|
| `web://distribution` | Package-owned component BOM plus offline, feature-aware doctor findings for the current factory and project. |
|
|
85
91
|
| `web://site-context` | Site profile, feature flags, content inventory, bibliography, bibliometrics, build state, and offline consumer-update advisory. |
|
|
86
92
|
| `web://site-doctor` | Read-only offline distribution, project-contract, freshness, scaffold-drift, and core-override findings. |
|
|
@@ -109,6 +115,8 @@ baseline format nor runtime cleanup changes.
|
|
|
109
115
|
|
|
110
116
|
| Tool | Notes |
|
|
111
117
|
| --- | --- |
|
|
118
|
+
| `runtime_identity` | Observe the actual serving instance, startup/current package evidence and selected/observed images; never prepare a runtime or inspect site content. |
|
|
119
|
+
| `runtime_drain` | With `confirm=true`, stop admission on this connection; then close stdio and verify exact container/session resource termination. It is not workspace-wide down. |
|
|
112
120
|
| `distribution_doctor` | Return offline component/factory/project findings with stable codes and optional local Docker image inspection that never pulls. |
|
|
113
121
|
| `new_web` | Create a profile-specific site from package-owned assets after a complete collision, path, and symlink preflight. |
|
|
114
122
|
| `starter_templates` | List package-owned profile scaffolds under the legacy inventory name. |
|
|
@@ -182,7 +190,7 @@ Manual PDF publication is a local workspace operation: it copies reviewed artefa
|
|
|
182
190
|
|
|
183
191
|
### Retained Letter Integration
|
|
184
192
|
|
|
185
|
-
The 0.6.0
|
|
193
|
+
The published 0.6.0 release adds package-only import/check commands and the
|
|
186
194
|
`web://artifact-imports` resource. Web rendering needs its containing Jekyll core;
|
|
187
195
|
manual inclusion also needs the matching PDF worker. Published 0.5.1 components
|
|
188
196
|
do not acquire this capability from a launcher-pin change.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# unaltraweb 0.6.0 delivery closeout
|
|
2
|
+
|
|
3
|
+
Published **2026-10-02 17:28:14 UTC**:
|
|
4
|
+
[v0.6.0](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.6.0).
|
|
5
|
+
Owner coordination: [issue 80](https://github.com/dosquartsdedocs/unaltraweb/issues/80).
|
|
6
|
+
This report supersedes the pending delivery state in the chronological
|
|
7
|
+
[preparation record](retained-letter-import.md). Issue 76 and release 0.5.1
|
|
8
|
+
remain closed and immutable.
|
|
9
|
+
|
|
10
|
+
## Review, source and integration
|
|
11
|
+
|
|
12
|
+
The owner explicitly authorized commits, push, PR review/integration, signed
|
|
13
|
+
candidate workflows, gated publication and the post-release launcher pin. The
|
|
14
|
+
checkout was reconciled against all existing unit-80 paths; no unrelated edits
|
|
15
|
+
were found. Work used one checkout and ordinary serial branches.
|
|
16
|
+
|
|
17
|
+
| Role | Revision / evidence |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| Reviewed implementation | `7af652fb83629e959af05c407a34a2f5a15f7936` |
|
|
20
|
+
| Integrated core selected by consumers | `5cf9817489c8dc47cee726bfe42fe3071cd32b85`, [PR 81](https://github.com/dosquartsdedocs/unaltraweb/pull/81) |
|
|
21
|
+
| Immutable core/PDF selection | `8e93b8b808204faef54cccaee622699f04a11805` |
|
|
22
|
+
| Final artifact-producing source | `de52db351490e94939aac20c6af264f22a6a1678`, [PR 82](https://github.com/dosquartsdedocs/unaltraweb/pull/82) |
|
|
23
|
+
| Receipt-only child | `3ce7606bc6148aee19d067c559823d8c5b52db5d` |
|
|
24
|
+
| Receipt integration and tag target | `ec6dcb28e890d32718aa173934527a7b4213a042`, [PR 83](https://github.com/dosquartsdedocs/unaltraweb/pull/83) |
|
|
25
|
+
| Annotated tag object | `1605578861a1a09157037e6085020baad4948d72` |
|
|
26
|
+
|
|
27
|
+
All three PRs have explicit agent review records and protected CI; those records
|
|
28
|
+
do not claim human review. Merge commits preserve the reviewed core's ancestry.
|
|
29
|
+
The receipt integration's first parent is exactly the artifact-producing source,
|
|
30
|
+
and its first-parent diff contains only `release-candidates.json`.
|
|
31
|
+
|
|
32
|
+
Review closed independent metadata-reference validation, malformed Pandoc-link
|
|
33
|
+
handling, internal PDF OpenAction destinations, and direct signed-runtime
|
|
34
|
+
acceptance. The vendored v1 verifier/schema still match the established hub pin
|
|
35
|
+
byte for byte; 26 reference conformance tests passed against matching fixtures.
|
|
36
|
+
Source checks reported 587 Python cases with 30 optional skips. Ruby, actual PDF,
|
|
37
|
+
MCP, wheel/gem, workflow/distribution, docs and reproducibility gates passed.
|
|
38
|
+
|
|
39
|
+
## Receipt and published identities
|
|
40
|
+
|
|
41
|
+
[Tagged native receipt](https://github.com/dosquartsdedocs/unaltraweb/blob/v0.6.0/release-candidates.json):
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
schema_version: 1
|
|
45
|
+
release: v0.6.0
|
|
46
|
+
source_commit: de52db351490e94939aac20c6af264f22a6a1678
|
|
47
|
+
receipt SHA-256: 5ed4e6dd615367927e6ea8a3541c9e7dca9dad73a738851705f563e0e6895280
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Exactly the four `ready` components are bound to that source:
|
|
51
|
+
|
|
52
|
+
| Component | Registry artifact | SHA-256 / OCI index digest |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| Gem | `unaltraweb-0.6.0.gem` | `276d04a71d1170220c3881cce8d0800633c42b0ee7ad07a376f80996c6afd177` |
|
|
55
|
+
| Wheel | `unaltraweb_mcp-0.6.0-py3-none-any.whl` | `3effb471ffd264f7fb2a8c88dd6536bc86639eae52806527c2d872653944c85a` |
|
|
56
|
+
| Base runtime | `ghcr.io/dosquartsdedocs/unaltraweb` | `sha256:a4e9d82b0e9a72e519c44e09ca449b2dc37964fbb9953ae6e4adff648e39b94b` |
|
|
57
|
+
| Full MCP | `ghcr.io/dosquartsdedocs/unaltraweb-mcp` | `sha256:736c4ddd0a543454e3edaeac2e9cfd97a1279ce472923ac54e326c1281b2ba05` |
|
|
58
|
+
|
|
59
|
+
Both `0.6.0` and `v0.6.0` OCI aliases were inspected anonymously and match those
|
|
60
|
+
index digests. The MCP's local configuration ID is
|
|
61
|
+
`sha256:73320210b19597243c7183ef255ffa1cbc36a07157e6ab4e1b3d9349fa89a063`;
|
|
62
|
+
its revision label is the exact artifact source above. Configuration IDs and
|
|
63
|
+
registry index digests are distinct identities.
|
|
64
|
+
|
|
65
|
+
The selected PDF 0.6.0 is the already-published, signed and tested specialization:
|
|
66
|
+
`ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed`.
|
|
67
|
+
It was produced from core `5cf9817489c8dc47cee726bfe42fe3071cd32b85` by the
|
|
68
|
+
[initial signed image run](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37029374441),
|
|
69
|
+
and its local configuration ID is
|
|
70
|
+
`sha256:d7e7d3243616270fc9e6eed7f8238c412dbe3d9ffc18d2832d17d66ca630d139`.
|
|
71
|
+
The BOM, generated consumer tuple and Make default select that same digest.
|
|
72
|
+
It is reused as `released`, outside the four-component coordinated receipt.
|
|
73
|
+
The later image workflow also tested a verification-only PDF candidate
|
|
74
|
+
`sha256:9b3ae6fe1f04ff7de6c81c258d7c16f79cc7f2857c9b46b0829fc71812ace11f`;
|
|
75
|
+
that candidate is not the selected worker and received no coordinated semver
|
|
76
|
+
promotion. No self-digest or fabricated core SHA was introduced.
|
|
77
|
+
|
|
78
|
+
Computation, capture, Diavisuals and Vegavisuals retain the tested 0.4.0 selections.
|
|
79
|
+
Their exact immutable references remain in the BOM, and earlier published
|
|
80
|
+
artifacts and receipts remain at their original tags.
|
|
81
|
+
|
|
82
|
+
## CI, signing and publication
|
|
83
|
+
|
|
84
|
+
| Gate | Successful run |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| Implementation PR CI / CodeQL | [37027921742](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37027921742) / [37027922332](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37027922332) |
|
|
87
|
+
| Core integration CI | [37028677932](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37028677932) |
|
|
88
|
+
| Tuple PR CI / CodeQL | [37032368507](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37032368507) / [37032368609](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37032368609) |
|
|
89
|
+
| Final source CI / CodeQL | [37033064607](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37033064607) / [37033064633](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37033064633) |
|
|
90
|
+
| Signed final image build/test | [37033593312](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37033593312) |
|
|
91
|
+
| Package preparation | [37033596931](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37033596931) |
|
|
92
|
+
| Receipt PR CI / CodeQL | [37038403708](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37038403708) / [37038403802](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37038403802) |
|
|
93
|
+
| Receipt/tag target CI / CodeQL | [37039075585](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37039075585) / [37039075748](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37039075748) |
|
|
94
|
+
| Tag CI | [37039786598](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37039786598) |
|
|
95
|
+
| Semver image promotion | [37040420721](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37040420721) |
|
|
96
|
+
| PyPI/RubyGems Trusted Publishing | [37040424945](https://github.com/dosquartsdedocs/unaltraweb/actions/runs/37040424945) |
|
|
97
|
+
|
|
98
|
+
The signed image workflows checked exact OCI digests, signer workflow, source
|
|
99
|
+
revision and labels before executing candidates. Promotion reverified those
|
|
100
|
+
bindings and reused the tested manifests without rebuilding. The package
|
|
101
|
+
authorizer bound workflow/run/source, immutable artifact ID `11237594327`, exact
|
|
102
|
+
inventory and checksums to the receipt. Its archive digest is
|
|
103
|
+
`sha256:79a67d7a8370468abe1f0265b248f3e9d6cf6187ac0bc891a0b3801e5a9931a6`.
|
|
104
|
+
OIDC jobs published only the staged verified gem and wheel.
|
|
105
|
+
|
|
106
|
+
The actual receipt-only branch, merged target and annotated tag passed strict
|
|
107
|
+
`distribution-release-check` and publication-ref/ancestry gates. Native package
|
|
108
|
+
run authorization, exact staging and `verify_package_publish.py release` passed
|
|
109
|
+
before privileged publication. Strict release checks apply to the receipt/tag
|
|
110
|
+
revision, not subsequent ordinary post-release source commits.
|
|
111
|
+
|
|
112
|
+
## Real retained-letter and rollback proofs
|
|
113
|
+
|
|
114
|
+
Acceptance consumed the authenticated published Carta 0.3.0rc1 packet, not a local
|
|
115
|
+
producer checkout or synthetic unit fixture. The sender bundle hash is
|
|
116
|
+
`aeaa757ee1be19bfe56dc9af8dd1178032929b4a2bec2dad2ebb621b158ad999`.
|
|
117
|
+
All 12 seal files remain under `.unaltraweb/artifacts/carta/bundle/`.
|
|
118
|
+
The mapping `payload/output/letter.pdf` → `assets/documents/carta.pdf` retains
|
|
119
|
+
SHA-256 `4a661740a18fe1cf75b84aa0d8532511fd105eb5484a5af700e11e8e30828ea4`.
|
|
120
|
+
The native chapter is `_chapters/en/carta.md`, with its separate binding and
|
|
121
|
+
standard-v1 integration record outside the seal.
|
|
122
|
+
|
|
123
|
+
The downloaded final CI wheel ran against the exact signed MCP and selected PDF
|
|
124
|
+
digests above, without deriving another controller image. Both copied producer
|
|
125
|
+
and incoming trees were removed, author prose survived an identical reimport,
|
|
126
|
+
and the receiver was moved before native/generic verification and a forced PDF
|
|
127
|
+
rebuild. Web/HTTP checks passed at both locations. The complete original letter
|
|
128
|
+
appears on page 10 of an 11-page composed manual. Both composed PDFs have hash
|
|
129
|
+
`416e96f66bb6608b1e20bf5e36b6b16133bd4018c17e6c079e8987b736fe9cae`.
|
|
130
|
+
The integration record hash is
|
|
131
|
+
`ebe07ee10ad740a2bbbd36d532f336374cf4bb19ccb373b6590b2279f664a222`.
|
|
132
|
+
Generic verification confirms one bundle, one mapping and 14 verified files;
|
|
133
|
+
the native checker additionally binds the source and rendered page.
|
|
134
|
+
|
|
135
|
+
Local evidence root: `/tmp/opencode/unaltraweb-closeout-060/`.
|
|
136
|
+
|
|
137
|
+
| Retained evidence | SHA-256 |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| `candidate-letter-proof/evidence.json` | `618573b1a867daf6b1f3023e0d5700c27a6de429abea160b4c51ff8699f86f9c` |
|
|
140
|
+
| `candidate-roundtrip/evidence.json` | `23ec8885e8306931fb8ee4899e95b7bff4b3d23d2b63cdd3321e3f68722c3bb8` |
|
|
141
|
+
| `published-packages/verified.json` | `073d7ca1bbe46b8be5d89211501ca8fc7b71297d7eb542c4c9cc27ff167aa91e` |
|
|
142
|
+
|
|
143
|
+
The roundtrip exercised all four profiles using immutable MCP references:
|
|
144
|
+
0.4.0 `sha256:389bc585cdb4fc89d3372f4896a55fe26e15df38b46bc114ce44fdb3f1c8deb9`,
|
|
145
|
+
unpatched 0.5.0 `sha256:36d17edbade77edb40a687f6a744203c6329acb33fbc2eb255e88d9ff1a42c98`,
|
|
146
|
+
then the new 0.6.0 digest. The unpatched failure was reproduced on a separate
|
|
147
|
+
copy. Two builds and a preview passed at 0.6.0 and again after returning to 0.4.0.
|
|
148
|
+
All six author/cache files retained their hashes; no caches were emptied.
|
|
149
|
+
|
|
150
|
+
## Public downloads and post-release selection
|
|
151
|
+
|
|
152
|
+
Anonymous PyPI and RubyGems metadata and package bytes match the receipt exactly.
|
|
153
|
+
GitHub Release assets were downloaded again and pass `SHA256SUMS`, whose own hash
|
|
154
|
+
is `60d80d6e0803154a7b5c98c1731f4bec905def3a481152d4e59d7daf8932fc1a`.
|
|
155
|
+
A fresh public-wheel venv passed default `prepare`, `check` and real stdio `smoke`,
|
|
156
|
+
selecting the expected MCP configuration ID without a local factory dependency.
|
|
157
|
+
That public installation rechecked the relocated receiver and rendered mapping.
|
|
158
|
+
The public gem installed into an isolated gem home and activated as 0.6.0 using
|
|
159
|
+
the runtime's existing Ruby dependencies; this is not a network-fresh dependency
|
|
160
|
+
installation claim. The downloaded candidate gem also passed isolated native
|
|
161
|
+
helper-closure inspection.
|
|
162
|
+
|
|
163
|
+
The source-only post-release branch `chore/80-pin-published-mcp-0.6.0` selects the
|
|
164
|
+
published MCP digest in `Makefile` and `scripts/unaltraweb-mcp-bootstrap.sh`, updates
|
|
165
|
+
the pin regression and current docs, and accompanies this report. Its PR/merge
|
|
166
|
+
and final clean-main confirmation are recorded in issue 80 after protected CI.
|
|
167
|
+
It does not rebuild or alter the published receipt, tag or packages.
|
|
168
|
+
|
|
169
|
+
The post-pin local recheck passed 587 Python cases (558 passed, 29 optional
|
|
170
|
+
skips), distribution/workflow/wheel and prose checks, `mcp-check`, real
|
|
171
|
+
`mcp-smoke` with the selected public PDF, docs build and whitespace checks.
|
|
172
|
+
Development builds used only `unaltraweb-closeout-060-*:post-pin` resources.
|
|
173
|
+
The actual `MCP_CONSUMER_WORKSPACE`-bound `make mcp-stdio` transport also initialized
|
|
174
|
+
a fresh synthetic consumer and exposed both native import tools; Docker inspection
|
|
175
|
+
confirmed the published MCP configuration ID above. Its retained result is
|
|
176
|
+
`/tmp/opencode/unaltraweb-closeout-060/post-pin-proof/evidence.json` and the session
|
|
177
|
+
exited normally. `mcp-build` and the bootstrap's `--check` selected the public
|
|
178
|
+
runtime directly.
|
|
179
|
+
|
|
180
|
+
Acceptance covers the exact Linux/amd64 tuple and published English one-page
|
|
181
|
+
Carta sample. The generic conformance tests do not establish Diapora composition
|
|
182
|
+
or other domain imports. Active IDE processes keep their loaded runtime until
|
|
183
|
+
reconnected. No real manual, author artifact, client registration or helper
|
|
184
|
+
selection was migrated. Consumer adoption and hub catalogue integration remain
|
|
185
|
+
separate owner actions; this report supplies their verified intake evidence.
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Native retained-letter import — issue 80
|
|
2
2
|
|
|
3
|
+
Delivery completed on 2026-10-02; see [the 0.6.0 closeout](owner-closeout-80.md)
|
|
4
|
+
for final revisions, receipts, registry downloads and the post-release pin.
|
|
5
|
+
The following sections retain the chronological preparation and review evidence.
|
|
6
|
+
|
|
3
7
|
## Scope and release state
|
|
4
8
|
|
|
5
9
|
This is a separate 0.6.0 development increment after the administrative closeout
|
|
@@ -142,14 +142,14 @@ def main() -> int:
|
|
|
142
142
|
fake_bin = temp / "fake-bin"
|
|
143
143
|
fake_bin.mkdir()
|
|
144
144
|
fake_docker = fake_bin / "docker"
|
|
145
|
-
fake_docker.write_text("#!/bin/sh\n[ \"$1 $2\" = 'image inspect' ] || exit 99\n[ \"$5\" = \"$EXPECTED_IMAGE\" ] || exit 98\nprintf 'sha256:
|
|
145
|
+
fake_docker.write_text("#!/bin/sh\n[ \"$1 $2\" = 'image inspect' ] || exit 99\n[ \"$5\" = \"$EXPECTED_IMAGE\" ] || exit 98\nprintf 'sha256:1111111111111111111111111111111111111111111111111111111111111111\\n'\n", encoding="utf-8")
|
|
146
146
|
fake_docker.chmod(0o755)
|
|
147
147
|
expected_image = json.loads((ROOT / "src/unaltraweb_mcp/component-contract.json").read_text())["components"]["mcp"]["reference"]
|
|
148
148
|
launcher_env = {**no_consumer_env, "PATH": f"{fake_bin}:{env['PATH']}", "EXPECTED_IMAGE": expected_image}
|
|
149
149
|
launcher_env.pop("UNALTRAWEB_MCP_IMAGE", None)
|
|
150
150
|
launcher_env.pop("MCP_RELEASE_IMAGE", None)
|
|
151
151
|
prepared_image = run([str(docker_cli), "prepare"], cwd=temp, env=launcher_env).stdout.strip()
|
|
152
|
-
if prepared_image != "sha256:
|
|
152
|
+
if prepared_image != "sha256:" + "1" * 64:
|
|
153
153
|
raise RuntimeError("Installed preparation did not use the packaged bootstrap")
|
|
154
154
|
run(["make", "--silent", "--no-print-directory", "-C", str(launcher), "mcp-build"], cwd=temp, env=launcher_env)
|
|
155
155
|
run([str(docker_cli), "prepare", "--image", "explicit:override"], cwd=temp,
|
|
@@ -3,18 +3,28 @@ set -eu
|
|
|
3
3
|
|
|
4
4
|
usage() {
|
|
5
5
|
cat <<'USAGE'
|
|
6
|
-
Usage: unaltraweb-mcp-bootstrap [--project PATH] [--
|
|
6
|
+
Usage: unaltraweb-mcp-bootstrap [--project PATH] [--host-project PATH] [--image IMAGE]
|
|
7
|
+
[--expected-image-id ID] [--managed] [--offline] [--session-id ID] [--worker-images JSON]
|
|
8
|
+
[--prepare|--check|--smoke]
|
|
7
9
|
|
|
8
10
|
Start one Dockerized unaltraweb MCP stdio server for the selected workspace.
|
|
9
11
|
If --project is omitted, MCP_CONSUMER_WORKSPACE is used, then the current directory.
|
|
10
12
|
--prepare inspects or pulls the selected image without mounting a consumer.
|
|
11
|
-
--check and --smoke require that image locally;
|
|
13
|
+
Launch, --check and --smoke require that exact image locally; none builds or pulls.
|
|
14
|
+
Managed mode requires an immutable reference or an expected full image ID.
|
|
12
15
|
USAGE
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
image="${UNALTRAWEB_MCP_IMAGE:-ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:
|
|
18
|
+
image="${UNALTRAWEB_MCP_IMAGE:-ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:736c4ddd0a543454e3edaeac2e9cfd97a1279ce472923ac54e326c1281b2ba05}"
|
|
16
19
|
project="${MCP_CONSUMER_WORKSPACE:-${UNALTRAWEB_PROJECT:-}}"
|
|
17
20
|
operation=serve
|
|
21
|
+
expected_image="${UNALTRAWEB_EXPECTED_IMAGE_ID:-}"
|
|
22
|
+
managed="${UNALTRAWEB_MANAGED_RUNTIME:-0}"
|
|
23
|
+
session_id=""
|
|
24
|
+
host_project=""
|
|
25
|
+
network=bridge
|
|
26
|
+
worker_images="${UNALTRAWEB_WORKER_IMAGES:-}"
|
|
27
|
+
[ -n "$worker_images" ] || worker_images='{}'
|
|
18
28
|
|
|
19
29
|
while [ "$#" -gt 0 ]; do
|
|
20
30
|
case "$1" in
|
|
@@ -28,6 +38,18 @@ while [ "$#" -gt 0 ]; do
|
|
|
28
38
|
image="$2"
|
|
29
39
|
shift 2
|
|
30
40
|
;;
|
|
41
|
+
--host-project|--expected-image-id|--session-id|--worker-images)
|
|
42
|
+
[ "$#" -ge 2 ] || { printf 'Missing value for %s\n' "$1" >&2; exit 2; }
|
|
43
|
+
case "$1" in
|
|
44
|
+
--host-project) host_project=$2 ;;
|
|
45
|
+
--expected-image-id) expected_image=$2 ;;
|
|
46
|
+
--session-id) session_id=$2 ;;
|
|
47
|
+
--worker-images) worker_images=$2 ;;
|
|
48
|
+
esac
|
|
49
|
+
shift 2
|
|
50
|
+
;;
|
|
51
|
+
--managed) managed=1; shift ;;
|
|
52
|
+
--offline) network=none; shift ;;
|
|
31
53
|
--prepare|--check|--smoke)
|
|
32
54
|
[ "$operation" = serve ] || { printf '%s\n' 'Select only one operation.' >&2; exit 2; }
|
|
33
55
|
operation="${1#--}"
|
|
@@ -45,10 +67,33 @@ while [ "$#" -gt 0 ]; do
|
|
|
45
67
|
esac
|
|
46
68
|
done
|
|
47
69
|
|
|
70
|
+
valid_image_id() {
|
|
71
|
+
case "$1" in sha256:*) hex=${1#sha256:} ;; *) return 1 ;; esac
|
|
72
|
+
[ "${#hex}" -eq 64 ] || return 1
|
|
73
|
+
case "$hex" in *[!0-9a-f]*) return 1 ;; esac
|
|
74
|
+
}
|
|
75
|
+
case "$image" in ''|*[!A-Za-z0-9._/:@-]*) printf '%s\n' 'Invalid image reference' >&2; exit 2 ;; esac
|
|
76
|
+
case "$image" in *://*) printf '%s\n' 'Docker references are not URLs' >&2; exit 2 ;; esac
|
|
77
|
+
case "$image" in
|
|
78
|
+
*@*)
|
|
79
|
+
valid_image_id "${image##*@}" || { printf '%s\n' 'Invalid digest reference' >&2; exit 2; }
|
|
80
|
+
case "${image%@*}" in *@*) printf '%s\n' 'Invalid digest reference' >&2; exit 2 ;; esac
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
if [ -n "$expected_image" ]; then
|
|
84
|
+
valid_image_id "$expected_image" || { printf '%s\n' 'Expected image ID must be a full lowercase sha256' >&2; exit 2; }
|
|
85
|
+
managed=1
|
|
86
|
+
fi
|
|
87
|
+
case "$image" in
|
|
88
|
+
sha256:*) valid_image_id "$image" || exit 2; managed=1 ;;
|
|
89
|
+
*@sha256:*) valid_image_id "sha256:${image##*@sha256:}" || exit 2; managed=1 ;;
|
|
90
|
+
*) if [ "$managed" = 1 ] && [ -z "$expected_image" ]; then printf '%s\n' 'Managed mutable references require --expected-image-id' >&2; exit 2; fi ;;
|
|
91
|
+
esac
|
|
92
|
+
|
|
48
93
|
resolve_image() {
|
|
49
94
|
if ! resolved_image="$(docker image inspect --format '{{.Id}}' "$image" 2>/dev/null)"; then
|
|
50
95
|
case "$operation" in
|
|
51
|
-
check|smoke)
|
|
96
|
+
serve|check|smoke)
|
|
52
97
|
printf 'Image is not prepared: %s. Run --prepare first.\n' "$image" >&2
|
|
53
98
|
exit 1
|
|
54
99
|
;;
|
|
@@ -56,14 +101,19 @@ resolve_image() {
|
|
|
56
101
|
docker pull "$image" >&2
|
|
57
102
|
resolved_image="$(docker image inspect --format '{{.Id}}' "$image")"
|
|
58
103
|
fi
|
|
104
|
+
valid_image_id "$resolved_image" || { printf '%s\n' 'Docker returned an invalid image identity' >&2; exit 2; }
|
|
105
|
+
case "$image" in sha256:*) [ "$image" = "$resolved_image" ] || { printf '%s\n' 'Selected image ID mismatch' >&2; exit 1; } ;; esac
|
|
106
|
+
if [ -n "$expected_image" ] && [ "$expected_image" != "$resolved_image" ]; then
|
|
107
|
+
printf '%s\n' 'Prepared image does not match the expected image ID; no fallback was attempted' >&2; exit 1
|
|
108
|
+
fi
|
|
59
109
|
}
|
|
60
110
|
|
|
61
111
|
if [ "$operation" != serve ]; then
|
|
62
112
|
resolve_image
|
|
63
113
|
case "$operation" in
|
|
64
114
|
prepare) printf '%s\n' "$resolved_image"; exit 0 ;;
|
|
65
|
-
check) exec docker run --rm --network none --user "$(id -u):$(id -g)" -e HOME=/tmp --entrypoint unaltraweb-mcp "$resolved_image" version ;;
|
|
66
|
-
smoke) exec docker run --rm --network none --user "$(id -u):$(id -g)" -e HOME=/tmp --entrypoint python3 "$resolved_image" /opt/unaltraweb/test/mcp_smoke.py ;;
|
|
115
|
+
check) exec docker run --rm --pull never --network none --user "$(id -u):$(id -g)" -e HOME=/tmp --entrypoint unaltraweb-mcp "$resolved_image" version ;;
|
|
116
|
+
smoke) exec docker run --rm --pull never --network none --user "$(id -u):$(id -g)" -e HOME=/tmp --entrypoint python3 "$resolved_image" /opt/unaltraweb/test/mcp_smoke.py ;;
|
|
67
117
|
esac
|
|
68
118
|
fi
|
|
69
119
|
|
|
@@ -85,10 +135,28 @@ if [ ! -d "$project" ]; then
|
|
|
85
135
|
fi
|
|
86
136
|
|
|
87
137
|
project="$(CDPATH= cd -- "$project" && pwd -P)"
|
|
138
|
+
launcher_project="$project"
|
|
139
|
+
if [ -z "$host_project" ]; then
|
|
140
|
+
host_project="${UNALTRAWEB_DOCKER_ROOT:-}"
|
|
141
|
+
if [ -n "$host_project" ]; then
|
|
142
|
+
inherited_workspace="${MCP_CONSUMER_WORKSPACE:-}"
|
|
143
|
+
if [ -z "$inherited_workspace" ] || [ ! -d "$inherited_workspace" ] || [ "$(CDPATH= cd -- "$inherited_workspace" && pwd -P)" != "$launcher_project" ]; then
|
|
144
|
+
printf '%s\n' 'Inherited daemon mapping belongs to another or unknown workspace; pass --host-project explicitly' >&2; exit 2
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
if [ -z "$host_project" ] && [ -f /.dockerenv ]; then
|
|
149
|
+
printf '%s\n' 'A containerized launcher needs --host-project with the explicit daemon-host mapping' >&2; exit 2
|
|
150
|
+
fi
|
|
151
|
+
host_project="${host_project:-$project}"
|
|
152
|
+
case "$host_project" in /*) ;; *) printf '%s\n' 'Host project must be absolute' >&2; exit 2 ;; esac
|
|
153
|
+
case "$host_project" in *"$newline"*|*"$carriage_return"*) exit 2 ;; esac
|
|
154
|
+
[ "$host_project" != / ] && [ "$(realpath -ms -- "$host_project")" = "$host_project" ] || { printf '%s\n' 'Host project must be normalized' >&2; exit 2; }
|
|
155
|
+
project="$host_project"
|
|
88
156
|
owner="${UNALTRAWEB_PROJECT_USER:-$(id -u):$(id -g)}"
|
|
89
157
|
docker_socket="${UNALTRAWEB_DOCKER_SOCKET:-/var/run/docker.sock}"
|
|
90
158
|
script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"
|
|
91
|
-
project_id="$(
|
|
159
|
+
project_id="$(printf '%s' "$project" | sha256sum | cut -c 1-16)"
|
|
92
160
|
workspace_mount="$(/bin/sh "$script_dir/unaltraweb-docker-mount.sh" "$project" /workspace)"
|
|
93
161
|
mirror_mount="$(/bin/sh "$script_dir/unaltraweb-docker-mount.sh" "$project" "$project")"
|
|
94
162
|
|
|
@@ -103,7 +171,7 @@ if [ -S "$docker_socket" ]; then
|
|
|
103
171
|
exit 1
|
|
104
172
|
fi
|
|
105
173
|
case "$docker_socket" in
|
|
106
|
-
"$project"|"$project"/*)
|
|
174
|
+
"$project"|"$project"/*|"$launcher_project"|"$launcher_project"/*)
|
|
107
175
|
printf '%s\n' 'UNALTRAWEB_DOCKER_SOCKET must be outside the consumer project so the persistent preview cannot inherit it.' >&2
|
|
108
176
|
exit 1
|
|
109
177
|
;;
|
|
@@ -111,6 +179,9 @@ if [ -S "$docker_socket" ]; then
|
|
|
111
179
|
fi
|
|
112
180
|
|
|
113
181
|
resolve_image
|
|
182
|
+
if [ -z "$session_id" ]; then session_id=$(od -An -N16 -tx1 /dev/urandom | tr -d ' \n'); fi
|
|
183
|
+
[ "${#session_id}" -eq 32 ] || { printf '%s\n' 'Session ID must contain 32 lowercase hex characters' >&2; exit 2; }
|
|
184
|
+
case "$session_id" in *[!0-9a-f]*) exit 2 ;; esac
|
|
114
185
|
image_reference="$image"
|
|
115
186
|
case "$image_reference" in
|
|
116
187
|
ghcr.io/dosquartsdedocs/unaltraweb-mcp@sha256:*) ;;
|
|
@@ -123,10 +194,13 @@ case "$image_reference" in
|
|
|
123
194
|
;;
|
|
124
195
|
esac
|
|
125
196
|
|
|
126
|
-
set -- docker run --rm -i \
|
|
197
|
+
set -- docker run --rm --pull never --init -i \
|
|
198
|
+
--network "$network" \
|
|
199
|
+
--name "unaltraweb-stdio-$session_id" --cpus 2 --memory 4g --pids-limit 512 \
|
|
127
200
|
--label io.context.mcp-factory=unaltraweb \
|
|
128
201
|
--label io.context.mcp-role=stdio \
|
|
129
202
|
--label "io.context.mcp-project=$project_id" \
|
|
203
|
+
--label "io.context.mcp-session=$session_id" \
|
|
130
204
|
--user "$owner" \
|
|
131
205
|
-e HOME=/tmp \
|
|
132
206
|
-e COMPUTE_CORE=/opt/unaltraweb \
|
|
@@ -136,6 +210,13 @@ set -- docker run --rm -i \
|
|
|
136
210
|
-e UNALTRAWEB_FACTORY_DIR=/opt/unaltraweb \
|
|
137
211
|
-e "UNALTRAWEB_MCP_IMAGE=$resolved_image" \
|
|
138
212
|
-e "UNALTRAWEB_MCP_IMAGE_REFERENCE=$image_reference" \
|
|
213
|
+
-e "UNALTRAWEB_MCP_REQUESTED_IMAGE=$image" \
|
|
214
|
+
-e "UNALTRAWEB_EXPECTED_IMAGE_ID=$resolved_image" \
|
|
215
|
+
-e "UNALTRAWEB_RUNTIME_SESSION=$session_id" \
|
|
216
|
+
-e "UNALTRAWEB_MANAGED_RUNTIME=$managed" \
|
|
217
|
+
-e "UNALTRAWEB_RUNTIME_NETWORK=$network" \
|
|
218
|
+
-e "UNALTRAWEB_LAUNCHER_PROJECT=$launcher_project" \
|
|
219
|
+
-e "UNALTRAWEB_WORKER_IMAGES=$worker_images" \
|
|
139
220
|
-e "UNALTRAWEB_PROJECT_USER=$owner" \
|
|
140
221
|
--mount "$workspace_mount" \
|
|
141
222
|
--mount "$mirror_mount" \
|
|
@@ -58,16 +58,48 @@ case "$project_id" in
|
|
|
58
58
|
;;
|
|
59
59
|
esac
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
# Explicit workspace-wide shutdown. Managed per-client detach uses live drain,
|
|
62
|
+
# stdio EOF and the separate session-status/reap-session native adapter instead.
|
|
63
|
+
containers=$(docker ps -aq --no-trunc \
|
|
62
64
|
--filter "label=io.context.mcp-factory=unaltraweb" \
|
|
63
65
|
--filter "label=io.context.mcp-project=$project_id")
|
|
64
|
-
|
|
65
|
-
docker rm -f $containers >/dev/null
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
networks=$(docker network ls -q \
|
|
66
|
+
networks=$(docker network ls -q --no-trunc \
|
|
69
67
|
--filter "label=io.context.mcp-factory=unaltraweb" \
|
|
70
68
|
--filter "label=io.context.mcp-project=$project_id")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
|
|
70
|
+
valid_id() {
|
|
71
|
+
[ "${#1}" -eq 64 ] || return 1
|
|
72
|
+
case "$1" in *[!0-9a-f]*) return 1 ;; esac
|
|
73
|
+
}
|
|
74
|
+
count=0
|
|
75
|
+
for cid in $containers; do
|
|
76
|
+
count=$((count + 1))
|
|
77
|
+
[ "$count" -le 64 ] && valid_id "$cid" || { printf '%s\n' 'Container inventory is invalid or exceeds bounds' >&2; exit 2; }
|
|
78
|
+
labels=$(docker container inspect --format '{{index .Config.Labels "io.context.mcp-factory"}}|{{index .Config.Labels "io.context.mcp-role"}}|{{index .Config.Labels "io.context.mcp-project"}}' "$cid")
|
|
79
|
+
case "$labels" in
|
|
80
|
+
"unaltraweb|stdio|$project_id"|"unaltraweb|preview|$project_id"|"unaltraweb|computation|$project_id"|"unaltraweb|manual-pdf|$project_id"|"unaltraweb|web-capture|$project_id"|"unaltraweb|web-capture-site|$project_id") ;;
|
|
81
|
+
*) printf '%s\n' 'Refusing unknown container ownership' >&2; exit 2 ;;
|
|
82
|
+
esac
|
|
83
|
+
done
|
|
84
|
+
for nid in $networks; do
|
|
85
|
+
count=$((count + 1))
|
|
86
|
+
[ "$count" -le 64 ] && valid_id "$nid" || { printf '%s\n' 'Network inventory is invalid or exceeds bounds' >&2; exit 2; }
|
|
87
|
+
labels=$(docker network inspect --format '{{index .Labels "io.context.mcp-factory"}}|{{index .Labels "io.context.mcp-role"}}|{{index .Labels "io.context.mcp-project"}}' "$nid")
|
|
88
|
+
[ "$labels" = "unaltraweb|web-capture|$project_id" ] || { printf '%s\n' 'Refusing unknown network ownership' >&2; exit 2; }
|
|
89
|
+
done
|
|
90
|
+
if [ -n "$containers" ]; then docker rm -f $containers >/dev/null; fi
|
|
91
|
+
if [ -n "$networks" ]; then docker network rm $networks >/dev/null; fi
|
|
92
|
+
for cid in $containers; do
|
|
93
|
+
if observed=$(docker container inspect --format '{{.Id}}' "$cid" 2>&1); then
|
|
94
|
+
printf '%s\n' 'Container termination is not confirmed' >&2; exit 1
|
|
95
|
+
else
|
|
96
|
+
case "$observed" in *"No such container"*|*"no such container"*|*"No such object"*) ;; *) printf '%s\n' 'Container absence is unknown' >&2; exit 1 ;; esac
|
|
97
|
+
fi
|
|
98
|
+
done
|
|
99
|
+
for nid in $networks; do
|
|
100
|
+
if observed=$(docker network inspect --format '{{.Id}}' "$nid" 2>&1); then
|
|
101
|
+
printf '%s\n' 'Network removal is not confirmed' >&2; exit 1
|
|
102
|
+
else
|
|
103
|
+
case "$observed" in *"No such network"*|*"no such network"*|*"No such object"*) ;; *) printf '%s\n' 'Network absence is unknown' >&2; exit 1 ;; esac
|
|
104
|
+
fi
|
|
105
|
+
done
|
|
@@ -588,6 +588,8 @@ def internal_network(network: str) -> bool:
|
|
|
588
588
|
|
|
589
589
|
def build_image(image: str) -> None:
|
|
590
590
|
available = inspect_image(image)["available"] == "true"
|
|
591
|
+
if not available and os.environ.get("UNALTRAWEB_MANAGED_RUNTIME") == "1":
|
|
592
|
+
raise WebCaptureError("Selected capture image is not prepared; managed execution never pulls")
|
|
591
593
|
if available:
|
|
592
594
|
return
|
|
593
595
|
completed = subprocess.run(["docker", "pull", image], check=False)
|
|
@@ -722,6 +724,9 @@ def run_worker(project: Path, image: str, config_path: Path) -> None:
|
|
|
722
724
|
"project": os.environ.get("UNALTRAWEB_WORKER_PROJECT", "").strip(),
|
|
723
725
|
"token": os.environ.get("UNALTRAWEB_WORKER_TOKEN", "").strip(),
|
|
724
726
|
}
|
|
727
|
+
session = os.environ.get("UNALTRAWEB_RUNTIME_SESSION", "")
|
|
728
|
+
if session and not re.fullmatch(r"[0-9a-f]{32}", session):
|
|
729
|
+
raise WebCaptureError("Invalid runtime session identity")
|
|
725
730
|
worker_args: list[str] = []
|
|
726
731
|
cidfile: Path | None = None
|
|
727
732
|
if any(worker_values.values()):
|
|
@@ -739,7 +744,9 @@ def run_worker(project: Path, image: str, config_path: Path) -> None:
|
|
|
739
744
|
"--label", f"io.context.mcp-worker-token={worker_values['token']}",
|
|
740
745
|
]
|
|
741
746
|
command = [
|
|
742
|
-
"docker", "run", "--rm",
|
|
747
|
+
"docker", "run", "--rm", "--pull", "never", *worker_args,
|
|
748
|
+
*(["--label", f"io.context.mcp-session={session}"] if session else []),
|
|
749
|
+
"--user", f"{os.getuid()}:{os.getgid()}", "--network", network, "--ipc=host",
|
|
743
750
|
"--read-only", "--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--pids-limit", "256", "--cpus", "2", "--memory", "2g",
|
|
744
751
|
"--tmpfs", "/tmp:rw,noexec,nosuid,size=512m", "-e", "HOME=/tmp",
|
|
745
752
|
"--mount", docker_bind_mount(project, "/project"), "-w", "/project", image,
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"$schema": "component-contract.schema.json",
|
|
3
3
|
"schema_version": 1,
|
|
4
4
|
"release": {
|
|
5
|
-
"version": "0.
|
|
6
|
-
"tag": "v0.
|
|
5
|
+
"version": "0.7.0",
|
|
6
|
+
"tag": "v0.7.0"
|
|
7
7
|
},
|
|
8
8
|
"consumer_integration": {
|
|
9
9
|
"schema_version": 1,
|
|
10
10
|
"core_repository": "https://github.com/dosquartsdedocs/unaltraweb.git",
|
|
11
|
-
"core_sha": "
|
|
11
|
+
"core_sha": "216ab2e8b6b8b45a5bb7da0a54bffd10edee895d",
|
|
12
12
|
"site_deploy_workflow": "dosquartsdedocs/unaltraweb/.github/workflows/site-deploy.yml",
|
|
13
13
|
"manual_pdf_image": "ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed",
|
|
14
|
-
"vegavisuals_sha": "
|
|
14
|
+
"vegavisuals_sha": "a448cc50a5f511743a6fcfc213baeb9be80f4a27"
|
|
15
15
|
},
|
|
16
16
|
"receipt_contract": {
|
|
17
17
|
"schema_version": 1,
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"gem": {
|
|
37
37
|
"kind": "gem",
|
|
38
38
|
"name": "unaltraweb",
|
|
39
|
-
"version": "0.
|
|
40
|
-
"release": "v0.
|
|
39
|
+
"version": "0.7.0",
|
|
40
|
+
"release": "v0.7.0",
|
|
41
41
|
"release_status": "ready",
|
|
42
|
-
"reference": "unaltraweb (= 0.
|
|
42
|
+
"reference": "unaltraweb (= 0.7.0)",
|
|
43
43
|
"repository": "https://github.com/dosquartsdedocs/unaltraweb",
|
|
44
44
|
"included_in_wheel": false,
|
|
45
45
|
"features": ["jekyll-core", "site-build"]
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"wheel": {
|
|
48
48
|
"kind": "python-wheel",
|
|
49
49
|
"name": "unaltraweb-mcp",
|
|
50
|
-
"version": "0.
|
|
51
|
-
"release": "v0.
|
|
50
|
+
"version": "0.7.0",
|
|
51
|
+
"release": "v0.7.0",
|
|
52
52
|
"release_status": "ready",
|
|
53
|
-
"reference": "unaltraweb-mcp==0.
|
|
53
|
+
"reference": "unaltraweb-mcp==0.7.0",
|
|
54
54
|
"repository": "https://github.com/dosquartsdedocs/unaltraweb",
|
|
55
55
|
"included_in_wheel": true,
|
|
56
56
|
"features": ["calibre-import", "doctor", "new-web", "offline-inspection", "mcp-control-plane"]
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"runtime": {
|
|
59
59
|
"kind": "container",
|
|
60
60
|
"name": "unaltraweb runtime",
|
|
61
|
-
"version": "0.
|
|
62
|
-
"release": "v0.
|
|
61
|
+
"version": "0.7.0",
|
|
62
|
+
"release": "v0.7.0",
|
|
63
63
|
"release_status": "ready",
|
|
64
|
-
"reference": "ghcr.io/dosquartsdedocs/unaltraweb:0.
|
|
64
|
+
"reference": "ghcr.io/dosquartsdedocs/unaltraweb:0.7.0",
|
|
65
65
|
"image_repository": "ghcr.io/dosquartsdedocs/unaltraweb",
|
|
66
66
|
"repository": "https://github.com/dosquartsdedocs/unaltraweb",
|
|
67
67
|
"included_in_wheel": false,
|
|
@@ -70,10 +70,10 @@
|
|
|
70
70
|
"mcp": {
|
|
71
71
|
"kind": "container",
|
|
72
72
|
"name": "unaltraweb MCP runtime",
|
|
73
|
-
"version": "0.
|
|
74
|
-
"release": "v0.
|
|
73
|
+
"version": "0.7.0",
|
|
74
|
+
"release": "v0.7.0",
|
|
75
75
|
"release_status": "ready",
|
|
76
|
-
"reference": "ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.
|
|
76
|
+
"reference": "ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.7.0",
|
|
77
77
|
"image_repository": "ghcr.io/dosquartsdedocs/unaltraweb-mcp",
|
|
78
78
|
"repository": "https://github.com/dosquartsdedocs/unaltraweb",
|
|
79
79
|
"included_in_wheel": false,
|
|
@@ -130,10 +130,10 @@
|
|
|
130
130
|
"diavisuals": {
|
|
131
131
|
"kind": "companion",
|
|
132
132
|
"name": "diavisuals",
|
|
133
|
-
"version": "0.
|
|
134
|
-
"release": "v0.
|
|
133
|
+
"version": "0.5.0",
|
|
134
|
+
"release": "v0.5.0",
|
|
135
135
|
"release_status": "released",
|
|
136
|
-
"reference": "https://github.com/dosquartsdedocs/diavisuals/releases/download/v0.
|
|
136
|
+
"reference": "https://github.com/dosquartsdedocs/diavisuals/releases/download/v0.5.0/diavisuals-0.5.0-py3-none-any.whl#sha256=f52e20f20f1fb3a2418f07adb8d6a68a5567d0c321fb7c0ccc0f4db04917b96b",
|
|
137
137
|
"repository": "https://github.com/dosquartsdedocs/diavisuals",
|
|
138
138
|
"included_in_wheel": false,
|
|
139
139
|
"features": ["mermaid", "plantuml"]
|
|
@@ -141,10 +141,10 @@
|
|
|
141
141
|
"vegavisuals": {
|
|
142
142
|
"kind": "companion",
|
|
143
143
|
"name": "vegavisuals",
|
|
144
|
-
"version": "0.
|
|
145
|
-
"release": "v0.
|
|
144
|
+
"version": "0.5.1",
|
|
145
|
+
"release": "v0.5.1",
|
|
146
146
|
"release_status": "released",
|
|
147
|
-
"reference": "https://github.com/dosquartsdedocs/vegavisuals/releases/download/v0.
|
|
147
|
+
"reference": "https://github.com/dosquartsdedocs/vegavisuals/releases/download/v0.5.1/vegavisuals-0.5.1-py3-none-linux_x86_64.whl#sha256=5aba4f267a37179c520b3cd164e1cec62ac5561872aa33b069cce73442dc52b1",
|
|
148
148
|
"repository": "https://github.com/dosquartsdedocs/vegavisuals",
|
|
149
149
|
"included_in_wheel": false,
|
|
150
150
|
"features": ["vega", "vega-lite"]
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: unaltraweb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dosquartsdedocs
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: classifier-reborn
|
|
@@ -782,6 +782,7 @@ files:
|
|
|
782
782
|
- docs/_documentation/en/43-workspace-path-policies.md
|
|
783
783
|
- docs/_documentation/en/44-editorial-review.md
|
|
784
784
|
- docs/_documentation/en/45-retained-documents.md
|
|
785
|
+
- docs/_documentation/en/46-live-runtime.md
|
|
785
786
|
- docs/_documentation/en/50-faq.md
|
|
786
787
|
- docs/_pages/ca/index.md
|
|
787
788
|
- docs/_pages/en/index.md
|
|
@@ -799,9 +800,11 @@ files:
|
|
|
799
800
|
- docs/agents/action-prompts/50-bibliography-entry.txt
|
|
800
801
|
- docs/agents/action-prompts/60-bibliometrics-refresh.txt
|
|
801
802
|
- docs/agents/action-prompts/70-build-and-review.txt
|
|
803
|
+
- docs/agents/d0-runtime-identity.md
|
|
802
804
|
- docs/agents/manual-authoring-components.md
|
|
803
805
|
- docs/agents/mcp-contract.md
|
|
804
806
|
- docs/agents/owner-closeout-76.md
|
|
807
|
+
- docs/agents/owner-closeout-80.md
|
|
805
808
|
- docs/agents/owner-followup-76.md
|
|
806
809
|
- docs/agents/owner-preparation-2026-09-29.md
|
|
807
810
|
- docs/agents/quarto-computation-adoption.md
|