unaltraweb 0.7.0 → 0.7.2
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 +27 -5
- data/docs/_documentation/en/33-reusable-workflows.md +28 -3
- data/docs/_documentation/en/40-distribution.md +57 -19
- data/docs/_documentation/en/43-workspace-path-policies.md +13 -0
- data/docs/_documentation/en/46-live-runtime.md +6 -3
- data/docs/_documentation/en/47-private-practice-pdfs.md +130 -0
- data/docs/agents/consolidation-0.7.2.md +97 -0
- data/docs/agents/d0-runtime-identity.md +22 -5
- data/docs/agents/deploy-provenance-86.md +86 -0
- data/docs/agents/deployment-integration-0.7.1.md +142 -0
- data/docs/agents/manual-authoring-components.md +23 -0
- data/docs/agents/mcp-contract.md +112 -6
- data/docs/agents/owner-closeout-85.md +269 -0
- data/docs/agents/owner-closeout-93.md +185 -0
- data/docs/agents/practice-editions-98.md +816 -0
- data/docs/agents/practice-pdf-installable-98.md +250 -0
- data/docs/agents/practice-runtime-archives-98.md +147 -0
- data/docs/agents/private-practice-verifier-98.md +296 -0
- data/docs/agents/source-ci-98.md +148 -0
- data/scripts/check_practice_verifier_runtime.py +69 -0
- data/scripts/export_practice_runtime_archives.py +138 -0
- data/scripts/manual/filters/practice-finish.lua +36 -0
- data/scripts/manual/filters/practice-layout.lua +84 -0
- data/scripts/manual/practice_pdf.py +31 -0
- data/scripts/manual/render_practice.py +125 -0
- data/scripts/manual/templates/practice.tex +95 -0
- data/scripts/prepare_practice_candidate.py +159 -0
- data/scripts/prepare_practice_editions_candidate.py +119 -0
- data/scripts/test_wheel_install.py +16 -1
- data/scripts/unaltraweb-mcp-bootstrap.sh +1 -1
- data/scripts/validate_distribution.py +51 -5
- data/scripts/validate_workflows.py +33 -4
- data/src/unaltraweb_mcp/component-contract.json +59 -22
- data/src/unaltraweb_mcp/component-contract.schema.json +35 -2
- data/src/unaltraweb_mcp/distribution.py +42 -2
- data/src/unaltraweb_mcp/editorial_sources.py +62 -4
- metadata +22 -2
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
# Web #98 / gaContExt #32 — verified recipient edition composition
|
|
2
|
+
|
|
3
|
+
**Completed as an immutable local candidate, 2026-10-09.** No commit, push,
|
|
4
|
+
publication, manual migration or general runtime work is authorised by this return.
|
|
5
|
+
|
|
6
|
+
**Current final integration: `candidate-04`**, with the explicitly selected QGIS
|
|
7
|
+
rc2 v1/v2 profiles described under [Native rc2 integration](#native-rc2-integration--candidate-04).
|
|
8
|
+
The shared reading-resource/link resolver from candidate-03 is preserved. Earlier
|
|
9
|
+
candidate identities and evidence remain retained historical checkpoints.
|
|
10
|
+
|
|
11
|
+
The later [working-tree consolidation](#working-tree-consolidation--independent-pdf-and-zip)
|
|
12
|
+
adds the independent delivery PDF. It is not part of the immutable candidate-04 image.
|
|
13
|
+
The subsequent [private-runtime bridge](private-practice-verifier-98.md) supersedes
|
|
14
|
+
the embedded-verifier plan for public 0.7.2; all candidate descriptions below remain historical.
|
|
15
|
+
|
|
16
|
+
## Checkout, preservation and reservation
|
|
17
|
+
|
|
18
|
+
- Authoritative checkout: `/home/benizar/git/unaltraweb`.
|
|
19
|
+
- Branch: `feat/98-installable-practice-pdf`.
|
|
20
|
+
- Git HEAD/base: `d37ef4c64eb7d2f2e7ef83cf037640ff42a964e0`.
|
|
21
|
+
- Preflight found one checkout, no conflicts or competing session. Its sole
|
|
22
|
+
dirty-checkout finding was the five phase-1 files explicitly authorised for
|
|
23
|
+
continuation. Those files and all phase-1 candidates/receipts are preserved.
|
|
24
|
+
- W1 remains on its existing branch/PR #103; no new generic manager or ledger.
|
|
25
|
+
- [Phase-2 exact reservation](https://github.com/dosquartsdedocs/unaltraweb/issues/98#issuecomment-6079361656)
|
|
26
|
+
and [private editorial mapping addendum](https://github.com/dosquartsdedocs/unaltraweb/issues/98#issuecomment-6079528210).
|
|
27
|
+
|
|
28
|
+
Implementation paths: `src/unaltraweb_mcp/practice_editions.py`,
|
|
29
|
+
`practice-edition-v1.schema.json`, `practice_pdf.py`, `editorial_sources.py`,
|
|
30
|
+
`site_tools.py`, `cli.py`, `mcp_server.py`, `component-contract.json`; `Makefile`,
|
|
31
|
+
`mcp-factory.yml`, `pyproject.toml`. Tests: `test/test_practice_editions.py`,
|
|
32
|
+
`test/test_editorial.py`, `test/practice_editions_smoke.py`. Preparation:
|
|
33
|
+
`scripts/prepare_practice_editions_candidate.py` and
|
|
34
|
+
`packaging/practice-editions-candidate/Dockerfile`. Docs: this file and
|
|
35
|
+
`docs/agents/mcp-contract.md`. All changes remain uncommitted in this checkout.
|
|
36
|
+
|
|
37
|
+
## Installed candidate and identities
|
|
38
|
+
|
|
39
|
+
Delivery directory (different from phase 1):
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/candidate-02/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| Artifact | SHA-256 |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `candidate.json` | `2ca91e63446393d1d0c479609d003ba21bc9576280fc46cada58acf024cfc192` |
|
|
48
|
+
| `packages/unaltraweb_mcp-0.7.1-py3-none-any.whl` | `e02fec9054ebe5ac5b08e27783bb763181a04e21a64d1b577beb343e986bc86a` |
|
|
49
|
+
| `controller.docker.tar.gz` | `0de5df95bfb895021b127a5616cfe6b7d37df920587f7b4bcc1561b76d2421dd` |
|
|
50
|
+
| `source.tar.gz` | `d42689458b53479cc9cf9c4c0a215cefb1de5481b46b926fda4728df72e0528d` |
|
|
51
|
+
| Web composition schema | `35a10534611d36a708af455dc07329f2003817e51da5b4631efb805fcea5d168` |
|
|
52
|
+
|
|
53
|
+
Prepared controller **configuration ID** (not an invented registry digest):
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
sha256:eb7fe76944d0c3238f2d00868cbacc76794ced8966d9b4fdad75adf606d3ab33
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Its archive is 525,065,228 bytes and has been loaded with Docker. It identifies
|
|
60
|
+
the exact source snapshot by SHA-256, comprising the approved Git base and the
|
|
61
|
+
eleven explicit overlays listed and hashed in `candidate.json`. It does not claim
|
|
62
|
+
that those uncommitted bytes equal Git HEAD. Package metadata remains `0.7.1`;
|
|
63
|
+
this is an **unpublished hash-bound successor**, never the published 0.7.1 wheel
|
|
64
|
+
or image. No existing candidate/release was overwritten.
|
|
65
|
+
|
|
66
|
+
The installed QGIS dependency is the owner-delivered wheel, not copied domain
|
|
67
|
+
source or a Web parser:
|
|
68
|
+
|
|
69
|
+
- `unaltracaptura-qgis 0.6.0rc1`, wheel
|
|
70
|
+
`82f2c6772fa8bb9aaae08237494af72df7e103038643fd6dfcdcd6f1ac45ed5f`.
|
|
71
|
+
- Installed source/assets revision
|
|
72
|
+
`sha256:69b61a4b144d2de9a3aa6344ebfb53d93269437bbe627c899b508235b668443c`.
|
|
73
|
+
- Producer schema `qgis-practice-v1`, hash
|
|
74
|
+
`9bc7f15ede9d67b3e1209c329da13d9fcb08004090d05b27662a43de6edf3445`.
|
|
75
|
+
- Prepared QGIS engine
|
|
76
|
+
`sha256:1003721d96abe9607d8337b36851f9b29f84c2f8f92b377d1a73ff03c9d15cd2`.
|
|
77
|
+
- Shared transfer marker and all eight transfer-file hashes were checked. Fixture
|
|
78
|
+
ZIP `ea6fbae78c93e8e0fc516a513cab246d0af7d36886585beff70cab79a65f762c`,
|
|
79
|
+
complete 27-file sender seal
|
|
80
|
+
`abd44b02101243a3ddfd492357c2882e6a3f62248dde192616159944c41056a4`.
|
|
81
|
+
|
|
82
|
+
The prepared PDF remains
|
|
83
|
+
`ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:1bb3f2dafd741e96c28639ec1cc8ccaeb81cbaa73e649f787c0b4ef59997bd4b`,
|
|
84
|
+
configuration ID `sha256:618163d3f924439792b2306617bd9612f566c5881166102fa544b4e782d569fa`,
|
|
85
|
+
producer `b7ec1d7a139c65b3b0b88699cdbeb19080f13be1`.
|
|
86
|
+
Consumer core and the independent workflow pin stay
|
|
87
|
+
`3332e0b93933f12317e05f1ce8d38ce80046feab`. All nine retained-document checker
|
|
88
|
+
files still agree between installed controller, selected core and PDF worker.
|
|
89
|
+
|
|
90
|
+
## One public composition API
|
|
91
|
+
|
|
92
|
+
MCP: **`manual_practice_compose(config, dry_run=false)`**.
|
|
93
|
+
Schema resource: **`web://practice-edition-schema`**.
|
|
94
|
+
CLI inside the installed controller:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
unaltraweb-mcp --project /absolute/manual mcp manual-practice-compose \
|
|
98
|
+
--config practiques/candidate/edition.json --dry-run
|
|
99
|
+
unaltraweb-mcp --project /absolute/manual mcp manual-practice-compose \
|
|
100
|
+
--config practiques/candidate/edition.json
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The same implementation is used by the factory Make target:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
MCP_CONSUMER_WORKSPACE=/absolute/manual \
|
|
107
|
+
PRACTICE_EDITION_CONFIG=practiques/candidate/edition.json \
|
|
108
|
+
make --silent --no-print-directory -C /opt/unaltraweb manual-practice-compose
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
It requires an absolute selected consumer and an indexed, non-ignored edition
|
|
112
|
+
configuration. It verifies Git ignores and Jekyll exclusions before work. Source
|
|
113
|
+
reading hashes explicitly bind the author's edition selection; mechanical review
|
|
114
|
+
does not confer author approval. The independent GIS activity/job version stays
|
|
115
|
+
in the producer report; the edition version governs only reading/delivery output.
|
|
116
|
+
|
|
117
|
+
Example versioned consumer configuration (replace the two reading hashes):
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
schema_version: 1
|
|
121
|
+
kind: unaltraweb-practice-edition
|
|
122
|
+
slug: candidate
|
|
123
|
+
version: 2026-10-r1
|
|
124
|
+
language: ca
|
|
125
|
+
gis:
|
|
126
|
+
bundle: sandbox/gis/delivery/bundle.json
|
|
127
|
+
sha256: abd44b02101243a3ddfd492357c2882e6a3f62248dde192616159944c41056a4
|
|
128
|
+
verifier:
|
|
129
|
+
package: unaltracaptura-qgis
|
|
130
|
+
version: 0.6.0rc1
|
|
131
|
+
revision: sha256:69b61a4b144d2de9a3aa6344ebfb53d93269437bbe627c899b508235b668443c
|
|
132
|
+
wheel_sha256: 82f2c6772fa8bb9aaae08237494af72df7e103038643fd6dfcdcd6f1ac45ed5f
|
|
133
|
+
schema_sha256: 9bc7f15ede9d67b3e1209c329da13d9fcb08004090d05b27662a43de6edf3445
|
|
134
|
+
teacher_only: [resolved-project, resolved-data, resolved-project-svg, resolved-project-original]
|
|
135
|
+
selection:
|
|
136
|
+
alumnat: [initial-project]
|
|
137
|
+
docent: [resolved-project, resolved-project-svg]
|
|
138
|
+
readings:
|
|
139
|
+
alumnat:
|
|
140
|
+
source: practiques/candidate/ca/alumnat/LLEGIU-ME.md
|
|
141
|
+
approved_sha256: REPLACE_WITH_EXACT_SOURCE_SHA256
|
|
142
|
+
docent:
|
|
143
|
+
source: practiques/candidate/ca/docent/LLEGIU-ME.md
|
|
144
|
+
approved_sha256: REPLACE_WITH_EXACT_SOURCE_SHA256
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The producer's installed `practice-schema` identity/schema and pip-recorded wheel
|
|
148
|
+
hash must match the pin. Web runs public `practice-check` only, verifies the whole
|
|
149
|
+
bundle independently with the unchanged generic verifier, and consumes each
|
|
150
|
+
returned ID/path/hash/bytes/role/dependency row. It never scans QGZ or guesses a
|
|
151
|
+
dependency. Required dependencies cannot be silently removed by a recipient filter:
|
|
152
|
+
an ineligible closure is refused in its entirety. Student closures reject resolved
|
|
153
|
+
project/data roles and all explicitly teacher-only IDs. Source/control/rebuild
|
|
154
|
+
roles are not classroom delivery products.
|
|
155
|
+
|
|
156
|
+
Outputs are atomically installed as a new directory:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
dist/practiques/<slug>/<version>/<lang>/
|
|
160
|
+
<slug>-<version>-<lang>.zip
|
|
161
|
+
<slug>-<version>-<lang>.zip.receipt.json
|
|
162
|
+
<slug>-docent-<version>-<lang>.zip
|
|
163
|
+
<slug>-docent-<version>-<lang>.zip.receipt.json
|
|
164
|
+
edition.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
An existing edition directory is always refused, including an unchanged repeat.
|
|
168
|
+
ZIP members are the exact producer closure at its unchanged `payload/...` relative
|
|
169
|
+
paths, the corresponding `LLEGIU-ME.pdf`/`LEEME.pdf`/`README.pdf`, and explicitly
|
|
170
|
+
selected author resources. Editable Markdown remains at its original versioned
|
|
171
|
+
consumer path and is hash-linked through external receipts and PDF snapshots.
|
|
172
|
+
Receipts/control scripts/reconstruction sources are not inserted into the ZIPs.
|
|
173
|
+
Partial same-parent candidates remain diagnosable on failure; no cleanup is implied.
|
|
174
|
+
Ignored `dist` remains a protected retained delivery.
|
|
175
|
+
|
|
176
|
+
## Explicit private reading mapping and editorial support
|
|
177
|
+
|
|
178
|
+
New sources use the canonical `practiques/<slug>/<lang>/<recipient>/...` path.
|
|
179
|
+
Existing sources can be declared once in `_config.yml`:
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
exclude: [practiques/, sandbox/, dist/, _practices/]
|
|
183
|
+
unaltraweb:
|
|
184
|
+
practices:
|
|
185
|
+
readings:
|
|
186
|
+
- source: _practices/tigit-projecte-territorial/ca/alumnat/LLEGIU-ME.md
|
|
187
|
+
slug: tigit-projecte-territorial
|
|
188
|
+
lang: ca
|
|
189
|
+
recipient: alumnat
|
|
190
|
+
- source: _practices/tigit-projecte-territorial/ca/docent/LLEGIU-ME.md
|
|
191
|
+
slug: tigit-projecte-territorial
|
|
192
|
+
lang: ca
|
|
193
|
+
recipient: docent
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Composition and `manual_practice_pdf_build` reuse the same resolver as targeted
|
|
197
|
+
`prose_check` and `editorial_review_prepare`. Draft/unpublished private readings
|
|
198
|
+
produce nonzero source/fragment coverage and original-path anchors. They stay
|
|
199
|
+
outside the default public corpus; selecting the whole `_practices` directory or
|
|
200
|
+
arbitrary `context` files is not granted by this mapping. Duplicate identities,
|
|
201
|
+
cross-recipient canonical paths, traversal, non-Markdown and unknown sources fail.
|
|
202
|
+
|
|
203
|
+
The installed legacy-path test reports **files_checked:1 for each recipient**,
|
|
204
|
+
prepares source-digest-bound fragments and records an agent pass without granting
|
|
205
|
+
approval. Both original reading hashes remain unchanged through PDF and ZIP
|
|
206
|
+
composition. Existing real TIGIT files were not moved, copied or edited here.
|
|
207
|
+
|
|
208
|
+
## Editable SVG author resources
|
|
209
|
+
|
|
210
|
+
Resources are separate from GIS IDs. Example optional edition field:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
resources:
|
|
214
|
+
- path: _practices/tigit-projecte-territorial/infografia.svg
|
|
215
|
+
role: editable-infographic
|
|
216
|
+
sha256: REPLACE_WITH_EXACT_SVG_SHA256
|
|
217
|
+
destination: resources/infografia.svg
|
|
218
|
+
recipients: [alumnat, docent]
|
|
219
|
+
dependencies:
|
|
220
|
+
- path: _practices/tigit-projecte-territorial/map.png
|
|
221
|
+
sha256: REPLACE_WITH_EXACT_PNG_SHA256
|
|
222
|
+
destination: resources/map.png
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Every selected file is confined and hashed. Bounded SVG XML/CSS references must
|
|
226
|
+
resolve to declared dependencies and retain the same relative relationship after
|
|
227
|
+
mapping. Embedded PNG/JPEG data is bounded using the existing image resource
|
|
228
|
+
inspector. External/imported stylesheets, remote rendering resources, scripts,
|
|
229
|
+
event handlers and dynamic SVG are rejected. Dependencies may be local SVG,
|
|
230
|
+
PNG/JPEG or declared font files; their integrity is recorded, not a promise that
|
|
231
|
+
every editor renders a font identically. Unreferenced neighbouring files and
|
|
232
|
+
destination collisions are refused. No directory is copied merely because it
|
|
233
|
+
contains an SVG. Opacity/visual author review and eventual publication remain
|
|
234
|
+
separate; the packager does not alter the author SVG or paint a background.
|
|
235
|
+
|
|
236
|
+
The installed synthetic TIGIT-shaped case includes an editable SVG plus its
|
|
237
|
+
declared PNG in both editions. A neighbouring `private-control.py` is preserved
|
|
238
|
+
at source and absent from all ZIPs. This proves selection mechanics, not approval
|
|
239
|
+
of TIGIT's separately authored real infographic.
|
|
240
|
+
|
|
241
|
+
## Final-ZIP acceptance (including no-private-fallback proof)
|
|
242
|
+
|
|
243
|
+
Final evidence:
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/acceptance-03/evidence.json
|
|
247
|
+
SHA-256 a7a2f75aeb74738a6d1b0cebdef465017e1d4da11e00b86bbc98ddf1e4e09ecb
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Two independent synthetic consumers with their own course metadata/readings use
|
|
251
|
+
the exact same GIS job/seal. Each produces an MCP edition and another version via
|
|
252
|
+
the public CLI: **eight final ZIPs/eight PDFs, eight actual offline QGIS reopens**.
|
|
253
|
+
The Make dry-run also executes the installed entry point. No GIS calculation is
|
|
254
|
+
invoked by composition; the eight scientific controls remain the producer's
|
|
255
|
+
verified retained execution evidence. Reopening is separately logged as actual
|
|
256
|
+
QGIS work.
|
|
257
|
+
|
|
258
|
+
For every ZIP, acceptance first extracts the **final archive**, checks exact
|
|
259
|
+
member inventory, hashes, sizes and relative tree against the producer closure
|
|
260
|
+
and declared author resources, then creates the reopen workspace. The producer
|
|
261
|
+
API requires its full seal, so unselected evidence remains private for validation,
|
|
262
|
+
but **every selected GIS file is replaced from the final extracted ZIP**.
|
|
263
|
+
|
|
264
|
+
Acceptance observes the actual running QGIS engine mounts and hashes its readonly
|
|
265
|
+
selected packet. That packet contains exactly the 3-file initial or 4-file resolved
|
|
266
|
+
GIS closure from the ZIP. The engine never mounts the complete private bundle or
|
|
267
|
+
the original consumer as an alternate source. Other mounts are producer runtime,
|
|
268
|
+
bounded controls and output. Network is `none`; exact engine absence is checked.
|
|
269
|
+
|
|
270
|
+
Both a missing and a byte-altered `payload/data/relief.tif` in new final ZIPs are
|
|
271
|
+
refused **even after recomputing their archive SHA-256**. The original declared
|
|
272
|
+
closure remains mandatory, before any private validation bundle can be used.
|
|
273
|
+
Those negative ZIPs and reports are retained under each `proof-N/`.
|
|
274
|
+
|
|
275
|
+
Main MCP-edition ZIPs (CLI-edition hashes/receipts are also in the evidence):
|
|
276
|
+
|
|
277
|
+
| Case | ZIP SHA-256 |
|
|
278
|
+
| --- | --- |
|
|
279
|
+
| Canonical alumnat | `a5ebe0a8487e3e9e5691cb742fad8923b3006d8c5f9e46c6eef32e54c44b42b0` |
|
|
280
|
+
| Canonical docent | `ae3e6fff012165e46949e49df5b11bb8e64ddae9f4122c796ecf3082943d0d6f` |
|
|
281
|
+
| Legacy-mapped alumnat + SVG | `b43d52f2714062b27aa0258db3e684627e321b00b954ba51afe71f7bf852dae3` |
|
|
282
|
+
| Legacy-mapped docent + SVG | `954f80ac61d811d86b00c027d81f6fdd686a42591e6def1b33402aa2fdc1746a` |
|
|
283
|
+
|
|
284
|
+
Locations:
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
.../acceptance-03/consumer-1/dist/practiques/candidate/2026-10-r1/ca/
|
|
288
|
+
.../acceptance-03/consumer-2/dist/practiques/tigit-projecte-territorial/2026-10-r2/ca/
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Installed negatives also cover manipulated unselected producer source, missing
|
|
292
|
+
closure data, resolved/student and teacher-visual/student misassignment,
|
|
293
|
+
reconstruction/control inclusion, swapped readings, stale approved-source hash,
|
|
294
|
+
wrong verifier hash and symlinked bundle ancestry. All refuse without changing
|
|
295
|
+
previous editions/PDFs. SVG unit negatives cover missing dependencies, broken
|
|
296
|
+
relative mappings, scripts and unreferenced neighbouring files.
|
|
297
|
+
|
|
298
|
+
Source tests: **667 cases, 640 passed / 27 optional skips**. Distribution and
|
|
299
|
+
whitespace checks pass. Exact installed controller check/smoke passes. Tuple and
|
|
300
|
+
portable archive load check:
|
|
301
|
+
`acceptance-03/tuple-check.json`, SHA-256
|
|
302
|
+
`73b41f0dc4109ebcd43f8d65d57651a0fcfc91d0bb022f2a93b275679311d9f3`.
|
|
303
|
+
PDF layout/code/year/first-page-logo and student-solution exclusion checks are
|
|
304
|
+
reused from phase 1. Actual isolated Jekyll builds preserve private exclusions.
|
|
305
|
+
No test job volumes are allocated; Web test containers and producer engines are
|
|
306
|
+
observed absent. Sources, PDF jobs, retained bundles, negative logs, ZIPs and
|
|
307
|
+
receipts remain available for independent inspection.
|
|
308
|
+
|
|
309
|
+
## Select from a consumer without local generic scripts
|
|
310
|
+
|
|
311
|
+
The hub's existing phase-1 host adapter can explicitly launch the successor:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
CLIENT=/tmp/opencode/practice32-web-client-9fb813becf28
|
|
315
|
+
IMAGE=sha256:17ef0d24e8611a6802b3c01ff440e6e552eac728343733198056fdbc6cdf379e
|
|
316
|
+
"$CLIENT/bin/unaltraweb-mcp-docker" serve --project /absolute/manual \
|
|
317
|
+
--image "$IMAGE" --expected-image-id "$IMAGE" --managed --offline
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Verify the new tool/schema in that actual connection. For a one-shot CLI directly
|
|
321
|
+
from the consumer shell, using the same already loaded image and native mount
|
|
322
|
+
encoder, controller limits, ownership labels and exact session reaper shipped in
|
|
323
|
+
the installed adapter. The command retains the exact container ID for teardown,
|
|
324
|
+
including a nonzero CLI exit; it never performs factory-wide cleanup:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
PROJECT="$(pwd -P)"
|
|
328
|
+
PROFILE="$("$CLIENT/bin/unaltraweb-mcp-docker" path)"
|
|
329
|
+
PROJECT_ID="$(/bin/sh "$PROFILE/scripts/unaltraweb-mcp-project-id.sh" "$PROJECT")"
|
|
330
|
+
SESSION="$(od -An -N16 -tx1 /dev/urandom | tr -d ' \n')"
|
|
331
|
+
PM="$(/bin/sh "$PROFILE/scripts/unaltraweb-docker-mount.sh" "$PROJECT" "$PROJECT")"
|
|
332
|
+
SOCKET="$(realpath /var/run/docker.sock)"
|
|
333
|
+
SM="$(/bin/sh "$PROFILE/scripts/unaltraweb-docker-mount.sh" "$SOCKET" /var/run/docker.sock)"
|
|
334
|
+
CID="$(docker create --pull never --network none --init \
|
|
335
|
+
--name "unaltraweb-stdio-$SESSION" --cpus 2 --memory 4g --pids-limit 512 \
|
|
336
|
+
--label io.context.mcp-factory=unaltraweb --label io.context.mcp-role=stdio \
|
|
337
|
+
--label "io.context.mcp-project=$PROJECT_ID" --label "io.context.mcp-session=$SESSION" \
|
|
338
|
+
--user "$(id -u):$(id -g)" --group-add "$(stat -c %g "$SOCKET")" \
|
|
339
|
+
--mount "$PM" --mount "$SM" -e HOME=/tmp \
|
|
340
|
+
-e "MCP_CONSUMER_WORKSPACE=$PROJECT" -e "UNALTRAWEB_DOCKER_ROOT=$PROJECT" \
|
|
341
|
+
-e "UNALTRAWEB_RUNTIME_SESSION=$SESSION" \
|
|
342
|
+
--entrypoint unaltraweb-mcp "$IMAGE" --project "$PROJECT" \
|
|
343
|
+
mcp manual-practice-compose --config practiques/candidate/edition.json)"
|
|
344
|
+
STATUS=0
|
|
345
|
+
docker start --attach "$CID" || STATUS=$?
|
|
346
|
+
"$CLIENT/bin/unaltraweb-mcp-docker" reap-session --project "$PROJECT" \
|
|
347
|
+
--session-id "$SESSION" --container-id "$CID"
|
|
348
|
+
test "$STATUS" -eq 0
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Only the native producer wheel selection and matching version/revision/schema/hash
|
|
352
|
+
pins need change for a compatible verifier successor. Its public return shape and
|
|
353
|
+
role contract remain the integration boundary. Embedded GPKG/raster/themes/layout
|
|
354
|
+
support is still QGIS-owned; rc1 limitations remain and Web does not certify those
|
|
355
|
+
unsupported resources. Publication and adoption in each real manual require their
|
|
356
|
+
separate authorisations. A successful synthetic composition is not a declaration
|
|
357
|
+
that TIG, TIGIT or Geodisseny is fully practice-ready.
|
|
358
|
+
|
|
359
|
+
## Portable reading bindings — candidate-03
|
|
360
|
+
|
|
361
|
+
### Reproduced defect and scope
|
|
362
|
+
|
|
363
|
+
The installed candidate-02 emitted the literal
|
|
364
|
+
`../../templates/infografia-a3.svg` in the final ZIP's student and teacher PDFs.
|
|
365
|
+
It resolved outside the extracted edition even though the SVG was present at
|
|
366
|
+
`resources/figures/plantilla-editable.svg`. The reproduction uses the actual
|
|
367
|
+
TIGIT source shape and the reported link at line 135 in a synthetic fixture:
|
|
368
|
+
|
|
369
|
+
```text
|
|
370
|
+
_practices/tigit-projecte-territorial/readings/ca/LLEGIU-ME-estudiant.md
|
|
371
|
+
_practices/tigit-projecte-territorial/readings/ca/LLEGIU-ME-docent.md
|
|
372
|
+
_practices/tigit-projecte-territorial/templates/infografia-a3.svg
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Evidence: `tmp/practice-editions-98/links-reproduction-01/evidence.json`, SHA-256
|
|
376
|
+
`ade15dd78789c793c21a3e23926f06ad1b81069326ef697b67009c397aa953a1`.
|
|
377
|
+
The old candidates and all failed/earlier proofs remain retained.
|
|
378
|
+
|
|
379
|
+
The correction stays in the existing practice domain: `practice_pdf.py` owns one
|
|
380
|
+
`ReadingResources` resolver shared by image snapshotting and prose links, and
|
|
381
|
+
`practice_editions.py` supplies only that recipient's verified selection. The
|
|
382
|
+
renderer applies the authorised URL lookup to its actual Pandoc AST and refuses
|
|
383
|
+
any unaccounted local link. It also checks the resulting PDF's link annotations.
|
|
384
|
+
No GIS code, template geometry or global path-validator rule was relaxed.
|
|
385
|
+
|
|
386
|
+
### One binding format, two declaration locations
|
|
387
|
+
|
|
388
|
+
A binding has a literal `reference`, exactly one `path` or `product`, a required
|
|
389
|
+
`sha256`, and an optional `destination`. It can live in the shared reading mapping
|
|
390
|
+
under `_config.yml`, or in the selected edition's `readings.<recipient>.bindings`.
|
|
391
|
+
The same resolver merges them; conflicting definitions of one reference fail.
|
|
392
|
+
Declared references must be used by that reading.
|
|
393
|
+
|
|
394
|
+
For the Geodisseny-shaped retained capture case (replace the hash/path with the
|
|
395
|
+
consumer's exact inventory):
|
|
396
|
+
|
|
397
|
+
```yaml
|
|
398
|
+
unaltraweb:
|
|
399
|
+
practices:
|
|
400
|
+
readings:
|
|
401
|
+
- source: practiques/accessibilitat-vilaseca/ca/alumnat/LLEGIU-ME.md
|
|
402
|
+
slug: accessibilitat-vilaseca
|
|
403
|
+
lang: ca
|
|
404
|
+
recipient: alumnat
|
|
405
|
+
bindings:
|
|
406
|
+
- reference: captures/inici.png
|
|
407
|
+
path: sandbox/practiques/accessibilitat-vilaseca/2026-10-07-organitzacio/captures/inici.png
|
|
408
|
+
sha256: REPLACE_WITH_EXACT_PNG_SHA256
|
|
409
|
+
# Optional only when this resource must also be a ZIP/link target:
|
|
410
|
+
destination: resources/captures/inici.png
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Declare the teacher reading separately. The Markdown stays
|
|
414
|
+
``; the source capture stays in its original run. There
|
|
415
|
+
is no scan of sandbox directories. A missing file, different hash, unsafe path,
|
|
416
|
+
unsupported image type or unbound logical reference fails.
|
|
417
|
+
|
|
418
|
+
An edition binding can instead address a producer ID:
|
|
419
|
+
|
|
420
|
+
```yaml
|
|
421
|
+
readings:
|
|
422
|
+
docent:
|
|
423
|
+
source: _practices/tigit-projecte-territorial/readings/ca/LLEGIU-ME-docent.md
|
|
424
|
+
approved_sha256: REPLACE_WITH_EXACT_MARKDOWN_SHA256
|
|
425
|
+
bindings:
|
|
426
|
+
- reference: captures/inici.png
|
|
427
|
+
product: resolved-project-original
|
|
428
|
+
sha256: REPLACE_WITH_EXACT_SELECTED_PRODUCT_SHA256
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
The ID must already belong to the teacher's selected producer closure. Its
|
|
432
|
+
destination is inherited without moving GIS files. A path alias cannot bypass
|
|
433
|
+
another recipient's known GIS/author-resource selection. Literal GIS images in a
|
|
434
|
+
reading must also be selected; the regression fixture now explicitly selects the
|
|
435
|
+
annotated teacher PNG used in its Markdown rather than relying on the private
|
|
436
|
+
bundle containing it.
|
|
437
|
+
|
|
438
|
+
PNG/JPEG/PDF path bindings can supply reading images. When an edition additionally
|
|
439
|
+
declares a `resources/...` destination, those exact bytes join its ZIP as a
|
|
440
|
+
`reading-resource`. Extra SVG/GIS resources still require the existing verified
|
|
441
|
+
GIS/author-resource selection; a reading binding is not a shortcut around SVG
|
|
442
|
+
dependency validation or recipient policy. For an already selected resource,
|
|
443
|
+
any stated destination must match that selection.
|
|
444
|
+
|
|
445
|
+
### Relative prose links and standalone behavior
|
|
446
|
+
|
|
447
|
+
For a normal local link such as
|
|
448
|
+
`[plantilla editable A3](../../templates/infografia-a3.svg)`, the resolver applies
|
|
449
|
+
URL-relative normalization against the **original reading's parent**, then requires
|
|
450
|
+
the resulting confined source path in the recipient's authorised resource map.
|
|
451
|
+
It emits the encoded ZIP-relative destination from that map. `..` is handled only
|
|
452
|
+
as URL syntax; normalized filesystem/ZIP paths still use the strict validator.
|
|
453
|
+
Absolute, escaped, undeclared, other-recipient and private/control targets fail.
|
|
454
|
+
HTTPS theory URLs and internal anchors are retained.
|
|
455
|
+
|
|
456
|
+
Standalone `manual_practice_pdf_build` supports the same explicit image bindings,
|
|
457
|
+
but **refuses local file links without a portable edition context**, even if the
|
|
458
|
+
source file exists. It cannot claim that a PDF in a sandbox directory has a valid
|
|
459
|
+
relative link to an unrelated original resource. HTTP(S), mailto and internal
|
|
460
|
+
anchors remain supported. The public composition signature is unchanged.
|
|
461
|
+
|
|
462
|
+
Snapshots/receipts now bind:
|
|
463
|
+
|
|
464
|
+
- `inputs/original.md`: exact authored Markdown, never rewritten in the consumer;
|
|
465
|
+
- `inputs/source.md`: parsed body input, plus image metadata and snapshots;
|
|
466
|
+
- `inputs/portable-links.json`: selected target map, declared/resolved bindings,
|
|
467
|
+
source paths, hashes, bytes and source-URL → ZIP-URL mappings;
|
|
468
|
+
- `outputs/source.effective.json` and `.md`: actual effective Pandoc source after
|
|
469
|
+
the authorised link pass; image layout still consumes the captured metadata;
|
|
470
|
+
- `outputs/practice.tex`, final PDF/preview and renderer link report, all hashed.
|
|
471
|
+
|
|
472
|
+
The target map and bindings participate in the existing fingerprint/no-clobber
|
|
473
|
+
contract. Bound source hashes are rechecked before sealing/delivery. Edition
|
|
474
|
+
receipts retain the mapping and effective-source hashes alongside GIS/PDF identity.
|
|
475
|
+
|
|
476
|
+
### Immutable successor and installed evidence
|
|
477
|
+
|
|
478
|
+
Directory:
|
|
479
|
+
|
|
480
|
+
```text
|
|
481
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/candidate-03/
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
| Artifact | SHA-256 |
|
|
485
|
+
| --- | --- |
|
|
486
|
+
| `candidate.json` | `7df6364d249dea3eeafbe1f89ebadbc4a16ce90502cb528ab97c0e261182e4e4` |
|
|
487
|
+
| Web wheel | `809a8afe0ce52d013391d2bfc0edbb2a908c81fdef53b9fe3e99e652c8923687` |
|
|
488
|
+
| `controller.docker.tar.gz` | `7fd63303a1dbab7f1b7b226ebb4e361bfc0008afe29ead4e149a88c232ea6eec` |
|
|
489
|
+
| `source.tar.gz` | `780a80d29255c8a60430af053689ab20473c940b3ab955be187e360052b90785` |
|
|
490
|
+
| Composition schema | `3b3334946c765f98188c5daa668c933ab81eaaabb8cf4898324f6d26b2974acd` |
|
|
491
|
+
|
|
492
|
+
Configuration ID:
|
|
493
|
+
`sha256:9f4370dc8d0e0681226f165f38b0c758fde949c62b6d23427c70c810f0cdf1f5`.
|
|
494
|
+
This remains an unpublished hash-bound candidate, not new bytes published as 0.7.1.
|
|
495
|
+
The selected QGIS rc1 and PDF/core/workflow tuple remain unchanged; no compatibility
|
|
496
|
+
with an undelivered QGIS successor is inferred.
|
|
497
|
+
|
|
498
|
+
Installed link/binding proof:
|
|
499
|
+
|
|
500
|
+
```text
|
|
501
|
+
tmp/practice-editions-98/links-acceptance-04/evidence.json
|
|
502
|
+
SHA-256 e6d2c24dd0c1727e9650b2b0b28596964842b47f6ee8539b89166eddb27ba5a7
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
The final ZIP PDFs now point to `resources/figures/plantilla-editable.svg`, and to
|
|
506
|
+
the recipient's declared capture destination. Every inspected local annotation
|
|
507
|
+
target exists inside the extracted edition. The exact HTTPS URL survives; the
|
|
508
|
+
internal link resolves through an actual named PDF destination to its expected
|
|
509
|
+
heading. Original Markdown/config/resources keep their hashes. Effective-source
|
|
510
|
+
and receipt hashes are checked independently.
|
|
511
|
+
|
|
512
|
+
Two additional standalone Geodisseny-shaped readings retain literal
|
|
513
|
+
`captures/inici.png` and compile from the declared separate run. Both dry-runs and
|
|
514
|
+
builds pass without any neighbouring capture directory or source rewrite. Changed
|
|
515
|
+
capture hashes, absent captures and removed bindings fail; no sandbox discovery
|
|
516
|
+
occurs. Other negatives cover undeclared/missing/teacher-only/escaped prose targets,
|
|
517
|
+
an unselected GIS product binding and standalone local-file-link refusal.
|
|
518
|
+
|
|
519
|
+
The bounded one-shot CLI example above was executed with observed **2 CPUs,
|
|
520
|
+
4 GiB, 512 PIDs**, native factory/role/project/session labels and exact native
|
|
521
|
+
`reap-session` cleanup:
|
|
522
|
+
`links-acceptance-04/review/native-cli.json`, SHA-256
|
|
523
|
+
`4bd9ff25ecd245c5c9f2a5038a29360ad2b2fc208bea1f5ec28c8fc64adb3f7f`.
|
|
524
|
+
|
|
525
|
+
Full GIS/ZIP/private-editorial/layout regression:
|
|
526
|
+
`tmp/practice-editions-98/acceptance-04/evidence.json`, SHA-256
|
|
527
|
+
`1fa74f1a030ef3b0028277babe252c15866c79a7cf3a15825a8c89c2de732393`.
|
|
528
|
+
It repeats the final-archive closure/mount/reopen tests, recalculated-archive
|
|
529
|
+
negatives, original-path private reviews and template checks. Original no-link
|
|
530
|
+
student ZIP hashes remain unchanged; teacher packages explicitly add their selected
|
|
531
|
+
annotated capture. **672 tests: 645 passed / 27 optional skips**, plus all 28 practice
|
|
532
|
+
tests with the real PDF worker enabled, installed check/smoke, and coherent
|
|
533
|
+
nine-checker/archive-load verification. Tuple receipt:
|
|
534
|
+
`links-acceptance-04/tuple-check.json`, SHA-256
|
|
535
|
+
`d8e50846bad79ab679f9da6aef70760d55d32198f1e13565989e27f1ed87593f`.
|
|
536
|
+
|
|
537
|
+
Additional reserved paths for this revision:
|
|
538
|
+
`scripts/manual/render_practice.py`, `test/practice_links_smoke.py`.
|
|
539
|
+
All prior candidates and receipts remain immutable. Branch/HEAD are unchanged;
|
|
540
|
+
the work is uncommitted and no real manual, producer checkout, release or general
|
|
541
|
+
runtime infrastructure was edited by this unit.
|
|
542
|
+
|
|
543
|
+
## Native rc2 integration — candidate-04
|
|
544
|
+
|
|
545
|
+
**Completed, local unpublished candidate.** The authoritative checkout/branch and
|
|
546
|
+
Git base remain unchanged. All source changes are uncommitted; candidates 02/03,
|
|
547
|
+
their bins/schemas/receipts and the earlier GIS selection remain preserved.
|
|
548
|
+
The exact continuing reservation is recorded in
|
|
549
|
+
[Web #98](https://github.com/dosquartsdedocs/unaltraweb/issues/98#issuecomment-6084077906).
|
|
550
|
+
The [completed integration return](https://github.com/dosquartsdedocs/unaltraweb/issues/98#issuecomment-6084722283)
|
|
551
|
+
records the selected candidate and installed acceptance evidence.
|
|
552
|
+
The only new source path is `test/practice_native_editions_smoke.py`; production
|
|
553
|
+
changes are limited to profile identity/invocation and explicit native export roles
|
|
554
|
+
in the existing adapter/schema. No GIS parser or dependency discovery is added.
|
|
555
|
+
|
|
556
|
+
### Verified producer and minimal adapter delta
|
|
557
|
+
|
|
558
|
+
Shared input: `/tmp/opencode/practice32-qgis-0.6.0rc2-round32-n1/`.
|
|
559
|
+
The `ready.json` SHA-256
|
|
560
|
+
`49a8887587eb5942aae7aa76b678acd617cec799294c350fe5fc6d344d881a1a`, all eleven files,
|
|
561
|
+
the 43-member fixture seal and descriptor were rehashed before use.
|
|
562
|
+
|
|
563
|
+
- Package: `unaltracaptura-qgis 0.6.0rc2`.
|
|
564
|
+
- Wheel: `1a7456c0b81e0a4729b702b60d9340456efea9a88b9f5c21b97c8ff4823d09bf`.
|
|
565
|
+
- Installed source/assets:
|
|
566
|
+
`sha256:5922d3dc411c14c7c3c2d9257a78b4d42f42fb1aae8451bcf245ca44a0e91992`.
|
|
567
|
+
- V2 schema: `528c8be229c72c346f134ffaa60094f94224094a25b6fb11bcc87802ddc7fffb`.
|
|
568
|
+
- V1 schema unchanged: `9bc7f15ede9d67b3e1209c329da13d9fcb08004090d05b27662a43de6edf3445`.
|
|
569
|
+
- Native fixture ZIP: `5598a98c6bd42561935ed3eb1c674dae34ff6ba2ce0fff9384c6ebf80d3f4e53`.
|
|
570
|
+
- Native sender seal: `7f26db5a8cc05af081ea21a65d7d167e05f4b6b1a2a7a6e9b361c91066605507`.
|
|
571
|
+
- Native descriptor: `3118638d53c63ef2c059d73f744b2ac399aa1f2e2c21f27f0026f3fbbb122df7`.
|
|
572
|
+
- Engine remains `sha256:1003721d96abe9607d8337b36851f9b29f84c2f8f92b377d1a73ff03c9d15cd2`.
|
|
573
|
+
|
|
574
|
+
`gis.profile` now selects the domain explicitly. V2 identity calls exactly
|
|
575
|
+
`practice-schema --profile qgis-practice-v2`; the returned schema pin/profile and
|
|
576
|
+
installed wheel/content identity must all agree. Legacy omitted profile means v1
|
|
577
|
+
only, using its established public default so an old rc1 v1 selection is not
|
|
578
|
+
silently reinterpreted. New configurations should state either profile explicitly.
|
|
579
|
+
The later `practice-check` result must match the selected profile, independently
|
|
580
|
+
of package version. A verifier package can therefore verify an older producer's
|
|
581
|
+
seal without pretending their versions/content revisions are identical.
|
|
582
|
+
|
|
583
|
+
V2 delivery adds only the declared `map-svg`/`map-pdf` output roles. Fonts, symbols,
|
|
584
|
+
Shapefile/CSV sidecars and other dependencies retain their returned roles and are
|
|
585
|
+
included through the exact producer closure, not filename heuristics. `teacher_only`
|
|
586
|
+
and resolved-role segregation still apply to the entire closure. No GPKG container
|
|
587
|
+
is split: its internal-member safety belongs to the producer verifier.
|
|
588
|
+
|
|
589
|
+
### Exact profile configuration
|
|
590
|
+
|
|
591
|
+
For the native fixture (the reading/version/recipient fields stay as documented
|
|
592
|
+
above):
|
|
593
|
+
|
|
594
|
+
```yaml
|
|
595
|
+
gis:
|
|
596
|
+
profile: qgis-practice-v2
|
|
597
|
+
bundle: sandbox/gis/native/bundle.json
|
|
598
|
+
sha256: 7f26db5a8cc05af081ea21a65d7d167e05f4b6b1a2a7a6e9b361c91066605507
|
|
599
|
+
verifier:
|
|
600
|
+
package: unaltracaptura-qgis
|
|
601
|
+
version: 0.6.0rc2
|
|
602
|
+
revision: sha256:5922d3dc411c14c7c3c2d9257a78b4d42f42fb1aae8451bcf245ca44a0e91992
|
|
603
|
+
wheel_sha256: 1a7456c0b81e0a4729b702b60d9340456efea9a88b9f5c21b97c8ff4823d09bf
|
|
604
|
+
schema_sha256: 528c8be229c72c346f134ffaa60094f94224094a25b6fb11bcc87802ddc7fffb
|
|
605
|
+
teacher_only:
|
|
606
|
+
- buffer-data
|
|
607
|
+
- infographic-pdf
|
|
608
|
+
- infographic-svg
|
|
609
|
+
- joined-data
|
|
610
|
+
- resolved-project
|
|
611
|
+
- resolved-project-original
|
|
612
|
+
- resolved-project-png
|
|
613
|
+
- resolved-project-svg
|
|
614
|
+
- route-closed
|
|
615
|
+
- route-open
|
|
616
|
+
selection:
|
|
617
|
+
alumnat: [initial-project]
|
|
618
|
+
docent: [resolved-project, infographic-svg, infographic-pdf, resolved-project-png]
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
For an unchanged rc1/v1 bundle with the **same rc2 verifier**, select
|
|
622
|
+
`profile: qgis-practice-v1`, use its own sender seal
|
|
623
|
+
`abd44b02101243a3ddfd492357c2882e6a3f62248dde192616159944c41056a4`, and set
|
|
624
|
+
`schema_sha256: 9bc7f15ede9d67b3e1209c329da13d9fcb08004090d05b27662a43de6edf3445`.
|
|
625
|
+
Verifier version/revision/wheel remain the rc2 values above. Both combinations were
|
|
626
|
+
executed. A v2 bundle with v1 profile/pin, a v1 schema hash under v2 or a wrong wheel
|
|
627
|
+
pin is refused rather than treated as a compatible success.
|
|
628
|
+
|
|
629
|
+
Inside the selected Web controller, these are the actual installed producer CLIs:
|
|
630
|
+
|
|
631
|
+
```bash
|
|
632
|
+
unaltracaptura-qgis practice-schema --profile qgis-practice-v2
|
|
633
|
+
unaltracaptura-qgis practice-check --workspace "$MCP_CONSUMER_WORKSPACE" \
|
|
634
|
+
--path sandbox/gis/native/bundle.json \
|
|
635
|
+
--sha256 7f26db5a8cc05af081ea21a65d7d167e05f4b6b1a2a7a6e9b361c91066605507 \
|
|
636
|
+
--select initial-project
|
|
637
|
+
unaltracaptura-qgis practice-reopen --workspace "$MCP_CONSUMER_WORKSPACE" \
|
|
638
|
+
--path sandbox/gis/native/bundle.json \
|
|
639
|
+
--sha256 7f26db5a8cc05af081ea21a65d7d167e05f4b6b1a2a7a6e9b361c91066605507 \
|
|
640
|
+
--select resolved-project --output sandbox/native-reopen-01.json
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Use the native bounded/labelled controller selection and teardown documented above,
|
|
644
|
+
changing the one-shot entrypoint to `unaltracaptura-qgis` for a host-shell invocation.
|
|
645
|
+
The verifier is installed in that image; a separate old QGIS connection on the host
|
|
646
|
+
does not determine this composition's verifier. Reopen needs the already prepared
|
|
647
|
+
engine; checking/selection alone does not start GIS or fetch data.
|
|
648
|
+
|
|
649
|
+
### Candidate identities and tuple
|
|
650
|
+
|
|
651
|
+
```text
|
|
652
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/candidate-04/
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
| Artifact | SHA-256 |
|
|
656
|
+
| --- | --- |
|
|
657
|
+
| `candidate.json` | `c79e688b95b4f94f2e2fc9df154611cae3611ab628ee0bc4e9f2cba08fdc3fc7` |
|
|
658
|
+
| Web wheel | `df1ca9d239c25342a81950f4906589a6f94f0deae192a99c3affd227597cbaa9` |
|
|
659
|
+
| `controller.docker.tar.gz` | `392853842dc49dafe15d10d37a7456d52add2d341b90ff3e3fe8142f66a9f9f3` |
|
|
660
|
+
| `source.tar.gz` | `8810efd4f4725eea5910996b790b9704786ef42b683c26e1c4d0ae12be24616e` |
|
|
661
|
+
| Web composition schema | `06707a0d847715f85576fd2f3118d132808c8cf5dbd522333bbabf4759bd867d` |
|
|
662
|
+
|
|
663
|
+
Controller configuration ID:
|
|
664
|
+
`sha256:17ef0d24e8611a6802b3c01ff440e6e552eac728343733198056fdbc6cdf379e`.
|
|
665
|
+
Actual serving package fingerprint:
|
|
666
|
+
`sha256:5b8de154fc10665f71056b2887959d41a2a6f5fb5726611d1ee3482c7d7b3d36`.
|
|
667
|
+
The archive was loaded and the image's source label matches its exact source
|
|
668
|
+
snapshot. It is a local hash-bound candidate, not a new published 0.7.1 artifact.
|
|
669
|
+
The embedded GIS package is rc2; the prepared PDF worker stays at its published
|
|
670
|
+
0.7.1 digest/configuration ID and producer `b7ec1d…`. Consumer core and independent
|
|
671
|
+
workflow remain `3332e0b…`. All nine retained-document checkers still agree.
|
|
672
|
+
|
|
673
|
+
### Actual native final-ZIP acceptance
|
|
674
|
+
|
|
675
|
+
Evidence:
|
|
676
|
+
|
|
677
|
+
```text
|
|
678
|
+
tmp/practice-editions-98/native-acceptance-01/evidence.json
|
|
679
|
+
SHA-256 1c7feca296ab5b991fe7c63d4cadcfb6f996f904abac20020aa661355adb2507
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
The installed public verifier returns exact closures **11 / 9 / 2** for
|
|
683
|
+
`initial-project`, `resolved-project`, `infographic-svg`. The student ZIP retains
|
|
684
|
+
the initial atomic GPKG, fonts/symbol, complete Shapefile and CSV/CSVT relationships;
|
|
685
|
+
the teacher ZIP adds the selected solved projects/data and native SVG/PDF exports.
|
|
686
|
+
The reading PDF is still the approved Web landscape template, separate from the
|
|
687
|
+
QGIS-native map-export PDF. Its local export links resolve inside the final ZIP.
|
|
688
|
+
|
|
689
|
+
Both final ZIPs were extracted, exactly inventoried and hashed. Actual QGIS workers
|
|
690
|
+
mounted only their selected extracted-byte packets plus provider controls/output;
|
|
691
|
+
the private full bundle/original was not mounted as a fallback. Fresh public
|
|
692
|
+
reopen observations include:
|
|
693
|
+
|
|
694
|
+
- embedded GPKG `inici` actually reopened, with its `mdt` and `ortofoto` subdatasets;
|
|
695
|
+
- 600×640 EPSG:25831 raster grid, 1-band elevation / 3-band orthophoto;
|
|
696
|
+
- 22-feature Shapefile and typed table, with all declared sidecars retained;
|
|
697
|
+
- saved `Principal` / `Referència` themes and layer membership;
|
|
698
|
+
- editable `Infografia base`, independent `principal` and `localitzador` frames at
|
|
699
|
+
1:15,000 / 1:75,000, with distinct extents matching their physical mm dimensions.
|
|
700
|
+
|
|
701
|
+
Those are assertions over the producer's public observations, not native-format
|
|
702
|
+
inspection implemented in Web. Scientific Geodisseny D/E controls and the real
|
|
703
|
+
TIGIT programme still belong to the upcoming authorised consumer runs.
|
|
704
|
+
|
|
705
|
+
Delivered native examples:
|
|
706
|
+
|
|
707
|
+
```text
|
|
708
|
+
.../native-acceptance-01/consumer/dist/practiques/candidate/2026-10-native-r1/ca/
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
| ZIP | Bytes | SHA-256 |
|
|
712
|
+
| --- | ---: | --- |
|
|
713
|
+
| `candidate-2026-10-native-r1-ca.zip` | 1591610 | `0c0f9536b7fa5a98254e698e4444fa5436f7e28ddf27be6ae2a3a5cfc0b39368` |
|
|
714
|
+
| `candidate-docent-2026-10-native-r1-ca.zip` | 2215680 | `0cf2b6440fea0953966a1194f4e8feb49c398adb24437071cd9e3df119c85b80` |
|
|
715
|
+
|
|
716
|
+
Their external receipt hashes are respectively
|
|
717
|
+
`8d2ca66cadc8e94255c8f6505d9a7a97833209cd9222e0ac7a57b6bde89d239a` and
|
|
718
|
+
`81d94c76aa87756702a9a42ab772101081b94e36c26b4bacdd6607ef7f2d63d6`.
|
|
719
|
+
|
|
720
|
+
The corresponding reading PDFs retain the approved A4 landscape layout and
|
|
721
|
+
first-page-only logos:
|
|
722
|
+
|
|
723
|
+
| Recipient | Pages | PDF SHA-256 |
|
|
724
|
+
| --- | ---: | --- |
|
|
725
|
+
| Alumnat | 4 | `d875d11b282983912ec4c783943815ea27eeb6d7056ef7e6cf1615bd05ee09fb` |
|
|
726
|
+
| Docent | 6 | `0326b75e690cba90f30aed7b66c45a2d7dc136fc2f3d954155fe9ee7c668ef47` |
|
|
727
|
+
|
|
728
|
+
Retained PDF paths, also recorded with their receipts in the acceptance evidence:
|
|
729
|
+
|
|
730
|
+
```text
|
|
731
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/native-acceptance-01/consumer/sandbox/practiques/candidate/lectura-2026-10-native-r1-ca-alumnat-edition-c7bdde58ad8f483f/outputs/LLEGIU-ME.pdf
|
|
732
|
+
/home/benizar/git/unaltraweb/tmp/practice-editions-98/native-acceptance-01/consumer/sandbox/practiques/candidate/lectura-2026-10-native-r1-ca-docent-edition-c7bdde58ad8f483f/outputs/LLEGIU-ME.pdf
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
Native negatives refuse missing font, altered sidecar, teacher export in student
|
|
736
|
+
selection and incorrect profile/schema/wheel pins without changing existing
|
|
737
|
+
deliveries. Final ZIPs with a Shapefile dependency removed/altered are also refused
|
|
738
|
+
after recalculating the archive hash; the original complete closure remains required.
|
|
739
|
+
|
|
740
|
+
### Regressions and final gates
|
|
741
|
+
|
|
742
|
+
- Same rc2 verifier over unchanged v1 data: complete installed composition, two
|
|
743
|
+
consumers, additional CLI editions and final-ZIP offline reopens pass. Evidence
|
|
744
|
+
`rc2-v1-acceptance-01/evidence.json`, SHA-256
|
|
745
|
+
`ac64b727ada3d9d4e4391bc35421fdb0ebbb5317968e27050d55cd057dc22ca1`.
|
|
746
|
+
ZIP hashes match the preceding rc1-verifier run; only verifier-bound receipts differ.
|
|
747
|
+
- TIGIT relative SVG links, HTTPS/internal anchors, Geodisseny retained-run image
|
|
748
|
+
bindings, original-source/effective-source receipts, private anchored reviews,
|
|
749
|
+
standalone refusal and bounded CLI teardown all pass with rc2. Evidence
|
|
750
|
+
`rc2-links-acceptance-01/evidence.json`, SHA-256
|
|
751
|
+
`358fa4e2cac126ea6e67325aa3cb0b100e60e1554abacfbe59fbf8f3d8cbedab`.
|
|
752
|
+
- Tuple, archive load, loaded fingerprint and actual embedded-reopen supplementary
|
|
753
|
+
verification: `native-acceptance-01/tuple-check.json`, SHA-256
|
|
754
|
+
`0bfbfc46cf621ef235f7eedf874d1a86bc9053f73367311b02ce1792c442d698`.
|
|
755
|
+
- **674 source tests: 647 passed / 27 optional skips**; distribution/whitespace and
|
|
756
|
+
installed controller check/smoke pass. Original sources and prior candidates are
|
|
757
|
+
preserved. Exact test controllers/engines are observed absent; zero job volumes.
|
|
758
|
+
|
|
759
|
+
This final candidate is available for the coordinator's explicit selection in all
|
|
760
|
+
three manual sessions. No publication or automatic scaffold/workflow migration is
|
|
761
|
+
required for the private practice circuit. The remaining step is each real manual's
|
|
762
|
+
authorised model/data/readings/adoption run, followed by human delivery/publication
|
|
763
|
+
decisions. No real manual is declared ready solely from this synthetic acceptance.
|
|
764
|
+
|
|
765
|
+
## Working-tree consolidation — independent PDF and ZIP
|
|
766
|
+
|
|
767
|
+
The author clarified the delivery contract: reproducibility code and draft
|
|
768
|
+
readings are versioned; data/PDFs stay outside Git and each activity supplies a
|
|
769
|
+
PDF and a ZIP for Moodle. The source compositor now stages, for each recipient:
|
|
770
|
+
|
|
771
|
+
```text
|
|
772
|
+
dist/practiques/<slug>/<version>/<lang>/
|
|
773
|
+
<slug>[-docent]-<version>-<lang>.pdf
|
|
774
|
+
<slug>[-docent]-<version>-<lang>.pdf.receipt.json
|
|
775
|
+
<slug>[-docent]-<version>-<lang>.zip
|
|
776
|
+
<slug>[-docent]-<version>-<lang>.zip.receipt.json
|
|
777
|
+
edition.json
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
The independent PDF is an exact checked copy of the sealed reading job, not a
|
|
781
|
+
second render. The ZIP keeps the same `LLEGIU-ME.pdf`/`LEEME.pdf`/`README.pdf`
|
|
782
|
+
member. Its receipt adds `reading.delivery`; `packages.<recipient>` keeps its
|
|
783
|
+
existing ZIP fields and adds `pdf`. The PDF receipt binds its source job/receipt,
|
|
784
|
+
paired ZIP and edition receipt without a cyclic hash dependency. The complete
|
|
785
|
+
directory is installed with the same atomic no-replace operation. Failed copies
|
|
786
|
+
or receipts leave only a retained unpublished staging attempt.
|
|
787
|
+
|
|
788
|
+
The PDF is readable separately; its relative links still refer to the ZIP tree.
|
|
789
|
+
For local access to linked SVGs/data, extract the paired ZIP beside the PDF.
|
|
790
|
+
Uploading the two files separately to Moodle does not itself recreate that tree
|
|
791
|
+
as web URLs. No authored Markdown, approval status or link bytes are rewritten.
|
|
792
|
+
|
|
793
|
+
Four additional composition regressions cover byte equality, exactly one build
|
|
794
|
+
per reading, paired receipts, no-clobber, partial-failure atomicity, dry-run and
|
|
795
|
+
refusal of symlink/hash-drift copies. A read-only-source redelivery proof also
|
|
796
|
+
used the previously sealed native fixture PDFs with **zero renders/GIS runs**:
|
|
797
|
+
|
|
798
|
+
```text
|
|
799
|
+
/home/benizar/git/unaltraweb/tmp/practice-standalone-pdf-98/evidence.json
|
|
800
|
+
SHA-256 e830e214cbde8a76b90a2daee9b0e5a785fe9e79f0ad5ded4cd190284b625bf9
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Both independent PDFs match their previous sealed bytes (`d875d11b…` alumnat,
|
|
804
|
+
`0326b75e…` docent), and both regenerated ZIPs match the previous ZIP hashes
|
|
805
|
+
exactly. This copy/packaging proof complements the full composition unit tests;
|
|
806
|
+
it is not a new installed-controller acceptance or a replacement of candidate-04.
|
|
807
|
+
|
|
808
|
+
The initial consolidation proposed a released-wheel installer. The owner then
|
|
809
|
+
chose to keep QGIS private; that installer has been removed from the working tree.
|
|
810
|
+
The public image delegates to the hub-prepared private controller and publishes
|
|
811
|
+
only its identity/transport contract. Public CI validates metadata/unit fixtures
|
|
812
|
+
and marks native private checks `not_run`. The PDF 0.7.1/workflow pins and nine
|
|
813
|
+
shared checkers remain unchanged. See the private-runtime bridge contract above.
|
|
814
|
+
|
|
815
|
+
The retained controller/PDF archive route for D1 is documented in
|
|
816
|
+
[practice-runtime-archives-98.md](practice-runtime-archives-98.md).
|