From 7114c04aa5dcb41998b67671b6b495fad58a06f2 Mon Sep 17 00:00:00 2001 From: Martin Hinshelwood Date: Wed, 23 Sep 2026 15:25:15 +0100 Subject: [PATCH 1/4] Add layered PDF recipe, cover credits and translation-team contributor files PDFs: Get-GuidePdfPlan now builds the recipe only from committed configuration, layered platform -> /pdf -> guide -> edition with . variants. Adds default cover, licence, back, running header/footer and style templates, the reviewed callouts and Hugo image filters, CJK font keys, RTL support and per-download overrides. Removes the per-run HeaderPaths/LuaFilterPaths/FontOverrides parameters and the Kanban-specific cover-page.tex. Contributors: data/contributions/..yml holds translation teams; localizedNames per record; Get-GuideCredits resolves authors (role creator), contributors and translators for PDFs. Website translator displays read the data files, including PDF-only translations. Prepare blocks retired front matter (author, translators, fonts, dir), invalid contributor records and PDF settings, and warns on missing creators, translators and PDF labels. Discovery reads declared downloads and records language direction. The sample site is migrated. Spec: docs/architecture/guide-pdf-and-contributors.md Co-Authored-By: Claude Opus 5.5 --- docs/architecture/current-system.md | 5 +- .../guide-pdf-and-contributors.md | 314 ++++++++++++++++++ .../content/Guide1/2020.12/index.md | 5 - .../content/Guide1/2020.12/index.min.md | 6 - .../content/Guide1/2020.7/index.md | 6 - .../content/Guide1/2020.7/index.min.md | 6 - .../content/Guide1/2025.5/index.md | 6 - .../content/Guide1/2025.5/index.min.md | 6 - .../content/Guide2/2025.7/index.md | 5 - .../content/Guide2/2025.7/index.min.md | 5 - .../data/contributions/guide1.min.yml | 8 + .../data/contributions/guide1.yml | 32 +- .../data/contributions/guide2.min.yml | 6 + .../data/contributions/guide2.yml | 29 +- examples/reference-guide-site/i18n/en.yaml | 3 + examples/reference-guide-site/i18n/min.yaml | 3 + examples/reference-guide-site/pdf/README.md | 14 + examples/reference-guide-site/pdf/pdf.ja.yaml | 5 + examples/reference-guide-site/pdf/pdf.yaml | 5 + .../instructions/guide-site.md | 1 + .../skills/guide.contributions/SKILL.md | 12 +- .../skills/guide.genpdfs/SKILL.md | 10 +- .../components/guide/guide-translators.html | 6 +- .../translations/community-translations2.html | 14 +- .../_partials/functions/get-contributors.html | 10 +- .../_partials/functions/get-participants.html | 6 +- .../_partials/functions/get-translators.html | 25 ++ .../functions/localize-contributor.html | 17 + .../Assessment/Get-GuideAssessment.ps1 | 8 + .../Contracts/site-policy.schema.json | 4 + .../Get-GuideCredits.ps1 | 147 ++++++++ .../New-GuideContributions.ps1 | 6 +- .../Update-GuideContributions.ps1 | 21 +- .../GuideInventory/Get-GuideInventory.ps1 | 5 +- .../OpenGuidePlatform.PowerShell.Core.psd1 | 2 +- .../OpenGuidePlatform.PowerShell.Core.psm1 | 2 + .../PdfPublishing/Get-GuidePdfPlan.ps1 | 144 +++++++- .../PdfPublishing/Resolve-GuidePdfRecipe.ps1 | 227 +++++++++++++ .../PdfPublishing/Test-GuidePdfCache.ps1 | 3 +- .../PdfPublishing/templates/back.tex | 8 + .../PdfPublishing/templates/body-start.tex | 5 + .../PdfPublishing/templates/cover-page.tex | 39 --- .../PdfPublishing/templates/cover.tex | 42 +++ .../templates/filters/callouts.lua | 75 +++++ .../templates/filters/callouts.tex | 21 ++ .../templates/filters/hugo-images.lua | 9 + .../PdfPublishing/templates/labels.yaml | 11 + .../PdfPublishing/templates/licence.tex | 12 + .../PdfPublishing/templates/page-footer.tex | 5 + .../PdfPublishing/templates/page-header.tex | 15 + .../PdfPublishing/templates/pdf.yaml | 14 + .../PdfPublishing/templates/rtl.tex | 8 + .../PdfPublishing/templates/style.tex | 13 + .../README.md | 19 ++ .../Discovery/New-GuideSiteDiscovery.ps1 | 29 +- tests/Core/Assessment.Tests.ps1 | 12 + tests/Core/Discovery.Tests.ps1 | 27 ++ tests/Core/GuideCredits.Tests.ps1 | 93 ++++++ tests/Core/GuidePdfRecipe.Tests.ps1 | 133 ++++++++ tests/Core/HugoGuideRendering.Tests.ps1 | 19 +- 60 files changed, 1569 insertions(+), 179 deletions(-) create mode 100644 docs/architecture/guide-pdf-and-contributors.md create mode 100644 examples/reference-guide-site/data/contributions/guide1.min.yml create mode 100644 examples/reference-guide-site/data/contributions/guide2.min.yml create mode 100644 examples/reference-guide-site/pdf/README.md create mode 100644 examples/reference-guide-site/pdf/pdf.ja.yaml create mode 100644 examples/reference-guide-site/pdf/pdf.yaml create mode 100644 system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/functions/get-translators.html create mode 100644 system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/functions/localize-contributor.html create mode 100644 system/OpenGuidePlatform.PowerShell.Core/ContributorManagement/Get-GuideCredits.ps1 create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Resolve-GuidePdfRecipe.ps1 create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/back.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/body-start.tex delete mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/cover-page.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/cover.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/filters/callouts.lua create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/filters/callouts.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/filters/hugo-images.lua create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/labels.yaml create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/licence.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/page-footer.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/page-header.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/pdf.yaml create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/rtl.tex create mode 100644 system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/style.tex create mode 100644 tests/Core/GuideCredits.Tests.ps1 create mode 100644 tests/Core/GuidePdfRecipe.Tests.ps1 diff --git a/docs/architecture/current-system.md b/docs/architecture/current-system.md index 2997b0c8..8585aab7 100644 --- a/docs/architecture/current-system.md +++ b/docs/architecture/current-system.md @@ -28,7 +28,8 @@ The **PowerShell filesystem walk**, not `hugo list all`, creates the `guides`, ` | Guide | Recursively find `_index.md` under the configured content directory; keep a directory when that file's front matter has `type: guide` and `layout: root` and at least one accepted edition. Guide `id` is its path relative to the content directory. | | Edition/version | Inspect immediate child directories of the guide. Keep one when it contains `index.md`, its layout is not `translations`, `history`, `root` or `details`, and its front matter has either `type: guide` or a `version` field. Use the `version` field as edition `id` when present; otherwise use the directory name. | | Language | Collect languages from edition-root `index*.md` filenames and from recognised PDF suffixes. `index.md` means the configured default language; `index..md` supplies ``. | -| PDF/download | Find `*.pdf` recursively inside the edition. A filename ending `..pdf` is assigned to that language; a PDF without a recognised suffix is assigned to the configured default language. Store its path relative to the edition and mark its inferred handling `supplied`. | +| PDF/download | Find `*.pdf` recursively inside the edition, plus any path declared in `/pdf///pdf[.].yaml` `downloads`. A filename ending `..pdf` is assigned to that language; a PDF without a recognised suffix is assigned to the configured default language. Store its path relative to the edition with the declared handling, otherwise `supplied`. | +| Language direction | Record `direction` (or the older `languageDirection`) for each configured language in `wrapper.languageDirections`. | For each collected language, the code reads the corresponding `index.md` or `index..md` body and infers `web` when populated, `pdf-only` when the body is empty but a matching PDF exists, `web` for the empty default-language source, or `fallback` to the default language otherwise. It also records required guide-root, history and translations wrapper files for active guide languages. These are the rules in the [source walk and entry construction](../../system/OpenGuidePlatform.PowerShell.GuideSiteBuild/Discovery/New-GuideSiteDiscovery.ps1); they describe what the code currently recognises, not a proposed content format. @@ -64,7 +65,7 @@ The [build-stage script](../../system/OpenGuidePlatform.PowerShell.GuideSiteBuil ## PDF evidence and preservation -[`Get-GuidePdfPlan` and `New-GuidePdf`](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Get-GuidePdfPlan.ps1) select only a download declared `generated`, read `index.md` or `index..md`, and pass language to Pandoc as metadata. They check tools/fonts, render in staging and check the PDF header before publishing. Replacement requires the existing output's expected SHA256. Supplied and protected downloads cannot be selected for generation. [`Get-GuideAssessment`](../../system/OpenGuidePlatform.PowerShell.Core/Assessment/Get-GuideAssessment.ps1) flags `lang` in Hugo front matter as deprecated. +[`Get-GuidePdfPlan` and `New-GuidePdf`](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Get-GuidePdfPlan.ps1) select only a download declared `generated`, read `index.md` or `index..md`, and pass language to Pandoc as metadata. The recipe is [resolved](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Resolve-GuidePdfRecipe.ps1) from platform templates and the site's `pdf/` folder by guide, edition and language; cover credits come from [contributor data](../../system/OpenGuidePlatform.PowerShell.Core/ContributorManagement/Get-GuideCredits.ps1). Template parts are rendered with the generated metadata before the main Pandoc run. See [Guide PDFs and contributor records](guide-pdf-and-contributors.md). They check tools/fonts, render in staging and check the PDF header before publishing. Replacement requires the existing output's expected SHA256. Supplied and protected downloads cannot be selected for generation. [`Get-GuideAssessment`](../../system/OpenGuidePlatform.PowerShell.Core/Assessment/Get-GuideAssessment.ps1) flags `lang` in Hugo front matter as deprecated, blocks the retired `author`, `translators`, font and `dir` keys, and validates contributor data and PDF settings. [`New-GuidePdf`](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Get-GuidePdfPlan.ps1) returns a v1 receipt with guide, edition, language, input/output hashes, configuration hash, toolchain, environment digest and optional cache key. [`Save-GuidePdfReceipt` and `Get-GuidePdfReceipts`](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Get-GuidePdfReceipts.ps1) save and validate declared receipts; Prepare calls the latter without rerunning Pandoc. [`Test-GuidePdfCache`](../../system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/Test-GuidePdfCache.ps1) uses content/recipe/tool/environment evidence rather than timestamps. The returned PDF result says visual review is required; neither receipt validation nor source discovery assesses translation quality. diff --git a/docs/architecture/guide-pdf-and-contributors.md b/docs/architecture/guide-pdf-and-contributors.md new file mode 100644 index 00000000..752dc1b4 --- /dev/null +++ b/docs/architecture/guide-pdf-and-contributors.md @@ -0,0 +1,314 @@ +# Guide PDFs and contributor records + +Status: platform part (actions 1 and 3, and section 5) implemented on branch `feature/guide-pdf-and-contributors`; consumer adoption (actions 2 and 4) not started. Section 9 records where the implementation differs from the original draft. + +## 1. Purpose and scope + +Every generated guide PDF gets a cover page with the title, edition, date, authors, contributors and translators, and every part of the PDF can be overridden per site, guide, edition and language. To make that possible, contributor and translator records move to one data format, and PDF settings move out of guide Markdown into a dedicated site folder. + +The work is delivered as four actions: + +1. Platform: new contributor record format (section 3). +2. Consumers: adopt the contributor format (section 7). +3. Platform: new PDF format (section 4). +4. Consumers: adopt the PDF format (section 7). + +Actions 1 and 3 ship in one coordinated platform release so each consumer performs a single preview update and one adoption branch. Prepare validation (section 5) ships in the same release. + +Out of scope: renaming guide identifiers or published PDF filenames, regenerating any PDF without an explicit `generated` declaration and visual review, translation quality, and Hugo module refactoring (E14). + +## 2. Current state + +Observed in KanbanGuides and ScrumGuide-ExpansionPack on 2026-09-23. + +PDF generation (`PdfPublishing/Get-GuidePdfPlan.ps1`) runs Pandoc with XeLaTeX and Pandoc's default LaTeX template. It passes only `--pdf-engine`, `-interaction=nonstopmode`, `lang` and an empty `keywords`. Header files, Lua filters and font overrides are per-invocation parameters; nothing records a site's approved recipe. The shipped `templates/cover-page.tex` is not wired to any invocation and contains Kanban-specific fixed text. ScrumGuide-ExpansionPack still tracks its retired recipe in `scripts/` (`Create-GuidePDFs.ps1`, `callouts-latex.lua`, `callouts-header.tex`, `callouts.lua`, `cover-page.tex`); its cover is the same template with Scrum-specific fixed text. + +PDF settings live in guide front matter: `mainfont`, `sansfont`, `monofont` and, for Persian, `dir`. Values are identical for every file of a language, with two exceptions in ScrumGuide-ExpansionPack: Japanese uses Times New Roman/Arial (no CJK glyphs), and `de` 2025.6 declares no fonts. + +Contributors are recorded in three inconsistent places: + +| Record | Location | Consumers | +|---|---|---| +| Authors | `author:` in every translation's front matter, and again as `role: creator` in `site/data/contributions/.yml` | JSON-LD `person.html`, Kanban home page | +| Contributors | `site/data/contributions/.yml` (`.yml` or `.yaml`) filtered by edition | `get-contributors.html` | +| Translators | `translators:` in some translations' front matter; names in body text for others; nothing for many | `guide-translators.html`, `community-translations2.html` | + +Known data defects are listed per consumer in section 7. + +## 3. Contributor records + +### 3.1 Files + +``` +site/data/contributions/ +├── .yml ← guide source: creators, contributors, reviewers +└── ..yml ← one translation team: translators, translation reviewers +``` + +`` is the content language code exactly as used in `index..md`. New files use `.yml`. Hugo does not treat the language suffix in data specially; layouts read `hugo.Data.contributions` with the key `.`. + +A subfolder per guide is not used because it would collide with the existing `.yml` key. + +### 3.2 Record schema + +Both files are YAML lists of records: + +| Field | Required | Meaning | +|---|---|---| +| `name` | yes | Display name | +| `role` | yes | One of the roles in 3.3, lower case | +| `contributions` | yes | Edition identifiers (`"2025.7"`) this record applies to | +| `weight` | no | Sort order, ascending; default 100 | +| `localizedNames` | no | Map of language code to the name as displayed in that language | +| `githubUsername`, `gravatarHash`, `url`, `founder` | no | Unchanged from today | + +Example `the-kanban-guide.yml` record with a Persian spelling, and `the-kanban-guide.fa.yml`: + +```yaml +- name: John Coleman + role: creator + contributions: ["2020.7", "2020.12", "2025.5"] + weight: 1 + localizedNames: + fa: جان کولمن +``` + +```yaml +- name: Pedram Keshavarzi + githubUsername: pedicurus + url: https://www.agile-gap.com/p/pedram-keshavarzi + role: translator + contributions: ["2025.5"] + weight: 6 +``` + +Within a file a person appears once, identified by `githubUsername` when present, otherwise by `name`. + +### 3.3 Roles + +| File | Roles | Shown as | +|---|---|---| +| `.yml` | `creator` | Authors | +| | `contributor`, `reviewer`, `involved` | Contributors (which roles appear is decision D3) | +| `..yml` | `translator` | Translators | +| | `reviewer` | Translation reviewers (decision D4) | + +Existing values are normalised on adoption: `Translator` → `translator`, `Reviewer` and `translation reviewer` → `reviewer`. Other values are refused by validation. + +### 3.4 Resolution for a page or PDF + +For guide `g`, edition `e`, language `l`: + +- Authors: records in `g.yml` with `role: creator` and `e` in `contributions`. +- Contributors: other records in `g.yml` for `e`, filtered by the roles selected. +- Translators: records in `g.l.yml` for `e`. Absent for the source language. +- Names: `localizedNames[l]` when present, otherwise `name`. +- Order: `weight`, then `name`. + +### 3.5 Retired front matter + +`translators:` is removed from all translation files and no longer read. `author:` is retired as well (decision D2). No platform layout reads guide `author` (the JSON-LD `person.html` reads `author` only on creator profile pages); the KanbanGuides home page (site-owned) reads it and is updated during adoption. + +### 3.6 Platform changes + +- Hugo module: `functions/get-translators.html` implements 3.4 for translation teams (data key matched case-insensitively, so `es-ES` files serve `es-es` pages); `guide-translators.html`, `community-translations2.html` (including PDF-only translations) and `get-participants.html` use it. `functions/localize-contributor.html` applies `localizedNames`, and `get-contributors.html` returns localised records. Language files join the existing all-guides list. +- `baseof.html` keeps the deprecated `.Language.LanguageDirection`: the platform supports Hugo 0.146+, and `.Language.Direction` only exists from 0.158. +- Core ContributorManagement: `New-GuideContributions` and `Update-GuideContributions` accept an optional language and address `..yml`. Existing `.yaml` files remain addressable until renamed. +- Skill `guide.contributions`: documents language files and the role set. + +## 4. PDF format + +### 4.1 Location + +Site-owned PDF configuration lives under `/pdf/` (for current consumers, `site/pdf/`). It is outside `content/` so Hugo does not publish templates as page resources, and it follows `site.source` so no additional setting is needed. + +### 4.2 Layering + +Most specific wins: + +| Level | Folder | +|---|---| +| Platform default | `system/OpenGuidePlatform.PowerShell.Core/PdfPublishing/templates/` | +| Site | `site/pdf/` | +| Guide | `site/pdf//` | +| Edition | `site/pdf///` | + +At every level a file may carry a language suffix (`cover.fa.tex`, `pdf.ja.yaml`). For a given level the language-suffixed file is applied after the unsuffixed one. + +### 4.3 Files + +| File | Part | Combination | +|---|---|---| +| `pdf.yaml` | Settings (4.4) | Merged key by key; lists replace | +| `cover.tex` | Cover page | Most specific file replaces | +| `page-header.tex`, `page-footer.tex` | Running header and footer | Most specific file replaces | +| `style.tex` | LaTeX preamble: colours, headings, spacing | Most specific file replaces | +| `licence.tex` | Licence and attribution page | Most specific file replaces | +| `back.tex` | Back page or colophon | Most specific file replaces | +| `filters/*.lua` | Pandoc Lua filters | Accumulate by filename; a same-named file at a more specific level replaces | +| `images/*` | Assets referenced by templates | Resource path, most specific first | + +Two fixed platform files are not overridable: `body-start.tex`, added after the front parts so the body starts on page 1, and `rtl.tex`, added for right-to-left languages to define `\LR`/`\RL`, which Pandoc's babel setup for XeTeX omits. A filter's optional `filters/.tex` is raw LaTeX included in the preamble with it. + +The name `header.tex` is not used because Pandoc's `--include-in-header` means the preamble, not the running header. + +### 4.4 `pdf.yaml` keys + +```yaml +mainfont: Times New Roman +sansfont: Arial +monofont: Courier New +CJKmainfont: "" # required for Japanese/Chinese/Korean line breaking; also CJKsansfont, CJKmonofont +papersize: a4 # a4 | letter +geometry: margin=2.2cm +fontsize: 11pt +toc: false +tocDepth: 2 +watermark: "" # e.g. set for preview translations +licence: "" # licence page text; no licence page when empty +parts: [cover, licence, body, back] +cover: + tagline: "" # e.g. "Based on the Scrum Guide 2020" + contributorRoles: [contributor, reviewer] + translatorRoles: [translator] +downloads: # edition level only + - path: pdf/.pdf + handling: supplied # supplied | protected | generated; default supplied + papersize: letter # per-download overrides: papersize, geometry, fontsize, watermark +``` + +Unknown keys are refused. `downloads` replaces the policy inventory removed during adoption and is the only place a PDF becomes eligible for generation. + +When `cover.tagline` is empty and the edition's front matter has `forked_from`, the default cover shows "Based on" followed by the source guide's title and edition. + +### 4.5 What is no longer read from front matter + +`mainfont`, `sansfont`, `monofont` and `dir` are removed from guide front matter and not read. There is no front-matter override; a single translation that needs different settings gets `site/pdf///pdf..yaml`. + +Text direction comes from Hugo's `languages..direction` (Hugo 0.158+; the older `languageDirection` key is deprecated but still honoured). Pandoc language metadata continues to come from the filename; `lang` stays out of front matter. + +### 4.6 Cover data + +Core writes a Pandoc metadata file per PDF and passes it with `--metadata-file`: + +| Variable | Source | +|---|---| +| `title`, `short_title`, `date` | Translation front matter | +| `edition` | Edition folder name | +| `guide` | Guide identifier | +| `authors`, `contributors`, `translators` | Section 3.4; each item has `name`, `role` and, when known, `url` | +| `tagline` / `based_on` | `cover.tagline`, or `forked_from` resolved to title and edition | +| `labels.*` | Effective i18n catalogue for the language (4.7) | +| `logo` | `content//images/-logo.png` when present | +| `licence`, `watermark` | `pdf.yaml` | +| `dir` | Set to `rtl` only for right-to-left languages (Pandoc loads bidi support whenever `dir` is set) | + +In right-to-left documents, text values without any right-to-left characters (Latin names, untranslated labels) are wrapped in left-to-right spans so their word order and punctuation survive. Pandoc's own title block is suppressed (`title` and `author` are cleared on the command line); the cover replaces it, and `title-meta`/`author-meta` keep the PDF properties. + +Templates use Pandoc template syntax, for example `$for(translators)$$translators.name$$sep$ · $endfor$`. + +### 4.7 Labels + +Labels come from the site i18n catalogue: platform English defaults, then the site catalogue for the source language, then the PDF language. Ids: `pdf_authors_label`, `pdf_contributors_label`, `pdf_translators_label`, `pdf_edition_label`, `pdf_based_on_label` and `pdf_callout_note`, `_tip`, `_important`, `_warning`, `_caution` (callout default titles). Prepare warns when a language with a generated PDF lacks any of them. + +### 4.8 Platform defaults + +The platform ships a complete default set: `pdf.yaml`, `labels.yaml`, `cover.tex`, `page-header.tex`, `page-footer.tex`, `style.tex`, `licence.tex`, `back.tex`, `filters/callouts.lua` with `filters/callouts.tex`, and `filters/hugo-images.lua`. The callouts filter and image handling come from ScrumGuide-ExpansionPack `scripts/`; review fixed three defects there: body text after the marker line became the title, titles were escaped incorrectly, and emoji icons are absent from the configured fonts (removed). Callout titles are translatable. Defaults contain no guide- or site-specific text. The old `templates/cover-page.tex` is removed. + +### 4.9 Core changes + +- `Get-GuidePdfPlan` resolves the layered files and settings itself. The per-invocation `HeaderPaths`, `LuaFilterPaths` and `FontOverrides` parameters are removed so the approved recipe is always the committed configuration (decision D6). +- The plan lists every resolved file with the level it came from, the merged settings and the generated metadata. All of these, the contributor data files and the i18n catalogue entries used are fingerprinted. +- Template parts are rendered first, each with its own Pandoc call (`--template --metadata-file`), because Pandoc does not expand variables in included files. The main call then uses `--include-in-header` (rtl support, style, running header/footer, filter preambles), `--include-before-body` (cover, licence, body start) and `--include-after-body` (back page), one `--lua-filter` per resolved filter, `--metadata-file`, `-V` for settings and `--resource-path` for the edition folder and `images/` folders. +- Generation is refused when a required font is not installed, as today. + +### 4.10 File naming for new PDFs + +New generated downloads use `/pdf/...pdf`. Existing published filenames are preserved and declared explicitly in `downloads`. + +## 5. Validation in Prepare + +Prepare reports, and the build fails on: + +- `translators`, `author`, `mainfont`, `sansfont`, `monofont` or `dir` in guide front matter; +- a contributor record without `name`, `role` or `contributions`, with an unknown role, or duplicated within a file; +- an edition in `contributions` that has no edition folder; +- a data file for a guide or language that does not exist; +- unknown `pdf.yaml` keys or a `downloads` path outside the edition; +- two data files for the same key differing only by `.yml`/`.yaml`. + +Prepare warns on a web translation with no translator record and an edition with no creator (only when the site has a `data/contributions` folder), and on a missing PDF label translation for a language with a generated PDF. Findings use the existing assessment scopes: contributor files `guide`, missing creators `edition`, missing translators `translation`, PDF settings `download`, labels `wrapper`. + +## 6. Rollout + +1. Agree this document and the decisions in section 8. +2. Implement sections 3–5 in the platform with tests; ship one preview release. +3. For each consumer, on a review branch: `./build.ps1 Update -ring preview`, apply section 7, run the full build, compare `Get-GuidePdfPlan` output before and after for every existing download, and review the diff. +4. Generate only downloads declared `generated`; render representative pages including RTL and CJK and record visual approval. +5. KanbanGuides first, then ScrumGuide-ExpansionPack, then remaining consumers. + +## 7. Consumer adoption + +### 7.1 Common steps + +- Move `translators:` into `..yml`; move names recorded only in body text into records; keep the body acknowledgement sections. +- Add `localizedNames` where front matter `author` used a localised spelling; then remove `author:`. +- Normalise roles (3.3); rename `.yaml` data files to `.yml`. +- Create `site/pdf/pdf.yaml` and language files for fonts; remove `mainfont`, `sansfont`, `monofont` and `dir` from front matter. +- Declare `downloads` for every existing PDF (default `supplied`). +- Remove retired PDF scripts and templates. + +### 7.2 KanbanGuides + +- Minimal PDF configuration: `site/pdf/pdf.yaml` (Times New Roman, Arial, Courier New), `pdf.fa.yaml` (HMXRoya), `pdf.ja.yaml` (Noto Serif JP, Noto Sans JP). Removes 3–4 lines from each of 32 translation files. +- Translators: structured for `ja` and `fa` only. Body text only for `es-ES` and `pl` (2025 editions) and `fr` (open-guide-to-kanban 2025.7). None for `es-419` or any 2020 translation. +- `site/hugo.yaml` already uses the current `direction: rtl` key for `fa`; built Persian pages carry `dir="rtl"`. +- `site/layouts/index.html` shows `.Params.author` from the latest edition; switch it to `functions/get-contributors.html` creators before removing `author`. +- Remove `.agents/skills/guide.genpdfs/cover-page.tex` once the platform default replaces it. +- `min` is a test language; confirm it stays excluded from production. + +### 7.3 ScrumGuide-ExpansionPack + +- Retire `scripts/Create-GuidePDFs.ps1`, `GuidePdfLanguage.ps1` and its test, `callouts*.lua`, `callouts-header.tex` and `cover-page.tex` after the callouts recipe is in the platform defaults. +- `site/hugo.yaml` uses the deprecated `languageDirection` key for `fa` and `tlh`; rename to `direction`. +- `pdf.ja.yaml` must set CJK fonts; current Japanese PDFs would need them for any regeneration. +- `cover.tagline: Based on the Scrum Guide 2020` at site level replaces fixed cover text. +- Three filename conventions exist: `scrum-guide-expansion-pack..pdf` (2025.6, does not match guide identifier `scrum-guide-expanded`, plus an `en-us` variant), `...pdf` (2026.1). All preserved via `downloads`. +- `strategy-as-an-empirical-capability/2026.1/pdf/strategy.2026.1.en.pdf` appears to be a stray duplicate; confirm before declaring it. +- Translators: structured for 2025.6 `es`, `fa`, `ja`, `ro`; body only for `pl`; none for `it` (six guides), `nl`, `pt`, `de`, `tlh`. `es` lists Marc Lluva twice. Roles include `contributor` and `translation reviewer`. Japanese translator names exist only in Japanese script. +- Authors: front matter and data disagree for `product-thinking` (three authors vs two creators and one contributor), `holistic-testing` (extra contributor) and `scrum-on-one-page` (no front-matter author). Author order differs between front matter and data; weights must reproduce the intended order. +- `planguage` has no contributions file. +- Three data files use `.yaml`. +- 2026.1 translations of `scrum-guide-expanded` other than `it` are empty and cannot produce a PDF. +- `tlh` is a test language with a published PDF; confirm production exclusion. +- The guide identifier `emergent-strategy-and-depoyment` is misspelt; it is part of live URLs and is not changed here. + +## 8. Decisions + +Recommendations were accepted when implementation was requested on 2026-09-23. + +| # | Decision | Implemented | +|---|---|---| +| D1 | PDF configuration location | `/pdf/` | +| D2 | Authors source | Data file `role: creator`; front-matter `author` retired | +| D3 | Roles shown as contributors on the cover | `contributor`, `reviewer`; `involved` excluded (configurable with `cover.contributorRoles`) | +| D4 | Translation reviewers on the cover | Not by default; `cover.translatorRoles: [translator, reviewer]` adds them to the translators list (see section 9) | +| D5 | Localised names | `localizedNames` per record, in whichever file holds the record | +| D6 | Keep per-invocation PDF overrides | No; committed configuration only | +| D7 | Paper-size variants | Per-download override in `downloads` | +| D8 | New PDF filename pattern | `...pdf` | +| D9 | Default part order | cover, licence, body, back | +| D10 | Licence page source | Platform default text parameterised by a `licence` key in `pdf.yaml`; body licence paragraphs unchanged | + +## 9. Implementation notes + +Differences from the original draft, found while implementing and checking real output (English, Persian and Japanese PDFs generated with Pandoc 3.10 and MiKTeX XeLaTeX and inspected page by page): + +- Added `CJKmainfont`, `CJKsansfont` and `CJKmonofont`: without `CJKmainfont` Pandoc does not load xeCJK and Japanese lines do not break. +- Added the `licence` key (D10) and per-download `geometry`, `fontsize` and `watermark` overrides. +- The licence text appears on the licence page only, not on the cover and back page as first drafted. +- Removed the unused `pdf_page_label`; added translatable callout titles. +- Added the fixed `body-start.tex` and `rtl.tex` includes (section 4.3) and left-to-right wrapping of Latin text in right-to-left covers and headers; the running header mirrors for right-to-left documents. +- D4: translation reviewers are not a separate cover group. They can be listed with translators through `cover.translatorRoles`; the website still shows the whole translation team. +- Contributor warnings apply only to sites that keep `data/contributions`, so sites without contributor data are not asked for it. +- Core exposes `Get-GuideCredits` (resolved credits) and `Get-GuidePdfDeclaredDownloads` (used by discovery). Discovery records `wrapper.languageDirections`, added to the site-policy schema. diff --git a/examples/reference-guide-site/content/Guide1/2020.12/index.md b/examples/reference-guide-site/content/Guide1/2020.12/index.md index 52867902..e39bf94c 100644 --- a/examples/reference-guide-site/content/Guide1/2020.12/index.md +++ b/examples/reference-guide-site/content/Guide1/2020.12/index.md @@ -4,12 +4,7 @@ description: Comprehensive Guide 1 for best practices date: 2020-12-01T09:00:00Z keywords: - Guide 1 -author: - - Jane Smith type: guide -mainfont: "Times New Roman" -sansfont: "Arial" -monofont: "Courier New" sitemap: priority: 0.6 --- diff --git a/examples/reference-guide-site/content/Guide1/2020.12/index.min.md b/examples/reference-guide-site/content/Guide1/2020.12/index.min.md index e42e04ca..6b0634fd 100644 --- a/examples/reference-guide-site/content/Guide1/2020.12/index.min.md +++ b/examples/reference-guide-site/content/Guide1/2020.12/index.min.md @@ -8,14 +8,8 @@ date: 2020-12-01T09:00:00Z keywords: - Guide 1 -author: - - Jane Banana Smith - - Anonymous Banana Author type: guide -mainfont: "Times New Banana" -sansfont: "Ari-Banana" -monofont: "Courier Peel" translationDraft: true sitemap: priority: 0.6 diff --git a/examples/reference-guide-site/content/Guide1/2020.7/index.md b/examples/reference-guide-site/content/Guide1/2020.7/index.md index 10051be6..4ddd4d66 100644 --- a/examples/reference-guide-site/content/Guide1/2020.7/index.md +++ b/examples/reference-guide-site/content/Guide1/2020.7/index.md @@ -4,13 +4,7 @@ description: This document aims to be a unifying reference for the community by date: 2020-07-01T09:00:00Z keywords: - Guide 1 -author: - - Jane Smith - - Anonymous Author type: guide -mainfont: "Times New Roman" -sansfont: "Arial" -monofont: "Courier New" sitemap: priority: 0.6 aliases: diff --git a/examples/reference-guide-site/content/Guide1/2020.7/index.min.md b/examples/reference-guide-site/content/Guide1/2020.7/index.min.md index 1d5bfcab..7ed75fd6 100644 --- a/examples/reference-guide-site/content/Guide1/2020.7/index.min.md +++ b/examples/reference-guide-site/content/Guide1/2020.7/index.min.md @@ -8,14 +8,8 @@ date: 2020-07-01T09:00:00Z keywords: - Guide 1 -author: - - Jane Banana Smith - - Anonymous Banana Author type: guide -mainfont: "Times New Banana" -sansfont: "Ari-Banana" -monofont: "Courier Peel" sitemap: priority: 0.6 diff --git a/examples/reference-guide-site/content/Guide1/2025.5/index.md b/examples/reference-guide-site/content/Guide1/2025.5/index.md index 7ace038c..dda0bbb8 100644 --- a/examples/reference-guide-site/content/Guide1/2025.5/index.md +++ b/examples/reference-guide-site/content/Guide1/2025.5/index.md @@ -6,13 +6,7 @@ version: 2025.5 keywords: - Guide 1 - Best Practices -author: - - Jane Smith - - Anonymous Author type: guide -mainfont: "Times New Roman" -sansfont: "Arial" -monofont: "Courier New" sitemap: priority: 0.6 guide_whatis: | diff --git a/examples/reference-guide-site/content/Guide1/2025.5/index.min.md b/examples/reference-guide-site/content/Guide1/2025.5/index.min.md index 36d4f3b5..ac9daf1f 100644 --- a/examples/reference-guide-site/content/Guide1/2025.5/index.min.md +++ b/examples/reference-guide-site/content/Guide1/2025.5/index.min.md @@ -8,14 +8,8 @@ version: 2025.5 keywords: - Guide 1 -author: - - Jane Banana Smith - - Anonymous Banana Author type: guide -mainfont: "Times New Banana" -sansfont: "Ari-Banana" -monofont: "Courier Peel" sitemap: priority: 0.6 diff --git a/examples/reference-guide-site/content/Guide2/2025.7/index.md b/examples/reference-guide-site/content/Guide2/2025.7/index.md index 8070cf3f..eab168e1 100644 --- a/examples/reference-guide-site/content/Guide2/2025.7/index.md +++ b/examples/reference-guide-site/content/Guide2/2025.7/index.md @@ -4,14 +4,9 @@ short_title: Guide 2 description: Guide 2 is a free, community-driven reference for applying advanced practices in knowledge work. It defines the core practices and metrics necessary to improve flow, optimize value delivery, and enhance team sustainability. This guide supports scalable implementations across diverse industries and complements other agile, lean, and flow-based approaches. keywords: - Guide 2 -author: - - Jane Smith date: 2025-07-02T09:00:00Z type: guide forked_from: guide1/2025.5 -mainfont: "Times New Roman" -sansfont: "Arial" -monofont: "Courier New" sitemap: priority: 1.0 aliases: diff --git a/examples/reference-guide-site/content/Guide2/2025.7/index.min.md b/examples/reference-guide-site/content/Guide2/2025.7/index.min.md index 3dd68028..9b02815c 100644 --- a/examples/reference-guide-site/content/Guide2/2025.7/index.min.md +++ b/examples/reference-guide-site/content/Guide2/2025.7/index.min.md @@ -7,14 +7,9 @@ description: > Works with Agiley, Lean-y, and flowy-wowy ways. All da bananas welcome! 🍌 keywords: - Guide 2 -author: - - Johnny Banana date: 2025-07-02T09:00:00Z type: guide forked_from: guide-1/2025.5 -mainfont: "Times New Banana" -sansfont: "Ari-Banana" -monofont: "Courier Peel" sitemap: priority: 1.0 aliases: diff --git a/examples/reference-guide-site/data/contributions/guide1.min.yml b/examples/reference-guide-site/data/contributions/guide1.min.yml new file mode 100644 index 00000000..52728884 --- /dev/null +++ b/examples/reference-guide-site/data/contributions/guide1.min.yml @@ -0,0 +1,8 @@ +# Minionese translation team for Guide 1. Roles: translator, reviewer. +- name: Banana Translator + role: translator + contributions: + - "2020.7" + - "2020.12" + - "2025.5" + weight: 1 diff --git a/examples/reference-guide-site/data/contributions/guide1.yml b/examples/reference-guide-site/data/contributions/guide1.yml index 70220059..89d2cccd 100644 --- a/examples/reference-guide-site/data/contributions/guide1.yml +++ b/examples/reference-guide-site/data/contributions/guide1.yml @@ -1,20 +1,25 @@ -# Contributions Data -# This file contains information about all contributors to the Guide 1 - -# All contributors in a flat list -- name: Martin Hinshelwood - gravatarHash: a9a55b4384e0420e376f441384d0c13fdadb9d39e72892ac60c3e89c3079d10d - githubUsername: mrhinsh - url: https://nkdagility.com/company/people/martin-hinshelwood/ +# Contributors to Guide 1. Authors are the records with role: creator. +# Roles: creator, contributor, reviewer, involved. Translation teams live in guide1..yml. +- name: Jane Smith + role: creator contributions: - "2020.7" - "2020.12" - "2025.5" - - "2025.7" - role: contributor - weight: 100 + weight: 1 founder: true -- name: Martin Hinshelwood 2 + localizedNames: + min: Jane Banana Smith +- name: Anonymous Author + role: creator + contributions: + - "2020.7" + - "2025.5" + weight: 2 + founder: true + localizedNames: + min: Anonymous Banana Author +- name: Martin Hinshelwood gravatarHash: a9a55b4384e0420e376f441384d0c13fdadb9d39e72892ac60c3e89c3079d10d githubUsername: mrhinsh url: https://nkdagility.com/company/people/martin-hinshelwood/ @@ -22,7 +27,6 @@ - "2020.7" - "2020.12" - "2025.5" - - "2025.7" role: contributor weight: 100 - founder: true \ No newline at end of file + founder: true diff --git a/examples/reference-guide-site/data/contributions/guide2.min.yml b/examples/reference-guide-site/data/contributions/guide2.min.yml new file mode 100644 index 00000000..60cacbb7 --- /dev/null +++ b/examples/reference-guide-site/data/contributions/guide2.min.yml @@ -0,0 +1,6 @@ +# Minionese translation team for Guide 2. Roles: translator, reviewer. +- name: Banana Translator + role: translator + contributions: + - "2025.7" + weight: 1 diff --git a/examples/reference-guide-site/data/contributions/guide2.yml b/examples/reference-guide-site/data/contributions/guide2.yml index 63c3480a..f1bbcd77 100644 --- a/examples/reference-guide-site/data/contributions/guide2.yml +++ b/examples/reference-guide-site/data/contributions/guide2.yml @@ -1,27 +1,18 @@ -# Contributors to the Guide 2 -# This file contains information about contributors to the original Guide 2 - -# Add contributors specific to the Guide 2 here -# Example structure: -# - name: Contributor Name -# githubUsername: username -# url: https://www.linkedin.com/in/profile/ -# contributions: -# - 2020.07 -# - 2020.12 -# - 2025.5 -# role: contributor -# weight: 100 -# Contributors to the Guide 2 -# This file contains information about contributors to the original Guide 2 +# Contributors to Guide 2. Authors are the records with role: creator. +# Roles: creator, contributor, reviewer, involved. Translation teams live in guide2..yml. +- name: Jane Smith + role: creator + contributions: + - "2025.7" + weight: 1 + founder: true + localizedNames: + min: Johnny Banana - name: Martin Hinshelwood gravatarHash: a9a55b4384e0420e376f441384d0c13fdadb9d39e72892ac60c3e89c3079d10d githubUsername: mrhinsh url: https://nkdagility.com/company/people/martin-hinshelwood/ contributions: - - "2020.7" - - "2020.12" - - "2025.5" - "2025.7" role: contributor weight: 100 diff --git a/examples/reference-guide-site/i18n/en.yaml b/examples/reference-guide-site/i18n/en.yaml index 7b63b805..e539729a 100644 --- a/examples/reference-guide-site/i18n/en.yaml +++ b/examples/reference-guide-site/i18n/en.yaml @@ -202,6 +202,9 @@ - id: contributors_label translation: "Contributors" +- id: translators_label + translation: "Translators" + - id: contributors_description translation: "The contributors listed below are a collection of all contributors across all guides and versions." diff --git a/examples/reference-guide-site/i18n/min.yaml b/examples/reference-guide-site/i18n/min.yaml index 0e57d8b6..f76262f4 100644 --- a/examples/reference-guide-site/i18n/min.yaml +++ b/examples/reference-guide-site/i18n/min.yaml @@ -491,6 +491,9 @@ - id: contributors_label translation: "Helper Minions" + +- id: translators_label + translation: "Translatey Minions" - id: download_table_contributed_by translation: "Made by da Helpers" diff --git a/examples/reference-guide-site/pdf/README.md b/examples/reference-guide-site/pdf/README.md new file mode 100644 index 00000000..956833ed --- /dev/null +++ b/examples/reference-guide-site/pdf/README.md @@ -0,0 +1,14 @@ +# PDF configuration + +Generated guide PDFs are configured here, outside `content/` so Hugo does not publish these files. Settings are layered; the most specific wins: + +| Level | Folder | +|---|---| +| Platform default | OpenGuidePlatform Core `PdfPublishing/templates/` | +| Site | `pdf/` | +| Guide | `pdf//` | +| Edition | `pdf///` | + +Each folder may contain `pdf.yaml` (settings, merged key by key), `cover.tex`, `licence.tex`, `back.tex`, `page-header.tex`, `page-footer.tex` and `style.tex` (Pandoc templates, most specific file wins), `filters/*.lua` with an optional companion `filters/.tex` preamble, and `images/`. Add `.` before the extension (`pdf.fa.yaml`, `cover.ja.tex`) for one language. + +Only downloads declared in an edition's `pdf.yaml` with `handling: generated` are ever generated; every other PDF is preserved as supplied. Cover credits come from `data/contributions/.yml` (role `creator` = authors) and `data/contributions/..yml` (translators). Do not put fonts, `dir`, `author` or `translators` in guide front matter. diff --git a/examples/reference-guide-site/pdf/pdf.ja.yaml b/examples/reference-guide-site/pdf/pdf.ja.yaml new file mode 100644 index 00000000..7d2cd4b5 --- /dev/null +++ b/examples/reference-guide-site/pdf/pdf.ja.yaml @@ -0,0 +1,5 @@ +# Japanese needs CJK fonts; CJKmainfont also enables Japanese line breaking. +mainfont: Noto Serif JP +sansfont: Noto Sans JP +monofont: Noto Sans JP +CJKmainfont: Noto Serif JP diff --git a/examples/reference-guide-site/pdf/pdf.yaml b/examples/reference-guide-site/pdf/pdf.yaml new file mode 100644 index 00000000..0809a131 --- /dev/null +++ b/examples/reference-guide-site/pdf/pdf.yaml @@ -0,0 +1,5 @@ +# Site PDF settings. Override per guide (pdf//pdf.yaml), per edition +# (pdf///pdf.yaml) and per language (pdf..yaml). +mainfont: Times New Roman +sansfont: Arial +monofont: Courier New diff --git a/system/OpenGuidePlatform.Agents.Integration/instructions/guide-site.md b/system/OpenGuidePlatform.Agents.Integration/instructions/guide-site.md index cb150baf..2ac84695 100644 --- a/system/OpenGuidePlatform.Agents.Integration/instructions/guide-site.md +++ b/system/OpenGuidePlatform.Agents.Integration/instructions/guide-site.md @@ -6,6 +6,7 @@ Use ./build.ps1 -Stage Serve -Target local for local development. Run a full bui Preserve the bespoke wrapper, supplied/protected PDFs and deliberate multilingual guide structure. Do not put lang in Hugo front matter; PDF generation passes Pandoc language metadata separately. +Guide credits live in data/contributions: .yml for creators (the authors) and contributors, ..yml for each translation team. PDF settings, templates and filters live in /pdf. Never put author, translators, mainfont, sansfont, monofont or dir in guide front matter. Never enable permanently excluded languages in production. Do not modify generated platform adapters, skills or the installation record by hand. Workflow callers are site-owned. Preserve site triggers, inputs and secrets; use the coordinated update to change OGP release references and regenerate the Actions lockfile. diff --git a/system/OpenGuidePlatform.Agents.Integration/skills/guide.contributions/SKILL.md b/system/OpenGuidePlatform.Agents.Integration/skills/guide.contributions/SKILL.md index 727a30ce..f26bbdd7 100644 --- a/system/OpenGuidePlatform.Agents.Integration/skills/guide.contributions/SKILL.md +++ b/system/OpenGuidePlatform.Agents.Integration/skills/guide.contributions/SKILL.md @@ -1,12 +1,14 @@ --- name: guide.contributions -description: "Create guide contributor YAML or apply a reviewed update to one existing contributor." +description: "Create guide or translation-team contributor YAML, apply a reviewed update to one existing contributor, or resolve an edition's credits." --- -Read [Core usage](../USAGE.md), load the consumer policy, and select the declared guide. Use `New-GuideContributions -WorkspaceRoot $WorkspaceRoot -Policy $policy -GuideId $GuideId -Contributors $Contributors` for a new file. Existing .yml and .yaml filenames are preserved; two matching files are ambiguous and require reconciliation. +Read [Core usage](../USAGE.md), load the consumer policy, and select the declared guide. Contributor data is the only source of guide credits: `data/contributions/.yml` holds the guide's own people (roles `creator`, `contributor`, `reviewer`, `involved`; creators are the authors) and `data/contributions/..yml` holds one translation team (roles `translator`, `reviewer`). Every record needs `name`, `role` and `contributions` (the edition identifiers it applies to); `weight` orders records and `localizedNames` maps a language code to the name shown in that language. Do not put `author` or `translators` in guide front matter; Prepare blocks them. -Records need a name and non-empty role. Preserve site-specific roles such as reviewer, supplied URLs, edition references and other contributor metadata; do not invent affiliations or contributions. Use `Get-GuideGravatar` only for an address the user supplied for that purpose. +Use `New-GuideContributions -WorkspaceRoot $WorkspaceRoot -Policy $policy -GuideId $GuideId -Contributors $Contributors [-Language $Language]` for a new file; `-Language` creates the translation-team file. Existing .yml and .yaml filenames are preserved; two matching files are ambiguous and require reconciliation. New files use .yml. -For an authorized update, read the original bytes and SHA-256 and prepare CandidateYaml with the minimal requested diff. Preserve comments, formatting, contributor order and every unselected record. Apply with `Update-GuideContributions -WorkspaceRoot $WorkspaceRoot -Policy $policy -GuideId $GuideId -ContributorName $Name -ExpectedSha256 $OriginalHash -CandidateYaml $CandidateYaml`. The command validates semantic scope and writes the candidate text exactly; it does not reconstruct formatting for you. Review the diff for comment/format preservation. +Preserve supplied URLs, edition references and other contributor metadata; do not invent affiliations, contributions or name spellings. Use `Get-GuideGravatar` only for an address the user supplied for that purpose. When moving names out of guide body text into records, copy them exactly and keep the body acknowledgement. -The update must select exactly one existing name; it cannot rename, add, remove or reorder contributors. A stale hash means re-read and review the changed file, never refresh the hash blindly to bypass the refusal. The cooperative lock cannot prevent edits by programs that ignore it. Use WhatIf to inspect the operation and run the consumer build after an authorized change. Report the changed path and verification result. \ No newline at end of file +For an authorized update, read the original bytes and SHA-256 and prepare CandidateYaml with the minimal requested diff. Preserve comments, formatting, contributor order and every unselected record. Apply with `Update-GuideContributions -WorkspaceRoot $WorkspaceRoot -Policy $policy -GuideId $GuideId -ContributorName $Name -ExpectedSha256 $OriginalHash -CandidateYaml $CandidateYaml [-Language $Language]`. The command validates semantic scope and writes the candidate text exactly; it does not reconstruct formatting for you. Review the diff for comment/format preservation. + +The update must select exactly one existing name; it cannot rename, add, remove or reorder contributors. A stale hash means re-read and review the changed file, never refresh the hash blindly to bypass the refusal. The cooperative lock cannot prevent edits by programs that ignore it. Use WhatIf to inspect the operation and run the consumer build after an authorized change; Prepare reports invalid roles, unknown editions, duplicates and missing creators or translators. `Get-GuideCredits` shows the authors, contributors and translators a PDF cover will use. Report the changed path and verification result. diff --git a/system/OpenGuidePlatform.Agents.Integration/skills/guide.genpdfs/SKILL.md b/system/OpenGuidePlatform.Agents.Integration/skills/guide.genpdfs/SKILL.md index 7cca5224..3c03ecf1 100644 --- a/system/OpenGuidePlatform.Agents.Integration/skills/guide.genpdfs/SKILL.md +++ b/system/OpenGuidePlatform.Agents.Integration/skills/guide.genpdfs/SKILL.md @@ -1,12 +1,14 @@ --- name: guide.genpdfs -description: "Plan, generate or replace a declared generated guide PDF using declared filenames, explicit language metadata and installed tools." +description: "Plan, generate or replace a declared generated guide PDF from the site's committed PDF configuration, contributor data and installed tools." --- -Read [Core usage](../USAGE.md). Select guide, edition, language and the exact download path declared in policy. Only generated downloads are eligible; supplied/protected resources are preserved. +Read [Core usage](../USAGE.md). Select guide, edition, language and the exact download path. Only downloads declared `handling: generated` in `/pdf///pdf.yaml` are eligible; every other PDF is supplied or protected and is preserved. -Use `Get-GuidePdfPlan` to inspect source, destination, arguments, fonts and fingerprints. Use `Get-GuidePdfToolchain` for diagnostics, then `New-GuidePdf` with the same selections. HeaderPaths, LuaFilterPaths and FontOverrides are explicit choices; preserve the consumer's approved PDF recipe. Do not silently substitute fonts or install packages. The command passes the filename/default language to Pandoc metadata and never needs lang in Hugo front matter. +The recipe is committed configuration, never per-run choices. Settings, templates and filters are layered: platform defaults, then `/pdf/`, `/pdf//` and `/pdf///`, with `.` variants (`pdf.fa.yaml`, `cover.ja.tex`) at any level. `pdf.yaml` keys merge; `cover.tex`, `licence.tex`, `back.tex`, `page-header.tex`, `page-footer.tex` and `style.tex` are Pandoc templates replaced by the most specific file; `filters/.lua` replaces a same-named filter and may have a companion `filters/.tex` preamble. Cover credits come from contributor data (see guide.contributions) and labels from the site i18n `pdf_*` ids. Fonts and direction never come from front matter; Japanese needs `CJKmainfont`. + +Use `Get-GuidePdfPlan` to inspect source, destination, resolved recipe files, settings, cover metadata, arguments, fonts and fingerprints. Use `Get-GuidePdfToolchain` for diagnostics, then `New-GuidePdf` with the same selections. Change the look by editing the site's PDF configuration in a reviewed change, not by passing options. Do not silently substitute fonts or install packages. The command passes the filename/default language to Pandoc metadata and never needs lang in Hugo front matter. For an authorized replacement, pass the reviewed existing PDF SHA-256 as ExpectedOutputSha256 to New-GuidePdf. A stale hash requires fresh review, not deleting the old file or blindly refreshing the hash. Failed generation preserves the previous PDF. Test-GuidePdfCache accepts the current plan, prior receipt and observed toolchain. Reuse requires an EnvironmentSha256 covering approved fonts, TeX packages and indirect resources; without that evidence it refuses reuse. Never invent this digest or use timestamps as proof of freshness. Cooperative locks do not prevent other editors ignoring them. -After generation, inspect the actual PDF and render representative pages, including RTL/CJK cases when applicable. A successful native command or PDF header is not visual approval. Record source/config/toolchain fingerprints and any font/tool warnings; keep published filenames unchanged. +After generation, inspect the actual PDF and render representative pages, including the cover and RTL/CJK cases when applicable. A successful native command or PDF header is not visual approval. Record source/config/toolchain fingerprints and any font/tool warnings; keep published filenames unchanged. diff --git a/system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/components/guide/guide-translators.html b/system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/components/guide/guide-translators.html index 6e49bd7b..4d0e89a8 100644 --- a/system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/components/guide/guide-translators.html +++ b/system/OpenGuidePlatform.Hugo.Guides/layouts/_partials/components/guide/guide-translators.html @@ -1,4 +1,8 @@ -{{ $translators := .Params.translators }} +{{- $version := "" -}} +{{- range split .Path "/" -}} + {{- if and (ne . "") (findRE `^\d{4}\.\d+$` .) -}}{{- $version = . -}}{{- end -}} +{{- end -}} +{{ $translators := partial "functions/get-translators.html" (dict "guide" .Section "version" $version "language" .Language.Lang) }} {{ if $translators }}