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,86 @@
|
|
|
1
|
+
# Independent PDF worker provenance — issue 86
|
|
2
|
+
|
|
3
|
+
[Owner issue 86](https://github.com/dosquartsdedocs/unaltraweb/issues/86) records
|
|
4
|
+
TIG's failed latest deployment at consumer
|
|
5
|
+
`a87eb4fc7fe58f072413a99356d2465b36d05136`. Its published PDF 0.5.0 was produced
|
|
6
|
+
from `d857f8c9f5fea90cf450c0b30b4e77a37b541275`, whereas its reusable workflow
|
|
7
|
+
was pinned to `02af70001bf8085af860fd57f8d7e75ec96a89c7`. Comparing those two
|
|
8
|
+
different component identities blocked the build before Pages publication.
|
|
9
|
+
|
|
10
|
+
The original gates were re-executed with real published images: canonical 0.5.0,
|
|
11
|
+
0.5.1 and 0.7.0 tuples fail; the 0.6.0 tuple passes because its two revisions
|
|
12
|
+
happen to coincide. Retained diagnostic evidence is
|
|
13
|
+
`/tmp/opencode/unaltraweb-deploy-86/matrix/evidence.json`, SHA-256
|
|
14
|
+
`8640b7b68456b1bce42b9a0a271fe1c4853fde181eff9b3a130c990bd119142f`.
|
|
15
|
+
|
|
16
|
+
## Corrected trust binding
|
|
17
|
+
|
|
18
|
+
The reviewed provider workflow now owns these exact digest/producer records:
|
|
19
|
+
|
|
20
|
+
| PDF worker | OCI digest | Producer commit |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| 0.5.0 | `sha256:9e0b3a45753c170b795e9a9d6df61580085c113436beac5bf6c8de69b6562097` | `d857f8c9f5fea90cf450c0b30b4e77a37b541275` |
|
|
23
|
+
| 0.6.0 | `sha256:0ba267cb87f53ebaca4e31805fe00610cd61fdf97a8d2c3692f4655700dceaed` | `5cf9817489c8dc47cee726bfe42fe3071cd32b85` |
|
|
24
|
+
|
|
25
|
+
Both references use the fixed repository
|
|
26
|
+
`ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf`. The gate first checks the defining
|
|
27
|
+
provider repository and full workflow SHA, rejects an unrecorded digest before
|
|
28
|
+
Docker access, pulls the exact digest and compares its actual revision label
|
|
29
|
+
with the recorded producer. The worker may have been released before the workflow.
|
|
30
|
+
The expected producer is not an input supplied by the consumer, and an inherited
|
|
31
|
+
environment value cannot replace it. Failed pull/inspection stops the step.
|
|
32
|
+
|
|
33
|
+
The deployment's reviewed-main guard, input interface and publication checks are
|
|
34
|
+
unchanged. The gate uses the already-reviewed immutable artifact identity; this
|
|
35
|
+
change does not introduce or claim a new live signature-verification service.
|
|
36
|
+
Release preparation's existing signed-image evidence remains separate.
|
|
37
|
+
|
|
38
|
+
Static workflow policy binds the whole gate, including its records and step
|
|
39
|
+
controls, to reviewed canonical JSON. It rejects disabled/error-tolerant gates
|
|
40
|
+
and refuses a BOM default whose worker has no approved record. A new worker
|
|
41
|
+
requires an explicit provider review, updated policy and published-image tests.
|
|
42
|
+
|
|
43
|
+
## Regression coverage
|
|
44
|
+
|
|
45
|
+
`test/test_deploy_provenance.py` executes the actual shell blocks from the reusable
|
|
46
|
+
workflow. Unit cases cover earlier legitimate producers, unknown digests with
|
|
47
|
+
plausible labels, mutable/foreign references, missing/wrong labels, a label that
|
|
48
|
+
matches the workflow instead of the worker, attempted expected-revision override,
|
|
49
|
+
foreign/unbound provider authority, pull/inspection failure and reviewed-main
|
|
50
|
+
ref/SHA rejection.
|
|
51
|
+
|
|
52
|
+
The independently gated Docker case executes real pulls and inspections for both
|
|
53
|
+
published workers against a later workflow revision. The ordinary CI distribution
|
|
54
|
+
job must run this case; static policy rejects silently disabling it:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
UNALTRAWEB_DEPLOY_PROVENANCE_DOCKER=1 PYTHONPATH=test \
|
|
58
|
+
python -m unittest test_deploy_provenance.PublishedDeployProvenanceTests
|
|
59
|
+
PYTHONPATH=src python3 -m unittest discover -s test -p 'test_*.py'
|
|
60
|
+
make workflow-check distribution-check
|
|
61
|
+
git diff --check
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Local checks passed 619 Python cases, with 30 optional/environment skips, plus
|
|
65
|
+
the explicitly enabled real-Docker case. The actual image configuration IDs were
|
|
66
|
+
`sha256:c1998dc3345444cb3994ac0cd649ad80ac88dde127dec1dd9f09c719aafe170a`
|
|
67
|
+
for PDF 0.5.0 and
|
|
68
|
+
`sha256:d7e7d3243616270fc9e6eed7f8238c412dbe3d9ffc18d2832d17d66ca630d139`
|
|
69
|
+
for PDF 0.6.0. These tests exercise provenance gates without deploying a consumer.
|
|
70
|
+
Protected PR/integration results and the exact delivery commit are recorded in
|
|
71
|
+
issue 86 after integration.
|
|
72
|
+
|
|
73
|
+
## Urgent consumer adoption
|
|
74
|
+
|
|
75
|
+
The owner authorized a reviewed workflow-only delivery, independently of a new
|
|
76
|
+
gem/wheel/image release. TIG can retain its approved 0.5.0 Gem/core, PDF digest
|
|
77
|
+
and Vega selection and change only the `deploy.uses` revision in
|
|
78
|
+
`.github/workflows/deploy.yml` to the corrected provider's immutable merge SHA.
|
|
79
|
+
This is a reviewed local caller override; a later scaffold update must preserve
|
|
80
|
+
or explicitly reconcile it rather than resetting it to an older packaged pin.
|
|
81
|
+
|
|
82
|
+
In the TIG checkout, open the integration PR, verify that the content remains at
|
|
83
|
+
its approved baseline, repeat the local publication checks, merge, then dispatch
|
|
84
|
+
with the exact newly reviewed `main` SHA. Confirm the hosted build, Pages site
|
|
85
|
+
and downloadable PDF. The provider gate proof alone does not replace TIG's full
|
|
86
|
+
311-page manual validation or successful hosted deployment.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Consolidated deployment integration — 0.7.1
|
|
2
|
+
|
|
3
|
+
Published [v0.7.1](https://github.com/dosquartsdedocs/unaltraweb/releases/tag/v0.7.1)
|
|
4
|
+
on 2026-10-07. The [final delivery report](owner-closeout-93.md) supersedes the
|
|
5
|
+
chronological preparation states below and binds the accepted published bytes.
|
|
6
|
+
|
|
7
|
+
Owner: [issue 93](https://github.com/dosquartsdedocs/unaltraweb/issues/93), following
|
|
8
|
+
the workflow-only [issue 86 correction](deploy-provenance-86.md). The owner
|
|
9
|
+
authorized implementation, review/integration and gated 0.7.1 publication.
|
|
10
|
+
Current source preparation is distinct from a published distribution; final
|
|
11
|
+
source, receipts, installed-byte evidence and publication are recorded in issue 93.
|
|
12
|
+
|
|
13
|
+
## One package-owned contract
|
|
14
|
+
|
|
15
|
+
The BOM now carries two additive schema-v1 fields:
|
|
16
|
+
|
|
17
|
+
- `consumer_integration.site_deploy_workflow_sha`, independent of the Gem's
|
|
18
|
+
`core_sha`. Legacy records default to their core revision.
|
|
19
|
+
- `deployment_contract`, with exact `manual_pdf_workers` digest/producer records
|
|
20
|
+
and bounded `caller_migrations` describing reviewed baseline/current hash pairs.
|
|
21
|
+
|
|
22
|
+
The package schema and semantic checks validate repository confinement, unique
|
|
23
|
+
records, nonzero identities, the selected PDF's membership and exact migration
|
|
24
|
+
identities. Existing packages, receipts and the issue-86 workflow pin remain
|
|
25
|
+
unchanged. PDF 0.6.0, computation/capture 0.4.0 and the accepted visual-helper
|
|
26
|
+
combination are reused rather than introducing additional component upgrades.
|
|
27
|
+
|
|
28
|
+
The workflow fetches at most 256 KiB of JSON from its **defining provider commit**
|
|
29
|
+
on the fixed canonical GitHub repository. It does not read a consumer-supplied
|
|
30
|
+
contract or producer SHA. Strict JSON rejects duplicate/non-finite values; records
|
|
31
|
+
have bounded inventory and exact digest/source syntax. Fetch, lookup, pull and
|
|
32
|
+
inspection failures stop publication. A selected immutable digest is checked
|
|
33
|
+
against its recorded producer, not a later workflow commit. Its temporary metadata
|
|
34
|
+
file is invocation-owned and removed on exit.
|
|
35
|
+
|
|
36
|
+
Static policy binds the generic gate code, while approved artifacts live in the
|
|
37
|
+
contract. Ready-source validation resolves the actual workflow Git pin, checks
|
|
38
|
+
its gate and compares its own producer record with the package selection.
|
|
39
|
+
The CI Docker test additionally creates a package caller and executes the
|
|
40
|
+
preflight blocks of the workflow that caller really selects. Checking only the
|
|
41
|
+
current checkout's YAML is insufficient.
|
|
42
|
+
|
|
43
|
+
## Reviewed hotfix migration
|
|
44
|
+
|
|
45
|
+
Only `.github/workflows/deploy.yml` is eligible for the issue-86 migration:
|
|
46
|
+
|
|
47
|
+
| Identity | SHA-256 |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Original package baseline | `a789870542614d5817d30ea4328c7d1ad38d27443c009c68a48ad5aaa3106b8e` |
|
|
50
|
+
| Exact reviewed one-line hotfix | `c632a548d0782867be20a2a52fe03469cf63066b7364bace77fd54a226cb3b18` |
|
|
51
|
+
|
|
52
|
+
Both must match. The dry-run lists `deploy-provenance-86` in `migrations`, proposes
|
|
53
|
+
the new package-generated caller and binds that authorization to `plan_sha256`.
|
|
54
|
+
The existing confinement, CAS rechecks, private staging, rollback and final
|
|
55
|
+
manifest commit remain in force. Any additional author edit remains a conflict;
|
|
56
|
+
removing the migration authority changes the plan hash. This is not a general
|
|
57
|
+
force-sync or semantic rewrite of authored workflow YAML.
|
|
58
|
+
|
|
59
|
+
## Acceptance stages
|
|
60
|
+
|
|
61
|
+
- Unit/schema/workflow tests cover independent core/workflow pins, legacy metadata,
|
|
62
|
+
invalid or ambiguous records, exact migration, preservation of additional edits,
|
|
63
|
+
plan binding, provider-only contract acquisition and fail-closed network/Docker
|
|
64
|
+
errors.
|
|
65
|
+
- `test/test_deploy_provenance.py` tests actual published PDF workers and a generated
|
|
66
|
+
caller's selected workflow. CI obtains the reviewed source SHA explicitly for
|
|
67
|
+
source-bound metadata access.
|
|
68
|
+
- `test/deployment_integration_smoke.py` uses installed launchers and owned synthetic
|
|
69
|
+
manuals: fresh, populated 0.5.0 upgrade and exact reviewed hotfix. It preserves
|
|
70
|
+
author/cache hashes, applies the reviewed plan, builds PDF/web, probes HTTP and
|
|
71
|
+
executes the exact remotely pinned workflow's source/provenance gates.
|
|
72
|
+
- Final acceptance must use the downloaded same-source wheel and signed MCP
|
|
73
|
+
candidate. The driver does not dispatch Pages or claim a hosted real-manual
|
|
74
|
+
deployment. TIG's authorized deployment is a separate consumer-session proof.
|
|
75
|
+
|
|
76
|
+
The implementation is integrated before the containing source selects its final
|
|
77
|
+
reviewed core/workflow revisions. Candidate components remain pending until that
|
|
78
|
+
selection; release readiness and publication keep their existing strict receipt,
|
|
79
|
+
ancestry, signing and immutable-byte gates.
|
|
80
|
+
|
|
81
|
+
## Reviewed source selection
|
|
82
|
+
|
|
83
|
+
Implementation `2133b8fa2f668e14d603a36d15584eed63e4386a` is integrated through
|
|
84
|
+
[PR 94](https://github.com/dosquartsdedocs/unaltraweb/pull/94) at
|
|
85
|
+
`2ff27f27c274eb09b2c53ef8bd374f333702d8ee`. PR CI `37526811887` and CodeQL
|
|
86
|
+
`37526811747` passed, including actual provider-record acquisition and generated
|
|
87
|
+
caller provenance checks. The review is agent-attributed.
|
|
88
|
+
|
|
89
|
+
The containing candidate now selects this integration for both independent
|
|
90
|
+
core/workflow fields and marks gem, wheel, runtime and MCP ready for same-source
|
|
91
|
+
candidate preparation. The selected workflow's own contract records the reused
|
|
92
|
+
PDF 0.6.0 producer correctly; no worker version change is needed.
|
|
93
|
+
|
|
94
|
+
Local source validation passed 629 cases with 31 optional/environment skips,
|
|
95
|
+
fresh-wheel and owned-image MCP checks/smoke, docs and prose checks. The installed
|
|
96
|
+
development new/upgrade/hotfix manual proof is retained at
|
|
97
|
+
`/tmp/opencode/unaltraweb-071-93/local-integration/evidence.json`, SHA-256
|
|
98
|
+
`d98c0fb56d2b74839a7132cc9dc7ab3f65a9802087837af1a13070a51316a14a`.
|
|
99
|
+
That development proof still used the earlier reviewed workflow pin; final
|
|
100
|
+
signed-candidate acceptance must exercise the now-selected integration above.
|
|
101
|
+
|
|
102
|
+
## Final-byte gate: retained-document worker closure
|
|
103
|
+
|
|
104
|
+
The first candidates from `b7ec1d7a139c65b3b0b88699cdbeb19080f13be1` passed normal
|
|
105
|
+
manual upgrades but failed retained-Carta freshness with the reused PDF 0.6.0.
|
|
106
|
+
The manifest fingerprints `artifact_imports.CHECKER_FILES`, including the changed
|
|
107
|
+
distribution module and component schema. Successful PDF generation alone was
|
|
108
|
+
not sufficient: the old worker and new controller calculated different identities.
|
|
109
|
+
Those first core candidates are retained diagnostic evidence and are not promoted
|
|
110
|
+
as the 0.7.1 release.
|
|
111
|
+
|
|
112
|
+
The signed PDF specialization already built/tested by run `37530306398` contains
|
|
113
|
+
the matching 0.7.1 checker closure:
|
|
114
|
+
`ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf@sha256:1bb3f2dafd741e96c28639ec1cc8ccaeb81cbaa73e649f787c0b4ef59997bd4b`.
|
|
115
|
+
Its configuration ID is
|
|
116
|
+
`sha256:618163d3f924439792b2306617bd9612f566c5881166102fa544b4e782d569fa`,
|
|
117
|
+
its producer revision is the first candidate source above and its native package
|
|
118
|
+
reports 0.7.1. The changed checker files match the controller byte for byte.
|
|
119
|
+
|
|
120
|
+
A local controller overlay selecting only that exact worker passed the complete
|
|
121
|
+
Carta import, copied-producer retirement, receiver relocation and forced PDF
|
|
122
|
+
rebuild. Both 11-page PDFs have hash
|
|
123
|
+
`eb693ced023efafe36a926dd38a1bf1c85399a1b114551cc0ff32e652144c496`; original Carta
|
|
124
|
+
bytes remain unchanged. Diagnostic evidence:
|
|
125
|
+
`/tmp/opencode/unaltraweb-071-93/pdf071-carta-probe/evidence.json`, SHA-256
|
|
126
|
+
`c076f988e43ddb474132e58f5027931085bd734242757b84fb50289ef68cde25`.
|
|
127
|
+
The overlay is not a signed final MCP identity.
|
|
128
|
+
|
|
129
|
+
The worker record is integrated before a follow-up selection pins its containing
|
|
130
|
+
workflow and PDF. Core components return to pending during this preparation.
|
|
131
|
+
Ready-source CI now requires the exact selected core, controller and PDF worker
|
|
132
|
+
to agree on every retained-document checker file. This catches this class of
|
|
133
|
+
incompatibility before final publication; the final signed core candidates must
|
|
134
|
+
still repeat the complete composed acceptance.
|
|
135
|
+
|
|
136
|
+
The producer record and checker-closure regression were integrated through
|
|
137
|
+
[PR 96](https://github.com/dosquartsdedocs/unaltraweb/pull/96) at
|
|
138
|
+
`3332e0b93933f12317e05f1ce8d38ce80046feab`. This is the final reviewed core/workflow
|
|
139
|
+
selection. The tuple selects the verified PDF specialization above as 0.7.1,
|
|
140
|
+
published by its immutable digest, and the four core components return to ready.
|
|
141
|
+
Their new same-source candidates replace the rejected first core tuple in the
|
|
142
|
+
eventual release receipt. No earlier release or worker is overwritten.
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
This is the component contract for MCP agents drafting or reviewing `unaltremanual` content. Read it together with the consumer site's `context/writing-profile.md`.
|
|
4
4
|
|
|
5
|
+
## Private practice readings
|
|
6
|
+
|
|
7
|
+
Standalone practice readings live in `practiques/<slug>/<lang>/<alumnat|docent>/`,
|
|
8
|
+
using `LLEGIU-ME.md` (ca), `LEEME.md` (es) or `README.md` (en). Use
|
|
9
|
+
`manual_practice_pdf_build` with an explicit practice version to produce a
|
|
10
|
+
private A4-landscape PDF under an ignored, retained `sandbox/practiques/` job.
|
|
11
|
+
The source requires front-matter `title`; `lang` must agree with the path.
|
|
12
|
+
Use `#` for body sections and `##` for subsections. Keep a table's `Table:`
|
|
13
|
+
caption and each standalone image's descriptive caption with its source.
|
|
14
|
+
|
|
15
|
+
The practice wrapper reuses site metadata and manual typography. Course codes
|
|
16
|
+
appear in parentheses beside the subject; the practice version is shown without
|
|
17
|
+
the academic year. Logos occur only on the first page. Figures are centred and
|
|
18
|
+
automatically fit the usable page after reserving the caption and its spacing.
|
|
19
|
+
|
|
20
|
+
The initial reading API accepts ordinary Pandoc Markdown, local PNG/JPEG/PDF
|
|
21
|
+
images, links, maths, fenced code and captioned tables. Use provider-rendered
|
|
22
|
+
printable images rather than executable or remote visual sources. Liquid,
|
|
23
|
+
manual-only component wrappers and automatic bibliography assembly are outside
|
|
24
|
+
this reading syntax. Its private source paths are not added to the public
|
|
25
|
+
editorial/translation inventories. Review the returned PDF explicitly; a layout
|
|
26
|
+
approval does not change source `content_status` or authorize publication.
|
|
27
|
+
|
|
5
28
|
## Paragraph development
|
|
6
29
|
|
|
7
30
|
Diagnose paragraph function before polishing sentences. A paragraph should normally have one primary job and, when the material warrants it, develop this sequence:
|
data/docs/agents/mcp-contract.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# MCP Contract
|
|
2
2
|
|
|
3
|
-
The D0 additions
|
|
3
|
+
The D0 additions ship in the published 0.7.0 runtime. Their pinned requirements,
|
|
4
4
|
exact API mapping, lifecycle scopes and external helper-identity blocker are
|
|
5
5
|
documented in [the owner contract](d0-runtime-identity.md). A source descriptor
|
|
6
|
-
does not upgrade an already-running 0.6.0 connection.
|
|
6
|
+
does not upgrade an already-running 0.6.0 connection. Exact public identities and
|
|
7
|
+
installed acceptance are recorded in [the delivery report](owner-closeout-85.md).
|
|
7
8
|
|
|
8
9
|
`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.
|
|
9
10
|
|
|
@@ -37,8 +38,10 @@ it to an image ID before execution. The source checkout's digest pin is separate
|
|
|
37
38
|
it advances only after a new receipt exists. Explicit `--image` (or the console
|
|
38
39
|
adapter's `UNALTRAWEB_MCP_IMAGE`) permits a reviewed immutable selection.
|
|
39
40
|
|
|
40
|
-
The post-release checkout pin selects published 0.
|
|
41
|
-
`sha256:
|
|
41
|
+
The post-release checkout pin selects published 0.7.1 MCP digest
|
|
42
|
+
`sha256:6aa20cff86c3891a876e37ba0548fa36f3c5633c9f22ba672e9f50123d677cf6`.
|
|
43
|
+
The [0.7.1 delivery report](owner-closeout-93.md) records the consolidated deployment
|
|
44
|
+
contract, exact hotfix migration and matching PDF verifier closure.
|
|
42
45
|
Existing processes keep their running image until clients reconnect. Site build
|
|
43
46
|
defaults and customized Makefiles remain separate, explicitly reviewed selections.
|
|
44
47
|
|
|
@@ -86,6 +89,8 @@ baseline format nor runtime cleanup changes.
|
|
|
86
89
|
|
|
87
90
|
| Resource | Description |
|
|
88
91
|
| --- | --- |
|
|
92
|
+
| `web://practice-edition-schema` | Versioned Web recipient/edition configuration, separate from the producer-owned GIS descriptor. |
|
|
93
|
+
| `web://practice-verifier-runtime` | Static private controller/package/profile identities and distinct release metadata; acquisition belongs to the hub. |
|
|
89
94
|
| `web://runtime-identity` | Bounded identity of this serving process: startup/current code, instance/PID namespaces, binding, runtime selections and cooperative lifecycle. |
|
|
90
95
|
| `web://distribution` | Package-owned component BOM plus offline, feature-aware doctor findings for the current factory and project. |
|
|
91
96
|
| `web://site-context` | Site profile, feature flags, content inventory, bibliography, bibliometrics, build state, and offline consumer-update advisory. |
|
|
@@ -113,8 +118,68 @@ baseline format nor runtime cleanup changes.
|
|
|
113
118
|
|
|
114
119
|
## Tools
|
|
115
120
|
|
|
121
|
+
Private teaching editions use `manual_practice_compose(config, dry_run=false)`
|
|
122
|
+
(CLI `mcp manual-practice-compose`, factory Make `manual-practice-compose`).
|
|
123
|
+
`web://practice-edition-schema` supplies the versioned Web composition contract.
|
|
124
|
+
The editor invokes the native CLI of the hub-prepared private QGIS controller, validates the full common
|
|
125
|
+
bundle, selects explicit IDs with their complete producer closure, and retains
|
|
126
|
+
one independent PDF and one ZIP per recipient, plus external receipts, under
|
|
127
|
+
`dist/practiques/`. The PDF is copied from the sealed reading job and has exactly
|
|
128
|
+
the same bytes as its ZIP member; no second render occurs. The entire edition
|
|
129
|
+
directory is installed atomically and never replaces an existing edition. GIS parsing,
|
|
130
|
+
execution and offline project reopening remain producer-owned.
|
|
131
|
+
|
|
132
|
+
Each PDF build returns its original PDF and receipt hashes. Composition captures
|
|
133
|
+
and checks that seal before building the other recipient, then copies only those
|
|
134
|
+
sealed bytes. A changed PDF or replaced/resealed receipt fails before publication.
|
|
135
|
+
|
|
136
|
+
`packages.<recipient>` retains its ZIP fields and adds `pdf` with the independent
|
|
137
|
+
PDF path/hash/bytes and its own receipt path/hash. Names share the same stem:
|
|
138
|
+
`<slug>[-docent]-<version>-<lang>.pdf` and `.zip`. Source/reading code remains
|
|
139
|
+
versioned; data, PDFs, ZIPs and their retained sandbox/dist jobs remain ignored
|
|
140
|
+
deliveries for Moodle, not Git publication. The paired PDF keeps ZIP-relative
|
|
141
|
+
resource links; extract the ZIP beside it for those links to resolve locally.
|
|
142
|
+
|
|
143
|
+
An edition's `gis.profile` explicitly selects `qgis-practice-v1` or
|
|
144
|
+
`qgis-practice-v2` and its matching producer schema hash. Omitted profile is the
|
|
145
|
+
legacy v1 case only. New configurations explicitly select verifier origin
|
|
146
|
+
`prepared-image`, its image ID, native installed-package revision and schema hash.
|
|
147
|
+
Legacy installed-wheel configuration shapes remain readable but are not silently
|
|
148
|
+
converted or executed by this public Web runtime. Schema discovery invokes the
|
|
149
|
+
requested profile in the private image. The selected bundle check must return
|
|
150
|
+
that same profile. V2 map exports and their font/symbol/sidecar closures retain
|
|
151
|
+
producer-declared roles and paths; the editor does not inspect their native formats.
|
|
152
|
+
|
|
153
|
+
The public Web image contains no private QGIS package. The hub prepares the
|
|
154
|
+
authenticated private image before activation; missing/mismatched images produce
|
|
155
|
+
a concrete blocker without pull/build. Native calls reuse bounded processes,
|
|
156
|
+
mount encoding and exact worker lifecycle. `practice_verifier` is a startup-fixed
|
|
157
|
+
worker selection. Release wheel hashes and release producer revisions are declared
|
|
158
|
+
provenance, separate from observed image/package identity; no `direct_url` is
|
|
159
|
+
fabricated. Public CI reports private checks as `not_run`.
|
|
160
|
+
See [private-practice-verifier-98.md](private-practice-verifier-98.md).
|
|
161
|
+
|
|
162
|
+
Existing private readings can be declared once in `_config.yml` under
|
|
163
|
+
`unaltraweb.practices.readings`, with exact `source`, `slug`, `lang`, `recipient`.
|
|
164
|
+
Only Markdown beneath `practiques/` or `_practices/` is accepted. The same resolver
|
|
165
|
+
serves PDF preparation and targeted `prose_check` / `editorial_review_prepare`.
|
|
166
|
+
Private targets include draft/unpublished prose and retain original anchors;
|
|
167
|
+
they are excluded from the default public corpus. Mapping does not approve copy
|
|
168
|
+
or expose private directories through Jekyll.
|
|
169
|
+
|
|
170
|
+
Reading mappings and edition readings accept the same optional `bindings` list:
|
|
171
|
+
`reference`, exactly one `path` or selected `product`, required `sha256`, and
|
|
172
|
+
optional portable `destination`. One practice resolver uses these declarations
|
|
173
|
+
for both image snapshots and prose links. It never searches sandbox directories.
|
|
174
|
+
Composition normalizes a prose href relative to the original source and emits
|
|
175
|
+
only the authorised recipient's ZIP destination; bound files/maps and effective
|
|
176
|
+
Pandoc sources are fingerprinted and receipted. Normal filesystem validators stay
|
|
177
|
+
strict. Standalone PDFs allow explicit image bindings but refuse local file links
|
|
178
|
+
without a portable edition context; HTTPS and internal anchors remain intact.
|
|
179
|
+
|
|
116
180
|
| Tool | Notes |
|
|
117
181
|
| --- | --- |
|
|
182
|
+
| `manual_practice_compose` | One versioned consumer configuration selects GIS roots, two approved reading hashes and optional declared editable-SVG resources; delivers an independent PDF and ZIP per recipient with complete closure and create-only receipts. |
|
|
118
183
|
| `runtime_identity` | Observe the actual serving instance, startup/current package evidence and selected/observed images; never prepare a runtime or inspect site content. |
|
|
119
184
|
| `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. |
|
|
120
185
|
| `distribution_doctor` | Return offline component/factory/project findings with stable codes and optional local Docker image inspection that never pulls. |
|
|
@@ -130,7 +195,7 @@ baseline format nor runtime cleanup changes.
|
|
|
130
195
|
| `site_source_read` | Read one allowed UTF-8 site source and return its exact SHA-256. |
|
|
131
196
|
| `site_source_write` | Dry-run or atomically create/update one allowed source. Creates require `create_only`; updates require the exact SHA-256 returned by a read. |
|
|
132
197
|
| `site_source_delete` | Dry-run or delete one allowed source with exact SHA-256 and explicit confirmation. It never deletes `_config.yml` or directories. |
|
|
133
|
-
| `scaffold_sync` | Dry-run or transactionally synchronize the
|
|
198
|
+
| `scaffold_sync` | Dry-run or transactionally synchronize the ten package-managed scaffold controls against `.unaltraweb/scaffold.json`; preserve local edits if the package file has not changed from baseline, reject conflicting edits and known version downgrades, and optionally require `expected_plan_sha256` from the reviewed proposal. Exact package bytes may be adopted without rewriting. Adopted, unchanged and preserved files are rechecked around the manifest-last transaction; rollback covers partial apply. README prose and source-CI project policy remain site-owned. |
|
|
134
199
|
| `profile_check` | Check current profile and expected content/config paths. |
|
|
135
200
|
| `prose_check` | Check a selected content target or all supported reader-facing sources and public metadata using shared profile/genre rules; no writes or model calls. |
|
|
136
201
|
| `editorial_policy` | Inspect common guidance, profile defaults, genre overrides, local writing preferences and optional publication requirements. |
|
|
@@ -152,6 +217,7 @@ baseline format nor runtime cleanup changes.
|
|
|
152
217
|
| `web_capture_render` | Start Jekyll and Chromium on an ephemeral internal Docker network, then publish original PNG plus editable annotated SVG from declared CSS selectors. |
|
|
153
218
|
| `manual_pdf_status` | Inspect PDF configuration, sources, generated artefacts, published paths, selector, and freshness without Docker, network, or writes. |
|
|
154
219
|
| `manual_pdf_build` | Build one or all configured language PDFs and first-page cover previews under `tmp/`; `release_selector` defaults to `latest` and is part of the PDF fingerprint. |
|
|
220
|
+
| `manual_practice_pdf_build` | Build one private A4-landscape reading from `practiques/<slug>/<lang>/<audience>/` into an ignored, retained sandbox job. Reuse manual metadata/logos; require a prepared PDF toolchain; never publish or package course data. `dry_run` plans without writes and `run` names an explicit retained attempt. |
|
|
155
221
|
| `manual_pdf_preview_prepare` | Build only stale `latest` PDF languages, then atomically stage ignored, untracked PDF and cover copies for local Jekyll review under a cleanup receipt. Always reports `publishes: false`; disabled PDF configuration is a no-op unless receipt-owned preview files still require cleanup. |
|
|
156
222
|
| `manual_pdf_preview_clean` | Dry-run or remove only preview files whose path, Git state, content hash, and file identity still match the staging receipt. Real cleanup requires explicit confirmation plus the dry-run's exact `receipt_sha256` as `expected_receipt_sha256`, and never publishes. |
|
|
157
223
|
| `manual_pdf_publish` | Copy built PDFs and covers to configured public assets. Defaults to dry-run; real publication requires explicit confirmation, and the selector must match the build. |
|
|
@@ -188,6 +254,36 @@ Manual PDF publication is a local workspace operation: it copies reviewed artefa
|
|
|
188
254
|
|
|
189
255
|
## New Site Initialization
|
|
190
256
|
|
|
257
|
+
### Private Practice Readings
|
|
258
|
+
|
|
259
|
+
`manual_practice_pdf_build(source, version, run="", dry_run=false)` delegates to
|
|
260
|
+
the factory target `manual-practice-pdf-build`. Source paths are
|
|
261
|
+
`practiques/<slug>/<ca|es|en>/<alumnat|docent>/<localized-name>.md`, using
|
|
262
|
+
`LLEGIU-ME`, `LEEME` and `README`. The consumer must exclude `practiques/`,
|
|
263
|
+
`sandbox/` and `dist/` from Jekyll and ignore `sandbox/practiques/` in Git.
|
|
264
|
+
`profile_check` blocks a manual with practice sources and missing exclusions.
|
|
265
|
+
|
|
266
|
+
The controller reuses manual metadata normalization and its authoritative
|
|
267
|
+
typographic preamble, with a factory-owned A4-landscape article wrapper. It
|
|
268
|
+
snapshots only the selected Markdown, local PNG/JPEG/PDF images, logos, template
|
|
269
|
+
and filters. Its network-disabled, read-only worker receives that snapshot and
|
|
270
|
+
one writable output directory; it receives neither checkout nor Docker socket.
|
|
271
|
+
The already-prepared PDF toolchain is resolved to an exact image ID and never
|
|
272
|
+
pulled implicitly. Session/project/token worker labels retain the existing D0
|
|
273
|
+
ownership and timeout-cleanup contract.
|
|
274
|
+
|
|
275
|
+
Jobs under `sandbox/practiques/` are create-only and sealed last. Repeat calls
|
|
276
|
+
verify and reuse the exact job when its effective inputs match. Changed source,
|
|
277
|
+
assets, rendering controls or image identity select another job; a nominal MCP
|
|
278
|
+
version change alone does not. Edited, incomplete or conflicting jobs are
|
|
279
|
+
retained. The optional `run` name provides an explicit retry/review identity.
|
|
280
|
+
Every result reports `publishes: false`.
|
|
281
|
+
|
|
282
|
+
This API compiles a reading, not a GIS job, public chapter or Moodle ZIP. The
|
|
283
|
+
larger producer-handoff and package contract remains under issue #98. See
|
|
284
|
+
[private practice PDFs](../_documentation/en/47-private-practice-pdfs.md) for
|
|
285
|
+
supported syntax and adoption in an existing manual.
|
|
286
|
+
|
|
191
287
|
### Retained Letter Integration
|
|
192
288
|
|
|
193
289
|
The published 0.6.0 release adds package-only import/check commands and the
|
|
@@ -223,7 +319,17 @@ It sets `lang`, `default_lang`, and `languages` so a new site has an explicit so
|
|
|
223
319
|
|
|
224
320
|
Before writing, it validates every managed path, rejects destination symlinks, and compares existing files with the complete rendered scaffold through bounded regular-file reads. Identical files make repeated calls idempotent. Any differing file or file/directory collision detected during preflight aborts the whole operation before website files are written. Descriptor-relative, no-clobber writes and a final descriptor-relative content check prevent raced paths from being followed or overwritten; overwrite mode is not available. The baseline manifest is created after every other scaffold file.
|
|
225
321
|
|
|
226
|
-
The baseline records exactly `.gitignore`, `.unaltraweb/docker-mount.sh`, `.github/CONTRIBUTING.md`, `.github/dependabot.yml`, `Makefile`, `Gemfile`, `Gemfile.lock`, `.github/pull_request_template.md`, and `.github/workflows/
|
|
322
|
+
The baseline records exactly `.gitignore`, `.unaltraweb/docker-mount.sh`, `.github/CONTRIBUTING.md`, `.github/dependabot.yml`, `Makefile`, `Gemfile`, `Gemfile.lock`, `.github/pull_request_template.md`, `.github/workflows/deploy.yml`, and `.github/workflows/source-checks.yml`. `scaffold_sync` updates one of these while its bytes still match the recorded baseline, adopts it when its bytes already equal the current package payload, and creates a newly managed path only when absent. If the package payload still equals the baseline but the local file differs, it preserves the local file and the original baseline hash; a subsequent upstream edit will still conflict. Conflicting local/upstream edits, missing managed files, collisions, unsafe paths and known newer consumer versions block the whole apply. It removes retired paths only from the baseline and never deletes their project files; it also never changes site-owned README/agent guidance, config, seed content, bibliography, data, assets, or `.unaltraweb/source-checks.json`. A real synchronization requires `dry_run=false` and `confirm_sync=true`; adopted, unchanged and preserved files are included in the final rechecks around the manifest-last commit.
|
|
323
|
+
|
|
324
|
+
Source CI is a separate host entrypoint, `unaltraweb-source-checks` (equivalently
|
|
325
|
+
`python -I -m unaltraweb_mcp.source_checks`), not another MCP server. One packaged
|
|
326
|
+
workflow control calls it for all profiles; only the bounded Git-versioned JSON
|
|
327
|
+
policy differs by project. It wraps the public `profile-check` and `prose-check`
|
|
328
|
+
commands and observes the existing approval inventory without granting approval.
|
|
329
|
+
Read-only clone mounts, no Docker socket, network-none checkers, explicit partial
|
|
330
|
+
coverage and base-to-head inventory checks preserve the distinction between
|
|
331
|
+
source conservation and retained-input/domain validation. See
|
|
332
|
+
[source-ci-98.md](source-ci-98.md) for activation and the public/private GitHub boundary.
|
|
227
333
|
|
|
228
334
|
At session start, `site_context.update_status` supplies an offline advisory against the active MCP package, including current literal version pins, target integration tuple, planned paths, preserved files, conflicts and `plan_sha256`. The agent explains available updates and asks for explicit acceptance before invoking `scaffold_sync` with that digest as `expected_plan_sha256`. The digest binds the consumer path, configuration, baseline, observed managed bytes and target package bytes; stale approval is rejected before writes. The parameter is optional for compatibility with existing explicit sync callers, but the guided flow always supplies it. An update can refresh scaffold controls without claiming a newer semver release. Unmanaged sites report an unavailable plan instead of being reinitialized. A declined update leaves normal content work available; there is no background network poll, self-upgrade, Git operation or automatic artefact regeneration. This flow requires a reviewed MCP/package release containing it and a reconnected client; updating the discovery checkout alone cannot replace the public digest-pinned runtime.
|
|
229
335
|
|