@openpresentation/opf 0.9.0 → 0.10.1
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.
- package/README.md +7 -1
- package/dist/{catalogs-BnnkUX9O.d.ts → catalogs-DoVmvDr7.d.ts} +6 -6
- package/dist/catalogs.d.ts +2 -2
- package/dist/catalogs.js +1 -1
- package/dist/{chunk-GQSK3T7X.js → chunk-D3GQIREP.js} +13 -4
- package/dist/chunk-EWJNRHXA.js +595 -0
- package/dist/{chunk-3GPZMY2W.js → chunk-FHGJX5QK.js} +24 -12
- package/dist/{chunk-JA5W5TVA.js → chunk-PQJRDNA6.js} +624 -73
- package/dist/{chunk-OZULJBSG.js → chunk-RS5GZ5RW.js} +14 -0
- package/dist/{chunk-TWMRZ43O.js → chunk-TU7I3KSB.js} +59 -21
- package/dist/{chunk-ZGV6I23P.js → chunk-ZIL7MGZU.js} +50 -5
- package/dist/composition.d.ts +257 -10
- package/dist/composition.js +1 -1
- package/dist/docs.js +58 -10
- package/dist/examples.js +2284 -1417
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7 -6
- package/dist/lint.d.ts +70 -0
- package/dist/lint.js +5 -0
- package/dist/pagination.d.ts +4 -0
- package/dist/pagination.js +5 -5
- package/dist/{schemas--QRVBhU1.d.ts → schemas-BYe5y8-i.d.ts} +1 -1
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/layouts/extract/canonical.json +45 -21
- package/dist/spec/catalogs/layouts/index.json +10 -0
- package/dist/spec/catalogs/layouts/number-1x.json +1 -1
- package/dist/spec/catalogs/layouts/number-2x.json +2 -2
- package/dist/spec/catalogs/layouts/number-3x.json +3 -3
- package/dist/spec/catalogs/layouts/number-4x.json +4 -4
- package/dist/spec/catalogs/layouts/number-5x.json +5 -5
- package/dist/spec/catalogs/layouts/number-6x.json +6 -6
- package/dist/spec/catalogs/layouts/quote-1x.json +13 -0
- package/dist/spec/catalogs/layouts/timeline-1x.json +13 -0
- package/dist/spec/schemas/layout.schema.json +12 -3
- package/dist/spec/schemas/narrative.schema.json +1 -1
- package/dist/spec-files.d.ts +1 -1
- package/dist/spec-files.js +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/validator.d.ts +2 -2
- package/dist/validator.js +4 -4
- package/package.json +11 -6
package/dist/docs.js
CHANGED
|
@@ -4,13 +4,13 @@ var docsData = Object.freeze([
|
|
|
4
4
|
"slug": "agent-skills",
|
|
5
5
|
"file": "docs/agent-skills.md",
|
|
6
6
|
"title": "AI agent skills for OPF",
|
|
7
|
-
"markdown": "# AI agent skills for OPF\n\nThe repository ships six reusable skills in `skills/`. Each folder has a `SKILL.md` entrypoint and optional references, assets, or scripts. `agents/openai.yaml` supplies Codex display metadata; the instructions themselves are Markdown and do not require a hosted service.\n\n| Skill | Use it for |\n| --- | --- |\n| [opf-author](../skills/opf-author/SKILL.md) | Turn briefs and source material into valid OPF content; includes a complete starter deck |\n| [opf-layout](../skills/opf-layout/SKILL.md) | Dynamic composition, nested groups, promoted regions, overflow repair, and pagination |\n| [opf-presets](../skills/opf-presets/SKILL.md) | Catalog discovery, design inheritance, gallery reuse, colors, themes, and fonts |\n| [opf-edit](../skills/opf-edit/SKILL.md) | Precise JSON Patch edits, undo, canvas/schema integration, and copy/import |\n| [opf-export](../skills/opf-export/SKILL.md) | Browser previews, SVG/PNG/PDF/PPTX, assets, fonts, and export verification |\n| [opf-inspect](../skills/opf-inspect/SKILL.md) | Exact schema fields, catalog IDs, validation errors, and reference warnings |\n\nLoad only the skills relevant to the request. They distinguish the portable format from current renderer/editor capabilities, and distinguish imported document instructions from the user's request. They do not authorize publishing, sending decks, or changing unrelated project configuration.\n\n## Use from a checkout\n\nAn agent can read the entrypoint directly, for example:\n\n> Use `skills/opf-author/SKILL.md` to create a decision brief in OPF, then validate it using `skills/opf-inspect/SKILL.md`.\n\nThe root `AGENTS.md` points repository agents to these entrypoints. Skills read the current project's schema and package exports instead of hardcoding a historical field count or assuming a public package has unreleased APIs.\n\n## Install in an agent environment\n\
|
|
7
|
+
"markdown": "# AI agent skills for OPF\n\nThe repository ships six reusable skills in `skills/`. Each folder has a `SKILL.md` entrypoint and optional references, assets, or scripts. `agents/openai.yaml` supplies Codex display metadata; the instructions themselves are Markdown and do not require a hosted service.\n\n| Skill | Use it for |\n| --- | --- |\n| [opf-author](../skills/opf-author/SKILL.md) | Turn briefs and source material into valid OPF content; includes a complete starter deck |\n| [opf-layout](../skills/opf-layout/SKILL.md) | Dynamic composition, nested groups, promoted regions, overflow repair, and pagination |\n| [opf-presets](../skills/opf-presets/SKILL.md) | Catalog discovery, design inheritance, gallery reuse, colors, themes, and fonts |\n| [opf-edit](../skills/opf-edit/SKILL.md) | Precise JSON Patch edits, undo, canvas/schema integration, and copy/import |\n| [opf-export](../skills/opf-export/SKILL.md) | Browser previews, SVG/PNG/PDF/PPTX, assets, fonts, and export verification |\n| [opf-inspect](../skills/opf-inspect/SKILL.md) | Exact schema fields, catalog IDs, validation errors, and reference warnings |\n\nLoad only the skills relevant to the request. They distinguish the portable format from current renderer/editor capabilities, and distinguish imported document instructions from the user's request. They do not authorize publishing, sending decks, or changing unrelated project configuration.\n\n## Use from a checkout\n\nAn agent can read the entrypoint directly, for example:\n\n> Use `skills/opf-author/SKILL.md` to create a decision brief in OPF, then validate it using `skills/opf-inspect/SKILL.md`.\n\nThe root `AGENTS.md` points repository agents to these entrypoints. Skills read the current project's schema and package exports instead of hardcoding a historical field count or assuming a public package has unreleased APIs.\n\n## Install in an agent environment\n\nThe installer introduced in CLI 0.5.0 bundles all six complete skill folders. Use Node 24 for this checkout and the next release. From your project directory:\n\n```sh\nnpx @openpresentation/cli@latest skills install\n```\n\nThe default installs copies into `.agents/skills` in the current project, suitable for agents including Codex. It does not change AGENTS.md or any agent configuration. No symlink privileges, paid service, API key or AI provider is required. npm downloads the CLI on first use; the installed CLI then installs its bundled skills without network access. Pin `@openpresentation/cli@0.5.0` for a repeatable version. This command requires the 0.5.0 release; when testing its release branch before publication, use `node packages/cli/dist/index.js skills install` after building.\n\n| Target | Project directory | Personal directory with `--global` |\n| --- | --- | --- |\n| Default / `--agent universal` | `.agents/skills` | `~/.agents/skills` |\n| `--agent codex` | `.agents/skills` | `~/.codex/skills` |\n| `--agent claude-code` | `.claude/skills` | `~/.claude/skills` |\n| `--agent cursor` | `.cursor/skills` | `~/.cursor/skills` |\n\nFor example, `npx @openpresentation/cli@latest skills install --agent codex --global` installs personal Codex skills. For another compatible agent use `--directory <its-skills-directory>`; this option cannot be combined with `--agent` or `--global`. Restart or reload your agent if its skill discovery requires it. A compatible client can invoke the installed skills with names such as `$opf-author` or `$opf-inspect`.\n\nInspect or update the same destination:\n\n```sh\nnpx @openpresentation/cli@latest skills status\nnpx @openpresentation/cli@latest skills update\n```\n\nSupply the same target options used for installation. `status` is read-only and compares against the invoked CLI's bundled version; it does not query npm for newer releases. Repeated installation is idempotent. Updates check every installed file before changing any skill. Modified, added, deleted or unmanaged files cause the command to stop and list the conflicting folders; keep your customizations, move those folders outside the active skills directory, then retry. There is no force-overwrite option. A successful update returns backup paths outside the active skills directory for recovering the previous managed versions. Keep those backups until you have reviewed the update. Do not run concurrent writers: the installer lock coordinates other installer runs, but cannot lock an external editor.\n\nNo skills are installed by the repository build. Manual installation remains supported: copy whole folders from `skills/`, including references and scripts, to your agent's skill directory. Each folder is self-contained. The managed installer treats existing manual copies as unmanaged and preserves them.\n\nThe inspection helper requires Node 24 and `@openpresentation/opf` in the current project. In this checkout, build with `pnpm build` first. For an installed skill used outside the checkout, either run from an npm project that has the package or set `OPF_ROOT` to the built OPF checkout. It does not install dependencies, fetch catalogs, or modify input files.\n\n## Local CLI\n\nThe [installable CLI](../packages/cli/README.md) complements these skills with `opf create`, `opf validate`, `opf edit`, and schema/catalog lookup. Its tarball bundles the core schema and validator; the inspection skill helper instead resolves the host project's core package. Check versions when moving between them.\n\n## Examples of requests\n\n- \u201CUse $opf-author to turn these notes into a five-slide decision brief. Keep every factual claim sourced.\u201D\n- \u201CUse $opf-layout to fix this overflow without losing any text or notes.\u201D\n- \u201CUse $opf-presets to apply our brand colors while preserving slide-specific overrides.\u201D\n- \u201CUse $opf-edit to replace one table and retain all other document fields.\u201D\n- \u201CUse $opf-export to export the same reviewed slides to SVG and editable PPTX.\u201D\n- \u201CUse $opf-inspect to explain which background forms the installed schema accepts.\u201D\n\n## Maintenance\n\n`pnpm test:skills` checks skill links, schema-valid examples, and the inspection helper's actual behavior, including a copied standalone skill and a package installed in a consumer project. Run the skill-creator frontmatter validator when editing skill metadata. Behavioral tests are not evidence that every renderer option is visually complete.\n\nWhen schema/package APIs change, update only the affected skill/reference and its executable examples. Keep option lists in the canonical schema and catalogs. The format package and skill folders are separate distribution surfaces: CLI 0.5.0 includes the six skills; the core `@openpresentation/opf` package does not install agent configuration.\n"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"slug": "catalog-schema-reference",
|
|
11
11
|
"file": "docs/catalog-schema-reference.md",
|
|
12
12
|
"title": "OPF Catalog Schema Reference",
|
|
13
|
-
"markdown": "# OPF Catalog Schema Reference\n\nCatalog records are reusable presets that OPF documents reference by id. This page summarizes every companion schema in `spec/schemas/` except the top-level presentation schema.\n\nOPF documents usually reference these records with string ids such as `design.theme = \"minimal\"`, `tone = \"formal\"`, or `chart.type = \"line\"`. Dense examples may also embed catalog sources or inline records under `catalogs`.\n\n## Audience\n\n- File: `spec/schemas/audience.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-audience/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for audience records in the pptx.gallery library. Each record names an audience archetype (e.g. 'executives', 'engineering-team', 'investors') and carries seniority, technical-fluency, decision-power, and attention-budget hints used by AI-driven generation. Audiences are referenced from OPF documents via audience; the engine resolves the reference against catalogs.audiences (inline) catalogs.audiences.source the default catalog at https://www.pptx.gallery/audiences. The audience field...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-audience/v1\"` | Identifies this record as an audience in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this audience via audience. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable audience name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the audience who they are and what they care about. |\n| `description` | no | `string` | Longer prose describing the audience archetype and how to address them. |\n| `seniority` | no | `enum:ic \\| manager \\| director \\| vp \\| c-suite \\| mixed` | Typical seniority level of the audience. Engines use this as a hint for default depth and pacing. |\n| `technicalFluency` | no | `enum:low \\| medium \\| high \\| mixed` | Typical technical fluency of the audience. AI generation uses this to decide whether to expand or assume technical terminology. |\n| `decisionPower` | no | `enum:informational \\| advisory \\| decision-maker` | Whether the audience is expected to be informed, to advise, or to actually decide. Shapes the strength of the closing ask. |\n| `attentionBudgetMinutes` | no | `number` | Realistic upper bound on this audience's focused attention for a single presentation, in minutes. Used as a hint when comparing against duration and the resolved narrative's durationRange. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this audience. Used by picker UIs to suggest narratives once an audience is chosen. Validators warn on unknown ids; never error. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this audience. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n\n## Chart Type\n\n- File: `spec/schemas/chart-type.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-chart-type/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `mappings`\n- Purpose: Schema for chart-type records in the pptx.gallery catalog. Each record describes a named chart variant, its Open XML mapping, its series/category cardinality, the column structure of the underlying workbook, and a small sample dataset suitable for previews. Chart types are referenced from OPF chart content payloads; the engine resolves the reference against catalogs.chartTypes (inline) -> catalogs.chartTypes.source -> the default catalog at https://www.pptx.gallery/chart-types.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-chart-type/v1\"` | Identifies this record as a chart type in the open presentation catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this chart type. Lowercase kebab-case. Chart type ids may start with a digit (e.g., '100pct-stacked-column', '3d-column') to mirror conventional chart naming. |\n| `name` | yes | `string` | Stable display/programmatic name for this chart type. |\n| `label` | no | `string` | Human-readable label shown in chart pickers. |\n| `summary` | no | `string` | One-sentence positioning: when to reach for this chart variant. |\n| `description` | no | `string` | Longer prose describing the chart and ideal use cases. |\n| `mappings` | yes | `ref:ChartTypeMappings` | Canonical and optional renderer-specific mappings used by engines to render this chart type. |\n| `group` | no | `string` | Top-level grouping in the chart picker (column, bar, line, area, pie, radar, etc.). |\n| `groupSort` | no | `integer` | Display ordering hint within the chart group. |\n| `complexity` | no | `enum:simple \\| calculated \\| hierarchical \\| normalized` | Shape of the underlying data: a flat series ('simple'), one with engine-side calculation ('calculated'), parent-child rows ('hierarchical'), or pre-normalized rows ('normalized'). |\n| `series` | no | `integer` | Number of data series this chart type expects. |\n| `categories` | no | `integer` | Number of category labels this chart type expects on the primary axis. |\n| `seriesGroups` | no | `integer` | Number of series groups (axis bands) this chart type uses; >1 for combo or banded charts. |\n| `useSecondaryCategories` | no | `boolean` | Whether the chart type uses a secondary category axis. |\n| `workbookRange` | no | `string` | A1 reference to the source range in the embedded workbook. |\n| `columns` | no | `array<string>` | Column header names of the embedded workbook, in left-to-right order. |\n| `dataColumns` | no | `array<ref:ChartDataColumn>` | Per-column metadata describing the role and position of each column in the workbook source. |\n| `helperColumns` | no | `array<string>` | Optional auxiliary column names used by calculated or banded charts (e.g., 'Excellent', 'Good', 'Fair', 'Poor' for a bullet chart). |\n| `sampleData` | no | `ref:ChartSampleData` | Inline sample dataset for previews and pickers. |\n| `slideNumber` | no | `integer` | Source slide number in the original chart-gallery deck. Carried for traceability. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n### Nested Types\n\n#### ChartTypeMappings\n\n- Type: `object`\n- Required fields: `openxml`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `openxml` | yes | `ref:OpenXmlChartMapping` | Canonical mapping to Open XML chart structures. |\n| `renderers` | no | `object` | Optional renderer-specific mappings. Keys are renderer ids; values are intentionally opaque to OPF. |\n\n#### OpenXmlChartMapping\n\n- Type: `object`\n- Required fields: none\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `element` | no | `string` | Primary Open XML chart element or extension chart element, such as 'barChart', 'lineChart', 'pieChart', 'treemapChart', or 'waterfallChart'. |\n| `barDir` | no | `enum:bar \\| col` | Bar direction for Open XML barChart mappings. |\n| `grouping` | no | `enum:standard \\| clustered \\| stacked \\| percentStacked` | Open XML chart grouping value when the chart family supports grouping. |\n| `marker` | no | `boolean` | Whether the chart type expects visible data markers. |\n| `radarStyle` | no | `enum:standard \\| marker \\| filled` | Open XML radarStyle value for radarChart mappings. |\n| `scatterStyle` | no | `enum:line \\| lineMarker \\| marker \\| smooth \\| smoothMarker` | Open XML scatterStyle value for scatterChart mappings. |\n| `composition` | no | `enum:single \\| mixed \\| extension` | Whether the chart maps to one standard chart element, multiple combined chart elements, or an Open XML extension chart. |\n| `extension` | no | `string` | Optional Open XML extension namespace or element hint for extension charts. |\n| `series` | no | `array<ref:OpenXmlChartMapping>` | Open XML chart elements used by mixed/composite chart types. |\n| `notes` | no | `string` | Short implementation note for mappings that need renderer interpretation. |\n\n#### ChartDataColumn\n\n- Type: `object`\n- Required fields: `name`, `role`, `type`\n- Purpose: One column of the embedded chart workbook, annotated with its role and grid position.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `name` | yes | `string` | Column header name (e.g. 'Series 1', 'Value', 'Level1', 'Level2'). |\n| `role` | yes | `enum:categoryLabel \\| series \\| helper` | Role this column plays: a category label (axis tick), a series (plotted values), or a helper (calculated/auxiliary). |\n| `type` | yes | `enum:string \\| number` | Cell value type for the column. |\n| `position` | no | `string` | Grid position of the column header in the source workbook, as 'row<N>_col<M>' (zero-indexed). |\n\n#### ChartSampleData\n\n- Type: `object`\n- Required fields: `headers`, `rows`\n- Purpose: Inline sample dataset for previews. Mirrors a small workbook with header row plus data rows.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `headers` | yes | `array<string>` | Header row labels. The first cell typically labels the series column; the rest are category labels. |\n| `rows` | yes | `array<array<string \\| number>>` | Two-dimensional sample data. Each row aligns by index with the headers first cell is the row label, remaining cells are values. |\n\n## Color Scheme\n\n- File: `spec/schemas/color-scheme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-color-scheme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for color-scheme records in the pptx.gallery library. Each scheme is a named palette with the twelve PowerPoint color slots (six accents, two darks, two lights, plus hyperlink and followed-hyperlink), suitable for being mapped directly into OOXML theme XML. Color schemes are referenced from OPF documents via design.colorScheme or design.colorScheme.id; the engine resolves the reference against catalogs.colorSchemes (inline) -> catalogs.colorSchemes.source -> the default catalog at http...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-color-scheme/v1\"` | Identifies this record as a color scheme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this color scheme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable scheme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the palette what mood it evokes and where to use it. |\n| `description` | no | `string` | Longer prose describing the palette and its intended use. |\n| `accent1` | no | `string` | Accent 1 color (hex). Mirrors the OOXML accent1 slot. |\n| `accent2` | no | `string` | Accent 2 color (hex). Mirrors the OOXML accent2 slot. |\n| `accent3` | no | `string` | Accent 3 color (hex). Mirrors the OOXML accent3 slot. |\n| `accent4` | no | `string` | Accent 4 color (hex). Mirrors the OOXML accent4 slot. |\n| `accent5` | no | `string` | Accent 5 color (hex). Mirrors the OOXML accent5 slot. |\n| `accent6` | no | `string` | Accent 6 color (hex). Mirrors the OOXML accent6 slot. |\n| `dark1` | no | `string` | Dark 1 color (hex). Typically the deepest neutral; OOXML dark1. |\n| `dark2` | no | `string` | Dark 2 color (hex). Secondary dark; OOXML dark2. |\n| `light1` | no | `string` | Light 1 color (hex). Typically the slide canvas; OOXML lt1. |\n| `light2` | no | `string` | Light 2 color (hex). Secondary light surface; OOXML lt2. |\n| `hyperlink` | no | `string` | Hyperlink color (hex). OOXML hlink. |\n| `followedHyperlink` | no | `string` | Followed-hyperlink color (hex). OOXML folHlink. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Font Scheme\n\n- File: `spec/schemas/font-scheme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-font-scheme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `major`, `minor`\n- Purpose: Schema for font-scheme records in the pptx.gallery library. Each scheme pairs a major (heading) and minor (body) font family in the OOXML majorFont/minorFont sense, scoped to a target app (PowerPoint or Google Slides) and a language family (Latin, East Asian, or Complex Script). Font schemes are referenced from OPF documents via design.fontScheme or design.fontScheme.id; the engine resolves the reference against catalogs.fontSchemes (inline) catalogs.fontSchemes.source the default catalog at...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-font-scheme/v1\"` | Identifies this record as a font scheme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this font scheme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable scheme name shown in pickers. |\n| `major` | yes | `string` | Heading (major) font family mirrors the OOXML majorFont entry. |\n| `minor` | yes | `string` | Body (minor) font family mirrors the OOXML minorFont entry. |\n| `type` | no | `enum:sans-serif \\| serif \\| monospace` | High-level typographic class of the scheme. |\n| `app` | no | `enum:PowerPoint \\| Google Slides` | Target application this font pairing is intended for. |\n| `languageFamily` | no | `enum:latin \\| ea \\| cs` | OOXML font-language family this scheme is intended for: 'latin' for Latin-script content, 'ea' for East Asian scripts, 'cs' for Complex Scripts. |\n| `languages` | no | `array<string>` | Optional list of human-readable language names this scheme is curated for. Useful for picker UIs that group fonts by language coverage. |\n| `textSample` | no | `string` | Short specimen string used by picker UIs to preview the scheme. |\n| `summary` | no | `string` | One-sentence positioning of the font pairing. |\n| `description` | no | `string` | Longer prose describing the font scheme and where it shines. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Language\n\n- File: `spec/schemas/language.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-language/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `bcp47`\n- Purpose: Schema for language records in the pptx.gallery library. Each record names a presentation language, carries a BCP-47 language tag, and pairs it with sensible default font schemes for PowerPoint and Google Slides output. Languages are referenced from OPF documents via language; the engine resolves the reference against catalogs.languages (inline) catalogs.languages.source the default catalog at https://www.pptx.gallery/languages. The presentation language field also accepts BCP-47 tags directl...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-language/v1\"` | Identifies this record as a language in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this language via language. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable language name. |\n| `code` | no | `string` | ISO 639-3 (or 639-2) three-letter language code. Carried for engines that prefer ISO codes. |\n| `bcp47` | yes | `string` | BCP-47 language tag for this record. Use 'en-GB' for UK English; 'en-UK' is not a valid BCP-47 region form. |\n| `direction` | no | `enum:ltr \\| rtl` | Base text direction for the language. |\n| `script` | no | `string` | ISO 15924 script code when the writing system should be explicit. |\n| `fontScheme` | no | `string` | Default font-scheme id for this language when targeting PowerPoint output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. |\n| `googleFontScheme` | no | `string` | Default font-scheme id for this language when targeting Google Slides output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. |\n| `summary` | no | `string` | One-sentence note about coverage or font defaults. |\n| `description` | no | `string` | Longer prose describing the language record and any font-pairing rationale. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Slide Layout\n\n- File: `spec/schemas/layout.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-layout/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for slide-layout records in the pptx.gallery library. Each record describes a semantic slide layout what regions it exposes and what content kinds those regions are intended to hold. Layouts are referenced from OPF documents via Slide.layout; the engine resolves the reference against catalogs.layouts (inline) catalogs.layouts.source the default catalog at https://www.pptx.gallery/layouts. Free-form custom layout names that don't resolve through any catalog fall through to engine-define...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-layout/v1\"` | Identifies this record as a slide layout in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this layout via Slide.layout. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable layout name shown in layout pickers. |\n| `summary` | no | `string` | One-sentence positioning of the layout when to reach for it. |\n| `description` | no | `string` | Longer prose describing the layout structure and ideal use cases. |\n| `contentType` | no | `enum:Title \\| Text \\| List \\| Image \\| Number \\| Chart` | Primary kind of content the layout holds. Drives pickers and AI placement decisions. |\n| `contentMultiple` | no | `enum:None \\| 1x \\| 2x \\| 3x \\| 4x \\| 5x \\| 6x` | How many parallel content blocks the layout exposes ('2x' = two-column, '3x' = three-up, etc.). |\n| `contentAlignment` | no | `enum:None \\| Left \\| Center` | Default horizontal alignment of the content area. |\n| `contentBox` | no | `boolean` | Whether the content area is rendered inside a visible box / card. |\n| `contentTypeChartPrimary` | no | `enum:None \\| Top \\| Bottom \\| Left \\| Right` | For chart layouts, where the primary chart sits relative to the rest of the content. |\n| `contentTypeImageFill` | no | `enum:None \\| Crop \\| Fit` | For image layouts, how the image fills its slot. |\n| `contentTypeListBullet` | no | `enum:None \\| Character \\| Image` | For list layouts, how bullets are rendered. |\n| `contentTypeListHeading` | no | `boolean` | For list layouts, whether each list item carries a heading. |\n| `slideTag` | no | `boolean` | Whether the layout includes a small slide-level tag / label region above or near the title. |\n| `slideTitle` | no | `boolean` | Whether the layout includes a slide title region. |\n| `slideSubtitle` | no | `boolean` | Whether the layout includes a slide-level subtitle or supporting-description region. When placeholders is present, this is true exactly when the layout exposes a placeholder with type 'subtitle'. |\n| `slideTitleAlignment` | no | `enum:None \\| Left \\| Center` | Horizontal alignment of the slide title region. |\n| `slideImage` | no | `boolean` | Whether the layout includes a dedicated slide-level image region (separate from any content image). |\n| `slideImageAlignment` | no | `enum:None \\| Top \\| Bottom \\| Left \\| Right \\| Background` | Where the slide-level image sits relative to the content. |\n| `slideLayoutDirection` | no | `enum:None \\| Horizontal \\| Vertical` | Axis along which the layout's primary regions are arranged. |\n| `composition` | no | `ref:Composition` | |\n| `placeholders` | no | `array<ref:Placeholder>` | Ordered regions the layout exposes. The engine fills 'title', 'subtitle', and 'tag' placeholders from Slide.title, Slide.subtitle, and Slide.tag. Other placeholders are content-kind hints for renderers and pickers. Sl... |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n### Nested Types\n\n#### Composition\n\n- Type: `object`\n- Required fields: none\n- Purpose: Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `mode` | no | `enum:auto \\| grid \\| row \\| column` | auto chooses a grid from available space and content; grid uses columns; row and column use one horizontal or vertical track. |\n| `columns` | no | `integer` | Column count for grid. In auto mode this caps the number of columns. |\n| `gap` | no | `number` | Space between cells as a fraction of the container short edge (canvas at slide root). Default 0.03333333333333333. |\n| `padding` | no | `number` | Inset as a fraction of the container short edge. Default 0.08 on a slide, 0 inside a group. |\n| `weights` | no | `array<number>` | Relative track sizes: columns for row/grid/auto, rows for column. Omitted tracks have weight 1; extra weights are ignored. |\n| `minFontSize` | no | `number` | Minimum readable text size in reference pixels at a 720-pixel canvas short edge. Default 16. Overflow is diagnosed when text cannot fit at this size. |\n| `overflow` | no | `enum:warn \\| error` | warn returns diagnostics for content that does not fit; error rejects layout. Content is never silently removed. Default warn. |\n\n#### Placeholder\n\n- Type: `object`\n- Required fields: `type`\n- Purpose: A single region inside a slide layout. Title, subtitle, and tag placeholders bind to the corresponding Slide fields; other placeholders describe the intended content kind for that region. The array order in the surrounding 'placeholders' field preserves layout region order.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `enum:title \\| subtitle \\| tag \\| text \\| list \\| chart \\| picture \\| table \\| media \\| diagram \\| code` | OPF placeholder kind. 'text' and 'list' are flexible textual content regions. The named kinds describe a specific content role used by pickers, AI generation, and engine defaulting. |\n\n## Narrative Template\n\n- File: `spec/schemas/narrative.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-narrative/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `beats`\n- Purpose: Schema for narrative template files in the openpresentation.org catalog. Each template describes a named story arc (e.g. 'problem-solution', 'scqa') as an ordered list of beats. Templates are referenced from OPF documents via narrative either as a bare id string (e.g. 'classic-story') or as an inline object whose shape matches this schema (sans '$schema').\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-narrative/v1\"` | |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this template, e.g. 'problem-solution'. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable template name, e.g. 'Problem Solution'. |\n| `summary` | no | `string` | One-sentence description of when and why to use this narrative. |\n| `description` | no | `string` | Longer prose describing the narrative arc and ideal use cases. Used by AI-driven generation to seed deck-level direction. |\n| `audienceFit` | no | `array<string>` | Audiences this narrative works well for, e.g. ['executives', 'investors', 'customers']. |\n| `durationRange` | no | `object` | Typical talk-length window this narrative suits. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search, e.g. ['business', 'pitch', 'internal']. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n| `beats` | yes | `array<ref:Beat>` | Ordered list of beats that make up the narrative arc. |\n\n### Nested Types\n\n#### Beat\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A single narrative beat a labeled segment of the story arc with a specific dramatic purpose. Mirrors the NarrativeBeat definition in opf.schema.json so library entries and inline OPF beats are interchangeable.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable slug used by Slide.beat to reference this beat. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable beat name, e.g. 'The Problem'. |\n| `description` | no | `string` | Curator-written prose that explains what this beat should accomplish. |\n| `instructions` | no | `string` | Short author-facing instruction for the beat typically one phrase. Complements 'description' with a concise directive. |\n| `slideCount` | no | `integer` | Optional explicit slide count for this beat. Defaults to 1 when omitted; values >1 are reserved for beats that intentionally span multiple slides. Prefer decomposing a heavy beat into multiple beats over setting a hig... |\n| `slideType` | no | `enum:text \\| list \\| image \\| shape \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Default content kind for the beat's slide. Mirrors ContentPayload.type and helps engines choose a sensible layout when only the beat is specified. |\n| `layoutHint` | no | `string` | Suggested layout id for the beat's opening slide, e.g. 'section-divider', 'title-slide', 'text-left'. Resolves the same way as Slide.layout against catalogs.layouts and the default catalog at https://www.pptx.gallery/... |\n| `thoughtCues` | no | `array<string>` | Optional speaker or thinking cues attached to the beat. Surfaced in presenter notes. |\n\n## Purpose\n\n- File: `spec/schemas/purpose.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-purpose/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for purpose records in the pptx.gallery library. Each record names a presentation objective such as informing, aligning, persuading, driving a decision, or selling. Purposes are referenced from OPF documents via purpose; the engine resolves the reference against catalogs.purposes (inline) catalogs.purposes.source the default catalog at https://www.pptx.gallery/purposes. The purpose field also accepts free-form strings and inline Purpose objects.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-purpose/v1\"` | Identifies this record as a purpose in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this purpose via purpose. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable purpose name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the purpose what this deck is trying to accomplish. |\n| `description` | no | `string` | Longer prose describing when to use this purpose and how it should shape a deck. |\n| `outcome` | no | `string` | Desired audience outcome after the presentation. |\n| `successCriteria` | no | `array<string>` | Observable signals that the deck accomplished this purpose. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this purpose. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this purpose. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n\n## Social Platform\n\n- File: `spec/schemas/social-platform.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-social-platform/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for social-platform records in the pptx.gallery library. Each record describes a single social-media platform its base URL, profile-URL pattern, handle prefix, brand color, and themed icons. Records are referenced from OPF documents indirectly: the property keys of any Socials object (Organization.socials, Speaker.socials) match record ids, and renderers use the catalog record to format URLs and pick icons. The engine resolves references against catalogs.socialPlatforms (inline) catalo...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-social-platform/v1\"` | Identifies this record as a social-platform entry in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this platform appears as a property key on Socials objects. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable platform name shown in pickers and footers. |\n| `summary` | no | `string` | One-sentence positioning of the platform what it's used for and who's on it. |\n| `description` | no | `string` | Longer prose describing the platform and any rendering conventions (e.g., handle prefixes, distributed instances). |\n| `baseUrl` | no | `string` | Canonical base URL of the platform used as the prefix when normalizing handles to full URLs. |\n| `profileUrlPattern` | no | `string` | URL pattern for individual member profiles. Use '{handle}' as the placeholder for the handle (with the prefix already stripped). |\n| `companyUrlPattern` | no | `string` | Optional URL pattern for organization / company pages, when the platform distinguishes them from member profiles. Use '{handle}' as the placeholder. |\n| `handlePrefix` | no | `string` | Conventional prefix character displayed before the handle (e.g. '@' for X / Mastodon / Threads / TikTok). Empty string when no prefix is used. Renderers strip it before substituting into URL patterns. |\n| `handleExample` | no | `string` | Example handle in its conventional rendered form, used by picker UIs and validation hints. |\n| `brandColor` | no | `string` | Brand color (hex) used for branded icon chips, link styling, or section accents. |\n| `icon` | no | `string` | Default icon source. Accepts an HTTPS URL, data URI, relative path, or asset reference. Used as the fallback when a themed (Light/Dark) variant isn't set. |\n| `iconLight` | no | `string` | Light-colored icon variant intended for rendering on dark backgrounds. |\n| `iconDark` | no | `string` | Dark-colored icon variant intended for rendering on light backgrounds. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Theme\n\n- File: `spec/schemas/theme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-theme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for theme records in the pptx.gallery library. Each theme is a small, named bundle that pairs a color scheme, a font scheme, a default theme-controlled background, and a slide size. Themes are referenced from OPF documents via design.theme or design.theme.id; the engine resolves the reference against catalogs.themes (inline) catalogs.themes.source the default catalog at https://www.pptx.gallery/themes. Inline overrides on design.colorScheme / design.fontScheme / design.background / des...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-theme/v1\"` | Identifies this record as a theme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this theme via design.theme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable theme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the theme when to reach for it. |\n| `description` | no | `string` | Longer prose describing what the theme looks and feels like and the kinds of decks it suits. |\n| `colorScheme` | no | `string` | Catalog reference to the theme's default color scheme resolved against catalogs.colorSchemes the same way design.colorScheme or design.colorScheme.id is. Accepts a bare id, HTTPS URL, or 'pkg:' reference. |\n| `fontScheme` | no | `string` | Catalog reference to the theme's default font scheme resolved against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id is. Accepts a bare id, HTTPS URL, or 'pkg:' reference. |\n| `background` | no | `ref:ThemeBackground` | |\n| `dimensions` | no | `enum:16:9 \\| 4:3 \\| 16:10 \\| letter \\| a4 \\| widescreen \\| standard` | Default slide size for this theme. Accepts the same preset values as design.dimensions.preset. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n### Nested Types\n\n#### ThemeBackgroundSlot\n\n- Type: `enum:light1 | light2 | dark1 | dark2`\n- Required fields: none\n- Purpose: PowerPoint theme-controlled slide background slot from the active color scheme. These are slots, not assumptions about actual colors: light1 is usually white and dark1 is usually black by convention, but the color scheme controls the real values.\n\n_No named properties._\n\n#### ThemeBackground\n\n- Type: `object`\n- Required fields: `type`, `slot`\n- Purpose: Theme-controlled PowerPoint slide background. The slot is resolved through the active color scheme and remains theme-aware.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"theme\"` | Theme-controlled background fill. |\n| `slot` | yes | `ref:ThemeBackgroundSlot` | |\n\n## Tone\n\n- File: `spec/schemas/tone.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-tone/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for tone records in the pptx.gallery library. Each record names a presentation tone (e.g. 'formal', 'casual', 'inspirational') and carries voice cues, anti-patterns, and sample phrases that AI-driven generation uses to shape output. Tones are referenced from OPF documents via tone; the engine resolves the reference against catalogs.tones (inline) catalogs.tones.source the default catalog at https://www.pptx.gallery/tones.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-tone/v1\"` | Identifies this record as a tone in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this tone via tone. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable tone name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the tone when to reach for it. |\n| `description` | no | `string` | Longer prose describing the tone and the kinds of decks it suits. |\n| `voiceCues` | no | `array<string>` | Short directives that shape AI generation toward this tone. Phrased as imperatives, e.g. 'use second-person', 'favor short sentences', 'lead with the recommendation'. |\n| `avoid` | no | `array<string>` | Anti-patterns that AI generation should not produce when this tone is active. |\n| `samplePhrases` | no | `array<string>` | Short example phrases that exemplify this tone. Used by picker UIs and as few-shot examples for AI generation. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids this tone pairs well with. Used by picker UIs to suggest narratives once a tone is chosen. Validators warn on unknown ids; never error. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n"
|
|
13
|
+
"markdown": "# OPF Catalog Schema Reference\n\nCatalog records are reusable presets that OPF documents reference by id. This page summarizes every companion schema in `spec/schemas/` except the top-level presentation schema.\n\nOPF documents usually reference these records with string ids such as `design.theme = \"minimal\"`, `tone = \"formal\"`, or `chart.type = \"line\"`. Dense examples may also embed catalog sources or inline records under `catalogs`.\n\n## Audience\n\n- File: `spec/schemas/audience.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-audience/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for audience records in the pptx.gallery library. Each record names an audience archetype (e.g. 'executives', 'engineering-team', 'investors') and carries seniority, technical-fluency, decision-power, and attention-budget hints used by AI-driven generation. Audiences are referenced from OPF documents via audience; the engine resolves the reference against catalogs.audiences (inline) catalogs.audiences.source the default catalog at https://www.pptx.gallery/audiences. The audience field...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-audience/v1\"` | Identifies this record as an audience in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this audience via audience. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable audience name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the audience who they are and what they care about. |\n| `description` | no | `string` | Longer prose describing the audience archetype and how to address them. |\n| `seniority` | no | `enum:ic \\| manager \\| director \\| vp \\| c-suite \\| mixed` | Typical seniority level of the audience. Engines use this as a hint for default depth and pacing. |\n| `technicalFluency` | no | `enum:low \\| medium \\| high \\| mixed` | Typical technical fluency of the audience. AI generation uses this to decide whether to expand or assume technical terminology. |\n| `decisionPower` | no | `enum:informational \\| advisory \\| decision-maker` | Whether the audience is expected to be informed, to advise, or to actually decide. Shapes the strength of the closing ask. |\n| `attentionBudgetMinutes` | no | `number` | Realistic upper bound on this audience's focused attention for a single presentation, in minutes. Used as a hint when comparing against duration and the resolved narrative's durationRange. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this audience. Used by picker UIs to suggest narratives once an audience is chosen. Validators warn on unknown ids; never error. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this audience. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n\n## Catalog Index\n\n- File: `spec/schemas/catalog-index.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-catalog-index/v1`\n- Type: `object`\n- Required fields: `$schema`, `version`, `description`, `records`\n- Purpose: Generic shape shared by every `spec/catalogs/<kind>/index.json` file in the OPF repo. An index is a lightweight, ordered summary of the full-record JSON files that live alongside it: each entry names the record's stable id, a human-readable name, and the record's filename, plus whatever extra summary fields are useful for picker UIs (e.g. `summary`, `tags`, `bcp47`, `durationRange`). This schema describes the repo-internal catalog index files themselves, not OPF documents or individual catalo...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-catalog-index/v1\"` | |\n| `version` | yes | `string` | Index format version, as a string. |\n| `description` | yes | `string` | Human-readable description of what this catalog kind holds and how entries are ordered. |\n| `records` | yes | `array<ref:IndexRecord>` | Ordered list of lightweight record summaries. Order defines the catalog's canonical/display order; full record data lives in the sibling JSON file named by `file`. |\n\n### Nested Types\n\n#### IndexRecord\n\n- Type: `object`\n- Required fields: `id`, `name`, `file`\n- Purpose: Lightweight summary of one catalog record. Additional per-kind fields (e.g. `summary`, `tags`, `bcp47`, `durationRange`, `group`, `label`) are allowed and vary by catalog kind.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable identifier, matching the `id` field inside the record file named by `file`. |\n| `name` | yes | `string` | Human-readable name shown in pickers. |\n| `file` | yes | `string` | Filename of the full record, relative to this index file's directory. |\n\n## Chart Type\n\n- File: `spec/schemas/chart-type.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-chart-type/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `mappings`\n- Purpose: Schema for chart-type records in the pptx.gallery catalog. Each record describes a named chart variant, its Open XML mapping, its series/category cardinality, the column structure of the underlying workbook, and a small sample dataset suitable for previews. Chart types are referenced from OPF chart content payloads; the engine resolves the reference against catalogs.chartTypes (inline) -> catalogs.chartTypes.source -> the default catalog at https://www.pptx.gallery/chart-types.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-chart-type/v1\"` | Identifies this record as a chart type in the open presentation catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this chart type. Lowercase kebab-case. Chart type ids may start with a digit (e.g., '100pct-stacked-column', '3d-column') to mirror conventional chart naming. |\n| `name` | yes | `string` | Stable display/programmatic name for this chart type. |\n| `label` | no | `string` | Human-readable label shown in chart pickers. |\n| `summary` | no | `string` | One-sentence positioning: when to reach for this chart variant. |\n| `description` | no | `string` | Longer prose describing the chart and ideal use cases. |\n| `mappings` | yes | `ref:ChartTypeMappings` | Canonical and optional renderer-specific mappings used by engines to render this chart type. |\n| `group` | no | `string` | Top-level grouping in the chart picker (column, bar, line, area, pie, radar, etc.). |\n| `groupSort` | no | `integer` | Display ordering hint within the chart group. |\n| `complexity` | no | `enum:simple \\| calculated \\| hierarchical \\| normalized` | Shape of the underlying data: a flat series ('simple'), one with engine-side calculation ('calculated'), parent-child rows ('hierarchical'), or pre-normalized rows ('normalized'). |\n| `series` | no | `integer` | Number of data series this chart type expects. |\n| `categories` | no | `integer` | Number of category labels this chart type expects on the primary axis. |\n| `seriesGroups` | no | `integer` | Number of series groups (axis bands) this chart type uses; >1 for combo or banded charts. |\n| `useSecondaryCategories` | no | `boolean` | Whether the chart type uses a secondary category axis. |\n| `workbookRange` | no | `string` | A1 reference to the source range in the embedded workbook. |\n| `columns` | no | `array<string>` | Column header names of the embedded workbook, in left-to-right order. |\n| `dataColumns` | no | `array<ref:ChartDataColumn>` | Per-column metadata describing the role and position of each column in the workbook source. |\n| `helperColumns` | no | `array<string>` | Optional auxiliary column names used by calculated or banded charts (e.g., 'Excellent', 'Good', 'Fair', 'Poor' for a bullet chart). |\n| `sampleData` | no | `ref:ChartSampleData` | Inline sample dataset for previews and pickers. |\n| `slideNumber` | no | `integer` | Source slide number in the original chart-gallery deck. Carried for traceability. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n### Nested Types\n\n#### ChartTypeMappings\n\n- Type: `object`\n- Required fields: `openxml`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `openxml` | yes | `ref:OpenXmlChartMapping` | Canonical mapping to Open XML chart structures. |\n| `renderers` | no | `object` | Optional renderer-specific mappings. Keys are renderer ids; values are intentionally opaque to OPF. |\n\n#### OpenXmlChartMapping\n\n- Type: `object`\n- Required fields: none\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `element` | no | `string` | Primary Open XML chart element or extension chart element, such as 'barChart', 'lineChart', 'pieChart', 'treemapChart', or 'waterfallChart'. |\n| `barDir` | no | `enum:bar \\| col` | Bar direction for Open XML barChart mappings. |\n| `grouping` | no | `enum:standard \\| clustered \\| stacked \\| percentStacked` | Open XML chart grouping value when the chart family supports grouping. |\n| `marker` | no | `boolean` | Whether the chart type expects visible data markers. |\n| `radarStyle` | no | `enum:standard \\| marker \\| filled` | Open XML radarStyle value for radarChart mappings. |\n| `scatterStyle` | no | `enum:line \\| lineMarker \\| marker \\| smooth \\| smoothMarker` | Open XML scatterStyle value for scatterChart mappings. |\n| `composition` | no | `enum:single \\| mixed \\| extension` | Whether the chart maps to one standard chart element, multiple combined chart elements, or an Open XML extension chart. |\n| `extension` | no | `string` | Optional Open XML extension namespace or element hint for extension charts. |\n| `series` | no | `array<ref:OpenXmlChartMapping>` | Open XML chart elements used by mixed/composite chart types. |\n| `notes` | no | `string` | Short implementation note for mappings that need renderer interpretation. |\n\n#### ChartDataColumn\n\n- Type: `object`\n- Required fields: `name`, `role`, `type`\n- Purpose: One column of the embedded chart workbook, annotated with its role and grid position.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `name` | yes | `string` | Column header name (e.g. 'Series 1', 'Value', 'Level1', 'Level2'). |\n| `role` | yes | `enum:categoryLabel \\| series \\| helper` | Role this column plays: a category label (axis tick), a series (plotted values), or a helper (calculated/auxiliary). |\n| `type` | yes | `enum:string \\| number` | Cell value type for the column. |\n| `position` | no | `string` | Grid position of the column header in the source workbook, as 'row<N>_col<M>' (zero-indexed). |\n\n#### ChartSampleData\n\n- Type: `object`\n- Required fields: `headers`, `rows`\n- Purpose: Inline sample dataset for previews. Mirrors a small workbook with header row plus data rows.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `headers` | yes | `array<string>` | Header row labels. The first cell typically labels the series column; the rest are category labels. |\n| `rows` | yes | `array<array<string \\| number>>` | Two-dimensional sample data. Each row aligns by index with the headers first cell is the row label, remaining cells are values. |\n\n## Color Scheme\n\n- File: `spec/schemas/color-scheme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-color-scheme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for color-scheme records in the pptx.gallery library. Each scheme is a named palette with the twelve PowerPoint color slots (six accents, two darks, two lights, plus hyperlink and followed-hyperlink), suitable for being mapped directly into OOXML theme XML. Color schemes are referenced from OPF documents via design.colorScheme or design.colorScheme.id; the engine resolves the reference against catalogs.colorSchemes (inline) -> catalogs.colorSchemes.source -> the default catalog at http...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-color-scheme/v1\"` | Identifies this record as a color scheme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this color scheme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable scheme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the palette what mood it evokes and where to use it. |\n| `description` | no | `string` | Longer prose describing the palette and its intended use. |\n| `accent1` | no | `string` | Accent 1 color (hex). Mirrors the OOXML accent1 slot. |\n| `accent2` | no | `string` | Accent 2 color (hex). Mirrors the OOXML accent2 slot. |\n| `accent3` | no | `string` | Accent 3 color (hex). Mirrors the OOXML accent3 slot. |\n| `accent4` | no | `string` | Accent 4 color (hex). Mirrors the OOXML accent4 slot. |\n| `accent5` | no | `string` | Accent 5 color (hex). Mirrors the OOXML accent5 slot. |\n| `accent6` | no | `string` | Accent 6 color (hex). Mirrors the OOXML accent6 slot. |\n| `dark1` | no | `string` | Dark 1 color (hex). Typically the deepest neutral; OOXML dark1. |\n| `dark2` | no | `string` | Dark 2 color (hex). Secondary dark; OOXML dark2. |\n| `light1` | no | `string` | Light 1 color (hex). Typically the slide canvas; OOXML lt1. |\n| `light2` | no | `string` | Light 2 color (hex). Secondary light surface; OOXML lt2. |\n| `hyperlink` | no | `string` | Hyperlink color (hex). OOXML hlink. |\n| `followedHyperlink` | no | `string` | Followed-hyperlink color (hex). OOXML folHlink. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Font Scheme\n\n- File: `spec/schemas/font-scheme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-font-scheme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `major`, `minor`\n- Purpose: Schema for font-scheme records in the pptx.gallery library. Each scheme pairs a major (heading) and minor (body) font family in the OOXML majorFont/minorFont sense, scoped to a target app (PowerPoint or Google Slides) and a language family (Latin, East Asian, or Complex Script). Font schemes are referenced from OPF documents via design.fontScheme or design.fontScheme.id; the engine resolves the reference against catalogs.fontSchemes (inline) catalogs.fontSchemes.source the default catalog at...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-font-scheme/v1\"` | Identifies this record as a font scheme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this font scheme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable scheme name shown in pickers. |\n| `major` | yes | `string` | Heading (major) font family mirrors the OOXML majorFont entry. |\n| `minor` | yes | `string` | Body (minor) font family mirrors the OOXML minorFont entry. |\n| `type` | no | `enum:sans-serif \\| serif \\| monospace` | High-level typographic class of the scheme. |\n| `app` | no | `enum:PowerPoint \\| Google Slides` | Target application this font pairing is intended for. |\n| `languageFamily` | no | `enum:latin \\| ea \\| cs` | OOXML font-language family this scheme is intended for: 'latin' for Latin-script content, 'ea' for East Asian scripts, 'cs' for Complex Scripts. |\n| `languages` | no | `array<string>` | Optional list of human-readable language names this scheme is curated for. Useful for picker UIs that group fonts by language coverage. |\n| `textSample` | no | `string` | Short specimen string used by picker UIs to preview the scheme. |\n| `summary` | no | `string` | One-sentence positioning of the font pairing. |\n| `description` | no | `string` | Longer prose describing the font scheme and where it shines. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Language\n\n- File: `spec/schemas/language.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-language/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `bcp47`\n- Purpose: Schema for language records in the pptx.gallery library. Each record names a presentation language, carries a BCP-47 language tag, and pairs it with sensible default font schemes for PowerPoint and Google Slides output. Languages are referenced from OPF documents via language; the engine resolves the reference against catalogs.languages (inline) catalogs.languages.source the default catalog at https://www.pptx.gallery/languages. The presentation language field also accepts BCP-47 tags directl...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-language/v1\"` | Identifies this record as a language in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this language via language. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable language name. |\n| `code` | no | `string` | ISO 639-3 (or 639-2) three-letter language code. Carried for engines that prefer ISO codes. |\n| `bcp47` | yes | `string` | BCP-47 language tag for this record. Use 'en-GB' for UK English; 'en-UK' is not a valid BCP-47 region form. |\n| `direction` | no | `enum:ltr \\| rtl` | Base text direction for the language. |\n| `script` | no | `string` | ISO 15924 script code when the writing system should be explicit. |\n| `fontScheme` | no | `string` | Default font-scheme id for this language when targeting PowerPoint output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. |\n| `googleFontScheme` | no | `string` | Default font-scheme id for this language when targeting Google Slides output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. |\n| `summary` | no | `string` | One-sentence note about coverage or font defaults. |\n| `description` | no | `string` | Longer prose describing the language record and any font-pairing rationale. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Layout Preview Index\n\n- File: `spec/schemas/layout-preview-index.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-layout-preview-index/v1`\n- Type: `object`\n- Required fields: `$schema`, `version`, `description`, `records`\n- Purpose: Shape of `spec/previews/layouts/index.json`, the manifest for the vendored slide-archetype preview gallery under `spec/previews/layouts/`. Each record names a preview id, its self-contained HTML file, and the file's exact UTF-8 byte length. These preview ids are an archetype taxonomy (e.g. 'swot-analysis', 'org-chart') distinct from the structural layout catalog at spec/catalogs/layouts/ (e.g. 'title', 'chart-2x') see spec/README.md. This schema describes a repo-internal index file, not an OP...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-layout-preview-index/v1\"` | |\n| `version` | yes | `string` | Index format version, as a string. |\n| `description` | yes | `string` | Human-readable description of the preview gallery and its rendering conventions. |\n| `records` | yes | `array<ref:PreviewRecord>` | One entry per vendored preview HTML file. |\n\n### Nested Types\n\n#### PreviewRecord\n\n- Type: `object`\n- Required fields: `id`, `file`, `bytes`\n- Purpose: Summary of one vendored preview HTML file.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Slide-archetype preview id (e.g. 'swot-analysis', 'agenda', 'org-chart'). Does not correspond to a spec/catalogs/layouts/ record id. |\n| `file` | yes | `string` | HTML filename, relative to this index file's directory. |\n| `bytes` | yes | `integer` | Exact UTF-8 byte length of the referenced HTML file's contents. |\n\n## Slide Layout\n\n- File: `spec/schemas/layout.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-layout/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for slide-layout records in the pptx.gallery library. Each record describes a semantic slide layout what regions it exposes and what content kinds those regions are intended to hold. Layouts are referenced from OPF documents via Slide.layout; the engine resolves the reference against catalogs.layouts (inline) catalogs.layouts.source the default catalog at https://www.pptx.gallery/layouts. Free-form custom layout names that don't resolve through any catalog fall through to engine-define...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-layout/v1\"` | Identifies this record as a slide layout in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this layout via Slide.layout. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable layout name shown in layout pickers. |\n| `summary` | no | `string` | One-sentence positioning of the layout when to reach for it. |\n| `description` | no | `string` | Longer prose describing the layout structure and ideal use cases. |\n| `contentType` | no | `enum:Title \\| Text \\| List \\| Image \\| Number \\| Metric \\| Chart \\| Table \\| Code \\| Video \\| Quote \\| Timeline` | Primary kind of content the layout holds. Drives pickers and AI placement decisions. Metric is the canonical numeric/KPI category; Number remains an accepted legacy label. |\n| `contentMultiple` | no | `enum:None \\| 1x \\| 2x \\| 3x \\| 4x \\| 5x \\| 6x` | How many parallel content blocks the layout exposes ('2x' = two-column, '3x' = three-up, etc.). |\n| `contentAlignment` | no | `enum:None \\| Left \\| Center` | Default horizontal alignment of the content area. |\n| `contentBox` | no | `boolean` | Whether the content area is rendered inside a visible box / card. |\n| `contentTypeChartPrimary` | no | `enum:None \\| Top \\| Bottom \\| Left \\| Right` | For chart layouts, where the primary chart sits relative to the rest of the content. |\n| `contentTypeImageFill` | no | `enum:None \\| Crop \\| Fit` | For image layouts, how the image fills its slot. |\n| `contentTypeListBullet` | no | `enum:None \\| Character \\| Image` | For list layouts, how bullets are rendered. |\n| `contentTypeListHeading` | no | `boolean` | For list layouts, whether each list item carries a heading. |\n| `slideTag` | no | `boolean` | Whether the layout includes a small slide-level tag / label region above or near the title. |\n| `slideTitle` | no | `boolean` | Whether the layout includes a slide title region. |\n| `slideSubtitle` | no | `boolean` | Whether the layout includes a slide-level subtitle or supporting-description region. When placeholders is present, this is true exactly when the layout exposes a placeholder with type 'subtitle'. |\n| `slideTitleAlignment` | no | `enum:None \\| Left \\| Center` | Horizontal alignment of the slide title region. |\n| `slideImage` | no | `boolean` | Whether the layout includes a dedicated slide-level image region (separate from any content image). |\n| `slideImageAlignment` | no | `enum:None \\| Top \\| Bottom \\| Left \\| Right \\| Background` | Where the slide-level image sits relative to the content. |\n| `slideLayoutDirection` | no | `enum:None \\| Horizontal \\| Vertical` | Axis along which the layout's primary regions are arranged. |\n| `placeholders` | no | `array<ref:Placeholder>` | Ordered regions the layout exposes. The engine fills 'title', 'subtitle', and 'tag' placeholders from Slide.title, Slide.subtitle, and Slide.tag. Other placeholders are content-kind hints for renderers and pickers. Sl... |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n| `composition` | no | `ref:Composition` | |\n\n### Nested Types\n\n#### Placeholder\n\n- Type: `object`\n- Required fields: `type`\n- Purpose: A single region inside a slide layout. Title, subtitle, and tag placeholders bind to the corresponding Slide fields; other placeholders describe the intended content kind for that region. The array order in the surrounding 'placeholders' field preserves layout region order.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `enum:title \\| subtitle \\| tag \\| text \\| metric \\| quote \\| timeline \\| list \\| chart \\| picture \\| table \\| media \\| diagram \\| code` | OPF placeholder kind. 'text' and 'list' are flexible textual content regions. 'metric' is a numeric/KPI content region filled by a metric payload, including its optional label, description, unit, delta, and trend. The... |\n\n#### Composition\n\n- Type: `object`\n- Required fields: none\n- Purpose: Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `mode` | no | `enum:auto \\| grid \\| row \\| column` | auto chooses a grid from available space and content; grid uses columns; row and column use one horizontal or vertical track. |\n| `columns` | no | `integer` | Column count for grid. In auto mode this caps the number of columns. |\n| `gap` | no | `number` | Space between cells as a fraction of the container short edge (canvas at slide root). Default 0.03333333333333333. |\n| `padding` | no | `number` | Inset as a fraction of the container short edge. Default 0.08 on a slide, 0 inside a group. |\n| `weights` | no | `array<number>` | Relative track sizes: columns for row/grid/auto, rows for column. Omitted tracks have weight 1; extra weights are ignored. |\n| `minFontSize` | no | `number` | Minimum readable text size in reference pixels at a 720-pixel canvas short edge. Default 16. Overflow is diagnosed when text cannot fit at this size. |\n| `overflow` | no | `enum:warn \\| error` | warn returns diagnostics for content that does not fit; error rejects layout. Content is never silently removed. Default warn. |\n\n## Narrative Template\n\n- File: `spec/schemas/narrative.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-narrative/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`, `beats`\n- Purpose: Schema for narrative template files in the openpresentation.org catalog. Each template describes a named story arc (e.g. 'problem-solution', 'scqa') as an ordered list of beats. Templates are referenced from OPF documents via narrative either as a bare id string (e.g. 'classic-story') or as an inline object whose shape matches this schema (sans '$schema').\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-narrative/v1\"` | |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this template, e.g. 'problem-solution'. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable template name, e.g. 'Problem Solution'. |\n| `summary` | no | `string` | One-sentence description of when and why to use this narrative. |\n| `description` | no | `string` | Longer prose describing the narrative arc and ideal use cases. Used by AI-driven generation to seed deck-level direction. |\n| `audienceFit` | no | `array<string>` | Audiences this narrative works well for, e.g. ['executives', 'investors', 'customers']. |\n| `durationRange` | no | `object` | Typical talk-length window this narrative suits. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search, e.g. ['business', 'pitch', 'internal']. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n| `beats` | yes | `array<ref:Beat>` | Ordered list of beats that make up the narrative arc. |\n\n### Nested Types\n\n#### Beat\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A single narrative beat a labeled segment of the story arc with a specific dramatic purpose. Mirrors the NarrativeBeat definition in opf.schema.json so library entries and inline OPF beats are interchangeable.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable slug used by Slide.beat to reference this beat. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable beat name, e.g. 'The Problem'. |\n| `description` | no | `string` | Curator-written prose that explains what this beat should accomplish. |\n| `instructions` | no | `string` | Short author-facing instruction for the beat typically one phrase. Complements 'description' with a concise directive. |\n| `slideCount` | no | `integer` | Optional explicit slide count for this beat. Defaults to 1 when omitted; values >1 are reserved for beats that intentionally span multiple slides. Prefer decomposing a heavy beat into multiple beats over setting a hig... |\n| `slideType` | no | `enum:text \\| list \\| image \\| shape \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Default content kind for the beat's slide. Uses ContentPayload.type names to help engines choose a layout. The legacy shape value is retained for compatibility and requests an image representation; it is not a native... |\n| `layoutHint` | no | `string` | Suggested layout id for the beat's opening slide, e.g. 'section-divider', 'title-slide', 'text-left'. Resolves the same way as Slide.layout against catalogs.layouts and the default catalog at https://www.pptx.gallery/... |\n| `thoughtCues` | no | `array<string>` | Optional speaker or thinking cues attached to the beat. Surfaced in presenter notes. |\n\n## Purpose\n\n- File: `spec/schemas/purpose.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-purpose/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for purpose records in the pptx.gallery library. Each record names a presentation objective such as informing, aligning, persuading, driving a decision, or selling. Purposes are referenced from OPF documents via purpose; the engine resolves the reference against catalogs.purposes (inline) catalogs.purposes.source the default catalog at https://www.pptx.gallery/purposes. The purpose field also accepts free-form strings and inline Purpose objects.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-purpose/v1\"` | Identifies this record as a purpose in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this purpose via purpose. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable purpose name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the purpose what this deck is trying to accomplish. |\n| `description` | no | `string` | Longer prose describing when to use this purpose and how it should shape a deck. |\n| `outcome` | no | `string` | Desired audience outcome after the presentation. |\n| `successCriteria` | no | `array<string>` | Observable signals that the deck accomplished this purpose. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this purpose. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this purpose. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n\n## Social Platform\n\n- File: `spec/schemas/social-platform.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-social-platform/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for social-platform records in the pptx.gallery library. Each record describes a single social-media platform its base URL, profile-URL pattern, handle prefix, brand color, and themed icons. Records are referenced from OPF documents indirectly: the property keys of any Socials object (Organization.socials, Speaker.socials) match record ids, and renderers use the catalog record to format URLs and pick icons. The engine resolves references against catalogs.socialPlatforms (inline) catalo...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-social-platform/v1\"` | Identifies this record as a social-platform entry in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this platform appears as a property key on Socials objects. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable platform name shown in pickers and footers. |\n| `summary` | no | `string` | One-sentence positioning of the platform what it's used for and who's on it. |\n| `description` | no | `string` | Longer prose describing the platform and any rendering conventions (e.g., handle prefixes, distributed instances). |\n| `baseUrl` | no | `string` | Canonical base URL of the platform used as the prefix when normalizing handles to full URLs. |\n| `profileUrlPattern` | no | `string` | URL pattern for individual member profiles. Use '{handle}' as the placeholder for the handle (with the prefix already stripped). |\n| `companyUrlPattern` | no | `string` | Optional URL pattern for organization / company pages, when the platform distinguishes them from member profiles. Use '{handle}' as the placeholder. |\n| `handlePrefix` | no | `string` | Conventional prefix character displayed before the handle (e.g. '@' for X / Mastodon / Threads / TikTok). Empty string when no prefix is used. Renderers strip it before substituting into URL patterns. |\n| `handleExample` | no | `string` | Example handle in its conventional rendered form, used by picker UIs and validation hints. |\n| `brandColor` | no | `string` | Brand color (hex) used for branded icon chips, link styling, or section accents. |\n| `icon` | no | `string` | Default icon source. Accepts an HTTPS URL, data URI, relative path, or asset reference. Used as the fallback when a themed (Light/Dark) variant isn't set. |\n| `iconLight` | no | `string` | Light-colored icon variant intended for rendering on dark backgrounds. |\n| `iconDark` | no | `string` | Dark-colored icon variant intended for rendering on light backgrounds. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n## Theme\n\n- File: `spec/schemas/theme.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-theme/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for theme records in the pptx.gallery library. Each theme is a small, named bundle that pairs a color scheme, a font scheme, a default theme-controlled background, and a slide size. Themes are referenced from OPF documents via design.theme or design.theme.id; the engine resolves the reference against catalogs.themes (inline) catalogs.themes.source the default catalog at https://www.pptx.gallery/themes. Inline overrides on design.colorScheme / design.fontScheme / design.background / des...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-theme/v1\"` | Identifies this record as a theme in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this theme via design.theme. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable theme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the theme when to reach for it. |\n| `description` | no | `string` | Longer prose describing what the theme looks and feels like and the kinds of decks it suits. |\n| `colorScheme` | no | `string` | Catalog reference to the theme's default color scheme resolved against catalogs.colorSchemes the same way design.colorScheme or design.colorScheme.id is. Accepts a bare id, HTTPS URL, or 'pkg:' reference. |\n| `fontScheme` | no | `string` | Catalog reference to the theme's default font scheme resolved against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id is. Accepts a bare id, HTTPS URL, or 'pkg:' reference. |\n| `background` | no | `ref:ThemeBackground` | |\n| `dimensions` | no | `enum:16:9 \\| 4:3 \\| 16:10 \\| letter \\| a4 \\| widescreen \\| standard` | Default slide size for this theme. Accepts the same preset values as design.dimensions.preset. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available. |\n\n### Nested Types\n\n#### ThemeBackgroundSlot\n\n- Type: `enum:light1 | light2 | dark1 | dark2`\n- Required fields: none\n- Purpose: PowerPoint theme-controlled slide background slot from the active color scheme. These are slots, not assumptions about actual colors: light1 is usually white and dark1 is usually black by convention, but the color scheme controls the real values.\n\n_No named properties._\n\n#### ThemeBackground\n\n- Type: `object`\n- Required fields: `type`, `slot`\n- Purpose: Theme-controlled PowerPoint slide background. The slot is resolved through the active color scheme and remains theme-aware.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"theme\"` | Theme-controlled background fill. |\n| `slot` | yes | `ref:ThemeBackgroundSlot` | |\n\n## Tone\n\n- File: `spec/schemas/tone.schema.json`\n- Schema id: `https://openpresentation.org/schema/opf-tone/v1`\n- Type: `object`\n- Required fields: `$schema`, `id`, `name`\n- Purpose: Schema for tone records in the pptx.gallery library. Each record names a presentation tone (e.g. 'formal', 'casual', 'inspirational') and carries voice cues, anti-patterns, and sample phrases that AI-driven generation uses to shape output. Tones are referenced from OPF documents via tone; the engine resolves the reference against catalogs.tones (inline) catalogs.tones.source the default catalog at https://www.pptx.gallery/tones.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | yes | `const:\"https://openpresentation.org/schema/opf-tone/v1\"` | Identifies this record as a tone in the openpresentation.org catalog. |\n| `id` | yes | `string` | Stable slug used by OPF documents to reference this tone via tone. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable tone name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the tone when to reach for it. |\n| `description` | no | `string` | Longer prose describing the tone and the kinds of decks it suits. |\n| `voiceCues` | no | `array<string>` | Short directives that shape AI generation toward this tone. Phrased as imperatives, e.g. 'use second-person', 'favor short sentences', 'lead with the recommendation'. |\n| `avoid` | no | `array<string>` | Anti-patterns that AI generation should not produce when this tone is active. |\n| `samplePhrases` | no | `array<string>` | Short example phrases that exemplify this tone. Used by picker UIs and as few-shot examples for AI generation. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids this tone pairs well with. Used by picker UIs to suggest narratives once a tone is chosen. Validators warn on unknown ids; never error. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional. |\n"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"slug": "content-item-design-overrides",
|
|
@@ -22,7 +22,7 @@ var docsData = Object.freeze([
|
|
|
22
22
|
"slug": "content-payloads",
|
|
23
23
|
"file": "docs/content-payloads.md",
|
|
24
24
|
"title": "Content Payloads",
|
|
25
|
-
"markdown": '# Content Payloads\n\nSlide content lives directly on a slide as a full-slide payload, in layout-agnostic `blocks`, or inside a promoted region key such as `left`, `center+right`, or `top:left`.\n\nThe optional payload `type` can make intent explicit, but OPF should usually infer the content kind from the field present:\n\n| Field | Inferred type | Notes |\n| --- | --- | --- |\n| `text` | `text` | Plain string or `TextRun[]`. |\n| `bullets` | `text` | Simple text bullets, usually `string[]`. |\n| `items` | `list` | Generic list payload, usually `string[]` or `ListItem[]`. |\n| `image` | `image` | Asset string shorthand or `Asset` object with `src` and optional metadata. |\n| `video` | `video` | Asset string shorthand or `Asset` object with `src` and optional metadata. |\n| `chart` | `chart` | Chart object with `type` and tabular `data`. |\n| `table` | `table` | Table object with optional `columns` and required `rows`. |\n| `code` | `code` | String shorthand or `Code` object with `source`, `language`, and `filename`. |\n| `metric` | `metric` | String/number shorthand or `Metric` object with `value`, `label`, `description`, `unit`, `delta`, and `trend`. |\n| `quote` | `quote` | String shorthand or `Quote` object with `text`, `attribution`, and `source`. |\n| `timeline` | `timeline` | Array shorthand or `Timeline` object with `name`, `description`, and `events`. |\n\n## Blocks\n\nUse slide-level `blocks` when a slide contains multiple content payloads, but exact placement should be inferred by the renderer. Blocks may contain a concrete content payload or a nested group with its own `blocks` and optional `composition`. Groups cannot mix child blocks with leaf payload fields. See [dynamic composition](dynamic-composition.md) for nesting and inheritance rules.\n\n```json\n{\n "title": "Customer Feedback Summary",\n "blocks": [\n {\n "table": {\n "columns": ["Theme", "Mentions"],\n "rows": [\n ["Speed", 42],\n ["Ease of use", 31]\n ]\n }\n },\n {\n "quote": {\n "text": "The new workflow cut review time in half.",\n "attribution": "Operations Lead",\n "source": "Customer interview"\n }\n }\n ]\n}\n```\n\nAt slide root only, multiple content payload kinds are accepted as shorthand for the equivalent blocks form when there is no explicit `type`, no `blocks`, and no promoted region keys:\n\n```json\n{\n "title": "Habitat & Territory",\n "text": "Jaguars are strongly associated with presence of water and dense cover.",\n "items": [\n "Primary habitats include dense rainforests, swamps, and seasonally flooded wetlands.",\n "Solitary animals that establish and defend large territories."\n ]\n}\n```\n\nThe same shorthand works for other content kinds:\n\n```json\n{\n "title": "Evidence Snapshot",\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Quarter", "Sightings"],\n "rows": [\n ["Q1", 12],\n ["Q2", 18]\n ]\n }\n },\n "quote": {\n "text": "Jaguar conservation depends on connected habitat.",\n "attribution": "Field researcher"\n }\n}\n```\n\n## Chart\n\nChart-specific fields are grouped under `chart`. Do not put loose chart data directly on a slide or region.\n\n```json\n{\n "title": "Revenue Trend",\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Quarter", "Revenue", "Costs"],\n "rows": [\n ["Q1", 12, 8],\n ["Q2", 18, 11],\n ["Q3", 24, 15]\n ]\n }\n }\n}\n```\n\nInline chart data is tabular by default. Renderers convert `columns` and `rows` into series, axes, legends, and workbook data internally.\n\nAsset-backed data is still table-oriented:\n\n```json\n{\n "chart": {\n "type": "column",\n "data": {\n "src": "asset:revenue-csv",\n "columns": ["Quarter", "Revenue"]\n }\n }\n}\n```\n\n## Table\n\nTable-specific fields are grouped under `table`. Do not put loose `columns` or `rows` directly on a slide or region.\n\n```json\n{\n "title": "Pipeline",\n "table": {\n "columns": ["Stage", "Count", "Value"],\n "rows": [\n ["Qualified", 42, "$1.2M"],\n ["Proposal", 18, "$840K"]\n ]\n }\n}\n```\n\nTable body cells accept strings, numbers, booleans, or `null`. Since core 0.5.0, a cell or column header also accepts the same `TextRun[]` used by rich text:\n\n```json\n{\n "table": {\n "columns": [["Quarter ", {"text": "growth", "bold": true}], "Value"],\n "rows": [\n [["Up ", {"text": "12%", "color": "#008800"}], 12]\n ]\n }\n}\n```\n\nUse core 0.6.0, renderer 0.4.0, editor 0.3.0 and PPTX 0.4.0 together. Core measures run styles when checking overflow and keeps each row intact when paginating. The renderer traces rich cells for the editor\'s existing formatting, typing and undo controls; the exporter emits editable native text runs. PPTX 0.4.0 imports supported native character styles, paragraph defaults, theme fonts/colors, external links and significant whitespace as rich runs. Unstyled body cells remain strings, and cached display text cannot recover original scalar types or live fields. Conditional table styles, merged geometry and cell fills/borders/alignment remain limited; native PowerPoint visual parity is not yet verified.\n\nCore 0.6.0 adds `layoutTable` from `@openpresentation/opf/composition`. It measures scalar and rich cells, keeps short rows compact, and gives wrapped or multiline rows the height they need. When space is constrained it reduces spare row height before shrinking text, and reports overflow when the minimum fitting size cannot fit. Pass the same `scale`, font family, measurement provider and effective `minFontSize` to each consumer. The returned row boxes, cell text boxes and fits are shared by the coordinated SVG and PPTX implementations; rich table cells use uniform line advances to match native cell paragraph spacing. Native viewer fidelity remains a separate verification boundary.\n\n\n## Code\n\nCode-specific fields are grouped under `code`. A string value is shorthand for `code.source`; use object form when syntax highlighting or a file label matters. In object form, `source` is required.\n\n```json\n{\n "title": "Decision Rule",\n "code": {\n "source": "if risk > threshold:\\n escalate(owner)\\nelse:\\n approve(change)",\n "language": "python",\n "filename": "decision.py"\n }\n}\n```\n\n## Metric\n\nMetric-specific fields are grouped under `metric`. A string or number value is shorthand for `metric.value`; numeric values stay numeric and are formatted by renderers at display time. Use object form when labels, descriptions, units, deltas, or trends matter.\n\n```json\n{\n "title": "Operating Metric",\n "metric": {\n "value": "42%",\n "label": "Review cycle reduction",\n "description": "Median reduction across customer review workflows.",\n "delta": "+11 pts",\n "trend": "up"\n }\n}\n```\n\n## Quote\n\nQuote-specific fields are grouped under `quote`. A string value is shorthand for `quote.text`; use object form when attribution or citation matters.\n\n```json\n{\n "title": "Customer Proof",\n "quote": {\n "text": "The new workflow made exceptions visible before they became escalations.",\n "attribution": "VP Operations, Acme Corp",\n "source": "Customer interview"\n }\n}\n```\n\n## Timeline\n\nTimeline-specific fields are grouped under `timeline`. An array value is shorthand for `timeline.events`; use object form when the timeline needs a name or description. Timeline events use `when`, `what`, and `description`.\n\n```json\n{\n "title": "Rollout Plan",\n "timeline": {\n "name": "Regional Rollout",\n "description": "Major milestones for the rollout.",\n "events": [\n {\n "when": "Q1",\n "what": "Pilot",\n "description": "Launch with one operations team."\n },\n {\n "when": "Q2",\n "what": "Rollout",\n "description": "Expand to all regions."\n }\n ]\n }\n}\n```\n\n## Regions\n\nRegion keys address a 3\xD73 grid of rows (`top`, `middle`, `bottom`) and columns (`left`, `center`, `right`):\n\n```\n left center right\n +--------------------+--------------------+--------------------+\n top | top:left | top:center | top:right |\n +--------------------+--------------------+--------------------+\n middle | middle:left | middle:center | middle:right |\n +--------------------+--------------------+--------------------+\n bottom | bottom:left | bottom:center | bottom:right |\n +--------------------+--------------------+--------------------+\n```\n\n- A bare column key (`left`) spans all three rows; a bare row key (`top`) spans all three columns.\n- `+` spans adjacent rows or columns: `center+right`, `top+middle`.\n- `row:column` combines the two: `top:left`, `middle+bottom:center+right`.\n- Keys on one slide must not overlap, and regions cannot be mixed with root payload fields.\n\nSpans compose into common slide shapes:\n\n```\n "left" + "center+right" "top" + "middle+bottom"\n (sidebar + main) (headline band + body)\n +----------+------------------+ +-------------------------------+\n | | | | top |\n | | | +-------------------------------+\n | left | center+right | | |\n | | | | middle+bottom |\n | | | | |\n +----------+------------------+ +-------------------------------+\n\n "top" + "middle+bottom:left" + "middle+bottom:center+right"\n (headline band, then sidebar + main)\n +---------------------------------------------+\n | top |\n +---------------+-----------------------------+\n | | |\n | middle+bottom | middle+bottom:center+right |\n | :left | |\n | | |\n +---------------+-----------------------------+\n```\n\nThe same payload objects work inside regions \u2014 here, the sidebar-plus-main shape:\n\n```json\n{\n "title": "Operating Snapshot",\n "left": {\n "table": {\n "columns": ["Metric", "Value"],\n "rows": [\n ["Revenue", "$4.2M"],\n ["Gross margin", "68%"]\n ]\n }\n },\n "center+right": {\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Month", "Revenue"],\n "rows": [\n ["Jan", 3.4],\n ["Feb", 3.8],\n ["Mar", 4.2]\n ]\n }\n }\n }\n}\n```\n'
|
|
25
|
+
"markdown": '# Content Payloads\n\nSlide content lives directly on a slide as a full-slide payload, in layout-agnostic `blocks`, or inside a promoted region key such as `left`, `center+right`, or `top:left`.\n\nThe optional payload `type` can make intent explicit, but OPF should usually infer the content kind from the field present:\n\n| Field | Inferred type | Notes |\n| --- | --- | --- |\n| `text` | `text` | Plain string or `TextRun[]`. |\n| `bullets` | `text` | Simple text bullets, usually `string[]`. |\n| `items` | `list` | Generic list payload, usually `string[]` or `ListItem[]`. |\n| `image` | `image` | Asset string shorthand or `Asset` object with `src` and optional metadata. |\n| `video` | `video` | Asset string shorthand or `Asset` object with `src` and optional metadata. |\n| `chart` | `chart` | Chart object with `type` and tabular `data`. |\n| `table` | `table` | Table object with optional `columns` and required `rows`. |\n| `code` | `code` | String shorthand or `Code` object with `source`, `language`, and `filename`. |\n| `metric` | `metric` | String/number shorthand or `Metric` object with `value`, `label`, `description`, `unit`, `delta`, and `trend`. |\n| `quote` | `quote` | String shorthand or `Quote` object with `text`, `attribution`, and `source`. |\n| `timeline` | `timeline` | Array shorthand or `Timeline` object with `name`, `description`, and `events`. |\n\n## Blocks\n\nUse slide-level `blocks` when a slide contains multiple content payloads, but exact placement should be inferred by the renderer. Blocks may contain a concrete content payload or a nested group with its own `blocks` and optional `composition`. Groups cannot mix child blocks with leaf payload fields. See [dynamic composition](dynamic-composition.md) for nesting and inheritance rules.\n\n```json\n{\n "title": "Customer Feedback Summary",\n "blocks": [\n {\n "table": {\n "columns": ["Theme", "Mentions"],\n "rows": [\n ["Speed", 42],\n ["Ease of use", 31]\n ]\n }\n },\n {\n "quote": {\n "text": "The new workflow cut review time in half.",\n "attribution": "Operations Lead",\n "source": "Customer interview"\n }\n }\n ]\n}\n```\n\nAt slide root only, multiple content payload kinds are accepted as shorthand for the equivalent blocks form when there is no explicit `type`, no `blocks`, and no promoted region keys:\n\n```json\n{\n "title": "Habitat & Territory",\n "text": "Jaguars are strongly associated with presence of water and dense cover.",\n "items": [\n "Primary habitats include dense rainforests, swamps, and seasonally flooded wetlands.",\n "Solitary animals that establish and defend large territories."\n ]\n}\n```\n\nThe same shorthand works for other content kinds:\n\n```json\n{\n "title": "Evidence Snapshot",\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Quarter", "Sightings"],\n "rows": [\n ["Q1", 12],\n ["Q2", 18]\n ]\n }\n },\n "quote": {\n "text": "Jaguar conservation depends on connected habitat.",\n "attribution": "Field researcher"\n }\n}\n```\n\n## Chart\n\nChart-specific fields are grouped under `chart`. Do not put loose chart data directly on a slide or region.\n\n```json\n{\n "title": "Revenue Trend",\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Quarter", "Revenue", "Costs"],\n "rows": [\n ["Q1", 12, 8],\n ["Q2", 18, 11],\n ["Q3", 24, 15]\n ]\n }\n }\n}\n```\n\nInline chart data is tabular by default. Renderers convert `columns` and `rows` into series, axes, legends, and workbook data internally.\n\nAsset-backed data is still table-oriented:\n\n```json\n{\n "chart": {\n "type": "column",\n "data": {\n "src": "asset:revenue-csv",\n "columns": ["Quarter", "Revenue"]\n }\n }\n}\n```\n\n## Table\n\nTable-specific fields are grouped under `table`. Do not put loose `columns` or `rows` directly on a slide or region.\n\n```json\n{\n "title": "Pipeline",\n "table": {\n "columns": ["Stage", "Count", "Value"],\n "rows": [\n ["Qualified", 42, "$1.2M"],\n ["Proposal", 18, "$840K"]\n ]\n }\n}\n```\n\nTable body cells accept strings, numbers, booleans, or `null`. Since core 0.5.0, a cell or column header also accepts the same `TextRun[]` used by rich text:\n\n```json\n{\n "table": {\n "columns": [["Quarter ", {"text": "growth", "bold": true}], "Value"],\n "rows": [\n [["Up ", {"text": "12%", "color": "#008800"}], 12]\n ]\n }\n}\n```\n\nUse core 0.6.0, renderer 0.4.0, editor 0.3.0 and PPTX 0.4.0 together. Core measures run styles when checking overflow and keeps each row intact when paginating. The renderer traces rich cells for the editor\'s existing formatting, typing and undo controls; the exporter emits editable native text runs. PPTX 0.4.0 imports supported native character styles, paragraph defaults, theme fonts/colors, external links and significant whitespace as rich runs. Unstyled body cells remain strings, and cached display text cannot recover original scalar types or live fields. Conditional table styles, merged geometry and cell fills/borders/alignment remain limited; native PowerPoint visual parity is not yet verified.\n\nCore 0.6.0 adds `layoutTable` from `@openpresentation/opf/composition`. It measures scalar and rich cells, keeps short rows compact, and gives wrapped or multiline rows the height they need. When space is constrained it reduces spare row height before shrinking text, and reports overflow when the minimum fitting size cannot fit. Pass the same `scale`, font family, measurement provider and effective `minFontSize` to each consumer. The returned row boxes, cell text boxes and fits are shared by the coordinated SVG and PPTX implementations; rich table cells use uniform line advances to match native cell paragraph spacing. Native viewer fidelity remains a separate verification boundary.\n\n\n## Code\n\nCode-specific fields are grouped under `code`. A string value is shorthand for `code.source`; use object form when syntax highlighting or a file label matters. In object form, `source` is required.\n\n```json\n{\n "title": "Decision Rule",\n "code": {\n "source": "if risk > threshold:\\n escalate(owner)\\nelse:\\n approve(change)",\n "language": "python",\n "filename": "decision.py"\n }\n}\n```\n\n## Metric\n\nMetric-specific fields are grouped under `metric`. A string or number value is shorthand for `metric.value`; numeric values stay numeric and are formatted by renderers at display time. Use object form when labels, descriptions, units, deltas, or trends matter.\n\nThe `number-1x` through `number-6x` layout IDs declare one title placeholder and one through six `metric` placeholders. The IDs retain their existing names; the content kind and payload key are `metric`, not `number` or `text`. For several metrics, use separate `{ "metric": ... }` entries in `blocks`. Choosing a layout does not reinterpret existing text as numeric data.\n\n```json\n{\n "title": "Operating Metric",\n "metric": {\n "value": "42%",\n "label": "Review cycle reduction",\n "description": "Median reduction across customer review workflows.",\n "delta": "+11 pts",\n "trend": "up"\n }\n}\n```\n\n## Quote\n\nQuote-specific fields are grouped under `quote`. A string value is shorthand for `quote.text`; use object form when attribution or citation matters.\n\n```json\n{\n "title": "Customer Proof",\n "quote": {\n "text": "The new workflow made exceptions visible before they became escalations.",\n "attribution": "VP Operations, Acme Corp",\n "source": "Customer interview"\n }\n}\n```\n\n## Timeline\n\nTimeline-specific fields are grouped under `timeline`. An array value is shorthand for `timeline.events`; use object form when the timeline needs a name or description. Timeline events use `when`, `what`, and `description`.\n\n```json\n{\n "title": "Rollout Plan",\n "timeline": {\n "name": "Regional Rollout",\n "description": "Major milestones for the rollout.",\n "events": [\n {\n "when": "Q1",\n "what": "Pilot",\n "description": "Launch with one operations team."\n },\n {\n "when": "Q2",\n "what": "Rollout",\n "description": "Expand to all regions."\n }\n ]\n }\n}\n```\n\n## Regions\n\nRegion keys address a 3\xD73 grid of rows (`top`, `middle`, `bottom`) and columns (`left`, `center`, `right`):\n\n```\n left center right\n +--------------------+--------------------+--------------------+\n top | top:left | top:center | top:right |\n +--------------------+--------------------+--------------------+\n middle | middle:left | middle:center | middle:right |\n +--------------------+--------------------+--------------------+\n bottom | bottom:left | bottom:center | bottom:right |\n +--------------------+--------------------+--------------------+\n```\n\n- A bare column key (`left`) spans all three rows; a bare row key (`top`) spans all three columns.\n- `+` spans adjacent rows or columns: `center+right`, `top+middle`.\n- `row:column` combines the two: `top:left`, `middle+bottom:center+right`.\n- Keys on one slide must not overlap, and regions cannot be mixed with root payload fields.\n\nSpans compose into common slide shapes:\n\n```\n "left" + "center+right" "top" + "middle+bottom"\n (sidebar + main) (headline band + body)\n +----------+------------------+ +-------------------------------+\n | | | | top |\n | | | +-------------------------------+\n | left | center+right | | |\n | | | | middle+bottom |\n | | | | |\n +----------+------------------+ +-------------------------------+\n\n "top" + "middle+bottom:left" + "middle+bottom:center+right"\n (headline band, then sidebar + main)\n +---------------------------------------------+\n | top |\n +---------------+-----------------------------+\n | | |\n | middle+bottom | middle+bottom:center+right |\n | :left | |\n | | |\n +---------------+-----------------------------+\n```\n\nThe same payload objects work inside regions \u2014 here, the sidebar-plus-main shape:\n\n```json\n{\n "title": "Operating Snapshot",\n "left": {\n "table": {\n "columns": ["Metric", "Value"],\n "rows": [\n ["Revenue", "$4.2M"],\n ["Gross margin", "68%"]\n ]\n }\n },\n "center+right": {\n "chart": {\n "type": "line",\n "data": {\n "columns": ["Month", "Revenue"],\n "rows": [\n ["Jan", 3.4],\n ["Feb", 3.8],\n ["Mar", 4.2]\n ]\n }\n }\n }\n}\n```\n'
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"slug": "data-import",
|
|
@@ -40,7 +40,7 @@ var docsData = Object.freeze([
|
|
|
40
40
|
"slug": "dynamic-composition",
|
|
41
41
|
"file": "docs/dynamic-composition.md",
|
|
42
42
|
"title": "Dynamic composition",
|
|
43
|
-
"markdown": '# Dynamic composition\n\nOPF keeps authoring intent in JSON. Use `blocks` when content can reflow; use promoted regions when relative placement is meaningful. `composition` on a slide overrides fields in the resolved layout\'s `composition`. Existing documents remain valid.\n\n```json\n{\n "name": "Decision brief",\n "slides": [{\n "title": "Make the main idea clear",\n "composition": { "mode": "row", "weights": [2, 1], "overflow": "error" },\n "blocks": [\n { "text": "The evidence and recommendation receive twice the width." },\n { "text": "The supporting detail receives the remaining width." }\n ]\n }]\n}\n```\n\n`auto` evaluates candidate grids using text fit and cell proportions. `columns` limits its candidates. `grid` uses `columns` if given, otherwise a grid based on the canvas shape. `row` uses one row; `column` uses one column. Items retain source order. Weights size columns except in column mode, where they size rows. Missing weights are 1; unused weights have no effect. A partially filled final row retains its grid tracks.\n\n`gap` defaults to 1/30 and `padding` to 0.08, both fractions of the canvas\'s shorter edge. Large gaps are reduced when necessary to keep cells positive. `minFontSize` defaults to 16 reference pixels at a 720-pixel short edge. The reference coordinate system uses 96 pixels per inch. Explicit inch dimensions override presets independently for each axis.\n\nHeadings reserve space according to their wrapped text. Content that exceeds the number of preset placeholders reflows together; it is not drawn over already-bound content. Promoted regions keep the 3\xD73 vocabulary, including standalone `top`, `middle`, and `bottom`. They ignore flow direction and track weights.\n\n## Nested groups\n\nA block or promoted region can contain its own `blocks` and `composition`. The optional discriminator is `"type": "group"`. A group has at least one child and cannot mix children with leaf fields such as `text` or `image`.\n\n```json\n{\n "composition": { "mode": "row", "weights": [2, 1] },\n "blocks": [\n {\n "composition": { "mode": "column", "padding": 0.02 },\n "blocks": [{ "text": "Recommendation" }, { "text": "Supporting evidence" }]\n },\n { "text": "Context" }\n ]\n}\n```\n\nThe parent allocates a box to each group, then the group arranges its children inside that box. Group padding defaults to zero; padding and gap use the group\'s shorter edge. Only `minFontSize` and `overflow` inherit. A strict ancestor cannot be weakened by a child\'s `overflow: "warn"`. Font sizes remain relative to the canvas, not the group. Groups can nest up to 32 levels; cycles and deeper nesting fail with an explicit error.\n\nAutomatic grid scoring inspects descendant text using each descendant\'s explicit arrangement or geometric automatic seed. After selecting the parent\'s grid, it optimizes each child\'s automatic grid. This deterministic, bounded search avoids exponential combinations; it does not claim a globally optimal packing.\n\n`result.items` contains every leaf with its full source path and effective composition. `result.groups` contains group paths, outer bounds, and content bounds. The editor\'s `setGroupComposition(path, value)` validates and records undo/redo just like slide composition edits.\n\n## Inspecting and repairing layout\n\n```js\nimport { composeSlide } from \'@openpresentation/opf/composition\';\nconst result = composeSlide(deck.slides[0], { width: 1280, height: 720, layout: resolvedLayout });\nconsole.log(result.items); // Source paths, content, geometry, and text estimates\nconsole.log(result.diagnostics); // Path-specific text-overflow and small-cell messages\n```\n\nThis pure function expects a validated slide. The caller resolves catalog records and passes the canvas size. The rendering and export packages perform those steps at their boundaries. No network, DOM, system font, or AI dependency is required.\n\n### Explain automatic selection (core 0.8.0 and later)\n\nPass `explain: true` to return `result.explanation`. This opt-in API requires core 0.8.0; it is absent from core 0.7.0. Enabling explanations adds no measurement calls and does not change geometry, source content, reading order, weights or selected arrangements within the same engine version.\n\n```js\nconst result = composeSlide(slide, {...resolvedOptions, explain: true});\nfor (const decision of result.explanation.decisions) {\n console.log(decision.path, decision.reason, decision.selectedColumns);\n console.table(decision.candidates);\n}\nconsole.log(result.explanation.textMeasurement);\nconsole.log(result.explanation.unmeasuredPayloads);\n```\n\n`resolvedOptions` supplies the same dimensions, layout, fonts and optional width provider as the preview. Core 0.8.0 identifies its explanation as `grid-score-v2`; core 0.9.0 advances to `grid-score-v3` to include complete code metadata/body measurements. Both record containers in parent-before-child order. `lowest-score` reports the candidates actually tried; `configured-mode` respects resolved row/column/grid intent and returns no invented candidates. `promoted-regions` leaves region placement fixed and has no selected column count. Empty slides have no decisions. Automatic search tries one through `min(slotCount, columns ?? 6)` columns, in ascending order; ties retain the first candidate. Reserved placeholders count as slots. The schema caps an explicit candidate limit at twelve columns.\n\nEach candidate has `columns`, `rows`, `score` and additive `penalties`:\n\n| Penalty | Rule |\n| --- | --- |\n| `cellProportions` | Sum of `abs(log(cellAspect / 1.6))` for descendant leaves |\n| `fontReduction` | Reduction from 25 reference pixels for text-like leaves; quotes and code in core 0.9 sum requested-minus-fitted sizes across their parts, divided by canvas scale |\n| `textOverflow` | 1,000 per overflowing text-like leaf, complete quote or complete code payload, regardless of the number of internal failure reasons |\n| `tableOverflow` | 1,000 per table whose shared cell layout overflows |\n| `smallCells` | 100 per leaf narrower than 100 or shorter than 60 reference pixels |\n| `emptySlots` | 2 per unused position in the candidate grid\'s final row |\n\nScores are preference costs, not quality percentages or guarantees. Floating-point summation can make the component total differ slightly from `score`. Parent scoring uses descendant explicit arrangements or geometric automatic seeds; child automatic grids are optimized only after selecting the parent. Candidate scores therefore describe the bounded search, not a full assessment of the final optimized subtree. Heading fit remains in ordinary diagnostics, outside body-grid scoring. A strict-fit rejection exposes the explanation on `OPFCompositionError` when requested.\n\n`textMeasurement` is `estimated` without a provider and `provided` with one. A provided width function does not establish font provenance, glyph coverage, shaping or native raster fidelity. Text, rich text, lists, quotes, table cells and code in core 0.9 participate in the fit model. `unmeasuredPayloads` identifies images, video, charts, metrics and timelines whose complete internal layout is not assessed. Core 0.8 also reports code as incomplete; core 0.9 measures its filename/language/body and insets. Media aspect ratios, chart labels, metric labels and timeline annotations remain gaps. A zero score or empty diagnostics is not proof that those payloads fit.\n\nThis milestone exposes the existing search for inspection. Guarded layout repairs, automatic weight allocation, content-aware candidate improvements, a common payload-internal measurement model, CLI explanations and a canvas **Auto arrange** preview/undo operation remain subsequent work. It does not silently paginate or rewrite a document.\n\nWith `overflow: "warn"` (default), the result retains all text and returns diagnostics. SVG emits all lines and marks overflowing groups with `data-opf-overflow="true"`; text may extend beyond its box or canvas. Consumers can collect diagnostics using `onDiagnostic`. With `overflow: "error"`, the layout rejects content that does not fit. Shorten the affected content, give it more space, or explicitly split it into another slide. Use the explicit pagination transform below to produce additional editable slides.\n\nThe editor exposes `editor.composeSlide(index)` and `editor.setComposition(index, value)`. The latter validates the change, records JSON Patch history, and supports undo/redo.\n\n## Pagination\n\n```js\nimport { paginateSlide, paginatePresentation } from \'@openpresentation/opf/pagination\';\nconst { presentation, pages } = paginatePresentation(deck);\n// Review, save, render, or export `presentation`; pages maps output fragments to source paths.\nconst single = paginateSlide(deck.slides[0], { width: 1280, height: 720, minFontSize: 24 });\n```\n\nPagination is an authoring operation. It produces ordinary OPF slides; previews and PPTX export consume those exact pages. It preserves the input, body order, nested groups, promoted regions, rich-text formatting, and source text characters. Plain text and rich runs split at grapheme boundaries, preferring sentence/paragraph breaks and then word breaks. Lists split between items, tables between rows with column labels repeated, and code splits without rewriting its source. Indivisible payloads remain intact. Existing track weights continue to apply to positions on each resulting page.\n\nThe default readability target is 24 reference pixels. Core 0.8.0 returns slides that persist that floor in `composition.minFontSize`, including an already-fitting one-page result; existing higher minima and strict overflow policies remain intact. Quotes can raise their nominal body/footer sizes to the floor. Other small-format payloads such as table cells retain their existing typography caps. Pagination relies on the shared engine\'s estimates; it is not a guarantee that every host font renders identically. Headings repeat unchanged, speaker notes remain on the first page, and continuation IDs avoid existing deck IDs. `pages[].mappings` records full source/output paths and half-open text or item ranges. Text offsets use UTF-16, so source strings can be reconstructed exactly. Quote bodies split at grapheme boundaries and repeat complete attribution/source fields on each page. An irreducible footer rejects the whole operation, including a quote with an empty body after earlier content.\n\nIf a heading, individual list item, table row, or other atomic payload cannot fit on an otherwise empty page, `OPFPaginationError` returns actionable diagnostics. There is no partial output. `maxSlides` defaults to 100, and a layout-evaluation limit bounds work on pathological input. Specialized chart and timeline internals still require visual inspection; their complete density models remain outstanding.\n\nThe editor\'s `editor.paginateSlide(index)` is one validated transaction with undo/redo. It returns `{change, pagination}`. Editor 0.5.0 commits a one-page readability-policy change too; repeating the operation after the policy is recorded returns `change: null`. The playground includes an overflowing draft and **Split overflow** action. The CLI writes a new file and refuses to overwrite an existing one:\n\n```sh\nnode packages/cli/dist/index.js paginate input.opf.json output.opf.json\n```\n\n## Fidelity boundary\n\nThe shared engine provides identical body and heading geometry to SVG and editable PPTX export. Text measurements default to deterministic estimates. For actual font advances, use the shared provider described in [measured fonts](font-fidelity.md). Complex scripts, fallback fonts, PowerPoint text rendering, rich text, charts, tables, and images still need visual verification. Dynamic composition is not a guarantee of pixel-identical PowerPoint output. List density includes rich runs, descriptions and nesting via `fitList`, with the same hanging indents used in preview and export. Only text-like payloads currently receive content-density estimates; small-cell diagnostics also cover non-text content.\n\nSVG embeds raster data URI images locally. Remote and file images require a host resolver that supplies a raster data URI; otherwise they appear as placeholders. `strictAssets` rejects unresolved images. The runtime never fetches them.\n\nSee [the complete example](../examples/technical/dynamic-composition.opf.json) and [local ecosystem verification](ecosystem-development.md).\n\n\n## Code internals (core 0.9.0 and coordinated packages)\n\nCore 0.9.0\'s `layoutCode(value, box, options)` API accepts the schema\'s string shorthand or `{source, language?, filename?}` object. It returns measured filename/language/body parts with exact original text, requested/resolved styles, readability floors, available boxes and diagnostics. Renderer/PPTX 0.7.0 and editor 0.6.0 are its coordinated release targets for shared rendering, native export, source/metadata edits and undo. [Release gates](plans/shared-code-release.md) distinguish prepared versions from verified publication. Core 0.8.0 does not include this API and retains the [recorded code-label, filename and whitespace defects](plans/layout-repair.md).\n\n`grid-score-v3` charges code font reductions across all metadata/body parts and one overflow penalty per failing leaf. It preserves explicit modes, weights, regions and source order. Accepted `item.codeLayout` is fitted to the same rounded cell exposed as `item.box`; `item.text` and `item.textStyle` alias the body, not the first metadata part. Strict ancestor settings apply to internal `.source`, `.filename` and `.language` diagnostics. Code no longer appears in `explanation.unmeasuredPayloads`, which concerns the core advance-based model only. It does not mean browser/native fidelity is verified.\n\nPagination slices the code body at grapheme boundaries, repeats filename/language and returns contiguous UTF-16 body ranges while preserving all source bytes and the evaluated readability floor. Irreducible metadata rejects all output, including when the body is empty or earlier content could have fitted. Consumers must preview/export the returned document. The [integration checkpoint](plans/shared-code-integration.md) separates source, installed browser, Windows PowerPoint and remaining release gates.\n\nEach fitted part retains every space and explicit CR/LF/CRLF break. `fit.lines` contains exact source slices, and `fit.sourceLines` records half-open UTF-16 `start`, `end` and `nextStart` offsets, the measured width and a `soft`, `hard` or `end` boundary. A hard break occupies `[end, nextStart)`; soft wrapping consumes no source character. Joining `part.text.slice(line.start, line.nextStart)` reconstructs the original part. Blank lines and a final empty line are retained, and long tokens split only at grapheme boundaries. Filename and language text are not case-converted. An absent/empty metadata pair creates a generated `code` label with no source range.\n\n`code-flow-v1` uses 18-reference-pixel outer insets, an eight-pixel gap between filename and language, and a twelve-pixel gap before the body. Nominal metadata/body sizes are 14/18 reference pixels, raised when necessary to respect the selected minimum, then scaled once. At most four metadata nominal/floor combinations are tried; each body fit tries at most 19 sizes regardless of canvas scale. The fitting combination with least font reduction wins. Irreducible metadata/body failures retain all text and diagnostic paths; invalid available boxes have no fit. `overflow: \'error\'` rejects rather than returning partial output.\n\nTabs remain literal characters in part text and displayed-line slices. Measurement advances to the next multiple of four measured spaces from that line\'s origin; `fit.tabSize` and `fit.tabWidth` expose the rule. Each source line\'s `segments` contains exact text/tab source ranges plus measured `x`/`width` values relative to its origin. Consumers must reuse those positions: an Edge probe showed that SVG treats a tab as one space despite CSS `tab-size: 4`. The candidate SVG renderer uses positioned spans and geometric precision; native export uses accepted tab stops. Width measurements and source preservation alone do not establish glyph-outline containment, shaping/bidi support or native fidelity. [Installed workflow evidence](evidence/shared-code-installed/summary.json) records the separate actual browser and native checks with their exact font/runtime scope.\n\nCandidate native export stores source boundaries in standard PowerPoint shape tags. Complete unique groups recover exact code/source metadata, with current native text taking precedence. Missing, damaged or ambiguous groups retain visible native shapes and report diagnostics. Reimport does not reconstruct native formatting, positioning, font theme or readability policy. Eight installed-export wide/portrait slides pass native edit/save/reopen and all 24 original/saved/edited imports on the recorded Windows PowerPoint build; this is not arbitrary PowerPoint round-trip or pixel equivalence. The editor preserves untouched CRLF/CR source around edits and keeps committed preview geometry separate from its active native textarea caret.\n\nThe JSON schema can accept strings that [XML 1.0 cannot represent](https://www.w3.org/TR/xml/#charsets). Candidate SVG/PPTX code output rejects forbidden controls, unpaired UTF-16 surrogates, U+FFFE and U+FFFF with `invalid-code-text`, the source field path and UTF-16 offset in the message. The input stays unchanged; the caller can correct that character explicitly. Tabs, CR/LF/CRLF and valid supplementary characters remain accepted for serialization. Schema support, format representability and glyph coverage are separate properties.\n\nThe controlled SVG harness requests `text-rendering="geometricPrecision"` as well as explicit segment placement. Initial Linux Chromium CI rounded glyph advances under default hinting, unlike Windows Edge with the same font bytes. The [SVG specification](https://www.w3.org/TR/SVG/painting.html#TextRenderingProperty) defines geometric precision as a rendering hint, so consumers still need actual browser checks with their exact fonts and supported environments; the hint alone does not certify agreement. The harness retains a 0.1-reference-pixel tolerance and records observations before assertions.\n\n## Quote internals (core 0.8.0 and coordinated packages)\n\nCore 0.8.0 exports `layoutQuote(value, box, options)` from the root or composition entrypoint. Pass validated quote content (object or string shorthand), its allocated reference-pixel box, resolved `fonts`, `textMeasurement`, `scale` (canvas short edge / 720), effective `minFontSize`, `overflow` policy and its source `path`.\n\nThe result contains `parts` for the body and any nonempty footer, exact display `text`, source mappings, requested and resolved text styles, and the available boxes/fits. Source ranges use half-open UTF-16 offsets in both the source field and display string; generated quotation marks and the footer separator have no source range. The original content is never modified. A supplied width provider is reported as `provided`; it does not certify shaping or font fidelity.\n\nCheck `overflow` and `diagnostics` before accepting the parts. Invalid available dimensions remain visible with `fit` absent, and `overflow: \'error\'` throws `OPFCompositionError`. Diagnostics distinguish invalid part space, parts outside their cell, text that exceeds its reserved space, and overlapping line rectangles. Those rectangles are conservative text-layout bounds, not measured glyph outlines. The readability floor is scaled once and can raise the nominal body (28) or footer (17) size; it is never silently capped below the selected floor.\n\n`quote-flow-v1` keeps 18-reference-pixel outer insets and an 18-pixel body/footer gap while fonts scale with the canvas. A 40-pixel footer is a whitespace preference. The allocator expands it for long sources or compacts it for dense bodies, trying at most the nominal and minimum footer sizes and selecting the fitting pair with least total font reduction. If neither fits, it returns floor-size failure diagnostics. This is a bounded internal allocation step, not a complete layout-repair engine.\n\n`composeSlide` scores both parts and accepts geometry against the final rounded item box. Each quote item carries `quoteLayout`; its compatibility `text` field is the same fit object as the quote body, including generated quotation marks. Consumers needing original offsets must use the explicit `sources` mappings. The coordinated renderer and PPTX consume these parts without another measurement/style-resolution pass. Missing geometry or invalid part boxes reject rendering/export rather than omitting content. This requires core 0.8.0 with renderer/PPTX 0.6.0; older core 0.7.0/renderer 0.5.1/PPTX 0.5.2 lack these changes. The complete published set, immutable verification refs and fresh registry evidence are recorded in `release-plan.json` and [the release plan](plans/shared-quote-release.md).\n\nBrowser glyph bounds can extend slightly beyond advance-based part boxes into the reserved inset. Current loaded-font tests record those overhangs, verify glyph containment inside the full quote cell and check body/footer separation. Native PowerPoint fixtures separately verify text, sizes, cell containment, save/reopen and reimport. Neither test establishes universal pixel equivalence. Original requested-font provenance through host substitutions and non-quote payload internals remain open requirements.\n\n## Resizing in the preview\n\nChoose **Arrange** in the editor to reveal track dividers. Drag a divider to redistribute the space between adjacent columns (row/grid) or rows (column), including nested groups. Arrow keys make small changes; Shift makes larger changes. Escape discards a pointer draft. One drag creates one undo step, and no content is removed. Strict overflow rejects a resize that violates its fit constraints.\n\nResizing an automatic layout makes its chosen columns explicit as `mode: grid` with `columns`. This prevents the number of columns from changing under the pointer. The adjacent share clamps to 5\u201395%, with positive schema-valid weights. Other track proportions and unrelated document fields remain intact. Promoted regions retain their positions; their nested groups can still be resized. Layouts with reserved placeholder slots need an explicit arrangement first. Flows with more than twelve tracks need grouping before the current resize controls can express all weights.\n\n`createCanvasEditor(container, {layoutEditing: true, ...options})` enables dividers initially. `canvas.setLayoutEditing(boolean)` toggles them, and `canvas.commit()` / `canvas.cancel()` also handle an active resize. `onDraft` receives the proposed document; the session stays unchanged until commit. Changes to the resized container cancel a stale draft; unrelated updates are retained.\n\nThe shared engine exposes `geometry.flows`: each flow has its container path, content box, resolved column/row tracks (offset and size), clamped gap, effective composition, item count, and reserved slot count. This is renderer geometry, not new OPF document fields.\n\nAgents can prepare the same guarded change without a DOM:\n\n```js\nimport {prepareTrackResize} from \'@openpresentation/opf-editor/layout\';\nimport {resolvePresentation} from \'@openpresentation/opf-render/svg\';\nconst geometry = resolvePresentation(editor.document, renderOptions).slides[0].geometry;\nconst flow = geometry.flows.find(flow => flow.path === \'slides.0\');\nconst prepared = prepareTrackResize(editor.document, flow, 0, 0.65);\n// Boundary 0: give the first track 65% of the adjacent pair\'s combined space.\n// Preview prepared.document with the same renderer and font provider before applying.\neditor.applyPatch(prepared.patches, {rejectInvalid: true});\n```\n\nThe patch contains a `test` guard for the container before changing its composition. Failed tests do not mutate the document or its history. A test-only patch is read-only. Rendering is preflighted by the canvas; headless callers should likewise render a candidate to enforce font and overflow constraints.\n\nVerification: editor layout model tests, `/layout-tests.html` browser keyboard checks and trusted-pointer specimens, and `pnpm test:layout` for measured SVG/native PPTX coordinate parity. Shape-coordinate checks do not establish PowerPoint raster pixel parity.\n\n\n## Reordering and moving blocks\n\nIn **Arrange**, drag a numbered block handle to reorder siblings. The insertion marker shows the destination; the shared renderer reflows the slide after drop. Arrow keys on a handle move the whole block earlier or later. Click a handle for **Earlier**, **Later**, or an explicit destination and insertion position. The destination menu supports existing groups and block-based slides, including moving a child out of a group or moving a whole group to another slide. `canvas.openBlockMenu(path)` opens the same controls programmatically.\n\nA move preserves the entire block and its nested content, formatting, data, and references. Parent composition weights describe positions, so they stay in place. Moving to another container can change the block\'s inherited design and readability constraints; the canvas renders the candidate before committing it. Strict overflow or an unavailable required font rejects the move. A move cannot leave an empty block container or put a group inside its own descendants. Move the group or add another block first when the source has only one child.\n\n```js\nimport {prepareBlockMove, listBlockContainers} from \'@openpresentation/opf-editor/layout\';\nconst containers = listBlockContainers(editor.document);\nconst prepared = prepareBlockMove(editor.document,\n \'/slides/0/blocks/0\', \'/slides/0/blocks/1\', 1);\n// Insert the first block before child 1 of the second block\'s group.\n// Destination indexes refer to the document before removal.\n// prepared.path reports the moved block\'s address after any index shifts.\neditor.applyPatch(prepared.patches, {rejectInvalid: true});\n```\n\n`prepareBlockMove` returns `{document, patches, path, changed}`. It validates the complete result and emits guarded remove/add patches, so the editor or CLI can apply it atomically. No-op moves return `changed: false` and no patches. `listBlockContainers(document, {slideIndex})` optionally limits discovery to a single slide and excludes arbitrary extension data. Headless callers should render the candidate with their intended font provider before applying. The browser and installed-package block harnesses exercise nested moves, undo, stale menus, keyboard access, strict-fit rejection, and native drag reordering.\n\nCreation and deletion use the same layout engine: insertions can normalize implicit payloads into explicit blocks; deletions prune empty groups while retaining the slide. Existing track weights stay positional. See the [editor creation guide](live-editor.md#create-duplicate-and-delete-content) for the guarded APIs and canvas controls.\n'
|
|
43
|
+
"markdown": '# Dynamic composition\n\nOPF keeps authoring intent in JSON. Use `blocks` when content can reflow; use promoted regions when relative placement is meaningful. `composition` on a slide overrides fields in the resolved layout\'s `composition`. Existing documents remain valid.\n\n```json\n{\n "name": "Decision brief",\n "slides": [{\n "title": "Make the main idea clear",\n "composition": { "mode": "row", "weights": [2, 1], "overflow": "error" },\n "blocks": [\n { "text": "The evidence and recommendation receive twice the width." },\n { "text": "The supporting detail receives the remaining width." }\n ]\n }]\n}\n```\n\n`auto` evaluates candidate grids using text fit and cell proportions. `columns` limits its candidates. `grid` uses `columns` if given, otherwise a grid based on the canvas shape. `row` uses one row; `column` uses one column. Items retain source order. Weights size columns except in column mode, where they size rows. Missing weights are 1; unused weights have no effect. A partially filled final row retains its grid tracks.\n\n`gap` defaults to 1/30 and `padding` to 0.08, both fractions of the canvas\'s shorter edge. Large gaps are reduced when necessary to keep cells positive. `minFontSize` defaults to 16 reference pixels at a 720-pixel short edge. The reference coordinate system uses 96 pixels per inch. Explicit inch dimensions override presets independently for each axis.\n\nHeadings reserve space according to their wrapped text. Content that exceeds the number of preset placeholders reflows together; it is not drawn over already-bound content. Promoted regions keep the 3\xD73 vocabulary, including standalone `top`, `middle`, and `bottom`. They ignore flow direction and track weights.\n\n## Unpublished shared headers and footers\n\nThe `codex/shared-furniture-20260910` candidate adds `layoutFurniture(slide, options)` and `geometry.furniture`, separate from body `items`. Composition identifies the changed available-space policy as `grid-score-v9`. Raw callers pass the presentation as `options.presentation`, resolved dimensions/fonts and the same measurement provider used by preview. `slideIndex` identifies source paths; optional `slideNumber` is the one-based displayed number.\n\nThe core resolver honors whole local header/footer overrides, including `false` and empty objects. Each zone retains its image and all configured text fields in source-aware parts. Literal text and dates preserve whitespace and empty strings. Organization and section values point to their metadata source; page numbers use the actual output sequence. A missing organization/section or `date: true` without a supported literal date produces `unresolved-content`; the implementation never consults a clock or invents source text.\n\n`furniture-flow-v1` gives each left/center/right zone 26% of the canvas width. Parts stack within a zone; the tallest zone sets the natural band height. Text uses at least the selected readability floor, with complete accepted source lines and optional measured outline placement. Header and footer bands reserve room before heading and body allocation. Irreducible text, conflicting bands or a heading displaced beyond the remaining space produce diagnostics; strict composition rejects them. No-furniture body geometry remains unchanged.\n\nPagination repeats these fields without putting them among body slices. An optional `page.repeatedMappings` records repeated heading/furniture and metadata paths while the existing `page.mappings` retains its body-fragment contract. Whole-deck pagination evaluates final output numbers, including preceding continuation pages, and rejects unresolved repeated content atomically. Renderer and editor reuse the accepted parts; literal text/date fields, including empty values, support direct canvas editing and undo. Generated labels remain tied to metadata.\n\nCandidate PPTX export draws the accepted text boxes and fitted images. Semantic furniture reimport, native Office acceptance, corpus review, clean installed-package verification and coordinated publication are still pending. The published versions do not expose this contract. Bounds/readability checks do not certify whole-slide design quality: long labels can wrap heavily in portrait zones, and outline agreement does not establish native font identity.\n\n## Nested groups\n\n### Unpublished shared content cards\n\nThe coordinated `codex/shared-metric-integration-20260910` source branches add `grid-score-v5`. For `design.contentBox: true`, each body leaf carries a `frameBox` at its outer allocation and a `box` padded inward by 12 reference pixels at a 720-pixel short edge, capped at one quarter of the frame\'s width or height. Scoring, accepted payload measurement, strict overflow and pagination all use that rounded interior. Headings remain unframed, nested groups keep their original padding, and explicit outer regions/track weights remain authoritative. Automatic candidates may change because their available content space changes.\n\nRaw composition callers pass their resolved deck flag as `composeSlide(slide, {contentBox: effectiveDesign.contentBox, ...options})`; a slide\'s explicit `design.contentBox: false` overrides it. Coordinated renderer, editor and whole-presentation pagination resolve this option for their callers. Consumers draw at `frameBox` and use the accepted `box` and payload internals without another inset. Published core 0.9.0 does not expose this behavior. Content cards do not make the incomplete chart/timeline density models complete or certify native raster fidelity.\n\nA block or promoted region can contain its own `blocks` and `composition`. The optional discriminator is `"type": "group"`. A group has at least one child and cannot mix children with leaf fields such as `text` or `image`.\n\n```json\n{\n "composition": { "mode": "row", "weights": [2, 1] },\n "blocks": [\n {\n "composition": { "mode": "column", "padding": 0.02 },\n "blocks": [{ "text": "Recommendation" }, { "text": "Supporting evidence" }]\n },\n { "text": "Context" }\n ]\n}\n```\n\nThe parent allocates a box to each group, then the group arranges its children inside that box. Group padding defaults to zero; padding and gap use the group\'s shorter edge. Only `minFontSize` and `overflow` inherit. A strict ancestor cannot be weakened by a child\'s `overflow: "warn"`. Font sizes remain relative to the canvas, not the group. Groups can nest up to 32 levels; cycles and deeper nesting fail with an explicit error.\n\nAutomatic grid scoring inspects descendant text using each descendant\'s explicit arrangement or geometric automatic seed. After selecting the parent\'s grid, it optimizes each child\'s automatic grid. This deterministic, bounded search avoids exponential combinations; it does not claim a globally optimal packing.\n\n`result.items` contains every leaf with its full source path and effective composition. `result.groups` contains group paths, outer bounds, and content bounds. The editor\'s `setGroupComposition(path, value)` validates and records undo/redo just like slide composition edits.\n\n## Inspecting and repairing layout\n\n```js\nimport { composeSlide } from \'@openpresentation/opf/composition\';\nconst result = composeSlide(deck.slides[0], { width: 1280, height: 720, layout: resolvedLayout });\nconsole.log(result.items); // Source paths, content, geometry, and text estimates\nconsole.log(result.diagnostics); // Path-specific text-overflow and small-cell messages\n```\n\nThis pure function expects a validated slide. The caller resolves catalog records and passes the canvas size. The rendering and export packages perform those steps at their boundaries. No network, DOM, system font, or AI dependency is required.\n\n### Explain automatic selection (core 0.8.0 and later)\n\nPass `explain: true` to return `result.explanation`. This opt-in API requires core 0.8.0; it is absent from core 0.7.0. Enabling explanations adds no measurement calls and does not change geometry, source content, reading order, weights or selected arrangements within the same engine version.\n\n```js\nconst result = composeSlide(slide, {...resolvedOptions, explain: true});\nfor (const decision of result.explanation.decisions) {\n console.log(decision.path, decision.reason, decision.selectedColumns);\n console.table(decision.candidates);\n}\nconsole.log(result.explanation.textMeasurement);\nconsole.log(result.explanation.unmeasuredPayloads);\n```\n\n`resolvedOptions` supplies the same dimensions, layout, fonts and optional width provider as the preview. Core 0.8.0 identifies its explanation as `grid-score-v2`; core 0.9.0 advances to `grid-score-v3` to include complete code metadata/body measurements. Both record containers in parent-before-child order. `lowest-score` reports the candidates actually tried; `configured-mode` respects resolved row/column/grid intent and returns no invented candidates. `promoted-regions` leaves region placement fixed and has no selected column count. Empty slides have no decisions. Automatic search tries one through `min(slotCount, columns ?? 6)` columns, in ascending order; ties retain the first candidate. Reserved placeholders count as slots. The schema caps an explicit candidate limit at twelve columns.\n\nEach candidate has `columns`, `rows`, `score` and additive `penalties`:\n\n| Penalty | Rule |\n| --- | --- |\n| `cellProportions` | Sum of `abs(log(cellAspect / 1.6))` for descendant leaves |\n| `fontReduction` | Reduction from 25 reference pixels for text-like leaves; quotes and code in core 0.9 sum requested-minus-fitted sizes across their parts, divided by canvas scale |\n| `textOverflow` | 1,000 per overflowing text-like leaf, complete quote or complete code payload, regardless of the number of internal failure reasons |\n| `tableOverflow` | 1,000 per table whose shared cell layout overflows |\n| `smallCells` | 100 per leaf narrower than 100 or shorter than 60 reference pixels |\n| `emptySlots` | 2 per unused position in the candidate grid\'s final row |\n\nScores are preference costs, not quality percentages or guarantees. Floating-point summation can make the component total differ slightly from `score`. Parent scoring uses descendant explicit arrangements or geometric automatic seeds; child automatic grids are optimized only after selecting the parent. Candidate scores therefore describe the bounded search, not a full assessment of the final optimized subtree. Heading fit remains in ordinary diagnostics, outside body-grid scoring. A strict-fit rejection exposes the explanation on `OPFCompositionError` when requested.\n\n`textMeasurement` is `estimated` without a provider and `provided` with one. A provided width function does not establish font provenance, glyph coverage, shaping or native raster fidelity. Text, rich text, lists, quotes, table cells and code in core 0.9 participate in the fit model. `unmeasuredPayloads` identifies images, video, charts, metrics and timelines whose complete internal layout is not assessed. Core 0.8 also reports code as incomplete; core 0.9 measures its filename/language/body and insets. Media aspect ratios, chart labels, metric labels and timeline annotations remain gaps. A zero score or empty diagnostics is not proof that those payloads fit.\n\nThis milestone exposes the existing search for inspection. Guarded layout repairs, automatic weight allocation, content-aware candidate improvements, a common payload-internal measurement model, CLI explanations and a canvas **Auto arrange** preview/undo operation remain subsequent work. It does not silently paginate or rewrite a document.\n\nWith `overflow: "warn"` (default), the result retains all text and returns diagnostics. SVG emits all lines and marks overflowing groups with `data-opf-overflow="true"`; text may extend beyond its box or canvas. Consumers can collect diagnostics using `onDiagnostic`. With `overflow: "error"`, the layout rejects content that does not fit. Shorten the affected content, give it more space, or explicitly split it into another slide. Use the explicit pagination transform below to produce additional editable slides.\n\nThe editor exposes `editor.composeSlide(index)` and `editor.setComposition(index, value)`. The latter validates the change, records JSON Patch history, and supports undo/redo.\n\n## Pagination\n\n```js\nimport { paginateSlide, paginatePresentation } from \'@openpresentation/opf/pagination\';\nconst { presentation, pages } = paginatePresentation(deck);\n// Review, save, render, or export `presentation`; pages maps output fragments to source paths.\nconst single = paginateSlide(deck.slides[0], { width: 1280, height: 720, minFontSize: 24 });\n```\n\nPagination is an authoring operation. It produces ordinary OPF slides; previews and PPTX export consume those exact pages. It preserves the input, body order, nested groups, promoted regions, rich-text formatting, and source text characters. Plain text and rich runs split at grapheme boundaries, preferring sentence/paragraph breaks and then word breaks. Lists split between items, tables between rows with column labels repeated, and code splits without rewriting its source. Indivisible payloads remain intact. Existing track weights continue to apply to positions on each resulting page.\n\nThe default readability target is 24 reference pixels. Core 0.8.0 returns slides that persist that floor in `composition.minFontSize`, including an already-fitting one-page result; existing higher minima and strict overflow policies remain intact. Quotes can raise their nominal body/footer sizes to the floor. Published small-format payloads such as table cells retain their earlier typography caps; the unpublished [readability-floor candidate](plans/readability-floor.md) removes those caps from shared text/list/table fitting. Pagination relies on the shared engine\'s estimates; it is not a guarantee that every host font renders identically. Headings repeat unchanged, speaker notes remain on the first page, and continuation IDs avoid existing deck IDs. `pages[].mappings` records full source/output paths and half-open text or item ranges. Text offsets use UTF-16, so source strings can be reconstructed exactly. Quote bodies split at grapheme boundaries and repeat complete attribution/source fields on each page. An irreducible footer rejects the whole operation, including a quote with an empty body after earlier content.\n\nIf a heading, individual list item, table row, or other atomic payload cannot fit on an otherwise empty page, `OPFPaginationError` returns actionable diagnostics. There is no partial output. `maxSlides` defaults to 100, and a layout-evaluation limit bounds work on pathological input. Specialized chart and timeline internals still require visual inspection; their complete density models remain outstanding.\n\nThe editor\'s `editor.paginateSlide(index)` is one validated transaction with undo/redo. It returns `{change, pagination}`. Editor 0.5.0 commits a one-page readability-policy change too; repeating the operation after the policy is recorded returns `change: null`. The playground includes an overflowing draft and **Split overflow** action. The CLI writes a new file and refuses to overwrite an existing one:\n\n```sh\nnode packages/cli/dist/index.js paginate input.opf.json output.opf.json\n```\n\n## Fidelity boundary\n\nThe shared engine provides identical body and heading geometry to SVG and editable PPTX export. Text measurements default to deterministic estimates. For actual font advances, use the shared provider described in [measured fonts](font-fidelity.md). Complex scripts, fallback fonts, PowerPoint text rendering, rich text, charts, tables, and images still need visual verification. Dynamic composition is not a guarantee of pixel-identical PowerPoint output. List density includes rich runs, descriptions and nesting via `fitList`, with the same hanging indents used in preview and export. Only text-like payloads currently receive content-density estimates; small-cell diagnostics also cover non-text content.\n\nSVG embeds raster data URI images locally. Remote and file images require a host resolver that supplies a raster data URI; otherwise they appear as placeholders. `strictAssets` rejects unresolved images. The runtime never fetches them.\n\nSee [the complete example](../examples/technical/dynamic-composition.opf.json) and [local ecosystem verification](ecosystem-development.md).\n\n\n## Metric internals (unreleased integration)\n\nThe candidate `layoutMetric(value, box, options)` export accepts a finite number, string, or `{value, unit?, label?, description?, delta?, trend?}`. Import it from the root or composition entrypoint after building this checkout. It is not included in published core 0.9.0. Coordinated source branches now consume it through composition, atomic pagination, SVG, editor and PPTX; candidate/registry adoption and native raster verification remain unfinished. The [primitive checkpoint](plans/shared-metric-layout.md) and [source integration checkpoint](plans/shared-metric-integration.md) distinguish their evidence and remaining gates.\n\nPass the allocated reference-pixel `box`, resolved heading/body `fonts`, `textMeasurement`, canvas `scale`, effective `minFontSize`, source `path` and optional `overflow: \'error\'`. `metric-flow-v1` returns separate value/unit/label/description/delta/trend parts in that order. Numeric zero is visible; scalar values keep the scalar path. Every provided field retains its original string or number in `sources[].value`. Source ranges address `String(value)` using UTF-16 offsets; the original spelling of a numeric JSON token is not available. No locale formatting, trend icon, case conversion or separator is invented. Empty optional strings retain source mappings with `visible: false`; the required empty value keeps a targetable blank line.\n\nThe allocator tries an adjacent value/unit baseline when both fit one line and the unit uses at most 35% of the cell width; otherwise it stacks the fields. Metadata has an eight-reference-pixel gap, with twelve pixels after the primary row. Related fields stay together rather than being separated by a percentage of the cell height. The value starts at up to 76 reference pixels (28% of cell height); label/unit/delta start at 23, description at 20 and trend at 18. Every requested size is raised to the chosen floor, scaled once. Natural metadata height gets space before reducing type. At most 48 arrangements are evaluated, each with at most 77 value-size trials; identical inputs and a deterministic measurement provider select the fitting candidate with least summed font reduction, preferring the first candidate on ties.\n\nEach part exposes requested/resolved styles and the same source-preserving line/segment representation used by code (`CodeTextFit`), measured with proportional heading/body fonts. CR/LF/CRLF, tabs, whitespace and grapheme boundaries remain exact. Consumers must reuse accepted line and segment positions, font sizes and styles rather than independently re-fit or normalize text. This API reports `provided` measurement when a provider is passed, without claiming that its glyph coverage or shaping is complete. Unsupported glyphs propagate the provider\'s error with the field path.\n\nPass `align: \'left\' | \'center\' | \'right\'` (default left) to the primitive. Its returned `alignment` and per-part `linePositions` give an absolute x origin and baseline for each `fit.sourceLines` entry, including blank lines. An inline value/unit pair moves together, with the gap following the actual value advance. Composition accepts host-resolved `contentAlignment`; an explicit slide `design.contentAlignment` overrides it. Renderer/export/pagination pass the effective design into the same operation. Alignment does not trigger a second font fit.\n\nCheck `overflow` before consuming parts. Irreducible text, invalid available space, parts outside the cell and overlapping occupied line boxes return field-specific diagnostics; strict mode throws `OPFCompositionError`. Invalid available boxes retain their dimensions and have no fit. These are advance-based line rectangles, not glyph outlines: the controlled browser evidence separately records small glyph overhangs. The API is a bounded internal allocator, not the complete layout-repair/Auto arrange operation or a native export fidelity guarantee.\n\n`grid-score-v4` now accounts for every metric part\'s font reduction and applies one overflow penalty per failing metric leaf. `item.metricLayout` is measured against the rounded accepted cell; `item.text`/`item.textStyle` alias the value fit/style. Field diagnostics obey strict ancestor policies, while explicit modes/weights/regions remain authoritative. Metrics leave this branch\'s advance-model `unmeasuredPayloads` list. Explicit pagination retains metrics atomically with complete source types/metadata and rejects irreducible fields without returning partial output. These source contracts still require coordinated consumer/browser/native verification before release.\n\n## Code internals (core 0.9.0 and coordinated packages)\n\nCore 0.9.0\'s `layoutCode(value, box, options)` API accepts the schema\'s string shorthand or `{source, language?, filename?}` object. It returns measured filename/language/body parts with exact original text, requested/resolved styles, readability floors, available boxes and diagnostics. Renderer/PPTX 0.7.0 and editor 0.6.0 are its coordinated release targets for shared rendering, native export, source/metadata edits and undo. [Release gates](plans/shared-code-release.md) distinguish prepared versions from verified publication. Core 0.8.0 does not include this API and retains the [recorded code-label, filename and whitespace defects](plans/layout-repair.md).\n\n`grid-score-v3` charges code font reductions across all metadata/body parts and one overflow penalty per failing leaf. It preserves explicit modes, weights, regions and source order. Accepted `item.codeLayout` is fitted to the same rounded cell exposed as `item.box`; `item.text` and `item.textStyle` alias the body, not the first metadata part. Strict ancestor settings apply to internal `.source`, `.filename` and `.language` diagnostics. Code no longer appears in `explanation.unmeasuredPayloads`, which concerns the core advance-based model only. It does not mean browser/native fidelity is verified.\n\nPagination slices the code body at grapheme boundaries, repeats filename/language and returns contiguous UTF-16 body ranges while preserving all source bytes and the evaluated readability floor. Irreducible metadata rejects all output, including when the body is empty or earlier content could have fitted. Consumers must preview/export the returned document. The [integration checkpoint](plans/shared-code-integration.md) separates source, installed browser, Windows PowerPoint and remaining release gates.\n\nEach fitted part retains every space and explicit CR/LF/CRLF break. `fit.lines` contains exact source slices, and `fit.sourceLines` records half-open UTF-16 `start`, `end` and `nextStart` offsets, the measured width and a `soft`, `hard` or `end` boundary. A hard break occupies `[end, nextStart)`; soft wrapping consumes no source character. Joining `part.text.slice(line.start, line.nextStart)` reconstructs the original part. Blank lines and a final empty line are retained, and long tokens split only at grapheme boundaries. Filename and language text are not case-converted. An absent/empty metadata pair creates a generated `code` label with no source range.\n\n`code-flow-v1` uses 18-reference-pixel outer insets, an eight-pixel gap between filename and language, and a twelve-pixel gap before the body. Nominal metadata/body sizes are 14/18 reference pixels, raised when necessary to respect the selected minimum, then scaled once. At most four metadata nominal/floor combinations are tried; each body fit tries at most 19 sizes regardless of canvas scale. The fitting combination with least font reduction wins. Irreducible metadata/body failures retain all text and diagnostic paths; invalid available boxes have no fit. `overflow: \'error\'` rejects rather than returning partial output.\n\nTabs remain literal characters in part text and displayed-line slices. Measurement advances to the next multiple of four measured spaces from that line\'s origin; `fit.tabSize` and `fit.tabWidth` expose the rule. Each source line\'s `segments` contains exact text/tab source ranges plus measured `x`/`width` values relative to its origin. Consumers must reuse those positions: an Edge probe showed that SVG treats a tab as one space despite CSS `tab-size: 4`. The candidate SVG renderer uses positioned spans and geometric precision; native export uses accepted tab stops. Width measurements and source preservation alone do not establish glyph-outline containment, shaping/bidi support or native fidelity. [Installed workflow evidence](evidence/shared-code-installed/summary.json) records the separate actual browser and native checks with their exact font/runtime scope.\n\nCandidate native export stores source boundaries in standard PowerPoint shape tags. Complete unique groups recover exact code/source metadata, with current native text taking precedence. Missing, damaged or ambiguous groups retain visible native shapes and report diagnostics. Reimport does not reconstruct native formatting, positioning, font theme or readability policy. Eight installed-export wide/portrait slides pass native edit/save/reopen and all 24 original/saved/edited imports on the recorded Windows PowerPoint build; this is not arbitrary PowerPoint round-trip or pixel equivalence. The editor preserves untouched CRLF/CR source around edits and keeps committed preview geometry separate from its active native textarea caret.\n\nThe JSON schema can accept strings that [XML 1.0 cannot represent](https://www.w3.org/TR/xml/#charsets). Candidate SVG/PPTX code output rejects forbidden controls, unpaired UTF-16 surrogates, U+FFFE and U+FFFF with `invalid-code-text`, the source field path and UTF-16 offset in the message. The input stays unchanged; the caller can correct that character explicitly. Tabs, CR/LF/CRLF and valid supplementary characters remain accepted for serialization. Schema support, format representability and glyph coverage are separate properties.\n\nThe controlled SVG harness requests `text-rendering="geometricPrecision"` as well as explicit segment placement. Initial Linux Chromium CI rounded glyph advances under default hinting, unlike Windows Edge with the same font bytes. The [SVG specification](https://www.w3.org/TR/SVG/painting.html#TextRenderingProperty) defines geometric precision as a rendering hint, so consumers still need actual browser checks with their exact fonts and supported environments; the hint alone does not certify agreement. The harness retains a 0.1-reference-pixel tolerance and records observations before assertions.\n\n## Quote internals (core 0.8.0 and coordinated packages)\n\nCore 0.8.0 exports `layoutQuote(value, box, options)` from the root or composition entrypoint. Pass validated quote content (object or string shorthand), its allocated reference-pixel box, resolved `fonts`, `textMeasurement`, `scale` (canvas short edge / 720), effective `minFontSize`, `overflow` policy and its source `path`.\n\nThe result contains `parts` for the body and any nonempty footer, exact display `text`, source mappings, requested and resolved text styles, and the available boxes/fits. Source ranges use half-open UTF-16 offsets in both the source field and display string; generated quotation marks and the footer separator have no source range. The original content is never modified. A supplied width provider is reported as `provided`; it does not certify shaping or font fidelity.\n\nCheck `overflow` and `diagnostics` before accepting the parts. Invalid available dimensions remain visible with `fit` absent, and `overflow: \'error\'` throws `OPFCompositionError`. Diagnostics distinguish invalid part space, parts outside their cell, text that exceeds its reserved space, and overlapping line rectangles. Those rectangles are conservative text-layout bounds, not measured glyph outlines. The readability floor is scaled once and can raise the nominal body (28) or footer (17) size; it is never silently capped below the selected floor.\n\n`quote-flow-v1` keeps 18-reference-pixel outer insets and an 18-pixel body/footer gap while fonts scale with the canvas. A 40-pixel footer is a whitespace preference. The allocator expands it for long sources or compacts it for dense bodies, trying at most the nominal and minimum footer sizes and selecting the fitting pair with least total font reduction. If neither fits, it returns floor-size failure diagnostics. This is a bounded internal allocation step, not a complete layout-repair engine.\n\n`composeSlide` scores both parts and accepts geometry against the final rounded item box. Each quote item carries `quoteLayout`; its compatibility `text` field is the same fit object as the quote body, including generated quotation marks. Consumers needing original offsets must use the explicit `sources` mappings. The coordinated renderer and PPTX consume these parts without another measurement/style-resolution pass. Missing geometry or invalid part boxes reject rendering/export rather than omitting content. This requires core 0.8.0 with renderer/PPTX 0.6.0; older core 0.7.0/renderer 0.5.1/PPTX 0.5.2 lack these changes. The complete published set, immutable verification refs and fresh registry evidence are recorded in `release-plan.json` and [the release plan](plans/shared-quote-release.md).\n\nBrowser glyph bounds can extend slightly beyond advance-based part boxes into the reserved inset. Current loaded-font tests record those overhangs, verify glyph containment inside the full quote cell and check body/footer separation. Native PowerPoint fixtures separately verify text, sizes, cell containment, save/reopen and reimport. Neither test establishes universal pixel equivalence. Original requested-font provenance through host substitutions and non-quote payload internals remain open requirements.\n\n## Resizing in the preview\n\nChoose **Arrange** in the editor to reveal track dividers. Drag a divider to redistribute the space between adjacent columns (row/grid) or rows (column), including nested groups. Arrow keys make small changes; Shift makes larger changes. Escape discards a pointer draft. One drag creates one undo step, and no content is removed. Strict overflow rejects a resize that violates its fit constraints.\n\nResizing an automatic layout makes its chosen columns explicit as `mode: grid` with `columns`. This prevents the number of columns from changing under the pointer. The adjacent share clamps to 5\u201395%, with positive schema-valid weights. Other track proportions and unrelated document fields remain intact. Promoted regions retain their positions; their nested groups can still be resized. Layouts with reserved placeholder slots need an explicit arrangement first. Flows with more than twelve tracks need grouping before the current resize controls can express all weights.\n\n`createCanvasEditor(container, {layoutEditing: true, ...options})` enables dividers initially. `canvas.setLayoutEditing(boolean)` toggles them, and `canvas.commit()` / `canvas.cancel()` also handle an active resize. `onDraft` receives the proposed document; the session stays unchanged until commit. Changes to the resized container cancel a stale draft; unrelated updates are retained.\n\nThe shared engine exposes `geometry.flows`: each flow has its container path, content box, resolved column/row tracks (offset and size), clamped gap, effective composition, item count, and reserved slot count. This is renderer geometry, not new OPF document fields.\n\nAgents can prepare the same guarded change without a DOM:\n\n```js\nimport {prepareTrackResize} from \'@openpresentation/opf-editor/layout\';\nimport {resolvePresentation} from \'@openpresentation/opf-render/svg\';\nconst geometry = resolvePresentation(editor.document, renderOptions).slides[0].geometry;\nconst flow = geometry.flows.find(flow => flow.path === \'slides.0\');\nconst prepared = prepareTrackResize(editor.document, flow, 0, 0.65);\n// Boundary 0: give the first track 65% of the adjacent pair\'s combined space.\n// Preview prepared.document with the same renderer and font provider before applying.\neditor.applyPatch(prepared.patches, {rejectInvalid: true});\n```\n\nThe patch contains a `test` guard for the container before changing its composition. Failed tests do not mutate the document or its history. A test-only patch is read-only. Rendering is preflighted by the canvas; headless callers should likewise render a candidate to enforce font and overflow constraints.\n\nVerification: editor layout model tests, `/layout-tests.html` browser keyboard checks and trusted-pointer specimens, and `pnpm test:layout` for measured SVG/native PPTX coordinate parity. Shape-coordinate checks do not establish PowerPoint raster pixel parity.\n\n\n## Reordering and moving blocks\n\nIn **Arrange**, drag a numbered block handle to reorder siblings. The insertion marker shows the destination; the shared renderer reflows the slide after drop. Arrow keys on a handle move the whole block earlier or later. Click a handle for **Earlier**, **Later**, or an explicit destination and insertion position. The destination menu supports existing groups and block-based slides, including moving a child out of a group or moving a whole group to another slide. `canvas.openBlockMenu(path)` opens the same controls programmatically.\n\nA move preserves the entire block and its nested content, formatting, data, and references. Parent composition weights describe positions, so they stay in place. Moving to another container can change the block\'s inherited design and readability constraints; the canvas renders the candidate before committing it. Strict overflow or an unavailable required font rejects the move. A move cannot leave an empty block container or put a group inside its own descendants. Move the group or add another block first when the source has only one child.\n\n```js\nimport {prepareBlockMove, listBlockContainers} from \'@openpresentation/opf-editor/layout\';\nconst containers = listBlockContainers(editor.document);\nconst prepared = prepareBlockMove(editor.document,\n \'/slides/0/blocks/0\', \'/slides/0/blocks/1\', 1);\n// Insert the first block before child 1 of the second block\'s group.\n// Destination indexes refer to the document before removal.\n// prepared.path reports the moved block\'s address after any index shifts.\neditor.applyPatch(prepared.patches, {rejectInvalid: true});\n```\n\n`prepareBlockMove` returns `{document, patches, path, changed}`. It validates the complete result and emits guarded remove/add patches, so the editor or CLI can apply it atomically. No-op moves return `changed: false` and no patches. `listBlockContainers(document, {slideIndex})` optionally limits discovery to a single slide and excludes arbitrary extension data. Headless callers should render the candidate with their intended font provider before applying. The browser and installed-package block harnesses exercise nested moves, undo, stale menus, keyboard access, strict-fit rejection, and native drag reordering.\n\nCreation and deletion use the same layout engine: insertions can normalize implicit payloads into explicit blocks; deletions prune empty groups while retaining the slide. Existing track weights stay positional. See the [editor creation guide](live-editor.md#create-duplicate-and-delete-content) for the guarded APIs and canvas controls.\n'
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"slug": "ecosystem-development",
|
|
@@ -58,25 +58,49 @@ var docsData = Object.freeze([
|
|
|
58
58
|
"slug": "examples",
|
|
59
59
|
"file": "docs/examples.md",
|
|
60
60
|
"title": "OPF Examples Guide",
|
|
61
|
-
"markdown": "# OPF Examples Guide\n\nThe `examples/` directory has three layers:\n\n- `examples/technical/` contains compact fixtures that isolate one or two schema behaviors.\n- `examples/gallery/` contains scenario-oriented decks that show OPF working across industries, functions, education, government, international, presentation-type, and design/media use cases.\n- The examples root is kept as an organizing directory rather than a home for standalone OPF files.\n\n## Technical Fixtures\n\
|
|
61
|
+
"markdown": "# OPF Examples Guide\n\nThe `examples/` directory has three layers:\n\n- `examples/technical/` contains compact fixtures that isolate one or two schema behaviors.\n- `examples/gallery/` contains scenario-oriented decks that show OPF working across industries, functions, education, government, international, presentation-type, and design/media use cases.\n- The examples root is kept as an organizing directory rather than a home for standalone OPF files.\n\n## Technical Fixtures\n\nUse `examples/technical/` when you want a small file that exercises a specific schema surface:\n\n- content payloads, rich text, blocks, charts, tables, media, metrics, quotes, and timelines\n- promoted region keys and span combinations\n- asset string/object forms and asset-backed chart data\n- design backgrounds, logo sets, headers, footers, watermarks, and slide-level overrides\n- metadata array forms, language metadata, narrative beats, and catalog overrides\n\n## Gallery Folders\n\n| Folder | What It Demonstrates |\n| --- | --- |\n| `industries/` | Vertical market decks with operating plans, investment briefs, readiness reviews, and launch coordination. |\n| `business-functions/` | Department-specific decks for sales, marketing, product, engineering, finance, HR, legal, security, support, procurement, and strategy. |\n| `education/` | K-12, higher education, research, advising, workforce, advancement, and student services scenarios. |\n| `government/` | Public health, transit, emergency management, utilities, regulators, courts, parks, workforce, tax, and civic engagement decks. |\n| `presentation-types/` | Reusable deck archetypes such as pitches, board updates, QBRs, conference talks, workshops, postmortems, launches, policy briefings, training, and research reports. |\n| `international/` | Region- or language-specific decks, including examples of language object metadata and right-to-left direction. |\n| `design-and-media/` | Decks that emphasize design controls, image/video assets, data storytelling, and self-running orientation patterns. |\n\n## Patterns To Look For\n\n- Technical fixtures that isolate validator and renderer behavior.\n- Sparse gallery documents that use shorthand catalog references and a small slide list.\n- Medium documents with schema ids, metadata, organization and speaker records, design overrides, assets, and richer slide payloads.\n- Dense documents with inline `catalogs` sources and records, promoted region keys, `blocks`, media assets, code payloads, header/footer configuration, logo sets, watermarks, and extensions.\n- Mixed content payloads across text, bullets, lists, image, video, chart, table, code, metric, quote, and timeline slides.\n- Catalog references across narratives, layouts, chart types, themes, color schemes, font schemes, languages, audiences, purposes, tones, and social platforms.\n\n## Validation\n\nRun the example validator after changing any `*.opf.json` file:\n\n```sh\nnode scripts/validate-examples.mjs\n```\n\nThe script walks every OPF document under `examples/` and reports schema or semantic validation issues with file paths.\n"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"slug": "font-fidelity",
|
|
65
65
|
"file": "docs/font-fidelity.md",
|
|
66
66
|
"title": "Measured fonts and reproducible previews",
|
|
67
|
-
"markdown": "# Measured fonts and reproducible previews\n\nFor the starter set and delivery priorities, see the [font roadmap](plans/font-roadmap.md).\n\nThe composition API accepts a `textMeasurement` provider. A provider resolves font faces and returns actual text widths; callers pass the same provider to pagination, editor geometry, SVG rendering, and PPTX export. Without one, the existing deterministic character-width estimate remains available.\n\nThe renderer's optional font registry uses [Fontkit](https://github.com/foliojs/fontkit) to shape text and measure glyph advances from local font bytes. It does not discover system fonts or fetch fonts. The Node helper loads the renderer's bundled Roboto and Roboto Mono faces:\n\n```js\nimport { loadBundledFontRegistry } from '@openpresentation/opf-render/fonts-node';\nimport { renderSvg, svgToPng } from '@openpresentation/opf-render';\nimport { paginatePresentation } from '@openpresentation/opf/pagination';\nimport { toPptx } from '@openpresentation/opf-pptx';\n\nconst registry = await loadBundledFontRegistry();\nconst options = { textMeasurement: registry.textMeasurement };\n// Use design.fontScheme: 'roboto', or supply the document's actual font files.\nconst { presentation } = paginatePresentation(deck, options);\nconst svg = renderSvg(presentation, {\n ...options,\n embeddedFonts: registry.embeddedFonts,\n});\nconst png = await svgToPng(svg, {\n fontFiles: registry.fontFiles,\n useBundledFonts: false,\n loadSystemFonts: false,\n});\nconst pptx = await toPptx(presentation, options);\n```\n\n`createFontRegistry` from `@openpresentation/opf-render/fonts` accepts `{data: Uint8Array, weight, italic?, family?, postscriptName?, license?}` entries in Node or the browser. Weights are explicit, with 400 as the default. Supply each style that the document uses. Missing font families and unsupported glyphs fail with `OPFFontError`, including the source path where available. Collection fonts require a `postscriptName` selecting one face.\n\nAliases and fallback families are explicit choices:\n\n```js\nconst registry = createFontRegistry(faces, {\n aliases: { Aptos: 'Roboto', 'Aptos Display': 'Roboto' },\n fallbackFamily: 'Roboto',\n});\nconsole.log(registry.substitutions);\nregistry.clearSubstitutions(); // Start a fresh render's diagnostic collection.\n```\n\nAn available exact family takes precedence over aliases. The registry resolves a requested weight to the closest supplied weight, reports the substitution, and makes the resolved style available to rendering. Missing italic/upright styles fail instead of synthesizing an unmeasured style. `strictGlyphs: false` is an explicit escape hatch for hosts with their own glyph-fallback policy; it is unsuitable for fidelity verification.\n\nSVG embeds supplied fonts using data URIs and includes supplied license notices as metadata. The bundled loader carries the fonts' SIL Open Font License notices. For PNG/PDF, pass the same font files to the rasterizer; its native font loader does not depend on browser CSS font loading. In a browser, wait for `document.fonts.ready` before measuring or taking a screenshot. The editor playground loads and embeds bundled fonts and displays substitutions.\n\n## Office compatibility pack\n\n`loadOfficeFontRegistry` from `@openpresentation/opf-render/fonts-node` supplies regular, bold, italic, and bold italic faces of Carlito, Caladea, Arimo, Tinos, Cousine, and Gelasio, plus the base Roboto pack. Package versions are pinned and each face carries its distribution's license notice. `includeBaseFonts: false` omits Roboto. Loading never installs fonts into the operating system or downloads fonts at render time.\n\n```js\nconst registry = await loadOfficeFontRegistry({\n substitutionPolicy: 'metric', // Default for this loader; no visual fallback.\n});\nregistry.resolveFont({fontFamily: 'Calibri', fontWeight: 400});\n// requestedFamily: Calibri, resolvedFamily: Carlito, compatibility: metric\n```\n\n`createFontRegistry` defaults to `substitutionPolicy: 'none'`. Policies are `none`, `metric`, and `visual`; visual permits both curated tiers. An explicit `fallbackFamily` is a separate, reported `generic` fallback. Aliases are explicit visual substitutions and never establish metric compatibility. `resolveFont` reports exact resolutions as well; `substitutions` only collects changes. Resolution records include requested/resolved weights, italic, source path, and supporting upstream information where available.\n\n| Requested family | Bundled substitute | Current automatic tier |\n| --- | --- | --- |\n| Calibri | Carlito | Metric intent, standard 400/700 styles |\n| Cambria | Caladea | Fontconfig metric mapping; reference-version testing remains necessary |\n| Arial | Arimo | Metric, standard 400/700 styles |\n| Times New Roman | Tinos | Metric, standard 400/700 styles |\n| Courier New | Cousine | Metric, standard 400/700 styles |\n| Georgia | Gelasio | Visual: optional ligatures changed measured widths |\n| Calibri Light | Carlito | Visual: the bundle has no Carlito Light face |\n| Aptos / Aptos Display | Carlito, unless Source Sans 3 is supplied | Visual; no Aptos metric claim |\n\nUpstream evidence: [Carlito](https://github.com/googlefonts/carlito), [Fontconfig mappings](https://chromium.googlesource.com/external/fontconfig/+/refs/heads/main/conf.d/30-metric-aliases.conf), [Arimo](https://github.com/google/fonts/blob/main/ofl/arimo/DESCRIPTION.en_us.html), [Tinos](https://github.com/google/fonts/blob/main/ofl/tinos/DESCRIPTION.en_us.html), [Cousine](https://github.com/google/fonts/blob/main/apache/cousine/DESCRIPTION.en_us.html), and [Gelasio](https://github.com/SorkinType/Gelasio). Metric classification describes compatibility intent within the stated style scope, not universal identical output. Missing matching weights cannot silently qualify for the metric tier.\n\nThe exported `FONT_COMPATIBILITY` list also contains optional visual candidates and CJK families. Listing a candidate does not bundle it or imply complete character coverage. Liberation Sans Narrow is a separate legacy distribution with a different license history; it is not part of this bundle. Wingdings, Webdings, and Symbol require character mapping before substitution; an ordinary fallback fails with `font-encoding-required`. Missing math fonts require an explicit math-aware choice and fail with `math-font-required` instead of falling through to body text.\n\nDrawingML tokens such as `+mn-lt` resolve through the registry's explicit `themeFonts` option before substitution. Supply concrete `majorLatin`, `minorLatin`, and, where used, `majorEastAsia`, `minorEastAsia`, `majorComplexScript`, or `minorComplexScript` families. Missing theme mappings fail. This helper does not yet extract theme font records or embedded fonts from imported PPTX files.\n\n### Measured results and experimental fonts\n\n`node --import ./scripts/register-local-opf.mjs scripts/test-office-fonts.mjs --system` compares the bundle to reference fonts already installed in macOS's Supplemental directory. It does not redistribute reference fonts. The report records source-file hashes and individual shaped widths. Across four samples and four styles, Arimo/Arial, Tinos/Times New Roman, and Cousine/Courier New matched exactly on 48 runs. Gelasio/Georgia differed on ligature-containing runs, with a maximum difference of 2.0125%. Individual basic-Latin advances matched; disabling optional ligatures removed the tested difference. Until feature handling is consistent across outputs, the policy conservatively labels Gelasio approximate. Calibri and Cambria reference fonts were not available for this comparison.\n\n[Akasia](https://codeberg.org/bloudraad/akasia) is a real upstream project claiming Aptos compatibility across twelve styles using open-licensed donor outlines. Its upstream README was inspected, but OPF has not yet validated its conformance or bundled its files. `EXPERIMENTAL_FONT_CANDIDATES` records it separately. Its claims do not imply compatibility with Aptos Narrow or Aptos Display.\n\nAn original OPF font project is technically feasible: independently designed or suitably open-licensed glyph outlines can be fitted to target advance widths, placement, vertical metrics, and shaping behavior. A successful font needs a reproducible source build, provenance, style/coverage tests, visual review, and cross-renderer conformance. Matching bounding boxes alone is insufficient: [OpenType horizontal metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hmtx) and [glyph positioning](https://learn.microsoft.com/en-us/typography/opentype/spec/gpos) jointly control text placement. Universal pixel identity across rasterizers is not the acceptance criterion; measured layout preservation over an explicit test matrix is.\n\n## Verification and remaining work\n\n`pnpm test:fonts` checks that editor and SVG geometry match, every native PPTX text box has the same coordinates and measured line breaks, and export uses the resolved family. It writes artifacts to `artifacts/fonts/`. A real-browser check of the same Roboto run measured 324.032 pixels versus the font engine's 324.170 pixels at 25 pixels, a difference of 0.138 pixels. These are measured tolerances, not a promise of pixel identity.\n\nPPTX currently records the resolved font family; it does not embed font binaries. PowerPoint still needs those fonts installed or may substitute them. Line height remains the shared 1.22 multiplier, rather than a complete ascent/descent model. Rich-text font overrides, mixed-script fallback and bidi layout, specialized payload internals, and native font embedding remain active fidelity work. Passing a width provider does not remove those limits.\n"
|
|
67
|
+
"markdown": "# Measured fonts and reproducible previews\n\nFor the starter set and delivery priorities, see the [font roadmap](plans/font-roadmap.md).\n\nThe [Windows reference-font advance study](evidence/shared-metric-native-anchor/font-study-comparison.json) is exploratory source-checkpoint evidence, not an additional compatibility certification. It measures 1,024 cases across regular/bold Calibri, Arial, Times New Roman and Courier New, recording local reference-file versions/hashes and native font-slot names. Disabling optional ligatures and rounding base glyph advances to eighth-point steps predicts 949 observations within 0.02pt; 75 outliers remain, including combining marks, Arabic and Calibri kerning. Office theme tokens and per-glyph fallback are not resolved to exact native files by these name properties. No runtime provider or open-font mapping changes from this hypothesis, and no reference font is redistributed.\n\nThe composition API accepts a `textMeasurement` provider. A provider resolves font faces and returns actual text widths; callers pass the same provider to pagination, editor geometry, SVG rendering, and PPTX export. Without one, the existing deterministic character-width estimate remains available.\n\nRenderer 0.8.0 publishes `prepareNodeFonts` from `/fonts-node`. Its returned `options` combine the same registry measurement, embedded SVG fonts and explicit raster files, with system/bundled fallback disabled for raster calls. Pass these options to pagination, editor geometry, SVG, PPTX and PNG/PDF export. `pack: 'base'` is the default for authored Roboto decks; `pack: 'office'` adds the six Office substitute families and retains metric policy unless visual substitution is explicitly requested. `registry.substitutions` records actual substitutions; the helper does not rewrite the authored document or add native embedding.\n\nRenderer 0.8.0 groups static files by their OpenType preferred family while retaining legacy family names and explicit custom namespaces. `Roboto` requests at 500/600/800 now select the actual Medium/SemiBold/ExtraBold files instead of nearby 400/700 faces. Optional `TextStyle.fontFace` carries the physical legacy family and native bold/italic flags independently of CSS numeric weight: SemiBold/ExtraBold are regular within their legacy families. The converter consumes this metadata; providers without it retain their prior behavior. Nine actual base faces pass metadata/measurement/outline checks and offline Chromium advances on Node 20/24. Seven payload slides cover serialized native selectors, deterministic output and source/reimport. These checks do not establish native Office paint, embedding or broader script coverage; see the [Mac candidate evidence](evidence/mac-font-variants/README.md).\n\nRenderer 0.8.0 uses adjacent SVG spans when no measurement provider is supplied. This closes the visible gaps caused by estimated fragment widths while retaining estimated line breaks and all run text/style/source offsets. Supplied providers and accepted placements still use exact fragment origins. Measured SVG requests geometric precision; accepted outline placements also constrain horizontal advances with `textLength`/`spacingAndGlyphs` to avoid browser quantization drift. This can scale glyphs horizontally while retaining nominal font size and baseline. Width-only providers do not receive that constraint, and constrained widths do not certify raw font-metric equivalence. The compatible editor supports both forms. This is a spacing improvement, not evidence that unmeasured wrapping or glyph coverage is accurate; see [candidate evidence](evidence/mac-rich-flow/README.md).\n\nBoth Node loaders verify exact package versions, 33 font-file hashes and eight license-notice hashes against the immutable `BUNDLED_FONT_MANIFEST` exported from `/fonts-node`. Missing/modified resources reject with actionable errors. Default raster loading now includes all nine base faces instead of omitting Roboto semibold, italic and bold italic. Font files must remain available and unchanged between preparation and raster export. Browser loading, actual glyph coverage, variant naming, rich spacing, and native compatibility remain separate requirements. These APIs are available in [renderer 0.8.0](https://github.com/OpenPresentation/opf-render/releases/tag/opf-render-v0.8.0), published against core 0.10.0 with Node 24. Prepared HarfBuzz shaping and variable-instance work remain separate drafts.\n\nThe renderer's optional font registry uses [Fontkit](https://github.com/foliojs/fontkit) to shape text and measure glyph advances from local font bytes. It does not discover system fonts or fetch fonts. The Node helper loads the renderer's bundled Roboto and Roboto Mono faces:\n\n```js\nimport { loadBundledFontRegistry } from '@openpresentation/opf-render/fonts-node';\nimport { renderSvg, svgToPng } from '@openpresentation/opf-render';\nimport { paginatePresentation } from '@openpresentation/opf/pagination';\nimport { toPptx } from '@openpresentation/opf-pptx';\n\nconst registry = await loadBundledFontRegistry();\nconst options = { textMeasurement: registry.textMeasurement };\n// Use design.fontScheme: 'roboto', or supply the document's actual font files.\nconst { presentation } = paginatePresentation(deck, options);\nconst svg = renderSvg(presentation, {\n ...options,\n embeddedFonts: registry.embeddedFonts,\n});\nconst png = await svgToPng(svg, {\n fontFiles: registry.fontFiles,\n useBundledFonts: false,\n loadSystemFonts: false,\n});\nconst pptx = await toPptx(presentation, options);\n```\n\n`createFontRegistry` from `@openpresentation/opf-render/fonts` accepts `{data: Uint8Array, weight, italic?, family?, postscriptName?, license?}` entries in Node or the browser. Weights are explicit, with 400 as the default. Supply each style that the document uses. Missing font families and unsupported glyphs fail with `OPFFontError`, including the source path where available. Collection fonts require a `postscriptName` selecting one face.\n\nAliases and fallback families are explicit choices:\n\n```js\nconst registry = createFontRegistry(faces, {\n aliases: { Aptos: 'Roboto', 'Aptos Display': 'Roboto' },\n fallbackFamily: 'Roboto',\n});\nconsole.log(registry.substitutions);\nregistry.clearSubstitutions(); // Start a fresh render's diagnostic collection.\n```\n\nAn available exact family takes precedence over aliases. The registry resolves a requested weight to the closest supplied weight, reports the substitution, and makes the resolved style available to rendering. Missing italic/upright styles fail instead of synthesizing an unmeasured style. `strictGlyphs: false` is an explicit escape hatch for hosts with their own glyph-fallback policy; it is unsuitable for fidelity verification.\n\nSVG embeds supplied fonts using data URIs and includes supplied license notices as metadata. The bundled loader carries the fonts' SIL Open Font License notices. For PNG/PDF, pass the same font files to the rasterizer; its native font loader does not depend on browser CSS font loading. In a browser, wait for `document.fonts.ready` before measuring or taking a screenshot. The editor playground loads and embeds bundled fonts and displays substitutions.\n\nCurrent `svgToPdf` output is image-only: each slide is rasterized and embedded as a PNG on a PDF page. Text is not selectable or searchable through PDF text objects, and shapes are not preserved as vectors. The accepted [selectable/vector PDF roadmap](plans/pdf-export.md) adds a separate backend and verification requirement, including permitted font embedding, Unicode extraction and shared placement. Raster PDF will remain an explicit compatibility mode when the verified vector mode becomes the default; no vector mode has shipped yet.\n\n## Office compatibility pack\n\n`loadOfficeFontRegistry` from `@openpresentation/opf-render/fonts-node` supplies regular, bold, italic, and bold italic faces of Carlito, Caladea, Arimo, Tinos, Cousine, and Gelasio, plus the base Roboto pack. Package versions are pinned and each face carries its distribution's license notice. `includeBaseFonts: false` omits Roboto. Loading never installs fonts into the operating system or downloads fonts at render time.\n\n```js\nconst registry = await loadOfficeFontRegistry({\n substitutionPolicy: 'metric', // Default for this loader; no visual fallback.\n});\nregistry.resolveFont({fontFamily: 'Calibri', fontWeight: 400});\n// requestedFamily: Calibri, resolvedFamily: Carlito, compatibility: metric\n```\n\n`createFontRegistry` defaults to `substitutionPolicy: 'none'`. Policies are `none`, `metric`, and `visual`; visual permits both curated tiers. An explicit `fallbackFamily` is a separate, reported `generic` fallback. Aliases are explicit visual substitutions and never establish metric compatibility. `resolveFont` reports exact resolutions as well; `substitutions` only collects changes. Resolution records include requested/resolved weights, italic, source path, and supporting upstream information where available.\n\n| Requested family | Bundled substitute | Current automatic tier |\n| --- | --- | --- |\n| Calibri | Carlito | Metric intent, standard 400/700 styles |\n| Cambria | Caladea | Fontconfig metric mapping; reference-version testing remains necessary |\n| Arial | Arimo | Metric, standard 400/700 styles |\n| Times New Roman | Tinos | Metric, standard 400/700 styles |\n| Courier New | Cousine | Metric, standard 400/700 styles |\n| Georgia | Gelasio | Visual: optional ligatures changed measured widths |\n| Calibri Light | Carlito | Visual: the bundle has no Carlito Light face |\n| Aptos / Aptos Display | Carlito, unless Source Sans 3 is supplied | Visual; no Aptos metric claim |\n\nUpstream evidence: [Carlito](https://github.com/googlefonts/carlito), [Fontconfig mappings](https://chromium.googlesource.com/external/fontconfig/+/refs/heads/main/conf.d/30-metric-aliases.conf), [Arimo](https://github.com/google/fonts/blob/main/ofl/arimo/DESCRIPTION.en_us.html), [Tinos](https://github.com/google/fonts/blob/main/ofl/tinos/DESCRIPTION.en_us.html), [Cousine](https://github.com/google/fonts/blob/main/apache/cousine/DESCRIPTION.en_us.html), and [Gelasio](https://github.com/SorkinType/Gelasio). Metric classification describes compatibility intent within the stated style scope, not universal identical output. Missing matching weights cannot silently qualify for the metric tier.\n\nThe exported `FONT_COMPATIBILITY` list also contains optional visual candidates and CJK families. Listing a candidate does not bundle it or imply complete character coverage. Liberation Sans Narrow is a separate legacy distribution with a different license history; it is not part of this bundle. Wingdings, Webdings, and Symbol require character mapping before substitution; an ordinary fallback fails with `font-encoding-required`. Missing math fonts require an explicit math-aware choice and fail with `math-font-required` instead of falling through to body text.\n\nDrawingML tokens such as `+mn-lt` resolve through the registry's explicit `themeFonts` option before substitution. Supply concrete `majorLatin`, `minorLatin`, and, where used, `majorEastAsia`, `minorEastAsia`, `majorComplexScript`, or `minorComplexScript` families. Missing theme mappings fail. This helper does not yet extract theme font records or embedded fonts from imported PPTX files.\n\n### Measured results and experimental fonts\n\n`node --import ./scripts/register-local-opf.mjs scripts/test-office-fonts.mjs --system` compares the bundle to reference fonts already installed in macOS's Supplemental directory. It does not redistribute reference fonts. The report records source-file hashes and individual shaped widths. Across four samples and four styles, Arimo/Arial, Tinos/Times New Roman, and Cousine/Courier New matched exactly on 48 runs. Gelasio/Georgia differed on ligature-containing runs, with a maximum difference of 2.0125%. Individual basic-Latin advances matched; disabling optional ligatures removed the tested difference. Until feature handling is consistent across outputs, the policy conservatively labels Gelasio approximate. Calibri and Cambria reference fonts were not available for this comparison.\n\n[Akasia](https://codeberg.org/bloudraad/akasia) remains experimental after the [v0.0.2 open-file assessment](evidence/akasia-assessment/README.md). All twelve styles match public upstream advance/kerning/ligature data, but 14 reference codepoints are missing and Black Italic decomposed accents expose a 0.421875px Fontkit/Chromium advance difference at size 32. Both Node runtimes retain the failure. This is not independent Aptos-binary or native Office verification; no mapping or bundled pack changes. `EXPERIMENTAL_FONT_CANDIDATES` records it separately. Aptos Narrow and Display remain outside that evidence.\n\nAn original OPF font project is technically feasible: independently designed or suitably open-licensed glyph outlines can be fitted to target advance widths, placement, vertical metrics, and shaping behavior. A successful font needs a reproducible source build, provenance, style/coverage tests, visual review, and cross-renderer conformance. Matching bounding boxes alone is insufficient: [OpenType horizontal metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hmtx) and [glyph positioning](https://learn.microsoft.com/en-us/typography/opentype/spec/gpos) jointly control text placement. Universal pixel identity across rasterizers is not the acceptance criterion; measured layout preservation over an explicit test matrix is.\n\n## Verification and remaining work\n\n`pnpm test:fonts` checks that editor and SVG geometry match, every native PPTX text box has the same coordinates and measured line breaks, and export uses the resolved family. It writes artifacts to `artifacts/fonts/`. A real-browser check of the same Roboto run measured 324.032 pixels versus the font engine's 324.170 pixels at 25 pixels, a difference of 0.138 pixels. These are measured tolerances, not a promise of pixel identity.\n\nPPTX currently records the resolved font family; it does not embed font binaries. PowerPoint still needs those fonts installed or may substitute them. Line height remains the shared 1.22 multiplier, rather than a complete ascent/descent model. Rich-text font overrides, mixed-script fallback and bidi layout, specialized payload internals, and native font embedding remain active fidelity work. Passing a width provider does not remove those limits.\n"
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
"slug": "handoff-2026-09-08",
|
|
71
71
|
"file": "docs/handoff-2026-09-08.md",
|
|
72
72
|
"title": "OpenPresentation ecosystem handoff \u2014 2026-09-08",
|
|
73
|
-
"markdown": "# OpenPresentation ecosystem handoff \u2014 2026-09-08\n\n## Current checkpoint \u2014 code integration merged; core/CLI release preparation\n\nCore [PR #54](https://github.com/OpenPresentation/opf/pull/54) merged as `8d9c9c80b788bbdc80e18ad2b6468f07b2e2321d`, tree-identical to reviewed `e8b520dd2c23e559a8d9affcfcb8772c8b8079b7`. Complete Linux coordinator `34441603873`, core CI `34441603829`, Windows/macOS CLI `34441603812` and Bugbot pass. [Portable final CI evidence](evidence/shared-code-ci-2026-09-09.json) records actual Chromium 153 code workflows, both seven-suite installed browser matrices, runtime/harness/package fingerprints and restored stale-evidence guards. The two Linux Node versions produce identical candidate tarball hashes. The separate corrected Windows installed/native evidence below remains authoritative for PowerPoint.\n\nContinue `codex/shared-code-release-20260909`. It prepares **unpublished core 0.9.0 and CLI 0.7.0**, versioned code/layout guidance and updated portable skills. The CLI-local changelog now includes the already published 0.6.0 history; no old version is republished. [Release gates and intended consumer versions](plans/shared-code-release.md) specify renderer/PPTX 0.7.0 and editor 0.6.0, with lockfile renewal and standalone checks after upstream publication. Complete core/CLI release checks and review before tagging. Keep `release-plan.json`, actual registry fixtures and all public deployments on the current verified published set until the new complete set exists.\n\nThe full repair, Auto arrange, metric/timeline/chart internals, font/multilingual/native-platform objective remains open. Preserve the exact previous package and deployment checkpoints below. New source behavior, actual installed browser interaction, schema validity and native text/raster scope remain separate claims.\n\n## Previous checkpoint \u2014 installed code workflows and coordinated CI prepared\n\nReview follow-up: renderer `b5a3722725338e8d964783e8b7f1f7b80ce28cd3` and converter `b4f4645cdaa2f5eff8a883f68533875d3b63f239` supersede the initial consumer commits below; editor remains `52e540b83e441892fd928e9f159bffbb29da5653`. A bounded installed probe found schema-valid controls emitted invalid XML and an unpaired surrogate became a replacement character. Both format boundaries now reject these with `invalid-code-text`, source path and UTF-16 offset while retaining the input. Each engine passes 132 source/metadata rejection cases and valid XML character boundaries on Node 20/24. This is separate from font coverage. [Renewed corrected-package evidence](evidence/shared-code-xml-boundary/summary.json) records passing continuous full source/tarball/browser/CLI/guard commands on both runtimes and renewed actual installed-native checks: all 24 original/saved/edited imports pass, and every native/SVG raster is byte-identical to the previously inspected valid-input fixture. The evidence below preserves the earlier checkpoint without relabeling its runtime hashes.\n\nCore PR #54's preceding `4f4a0b44584be945420f2b8d519f9417ee073e7d` passes complete Linux coordinator `34440657844`, core `34440657756`, Windows/macOS CLI `34440657695` and Bugbot. The latest CI pins now include the two character-preservation fixes and require a fresh run/review before merge. No version has been published.\n\nContinue `codex/shared-code-integration-20260909`. The four pushed source checkpoints below remain the tested runtime inputs; this checkpoint adds fresh installed-tarball code verification and pins coordinated CI to the exact consumer commits and reviewed code raster manifest. [Installed evidence](evidence/shared-code-installed/summary.json) binds all four local package hashes, lock integrity, runtime files, copied test harnesses and actual browser bundle inputs. Node 20.20.2 and 24.20.0 produce identical candidate tarballs and runtime bytes. They are private local preview packages, not published versions.\n\nThe installed checks execute 15 core code/composition tests, converter source/metadata guards, renderer measurement checks, and actual font-loaded offline renderer/editor workflows, including pointer/keyboard edits, CRLF, Tab/cancel, pagination floors, undo/redo and export/reimport. All seven prior packed browser suites also pass on both runtimes. Negative checks reject altered runtime bytes, incorrect lock integrity, external module links and loader environments, then restore the generated fixtures. CLI 69-command and standalone global/npx-style local-pack checks pass on both runtimes; Windows file-symlink privilege coverage remains in Unix CI.\n\nThe continuous Node 20 source/package wrapper passes. The first Node 24 wrapper passed its source checks but failed a new harness import; the corrected installed, tarball, browser, CLI and guard stages pass. The next harness iteration also needed to recognize esbuild's empty disabled-module stubs; it now accepts only zero-byte stubs with no imports and verifies every real bundle input stays inside the installed consumer. Neither failure changed a runtime or relaxed a product assertion. Renewed full Linux Node 20/24 CI and review remain the next gate.\n\nSeparate fresh registry installations pass the exact published package, seven browser and pinned fidelity suites on both runtimes, including 126 decks / 805 raster slides. These remain core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0. `release-plan.json`, registry fixture refs and public deployments stay on that published set; these registry checks do not claim the new code feature.\n\nReal PowerPoint also passes against the fresh installed candidate runtime: eight wide/portrait slides, all 24 original/saved/edited imports, exact source/metadata and save/reopen. Native comparisons pass on both Node versions; four text-after-tab targets are within 0.007031 point of accepted stops (0.02-point gate). New native preparation validates the candidate lock/runtime against the executed browser report before copying the versioned native harness. Representative installed SVG/native rasters were inspected; baselines and glyph appearance differ. This proves the documented editable text and source-preservation scope, not pixel equivalence, substitute-font compatibility or arbitrary Office round trips. No proprietary fonts were copied or embedded; unrelated user decks stay open.\n\nCoordinated core [PR #54](https://github.com/OpenPresentation/opf/pull/54) is open. Finish its Linux CI and review, then prepare new versions and publish in dependency order. Consumers need the released coordinated core before their standalone release checks. Add actual registry code workflows only after those releases exist, update the published plan/refs, and repeat public adoption and deployed E2E. A renewed seven-repository audit still found zero open PRs and security alerts before opening this milestone. The full repair/Auto arrange/font/multilingual/native-platform objective remains active.\n\n## Previous checkpoint \u2014 shared code consumers and native round trips verified locally\n\nContinue `codex/shared-code-integration-20260909`. All source work is pushed: core implementation `8d11fd650eb14fad3473b918713d9caa95321b83`, renderer `343ffea275e2eff478fc6a355551379897b748df`, converter `860e9476520659bf65822c945bf96b253cbe6c01`, editor `52e540b83e441892fd928e9f159bffbb29da5653`. Fetch these GitHub branches/commits; the local worktree paths are disposable. No new versions are published and no consumer PR has been opened yet; standalone consumer checks still need a released coordinated core. Existing published versions, release-plan refs and public deployments remain authoritative.\n\nRenderer and converter now consume accepted filename/language/body code geometry, preserve whitespace/tabs/empty lines and avoid another fitting pass. Unspecified code layouts use shared automatic composition; explicit presets retain their slots. Editor metadata/body targets, CRLF-preserving edits, literal Tab, cancel, pagination and undo are tested offline. Guarded native shape tags reconstruct complete code/source-boundary metadata; native text edits take precedence. Damaged/deleted/duplicate groups retain visible shapes with diagnostics. Native font theme, formatting, geometry and readability policy are not reconstructed.\n\n[Portable consumer evidence](evidence/shared-code-consumers/summary.json) records 28 passing existing/targeted consumer script runs and four actual new code-browser reports across Node 20.20.2/24.20.0. The full renderer, PPTX and editor suites and existing browser/playground workflows pass on both. All 43 changed code rasters were reproduced against ordinary registry renderer 0.6.0 and visually reviewed, with four full-resolution inspections; the other 762 hashes are unchanged. A legacy test needed to read nested SVG tspans to keep checking code typography; its 36-line coverage passes without weakening its count gate. No lockfile changed.\n\nActual PowerPoint `16.0.20326.20132`, Windows `26200.9445`, passes eight wide/portrait code slides, editable source/metadata, tags and save/reopen. All 24 original/saved/edited slide imports recover exact code objects, including CR/LF/CRLF, blank/final lines and soft wraps. Four native text-after-tab targets differ by at most 0.007031 point against the 0.02-point gate. Node 20/24 comparisons agree. The native and resvg fixtures use the same local Courier New regular/bold bytes; representative wide/portrait rasters were inspected. This is neither substitute-font verification nor pixel equivalence. The first harness attempts had a missing expected cell reference and omitted explicit raster font files; corrected checks were regenerated and rerun, with no tolerance relaxation. No user presentations were closed.\n\nNext: add the new code cases to installed-tarball verification and coordinated CI, pin the three consumer commits with the reviewed code raster manifest, finish full coordinated Node 20/24 checks/review, then prepare releases in dependency order. Keep registry checks pinned to the currently published set until new releases exist. The full repair/Auto arrange/font/multilingual/native-platform objective remains active. Latest main coordinator `34434340695` succeeds; the old failed notification `34433357130` was the now-fixed Linux browser precision assertion, not an Actions billing rejection.\n\n## Previous checkpoint \u2014 code composition/pagination integration in progress\n\nCore [PR #53](https://github.com/OpenPresentation/opf/pull/53) merged as `7c978f8b7ef0cc649d8452f8f1b829f36a5ae6e3`, tree-identical to reviewed `f90f7c5152d4075a2c184959164df655ba05fa19`. The explicit SVG `geometricPrecision` correction passes Linux Chromium `153.0.8010.12` on Node 20/24 with the original 0.1-reference-pixel tolerance. Complete coordinator `34433911033`, core CI `34433911144`, Windows/macOS CLI `34433911057` and Bugbot pass. The initial browser rounding failure below remains historical evidence, not an open billing issue. [Preserved Linux report](evidence/shared-code-browser-linux-2026-09-09.json) supplements the separate Edge report.\n\nContinue branch `codex/shared-code-integration-20260909`. Core now measures filename/language/body in automatic candidates, exposes `item.codeLayout` using rounded accepted boxes, aliases compatibility `item.text` to the body, reports internal paths under strict ancestors and labels the changed scoring `grid-score-v3`. Existing pagination now evaluates the complete code payload. Six new integration tests plus all 448 core tests and preservation suites pass on Node 20.20.2/24.20.0; core/CLI typechecks pass. This is unreleased source. Renderer, converter and editor integration and the complete coordinated/browser/native gates remain unfinished; no new package/version/ref or public deployment is advanced.\n\nA repeatable native probe generates eight cases with the candidate core API, actual registry converter's PptxGenJS vendor and local Courier New regular/bold. Real PowerPoint preserves all literal tabs/spaces, native edits and save/reopen. Text after tabs begins at accepted stops within 0.010544 point (0.02-point gate). Native text widths differ by up to 0.78629 point; this is measured drift, not pixel equivalence. Current registry imports are schema-valid but trim leading/trailing whitespace, and whitespace-only shapes become placeholders. [Native evidence](evidence/shared-code-native-2026-09-09.json) and [integration audit/reproduction](plans/shared-code-integration.md) separate these observations from unimplemented OPF export/reimport integration. Native comparison passes on Node 20/24; original/saved/edited imports each have text loss. Preserve the user's PowerPoint session and all older worktrees.\n\nThe full repair/Auto arrange/font/multilingual/native-platform objective remains active. Finish the shared code consumer milestone, then continue metric/timeline/chart internals and the remaining roadmap. All published release and deployment checkpoints below remain authoritative.\n\n## Previous checkpoint \u2014 standalone shared code layout candidate\n\nCore [PR #53](https://github.com/OpenPresentation/opf/pull/53) continues on `codex/shared-code-layout-20260909`. The candidate adds `layoutCode` and public types for filename/language/body parts, original text, requested/resolved styles, readability floors, exact UTF-16 source/line ranges, explicit text/tab segment placement and bounded internal allocation. Missing space or irreducible content stays visible in diagnostics; strict mode rejects all output. This is an unreleased standalone API. Composition, pagination, renderer and converter integration remain next work, and the actual published code defects below still reproduce.\n\nLocal Node 20.20.2/24.20.0 checks pass: nine new tests, all 442 core tests plus composition/nesting/pagination/data/rich-text/list suites, public root/focused declaration checks, eight actual-font wide/portrait cases and eight controlled browser segment cases. [Geometry evidence](evidence/shared-code-layout-2026-09-09.json) binds the source, built runtime, registry packages and font bytes. [Browser evidence](evidence/shared-code-browser-2026-09-09.json) binds the same geometry to Edge `152.0.4191.66`, exact Cousine regular/bold and a 0.1-reference-pixel advance/segment-position tolerance; literal tabs and whitespace survive and no external requests/page errors occur. Both reports are identical across the two Node runtimes. The browser harness is not integrated OPF renderer or native PowerPoint output.\n\nThe Edge probe found SVG ignores the intended CSS-only tab spacing, so each accepted line now carries explicit text/tab segment positions and widths. The controlled harness reuses those positions with preserved literal tab text. Initial coordinator `34433357130` passes source/tarball/registry checks and actual-font geometry, then fails both Node versions' new browser check because Linux Chromium's default glyph advances round to whole pixels. Core CI `34433357078`, Windows/macOS CLI `34433357095` and Bugbot pass. The follow-up explicitly requests SVG `text-rendering=\"geometricPrecision\"`, retains the 0.1-pixel tolerance and writes observations before asserting, so CI preserves future failures. Renewed local Node 20/24 Edge evidence passes; renewed Linux coordinator/review remain required. This was a measured browser failure, not a billing-limit rejection.\n\nComplete review and both CI matrices of this primitive, then consume it in scoring, rounded accepted composition boxes, strict ancestor diagnostics, SVG, editable PPTX and the editor/pagination workflow. Native tab placement and source-preserving reimport need real PowerPoint tests. All previously published versions, immutable release-plan refs and verified public deployments remain unchanged.\n\n## Previous checkpoint \u2014 public documentation verified; code layout baseline\n\nCore public-evidence [PR #52](https://github.com/OpenPresentation/opf/pull/52) merged as `74f39c68585586cb2eb41a4adc96e60eeab8e9da`, tree-identical to reviewed `8fc5000bc78f5e89e5464d7efdfb3b96ed9cea01`. Core Node 20/24 CI `34429765513`, full coordinator `34429765488` and Bugbot pass. All five published packages and all three public adoptions remain verified as recorded below; never republish their versions.\n\nWebsite [PR #22](https://github.com/Data-Advantage/openpresentation-site/pull/22) merged as `e61319537de1c4defc2368b07ad92207e31c655b`, tree-identical to reviewed `f4cc87d10aa22370d5f2d7b901e85fa9bfbff449`, after CI `34429916760`, Bugbot and six exact-preview workflows passed (20.5s). It advances only the core 0.8.0 documentation pin to reviewed `8fc5000bc78f5e89e5464d7efdfb3b96ed9cea01`; no runtime dependency, lockfile or npm version changed. READY production `dpl_HaHBwTk5BW7LACfpLYUtFH1S37PY` passes all six public workflows (18.7s). Published-version reference headings, full LLM text, the complete six-skill/647-file manifest and exact raw documentation hashes match. [Website reference evidence](evidence/site-published-reference-2026-09-09.json). The accurate changelog and prior website/gallery/application browser/native evidence remain separate records. A renewed seven-repository audit finds no open PRs or security alerts.\n\nContinue core branch `codex/shared-code-layout-20260909` from that merged GitHub checkpoint. The first new baseline is reproduced on Node 20.20.2 and 24.20.0 with actual registry core 0.8.0/renderer 0.6.0 and bundled font bytes: an oversized language label receives no overflow diagnostic; a second valid fixture loses its filename and significant whitespace in serialized SVG, including spaces inside a string literal. Input JSON is unchanged. [Source and evidence](evidence/code-layout-gap-2026-09-09.json) and `scripts/probe-code-layout-gap.mjs` preserve the exact failing behavior. The helper asserts a historical defect and must not be used as a future quality-success gate. No browser glyph or native code-export claim is made.\n\nImplement the shared code payload API and consume its accepted geometry in composition, preview and export before claiming this gap fixed. Cover source/filename/language, meaningful whitespace/newlines, wrapped-line mappings, explicit readability floors, requested/resolved styles and irreducible failure. Then continue other payload internals, bounded repair/Auto arrange and the full font/native-platform roadmap. No new software permission is required; preserve existing worktrees and the user's PowerPoint session.\n\n## Previous checkpoint \u2014 all three public adoptions verified\n\nCore [PR #51](https://github.com/OpenPresentation/opf/pull/51) merged as `c2f6aefd63d1c428ac35ea3da0d600e6c009b367`, tree-identical to reviewed `ce014f1`. Core Node 20/24 CI `34426024145`, complete coordinator `34426024128` and Bugbot pass. The release plan and immutable CI refs now use the published core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0 set. All individual publication and combined registry/browser/native evidence below is portable in GitHub. Never republish these versions. Continue core branch `codex/shared-quote-public-adoption-20260909` for deployment evidence and remaining work.\n\nWebsite [PR #21](https://github.com/Data-Advantage/openpresentation-site/pull/21) merged as `b0a7733cfa9a97fbb8bdb91f39bcd3075640005a`, tree-identical to reviewed `27dcdb25ef6db97db2342d106cf9b51bfd625f79`. CI `34425812307`, Bugbot and exact READY preview `dpl_2TPrYFLJuSmrmQduYeV3SDwp8xVG` pass; all six preview workflows pass (20.5s). Production `dpl_FXtMtDzuUddejNkmXv9R9SkAPMVg` is READY on that merge and serves both openpresentation.org aliases. All six public Edge workflows pass (18.8s), actual UTC npm dates and the full five-package showcase manifest agree, all downloads match hashes, and fourteen served JavaScript fingerprints are recorded. The [public changelog evidence](evidence/site-shared-quote-2026-09-09.json) and [visually inspected page](evidence/site-shared-quote-2026-09-09.png) are separate from native package raster observations. Temporary preview cookies stay in ignored local artifacts; Vercel protection remains unchanged.\n\nGallery [PR #24](https://github.com/Data-Advantage/pptx-gallery/pull/24) merged as `1403916aea3f50c7d39c965ec7136da6e4b7af32`, tree-identical to reviewed `8ed70324635c2e5fb69db5479cf13755d6635a0b`. It adopts the full set and immutable editor examples, regenerates the runtime/license manifest, and adds offline quote editing/readability/undo/export/reimport coverage. 106 unit tests, typecheck/build, all required catalog/production-markup/link checks and three local Edge workflows pass. Initial CI `34427001057` timed out after five seconds waiting for the initial preview. The reviewed fix gives only initial font/preview startup a bounded 20-second wait and uploads failure traces; renewed CI `34427426307`, Bugbot and all three exact-preview workflows pass (13.3s). READY production `dpl_ENk7dmxQ22Czhq18hKZujmcJaN9s` passes all three public workflows (10.4s) and all eight bundle/font/license/example hashes. No assertion or security alert was disabled.\n\npptx.dev [PR #29](https://github.com/Data-Advantage/pptx-dev/pull/29) merged as `482f769d4676b65ac16fe3fb4660aeaa03a77a44`, tree-identical to reviewed `ea89253de9a0e1400c297b75f295807f4a0b7239`. It adopts the four public libraries and core 0.8.0 schema/examples with otherwise unchanged dependencies. 598 tests, typecheck/build, SDK/CLI build gates, zero-advisory audit, Linux/Windows CI `34427524816`, Bugbot and all eight exact-preview workflows pass. Its actual browser download again passes native PowerPoint title/table editing, save/reopen and valid reimport; portable evidence in that PR binds the package lock, PowerPoint `16.0.20326.20132`, Windows build `26200.9445` and visually inspected raster.\n\nThe first public application run on READY deployment `dpl_6avWXN5F4L7WuqiWJG713M26oa9f` passes seven workflows but reports a lazy Monaco worker-download error when Author switches offline. Follow-up [PR #30](https://github.com/Data-Advantage/pptx-dev/pull/30) waits for a real JSON-schema diagnostic before that test goes offline and derives the canvas version marker from the installed editor package. It merged as `b9eefaac764c4a3ec009b17d363663f0c6cfe146`, tree-identical to reviewed `636da78c4b18f732530881cb09da3e5554bdcdd9`, after Linux/Windows CI `34428833533`, Bugbot and all eight exact-preview workflows passed. The readiness check also passed against the unchanged public runtime; no page-error assertion was suppressed.\n\nREADY production `dpl_F1LgvvbZ8QwcvCy8ZRnZ2WaunVDe` serves that follow-up merge and passes all eight public Edge workflows (29.4s). All [33 public font/license hashes](evidence/pptx-dev-shared-quote-fonts-2026-09-09.json) match actual renderer 0.6.0. [55 served JavaScript fingerprints](evidence/pptx-dev-shared-quote-bundles-2026-09-09.json) accompany installed-package toolkit proofs and the actual browser editor 0.5.0 marker; bundled assets are not asserted byte-identical to unbundled npm. The public Author download is byte-identical to the native-tested local/preview PPTX, SHA-256 `383512f28856d1b0d86ddd378d63b5a529e9928983743d9ebac72d99200c8ac4`. [Complete gallery/application evidence](evidence/gallery-app-shared-quote-2026-09-09.json) keeps the initial failure, reviewed fix, successful public run and native bridge separate. The original nine-PR backlog is resolved; the [fresh seven-repository audit](evidence/repository-adoption-audit-2026-09-09.json) finds zero open PRs and zero open security alerts.\n\nFinish review/merge of this core public-evidence checkpoint, then advance the website's `opfSource` documentation pin to the reviewed correction so its copied reference and LLM content use published-version wording. The release changelog itself is already accurate and live. Continue shared code-language/body measurement next, followed by metric/timeline/chart internals, bounded repair and Auto arrange, with the font/native-platform roadmap still required. No new package publication is needed for these documentation corrections.\n\nLocal setup: gallery has no own pnpm workspace file, so use `pnpm --ignore-workspace` when running its checkout nested under core artifacts. An initial gallery install touched the parent core lock; that unintended change was restored and gallery was reinstalled from its own lock. pptx.dev **does** have its own workspace policy: use its declared pnpm 11.1.3 normally, retaining `minimumReleaseAgeExclude: @openpresentation/*` and all existing supply-chain controls. Disabling its workspace discovery incorrectly bypasses that configuration and causes recent-release installation rejection. No OS settings or new user permissions are required. Preserve all old worktrees and unrelated local artifacts. Full repair/Auto arrange/font/multilingual/native-platform work remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 all five packages published; coordinated registry adoption\n\nCore [PR #50](https://github.com/OpenPresentation/opf/pull/50) merged as `2a39a15cbdd750699bf8e3adac8f78420baa1fa9`, tree-identical to reviewed `edf0806e8d88d941f1dc6762cf41d045c383ebbe`. Core CI `34421921795`, coordinator `34421921845`, Windows/macOS CLI `34421921853` and Bugbot pass. Continue core branch `codex/shared-quote-registry-adoption-20260909` for the complete release-plan/CI update and final combined checks.\n\nPPTX [PR #14](https://github.com/OpenPresentation/opf-pptx/pull/14) merged as `898e3c27919a2488e1e3d384168d6b25aae4bd5c`, tree-identical to reviewed `268fcb523924c95b453acbe407d1b5359ea5f485`. Linux/Windows Node 20/24 CI `34422214063`, Bugbot and trusted publication `34422584331` pass. PPTX 0.6.0 is published. Fresh Node 20/24 registry installations verify all 19 shipped files, signatures/provenance, the 126-deck/805-slide corpus and five browser suites. Twelve fresh registry export fixtures pass real Windows PowerPoint glyph containment, editable save/reopen and six valid reimports. Exact heading/body/footer order and repeated-line counts survive; first quote lines can become subtitles and OPF quote semantics are not reconstructed. Raster differences remain observations without a pixel-equivalence threshold. [Publication](evidence/pptx-060-publication-2026-09-09.json) and [native evidence](evidence/pptx-060-native-registry-2026-09-09.json) bind the package bytes and PowerPoint build `16.0.20326.20132` on Windows build `26200.9445`.\n\nEditor [PR #8](https://github.com/OpenPresentation/opf-editor/pull/8) merged as `dba5fe5e5580a4172c052132c4db5851d1decc4c`, tree-identical to reviewed `4d056532328bdfb765701880cb35ff87a0cc8829`. Node 20/24 CI `34424194308`, final Bugbot review and trusted publication `34424531044` pass. The review's JSON-key-order no-op concern uses the existing structural comparison and has regression coverage preserving redo. Editor 0.5.0 is published and fresh Node 20/24 registry verification passes: all 32 shipped files, 67 signatures/18 attestations including test dependencies, nine model/component suites and offline author/edit/paginate/export/reimport/undo. [Editor publication evidence](evidence/editor-050-publication-2026-09-09.json).\n\nAll five published successors are independently verified. `release-plan.json` and immutable CI refs now select core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0. Fresh isolated Node 20/24 combined source/tarball/registry checks pass: seven installed-browser suites, 230 assertions/eight trusted interactions per mode, four evidence guards, TypeScript/CLI checks, twelve pinned fidelity suites including 805 raster baselines, and the exact registry/native text bridge. Both registry consumers verify 64 signatures/15 attestations with zero advisories. [Coordinated evidence](evidence/shared-quote-coordinator-2026-09-09.json) records the tested core candidate `e635249` and published siblings; remote CI/review of this checkpoint remain gates. Never republish these versions. Use exact locally available runtimes Node `20.20.2`/`24.20.0` (floating `node@24` temporarily selected an unavailable version); no new software permission is required.\n\nThe three site adoption branches `codex/shared-quote-adoption-20260909` start from GitHub website main `e5dd771e6df3ddabb4544e8e435561b1dba178f3`, gallery main `b28d33564d7da2836f5c5d2e060ea461a7ac96bb` and pptx.dev **master** `b922f2f89fdb1e68f0e71a7f1df638be9c5314d4`. Website #20 has merged and its production deployment is `dpl_QKF3qGAtfGvizXu1sgPz43YReFdM`. Website [adoption PR #21](https://github.com/Data-Advantage/openpresentation-site/pull/21), head `27dcdb2`, updates the five releases, core source pin and registry showcase; production build, all registry dates and six local Edge workflows pass (8.0s). Preview/remote review/public verification remain gates. Gallery and pptx.dev adoption edits are next. All three public sites still use the previous complete set until deployments are verified. A fresh seven-repository audit found no open security alerts; the original nine-PR backlog remains resolved. The full repair/Auto arrange/font/native-platform objective remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 core, CLI and renderer published; converter checks\n\nCore [PR #49](https://github.com/OpenPresentation/opf/pull/49) merged as `4dc292fa93bee52320bafa3fd0f5b05a2dc0a283`, tree-identical to reviewed `95f9982036a01a52e080992abe4c4350c4b72354`. Core CI `34400722403`, coordinated source/tarball/registry/browser CI `34400722391`, Windows/macOS CLI CI `34400722421` and Bugbot pass. Both `opf-v0.8.0` and `cli-v0.6.0` are published through trusted workflows `34401446306` and `34402210003`; never republish them. Fresh npm installs on Node 20/24 verify registry integrities, signatures, provenance, core's 519 entries/public imports/thirteen quote tests, and CLI's exact bundled versions/global executable/npx six-skill installation/69 command checks. [Actual publication evidence](evidence/core-cli-publication-2026-09-09.json) keeps local candidate archives separate from registry artifacts.\n\nRenderer [PR #10](https://github.com/OpenPresentation/opf-render/pull/10) merged as `7fe9905ad2d8a224efeef51b4a22d0aff0c413fe`, tree-identical to reviewed `95c1eb92a8b3be0c8e63917180dcb447aed0cfb8`. Node 20/24 CI `34420837605`, Bugbot and trusted tag publication `34421186727` pass. Renderer 0.6.0 is published and verified from fresh npm installs on Node 20/24: 16 shipped files match the release commit, signatures/provenance verify, seven fidelity suites and all 805 raster baselines pass, and actual loaded-font quote/JPEG browser suites pass on Edge 152. [Renderer publication evidence](evidence/renderer-060-publication-2026-09-09.json).\n\nContinue portable branch `codex/shared-quote-release-20260909` in the converter/editor repositories. PPTX 0.6.0 preparation (`bb449f954699a3ce46ce9c2fc864875cd3894cf8`) now has an npm lock resolving core 0.8.0 and renderer 0.6.0; full local installed/browser/native checks are underway before opening its release PR. Editor 0.5.0 preparation (`dc3d81d3a1de06c9923476d808328e22ffa625b2`) still waits for converter publication before its final lock. Renew Windows PowerPoint evidence against the actual installed candidate bytes and registry predecessors; do not relabel the earlier source report.\n\n`release-plan.json` still intentionally describes the last complete published set. The [release gates](plans/shared-quote-release.md) give explicit verifier commands for the newly published core/CLI without prematurely advancing the full set. After all five successors are verified, update immutable refs and actual registry quote/raster checks, adopt the set on all three public sites, and repeat deployed bundle/browser/native checks. Website #20 remains independent active work. The full repair/Auto arrange/font/native-platform objective remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 installed browser CI merged; core/CLI release preparation\n\nCore [PR #48](https://github.com/OpenPresentation/opf/pull/48) merged as `abf32daa67543c30b29dbe813b17996456b90e34`, tree-identical to reviewed `565fbd2905006624c57a7c24c1b1fe62ac10ca4d`. Core Node 20/24 CI `34399051774`, complete coordinated source/tarball/registry CI `34399051732`, and Bugbot pass. CI now executes all seven installed-package browser suites against both tarballs and registry packages on Chromium 153, with 230 harness assertions and eight trusted input scenarios per run. All four stale/mutated-evidence guard cases pass on both runtimes. [Immutable CI evidence](evidence/installed-browser-ci-2026-09-09.json) complements the local Edge report below.\n\nContinue `codex/shared-quote-release-20260909`: it prepares **unpublished core 0.8.0 and CLI 0.6.0**, including the public type-tightening notice and versioned quote/pagination documentation. The [release gates and intended downstream versions](plans/shared-quote-release.md) keep actual registry refs unchanged until publication is verified. Complete release checks/review before tagging. Then update renderer, PPTX and editor dependencies/locks in order against published packages, renew exact package/browser/native evidence, and update the actual release plan and public deployments. The full objective remains active; releases do not complete bounded repair, Auto arrange or the font roadmap.\n\nProduction openpresentation.org now serves independent website #19 merge `31c84759c044480045a07f1e150149ecb2a423d3`, READY deployment `dpl_9q2ihhJXVxnWzcjizev6M2GSVMDS`. All six public Edge workflows pass (16.9s), live npm verifies the changelog dates/set, and all three showcase downloads match exact source/registry hashes. [Fresh production evidence](evidence/site-production-design-2026-09-09.json). Website #20 is still independent active work and is left untouched. A fresh seven-repository audit finds zero open Dependabot security alerts.\n\n## Previous checkpoint \u2014 shared quote core merged\n\nCore [PR #47](https://github.com/OpenPresentation/opf/pull/47) merged as `01e69ba1a6c3915778ede6aa12fb7ecda652ea42`, tree-identical to reviewed `c81b8b1cdf7004af186dce81c2b81cfb9a25be12`. Core Node 20/24 CI `34397006994`, complete coordinated source/tarball/registry CI `34397007028`, Windows/macOS CLI CI `34397007117`, and Bugbot pass. The [integration checkpoint](plans/shared-quote-integration.md) records quote allocation/scoring, pagination content-loss/readability fixes, downstream editor undo behavior, real Edge/PowerPoint evidence and the 41-slide raster review. Renderer, converter and editor retain their pinned `codex/shared-quote-integration-20260909` branches, with no downstream PRs yet. All changes remain unreleased; actual registry versions, release-plan refs and public deployments are unchanged by this milestone.\n\nCore branch `codex/installed-browser-checks-20260909` supplied the merged runner above. Keep the published registry baseline separate from the reviewed candidate footer changes. Native reimport retains editable quote text but loses quote structure/typography/readability policy; this remains an explicit gap. The full goal is active and substantially unfinished. No renewed permission is needed for already-authorized releases/deployments after their gates pass.\n\nThe [installed-browser report](evidence/installed-browser-2026-09-09.json) records four passing local runs: actual registry and candidate tarballs on Node 20/24 with Edge 152. Each runs seven suites, 230 harness assertions and eight trusted input scenarios, with zero external requests, writes or browser errors. Four evidence-rejection tests pass on both runtimes. Plain-to-rich conversion and bold formatting remain separate undo steps. This expands package/browser verification; it does not add native raster or public-deployment evidence.\n\nWebsite PR #20 (`claude/branch-icon-spacing-fixes-de47tz`, observed `6bf9b294a05a5943be77056f372c988266ad475b`) is separate active user work and was left untouched. Do not overwrite it during future package adoption. The original nine-PR backlog is resolved as recorded below.\n\n## Previous checkpoint \u2014 quote primitive merged; shared consumer integration next\n\nCore [PR #46](https://github.com/OpenPresentation/opf/pull/46) merged as `6d8df02940deec8f1fa89192d10576d6048de341`, tree-identical to reviewed `83e35649f91fc430c817c19492b0bf3d01212766`. Core Node 20/24 CI `34389245732`, coordinated source/registry CI `34389245620` (including the new real-font quote check), Windows/macOS CLI and packed-install CI `34389245733`, and Bugbot pass. The standalone quote API is now on main and remains unreleased. No package was republished or actual-release ref advanced.\n\nContinue from branch `codex/shared-quote-integration-20260909`. The [consumer integration audit](plans/shared-quote-integration.md) records exact downstream bases, candidate/accepted-fit reuse, strict descendant-path handling, atomic pagination, renderer and converter entrypoints, readability/rounding/source-map tests and the original requested-font provenance gap. Implement and verify the shared composition/preview/export path before claiming complete quote coverage, then continue code/metric/timeline/chart internals, bounded repair, Auto arrange and font/native fidelity. This is planned next work, not completed integration.\n\nA fresh audit after the original backlog resolution finds zero open Dependabot security alerts in all seven repositories. The only unrelated new PR is website [#19](https://github.com/Data-Advantage/openpresentation-site/pull/19), `claude/openpresentation-design-review-40j83i`, observed at `246aaa165d3dffb4c5e8b1a59376cfd4d47f760e`; it was recently updated and left untouched as independent work. All earlier PR dispositions and verified public deployments remain as recorded below. User authorization for pushes, PR updates, merges, tags, publication and deployments persists; remaining checks are release gates, not a request for renewed permission. The full goal stays active.\n\n## Previous checkpoint \u2014 standalone quote layout candidate; evidence checkpoint merged\n\nCore evidence [PR #45](https://github.com/OpenPresentation/opf/pull/45) merged as `24f64d67ef907282d73c25d04e80696879ab291f`, tree-identical to reviewed `b3659b0889414737ce82f552ea2753019bf9f1c5`. Core Node 20/24 CI `34387935655`, coordinated source/registry CI `34387935681`, Windows/macOS CLI and packed-install CI `34387935660`, and Bugbot pass. The failure email/budget questions and original PR backlog are resolved as recorded below.\n\nNext branch `codex/shared-quote-layout-20260909` adds standalone `layoutQuote` body/footer measurement with styles, source mappings and explicit internal failures. It is additive and unreleased: existing composition, preview, export and pagination are not switched to it. All 426 core tests plus preservation suites pass on Windows Node 20/24; six new quote cases and public declaration imports pass. The repeated actual-font wide/portrait check produces identical source/runtime/font-bound evidence on both runtimes. See [the implementation scope, report and remaining integration gates](plans/layout-repair.md#next-increments-and-acceptance-criteria). Finish CI/review before merging; connect all consumers before claiming shared accepted geometry or considering publication. The full deterministic repair, cross-surface workflow and font/native-fidelity goal remains active.\n\n## Previous checkpoint \u2014 original PR backlog resolved; YAML deployed; payload-fit gaps measured\n\npptx.dev [PR #28](https://github.com/Data-Advantage/pptx-dev/pull/28) merged as `b922f2f89fdb1e68f0e71a7f1df638be9c5314d4`, tree-identical to reviewed `dfdede29458bea1afb13f7f07d5e1079f9e9e515`. Linux/Windows application CI `34386017908`, artifact CI `34386017825` and Bugbot pass. Exact READY preview `dpl_6dXvANdwpkPgRPQ31oSKhrGqFHbx` passes eight Edge workflows (25.1s). Production `dpl_9B4YfiTrX3YCvK632T9qwtPTYpMs` is READY on that merge and serves www.pptx.dev, pptx.dev and the existing API/MCP aliases. All eight public Edge workflows pass (28.8s): author/import, quote preview/export, shared navigation, Inspector undo/download/reimport, offline Monaco, hostile SVG, installed-package toolkit and offline YAML/Markdown recovery. All 33 deployed font files and licenses still match actual registry renderer 0.5.1; [fresh font report](evidence/pptx-dev-yaml-fonts-2026-09-09.json). The previous native report remains bound to the adoption #25 download; this YAML deployment run does not add native raster-equivalence evidence.\n\nThe Data-Advantage budget increase restored CI execution. Two subsequent Linux attempts hit an external apt repository hash mismatch during Playwright dependency installation. The final pipeline uses the official matching Playwright 1.63.0 Noble image pinned to `sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27`; Linux executes all tests in it and Windows retains its native job. No checks were waived. All nine original PRs now have a disposition, and their feature/migration replacements are merged and publicly verified. Deferred TypeScript/Commander/Author-copy work remains explicit in issues, as recorded in [the backlog](pr-backlog-2026-09-09.md).\n\nCore [PR #44](https://github.com/OpenPresentation/opf/pull/44) merged as `94e4e019d28a1e16ac7e192b564596077dc2a6fa`, tree-identical to reviewed `8b09dd2757980fdae2471107a874d07bdf3a4fa0`. Coordinated Node 20/24 CI `34385371576`, core CI `34385371565`, Windows/macOS CLI and packed-install CI `34385371589`, and Bugbot pass. The earlier coordinated failure email was caused by a fixture copying the linker without its new package-manager helper; the final revision copies both and passes renewed checks. Windows linking uses junctions with checked target parents, and package-manager calls execute JavaScript entrypoints with literal arguments. No OS setting or elevated symlink privilege is required.\n\nThe next checkpoint, branch `codex/payload-fit-evidence-20260909`, corrects the unreleased explanation coverage to include incomplete code internals and adds a repeatable actual-registry probe. A schema-valid long quote footer produces no composition diagnostic but does produce renderer overflow; a long code label has measured advance 4200.68 pixels against 1128.8 available, with neither composition nor renderer reporting overflow. [Hash-bound evidence and next steps](plans/layout-repair.md#published-payload-fit-gaps) separate font-advance measurement from browser/native glyph behavior. These are priority inputs to shared internal measurement and bounded repair, not repaired layouts. The full layout/font goal remains active. No package was republished or publication ref advanced.\n\n## Previous checkpoint \u2014 layout explanations merged; Windows harness; YAML CI resumed\n\nCore [PR #43](https://github.com/OpenPresentation/opf/pull/43) merged as `1cc549183c6fd2e885f06410471e7142be69410a`, tree-identical to reviewed `d32b3eeedc0340ae3b8b3141a4677195346ddee5`. Node 20/24 core CI `34384042495`, coordinated source/registry CI `34384041071`, Windows/macOS CLI CI `34384041098` and Bugbot pass. Candidate explanations are now on main but remain unreleased. Full repair/font work remains open. Independent [PR #44](https://github.com/OpenPresentation/opf/pull/44), branch `codex/windows-test-harness-20260909`, fixes Windows junction/package-manager invocation and adds actual packed-install CI coverage; final combined-source checks and review remain gates.\n\nThe owner added $10 to the Data-Advantage GitHub Actions budget. YAML CI `34382820569` attempt 2 now starts and executes both Linux and Windows jobs. A missing exact-head Bugbot review was requested once; do not repeat while it is running. The initial billing failure below is retained as history, not a current reason to leave work idle. Finish the running checks/review and then merge/deploy PR #28 if clean.\n\nCore evidence PR #42 merged as `2c1cac7cbbc8d1afc9c26ca0b0fbdaa9b6ee3090`, tree-identical to reviewed `7b8def879883f3f8a42a9aff198620190470144c`, after Node 20/24 package CI `34381607903`, coordinated CI `34381607943` and Bugbot passed. The next source milestone is branch `codex/layout-repair-20260909`: opt-in candidate explanations preserve geometry and measurement calls and expose unsupported internal payload coverage. See [the layout plan and evidence](plans/layout-repair.md). This is unreleased source, not completed automatic repair; no package has been republished.\n\npptx.dev YAML PR #28 is now `e9f21ec007d3e382234c7bd8e062bc062fad471f`. The Escape fix passed both OS CI jobs `34381496268`; subsequent review found comment-only frontmatter, now fixed with parser-based empty-document handling and exact content/browser regression coverage. Latest local evidence: 598 tests, fresh production build and eight Edge workflows. Exact READY preview `dpl_CEw5yBz6cv622CbHvHfzNYvVqz5x` passes all eight workflows (25.8s). GitHub CI `34382820569` **did not start any steps**: both annotations report failed account payments or an insufficient spending limit. Leave the PR open and rerun Linux/Windows CI after GitHub Billing & plans is resolved; final review and public deployment remain gates. This is an infrastructure blocker, not a passing test result. Public pptx.dev remains the verified adoption #25 production below. Continue independent layout/font work while this gate is unavailable.\n\n## Latest checkpoint \u2014 public adoption verified; older PRs resolved or migrated\n\nRead [the current PR backlog and adoption checkpoint](pr-backlog-2026-09-09.md) before acting. Core #40/#13 and all three adoption PRs (website #17, gallery #23, pptx.dev #25) are merged. Exact READY production deployments pass public Edge workflows, including accurate published changelog, all six complete skills, all eight gallery bundle resources, 33 byte-matched renderer font files and offline editable export/reimport. Website #4's recovery #18 is also merged and verified live. The actual public pptx.dev export passes PowerPoint 16 native edit/save/reopen/reimport with a visually inspected raster. TypeScript #16, Commander #19 and the stale Author draft #6 are closed with explicit follow-up issues; js-yaml #20 is superseded by migration #28, with its current gate recorded above. Vercel duplicate comments are disabled and verified through the authenticated CLI; deployment checks and security alerts remain enabled. Schema-generator #13's public-type tightening is documented for a future release. No package was republished; the full layout/font/native-fidelity objective remains active.\n\n## Latest checkpoint \u2014 published content releases; expanded layout/font objective\n\nThe user's [updated objective](plans/ecosystem-objective-2026-09-09.md) supersedes the earlier goal. OPF must remain deterministic and independent of AI/model calls, keys, accounts and paid services. New explicit requirements include bounded layout candidate evaluation/repair with content/readability preservation, shared internal payload measurement, API/CLI/skills/canvas Auto arrange with preview/undo, and broad versioned open-font compatibility and native-platform evidence. The current releases do not complete that objective. Existing composition has heuristic auto-column scoring and explicit pagination; a full scored repair operation and its cross-surface workflow remain unfinished. Read `docs/font-fidelity.md` and the updated font roadmap before continuing that work. Width samples and baseline stability are not font/raster equivalence.\n\nRenderer **0.5.1** is published from `335ed01b2efbbb872894949f2ac0519e35651474`, workflow `34322801526`, npm timestamp `2026-09-09T07:14:52.658Z`. Renderer PR #9 corrected initially ineffective portrait fixtures; reviewed `12a3aa1dfb5196b3bcebe90d7e4ebb235627b0b4` merged as `d8696224e7a99618701e641ef7573ef394489885` after Node 20/24 CI `34323435532` and Bugbot. That test-only source is the new immutable verification/CI ref; the actual registry gitHead remains the publication merge. No renderer republish occurred.\n\nPPTX **0.5.2** is published from `383666b366b8c9b8ed8e7e72934d1d3fd0fb634d`, workflow `34370539691`, npm timestamp `2026-09-09T15:31:43.997Z`. PR #13 reviewed `22418c55b7e4140a7d325770510930f9e81b6b50` passed all Linux/Windows Node 20/24 jobs `34323665995` and renewed Bugbot; the quote-footer finding is resolved. npm processing finished before installation. Core PR #39 merged as `3d9321621486c95d06cc8153e2d30020c624f489` after renewed CI/review, closing the candidate linked-dependency gap.\n\nCore branch `codex/content-release-sync-20260909` updates the release plan, immutable CI refs and pinned registry content tests. Fresh full-set registry ecosystem/fidelity checks pass on Windows Node 20/24; all 805 renderer hashes remain unchanged. Registry signatures (64) and attestations (15) verify. Actual runtime/license payloads match release Git blobs exactly. The [published native report](native-content-release-2026-09-09.md) records actual-registry PowerPoint 16 checks on 19 feature slides, 24 imports and native object/edit preservation. A new registry/native quote verifier proves eight actual registry exports byte-identical to the native-tested wide/portrait files, with glyph separation, save/reopen and six valid imports on both runtimes. Native chart geometry and general text wrapping remain documented gaps. No proprietary fonts are distributed.\n\nDownstream adoption is saved on branch `codex/native-content-adoption-20260909` in each repository:\n\n- Website [PR #17](https://github.com/Data-Advantage/openpresentation-site/pull/17), `56069382de43c504e871cfc9d1e9cc88e83fb1ab`: accurate published changelog and registry showcase manifest. Build, registry dates, audit and four local Edge workflows pass.\n- Gallery [PR #23](https://github.com/Data-Advantage/pptx-gallery/pull/23), `58dd6957c7508d9459007cea4616e9c811f17383`: regenerated eight-resource registry editor/export bundle, full licenses and direct converter dependency. Builder validates/renders 854 documents; 106 tests, build, audit and both full local Edge workflows pass.\n- pptx.dev [PR #25](https://github.com/Data-Advantage/pptx-dev/pull/25), `a7f785da3c4fc0a819091efe617e0e46382531d1`: package adoption, installed-version font/preview labels and shared-hash navigation fix found by the new real wide/portrait quote E2E. Stale async loads and pending URL writes are guarded. 592 tests, typecheck, build, audit and six local Edge workflows pass.\n\nThese new site revisions are **not yet verified production deployments**. Next: complete core/site reviews and CI, verify exact previews, merge/deploy in order, verify public changelog, all bundle/font hashes and complete browser flows, and keep this handoff current. The previous production checkpoints below remain authoritative until replaced with observed READY deployments and public test evidence. The latest audit still finds zero open Dependabot security alerts across all seven repositories; four major compatibility reviews remain (core schema generator/TypeScript, pptx.dev Commander/js-yaml). Pending Vercel duplicate-comment sign-in and missing macOS native evidence remain explicit gaps, not reasons to stop independent layout/font work. Never republish completed versions.\n\n## Latest checkpoint \u2014 quote review fixes and renderer 0.5.1 release gate\n\nRenderer [PR #8](https://github.com/OpenPresentation/opf-render/pull/8), branch `codex/quote-footer-layout-20260909`, saves prepared **unpublished 0.5.1** at `e2d2a0260e7d83831d70e15bd17d173a1600ef0f`. A valid converter review finding also reproduced in the renderer: long quote text could cover its attribution/source footer. Reserving footer space before fitting fixes eight long-quote cases on wide/portrait canvases; two oversized cases retain diagnostics and strict rejection. Full local Node 20/24 suites preserve all 126-deck/805-slide raster hashes. Real Edge tests load the exact four open font faces used for measurement and verify eight actual SVG glyph layouts; renderer CI and publication now execute this browser suite and the existing JPEG suite. Exact-head CI `34322142453` and Bugbot pass. Fresh packed verification, merge/tree check, tag and trusted publication remain gates.\n\nCore [PR #39](https://github.com/OpenPresentation/opf/pull/39) addresses its valid review finding by rejecting candidate dependencies resolved outside installed `node_modules` and linked/non-registry lock records. The new same-version linked-dependency regression passes on Node 20/24. Converter [PR #13](https://github.com/OpenPresentation/opf-pptx/pull/13) has the corresponding quote fix and extended packed/browser checks in progress; its older `422f1e39e643cbb1c23260f0c9ddef7a3c6ec722` evidence is a historical candidate, not verification of subsequent edits. Next order: renderer 0.5.1 publication, converter registry dependency/lock update, refreshed packed/browser/native checks and review, then PPTX 0.5.2 publication and fresh registry/downstream adoption. No previously released package should be republished. Native chart geometry and general text wrapping remain measured fidelity gaps; the full goal remains active.\n\n## Latest checkpoint \u2014 Monaco deployed; native fixes in 0.5.2 review\n\npptx.dev PR #24 merged as `1e13e469bda257df197c79bb10948c62c3ea6535`, tree-identical to reviewed `3d372dde1c4e19fd7d59e39fba4c18c1349f5355`. Linux/Windows CI `34319106580` and Bugbot pass. All five Edge workflows pass on exact final preview `dpl_GQbmdzmR2vFzsCo48F5pN3cNaTYr` (18.4s) and public production `dpl_9LnTh1yQ9JzhUcmhBe7vbmsYZtEh` (20.4s), READY on that merge. This includes actual same-origin Monaco 0.56 JSON workers, schema diagnostics, offline completion and recovery. Dependabot #18 is closed as superseded; temporary preview browser credentials were removed. No OPF package was republished.\n\nCore PR #38 merged as `204cd42278992b58f6468a98e1eb168e3531df40` from reviewed `8910b9052c6c6854284d2e9e25506798f0a670d6`, after Node 20/24 coordinated CI `34319241226`, package CI `34319241251` and Bugbot. It preserves the 19-slide published baseline and the substantial native differences found by visual inspection.\n\nPPTX [PR #13](https://github.com/OpenPresentation/opf-pptx/pull/13), branch `codex/native-content-fidelity-20260909`, saves **unpublished 0.5.2** candidate `422f1e39e643cbb1c23260f0c9ddef7a3c6ec722`. Metrics, quotes, code and timelines now follow renderer geometry/shared core text fitting; native chart labels use readable theme text. Quote source/attribution survives, and timelines use editable native lines/markers. Full local Node 20/24 converter/corpus/styled suites pass; the new regression compares 34 text lines to actual renderer typography/geometry at two dimensions and checks chart contrast/native markers. Final candidate PowerPoint 16 checks pass for all 19 edits, 24 reimports, three native tables, one native chart and one picture. Hash-bound [candidate reports/contact sheets](https://github.com/OpenPresentation/opf-pptx/blob/422f1e39e643cbb1c23260f0c9ddef7a3c6ec722/docs/native-content-candidate.md) show the visual improvements; chart ticks/plot geometry and general scalar-text wrapping remain open.\n\nCore branch `codex/native-candidate-comparison-20260909` adds explicit candidate comparison with full runtime/vendor/package/lock hashes and matching registry core/renderer requirements. The default remains registry-only; missing/changed candidate evidence is rejected. The published baseline is retained unchanged. Next gates: review PPTX #13, complete Linux/Windows Node 20/24 packed/browser/native checks, address findings, finalize unreleased changelog/version, merge/tag/publish 0.5.2 only after gates pass, then fresh registry/native verification and downstream adoption. Do not republish 0.5.1 or advance actual-release verification refs early. Continue remaining native fidelity and dependency reviews (core schema generator/TypeScript, pptx.dev Commander/js-yaml), plus the previously pending Vercel duplicate-comment sign-in. The full goal remains active.\n\n## Latest checkpoint \u2014 expanded native coverage exposes export gaps\n\nCore PR #37 merged as `13fc56e0b1af8b24ca93ddd871cb6308bc4b77fa`, tree-identical to reviewed `f3f057cbcfa720e12eb3f46eca0cf8c7e5d9384b`, after Node 20/24 package/coordinated CI `34317326511` / `34317326517` and Bugbot.\n\nThe new [19-slide native feature matrix](native-feature-matrix-2026-09-09.md) uses actual registry core 0.7.0/render 0.5.0/PPTX 0.5.1, published examples and controlled local Calibri. PowerPoint 16 passes open/edit/save/reopen for every slide; Node 20/24 validates all 24 original/native-saved/native-edited deck imports and every native edit. Three native tables, one Office chart and one picture are verified. Hash-bound reports and all contact sheets are portable in `docs/evidence/native-feature-matrix/`.\n\nNative raster review found unresolved metric sizing, quote/source/attribution layout, flattened timeline, code panel styling, chart-axis contrast/ticks and text wrapping differences. Zero schema/converter errors did not detect them. The goal is active and these are priority export fixes; do not claim native equivalence from the successful file/edit checks. No package was republished.\n\npptx.dev Monaco migration is saved in [PR #24](https://github.com/Data-Advantage/pptx-dev/pull/24), branch `codex/monaco-worker-migration-20260909`. Supported worker exports and the new JSON API fix Dependabot #18's build failure. Initial application commit `e9d089462580f2d5c8f1b5d83b283b215a9b0a71` passes Linux/Windows CI `34318174221`, Bugbot, 592 tests and a 214-page build. All five Edge tests pass on exact preview `dpl_FGHxNYV6GDpReD9Ez8KYXNF59xno`; the final test-only revision fixes offline readiness/completion timing and requires renewed review/CI before merge, exact deployment verification and closing #18. Production remains the previously verified `fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a` until that gate completes.\n\nContinue other explicit dependency compatibility reviews and pending Vercel duplicate-comment configuration as recorded below. The previously requested browser passkey sign-in remains separate from working CLI deployment access.\n\n## Latest checkpoint \u2014 pptx.dev browser workflow deployed and native-verified\n\npptx.dev PR #22 merged as `fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a`, tree-identical to reviewed `c18b1fdd5d5e5e2e10b259957ba678def598a2ac`. Linux/Windows CI `34316394032` and renewed Bugbot pass; all three review threads are resolved. Production `dpl_4bQ6pSkG7kiCw8FNAPuEx9RtumTS` is READY on that merge and serves www.pptx.dev, pptx.dev and existing API/MCP aliases. All four actual public Edge tests pass: Inspector author/preview/source undo/redo/share/reimport/offline PPTX export; Author canvas edit/tab changes/undo/redo/source exports/copy/local requests/PPTX/undoable import/malformed-file recovery; hostile shared/imported document DOM checks; exact installed-package toolkit proofs. Local verification includes 592 tests in 60 files and all four starter decks (17 slides) rendered/exported/reimported with the published packages. Starter layout/theme aliases were migrated to resolvable public catalog IDs.\n\nAll 33 deployed font files and full licenses match the actual installed registry renderer, verified by the repeatable `node scripts/verify-deployed-browser-fonts.mjs <registry-consumer> https://www.pptx.dev` on Node 20/24. [Font hashes](evidence/pptx-dev-browser/fonts.json) and [production-native report](evidence/pptx-dev-browser/native-production.json) are portable. The actual Author production download has SHA-256 `383512f28856d1b0d86ddd378d63b5a529e9928983743d9ebac72d99200c8ac4`, identical to the final local candidate fixture. PowerPoint 16 exposes native editable title/table, preserves the title edit through save/reopen, rasterizes the slide and produces a schema-valid reimport with the table intact. The native-saved file hash is `9b1941ae5ae36653790375d28028b20695a197d54811cb6369b528ec9cbb1ffb`. See the [merged workflow and repeatable scripts](https://github.com/Data-Advantage/pptx-dev/blob/fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a/docs/browser-opf-workflow.md). This remains targeted native editability evidence, not broad raster equivalence. Hosted account/AI calls and the legacy Decoder/API are separate from the tested free browser workflow.\n\nThe same continuation merged pptx.dev action maintenance PR #23 as `5c862d23c39f330e4fccdaa5a45bd053ae86a1dc`: real wheel/sdist artifact upload/download, exact filename/hash comparison and Twine checks pass on Linux/Windows in `34315591982`; full application CI `34315591938` and Bugbot also pass. Immutable upload 7.0.1/download 8.0.1 retain ZIP behavior and fatal digest checks. The missing `sdk/mcp` publisher was retired, and Dependabot PRs #16/#17 closed as superseded. PPTX parser lock PR #12 merged as `9c0abf1d6f296a62322fac7c4ef5c91d025a3705`, tree-identical to tested `5016051b45bb35a5d02591cc720a82dda95eae6e`, after all four Linux/Windows Node 20/24 jobs `34307685202`. It matches the parser graph already used by fresh 0.5.1 consumers. No packages were republished, and actual release verification refs stay unchanged.\n\nCore handoff PR #36 merged as `0bc35c24c5011af81ecb5d9a93626d901331fde2` after coordinated CI `34315154485`, package CI `34315154475` and Bugbot. A fresh audit of all seven repositories finds zero open Dependabot security alerts without dismissals. Remaining separate dependency reviews: core TypeScript #16 and schema-generator #13; pptx.dev Monaco #18, Commander #19 and js-yaml #20. Vercel redundant-comment settings still await the previously requested browser passkey sign-in; project protection/security notifications have not been weakened. Preserve unrelated website PR #4 and pptx.dev PR #6. Continue broader native/UX verification and the remaining compatibility reviews; the overall goal is active, not complete or blocked.\n\n## Previous checkpoint \u2014 gallery PowerPoint deployed; pptx.dev browser workflow in review\n\nThis section supersedes pending states in the historical checkpoints below. The goal remains active. No completed package release was republished.\n\nCore PR #35 merged as `264457659c7149e4e8684fab4c0b895388ad2344`, from reviewed `875ea7da4112ec10bb7549c7ca8ebd5053c9b304`, after coordinated CI `34313022598`, package CI `34313022602` and Bugbot. The release plan pins editor example source `eea4b3763026820798cb7e611f01574681c1742c` independently from actual published package verification refs. Registry gallery builds preserve runtime bytes and include complete linked license notices as an eighth hashed resource.\n\nGallery PR #22 merged as `73737dc5c50632c29234d7e5df2704e28a3ba121`, from reviewed `dae38538cb7c90090a9072247af16c8833a84b4f`, after CI `34313026600` and Bugbot. Production `dpl_7bZ8BZqmFTG57NNA48VEMrCVd4np` is READY on that exact merge. All eight deployed resources and registry integrities verify; both real Edge tests pass against https://www.pptx.gallery, including offline author/import, weighted layout, inline edit/undo/redo, OPF download, editable PowerPoint download/native merged-table XML, conversion and UI reimport equality, undo and redo. The full browser PowerPoint workflow is now public.\n\npptx.dev [PR #22](https://github.com/Data-Advantage/pptx-dev/pull/22), branch `codex/published-browser-workflow-20260909`, saves candidate `4c4e6cfb02abc8af62023674e65619dee27efca5`. Inspector and Author now use the published renderer for actual previews and the published converter for local PowerPoint export with shared font measurements. Author adds the published editable canvas and persistent validated undo session across source/preview tabs, plus local OPF/PPTX preview/import as one undoable replacement. These manual operations require no account or paid service; hosted APIs/AI remain separate. No Convex backend code changes.\n\nLocal Windows Node 24 checks pass: 591 tests in 59 files, typecheck, full 214-page production build, zero-advisory audit and all three real Edge E2E tests. Author testing caught and fixed offline canvas remounts losing their font registry. The final test verifies offline tab changes, inline edits, undo/redo, active-draft export, merged-table native XML, browser/Node import equality, import undo/redo and malformed-file recovery. Its actual downloaded file passes PowerPoint 16 native text edit/save/reopen/raster/reimport with one native table. Source SHA-256 `9744aed5c41da31187bb5a98dabec3ee3b0edacb9fe263f698039cb0a7c3b84b`; native-saved SHA-256 `cda33e17824abb265db10f02138797f3c6c36eb0e7231e0b93f3c2587fd928ee`. See [portable workflow/native evidence](https://github.com/Data-Advantage/pptx-dev/blob/4c4e6cfb02abc8af62023674e65619dee27efca5/docs/browser-opf-workflow.md) and its repeatable scripts. This one-slide native fixture does not establish broad raster equivalence.\n\nNext gates: review current pptx.dev PR #22, complete Linux/Windows CI and Vercel preview checks, address findings, merge/deploy, then run all three tests against the actual public deployment and update this handoff. Production pptx.dev remains on `f1f9e700ae2648467b36baf22b3393a216b78780` until then. Continue the remaining dependency-major/action reviews and broader native comparisons. Vercel duplicate-comment settings still await the user's previously requested passkey sign-in; no notification setting or security alert was suppressed. Preserve unrelated website PR #4 and pptx.dev PR #6. All source checkpoints are on GitHub; local generated artifacts are optional evidence, not required resume inputs.\n\n## Historical browser PowerPoint workflow candidate \u2014 September 9 UTC\n\nEditor PR #7 has now merged as `ccd42d9276f7e47a545205469dc2665e03c28a8f`, tree-identical to the fixed candidate below, after Node 20/24 CI `34312112286` and renewed Bugbot. Core PR #35 and gallery PR #22 save adoption. Their initial CI/reviews pass; a final linked-license packaging update requires renewed checks before merging/deployment. The registry builder now preserves runtime JavaScript untouched and includes full package notices plus pinned upstream license supplements in the eighth hashed resource, `playground.js.LEGAL.txt`. Both local gallery browser tests pass with this final packaging, including offline PowerPoint export/reimport. No notification settings were changed; the Vercel browser still requires the previously requested passkey sign-in.\n\nCore deployment checkpoint PR #34 merged as `4fcc217287ddf6f8ec3c6f4f351d9b1d4534df69` after package/coordinated CI and Bugbot. New work is saved in editor [PR #7](https://github.com/OpenPresentation/opf-editor/pull/7), branch `codex/browser-pptx-transfer-20260909`, candidate `eea4b3763026820798cb7e611f01574681c1742c`. Its playground accepts local PPTX in the existing preview/import dialog and exports editable PowerPoint using the preview's text measurements. Import remains a validated undoable change; export commits the active canvas draft and displays conversion notes. No package version changes or republishing are needed.\n\nLocal Node 20/24 full editor suites and offline-after-load Edge E2E pass. Actual downloaded PPTX contains native text and a merged table; PowerPoint 16 permits editing, save/reopen and valid reimport with its native table preserved. The portable [browser/native report and scripts](https://github.com/OpenPresentation/opf-editor/blob/eea4b3763026820798cb7e611f01574681c1742c/docs/browser-pptx-workflow.md) distinguish this targeted fixture from broad raster equivalence. Review caught the converted-image JSON size edge case; the fix retains schema/nesting/item validation and adds a real compressed-image regression on both runtimes. Renewed upstream CI/review must pass before merge.\n\nCore branch `codex/gallery-pptx-workflow-20260909` separates immutable example source refs from published package verification refs and includes the new host module in registry-only gallery builds. Gallery branch `codex/browser-pptx-transfer-20260909` carries regenerated assets and extends actual E2E to offline PowerPoint download/native-table inspection/reimport/undo. Its 106 unit tests, typecheck, audit and full build pass; the initial bundle passes both browser tests. Final fix bundle review, production deployment and public E2E remain gates. These candidate controls are not yet the deployed gallery. The main pptx.dev published renderer/editor/exporter integration and remaining dependency reviews remain open.\n\n## Latest checkpoint \u2014 all three 0.5.1 production deployments verified\n\nThis section supersedes pending merge/deployment states below. Core PR #33 merged as `188c32333a903fed9058d781caaaae4cd10b3d28`, from reviewed `1950afe9804d7e4f7037372d24e8b9d8b864f5fb`. Package CI `34309217317`, coordinated Node 20/24 CI `34309217315` and Bugbot pass. The release plan and immutable PPTX verification ref now select published 0.5.1 at `f7f30082da3568a4f911d42493ffc75c77dd4e14`. No package was republished.\n\n- openpresentation.org PR #16: merge `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f`, production `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm`. All four public Edge tests pass: accurate changelog, six skill files and installer command, mobile layout and exact showcase downloads.\n- pptx.gallery PR #21: reviewed `93f9a720aa6ebe3b48a981f52012f809f6f8cd40`, merge `2ea8ccb75b9a6d9b64a93e6ec36d78100c044f8a`. CI `34309168015` and Bugbot pass. Production `dpl_5cooy8gD6MrZXu5vDDXNNxkBpFjN` is READY on that merge. The deployed manifest and all seven asset hashes verify; both real Edge tests pass, including JSON authoring, preview, inline edit/undo/redo, OPF download and reimport.\n- pptx.dev PR #21: reviewed `be44a1230dd17eb8ae8ca3889304aa2fb084b49c`, merge `f1f9e700ae2648467b36baf22b3393a216b78780`. Linux/Windows CI `34309892749` and Bugbot pass. Production `dpl_wkf6fiWCeyW1E562zHFU9RXwM92X` is READY on that merge. Both real Edge tests pass against https://www.pptx.dev: anonymous inspector author/preview/edit/undo/redo/OPF-download/shared-reimport and the toolkit's exact installed package versions plus render/edit/export proofs. Local self-hosted pages no longer request unavailable Vercel analytics; production analytics remains enabled. Its legacy direct PptxGenJS generator still requires the scoped image-size removal override.\n\nRemaining dependency reviews are explicit: pptx.dev Monaco #18 fails CI because 0.56 changes worker export paths; Commander #19 requires Node >=22.12 while its CLI promises Node 20; js-yaml #20 fails codec/API tests because version 5 changes exports. Evidence and migration requirements are posted on each PR; none was blindly merged. Core TypeScript #16 and schema-generator #13 remain separate compatibility reviews. pptx.dev actions #16/#17 and its obsolete missing-sdk/mcp publish workflow still need maintenance. Vercel duplicate comments await the previously requested browser passkey sign-in; no alert or notification setting has been suppressed.\n\nNext implementation milestone: free browser PPTX import/export and repeatable complete author/import \u2192 preview/layout \u2192 edit/undo \u2192 export/reimport coverage, then integration of the published renderer/editor/exporter in pptx.dev's main flow. The gallery currently exposes OPF transfer only, and pptx.dev's main preview/export still use custom implementations. Targeted native PowerPoint edit/save/reopen/raster evidence covers three slides, not broad native raster equivalence. Preserve unrelated website PR #4 and pptx.dev PR #6. Resume sources from the GitHub merge commits above; generated local artifacts are not required checkpoints.\n\n## September 9 UTC \u2014 PPTX 0.5.1 published and registry/native checks verified\n\nWebsite PR #16 is merged as `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f` after CI `34308522871` and Bugbot. Production `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm` is READY on that commit; all four real Edge production tests pass, including the accurate 0.5.1 changelog, skill installer, mobile layout and unchanged showcase downloads. Gallery PR #21 and pptx.dev PR #21 save their 0.5.1 adoption candidates and await full review/deployment checks. pptx.dev's clean install, audit, 591 tests and typecheck pass; its legacy direct PptxGenJS generator still requires the scoped removal override.\n\nCore PR #33 records the new registry refs and native evidence. Its first coordinated run exposed a local preview-packer omission: the staging builder copied only `dist`, excluding declared vendored runtime/license files. The corrected builder copies every declared literal package payload, validates staging paths and uses portable Windows npm invocation. Fresh local preview packs and consumer checks now pass on Node 20/24; renewed coordinated CI is required before merging. Published tarballs and both registry fidelity suites passed independently.\n\n**PPTX security patch checkpoint:** PR #11 merged as `f7f30082da3568a4f911d42493ffc75c77dd4e14`, tree-identical to reviewed `13d404ab4a8f029622957c8afe53f339c4a6949f`. All four Linux/Windows Node 20/24 jobs in CI `34307186304` and Bugbot pass, including fresh packed installs and real Chromium suites. Actual local Edge and PowerPoint tests pass. Tag `opf-pptx-v0.5.1` triggered successful trusted publication `34307645895`; npm records publication at `2026-09-09T03:37:39.613Z`. Fresh Node 20/24 five-package installs and full pinned registry fidelity suites pass. The consumer audits clean, with 64 registry signatures and 15 attestations verified. The actual registry tarball also passes native PowerPoint edit/save/reopen/reimport and the unchanged three-slide raster measurements. Do not publish again. See the portable [PPTX evidence](https://github.com/OpenPresentation/opf-pptx/blob/f7f30082da3568a4f911d42493ffc75c77dd4e14/docs/security-0.5.1.md). The patch removes the unused parser from ordinary npm installations by shipping unmodified, licensed and hash-verified upstream runtime code. Vendored upstream advisory review remains separate from npm's installed-graph audit.\n\nCore documentation PR #32 merged as `900613f14ab7ed2d57aa6246f6ce7c3519cad39d`. Supported Node 20 types PR #31 merged as `47190652f436e80fa5dd0a947bc1ceeb6db709ff` after all package/coordinated/Windows/macOS checks. Website action PRs #12/#13 merged as `227088da3f2aa48724d53df8625d0dad7d052005` and `174fc0d953526454848da07db9013ab35ceb5e5e` after renewed combined CI. Gallery PR #20 merged as `d01cbfc24855d5e41adc6e092841554196a3e9cb` after full CI `34307438488`; action PRs #16/#17/#18 were closed as superseded. A false-positive missing-pnpm-tag finding was resolved with the live annotated tag and successful exact-head CI evidence. Open Dependabot security alerts were refreshed across all seven repositories: zero, without dismissals. This does not change historical published package graphs.\n\n**Production checkpoint:** pptx.dev PR #15 is now merged as `06ebef116608110fa88ac98cbcd6fe8ea6ad76f1`. Reviewed head `aad6b5ce29dc4ed5b03a7982121ff4a7ea4543bc` passed Linux/Windows CI `34304827786`, Bugbot, an actual adapter build and deployed preview E2E. Production `dpl_638zt5oC7grWNTYEXL3XM4cFMbGE` is READY on the merge, with www.pptx.dev, pptx.dev and API/MCP aliases. The real Edge inspector author/preview/edit/undo/redo/OPF-download/shared-reimport test passes on https://www.pptx.dev. GitHub open Dependabot alerts are now zero without dismissals. SDK/CLI source builds use the single audited root workspace, and standalone output remains supported outside Vercel. This is the first adoption baseline; the main custom preview/export still needs replacement.\n\nCore PR #30 merged as `6967b037c934c665e312086e232545cb71753bcf` after Node 20/24 package/coordinated checks, full Windows/macOS core/CLI checks and Bugbot. Renderer maintenance PR #7 merged as `ad59248ad8dbf11e519c1ba75e95d6d3fa4a39ed`; editor maintenance PR #6 merged as `aeb2871ba381bf97656e58418b5271ec764ed0d5`, both with Node 20/24 CI and Bugbot. These add grouped weekly Dependabot, unfiltered audits and reviewed immutable actions; no package version changed or was republished. Existing published verification refs remain correct.\n\nVercel duplicate bot-comment configuration requires a browser passkey sign-in. CLI authentication and production deployment work. The user was asked to complete the open login page when convenient; no notification/security setting has been changed yet. Continue unaffected work. pptx.dev action PRs #16/#17 remain for individual review; the obsolete missing-sdk/mcp publishing workflow also needs maintenance. Existing PPTX 0.5.0 keeps its older dependency graph; 0.5.1 fixes ordinary new installations without the incompatible downgrade.\n\nThis checkpoint supersedes the historical pending states below. Core PR #29 merged as `e49278514ca3f98b0e14e47ceaa4315adada00b1`. All five intended package releases and the six-skill npx installer remain published; do not republish them. The release plan already pins their actual immutable release commits.\n\nWebsite security PR #15 merged as `2f1b5428a06079e70f3ad67653768fa55a8c463c`; production `dpl_Bdxr6u3j6rdEjp9fJP9RbLp4f2pS` is READY on that commit. All four public-site browser tests pass, including the accurate changelog and complete skill files/clipboard command. Gallery security PR #19 merged as `7d661c074a73dc81487a713a2af040246e62a097`; production `dpl_3GbDE7grPv3zCyCzfzhgAKuCuTsg` is READY on that commit. Both public gallery browser tests pass, including exact bundle hashes and OPF author/edit/undo/download/reimport. Both upgrades passed CI and Bugbot before merging. See [September 9 security evidence](security-2026-09-09.md).\n\npptx.dev PR #15's earlier standalone/adapter packaging failure is resolved: ordinary builds preserve standalone self-hosting, while Vercel uses its adapter output. The exact final commit, full CI and production evidence are recorded above. Its primary renderer/exporter adoption remains incomplete.\n\nCore security work is on `codex/security-policy-20260909`: patched js-yaml/esbuild, unfiltered CI audit, consistent LF text checkouts, reviewed immutable actions in the portability workflow, and routine Node-type major-update policy. TypeScript 7 PR #16 remains deferred because of tsup declaration-bundler incompatibility. Schema-generator PR #13 changes the exported ContentPayload type and remains separate for consumer compatibility review; the security fix does not depend on it. Node 26 types PR #15 is closed because declarations must match the minimum Node 20 runtime. No security alert is dismissed.\n\nRemaining work: merge the updated core 0.5.1 verification refs and deploy downstream adoption/changelog (website PR #16 is prepared with verified npm dates and unchanged showcase bytes); finish application action PRs and redundant Vercel comments; free browser PPTX import/export controls and repeatable complete workflows; actual published renderer/editor/exporter integration in pptx.dev; broader native PowerPoint comparisons. Preserve website PR #4 and pptx.dev PR #6. Native PowerPoint evidence remains three targeted slides, not broad pixel equivalence.\n\n## Latest checkpoint \u2014 deployed installer and gallery; pptx.dev integration underway\n\nUpdate: pptx.dev [draft PR #15](https://github.com/Data-Advantage/pptx-dev/pull/15) saves the compatibility/security candidate at `08fab78`. A fresh Windows Node 24 frozen installation passes 588 tests, typecheck and compile build. Its root audit is now zero: an exact-version pnpm override removes PptxGenJS 4.0.1's unused image-size dependency, and an installed regression test confirms it cannot resolve while text/table/image export works. This does not patch image-size or change existing public npm packages; separate SDK lockfiles still have an esbuild advisory. Browser testing subsequently found missing-auth configuration assumptions on public inspector pages; fixes and repeatable E2E are being added before deployment. Core pnpm/action-setup PR #12 merged as `e43e263795c824b0fe6bddc4b37deb612a196766` after renewed combined Node 20/24 checks. Gallery GitHub open security alerts have now reached zero without dismissals.\n\nThis section supersedes pending states in the historical checkpoints below. All five intended packages are published: core 0.7.0, renderer 0.5.0, PPTX 0.5.0, editor 0.4.0 and CLI 0.5.0. Do not republish them. Core PR #28 merged as `51445f03b70bed896e53e346f2fb7b2c04293b94`, with renewed review and package/coordinated/Windows/macOS checks. The release plan and published CLI test source are pinned to the actual CLI release commit, independently of future local CLI development.\n\nWebsite PR #14 merged as `49d30c6a25d684e7f1a3cbdca44ec565e1b9472f`; production deployment `dpl_6iQrr4VNh9Mu61DvdJXJ6Xs9c8Rc` serves that commit. Four production browser tests pass: accurate releases, mobile layout, exact showcase downloads, and the copied npx installer command plus every served skill file hash. The changelog and supported skill installation documentation are live. Preserve unrelated website PR #4.\n\nGallery PR #15 merged as `188758dcde7248f70ceeb44238ba5986be4c91d0`; production deployment `dpl_6WQqZZAeS28tDCxuMLa6dJeWw7oo` serves that commit. Two production browser tests verify the seven deployed bundle files against their hashes and a real JSON-author/preview/inline-edit/undo/redo/OPF-download/reimport flow, including a styled merged table. Local verification passes 106 unit tests, a 1,925-page build, catalog checks and zero npm advisories. Browser PPTX import/export controls are still absent from the editor example: do not claim this OPF workflow proves PPTX UI coverage.\n\nCore Dependabot checkout PR #10 merged as `84c757e55234ea8c8706ba8717717d7a4c541005`; setup-node PR #11 merged as `414c40fb6bfa2f7f33714ddb949f43a7f8ce70d4`. Both received migration review and passing Node 20/24 checks. pnpm/action-setup PR #12 has a resolved adjacent-line merge conflict and renewed CI pending on `9f10ef3`. TypeScript 7 PR #16 remains unmerged: explicit Node globals fix its first error, but tsup's declaration bundler fails against the removed legacy TypeScript API. Failure evidence is posted on the PR. Review other majors individually; security alerts remain visible.\n\npptx.dev work is on Data-Advantage/pptx-dev branch `codex/published-ecosystem-adoption-20260908`, based on `4a1fc69af09addd37fe62500a1ab8b50fa63cbf8`. It upgrades the four OPF dependencies to the published set, updates vulnerable dependencies and replaces AI canaries with compatible stable releases. Its 575 existing tests, typecheck and compile build passed, followed by a new installed-package edit/undo/redo/export proof. Running the formerly Unix-only standalone playground tests then exposed unbounded palette traversal of recursive groups; the fix and regression coverage are in progress. No pptx.dev candidate is deployed yet. Its primary preview/export still use custom implementations, so dependency upgrades alone do not establish complete adoption. Preserve unrelated PR #6. Remaining high image-size advisories have no published patched version; do not dismiss them or claim a clean audit. SDK lockfile maintenance, application E2E, free browser PPTX workflows and broader native fidelity verification remain open.\n\n## Earlier checkpoint \u2014 CLI installer published; website changelog deployed\n\nCLI 0.5.0 is published. PR #27 merged as `7a2845f45bd7c6f48312b07100851c0ee29a9d1c`, tree-identical to `fcaa85fb50c06dd737f9e71419f3b9a40618184d`, after Linux/Windows/macOS Node 20/24 checks and successful renewed review. Tag `cli-v0.5.0` and trusted publish run `34261574915` succeeded. Registry gitHead/provenance and fresh global/npx-style installs pass on Windows Node 20/24. Do not republish CLI 0.5.0 or any earlier completed package release.\n\nThe supported command is `npx @openpresentation/cli@latest skills install`. It installs all six bundled skills, preserves project instructions and refuses to overwrite customized skills. Core follow-up branch `codex/cli-release-adoption-20260908` advances the release plan to CLI 0.5.0 and adds repeatable published CLI installer checks. Fresh complete registry ecosystem tests pass on Node 20/24.\n\nWebsite PR #11 merged as `c1cbbbb4e91911392612a157155441b523f187dc`. Vercel production deployment `dpl_ApPs9yCN43U6zVsGEkSmfQ6tFRTM` serves that commit. All three browser checks pass against https://www.openpresentation.org: published history and package links, mobile layout, and exact OPF/SVG/PPTX download hashes. The separate website changelog task is deployed. Follow-up branch `codex/skills-installer-site-20260908` adds the newly published CLI 0.5.0, installer quickstart and its immutable documentation snapshot. Four local browser tests pass, including actual command copying and every file hash in all six served skills. Follow-up CI/review/deployment remain pending.\n\nGallery adoption is in progress on `codex/published-ecosystem-adoption-20260908` in Data-Advantage/pptx-gallery. Targeted dependency updates pass 106 existing tests, a 1,925-page build and a zero-advisory audit. Its regenerated registry bundle uses core 0.7/render 0.5/PPTX 0.5/editor 0.4/CLI 0.5 and validates/renders 854 documents. Final bundle checks, browser workflows and deployment remain pending. The existing editor example lacks browser PPTX import/export controls; addressing that gap is separate from updating the bundle. pptx.dev adoption/security and the six core major Dependabot PRs remain open. Historical sections below are superseded by these checkpoints.\n\n## Windows continuation checkpoint \u2014 registry releases complete\n\nRenderer 0.5.0, PPTX 0.5.0 and editor 0.4.0 are all published with provenance after exact-head checks and review. Their published merge refs are recorded in `release-plan.json`; do not republish them, core 0.7.0 or CLI 0.4.0. Fresh full-set registry ecosystem and pinned rendering/export fidelity checks pass on Windows Node 20/24, including the unchanged 805-slide raster baseline. Registry editor pointer/keyboard typing, formatting and undo pass in Edge. Registry PPTX passes native PowerPoint open/edit/save/reopen/reimport and two targeted border raster assertions; broad pixel equivalence is not established.\n\nCore PR #26 merged as `533b53cd7db3cf58e9ebf5fbd987741323ea2699` after full Node 20/24 coordinated CI, package CI and successful Bugbot review on `3d1c2bbc7c68a3f74f68232d1ae320a4f41ccdfd`; merged tree is identical. The complete release plan and immutable CI refs are on main.\n\nContinue CLI 0.5.0 on `codex/skills-installer-20260908`, [PR #27](https://github.com/OpenPresentation/opf/pull/27). All six skills are bundled with safe install/update/status, offline packed installation and Windows checks. It remains unpublished. Review found overly strict ancestor-symlink rejection; canonical parent resolution now supports linked project directories while rejecting linked skill destinations, and macOS CI was added. Wait for final CI/review before release.\n\nMain website work is on Data-Advantage/openpresentation-site branch `codex/published-ecosystem-adoption-20260908`, [PR #11](https://github.com/Data-Advantage/openpresentation-site/pull/11), initial head `83ccb57`. It adds the accurate published changelog, core 0.7.0 and complete registry showcase, targeted security fixes with zero current local audit advisories, grouped Dependabot and browser/download CI. Local build and three browser tests pass; deployment remains pending. Gallery and pptx.dev adoption/security/full workflow E2E remain open. See [current Windows evidence](evidence-2026-09-08-windows.md). Historical checkpoints below are superseded where they describe unpublished downstream packages or stale lockfiles.\n\nThe user requested an immediate stop and remote checkpoint to move computers. Resume from GitHub; do not depend on the old computer's temporary worktrees, tarballs, logs, or browser state. The goal is ongoing, not completed or blocked. User authorization covers commits, pushes, PR creation/updates/merges, tags and npm publication. Recheck CI/reviews and exact commits before releases. Do not bulk-merge unrelated Dependabot PRs. No subagents unless requested.\n\n## Goal\n\nMake OpenPresentation a polished, reliable, fully open presentation ecosystem for people and AI agents: authoring JSON, dynamic layout, browser preview, intuitive WYSIWYG editing and editable PowerPoint export. Keep core free, open source, provider-neutral and usable without a paid service or AI account. Publish compatible packages in dependency order and prove the workflow using clean registry installations. Advance presets, rich text, tables, media, fonts and layout fidelity. Evaluate schema support, browser interactions, rendering and native PowerPoint compatibility separately. Public sites must showcase the same installable tools users receive.\n\nEarlier PR #8 reconciliation and the missing core 0.4.0 changelog entry are already handled; do not repeat them. The NEW public website changelog request below remains open.\n\n## Portable checkout map\n\nClone sibling repositories so the core ecosystem scripts can find their sources. Read each repository's AGENTS.md. Avoid resetting any existing user checkout.\n\n| Repository | Branch to resume | Remote checkpoint |\n| --- | --- | --- |\n| OpenPresentation/opf | codex/styled-table-release-sync-20260908 | [PR #26](https://github.com/OpenPresentation/opf/pull/26), this handoff and verification scripts |\n| OpenPresentation/opf-render | codex/styled-table-cells-20260908 | [PR #6](https://github.com/OpenPresentation/opf-render/pull/6), head `b47bba101ab78dc226d9ff848bb8622e3a0109e1` |\n| OpenPresentation/opf-pptx | codex/styled-table-cells-20260908 | [PR #10](https://github.com/OpenPresentation/opf-pptx/pull/10), head prefix `a0e9d14` |\n| OpenPresentation/opf-editor | codex/styled-table-cells-20260908 | [PR #5](https://github.com/OpenPresentation/opf-editor/pull/5), head prefix `21449a7` |\n| Data-Advantage/pptx-gallery | main | Deployed merge `12fcf77399cb6ae21d3bfcea5cfafb37c3323b79`, PR #14 |\n| Data-Advantage/openpresentation-site | main | Deployed merge `280a616701320cd1ca8d2484cf166fb91d882137`, PR #10 |\n| Data-Advantage/pptx-dev | master | Newly added integration scope; old checkout `4a1fc69af09addd37fe62500a1ab8b50fa63cbf8`, not yet audited or modified |\n\nUse fresh fetches to resolve full commit IDs/current PR states. The old machine's primary downstream checkouts were deliberately left untouched and lag origin; release work happened in temporary clones. Gallery's primary checkout contains a pre-existing untracked `pnpm-workspace.yaml`; not part of this work. Temporary PPTX `artifacts/` contains generated evidence/build outputs; source fixtures and builders are committed and can regenerate it.\n\n## Already published \u2014 do not republish\n\nCore PR #25 merged as `21e4cfca617ddfebeee85f79b09c35b2e82637e1`, with tree identical to reviewed head `e71f7c3d1b9a99bf210d038ceac613f72f41f894`.\n\n- `@openpresentation/opf@0.7.0`, tag `opf-v0.7.0`, successful publish run `34243706990`.\n- `@openpresentation/cli@0.4.0`, tag `cli-v0.4.0`, successful publish run `34244109903`.\n- Both registry gitHeads match the merge and have SLSA provenance. Tarball integrities matched the tested candidates. A fresh global CLI registry install reported CLI 0.4/core 0.7 and validated the styled fixture.\n- Core 404 tests, CLI 70 command checks, packed package checks, strict installed TypeScript fixture and coordinated Node20/24 CI passed before release. These results do not establish that later downstream edits are verified.\n\nCore 0.7 introduces strict styled cells `{value, style?, rowSpan?, colSpan?}` with covered positions `null`; merge ownership validation; shared anchor geometry and `.value` editing paths; padding, alignment and spanning row heights; pagination that keeps connected vertical merges. Equal column widths and content-fit row heights remain limitations for importing native arbitrary table geometry.\n\n## Immediate release gates\n\n### Renderer PR #6: draft, not published\n\nVersion 0.5.0, core dependency ^0.7.0, registry lockfile current. Prior head `b63bd0e` passed standalone Node20/24 full suites and unchanged 126-deck/805-slide raster baseline against actual registry core 0.7. A fresh candidate consumer passed and matched runtime bytes.\n\nBugbot review on that head completed neutral with two findings. They must be assessed, not treated as a passing review:\n\n1. Claimed vertical alignment was ignored. Core `layoutTable` already offsets `cell.textBox.y`; scalar and rich renderer paths consume that box. New baseline assertions prove top/middle/bottom movement. Do not add a second offset.\n2. Valid finding: default neighboring edges could cover custom borders. Follow-up commits `dabf91b` and `80ae8bb` render defaults before explicit edges and remove overlapping default segments, including zero-width/transparent/dashed edges and partial merge boundaries. Legacy tables without custom borders retain their prior rendering path.\n\nThe final head is `b47bba1`, including the regenerated tracked `dist/svg.js`. On the identical source/build from `80ae8bb`, focused styled-table regressions pass on Node20/24 and renderer syntax checks pass. Full suite/raster baseline, renewed CI/review, and a new packed candidate remain required. The previous tarball integrity is obsolete. Review threads were left open for evidence-based follow-up. PR description records these distinctions.\n\nNext: run checks on exact head, address review findings, mark ready, wait for CI/review, merge with exact-head protection, verify merged tree, tag `opf-render-v0.5.0`, monitor trusted npm publish, verify registry version/gitHead/provenance/integrity against the new tested tarball.\n\n### PPTX PR #10 and editor PR #5: draft release preparation\n\nTheir implementation and final README/CHANGELOG/package.json version changes are pushed. **Lockfiles still describe the preceding dependency set.** This is an explicit unfinished checkpoint because renderer 0.5.0 does not exist on npm yet. Do not merge or publish these drafts as-is.\n\nAfter renderer publication, regenerate lockfiles from the registry and run clean installs. PPTX targets 0.5.0; editor targets 0.4.0. Both require core ^0.7.0 and renderer ^0.5.0 (optional peer, exact 0.5.0 development dependency). Use Node20 and Node24; prior toolchain was npm11.16/pnpm10.33.2. Run standalone suites **without NODE_OPTIONS source loaders**. Pack final versions, test fresh consumers, verify runtime bytes, update PR evidence, review/merge and tag in dependency order. Inspect workflows for exact tag patterns (PPTX `opf-pptx-v0.5.0`; verify editor pattern before tagging).\n\nPPTX implementation preserves supported native fills/alpha, margins, alignments, borders/dashes, rich runs and dense merges; conditional styles resolve band/edge/corner precedence and archive-local line references. Malformed merges retain source text with diagnostics. Different border segments on merge continuations preserve anchor style with a diagnostic. Native arbitrary row/column geometry, effects and PowerPoint raster parity are incomplete.\n\nEditor uses `.value` inline paths, preserves styles/spans, rejects invalid structure, supports rich promotion/selection formatting and undo; covered slots have no editable target. Browser and model fixtures are committed.\n\n### Core release sync: draft\n\nThis branch adds installed-package styled editor browser fixture generation to `scripts/test-packed-ecosystem.mjs` and styled renderer/PPTX tests to `scripts/test-registry-fidelity.mjs`. The latter clears NODE_OPTIONS in child tests to prevent a source loader invalidating registry claims. Syntax and diff checks pass; final full registry checks are pending.\n\n`release-plan.json` still describes the previous complete published set. Update it and `.github/workflows/ecosystem-ci.yml` immutable downstream refs only after all new packages are available. Use the published core merge for core fixtures. Run fresh Node20/24 registry ecosystem/fidelity checks and actual installed-package browser interactions. Do not conflate generated browser bundles with executed UI tests.\n\nUseful core commands: `pnpm test:registry-ecosystem`, `pnpm test:registry-fidelity`, `pnpm prepare:gallery:registry`, `pnpm build:showcase:registry`. Read their scripts and release plan for arguments/setup. Source-coordinated tests may use `scripts/register-local-opf.mjs`; registry verification must not.\n\n## Evidence and public integration status\n\nBefore the final renderer border follow-up, actual Edge browser interaction verified:\n\n- PPTX native styled import: 12 checks; rich import: 20 cases; conditional table styles: 11 checks.\n- Editor legacy rich fixture: 14 checks. Styled fixture: 37 passing assertions including repeated style/undo checks, real Roboto/Roboto Mono loading, double-click/keyboard edits, empty values, scalar promotion, Bold, partial selection/Italic, cancellation, merged glyph containment and undo.\n- These were coordinated development builds; final installed-registry browser runs still remain. No styled-table native Keynote inspection was completed. No native PowerPoint raster equivalence claim is supported.\n\nGallery and main site were deployed and verified against the PREVIOUS full package set: core 0.6, renderer 0.4, PPTX 0.4, editor 0.3, CLI 0.3. Prior checks covered 854 gallery documents, 593 site routes, six skills and 584 raw resources. They do not yet showcase the full new styled release set. Update assets, docs and deployments only after final registry verification, then test actual public workflows. `pptx.dev` has not yet been assessed.\n\n## New user priorities to address after resume\n\n1. **Dependabot overload.** Inspect notices/open PRs across all relevant repos. Screenshot examples from core: TypeScript 5.9.3\u21927.0.2 (#16), @types/node20\u219226 (#15), Biome (#14), json-schema-to-typescript15\u219216 (#13), pnpm/action-setup5\u21926 (#12), setup-node4\u21927 and checkout4\u21927 (#10). These are examples, not a current authoritative PR inventory. Evaluate runtime/schema/build compatibility, security significance and CI; safely group/schedule updates and reduce redundant reviewer notifications where appropriate. Preserve security visibility. Do not blindly merge major upgrades or suppress useful alerts.\n2. **Public changelog.** Update https://www.openpresentation.org/changelog from actual published release contents and dates. Clearly distinguish live npm releases from upcoming drafts and ensure site deployment is verified. The earlier core CHANGELOG0.4 fix does not satisfy this request.\n3. **Easy skill installation.** User wants a supported npx-style skill installer like Convex's AI-file installation experience, documented and suggested in relevant CLI output. Current `docs/agent-skills.md` instructs copying entire self-contained folders; do not assume an npx installer already exists. Research current official Convex/installer guidance before choosing syntax, implement/test actual clean-project installation and sensible updates across supported agents, keep provider-neutral, document it on site/repo, and add concise actionable CLI guidance. Avoid overwriting existing user skill configuration without an explicit update flow. Six OPF skill entrypoints: author, layout, presets, edit, export, inspect.\n4. **Real downstream adoption and E2E quality.** Audit openpresentation.org, pptx.gallery and Data-Advantage/pptx-dev (https://pptx.dev) for exact dependencies/bundles and user workflows. Adopt the tested published set and assess quality visually and functionally. Inventory existing model, package, browser and E2E tests; automate missing end-to-end paths from author/import through layout/preview, editing/undo, export and reimport. Test deployment versions and editable native output; report native-app fidelity gaps explicitly. Do not answer \u201Call integrated\u201D or \u201CE2E complete\u201D from the existing unit/corpus evidence alone.\n\nContinue in reviewable milestones under existing authorization. Keep a concise evidence trail, preserve user work and stop relying on old-machine absolute paths.\n"
|
|
73
|
+
"markdown": "# OpenPresentation ecosystem handoff \u2014 2026-09-08\n\nRuntime update (September 10): use **Node 24 only** for new development and verification; see [migration instructions](migrations/node24.md). Historical Node 20/24 results and commands below describe prior checkpoints. Keep distinct browser/OS/native gates and the existing Office recovery prerequisite.\n\n## Current checkpoint \u2014 source wrap-up and Mac/Windows continuation\n\nUse the [September 10 wrap-up](handoff-2026-09-10-wrap-up.md) and its two copy/paste goal prompts. The integration is recorded in core PR #61, renderer #12, PPTX #16 and editor #11 on `codex/shared-metric-integration-20260910`; fetch GitHub main and verify the linked merge/check state. Coordinated candidate CI, accepted-line cross-package tests, binary-evidence checking and cleared native heading recovery are corrected. The 805-slide shared-text baseline is reviewed for regression stability with explicit quality limitations. Published versions and historical registry refs remain unchanged.\n\nThe Mac agent owns the broader project and subsequent releases/public adoption. The Windows agent owns bounded real-PowerPoint checks and portable native evidence. No Office calls were resumed in the wrap-up. Full native text/chart editing, metric tab/ink and font/layout quality gates remain open. Historical \"zero open PRs\" and \"no integration PR\" statements below describe their dated checkpoints, not the current wrap-up.\n\n## Previous checkpoint \u2014 native chart save/reopen confirmed; Excel activation isolated\n\nContinue `codex/shared-metric-integration-20260910`. Product runtime checkpoints remain unchanged from the shared-outline milestone below. PPTX test/doc source advances through indexed COM collections `0e3b58fb7a91a6f29f52ce2338f2cc91b4f803dc` to bounded chart workers and a prepared native text verifier `bf1c7bd8db21bfc400e92a7bf4275f4e3048c7e4`. [Portable native resume evidence](evidence/native-resume/README.md) preserves successes, failures, the user's Office warning and exact artifacts. No package, baseline, release ref or deployment changed.\n\nAfter the user dismissed a dialog, PowerPoint responded and opened/saved/reopened eight real charts. All 16 original/native-saved data imports and eight native raster pairs agree exactly. The first embedded workbook edit returned, but activating the second stalled; no edited deck/reimport gate completed. The user supplied PowerPoint's warning about an open Excel dialog or cell-edit mode. Only the two owned stuck helper processes were terminated; Office/user files were not closed and generated-file cleanup completion is unknown.\n\nThe chart harness now requires one explicit `-EditSlide`, records progress, runs a hidden helper with a 45-second deadline and never automatically retries. Dummy-process success/failure/literal-argument/timeout checks pass without Office. Node 20/24 generate 24 accepted-text fixtures each with identical bytes/geometry. All four exact Carlito faces pass temporary Windows registration/removal. Full native text execution and fresh metric COM checks remain queued; their preparation is not native fidelity evidence. Prior metric tab/portrait ink counterexamples stay open.\n\nNo Office calls were started after asking the user to resolve Excel's modal/editing state. Once cleared, make one controlled bounded check and retain any failure. The refreshed seven-repository audit finds no open PRs or security alerts; separately merged roadmap PR #59 and coordinated main CI run `34500983790` are complete, while these integration branches remain unpublished. Preserve concurrent font/PDF/SVG roadmap edits. All broader layout/font/review/release/registry/public gates remain active.\n\n## Previous checkpoint \u2014 shared outline placement and editable heading recovery; native/release gates open\n\nContinue `codex/shared-metric-integration-20260910`. Core source `ac0c99fcdc03dd7cd7ac9840be841b903a941f77`, renderer `53e6f5fb5911ebecbfcdfef341bbb53e33c1f7a5`, PPTX `12c6cee646a5c8760dcbf964b722a108d21687b4` and editor `0e8a1676c780919ceefe8b9972372f364e542944` implement the [shared vector-outline placement contract](plans/text-placement.md). [Portable evidence](evidence/text-placement/README.md) binds 598 artifacts (11,455,177 bytes). No package versions, release refs, public deployments or accepted baselines changed.\n\nOptional font-registry outlines now feed `grid-score-v6` fitting and scoring for headings and scalar/rich text. Shared `textRasterPadding` defaults to one scaled reference pixel; all consumers reuse accepted origins. Both Node 20.20.2/24.20.0 pass 482 core tests, preservation/type/lint/example checks, 99 font combinations and 48 renderer contract cases. All 24 actual Edge paint cases now pass the unchanged 0.1-pixel mask gate. Zero-clearance controls on both runtimes reproduce exactly the four previous portrait/right title failures; vector-path versus text-mode evidence remains separate.\n\nPPTX exports 144 editable lines across 24 cases per runtime and preserves complete title/subtitle/tag roles through guarded native tags. Current native text wins; malformed/incomplete/ambiguous sets fall back without restoring stale source. Full PPTX reruns pass after updating an obsolete full-cell assertion to accepted line geometry; the earlier failures remain in evidence. Full editor checks, twelve shared geometry/edit/undo/pagination cases, seven browser suites and 46 rich canvas checks pass per runtime. All 2,415 before/current image hashes verify; all 805 default estimated rasters are unchanged. Renderer full commands still fail at the existing unapproved corpus-source gate, with subsequent commands passing separately.\n\nThe fresh seven-repository audit has zero open PRs and zero open Dependabot security alerts. Latest main coordinated package CI passes; it does not certify these unpublished branches. No integration PR is opened by this checkpoint. Native PowerPoint still rejects its COM factory with `0x80010001`; no connected document session is available. The attempt opened no fixture and closed no user file/process. Current native save/reopen/raster gates and older metric tab/ink counterexamples remain open.\n\nNext extend actual ink/source-preserving layout to the remaining payload internals, make measured-font preparation easier, resolve missing CSV/advanced chart semantics and resume native checks. Complete quality/candidate/review gates before dependency-ordered publication, fresh registry E2E and public adoption. Preserve the concurrent selectable/vector-PDF roadmap work; no PDF backend shipped here. The full ecosystem goal remains active and making progress.\n\n## Previous checkpoint \u2014 accepted text fits and measured rich spacing; paint/native/release gates open\n\nContinue `codex/shared-metric-integration-20260910`. Renderer `3068c0ecd7f453c00de3cd72a7a98979e31d14d5` now paints plain/rich text and headings from accepted composition fits and resolved styles, without a second measurement pass. Core runtime remains card source `cc3c8131a14d7945c28e89f2819e4beeaa89cd51` (repository checkpoint `2d7a47ccbfc1b02f7784e85364ad7c048c4d07f4`); PPTX `b9885ab6601c1bdecc7e3b5547baa33a2a467735` and editor `125782eb537a3a37f61dfba661f66cb9658a33f4` are unchanged. [Portable text evidence](evidence/accepted-text-layout/README.md) binds 545 artifacts. No versions, approved baselines, release refs or deployments changed.\n\nBoth Node 20.20.2/24.20.0 pass 24 exact accepted-fit cases, full PPTX/editor commands, six other browser suites and 46 rich-text canvas checks. Full renderer commands still exit 1 at the unapproved corpus source gate; later checks pass separately. All 2,415 corpus image hashes verify. Exactly 102 slides change, with identical composition and normalized words: 86 titles and 28 subtitles now retain accepted sizes. All five pair sheets and four selected full-size rasters were inspected; no baseline was promoted.\n\nThe unchanged compliance/water-utility slides show why font loading must precede measurement. With identical Carlito bytes in a controlled comparison, estimated run-boundary errors reach 105.89/18.80 reference pixels; explicit measured-font rendering reduces them below 0.01/0.08. The renderer README and export skill now supply consistent measurement/raster fonts. This is an explicitly selected Aptos visual substitute, not a proprietary-font or native-equivalence result. The default unmeasured corpus still has visible rich spacing problems, and plain core fitting normalizes whitespace.\n\nThe 24-case actual Edge test passes advances/origins but **exits 1 for four portrait/right title paint cases**: one pixel at (497,186), coverage 90/255, beyond an accepted right edge of 496.8. Independent per-item paint masks and separate DOM font rectangles are preserved for both runtimes. Do not hide this with clipping or consumer-specific nudges; shared ink bounds remain work.\n\nThe refreshed seven-repository audit again has zero open PRs and zero open Dependabot security alerts. No integration PR is open. No connected PowerPoint session was available and no new native application check was attempted; prior COM/native metric/chart gates remain open. No user Office process or presentation was closed. Next address shared ink/whitespace, make measured-font preparation easier, resolve absent referenced CSV/advanced chart semantics, then finish native, candidate, review, release and public gates. The full goal remains active and making progress.\n\n## Previous checkpoint \u2014 shared card geometry and five glyph contrast corrections; native and release gates open\n\nContinue `codex/shared-metric-integration-20260910`. Core source `cc3c8131a14d7945c28e89f2819e4beeaa89cd51`, renderer `053edb1797fd367ae401885fc1d2a8667f212e2d`, PPTX `b9885ab6601c1bdecc7e3b5547baa33a2a467735` and editor `125782eb537a3a37f61dfba661f66cb9658a33f4` implement shared card padding. [Portable card evidence](evidence/content-card-layout/README.md) records 730 hashed artifacts, checks and remaining gaps. No versions, release refs, deployments or approved baseline changed.\n\nCore preserves each card's outer allocation as `frameBox` and measures the rounded inner `box` before `grid-score-v5` scoring, strict overflow and pagination. Explicit placement, source content and readability floors remain intact. Renderer/editor/PPTX resolve the same deck/slide flag. Native editable frames use guarded tags so unchanged empty cards do not reimport as unwanted text; their styling and placement are not reconstructed. Changed or untagged frames retain ordinary import text/unsupported-shape descriptions with the documented limitations.\n\nBoth Node 20.20.2 and 24.20.0 pass 473 core tests, core checks, full PPTX/editor suites, five additional real-browser suites and six card-enabled edit/undo/export/reimport workflows per runtime. Full renderer commands still exit 1 at the unapproved corpus gate; later checks pass separately. This is linked-source evidence, not registry/native-raster certification.\n\nThe previous 28 rectangle findings refine to 23 glyph passes and five actual failures. All five failures now pass targeted source-preserving glyph regressions, with opposite-polarity masks and failing invisible-text controls retained. Separate complete current browser audits report zero findings across 100 decks, 720 slides and 10,313 text runs on both runtimes. Recorded bundled fonts, host fallback and audit scope do not establish font compatibility or universal accessibility.\n\nAll 2,415 corpus hashes verify; 213 card-enabled rasters change and 592 remain identical. Source digest stays `3a1ed8ad00b30863b5852197a85602263a2238c613020fb891d933f86e124c4b`. Nine pair sheets, four full-size examples and three targeted browser slides were inspected. Chart placeholders, awkward rich-text spacing/default font measurement and excessive card whitespace remain visible quality gaps; no baseline was promoted.\n\nThe refreshed seven-repository audit again reports zero open PRs and zero open Dependabot security alerts. No integration PR is open. Native PowerPoint remains unverified for this change; existing COM rejection and metric tab/ink counterexamples are still open, and no connected document session was available. No user Office file/process was closed. Next investigate the observed chart/rich-text quality gaps with resolved font measurement and resume native checks when Office accepts automation, then complete clean candidates, PR reviews and dependency-ordered release/registry/public gates. The overall goal is active and making progress.\n\n## Previous checkpoint \u2014 offline gallery artwork and bounded image fallbacks; native and release gates open\n\nContinue `codex/shared-metric-integration-20260910`. Core source `6cf9d138383846e14770bc6a5289f17fb0f5beb0` and renderer `5257b906fe3fd28ea19a4367474f9c594712a270` are pushed. PPTX `7ed519de3daadb49123baf574bab89fd817d411a` and editor `b30c25c5af426590857f1a84c54b775056fee5ca` are unchanged. [Portable artwork/image evidence](evidence/gallery-artwork-images/README.md) records the checks, exact source preservation, final corpus and remaining gaps. No released versions, immutable release refs, public deployments or approved golden baseline changed.\n\nEighty gallery decks now embed 400 original MIT-licensed abstract branding/background PNGs. The source guard preserves all other document content, values, metadata, geometry, colors, alt descriptions and opacity across all 100 gallery decks. The 240 remaining photo/video/data references are explicitly inventoried, not substituted. SVG unresolved images report complete descriptions and path-specific reasons; bounded labels/icons preserve the readability floor and accessible name. Alias overrides survive, and header/footer/watermark artwork fits its region without inheriting content-picture crop mode.\n\nBoth Node 20.20.2/24.20.0 pass core's 470 tests and preservation/typecheck/lint/examples, all 400 independent PNG decodes, six real-browser placeholder cases/18 bounds and complete actual-image browser/PPTX embed/reimport checks without a resolver. Full PPTX/code/metric/six-browser-suite checks pass with the final renderer. Renderer full commands still exit 1 at the unapproved corpus gate; the subsequent checks pass separately. These are linked-source results, not registry installations or native PowerPoint image fidelity.\n\nAll 2,415 historical/current Node20/current Node24 PNG hashes verify, and current manifests match. The new source digest is `3a1ed8ad00b30863b5852197a85602263a2238c613020fb891d933f86e124c4b`; 642 of 805 rasters change. All 17 final overview sheets and six full-size images were inspected. The offline Edge audit drops from 942 to 28 findings: 914 missing watermark/header/background labels are replaced by actual artwork, while all 28 other finding identities remain. Text-run population changes; this is not a contrast or native-fidelity certification.\n\nThe fresh seven-repository GitHub audit reports zero open PRs and zero open Dependabot security alerts. No integration PR is open yet. The existing PowerPoint COM connection failure and native metric tab/portrait ink counterexamples remain open. Next address those native/corpus/remaining resource gaps, then complete coordinated candidate CI, PR review and release gates. Preserve the published set and earlier evidence. The full goal remains active and making progress.\n\n## Previous checkpoint \u2014 chart colors and workbook headings checked; PowerPoint connection gate open\n\nContinue `codex/shared-metric-integration-20260910`. Core source is `a58a9e39a02b1ca13b947dd045bfa9f664c3db57`, renderer `a6c499434b98754597c6cb7e2b8ec744fdecd7fc`, PPTX `7ed519de3daadb49123baf574bab89fd817d411a`, and unchanged editor `b30c25c5af426590857f1a84c54b775056fee5ca`. [Portable chart evidence](evidence/chart-colors-workbook/README.md) binds 348 artifacts to these pushed sources. No published versions, deployment or accepted golden baseline changed.\n\nSVG/native chart panels and inherited label colors are explicit. A bounded shared fallback keeps inherited opaque series marks at least 3:1 against the panel while preserving passing colors and unresolved alpha. PPTX writes category headings into the actual embedded workbook; import reads its current supported header cell, including Unicode, whitespace and rich shared strings, with bounded unsupported/external-reference handling. This does not unify chart semantics, palette identity or geometry; scatter and arbitrary workbook layouts remain outside heading recovery.\n\nBoth Node 20.20.2/24.20.0 pass 470 core tests and preservation/typecheck/lint/example checks, 40 chart cases per consumer, 37 workbook cases, full PPTX/code/metric suites and six actual Edge browser suites (four new chart cases / 28 checks). Renderer full commands still exit 1 at the unpromoted corpus gate; the subsequent checks pass separately. All 805 before/after image hashes are verified and current runtime manifests match across Node versions. The 141 final chart rasters were covered by the initial panel/text review and the follow-up series-visibility review. The offline text-rectangle audit drops from 962 to 942 findings: all 20 chart-label findings are removed; placeholders and 28 other content findings remain.\n\n**Current native charts are not verified.** The fresh runtime-bound attempt failed before opening the deck: PowerPoint's COM factory rejected the connection with `0x80010001 / RPC_E_CALL_REJECTED`. Its exact fixture and failure log are committed. Earlier exploratory chart save/reopen rasters and a failed numeric edit are not current passing evidence. No Office process or user file was closed. Resume one new native fixture at a time after Office accepts automation; test embedded workbook edits, save/reopen/reimport and point colors on both runtimes.\n\nNext complete that native gate, address remaining corpus/metric findings and chart/theme gaps, then finish coordinated source/clean-candidate CI and PR review before release preparation. Preserve all previous evidence and published packages. The larger deterministic repair/Auto arrange/shared-payload/font objective remains active and making progress.\n\n## Previous checkpoint \u2014 native table colors verified; gallery contrast review remains open\n\nContinue `codex/shared-metric-integration-20260910`. Core source is `c3edf5696c028d5150e77e32d7904060022eb83c`, renderer `a688f619b4617ca229bc910ce5d4dc1548dcf601`, PPTX `eac68e3b675c279f97fae61764e015566c2c1d39`, and unchanged editor `b30c25c5af426590857f1a84c54b775056fee5ca`. [The new portable checkpoint](evidence/table-colors-gallery-contrast/README.md) contains 75 hash-bound artifacts. These are unpublished linked-source branches; no released version or public deployment changed.\n\nSVG and native table cells now share a core inherited-color fallback against opaque fills. Explicit cell/run colors remain authoritative; translucent fills make no guessed-backdrop contrast claim. Both Node 20.20.2/24.20.0 pass 469 core tests, preservation suites, typechecks, example validation and PPTX full/code/metric checks. Renderer full commands still stop at the unpromoted corpus gate, while the remaining commands pass separately. Real PowerPoint opens/saves/reopens six generated editable tables per runtime: all 48 cell observations and 624 character-color observations match. Native PNGs match across runtimes and reopen. This is not browser/native raster equivalence.\n\nThe generator and 96 gallery decks now use more coherent authored colors. A source guard proves 725 changes are limited to palette slots, gradient stops and emphasized outcome colors; text, values/units, metadata and geometry are preserved. All 805 before/after PNGs match their respective manifests; 656 current rasters differ. Current corpus digest: `a7c34efedca3f700b475d15e02f83b6adab667de4046f1d1ebdf538ec2517078`. Selected pairs were inspected, but full visual review and baseline promotion remain open.\n\nThe conservative audit retains 962 findings over 100 gallery decks / 720 slides / 11,691 text runs, mostly unresolved image placeholders. Twenty chart-label findings include confirmed near-white labels on a white panel in dark themes; 28 other content rectangles require further assessment. An actual browser glyph-mask probe proves one metric finding is a border outside the glyphs: rectangle minimum 1.588:1 versus actual glyph-support minimum 7.013:1. No other findings were dismissed. Font rectangles and approximate shared opacity are not accessibility certification.\n\nNext fix the chart/background and placeholder issues, finish corpus review, then coordinated source/clean-candidate CI and PR review. Existing metric tab-position and portrait-label raster counterexamples remain open; their historical native evidence below was not rerun for this table-color change. Release preparation, registry E2E and deployments follow acceptance. The larger repair/Auto arrange/shared-payload/font objective remains active and making progress.\n\n## Previous checkpoint \u2014 native metric anchors, complete field masks and corrected gallery data\n\nContinue `codex/shared-metric-integration-20260910`. Core source is `621bc86b6b04f2b33080fbe2565e10e4d3681aec`; PPTX source is `78993a14f2e79959df3390c370b2d35dadc0d059`. Renderer `647368a481d316c390671fe4d33803cd08b933a6` and editor `b30c25c5af426590857f1a84c54b775056fee5ca` are unchanged. These pushed branches remain unpublished integration checkpoints. The complete published shared-code set and production sites remain as recorded below.\n\n[New portable evidence](evidence/shared-metric-native-anchor/summary.json) preserves 55 artifacts separately from the earlier metric evidence. Native paragraphs now use the accepted left/center/right alignment anchor and part width. This removes all nine prior source-character-bound overruns without refitting. Both Node 20.20.2 and 24.20.0 pass the expanded 48-slide real PowerPoint open/edit/save/reopen matrix and all **144 original/saved/edited field/type imports per runtime**. The 138 isolated native field rasters per runtime cover every nonblank field, reproduce every full-slide ink pixel when combined, and have no inter-field pixel collisions at these dimensions; runtime and raster hashes match across runtimes.\n\n**Native comparisons still exit 1.** Eight tab-position observations exceed the existing 0.02pt gate, up to 0.067383pt; the \u201CLatency\u201D label in the portrait/right long-unit fixture still has visible ink at x=497 beyond the accepted edge x=496.8. Its unit ends at x=496. Character containment and isolated mask intersections are separate checks, not pixel equivalence. No tolerance was widened, font embedded or unrelated PowerPoint presentation changed. The PowerShell harness explicitly reads UTF-8 in both Windows PowerShell and newer PowerShell.\n\nThe affected PPTX package/full/code/metric checks and actual editor metric browser workflows pass again on both runtimes. Renderer commands after its golden gate (`fonts-browser`, `design-preview`, browser harness build and styled tables), plus focused metrics, were run separately and pass. This does not make the full renderer command pass: its baseline remains unpromoted.\n\nAll nine before/after sheets covering 85 changed slides were inspected. The new renderer revealed an authoring defect: 40 fictional gallery metrics paired preformatted values with unrelated units and changes. The generator and those metric payloads now use consistent values/units/deltas and an explicit \u201CIllustrative result\u201D label; all 126 decks validate. Runtime metadata preservation is unchanged. The reproducible review helper verifies 535 prior registry files, renders the old and revised source corpora against their respective manifests, and records each authored metric change. The revised corpus digest is `e3c7194f1fc4ee452570d27a24633a9baa413ea1bbfe117668e3434d01686f50`. Pale/gradient template contrast and compact hierarchy remain visual quality findings; no golden baseline was promoted.\n\nA separate 1,024-case native font study covers eight local reference faces. An experimental no-optional-ligatures/eighth-point-advance hypothesis is within 0.02pt in 949 cases; the 75 outliers include combining marks, Arabic and Calibri kerning. The study records reference font bytes/versions, native font-slot names and theme tokens. Native name properties do not prove the exact file used for every glyph. This is exploratory evidence, not a shipped profile or a verified open-font mapping.\n\nNext resolve the tab/raster counterexamples and corpus quality findings; finish a reviewed baseline, coordinated source/clean-candidate CI and PR review before release preparation. Then perform dependency-ordered publication, immutable release/CI updates, fresh registry and public deployment checks. No versions were bumped or republished. The broader repair/Auto arrange, chart/timeline, open font-pack, multilingual and missing native-platform objective remains active and making progress.\n\n## Previous checkpoint \u2014 metric consumers and native source recovery; raster gates open\n\nContinue `codex/shared-metric-integration-20260910` across all four GitHub repositories. The [integration plan](plans/shared-metric-integration.md) records core source `09ab32fa4899b32ee55bdd2b1bfea32c4de7d674`, renderer `647368a481d316c390671fe4d33803cd08b933a6`, PPTX `8723f0c16a1e4ffd0f592a881c71a79067e5e989` and editor `b30c25c5af426590857f1a84c54b775056fee5ca`. Core supplies accepted left/center/right line origins; consumers preserve metric fields, zero, metadata and blank targets. SVG/native export consume accepted styles/geometry; guarded tags recover current native text and source types. Actual editor edits, selection, validation, pagination, undo/redo and export/reimport are implemented.\n\n[Source evidence](evidence/shared-metric-integration/summary.json) separates passing checks from open gates. Core passes 466 tests plus preservation suites on Node 20.20.2/24.20.0. Both runtimes pass metric/code focused checks, existing PPTX/editor package commands, six offline metric editor workflows, eight scalar/blank cases and two rejected-edit cases. Renderer full checks stop at **85 changed rasters out of 805**, with unchanged corpus source; visual review and baseline promotion have not happened.\n\nReal Windows PowerPoint 16.0.20326.20132 opened/edited/saved/reopened 36 source-exported metric slides. All **108 original/saved/edited imports preserve exact tested fields and types**. Its native raster gate remains failing: nine advance-bound differences up to 0.70866 point and one portrait/right visible-ink outlier at x=497 beyond a cell ending x=496.8. Reports preserve that nonzero result; native inter-part glyph collision and pixel equivalence are not established. No reference font is embedded or redistributed.\n\nNext investigate native metric/raster differences, review the changed corpus slides, finish source/clean-candidate checks, add coordinated CI/guards and complete PR review. No versions, release-plan refs, registry installations or public deployments have advanced. The full goal is active and making progress. Preserve previous evidence and use pushed GitHub branches as portable checkpoints.\n\n## Previous checkpoint \u2014 metric primitive merged; composition/pagination source integration started\n\nCore [PR #58](https://github.com/OpenPresentation/opf/pull/58) merged as `5cfc944ee7709b54bc2d1e7192cd86b7a52d6cb7`, tree-identical to reviewed `d484a32a910cd9f0c729bcb9e5dc57f1e1cdfaa6`. Complete coordinated Node 20/24 CI `34461397322`, core CI `34461397297`, Windows/macOS CLI `34461397393` and Bugbot pass. The valid inline-search review finding was reproduced and fixed before merge. All standalone evidence immediately below is now merged. No package was published.\n\nContinue `codex/shared-metric-integration-20260910` and the [source integration checkpoint](plans/shared-metric-integration.md). Core composition now consumes complete accepted metric geometry, identifies the changed selection rules as `grid-score-v4`, and retains value compatibility aliases, explicit placement, source types and inherited strict diagnostics. Existing atomic pagination now sees complete metric failures. Both Windows Node 20.20.2 and 24.20.0 pass 464 core tests plus existing preservation suites. This is an initial source-only integration, not a finished consumer or release milestone.\n\nFresh GitHub sibling checkouts of renderer `f4a1b8e1324cbc182b98d43f16528594c8006f86`, PPTX `f421c91b7b127c7eeab788acdc0c51969402e057` and editor `1b05f8ba97f9617b25b1a9d18ac05648419318c9` are prepared. Their source remains unchanged. Next audit shared alignment, replace the legacy metric formulas, implement guarded source/type recovery and actual editing/undo, then run coordinated candidate/browser and real PowerPoint gates. Preserve the complete published set and public deployments until a reviewed coordinated release is ready. The full goal remains active.\n\n## Previous checkpoint \u2014 standalone metric allocator verified locally; integration remains open\n\nContinue [core PR #58](https://github.com/OpenPresentation/opf/pull/58), `codex/shared-metric-layout-20260910`. The [metric checkpoint](plans/shared-metric-layout.md) now records the additive `layoutMetric` API, complete field/source preservation, compact inline/stacked allocation, scaled readability floors and strict failures. Core Node 20.20.2/24.20.0 both pass 458 tests and existing preservation suites; workspace typecheck and lint pass. Trial limits remain bounded even at near-zero floors; the rounding regression and regenerated reports pass on both runtimes. Published packages and public deployments remain the complete shared-code set. No version was bumped or republished, and composition/pagination/editor/export do not yet consume the new primitive.\n\nThe [real-font geometry report](evidence/shared-metric-layout-2026-09-10.json) and [controlled SVG report](evidence/shared-metric-browser-2026-09-10.json) are byte-identical across those runtimes. Sixty wide/portrait cases across Carlito, Caladea and Roboto include 50 fitting layouts, six strict irreducible failures and four explicit missing-glyph failures (Carlito U+0301; Caladea \u03A9). All 50 browser cases pass exact source and 0.1-pixel advance/segment checks offline in Edge 152.0.4191.66. Two inspected rasters led to removing an excessive percentage gap. Sixteen Canvas ink observations extend up to one reference pixel beyond part advances, with no inter-part ink collisions; this is not glyph-outline containment or native pixel equivalence.\n\nComplete CI/review remains a gate on this candidate. Coordinated CI now runs the new model/browser probes using real registry fonts and preserves their reports. After review, integrate metric measurement through candidate scoring, accepted-cell rounding, inherited strict policies, all-or-nothing pagination, actual browser editing/undo, and real PowerPoint export/edit/save/reopen/reimport. Keep the larger repair/Auto arrange/font objective active; do not close metric coverage or release from an unintegrated primitive.\n\n## Previous checkpoint \u2014 public adoption merged; metric layout counterexamples recorded\n\nCore [PR #57](https://github.com/OpenPresentation/opf/pull/57) merged as `115f3e915b9b36f0518e55ac6a4f8014ac7114cc`, tree-identical to reviewed `9bc0e2705e4957b4abc0683fa34ffe308c8e9b81`. Complete coordinated Node 20/24 CI `34456846499`, core CI `34456846509` and Bugbot pass. All public deployment and native evidence immediately below is now merged; the shared-code release/adoption milestone is complete. No package needs republishing.\n\nContinue root `codex/shared-metric-layout-20260910`. The [layout plan](plans/layout-repair.md) now records the next concrete gaps against actual registry core 0.9.0 and renderer/PPTX 0.7.0: metric unit/zero-delta/trend fields disappear from serialized output, a label ignores an explicit 32px floor, and strict composition accepts a long label that preview/export reject later. Node 20.20.2 and 24.20.0 reproduce identical [source/runtime/font-bound counterexamples](evidence/metric-layout-gap-2026-09-10.node24.json), checking all 555 installed library files against prior verified registry archives. Input documents remain unchanged. These are expected baseline defects, not accepted behavior or new native raster findings.\n\nNo metric runtime code has changed at this checkpoint. Implement and review complete shared metric geometry next, then integrate it through composition, pagination, browser/editor and native export. The larger deterministic repair/Auto arrange, other payload internals and font/native-platform goals remain active. Preserve the published package set and all earlier evidence while that work proceeds.\n\n## Previous checkpoint \u2014 shared-code packages adopted and verified on all three public sites\n\nCore [PR #56](https://github.com/OpenPresentation/opf/pull/56) merged as `921fce853fefacf6d17c3572d77b1714c139a9ab`, tree-identical to reviewed `db285830a4c4fa0bdad22254b5eacfafd3ad2ea6`. Complete Node 20/24 coordinator `34452913573`, core CI `34452913519` and Bugbot pass. The five published versions below and their immutable library verification refs are the complete set. No package was republished during public adoption.\n\nAll three adoption PRs have merged after review and CI. [Portable public evidence](evidence/shared-code-public-adoption/summary.json) records exact Git trees, registry integrities, deployment aliases, test-source and served-asset hashes, and separate preview/production runs. Each of the 21 workflows passed against its preview and again against public production:\n\n| Repository | Reviewed / merged checkpoint | Ready production deployment | Public checks |\n| --- | --- | --- | --- |\n| [openpresentation-site #23](https://github.com/Data-Advantage/openpresentation-site/pull/23) | `2aa5432e670fafb108e5c3bcb7f0b2d9a57bf97f` / `54347ac89b59658a57db95b6b26e806db8fd30f4` | `dpl_DWCgLrVof7cjwGoauJSfKiLv3wcv` \u2014 www.openpresentation.org | Six workflows; accurate npm UTC release dates, all 737 raw files for six skills, copied installation command, reference Markdown/LLM source, offline validator and three hash-matched downloads. |\n| [pptx-gallery #25](https://github.com/Data-Advantage/pptx-gallery/pull/25) | `ce133ecce42506896cd88c5850fc26f1ed38bf00` / `d048252ab3309a769c1ea9aa9d0c63deded6ad46` | `dpl_4KfB7yEGfqFFnNj8A8yS6Dfa3PY9` \u2014 www.pptx.gallery | Five workflows; eight exact registry editor assets, actual wide/portrait code editing, selection, pagination, undo/redo, export/reimport, tables and quotes. |\n| [pptx-dev #31](https://github.com/Data-Advantage/pptx-dev/pull/31) | `f8d49a7da4175226b14e2dc086fe80b1433a68d3` / `0004d4ceb595fc2ed8b561d4c8d7648cab1bc8a1` | `dpl_FsecBQDSBH2JiBeEYyV8hsN5ggek` \u2014 www.pptx.dev | Ten workflows; anonymous Author/Inspector, actual wide/portrait code edits, undo/reimport, offline JSON worker and YAML/Markdown, hostile SVG boundaries, toolkit proofs and 33 exact licensed font files. |\n\nThe site changelog was visually inspected after deployment. Public Next.js script fingerprints are recorded, not equated with unbundled npm bytes. Dependency audits and the refreshed seven-repository GitHub audit report zero advisories/open security alerts and no open PR backlog as of `2026-09-10T08:39:48Z`; compatibility follow-up issues remain intentionally open. Existing grouping/scheduling and visible security alerts are preserved.\n\nThe actual mobile gallery workflow exposed four unnamed icon buttons. Editor [PR #10](https://github.com/OpenPresentation/opf-editor/pull/10) fixed the host example, passing Node 20/24 CI `34455390448` and Bugbot. Reviewed `fa4acf1c2108fd831d10ceb803fd708e908a4e17` merged tree-identically as `1b05f8ba97f9617b25b1a9d18ac05648419318c9`. Gallery and this branch's `exampleRefs` pin the reviewed example commit; library verification remains pinned to published editor 0.6.0. No new npm version was necessary.\n\nA fresh download from the deployed pptx.dev Author was opened in real PowerPoint `16.0.20326.20132`, edited as native text, saved/reopened and reimported with its table intact. [Native evidence](evidence/shared-code-public-adoption/dev-production-native.json) and the inspected raster bind the actual download and saved-file hashes. This one public fixture supplements the complete registry code/quote native matrices below; it does not establish general formatting preservation or pixel equivalence.\n\nContinue `codex/shared-code-public-adoption-20260910`. This portable checkpoint and the example ref update require core CI/review. The [full accepted objective](plans/ecosystem-objective-2026-09-09.md) remains active: deterministic repair and Auto arrange, other payload internals, broader font/multilingual compatibility and missing macOS PowerPoint/Keynote evidence are next. Preserve all previous release and native evidence.\n\n## Previous checkpoint \u2014 shared-code registry/native gates pass; plan and CI update prepared\n\nCore [PR #55](https://github.com/OpenPresentation/opf/pull/55) merged as `685733976a665d0190bdb9922b9a174ef94153d9`, tree-identical to reviewed `7aa98ec32241e807ec18a95a7b1440fc780dfdc6`. Complete coordinator `34443625041`, core `34443625103`, Windows/macOS CLI `34443625117` and Bugbot pass. Trusted publication succeeded for **core 0.9.0** (`34444106008`, tag `opf-v0.9.0`) and **CLI 0.7.0** (`34444558025`, tag `cli-v0.7.0`). Both npm gitHeads match the merge; do not republish either version.\n\nFresh actual registry installs pass on Node 20.20.2 and 24.20.0. [Core evidence](evidence/shared-code-publication/core.json) records 28 immutable quote/code public-API fixtures, schema/catalog/pagination smoke, seven dependency signatures and one publication attestation. All 519 installed files match the fetched registry archive and both runtimes match each other. [CLI evidence](evidence/shared-code-publication/cli.json) records the standalone global executable, npx-style six-skill installation, preserved user instructions, repeat-install no-op, 69 immutable command checks, bundled core 0.9.0 and signature/attestation verification. The Windows file-symlink guard remains skipped locally and covered by Unix CI. Both packages have GitHub release notes.\n\nRenderer [PR #11](https://github.com/OpenPresentation/opf-render/pull/11) merged as `f4a1b8e1324cbc182b98d43f16528594c8006f86`, tree-identical to reviewed `c6b8ae18a0033dcd4c1f2893d760e76ee0bc9475`. Final CI `34446148105` and Bugbot pass after fixing the valid one-line trace-height finding. **Renderer 0.7.0 is published**, tag `opf-render-v0.7.0`, trusted run `34446669234`. [Actual registry evidence](evidence/shared-code-publication/renderer.json) passes on Node 20.20.2/24.20.0: every shipped file matches the immutable merge, eight pinned fixture suites, 126 decks / 805 raster hashes, 132 XML-boundary rejections, JPEG/quote browser suites and twelve code/font cases. npm verifies 44 package signatures and twelve attestations with zero advisories. The Windows local archive and Linux registry archive retain separate integrities. Complete accepted trace boxes and actual candidate-editor blank multiline selection/edit/no-op/undo are covered; no new native raster-equivalence claim is made.\n\nConverter [PR #15](https://github.com/OpenPresentation/opf-pptx/pull/15) merged as `f421c91b7b127c7eeab788acdc0c51969402e057`, tree-identical to reviewed `54f452097a52da8e39f1a600dfbf2ccd08f22b81`. All four Linux/Windows CI jobs (`34448046042`) and Bugbot pass. **PPTX 0.7.0 is published**, tag `opf-pptx-v0.7.0`, trusted run `34448635137`; GitHub release notes exist. Registry processing briefly returned 404 after successful publication; the package subsequently became available without another publish. [Actual registry/native evidence](evidence/shared-code-publication/pptx.json) passes on both runtimes: all 20 shipped files match the immutable merge, seven pinned suites and five browser suites pass with zero advisories and verified signatures/attestations. Each runtime passes real PowerPoint with twelve Calibri quote and eight Courier New code fixtures, six quote deck imports and all 24 exact original/saved/edited code slide imports. Native tab error is at most 0.007031 point (0.02-point gate). All 24 tested archives across both runtimes contain no embedded font entries. Actual registry representative PNG hashes match the already inspected candidate images; baseline and glyph differences remain, and pixel equivalence is not claimed.\n\nEditor [PR #9](https://github.com/OpenPresentation/opf-editor/pull/9) merged as `7b6db50f42783979841674e628193b1ba2f5c0e2`, tree-identical to reviewed `02e9abc47a987e94ccd44dec38f1112753a13631`. Final CI `34451155459` and Bugbot pass after fixing the valid invisible-selection finding. **Editor 0.6.0 is published**, tag `opf-editor-v0.6.0`, trusted run `34451545452`; GitHub release notes exist. [Actual registry evidence](evidence/shared-code-publication/editor.json) passes on Node 20.20.2/24.20.0: all 32 shipped files match the merge, nine model suites and offline playground/code workflows pass, with signatures/attestations and zero advisories. Fully selected source and filename text stays visible; blank multiline targets, CRLF/no-op, Tab/cancel, pagination/readability, undo/redo and exact code export/reimport pass. The regression reproduced the original transparent glyphs, and corrected candidate screenshots were inspected in both dimensions.\n\nContinue root `codex/shared-code-publication-20260910`. All standalone publication helpers and [complete source/candidate, registry and native matrices](evidence/shared-code-complete/summary.json) pass on Node 20.20.2/24.20.0. Each complete registry run includes every library archive/file match, pinned code fixtures, all seven browser suites (230 assertions/eight trusted interaction scenarios), additional code/blank/selection workflows, fifteen fidelity suites, 126 decks/805 rasters, CLI installation and negative runtime/integrity/link/loader guards. Candidate and registry evidence remain separate. The immutable native bridge uses bytes matching both browser matrices: eight code slides and all 24 original/saved/edited source/metadata imports pass per runtime, with tab error at most 0.007031 point. Twelve complete-set code archives contain no embedded fonts; representative PNGs match previously inspected converter images. Native raster equivalence remains unproven.\n\nThe branch now advances `release-plan.json`, editor example ref and CI consumer refs to the five published merges above and enables immutable code registry verification plus its negative guards. Full coordinated CI/review is the next gate before this plan update merges. Preserve both old and new evidence. No additional package publication is needed for this documentation/verification milestone.\n\nThe public sites still use core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0. After plan/CI review, advance public dependencies, accurate UTC changelog, bundles and deployed E2E. Registry publication alone does not establish public adoption. The [seven-repository audit](evidence/shared-code-publication/repository-audit.json) recorded no old PR backlog and zero open security alerts before the final release PRs. The full repair, Auto arrange, other payload internals, font/multilingual and missing native-platform objectives remain open.\n\n## Previous checkpoint \u2014 code integration merged; core/CLI release preparation\n\nCore [PR #54](https://github.com/OpenPresentation/opf/pull/54) merged as `8d9c9c80b788bbdc80e18ad2b6468f07b2e2321d`, tree-identical to reviewed `e8b520dd2c23e559a8d9affcfcb8772c8b8079b7`. Complete Linux coordinator `34441603873`, core CI `34441603829`, Windows/macOS CLI `34441603812` and Bugbot pass. [Portable final CI evidence](evidence/shared-code-ci-2026-09-09.json) records actual Chromium 153 code workflows, both seven-suite installed browser matrices, runtime/harness/package fingerprints and restored stale-evidence guards. The two Linux Node versions produce identical candidate tarball hashes. The separate corrected Windows installed/native evidence below remains authoritative for PowerPoint.\n\nContinue `codex/shared-code-release-20260909`. It prepares **unpublished core 0.9.0 and CLI 0.7.0**, versioned code/layout guidance and updated portable skills. The CLI-local changelog now includes the already published 0.6.0 history; no old version is republished. [Release gates and intended consumer versions](plans/shared-code-release.md) specify renderer/PPTX 0.7.0 and editor 0.6.0, with lockfile renewal and standalone checks after upstream publication. Complete core/CLI release checks and review before tagging. Keep `release-plan.json`, actual registry fixtures and all public deployments on the current verified published set until the new complete set exists.\n\nThe full repair, Auto arrange, metric/timeline/chart internals, font/multilingual/native-platform objective remains open. Preserve the exact previous package and deployment checkpoints below. New source behavior, actual installed browser interaction, schema validity and native text/raster scope remain separate claims.\n\n## Previous checkpoint \u2014 installed code workflows and coordinated CI prepared\n\nReview follow-up: renderer `b5a3722725338e8d964783e8b7f1f7b80ce28cd3` and converter `b4f4645cdaa2f5eff8a883f68533875d3b63f239` supersede the initial consumer commits below; editor remains `52e540b83e441892fd928e9f159bffbb29da5653`. A bounded installed probe found schema-valid controls emitted invalid XML and an unpaired surrogate became a replacement character. Both format boundaries now reject these with `invalid-code-text`, source path and UTF-16 offset while retaining the input. Each engine passes 132 source/metadata rejection cases and valid XML character boundaries on Node 20/24. This is separate from font coverage. [Renewed corrected-package evidence](evidence/shared-code-xml-boundary/summary.json) records passing continuous full source/tarball/browser/CLI/guard commands on both runtimes and renewed actual installed-native checks: all 24 original/saved/edited imports pass, and every native/SVG raster is byte-identical to the previously inspected valid-input fixture. The evidence below preserves the earlier checkpoint without relabeling its runtime hashes.\n\nCore PR #54's preceding `4f4a0b44584be945420f2b8d519f9417ee073e7d` passes complete Linux coordinator `34440657844`, core `34440657756`, Windows/macOS CLI `34440657695` and Bugbot. The latest CI pins now include the two character-preservation fixes and require a fresh run/review before merge. No version has been published.\n\nContinue `codex/shared-code-integration-20260909`. The four pushed source checkpoints below remain the tested runtime inputs; this checkpoint adds fresh installed-tarball code verification and pins coordinated CI to the exact consumer commits and reviewed code raster manifest. [Installed evidence](evidence/shared-code-installed/summary.json) binds all four local package hashes, lock integrity, runtime files, copied test harnesses and actual browser bundle inputs. Node 20.20.2 and 24.20.0 produce identical candidate tarballs and runtime bytes. They are private local preview packages, not published versions.\n\nThe installed checks execute 15 core code/composition tests, converter source/metadata guards, renderer measurement checks, and actual font-loaded offline renderer/editor workflows, including pointer/keyboard edits, CRLF, Tab/cancel, pagination floors, undo/redo and export/reimport. All seven prior packed browser suites also pass on both runtimes. Negative checks reject altered runtime bytes, incorrect lock integrity, external module links and loader environments, then restore the generated fixtures. CLI 69-command and standalone global/npx-style local-pack checks pass on both runtimes; Windows file-symlink privilege coverage remains in Unix CI.\n\nThe continuous Node 20 source/package wrapper passes. The first Node 24 wrapper passed its source checks but failed a new harness import; the corrected installed, tarball, browser, CLI and guard stages pass. The next harness iteration also needed to recognize esbuild's empty disabled-module stubs; it now accepts only zero-byte stubs with no imports and verifies every real bundle input stays inside the installed consumer. Neither failure changed a runtime or relaxed a product assertion. Renewed full Linux Node 20/24 CI and review remain the next gate.\n\nSeparate fresh registry installations pass the exact published package, seven browser and pinned fidelity suites on both runtimes, including 126 decks / 805 raster slides. These remain core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0. `release-plan.json`, registry fixture refs and public deployments stay on that published set; these registry checks do not claim the new code feature.\n\nReal PowerPoint also passes against the fresh installed candidate runtime: eight wide/portrait slides, all 24 original/saved/edited imports, exact source/metadata and save/reopen. Native comparisons pass on both Node versions; four text-after-tab targets are within 0.007031 point of accepted stops (0.02-point gate). New native preparation validates the candidate lock/runtime against the executed browser report before copying the versioned native harness. Representative installed SVG/native rasters were inspected; baselines and glyph appearance differ. This proves the documented editable text and source-preservation scope, not pixel equivalence, substitute-font compatibility or arbitrary Office round trips. No proprietary fonts were copied or embedded; unrelated user decks stay open.\n\nCoordinated core [PR #54](https://github.com/OpenPresentation/opf/pull/54) is open. Finish its Linux CI and review, then prepare new versions and publish in dependency order. Consumers need the released coordinated core before their standalone release checks. Add actual registry code workflows only after those releases exist, update the published plan/refs, and repeat public adoption and deployed E2E. A renewed seven-repository audit still found zero open PRs and security alerts before opening this milestone. The full repair/Auto arrange/font/multilingual/native-platform objective remains active.\n\n## Previous checkpoint \u2014 shared code consumers and native round trips verified locally\n\nContinue `codex/shared-code-integration-20260909`. All source work is pushed: core implementation `8d11fd650eb14fad3473b918713d9caa95321b83`, renderer `343ffea275e2eff478fc6a355551379897b748df`, converter `860e9476520659bf65822c945bf96b253cbe6c01`, editor `52e540b83e441892fd928e9f159bffbb29da5653`. Fetch these GitHub branches/commits; the local worktree paths are disposable. No new versions are published and no consumer PR has been opened yet; standalone consumer checks still need a released coordinated core. Existing published versions, release-plan refs and public deployments remain authoritative.\n\nRenderer and converter now consume accepted filename/language/body code geometry, preserve whitespace/tabs/empty lines and avoid another fitting pass. Unspecified code layouts use shared automatic composition; explicit presets retain their slots. Editor metadata/body targets, CRLF-preserving edits, literal Tab, cancel, pagination and undo are tested offline. Guarded native shape tags reconstruct complete code/source-boundary metadata; native text edits take precedence. Damaged/deleted/duplicate groups retain visible shapes with diagnostics. Native font theme, formatting, geometry and readability policy are not reconstructed.\n\n[Portable consumer evidence](evidence/shared-code-consumers/summary.json) records 28 passing existing/targeted consumer script runs and four actual new code-browser reports across Node 20.20.2/24.20.0. The full renderer, PPTX and editor suites and existing browser/playground workflows pass on both. All 43 changed code rasters were reproduced against ordinary registry renderer 0.6.0 and visually reviewed, with four full-resolution inspections; the other 762 hashes are unchanged. A legacy test needed to read nested SVG tspans to keep checking code typography; its 36-line coverage passes without weakening its count gate. No lockfile changed.\n\nActual PowerPoint `16.0.20326.20132`, Windows `26200.9445`, passes eight wide/portrait code slides, editable source/metadata, tags and save/reopen. All 24 original/saved/edited slide imports recover exact code objects, including CR/LF/CRLF, blank/final lines and soft wraps. Four native text-after-tab targets differ by at most 0.007031 point against the 0.02-point gate. Node 20/24 comparisons agree. The native and resvg fixtures use the same local Courier New regular/bold bytes; representative wide/portrait rasters were inspected. This is neither substitute-font verification nor pixel equivalence. The first harness attempts had a missing expected cell reference and omitted explicit raster font files; corrected checks were regenerated and rerun, with no tolerance relaxation. No user presentations were closed.\n\nNext: add the new code cases to installed-tarball verification and coordinated CI, pin the three consumer commits with the reviewed code raster manifest, finish full coordinated Node 20/24 checks/review, then prepare releases in dependency order. Keep registry checks pinned to the currently published set until new releases exist. The full repair/Auto arrange/font/multilingual/native-platform objective remains active. Latest main coordinator `34434340695` succeeds; the old failed notification `34433357130` was the now-fixed Linux browser precision assertion, not an Actions billing rejection.\n\n## Previous checkpoint \u2014 code composition/pagination integration in progress\n\nCore [PR #53](https://github.com/OpenPresentation/opf/pull/53) merged as `7c978f8b7ef0cc649d8452f8f1b829f36a5ae6e3`, tree-identical to reviewed `f90f7c5152d4075a2c184959164df655ba05fa19`. The explicit SVG `geometricPrecision` correction passes Linux Chromium `153.0.8010.12` on Node 20/24 with the original 0.1-reference-pixel tolerance. Complete coordinator `34433911033`, core CI `34433911144`, Windows/macOS CLI `34433911057` and Bugbot pass. The initial browser rounding failure below remains historical evidence, not an open billing issue. [Preserved Linux report](evidence/shared-code-browser-linux-2026-09-09.json) supplements the separate Edge report.\n\nContinue branch `codex/shared-code-integration-20260909`. Core now measures filename/language/body in automatic candidates, exposes `item.codeLayout` using rounded accepted boxes, aliases compatibility `item.text` to the body, reports internal paths under strict ancestors and labels the changed scoring `grid-score-v3`. Existing pagination now evaluates the complete code payload. Six new integration tests plus all 448 core tests and preservation suites pass on Node 20.20.2/24.20.0; core/CLI typechecks pass. This is unreleased source. Renderer, converter and editor integration and the complete coordinated/browser/native gates remain unfinished; no new package/version/ref or public deployment is advanced.\n\nA repeatable native probe generates eight cases with the candidate core API, actual registry converter's PptxGenJS vendor and local Courier New regular/bold. Real PowerPoint preserves all literal tabs/spaces, native edits and save/reopen. Text after tabs begins at accepted stops within 0.010544 point (0.02-point gate). Native text widths differ by up to 0.78629 point; this is measured drift, not pixel equivalence. Current registry imports are schema-valid but trim leading/trailing whitespace, and whitespace-only shapes become placeholders. [Native evidence](evidence/shared-code-native-2026-09-09.json) and [integration audit/reproduction](plans/shared-code-integration.md) separate these observations from unimplemented OPF export/reimport integration. Native comparison passes on Node 20/24; original/saved/edited imports each have text loss. Preserve the user's PowerPoint session and all older worktrees.\n\nThe full repair/Auto arrange/font/multilingual/native-platform objective remains active. Finish the shared code consumer milestone, then continue metric/timeline/chart internals and the remaining roadmap. All published release and deployment checkpoints below remain authoritative.\n\n## Previous checkpoint \u2014 standalone shared code layout candidate\n\nCore [PR #53](https://github.com/OpenPresentation/opf/pull/53) continues on `codex/shared-code-layout-20260909`. The candidate adds `layoutCode` and public types for filename/language/body parts, original text, requested/resolved styles, readability floors, exact UTF-16 source/line ranges, explicit text/tab segment placement and bounded internal allocation. Missing space or irreducible content stays visible in diagnostics; strict mode rejects all output. This is an unreleased standalone API. Composition, pagination, renderer and converter integration remain next work, and the actual published code defects below still reproduce.\n\nLocal Node 20.20.2/24.20.0 checks pass: nine new tests, all 442 core tests plus composition/nesting/pagination/data/rich-text/list suites, public root/focused declaration checks, eight actual-font wide/portrait cases and eight controlled browser segment cases. [Geometry evidence](evidence/shared-code-layout-2026-09-09.json) binds the source, built runtime, registry packages and font bytes. [Browser evidence](evidence/shared-code-browser-2026-09-09.json) binds the same geometry to Edge `152.0.4191.66`, exact Cousine regular/bold and a 0.1-reference-pixel advance/segment-position tolerance; literal tabs and whitespace survive and no external requests/page errors occur. Both reports are identical across the two Node runtimes. The browser harness is not integrated OPF renderer or native PowerPoint output.\n\nThe Edge probe found SVG ignores the intended CSS-only tab spacing, so each accepted line now carries explicit text/tab segment positions and widths. The controlled harness reuses those positions with preserved literal tab text. Initial coordinator `34433357130` passes source/tarball/registry checks and actual-font geometry, then fails both Node versions' new browser check because Linux Chromium's default glyph advances round to whole pixels. Core CI `34433357078`, Windows/macOS CLI `34433357095` and Bugbot pass. The follow-up explicitly requests SVG `text-rendering=\"geometricPrecision\"`, retains the 0.1-pixel tolerance and writes observations before asserting, so CI preserves future failures. Renewed local Node 20/24 Edge evidence passes; renewed Linux coordinator/review remain required. This was a measured browser failure, not a billing-limit rejection.\n\nComplete review and both CI matrices of this primitive, then consume it in scoring, rounded accepted composition boxes, strict ancestor diagnostics, SVG, editable PPTX and the editor/pagination workflow. Native tab placement and source-preserving reimport need real PowerPoint tests. All previously published versions, immutable release-plan refs and verified public deployments remain unchanged.\n\n## Previous checkpoint \u2014 public documentation verified; code layout baseline\n\nCore public-evidence [PR #52](https://github.com/OpenPresentation/opf/pull/52) merged as `74f39c68585586cb2eb41a4adc96e60eeab8e9da`, tree-identical to reviewed `8fc5000bc78f5e89e5464d7efdfb3b96ed9cea01`. Core Node 20/24 CI `34429765513`, full coordinator `34429765488` and Bugbot pass. All five published packages and all three public adoptions remain verified as recorded below; never republish their versions.\n\nWebsite [PR #22](https://github.com/Data-Advantage/openpresentation-site/pull/22) merged as `e61319537de1c4defc2368b07ad92207e31c655b`, tree-identical to reviewed `f4cc87d10aa22370d5f2d7b901e85fa9bfbff449`, after CI `34429916760`, Bugbot and six exact-preview workflows passed (20.5s). It advances only the core 0.8.0 documentation pin to reviewed `8fc5000bc78f5e89e5464d7efdfb3b96ed9cea01`; no runtime dependency, lockfile or npm version changed. READY production `dpl_HaHBwTk5BW7LACfpLYUtFH1S37PY` passes all six public workflows (18.7s). Published-version reference headings, full LLM text, the complete six-skill/647-file manifest and exact raw documentation hashes match. [Website reference evidence](evidence/site-published-reference-2026-09-09.json). The accurate changelog and prior website/gallery/application browser/native evidence remain separate records. A renewed seven-repository audit finds no open PRs or security alerts.\n\nContinue core branch `codex/shared-code-layout-20260909` from that merged GitHub checkpoint. The first new baseline is reproduced on Node 20.20.2 and 24.20.0 with actual registry core 0.8.0/renderer 0.6.0 and bundled font bytes: an oversized language label receives no overflow diagnostic; a second valid fixture loses its filename and significant whitespace in serialized SVG, including spaces inside a string literal. Input JSON is unchanged. [Source and evidence](evidence/code-layout-gap-2026-09-09.json) and `scripts/probe-code-layout-gap.mjs` preserve the exact failing behavior. The helper asserts a historical defect and must not be used as a future quality-success gate. No browser glyph or native code-export claim is made.\n\nImplement the shared code payload API and consume its accepted geometry in composition, preview and export before claiming this gap fixed. Cover source/filename/language, meaningful whitespace/newlines, wrapped-line mappings, explicit readability floors, requested/resolved styles and irreducible failure. Then continue other payload internals, bounded repair/Auto arrange and the full font/native-platform roadmap. No new software permission is required; preserve existing worktrees and the user's PowerPoint session.\n\n## Previous checkpoint \u2014 all three public adoptions verified\n\nCore [PR #51](https://github.com/OpenPresentation/opf/pull/51) merged as `c2f6aefd63d1c428ac35ea3da0d600e6c009b367`, tree-identical to reviewed `ce014f1`. Core Node 20/24 CI `34426024145`, complete coordinator `34426024128` and Bugbot pass. The release plan and immutable CI refs now use the published core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0 set. All individual publication and combined registry/browser/native evidence below is portable in GitHub. Never republish these versions. Continue core branch `codex/shared-quote-public-adoption-20260909` for deployment evidence and remaining work.\n\nWebsite [PR #21](https://github.com/Data-Advantage/openpresentation-site/pull/21) merged as `b0a7733cfa9a97fbb8bdb91f39bcd3075640005a`, tree-identical to reviewed `27dcdb25ef6db97db2342d106cf9b51bfd625f79`. CI `34425812307`, Bugbot and exact READY preview `dpl_2TPrYFLJuSmrmQduYeV3SDwp8xVG` pass; all six preview workflows pass (20.5s). Production `dpl_FXtMtDzuUddejNkmXv9R9SkAPMVg` is READY on that merge and serves both openpresentation.org aliases. All six public Edge workflows pass (18.8s), actual UTC npm dates and the full five-package showcase manifest agree, all downloads match hashes, and fourteen served JavaScript fingerprints are recorded. The [public changelog evidence](evidence/site-shared-quote-2026-09-09.json) and [visually inspected page](evidence/site-shared-quote-2026-09-09.png) are separate from native package raster observations. Temporary preview cookies stay in ignored local artifacts; Vercel protection remains unchanged.\n\nGallery [PR #24](https://github.com/Data-Advantage/pptx-gallery/pull/24) merged as `1403916aea3f50c7d39c965ec7136da6e4b7af32`, tree-identical to reviewed `8ed70324635c2e5fb69db5479cf13755d6635a0b`. It adopts the full set and immutable editor examples, regenerates the runtime/license manifest, and adds offline quote editing/readability/undo/export/reimport coverage. 106 unit tests, typecheck/build, all required catalog/production-markup/link checks and three local Edge workflows pass. Initial CI `34427001057` timed out after five seconds waiting for the initial preview. The reviewed fix gives only initial font/preview startup a bounded 20-second wait and uploads failure traces; renewed CI `34427426307`, Bugbot and all three exact-preview workflows pass (13.3s). READY production `dpl_ENk7dmxQ22Czhq18hKZujmcJaN9s` passes all three public workflows (10.4s) and all eight bundle/font/license/example hashes. No assertion or security alert was disabled.\n\npptx.dev [PR #29](https://github.com/Data-Advantage/pptx-dev/pull/29) merged as `482f769d4676b65ac16fe3fb4660aeaa03a77a44`, tree-identical to reviewed `ea89253de9a0e1400c297b75f295807f4a0b7239`. It adopts the four public libraries and core 0.8.0 schema/examples with otherwise unchanged dependencies. 598 tests, typecheck/build, SDK/CLI build gates, zero-advisory audit, Linux/Windows CI `34427524816`, Bugbot and all eight exact-preview workflows pass. Its actual browser download again passes native PowerPoint title/table editing, save/reopen and valid reimport; portable evidence in that PR binds the package lock, PowerPoint `16.0.20326.20132`, Windows build `26200.9445` and visually inspected raster.\n\nThe first public application run on READY deployment `dpl_6avWXN5F4L7WuqiWJG713M26oa9f` passes seven workflows but reports a lazy Monaco worker-download error when Author switches offline. Follow-up [PR #30](https://github.com/Data-Advantage/pptx-dev/pull/30) waits for a real JSON-schema diagnostic before that test goes offline and derives the canvas version marker from the installed editor package. It merged as `b9eefaac764c4a3ec009b17d363663f0c6cfe146`, tree-identical to reviewed `636da78c4b18f732530881cb09da3e5554bdcdd9`, after Linux/Windows CI `34428833533`, Bugbot and all eight exact-preview workflows passed. The readiness check also passed against the unchanged public runtime; no page-error assertion was suppressed.\n\nREADY production `dpl_F1LgvvbZ8QwcvCy8ZRnZ2WaunVDe` serves that follow-up merge and passes all eight public Edge workflows (29.4s). All [33 public font/license hashes](evidence/pptx-dev-shared-quote-fonts-2026-09-09.json) match actual renderer 0.6.0. [55 served JavaScript fingerprints](evidence/pptx-dev-shared-quote-bundles-2026-09-09.json) accompany installed-package toolkit proofs and the actual browser editor 0.5.0 marker; bundled assets are not asserted byte-identical to unbundled npm. The public Author download is byte-identical to the native-tested local/preview PPTX, SHA-256 `383512f28856d1b0d86ddd378d63b5a529e9928983743d9ebac72d99200c8ac4`. [Complete gallery/application evidence](evidence/gallery-app-shared-quote-2026-09-09.json) keeps the initial failure, reviewed fix, successful public run and native bridge separate. The original nine-PR backlog is resolved; the [fresh seven-repository audit](evidence/repository-adoption-audit-2026-09-09.json) finds zero open PRs and zero open security alerts.\n\nFinish review/merge of this core public-evidence checkpoint, then advance the website's `opfSource` documentation pin to the reviewed correction so its copied reference and LLM content use published-version wording. The release changelog itself is already accurate and live. Continue shared code-language/body measurement next, followed by metric/timeline/chart internals, bounded repair and Auto arrange, with the font/native-platform roadmap still required. No new package publication is needed for these documentation corrections.\n\nLocal setup: gallery has no own pnpm workspace file, so use `pnpm --ignore-workspace` when running its checkout nested under core artifacts. An initial gallery install touched the parent core lock; that unintended change was restored and gallery was reinstalled from its own lock. pptx.dev **does** have its own workspace policy: use its declared pnpm 11.1.3 normally, retaining `minimumReleaseAgeExclude: @openpresentation/*` and all existing supply-chain controls. Disabling its workspace discovery incorrectly bypasses that configuration and causes recent-release installation rejection. No OS settings or new user permissions are required. Preserve all old worktrees and unrelated local artifacts. Full repair/Auto arrange/font/multilingual/native-platform work remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 all five packages published; coordinated registry adoption\n\nCore [PR #50](https://github.com/OpenPresentation/opf/pull/50) merged as `2a39a15cbdd750699bf8e3adac8f78420baa1fa9`, tree-identical to reviewed `edf0806e8d88d941f1dc6762cf41d045c383ebbe`. Core CI `34421921795`, coordinator `34421921845`, Windows/macOS CLI `34421921853` and Bugbot pass. Continue core branch `codex/shared-quote-registry-adoption-20260909` for the complete release-plan/CI update and final combined checks.\n\nPPTX [PR #14](https://github.com/OpenPresentation/opf-pptx/pull/14) merged as `898e3c27919a2488e1e3d384168d6b25aae4bd5c`, tree-identical to reviewed `268fcb523924c95b453acbe407d1b5359ea5f485`. Linux/Windows Node 20/24 CI `34422214063`, Bugbot and trusted publication `34422584331` pass. PPTX 0.6.0 is published. Fresh Node 20/24 registry installations verify all 19 shipped files, signatures/provenance, the 126-deck/805-slide corpus and five browser suites. Twelve fresh registry export fixtures pass real Windows PowerPoint glyph containment, editable save/reopen and six valid reimports. Exact heading/body/footer order and repeated-line counts survive; first quote lines can become subtitles and OPF quote semantics are not reconstructed. Raster differences remain observations without a pixel-equivalence threshold. [Publication](evidence/pptx-060-publication-2026-09-09.json) and [native evidence](evidence/pptx-060-native-registry-2026-09-09.json) bind the package bytes and PowerPoint build `16.0.20326.20132` on Windows build `26200.9445`.\n\nEditor [PR #8](https://github.com/OpenPresentation/opf-editor/pull/8) merged as `dba5fe5e5580a4172c052132c4db5851d1decc4c`, tree-identical to reviewed `4d056532328bdfb765701880cb35ff87a0cc8829`. Node 20/24 CI `34424194308`, final Bugbot review and trusted publication `34424531044` pass. The review's JSON-key-order no-op concern uses the existing structural comparison and has regression coverage preserving redo. Editor 0.5.0 is published and fresh Node 20/24 registry verification passes: all 32 shipped files, 67 signatures/18 attestations including test dependencies, nine model/component suites and offline author/edit/paginate/export/reimport/undo. [Editor publication evidence](evidence/editor-050-publication-2026-09-09.json).\n\nAll five published successors are independently verified. `release-plan.json` and immutable CI refs now select core 0.8.0, CLI 0.6.0, renderer/PPTX 0.6.0 and editor 0.5.0. Fresh isolated Node 20/24 combined source/tarball/registry checks pass: seven installed-browser suites, 230 assertions/eight trusted interactions per mode, four evidence guards, TypeScript/CLI checks, twelve pinned fidelity suites including 805 raster baselines, and the exact registry/native text bridge. Both registry consumers verify 64 signatures/15 attestations with zero advisories. [Coordinated evidence](evidence/shared-quote-coordinator-2026-09-09.json) records the tested core candidate `e635249` and published siblings; remote CI/review of this checkpoint remain gates. Never republish these versions. Use exact locally available runtimes Node `20.20.2`/`24.20.0` (floating `node@24` temporarily selected an unavailable version); no new software permission is required.\n\nThe three site adoption branches `codex/shared-quote-adoption-20260909` start from GitHub website main `e5dd771e6df3ddabb4544e8e435561b1dba178f3`, gallery main `b28d33564d7da2836f5c5d2e060ea461a7ac96bb` and pptx.dev **master** `b922f2f89fdb1e68f0e71a7f1df638be9c5314d4`. Website #20 has merged and its production deployment is `dpl_QKF3qGAtfGvizXu1sgPz43YReFdM`. Website [adoption PR #21](https://github.com/Data-Advantage/openpresentation-site/pull/21), head `27dcdb2`, updates the five releases, core source pin and registry showcase; production build, all registry dates and six local Edge workflows pass (8.0s). Preview/remote review/public verification remain gates. Gallery and pptx.dev adoption edits are next. All three public sites still use the previous complete set until deployments are verified. A fresh seven-repository audit found no open security alerts; the original nine-PR backlog remains resolved. The full repair/Auto arrange/font/native-platform objective remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 core, CLI and renderer published; converter checks\n\nCore [PR #49](https://github.com/OpenPresentation/opf/pull/49) merged as `4dc292fa93bee52320bafa3fd0f5b05a2dc0a283`, tree-identical to reviewed `95f9982036a01a52e080992abe4c4350c4b72354`. Core CI `34400722403`, coordinated source/tarball/registry/browser CI `34400722391`, Windows/macOS CLI CI `34400722421` and Bugbot pass. Both `opf-v0.8.0` and `cli-v0.6.0` are published through trusted workflows `34401446306` and `34402210003`; never republish them. Fresh npm installs on Node 20/24 verify registry integrities, signatures, provenance, core's 519 entries/public imports/thirteen quote tests, and CLI's exact bundled versions/global executable/npx six-skill installation/69 command checks. [Actual publication evidence](evidence/core-cli-publication-2026-09-09.json) keeps local candidate archives separate from registry artifacts.\n\nRenderer [PR #10](https://github.com/OpenPresentation/opf-render/pull/10) merged as `7fe9905ad2d8a224efeef51b4a22d0aff0c413fe`, tree-identical to reviewed `95c1eb92a8b3be0c8e63917180dcb447aed0cfb8`. Node 20/24 CI `34420837605`, Bugbot and trusted tag publication `34421186727` pass. Renderer 0.6.0 is published and verified from fresh npm installs on Node 20/24: 16 shipped files match the release commit, signatures/provenance verify, seven fidelity suites and all 805 raster baselines pass, and actual loaded-font quote/JPEG browser suites pass on Edge 152. [Renderer publication evidence](evidence/renderer-060-publication-2026-09-09.json).\n\nContinue portable branch `codex/shared-quote-release-20260909` in the converter/editor repositories. PPTX 0.6.0 preparation (`bb449f954699a3ce46ce9c2fc864875cd3894cf8`) now has an npm lock resolving core 0.8.0 and renderer 0.6.0; full local installed/browser/native checks are underway before opening its release PR. Editor 0.5.0 preparation (`dc3d81d3a1de06c9923476d808328e22ffa625b2`) still waits for converter publication before its final lock. Renew Windows PowerPoint evidence against the actual installed candidate bytes and registry predecessors; do not relabel the earlier source report.\n\n`release-plan.json` still intentionally describes the last complete published set. The [release gates](plans/shared-quote-release.md) give explicit verifier commands for the newly published core/CLI without prematurely advancing the full set. After all five successors are verified, update immutable refs and actual registry quote/raster checks, adopt the set on all three public sites, and repeat deployed bundle/browser/native checks. Website #20 remains independent active work. The full repair/Auto arrange/font/native-platform objective remains active and substantially unfinished.\n\n## Previous checkpoint \u2014 installed browser CI merged; core/CLI release preparation\n\nCore [PR #48](https://github.com/OpenPresentation/opf/pull/48) merged as `abf32daa67543c30b29dbe813b17996456b90e34`, tree-identical to reviewed `565fbd2905006624c57a7c24c1b1fe62ac10ca4d`. Core Node 20/24 CI `34399051774`, complete coordinated source/tarball/registry CI `34399051732`, and Bugbot pass. CI now executes all seven installed-package browser suites against both tarballs and registry packages on Chromium 153, with 230 harness assertions and eight trusted input scenarios per run. All four stale/mutated-evidence guard cases pass on both runtimes. [Immutable CI evidence](evidence/installed-browser-ci-2026-09-09.json) complements the local Edge report below.\n\nContinue `codex/shared-quote-release-20260909`: it prepares **unpublished core 0.8.0 and CLI 0.6.0**, including the public type-tightening notice and versioned quote/pagination documentation. The [release gates and intended downstream versions](plans/shared-quote-release.md) keep actual registry refs unchanged until publication is verified. Complete release checks/review before tagging. Then update renderer, PPTX and editor dependencies/locks in order against published packages, renew exact package/browser/native evidence, and update the actual release plan and public deployments. The full objective remains active; releases do not complete bounded repair, Auto arrange or the font roadmap.\n\nProduction openpresentation.org now serves independent website #19 merge `31c84759c044480045a07f1e150149ecb2a423d3`, READY deployment `dpl_9q2ihhJXVxnWzcjizev6M2GSVMDS`. All six public Edge workflows pass (16.9s), live npm verifies the changelog dates/set, and all three showcase downloads match exact source/registry hashes. [Fresh production evidence](evidence/site-production-design-2026-09-09.json). Website #20 is still independent active work and is left untouched. A fresh seven-repository audit finds zero open Dependabot security alerts.\n\n## Previous checkpoint \u2014 shared quote core merged\n\nCore [PR #47](https://github.com/OpenPresentation/opf/pull/47) merged as `01e69ba1a6c3915778ede6aa12fb7ecda652ea42`, tree-identical to reviewed `c81b8b1cdf7004af186dce81c2b81cfb9a25be12`. Core Node 20/24 CI `34397006994`, complete coordinated source/tarball/registry CI `34397007028`, Windows/macOS CLI CI `34397007117`, and Bugbot pass. The [integration checkpoint](plans/shared-quote-integration.md) records quote allocation/scoring, pagination content-loss/readability fixes, downstream editor undo behavior, real Edge/PowerPoint evidence and the 41-slide raster review. Renderer, converter and editor retain their pinned `codex/shared-quote-integration-20260909` branches, with no downstream PRs yet. All changes remain unreleased; actual registry versions, release-plan refs and public deployments are unchanged by this milestone.\n\nCore branch `codex/installed-browser-checks-20260909` supplied the merged runner above. Keep the published registry baseline separate from the reviewed candidate footer changes. Native reimport retains editable quote text but loses quote structure/typography/readability policy; this remains an explicit gap. The full goal is active and substantially unfinished. No renewed permission is needed for already-authorized releases/deployments after their gates pass.\n\nThe [installed-browser report](evidence/installed-browser-2026-09-09.json) records four passing local runs: actual registry and candidate tarballs on Node 20/24 with Edge 152. Each runs seven suites, 230 harness assertions and eight trusted input scenarios, with zero external requests, writes or browser errors. Four evidence-rejection tests pass on both runtimes. Plain-to-rich conversion and bold formatting remain separate undo steps. This expands package/browser verification; it does not add native raster or public-deployment evidence.\n\nWebsite PR #20 (`claude/branch-icon-spacing-fixes-de47tz`, observed `6bf9b294a05a5943be77056f372c988266ad475b`) is separate active user work and was left untouched. Do not overwrite it during future package adoption. The original nine-PR backlog is resolved as recorded below.\n\n## Previous checkpoint \u2014 quote primitive merged; shared consumer integration next\n\nCore [PR #46](https://github.com/OpenPresentation/opf/pull/46) merged as `6d8df02940deec8f1fa89192d10576d6048de341`, tree-identical to reviewed `83e35649f91fc430c817c19492b0bf3d01212766`. Core Node 20/24 CI `34389245732`, coordinated source/registry CI `34389245620` (including the new real-font quote check), Windows/macOS CLI and packed-install CI `34389245733`, and Bugbot pass. The standalone quote API is now on main and remains unreleased. No package was republished or actual-release ref advanced.\n\nContinue from branch `codex/shared-quote-integration-20260909`. The [consumer integration audit](plans/shared-quote-integration.md) records exact downstream bases, candidate/accepted-fit reuse, strict descendant-path handling, atomic pagination, renderer and converter entrypoints, readability/rounding/source-map tests and the original requested-font provenance gap. Implement and verify the shared composition/preview/export path before claiming complete quote coverage, then continue code/metric/timeline/chart internals, bounded repair, Auto arrange and font/native fidelity. This is planned next work, not completed integration.\n\nA fresh audit after the original backlog resolution finds zero open Dependabot security alerts in all seven repositories. The only unrelated new PR is website [#19](https://github.com/Data-Advantage/openpresentation-site/pull/19), `claude/openpresentation-design-review-40j83i`, observed at `246aaa165d3dffb4c5e8b1a59376cfd4d47f760e`; it was recently updated and left untouched as independent work. All earlier PR dispositions and verified public deployments remain as recorded below. User authorization for pushes, PR updates, merges, tags, publication and deployments persists; remaining checks are release gates, not a request for renewed permission. The full goal stays active.\n\n## Previous checkpoint \u2014 standalone quote layout candidate; evidence checkpoint merged\n\nCore evidence [PR #45](https://github.com/OpenPresentation/opf/pull/45) merged as `24f64d67ef907282d73c25d04e80696879ab291f`, tree-identical to reviewed `b3659b0889414737ce82f552ea2753019bf9f1c5`. Core Node 20/24 CI `34387935655`, coordinated source/registry CI `34387935681`, Windows/macOS CLI and packed-install CI `34387935660`, and Bugbot pass. The failure email/budget questions and original PR backlog are resolved as recorded below.\n\nNext branch `codex/shared-quote-layout-20260909` adds standalone `layoutQuote` body/footer measurement with styles, source mappings and explicit internal failures. It is additive and unreleased: existing composition, preview, export and pagination are not switched to it. All 426 core tests plus preservation suites pass on Windows Node 20/24; six new quote cases and public declaration imports pass. The repeated actual-font wide/portrait check produces identical source/runtime/font-bound evidence on both runtimes. See [the implementation scope, report and remaining integration gates](plans/layout-repair.md#next-increments-and-acceptance-criteria). Finish CI/review before merging; connect all consumers before claiming shared accepted geometry or considering publication. The full deterministic repair, cross-surface workflow and font/native-fidelity goal remains active.\n\n## Previous checkpoint \u2014 original PR backlog resolved; YAML deployed; payload-fit gaps measured\n\npptx.dev [PR #28](https://github.com/Data-Advantage/pptx-dev/pull/28) merged as `b922f2f89fdb1e68f0e71a7f1df638be9c5314d4`, tree-identical to reviewed `dfdede29458bea1afb13f7f07d5e1079f9e9e515`. Linux/Windows application CI `34386017908`, artifact CI `34386017825` and Bugbot pass. Exact READY preview `dpl_6dXvANdwpkPgRPQ31oSKhrGqFHbx` passes eight Edge workflows (25.1s). Production `dpl_9B4YfiTrX3YCvK632T9qwtPTYpMs` is READY on that merge and serves www.pptx.dev, pptx.dev and the existing API/MCP aliases. All eight public Edge workflows pass (28.8s): author/import, quote preview/export, shared navigation, Inspector undo/download/reimport, offline Monaco, hostile SVG, installed-package toolkit and offline YAML/Markdown recovery. All 33 deployed font files and licenses still match actual registry renderer 0.5.1; [fresh font report](evidence/pptx-dev-yaml-fonts-2026-09-09.json). The previous native report remains bound to the adoption #25 download; this YAML deployment run does not add native raster-equivalence evidence.\n\nThe Data-Advantage budget increase restored CI execution. Two subsequent Linux attempts hit an external apt repository hash mismatch during Playwright dependency installation. The final pipeline uses the official matching Playwright 1.63.0 Noble image pinned to `sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27`; Linux executes all tests in it and Windows retains its native job. No checks were waived. All nine original PRs now have a disposition, and their feature/migration replacements are merged and publicly verified. Deferred TypeScript/Commander/Author-copy work remains explicit in issues, as recorded in [the backlog](pr-backlog-2026-09-09.md).\n\nCore [PR #44](https://github.com/OpenPresentation/opf/pull/44) merged as `94e4e019d28a1e16ac7e192b564596077dc2a6fa`, tree-identical to reviewed `8b09dd2757980fdae2471107a874d07bdf3a4fa0`. Coordinated Node 20/24 CI `34385371576`, core CI `34385371565`, Windows/macOS CLI and packed-install CI `34385371589`, and Bugbot pass. The earlier coordinated failure email was caused by a fixture copying the linker without its new package-manager helper; the final revision copies both and passes renewed checks. Windows linking uses junctions with checked target parents, and package-manager calls execute JavaScript entrypoints with literal arguments. No OS setting or elevated symlink privilege is required.\n\nThe next checkpoint, branch `codex/payload-fit-evidence-20260909`, corrects the unreleased explanation coverage to include incomplete code internals and adds a repeatable actual-registry probe. A schema-valid long quote footer produces no composition diagnostic but does produce renderer overflow; a long code label has measured advance 4200.68 pixels against 1128.8 available, with neither composition nor renderer reporting overflow. [Hash-bound evidence and next steps](plans/layout-repair.md#published-payload-fit-gaps) separate font-advance measurement from browser/native glyph behavior. These are priority inputs to shared internal measurement and bounded repair, not repaired layouts. The full layout/font goal remains active. No package was republished or publication ref advanced.\n\n## Previous checkpoint \u2014 layout explanations merged; Windows harness; YAML CI resumed\n\nCore [PR #43](https://github.com/OpenPresentation/opf/pull/43) merged as `1cc549183c6fd2e885f06410471e7142be69410a`, tree-identical to reviewed `d32b3eeedc0340ae3b8b3141a4677195346ddee5`. Node 20/24 core CI `34384042495`, coordinated source/registry CI `34384041071`, Windows/macOS CLI CI `34384041098` and Bugbot pass. Candidate explanations are now on main but remain unreleased. Full repair/font work remains open. Independent [PR #44](https://github.com/OpenPresentation/opf/pull/44), branch `codex/windows-test-harness-20260909`, fixes Windows junction/package-manager invocation and adds actual packed-install CI coverage; final combined-source checks and review remain gates.\n\nThe owner added $10 to the Data-Advantage GitHub Actions budget. YAML CI `34382820569` attempt 2 now starts and executes both Linux and Windows jobs. A missing exact-head Bugbot review was requested once; do not repeat while it is running. The initial billing failure below is retained as history, not a current reason to leave work idle. Finish the running checks/review and then merge/deploy PR #28 if clean.\n\nCore evidence PR #42 merged as `2c1cac7cbbc8d1afc9c26ca0b0fbdaa9b6ee3090`, tree-identical to reviewed `7b8def879883f3f8a42a9aff198620190470144c`, after Node 20/24 package CI `34381607903`, coordinated CI `34381607943` and Bugbot passed. The next source milestone is branch `codex/layout-repair-20260909`: opt-in candidate explanations preserve geometry and measurement calls and expose unsupported internal payload coverage. See [the layout plan and evidence](plans/layout-repair.md). This is unreleased source, not completed automatic repair; no package has been republished.\n\npptx.dev YAML PR #28 is now `e9f21ec007d3e382234c7bd8e062bc062fad471f`. The Escape fix passed both OS CI jobs `34381496268`; subsequent review found comment-only frontmatter, now fixed with parser-based empty-document handling and exact content/browser regression coverage. Latest local evidence: 598 tests, fresh production build and eight Edge workflows. Exact READY preview `dpl_CEw5yBz6cv622CbHvHfzNYvVqz5x` passes all eight workflows (25.8s). GitHub CI `34382820569` **did not start any steps**: both annotations report failed account payments or an insufficient spending limit. Leave the PR open and rerun Linux/Windows CI after GitHub Billing & plans is resolved; final review and public deployment remain gates. This is an infrastructure blocker, not a passing test result. Public pptx.dev remains the verified adoption #25 production below. Continue independent layout/font work while this gate is unavailable.\n\n## Latest checkpoint \u2014 public adoption verified; older PRs resolved or migrated\n\nRead [the current PR backlog and adoption checkpoint](pr-backlog-2026-09-09.md) before acting. Core #40/#13 and all three adoption PRs (website #17, gallery #23, pptx.dev #25) are merged. Exact READY production deployments pass public Edge workflows, including accurate published changelog, all six complete skills, all eight gallery bundle resources, 33 byte-matched renderer font files and offline editable export/reimport. Website #4's recovery #18 is also merged and verified live. The actual public pptx.dev export passes PowerPoint 16 native edit/save/reopen/reimport with a visually inspected raster. TypeScript #16, Commander #19 and the stale Author draft #6 are closed with explicit follow-up issues; js-yaml #20 is superseded by migration #28, with its current gate recorded above. Vercel duplicate comments are disabled and verified through the authenticated CLI; deployment checks and security alerts remain enabled. Schema-generator #13's public-type tightening is documented for a future release. No package was republished; the full layout/font/native-fidelity objective remains active.\n\n## Latest checkpoint \u2014 published content releases; expanded layout/font objective\n\nThe user's [updated objective](plans/ecosystem-objective-2026-09-09.md) supersedes the earlier goal. OPF must remain deterministic and independent of AI/model calls, keys, accounts and paid services. New explicit requirements include bounded layout candidate evaluation/repair with content/readability preservation, shared internal payload measurement, API/CLI/skills/canvas Auto arrange with preview/undo, and broad versioned open-font compatibility and native-platform evidence. The current releases do not complete that objective. Existing composition has heuristic auto-column scoring and explicit pagination; a full scored repair operation and its cross-surface workflow remain unfinished. Read `docs/font-fidelity.md` and the updated font roadmap before continuing that work. Width samples and baseline stability are not font/raster equivalence.\n\nRenderer **0.5.1** is published from `335ed01b2efbbb872894949f2ac0519e35651474`, workflow `34322801526`, npm timestamp `2026-09-09T07:14:52.658Z`. Renderer PR #9 corrected initially ineffective portrait fixtures; reviewed `12a3aa1dfb5196b3bcebe90d7e4ebb235627b0b4` merged as `d8696224e7a99618701e641ef7573ef394489885` after Node 20/24 CI `34323435532` and Bugbot. That test-only source is the new immutable verification/CI ref; the actual registry gitHead remains the publication merge. No renderer republish occurred.\n\nPPTX **0.5.2** is published from `383666b366b8c9b8ed8e7e72934d1d3fd0fb634d`, workflow `34370539691`, npm timestamp `2026-09-09T15:31:43.997Z`. PR #13 reviewed `22418c55b7e4140a7d325770510930f9e81b6b50` passed all Linux/Windows Node 20/24 jobs `34323665995` and renewed Bugbot; the quote-footer finding is resolved. npm processing finished before installation. Core PR #39 merged as `3d9321621486c95d06cc8153e2d30020c624f489` after renewed CI/review, closing the candidate linked-dependency gap.\n\nCore branch `codex/content-release-sync-20260909` updates the release plan, immutable CI refs and pinned registry content tests. Fresh full-set registry ecosystem/fidelity checks pass on Windows Node 20/24; all 805 renderer hashes remain unchanged. Registry signatures (64) and attestations (15) verify. Actual runtime/license payloads match release Git blobs exactly. The [published native report](native-content-release-2026-09-09.md) records actual-registry PowerPoint 16 checks on 19 feature slides, 24 imports and native object/edit preservation. A new registry/native quote verifier proves eight actual registry exports byte-identical to the native-tested wide/portrait files, with glyph separation, save/reopen and six valid imports on both runtimes. Native chart geometry and general text wrapping remain documented gaps. No proprietary fonts are distributed.\n\nDownstream adoption is saved on branch `codex/native-content-adoption-20260909` in each repository:\n\n- Website [PR #17](https://github.com/Data-Advantage/openpresentation-site/pull/17), `56069382de43c504e871cfc9d1e9cc88e83fb1ab`: accurate published changelog and registry showcase manifest. Build, registry dates, audit and four local Edge workflows pass.\n- Gallery [PR #23](https://github.com/Data-Advantage/pptx-gallery/pull/23), `58dd6957c7508d9459007cea4616e9c811f17383`: regenerated eight-resource registry editor/export bundle, full licenses and direct converter dependency. Builder validates/renders 854 documents; 106 tests, build, audit and both full local Edge workflows pass.\n- pptx.dev [PR #25](https://github.com/Data-Advantage/pptx-dev/pull/25), `a7f785da3c4fc0a819091efe617e0e46382531d1`: package adoption, installed-version font/preview labels and shared-hash navigation fix found by the new real wide/portrait quote E2E. Stale async loads and pending URL writes are guarded. 592 tests, typecheck, build, audit and six local Edge workflows pass.\n\nThese new site revisions are **not yet verified production deployments**. Next: complete core/site reviews and CI, verify exact previews, merge/deploy in order, verify public changelog, all bundle/font hashes and complete browser flows, and keep this handoff current. The previous production checkpoints below remain authoritative until replaced with observed READY deployments and public test evidence. The latest audit still finds zero open Dependabot security alerts across all seven repositories; four major compatibility reviews remain (core schema generator/TypeScript, pptx.dev Commander/js-yaml). Pending Vercel duplicate-comment sign-in and missing macOS native evidence remain explicit gaps, not reasons to stop independent layout/font work. Never republish completed versions.\n\n## Latest checkpoint \u2014 quote review fixes and renderer 0.5.1 release gate\n\nRenderer [PR #8](https://github.com/OpenPresentation/opf-render/pull/8), branch `codex/quote-footer-layout-20260909`, saves prepared **unpublished 0.5.1** at `e2d2a0260e7d83831d70e15bd17d173a1600ef0f`. A valid converter review finding also reproduced in the renderer: long quote text could cover its attribution/source footer. Reserving footer space before fitting fixes eight long-quote cases on wide/portrait canvases; two oversized cases retain diagnostics and strict rejection. Full local Node 20/24 suites preserve all 126-deck/805-slide raster hashes. Real Edge tests load the exact four open font faces used for measurement and verify eight actual SVG glyph layouts; renderer CI and publication now execute this browser suite and the existing JPEG suite. Exact-head CI `34322142453` and Bugbot pass. Fresh packed verification, merge/tree check, tag and trusted publication remain gates.\n\nCore [PR #39](https://github.com/OpenPresentation/opf/pull/39) addresses its valid review finding by rejecting candidate dependencies resolved outside installed `node_modules` and linked/non-registry lock records. The new same-version linked-dependency regression passes on Node 20/24. Converter [PR #13](https://github.com/OpenPresentation/opf-pptx/pull/13) has the corresponding quote fix and extended packed/browser checks in progress; its older `422f1e39e643cbb1c23260f0c9ddef7a3c6ec722` evidence is a historical candidate, not verification of subsequent edits. Next order: renderer 0.5.1 publication, converter registry dependency/lock update, refreshed packed/browser/native checks and review, then PPTX 0.5.2 publication and fresh registry/downstream adoption. No previously released package should be republished. Native chart geometry and general text wrapping remain measured fidelity gaps; the full goal remains active.\n\n## Latest checkpoint \u2014 Monaco deployed; native fixes in 0.5.2 review\n\npptx.dev PR #24 merged as `1e13e469bda257df197c79bb10948c62c3ea6535`, tree-identical to reviewed `3d372dde1c4e19fd7d59e39fba4c18c1349f5355`. Linux/Windows CI `34319106580` and Bugbot pass. All five Edge workflows pass on exact final preview `dpl_GQbmdzmR2vFzsCo48F5pN3cNaTYr` (18.4s) and public production `dpl_9LnTh1yQ9JzhUcmhBe7vbmsYZtEh` (20.4s), READY on that merge. This includes actual same-origin Monaco 0.56 JSON workers, schema diagnostics, offline completion and recovery. Dependabot #18 is closed as superseded; temporary preview browser credentials were removed. No OPF package was republished.\n\nCore PR #38 merged as `204cd42278992b58f6468a98e1eb168e3531df40` from reviewed `8910b9052c6c6854284d2e9e25506798f0a670d6`, after Node 20/24 coordinated CI `34319241226`, package CI `34319241251` and Bugbot. It preserves the 19-slide published baseline and the substantial native differences found by visual inspection.\n\nPPTX [PR #13](https://github.com/OpenPresentation/opf-pptx/pull/13), branch `codex/native-content-fidelity-20260909`, saves **unpublished 0.5.2** candidate `422f1e39e643cbb1c23260f0c9ddef7a3c6ec722`. Metrics, quotes, code and timelines now follow renderer geometry/shared core text fitting; native chart labels use readable theme text. Quote source/attribution survives, and timelines use editable native lines/markers. Full local Node 20/24 converter/corpus/styled suites pass; the new regression compares 34 text lines to actual renderer typography/geometry at two dimensions and checks chart contrast/native markers. Final candidate PowerPoint 16 checks pass for all 19 edits, 24 reimports, three native tables, one native chart and one picture. Hash-bound [candidate reports/contact sheets](https://github.com/OpenPresentation/opf-pptx/blob/422f1e39e643cbb1c23260f0c9ddef7a3c6ec722/docs/native-content-candidate.md) show the visual improvements; chart ticks/plot geometry and general scalar-text wrapping remain open.\n\nCore branch `codex/native-candidate-comparison-20260909` adds explicit candidate comparison with full runtime/vendor/package/lock hashes and matching registry core/renderer requirements. The default remains registry-only; missing/changed candidate evidence is rejected. The published baseline is retained unchanged. Next gates: review PPTX #13, complete Linux/Windows Node 20/24 packed/browser/native checks, address findings, finalize unreleased changelog/version, merge/tag/publish 0.5.2 only after gates pass, then fresh registry/native verification and downstream adoption. Do not republish 0.5.1 or advance actual-release verification refs early. Continue remaining native fidelity and dependency reviews (core schema generator/TypeScript, pptx.dev Commander/js-yaml), plus the previously pending Vercel duplicate-comment sign-in. The full goal remains active.\n\n## Latest checkpoint \u2014 expanded native coverage exposes export gaps\n\nCore PR #37 merged as `13fc56e0b1af8b24ca93ddd871cb6308bc4b77fa`, tree-identical to reviewed `f3f057cbcfa720e12eb3f46eca0cf8c7e5d9384b`, after Node 20/24 package/coordinated CI `34317326511` / `34317326517` and Bugbot.\n\nThe new [19-slide native feature matrix](native-feature-matrix-2026-09-09.md) uses actual registry core 0.7.0/render 0.5.0/PPTX 0.5.1, published examples and controlled local Calibri. PowerPoint 16 passes open/edit/save/reopen for every slide; Node 20/24 validates all 24 original/native-saved/native-edited deck imports and every native edit. Three native tables, one Office chart and one picture are verified. Hash-bound reports and all contact sheets are portable in `docs/evidence/native-feature-matrix/`.\n\nNative raster review found unresolved metric sizing, quote/source/attribution layout, flattened timeline, code panel styling, chart-axis contrast/ticks and text wrapping differences. Zero schema/converter errors did not detect them. The goal is active and these are priority export fixes; do not claim native equivalence from the successful file/edit checks. No package was republished.\n\npptx.dev Monaco migration is saved in [PR #24](https://github.com/Data-Advantage/pptx-dev/pull/24), branch `codex/monaco-worker-migration-20260909`. Supported worker exports and the new JSON API fix Dependabot #18's build failure. Initial application commit `e9d089462580f2d5c8f1b5d83b283b215a9b0a71` passes Linux/Windows CI `34318174221`, Bugbot, 592 tests and a 214-page build. All five Edge tests pass on exact preview `dpl_FGHxNYV6GDpReD9Ez8KYXNF59xno`; the final test-only revision fixes offline readiness/completion timing and requires renewed review/CI before merge, exact deployment verification and closing #18. Production remains the previously verified `fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a` until that gate completes.\n\nContinue other explicit dependency compatibility reviews and pending Vercel duplicate-comment configuration as recorded below. The previously requested browser passkey sign-in remains separate from working CLI deployment access.\n\n## Latest checkpoint \u2014 pptx.dev browser workflow deployed and native-verified\n\npptx.dev PR #22 merged as `fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a`, tree-identical to reviewed `c18b1fdd5d5e5e2e10b259957ba678def598a2ac`. Linux/Windows CI `34316394032` and renewed Bugbot pass; all three review threads are resolved. Production `dpl_4bQ6pSkG7kiCw8FNAPuEx9RtumTS` is READY on that merge and serves www.pptx.dev, pptx.dev and existing API/MCP aliases. All four actual public Edge tests pass: Inspector author/preview/source undo/redo/share/reimport/offline PPTX export; Author canvas edit/tab changes/undo/redo/source exports/copy/local requests/PPTX/undoable import/malformed-file recovery; hostile shared/imported document DOM checks; exact installed-package toolkit proofs. Local verification includes 592 tests in 60 files and all four starter decks (17 slides) rendered/exported/reimported with the published packages. Starter layout/theme aliases were migrated to resolvable public catalog IDs.\n\nAll 33 deployed font files and full licenses match the actual installed registry renderer, verified by the repeatable `node scripts/verify-deployed-browser-fonts.mjs <registry-consumer> https://www.pptx.dev` on Node 20/24. [Font hashes](evidence/pptx-dev-browser/fonts.json) and [production-native report](evidence/pptx-dev-browser/native-production.json) are portable. The actual Author production download has SHA-256 `383512f28856d1b0d86ddd378d63b5a529e9928983743d9ebac72d99200c8ac4`, identical to the final local candidate fixture. PowerPoint 16 exposes native editable title/table, preserves the title edit through save/reopen, rasterizes the slide and produces a schema-valid reimport with the table intact. The native-saved file hash is `9b1941ae5ae36653790375d28028b20695a197d54811cb6369b528ec9cbb1ffb`. See the [merged workflow and repeatable scripts](https://github.com/Data-Advantage/pptx-dev/blob/fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a/docs/browser-opf-workflow.md). This remains targeted native editability evidence, not broad raster equivalence. Hosted account/AI calls and the legacy Decoder/API are separate from the tested free browser workflow.\n\nThe same continuation merged pptx.dev action maintenance PR #23 as `5c862d23c39f330e4fccdaa5a45bd053ae86a1dc`: real wheel/sdist artifact upload/download, exact filename/hash comparison and Twine checks pass on Linux/Windows in `34315591982`; full application CI `34315591938` and Bugbot also pass. Immutable upload 7.0.1/download 8.0.1 retain ZIP behavior and fatal digest checks. The missing `sdk/mcp` publisher was retired, and Dependabot PRs #16/#17 closed as superseded. PPTX parser lock PR #12 merged as `9c0abf1d6f296a62322fac7c4ef5c91d025a3705`, tree-identical to tested `5016051b45bb35a5d02591cc720a82dda95eae6e`, after all four Linux/Windows Node 20/24 jobs `34307685202`. It matches the parser graph already used by fresh 0.5.1 consumers. No packages were republished, and actual release verification refs stay unchanged.\n\nCore handoff PR #36 merged as `0bc35c24c5011af81ecb5d9a93626d901331fde2` after coordinated CI `34315154485`, package CI `34315154475` and Bugbot. A fresh audit of all seven repositories finds zero open Dependabot security alerts without dismissals. Remaining separate dependency reviews: core TypeScript #16 and schema-generator #13; pptx.dev Monaco #18, Commander #19 and js-yaml #20. Vercel redundant-comment settings still await the previously requested browser passkey sign-in; project protection/security notifications have not been weakened. Preserve unrelated website PR #4 and pptx.dev PR #6. Continue broader native/UX verification and the remaining compatibility reviews; the overall goal is active, not complete or blocked.\n\n## Previous checkpoint \u2014 gallery PowerPoint deployed; pptx.dev browser workflow in review\n\nThis section supersedes pending states in the historical checkpoints below. The goal remains active. No completed package release was republished.\n\nCore PR #35 merged as `264457659c7149e4e8684fab4c0b895388ad2344`, from reviewed `875ea7da4112ec10bb7549c7ca8ebd5053c9b304`, after coordinated CI `34313022598`, package CI `34313022602` and Bugbot. The release plan pins editor example source `eea4b3763026820798cb7e611f01574681c1742c` independently from actual published package verification refs. Registry gallery builds preserve runtime bytes and include complete linked license notices as an eighth hashed resource.\n\nGallery PR #22 merged as `73737dc5c50632c29234d7e5df2704e28a3ba121`, from reviewed `dae38538cb7c90090a9072247af16c8833a84b4f`, after CI `34313026600` and Bugbot. Production `dpl_7bZ8BZqmFTG57NNA48VEMrCVd4np` is READY on that exact merge. All eight deployed resources and registry integrities verify; both real Edge tests pass against https://www.pptx.gallery, including offline author/import, weighted layout, inline edit/undo/redo, OPF download, editable PowerPoint download/native merged-table XML, conversion and UI reimport equality, undo and redo. The full browser PowerPoint workflow is now public.\n\npptx.dev [PR #22](https://github.com/Data-Advantage/pptx-dev/pull/22), branch `codex/published-browser-workflow-20260909`, saves candidate `4c4e6cfb02abc8af62023674e65619dee27efca5`. Inspector and Author now use the published renderer for actual previews and the published converter for local PowerPoint export with shared font measurements. Author adds the published editable canvas and persistent validated undo session across source/preview tabs, plus local OPF/PPTX preview/import as one undoable replacement. These manual operations require no account or paid service; hosted APIs/AI remain separate. No Convex backend code changes.\n\nLocal Windows Node 24 checks pass: 591 tests in 59 files, typecheck, full 214-page production build, zero-advisory audit and all three real Edge E2E tests. Author testing caught and fixed offline canvas remounts losing their font registry. The final test verifies offline tab changes, inline edits, undo/redo, active-draft export, merged-table native XML, browser/Node import equality, import undo/redo and malformed-file recovery. Its actual downloaded file passes PowerPoint 16 native text edit/save/reopen/raster/reimport with one native table. Source SHA-256 `9744aed5c41da31187bb5a98dabec3ee3b0edacb9fe263f698039cb0a7c3b84b`; native-saved SHA-256 `cda33e17824abb265db10f02138797f3c6c36eb0e7231e0b93f3c2587fd928ee`. See [portable workflow/native evidence](https://github.com/Data-Advantage/pptx-dev/blob/4c4e6cfb02abc8af62023674e65619dee27efca5/docs/browser-opf-workflow.md) and its repeatable scripts. This one-slide native fixture does not establish broad raster equivalence.\n\nNext gates: review current pptx.dev PR #22, complete Linux/Windows CI and Vercel preview checks, address findings, merge/deploy, then run all three tests against the actual public deployment and update this handoff. Production pptx.dev remains on `f1f9e700ae2648467b36baf22b3393a216b78780` until then. Continue the remaining dependency-major/action reviews and broader native comparisons. Vercel duplicate-comment settings still await the user's previously requested passkey sign-in; no notification setting or security alert was suppressed. Preserve unrelated website PR #4 and pptx.dev PR #6. All source checkpoints are on GitHub; local generated artifacts are optional evidence, not required resume inputs.\n\n## Historical browser PowerPoint workflow candidate \u2014 September 9 UTC\n\nEditor PR #7 has now merged as `ccd42d9276f7e47a545205469dc2665e03c28a8f`, tree-identical to the fixed candidate below, after Node 20/24 CI `34312112286` and renewed Bugbot. Core PR #35 and gallery PR #22 save adoption. Their initial CI/reviews pass; a final linked-license packaging update requires renewed checks before merging/deployment. The registry builder now preserves runtime JavaScript untouched and includes full package notices plus pinned upstream license supplements in the eighth hashed resource, `playground.js.LEGAL.txt`. Both local gallery browser tests pass with this final packaging, including offline PowerPoint export/reimport. No notification settings were changed; the Vercel browser still requires the previously requested passkey sign-in.\n\nCore deployment checkpoint PR #34 merged as `4fcc217287ddf6f8ec3c6f4f351d9b1d4534df69` after package/coordinated CI and Bugbot. New work is saved in editor [PR #7](https://github.com/OpenPresentation/opf-editor/pull/7), branch `codex/browser-pptx-transfer-20260909`, candidate `eea4b3763026820798cb7e611f01574681c1742c`. Its playground accepts local PPTX in the existing preview/import dialog and exports editable PowerPoint using the preview's text measurements. Import remains a validated undoable change; export commits the active canvas draft and displays conversion notes. No package version changes or republishing are needed.\n\nLocal Node 20/24 full editor suites and offline-after-load Edge E2E pass. Actual downloaded PPTX contains native text and a merged table; PowerPoint 16 permits editing, save/reopen and valid reimport with its native table preserved. The portable [browser/native report and scripts](https://github.com/OpenPresentation/opf-editor/blob/eea4b3763026820798cb7e611f01574681c1742c/docs/browser-pptx-workflow.md) distinguish this targeted fixture from broad raster equivalence. Review caught the converted-image JSON size edge case; the fix retains schema/nesting/item validation and adds a real compressed-image regression on both runtimes. Renewed upstream CI/review must pass before merge.\n\nCore branch `codex/gallery-pptx-workflow-20260909` separates immutable example source refs from published package verification refs and includes the new host module in registry-only gallery builds. Gallery branch `codex/browser-pptx-transfer-20260909` carries regenerated assets and extends actual E2E to offline PowerPoint download/native-table inspection/reimport/undo. Its 106 unit tests, typecheck, audit and full build pass; the initial bundle passes both browser tests. Final fix bundle review, production deployment and public E2E remain gates. These candidate controls are not yet the deployed gallery. The main pptx.dev published renderer/editor/exporter integration and remaining dependency reviews remain open.\n\n## Latest checkpoint \u2014 all three 0.5.1 production deployments verified\n\nThis section supersedes pending merge/deployment states below. Core PR #33 merged as `188c32333a903fed9058d781caaaae4cd10b3d28`, from reviewed `1950afe9804d7e4f7037372d24e8b9d8b864f5fb`. Package CI `34309217317`, coordinated Node 20/24 CI `34309217315` and Bugbot pass. The release plan and immutable PPTX verification ref now select published 0.5.1 at `f7f30082da3568a4f911d42493ffc75c77dd4e14`. No package was republished.\n\n- openpresentation.org PR #16: merge `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f`, production `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm`. All four public Edge tests pass: accurate changelog, six skill files and installer command, mobile layout and exact showcase downloads.\n- pptx.gallery PR #21: reviewed `93f9a720aa6ebe3b48a981f52012f809f6f8cd40`, merge `2ea8ccb75b9a6d9b64a93e6ec36d78100c044f8a`. CI `34309168015` and Bugbot pass. Production `dpl_5cooy8gD6MrZXu5vDDXNNxkBpFjN` is READY on that merge. The deployed manifest and all seven asset hashes verify; both real Edge tests pass, including JSON authoring, preview, inline edit/undo/redo, OPF download and reimport.\n- pptx.dev PR #21: reviewed `be44a1230dd17eb8ae8ca3889304aa2fb084b49c`, merge `f1f9e700ae2648467b36baf22b3393a216b78780`. Linux/Windows CI `34309892749` and Bugbot pass. Production `dpl_wkf6fiWCeyW1E562zHFU9RXwM92X` is READY on that merge. Both real Edge tests pass against https://www.pptx.dev: anonymous inspector author/preview/edit/undo/redo/OPF-download/shared-reimport and the toolkit's exact installed package versions plus render/edit/export proofs. Local self-hosted pages no longer request unavailable Vercel analytics; production analytics remains enabled. Its legacy direct PptxGenJS generator still requires the scoped image-size removal override.\n\nRemaining dependency reviews are explicit: pptx.dev Monaco #18 fails CI because 0.56 changes worker export paths; Commander #19 requires Node >=22.12 while its CLI promises Node 20; js-yaml #20 fails codec/API tests because version 5 changes exports. Evidence and migration requirements are posted on each PR; none was blindly merged. Core TypeScript #16 and schema-generator #13 remain separate compatibility reviews. pptx.dev actions #16/#17 and its obsolete missing-sdk/mcp publish workflow still need maintenance. Vercel duplicate comments await the previously requested browser passkey sign-in; no alert or notification setting has been suppressed.\n\nNext implementation milestone: free browser PPTX import/export and repeatable complete author/import \u2192 preview/layout \u2192 edit/undo \u2192 export/reimport coverage, then integration of the published renderer/editor/exporter in pptx.dev's main flow. The gallery currently exposes OPF transfer only, and pptx.dev's main preview/export still use custom implementations. Targeted native PowerPoint edit/save/reopen/raster evidence covers three slides, not broad native raster equivalence. Preserve unrelated website PR #4 and pptx.dev PR #6. Resume sources from the GitHub merge commits above; generated local artifacts are not required checkpoints.\n\n## September 9 UTC \u2014 PPTX 0.5.1 published and registry/native checks verified\n\nWebsite PR #16 is merged as `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f` after CI `34308522871` and Bugbot. Production `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm` is READY on that commit; all four real Edge production tests pass, including the accurate 0.5.1 changelog, skill installer, mobile layout and unchanged showcase downloads. Gallery PR #21 and pptx.dev PR #21 save their 0.5.1 adoption candidates and await full review/deployment checks. pptx.dev's clean install, audit, 591 tests and typecheck pass; its legacy direct PptxGenJS generator still requires the scoped removal override.\n\nCore PR #33 records the new registry refs and native evidence. Its first coordinated run exposed a local preview-packer omission: the staging builder copied only `dist`, excluding declared vendored runtime/license files. The corrected builder copies every declared literal package payload, validates staging paths and uses portable Windows npm invocation. Fresh local preview packs and consumer checks now pass on Node 20/24; renewed coordinated CI is required before merging. Published tarballs and both registry fidelity suites passed independently.\n\n**PPTX security patch checkpoint:** PR #11 merged as `f7f30082da3568a4f911d42493ffc75c77dd4e14`, tree-identical to reviewed `13d404ab4a8f029622957c8afe53f339c4a6949f`. All four Linux/Windows Node 20/24 jobs in CI `34307186304` and Bugbot pass, including fresh packed installs and real Chromium suites. Actual local Edge and PowerPoint tests pass. Tag `opf-pptx-v0.5.1` triggered successful trusted publication `34307645895`; npm records publication at `2026-09-09T03:37:39.613Z`. Fresh Node 20/24 five-package installs and full pinned registry fidelity suites pass. The consumer audits clean, with 64 registry signatures and 15 attestations verified. The actual registry tarball also passes native PowerPoint edit/save/reopen/reimport and the unchanged three-slide raster measurements. Do not publish again. See the portable [PPTX evidence](https://github.com/OpenPresentation/opf-pptx/blob/f7f30082da3568a4f911d42493ffc75c77dd4e14/docs/security-0.5.1.md). The patch removes the unused parser from ordinary npm installations by shipping unmodified, licensed and hash-verified upstream runtime code. Vendored upstream advisory review remains separate from npm's installed-graph audit.\n\nCore documentation PR #32 merged as `900613f14ab7ed2d57aa6246f6ce7c3519cad39d`. Supported Node 20 types PR #31 merged as `47190652f436e80fa5dd0a947bc1ceeb6db709ff` after all package/coordinated/Windows/macOS checks. Website action PRs #12/#13 merged as `227088da3f2aa48724d53df8625d0dad7d052005` and `174fc0d953526454848da07db9013ab35ceb5e5e` after renewed combined CI. Gallery PR #20 merged as `d01cbfc24855d5e41adc6e092841554196a3e9cb` after full CI `34307438488`; action PRs #16/#17/#18 were closed as superseded. A false-positive missing-pnpm-tag finding was resolved with the live annotated tag and successful exact-head CI evidence. Open Dependabot security alerts were refreshed across all seven repositories: zero, without dismissals. This does not change historical published package graphs.\n\n**Production checkpoint:** pptx.dev PR #15 is now merged as `06ebef116608110fa88ac98cbcd6fe8ea6ad76f1`. Reviewed head `aad6b5ce29dc4ed5b03a7982121ff4a7ea4543bc` passed Linux/Windows CI `34304827786`, Bugbot, an actual adapter build and deployed preview E2E. Production `dpl_638zt5oC7grWNTYEXL3XM4cFMbGE` is READY on the merge, with www.pptx.dev, pptx.dev and API/MCP aliases. The real Edge inspector author/preview/edit/undo/redo/OPF-download/shared-reimport test passes on https://www.pptx.dev. GitHub open Dependabot alerts are now zero without dismissals. SDK/CLI source builds use the single audited root workspace, and standalone output remains supported outside Vercel. This is the first adoption baseline; the main custom preview/export still needs replacement.\n\nCore PR #30 merged as `6967b037c934c665e312086e232545cb71753bcf` after Node 20/24 package/coordinated checks, full Windows/macOS core/CLI checks and Bugbot. Renderer maintenance PR #7 merged as `ad59248ad8dbf11e519c1ba75e95d6d3fa4a39ed`; editor maintenance PR #6 merged as `aeb2871ba381bf97656e58418b5271ec764ed0d5`, both with Node 20/24 CI and Bugbot. These add grouped weekly Dependabot, unfiltered audits and reviewed immutable actions; no package version changed or was republished. Existing published verification refs remain correct.\n\nVercel duplicate bot-comment configuration requires a browser passkey sign-in. CLI authentication and production deployment work. The user was asked to complete the open login page when convenient; no notification/security setting has been changed yet. Continue unaffected work. pptx.dev action PRs #16/#17 remain for individual review; the obsolete missing-sdk/mcp publishing workflow also needs maintenance. Existing PPTX 0.5.0 keeps its older dependency graph; 0.5.1 fixes ordinary new installations without the incompatible downgrade.\n\nThis checkpoint supersedes the historical pending states below. Core PR #29 merged as `e49278514ca3f98b0e14e47ceaa4315adada00b1`. All five intended package releases and the six-skill npx installer remain published; do not republish them. The release plan already pins their actual immutable release commits.\n\nWebsite security PR #15 merged as `2f1b5428a06079e70f3ad67653768fa55a8c463c`; production `dpl_Bdxr6u3j6rdEjp9fJP9RbLp4f2pS` is READY on that commit. All four public-site browser tests pass, including the accurate changelog and complete skill files/clipboard command. Gallery security PR #19 merged as `7d661c074a73dc81487a713a2af040246e62a097`; production `dpl_3GbDE7grPv3zCyCzfzhgAKuCuTsg` is READY on that commit. Both public gallery browser tests pass, including exact bundle hashes and OPF author/edit/undo/download/reimport. Both upgrades passed CI and Bugbot before merging. See [September 9 security evidence](security-2026-09-09.md).\n\npptx.dev PR #15's earlier standalone/adapter packaging failure is resolved: ordinary builds preserve standalone self-hosting, while Vercel uses its adapter output. The exact final commit, full CI and production evidence are recorded above. Its primary renderer/exporter adoption remains incomplete.\n\nCore security work is on `codex/security-policy-20260909`: patched js-yaml/esbuild, unfiltered CI audit, consistent LF text checkouts, reviewed immutable actions in the portability workflow, and routine Node-type major-update policy. TypeScript 7 PR #16 remains deferred because of tsup declaration-bundler incompatibility. Schema-generator PR #13 changes the exported ContentPayload type and remains separate for consumer compatibility review; the security fix does not depend on it. Node 26 types PR #15 is closed because declarations must match the minimum Node 20 runtime. No security alert is dismissed.\n\nRemaining work: merge the updated core 0.5.1 verification refs and deploy downstream adoption/changelog (website PR #16 is prepared with verified npm dates and unchanged showcase bytes); finish application action PRs and redundant Vercel comments; free browser PPTX import/export controls and repeatable complete workflows; actual published renderer/editor/exporter integration in pptx.dev; broader native PowerPoint comparisons. Preserve website PR #4 and pptx.dev PR #6. Native PowerPoint evidence remains three targeted slides, not broad pixel equivalence.\n\n## Latest checkpoint \u2014 deployed installer and gallery; pptx.dev integration underway\n\nUpdate: pptx.dev [draft PR #15](https://github.com/Data-Advantage/pptx-dev/pull/15) saves the compatibility/security candidate at `08fab78`. A fresh Windows Node 24 frozen installation passes 588 tests, typecheck and compile build. Its root audit is now zero: an exact-version pnpm override removes PptxGenJS 4.0.1's unused image-size dependency, and an installed regression test confirms it cannot resolve while text/table/image export works. This does not patch image-size or change existing public npm packages; separate SDK lockfiles still have an esbuild advisory. Browser testing subsequently found missing-auth configuration assumptions on public inspector pages; fixes and repeatable E2E are being added before deployment. Core pnpm/action-setup PR #12 merged as `e43e263795c824b0fe6bddc4b37deb612a196766` after renewed combined Node 20/24 checks. Gallery GitHub open security alerts have now reached zero without dismissals.\n\nThis section supersedes pending states in the historical checkpoints below. All five intended packages are published: core 0.7.0, renderer 0.5.0, PPTX 0.5.0, editor 0.4.0 and CLI 0.5.0. Do not republish them. Core PR #28 merged as `51445f03b70bed896e53e346f2fb7b2c04293b94`, with renewed review and package/coordinated/Windows/macOS checks. The release plan and published CLI test source are pinned to the actual CLI release commit, independently of future local CLI development.\n\nWebsite PR #14 merged as `49d30c6a25d684e7f1a3cbdca44ec565e1b9472f`; production deployment `dpl_6iQrr4VNh9Mu61DvdJXJ6Xs9c8Rc` serves that commit. Four production browser tests pass: accurate releases, mobile layout, exact showcase downloads, and the copied npx installer command plus every served skill file hash. The changelog and supported skill installation documentation are live. Preserve unrelated website PR #4.\n\nGallery PR #15 merged as `188758dcde7248f70ceeb44238ba5986be4c91d0`; production deployment `dpl_6WQqZZAeS28tDCxuMLa6dJeWw7oo` serves that commit. Two production browser tests verify the seven deployed bundle files against their hashes and a real JSON-author/preview/inline-edit/undo/redo/OPF-download/reimport flow, including a styled merged table. Local verification passes 106 unit tests, a 1,925-page build, catalog checks and zero npm advisories. Browser PPTX import/export controls are still absent from the editor example: do not claim this OPF workflow proves PPTX UI coverage.\n\nCore Dependabot checkout PR #10 merged as `84c757e55234ea8c8706ba8717717d7a4c541005`; setup-node PR #11 merged as `414c40fb6bfa2f7f33714ddb949f43a7f8ce70d4`. Both received migration review and passing Node 20/24 checks. pnpm/action-setup PR #12 has a resolved adjacent-line merge conflict and renewed CI pending on `9f10ef3`. TypeScript 7 PR #16 remains unmerged: explicit Node globals fix its first error, but tsup's declaration bundler fails against the removed legacy TypeScript API. Failure evidence is posted on the PR. Review other majors individually; security alerts remain visible.\n\npptx.dev work is on Data-Advantage/pptx-dev branch `codex/published-ecosystem-adoption-20260908`, based on `4a1fc69af09addd37fe62500a1ab8b50fa63cbf8`. It upgrades the four OPF dependencies to the published set, updates vulnerable dependencies and replaces AI canaries with compatible stable releases. Its 575 existing tests, typecheck and compile build passed, followed by a new installed-package edit/undo/redo/export proof. Running the formerly Unix-only standalone playground tests then exposed unbounded palette traversal of recursive groups; the fix and regression coverage are in progress. No pptx.dev candidate is deployed yet. Its primary preview/export still use custom implementations, so dependency upgrades alone do not establish complete adoption. Preserve unrelated PR #6. Remaining high image-size advisories have no published patched version; do not dismiss them or claim a clean audit. SDK lockfile maintenance, application E2E, free browser PPTX workflows and broader native fidelity verification remain open.\n\n## Earlier checkpoint \u2014 CLI installer published; website changelog deployed\n\nCLI 0.5.0 is published. PR #27 merged as `7a2845f45bd7c6f48312b07100851c0ee29a9d1c`, tree-identical to `fcaa85fb50c06dd737f9e71419f3b9a40618184d`, after Linux/Windows/macOS Node 20/24 checks and successful renewed review. Tag `cli-v0.5.0` and trusted publish run `34261574915` succeeded. Registry gitHead/provenance and fresh global/npx-style installs pass on Windows Node 20/24. Do not republish CLI 0.5.0 or any earlier completed package release.\n\nThe supported command is `npx @openpresentation/cli@latest skills install`. It installs all six bundled skills, preserves project instructions and refuses to overwrite customized skills. Core follow-up branch `codex/cli-release-adoption-20260908` advances the release plan to CLI 0.5.0 and adds repeatable published CLI installer checks. Fresh complete registry ecosystem tests pass on Node 20/24.\n\nWebsite PR #11 merged as `c1cbbbb4e91911392612a157155441b523f187dc`. Vercel production deployment `dpl_ApPs9yCN43U6zVsGEkSmfQ6tFRTM` serves that commit. All three browser checks pass against https://www.openpresentation.org: published history and package links, mobile layout, and exact OPF/SVG/PPTX download hashes. The separate website changelog task is deployed. Follow-up branch `codex/skills-installer-site-20260908` adds the newly published CLI 0.5.0, installer quickstart and its immutable documentation snapshot. Four local browser tests pass, including actual command copying and every file hash in all six served skills. Follow-up CI/review/deployment remain pending.\n\nGallery adoption is in progress on `codex/published-ecosystem-adoption-20260908` in Data-Advantage/pptx-gallery. Targeted dependency updates pass 106 existing tests, a 1,925-page build and a zero-advisory audit. Its regenerated registry bundle uses core 0.7/render 0.5/PPTX 0.5/editor 0.4/CLI 0.5 and validates/renders 854 documents. Final bundle checks, browser workflows and deployment remain pending. The existing editor example lacks browser PPTX import/export controls; addressing that gap is separate from updating the bundle. pptx.dev adoption/security and the six core major Dependabot PRs remain open. Historical sections below are superseded by these checkpoints.\n\n## Windows continuation checkpoint \u2014 registry releases complete\n\nRenderer 0.5.0, PPTX 0.5.0 and editor 0.4.0 are all published with provenance after exact-head checks and review. Their published merge refs are recorded in `release-plan.json`; do not republish them, core 0.7.0 or CLI 0.4.0. Fresh full-set registry ecosystem and pinned rendering/export fidelity checks pass on Windows Node 20/24, including the unchanged 805-slide raster baseline. Registry editor pointer/keyboard typing, formatting and undo pass in Edge. Registry PPTX passes native PowerPoint open/edit/save/reopen/reimport and two targeted border raster assertions; broad pixel equivalence is not established.\n\nCore PR #26 merged as `533b53cd7db3cf58e9ebf5fbd987741323ea2699` after full Node 20/24 coordinated CI, package CI and successful Bugbot review on `3d1c2bbc7c68a3f74f68232d1ae320a4f41ccdfd`; merged tree is identical. The complete release plan and immutable CI refs are on main.\n\nContinue CLI 0.5.0 on `codex/skills-installer-20260908`, [PR #27](https://github.com/OpenPresentation/opf/pull/27). All six skills are bundled with safe install/update/status, offline packed installation and Windows checks. It remains unpublished. Review found overly strict ancestor-symlink rejection; canonical parent resolution now supports linked project directories while rejecting linked skill destinations, and macOS CI was added. Wait for final CI/review before release.\n\nMain website work is on Data-Advantage/openpresentation-site branch `codex/published-ecosystem-adoption-20260908`, [PR #11](https://github.com/Data-Advantage/openpresentation-site/pull/11), initial head `83ccb57`. It adds the accurate published changelog, core 0.7.0 and complete registry showcase, targeted security fixes with zero current local audit advisories, grouped Dependabot and browser/download CI. Local build and three browser tests pass; deployment remains pending. Gallery and pptx.dev adoption/security/full workflow E2E remain open. See [current Windows evidence](evidence-2026-09-08-windows.md). Historical checkpoints below are superseded where they describe unpublished downstream packages or stale lockfiles.\n\nThe user requested an immediate stop and remote checkpoint to move computers. Resume from GitHub; do not depend on the old computer's temporary worktrees, tarballs, logs, or browser state. The goal is ongoing, not completed or blocked. User authorization covers commits, pushes, PR creation/updates/merges, tags and npm publication. Recheck CI/reviews and exact commits before releases. Do not bulk-merge unrelated Dependabot PRs. No subagents unless requested.\n\n## Goal\n\nMake OpenPresentation a polished, reliable, fully open presentation ecosystem for people and AI agents: authoring JSON, dynamic layout, browser preview, intuitive WYSIWYG editing and editable PowerPoint export. Keep core free, open source, provider-neutral and usable without a paid service or AI account. Publish compatible packages in dependency order and prove the workflow using clean registry installations. Advance presets, rich text, tables, media, fonts and layout fidelity. Evaluate schema support, browser interactions, rendering and native PowerPoint compatibility separately. Public sites must showcase the same installable tools users receive.\n\nEarlier PR #8 reconciliation and the missing core 0.4.0 changelog entry are already handled; do not repeat them. The NEW public website changelog request below remains open.\n\n## Portable checkout map\n\nClone sibling repositories so the core ecosystem scripts can find their sources. Read each repository's AGENTS.md. Avoid resetting any existing user checkout.\n\n| Repository | Branch to resume | Remote checkpoint |\n| --- | --- | --- |\n| OpenPresentation/opf | codex/styled-table-release-sync-20260908 | [PR #26](https://github.com/OpenPresentation/opf/pull/26), this handoff and verification scripts |\n| OpenPresentation/opf-render | codex/styled-table-cells-20260908 | [PR #6](https://github.com/OpenPresentation/opf-render/pull/6), head `b47bba101ab78dc226d9ff848bb8622e3a0109e1` |\n| OpenPresentation/opf-pptx | codex/styled-table-cells-20260908 | [PR #10](https://github.com/OpenPresentation/opf-pptx/pull/10), head prefix `a0e9d14` |\n| OpenPresentation/opf-editor | codex/styled-table-cells-20260908 | [PR #5](https://github.com/OpenPresentation/opf-editor/pull/5), head prefix `21449a7` |\n| Data-Advantage/pptx-gallery | main | Deployed merge `12fcf77399cb6ae21d3bfcea5cfafb37c3323b79`, PR #14 |\n| Data-Advantage/openpresentation-site | main | Deployed merge `280a616701320cd1ca8d2484cf166fb91d882137`, PR #10 |\n| Data-Advantage/pptx-dev | master | Newly added integration scope; old checkout `4a1fc69af09addd37fe62500a1ab8b50fa63cbf8`, not yet audited or modified |\n\nUse fresh fetches to resolve full commit IDs/current PR states. The old machine's primary downstream checkouts were deliberately left untouched and lag origin; release work happened in temporary clones. Gallery's primary checkout contains a pre-existing untracked `pnpm-workspace.yaml`; not part of this work. Temporary PPTX `artifacts/` contains generated evidence/build outputs; source fixtures and builders are committed and can regenerate it.\n\n## Already published \u2014 do not republish\n\nCore PR #25 merged as `21e4cfca617ddfebeee85f79b09c35b2e82637e1`, with tree identical to reviewed head `e71f7c3d1b9a99bf210d038ceac613f72f41f894`.\n\n- `@openpresentation/opf@0.7.0`, tag `opf-v0.7.0`, successful publish run `34243706990`.\n- `@openpresentation/cli@0.4.0`, tag `cli-v0.4.0`, successful publish run `34244109903`.\n- Both registry gitHeads match the merge and have SLSA provenance. Tarball integrities matched the tested candidates. A fresh global CLI registry install reported CLI 0.4/core 0.7 and validated the styled fixture.\n- Core 404 tests, CLI 70 command checks, packed package checks, strict installed TypeScript fixture and coordinated Node20/24 CI passed before release. These results do not establish that later downstream edits are verified.\n\nCore 0.7 introduces strict styled cells `{value, style?, rowSpan?, colSpan?}` with covered positions `null`; merge ownership validation; shared anchor geometry and `.value` editing paths; padding, alignment and spanning row heights; pagination that keeps connected vertical merges. Equal column widths and content-fit row heights remain limitations for importing native arbitrary table geometry.\n\n## Immediate release gates\n\n### Renderer PR #6: draft, not published\n\nVersion 0.5.0, core dependency ^0.7.0, registry lockfile current. Prior head `b63bd0e` passed standalone Node20/24 full suites and unchanged 126-deck/805-slide raster baseline against actual registry core 0.7. A fresh candidate consumer passed and matched runtime bytes.\n\nBugbot review on that head completed neutral with two findings. They must be assessed, not treated as a passing review:\n\n1. Claimed vertical alignment was ignored. Core `layoutTable` already offsets `cell.textBox.y`; scalar and rich renderer paths consume that box. New baseline assertions prove top/middle/bottom movement. Do not add a second offset.\n2. Valid finding: default neighboring edges could cover custom borders. Follow-up commits `dabf91b` and `80ae8bb` render defaults before explicit edges and remove overlapping default segments, including zero-width/transparent/dashed edges and partial merge boundaries. Legacy tables without custom borders retain their prior rendering path.\n\nThe final head is `b47bba1`, including the regenerated tracked `dist/svg.js`. On the identical source/build from `80ae8bb`, focused styled-table regressions pass on Node20/24 and renderer syntax checks pass. Full suite/raster baseline, renewed CI/review, and a new packed candidate remain required. The previous tarball integrity is obsolete. Review threads were left open for evidence-based follow-up. PR description records these distinctions.\n\nNext: run checks on exact head, address review findings, mark ready, wait for CI/review, merge with exact-head protection, verify merged tree, tag `opf-render-v0.5.0`, monitor trusted npm publish, verify registry version/gitHead/provenance/integrity against the new tested tarball.\n\n### PPTX PR #10 and editor PR #5: draft release preparation\n\nTheir implementation and final README/CHANGELOG/package.json version changes are pushed. **Lockfiles still describe the preceding dependency set.** This is an explicit unfinished checkpoint because renderer 0.5.0 does not exist on npm yet. Do not merge or publish these drafts as-is.\n\nAfter renderer publication, regenerate lockfiles from the registry and run clean installs. PPTX targets 0.5.0; editor targets 0.4.0. Both require core ^0.7.0 and renderer ^0.5.0 (optional peer, exact 0.5.0 development dependency). Use Node20 and Node24; prior toolchain was npm11.16/pnpm10.33.2. Run standalone suites **without NODE_OPTIONS source loaders**. Pack final versions, test fresh consumers, verify runtime bytes, update PR evidence, review/merge and tag in dependency order. Inspect workflows for exact tag patterns (PPTX `opf-pptx-v0.5.0`; verify editor pattern before tagging).\n\nPPTX implementation preserves supported native fills/alpha, margins, alignments, borders/dashes, rich runs and dense merges; conditional styles resolve band/edge/corner precedence and archive-local line references. Malformed merges retain source text with diagnostics. Different border segments on merge continuations preserve anchor style with a diagnostic. Native arbitrary row/column geometry, effects and PowerPoint raster parity are incomplete.\n\nEditor uses `.value` inline paths, preserves styles/spans, rejects invalid structure, supports rich promotion/selection formatting and undo; covered slots have no editable target. Browser and model fixtures are committed.\n\n### Core release sync: draft\n\nThis branch adds installed-package styled editor browser fixture generation to `scripts/test-packed-ecosystem.mjs` and styled renderer/PPTX tests to `scripts/test-registry-fidelity.mjs`. The latter clears NODE_OPTIONS in child tests to prevent a source loader invalidating registry claims. Syntax and diff checks pass; final full registry checks are pending.\n\n`release-plan.json` still describes the previous complete published set. Update it and `.github/workflows/ecosystem-ci.yml` immutable downstream refs only after all new packages are available. Use the published core merge for core fixtures. Run fresh Node20/24 registry ecosystem/fidelity checks and actual installed-package browser interactions. Do not conflate generated browser bundles with executed UI tests.\n\nUseful core commands: `pnpm test:registry-ecosystem`, `pnpm test:registry-fidelity`, `pnpm prepare:gallery:registry`, `pnpm build:showcase:registry`. Read their scripts and release plan for arguments/setup. Source-coordinated tests may use `scripts/register-local-opf.mjs`; registry verification must not.\n\n## Evidence and public integration status\n\nBefore the final renderer border follow-up, actual Edge browser interaction verified:\n\n- PPTX native styled import: 12 checks; rich import: 20 cases; conditional table styles: 11 checks.\n- Editor legacy rich fixture: 14 checks. Styled fixture: 37 passing assertions including repeated style/undo checks, real Roboto/Roboto Mono loading, double-click/keyboard edits, empty values, scalar promotion, Bold, partial selection/Italic, cancellation, merged glyph containment and undo.\n- These were coordinated development builds; final installed-registry browser runs still remain. No styled-table native Keynote inspection was completed. No native PowerPoint raster equivalence claim is supported.\n\nGallery and main site were deployed and verified against the PREVIOUS full package set: core 0.6, renderer 0.4, PPTX 0.4, editor 0.3, CLI 0.3. Prior checks covered 854 gallery documents, 593 site routes, six skills and 584 raw resources. They do not yet showcase the full new styled release set. Update assets, docs and deployments only after final registry verification, then test actual public workflows. `pptx.dev` has not yet been assessed.\n\n## New user priorities to address after resume\n\n1. **Dependabot overload.** Inspect notices/open PRs across all relevant repos. Screenshot examples from core: TypeScript 5.9.3\u21927.0.2 (#16), @types/node20\u219226 (#15), Biome (#14), json-schema-to-typescript15\u219216 (#13), pnpm/action-setup5\u21926 (#12), setup-node4\u21927 and checkout4\u21927 (#10). These are examples, not a current authoritative PR inventory. Evaluate runtime/schema/build compatibility, security significance and CI; safely group/schedule updates and reduce redundant reviewer notifications where appropriate. Preserve security visibility. Do not blindly merge major upgrades or suppress useful alerts.\n2. **Public changelog.** Update https://www.openpresentation.org/changelog from actual published release contents and dates. Clearly distinguish live npm releases from upcoming drafts and ensure site deployment is verified. The earlier core CHANGELOG0.4 fix does not satisfy this request.\n3. **Easy skill installation.** User wants a supported npx-style skill installer like Convex's AI-file installation experience, documented and suggested in relevant CLI output. Current `docs/agent-skills.md` instructs copying entire self-contained folders; do not assume an npx installer already exists. Research current official Convex/installer guidance before choosing syntax, implement/test actual clean-project installation and sensible updates across supported agents, keep provider-neutral, document it on site/repo, and add concise actionable CLI guidance. Avoid overwriting existing user skill configuration without an explicit update flow. Six OPF skill entrypoints: author, layout, presets, edit, export, inspect.\n4. **Real downstream adoption and E2E quality.** Audit openpresentation.org, pptx.gallery and Data-Advantage/pptx-dev (https://pptx.dev) for exact dependencies/bundles and user workflows. Adopt the tested published set and assess quality visually and functionally. Inventory existing model, package, browser and E2E tests; automate missing end-to-end paths from author/import through layout/preview, editing/undo, export and reimport. Test deployment versions and editable native output; report native-app fidelity gaps explicitly. Do not answer \u201Call integrated\u201D or \u201CE2E complete\u201D from the existing unit/corpus evidence alone.\n\nContinue in reviewable milestones under existing authorization. Keep a concise evidence trail, preserve user work and stop relying on old-machine absolute paths.\n"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"slug": "handoff-2026-09-10-wrap-up",
|
|
77
|
+
"file": "docs/handoff-2026-09-10-wrap-up.md",
|
|
78
|
+
"title": "Source wrap-up and two-machine continuation \u2014 September 10, 2026",
|
|
79
|
+
"markdown": "# Source wrap-up and two-machine continuation \u2014 September 10, 2026\n\nRuntime update (September 10): use **Node 24 only** for new development and verification; see [migration instructions](migrations/node24.md). Historical Node 20/24 results and commands below describe prior checkpoints. Keep distinct browser/OS/native gates and the existing Office recovery prerequisite.\n\nThe user requested that existing integration work be committed, synchronized and merged, then continued by a Mac project owner and a separate Windows native-PowerPoint testing owner. This is a source milestone. The broader [accepted objective](plans/ecosystem-objective-2026-09-09.md), publication, public adoption and unresolved native/quality gates remain open.\n\n## Portable checkpoint\n\nFetch GitHub `main` in each repository. These PRs identify the complete integration and its merge commits; verify their state from GitHub before resuming. The branch is `codex/shared-metric-integration-20260910`. Do not reconstruct work from an old computer's paths.\n\n| Repository | Wrap-up PR | Reviewed source checkpoint before final handoff documentation |\n| --- | --- | --- |\n| OpenPresentation/opf | [#61](https://github.com/OpenPresentation/opf/pull/61) | `1cc9be9788e7ae0e940af94feb028347e27433b0` |\n| OpenPresentation/opf-render | [#12](https://github.com/OpenPresentation/opf-render/pull/12) | `4b9706367039c13399d0a8b33c9e2bd305904c4b` |\n| OpenPresentation/opf-pptx | [#16](https://github.com/OpenPresentation/opf-pptx/pull/16) | `df43cfcf58cf9bcee6435620e36d9e9bfd5a253c` |\n| OpenPresentation/opf-editor | [#11](https://github.com/OpenPresentation/opf-editor/pull/11) | `26a04baed9ca1715c5ad50e2f3239d6cba67786e` |\n\nUse named sibling checkouts `opf`, `opf-render`, `opf-pptx`, `opf-editor` for coordinated scripts. The three public application repositories remain `Data-Advantage/openpresentation-site`, `Data-Advantage/pptx-gallery` and `Data-Advantage/pptx-dev`. Their prior published-set adoption is recorded in the full [historical handoff](handoff-2026-09-08.md). Audit current remote state before further changes.\n\n## Source and release boundaries\n\nThe actual published set remains core **0.9.0**, CLI **0.7.0**, renderer **0.7.0**, PPTX **0.7.0**, editor **0.6.0**. Do not republish those or any earlier versions. No package version, npm dist-tag or public deployment changes in this wrap-up. `release-plan.json` retains those exact versions and their historical immutable verification refs. The newly integrated APIs require coordinated sources or candidate tarballs; old registry dependencies alone do not provide them.\n\nCI now checks the current downstream PR against immutable coordinated source refs and installs all four candidate tarballs into a clean consumer. The existing per-package registry-predecessor `test:packed` scripts remain release gates after their predecessors are published. Core's coordinator retains separate exact-registry installation, installed-browser, CLI and fidelity tests using the published plan/historical harnesses. A source baseline is scoped only to the source step. Candidate versions such as `0.4.0-preview.11` are temporary staging labels, never releases.\n\nThe [shared-text corpus review](evidence/shared-text-regression-review.md) accepts an 805-slide regression checkpoint after review of all 17 overview sheets and prior milestone detail reviews. Linux renderer CI agrees with the Windows Node 20/24 manifest. This is not a polished-gallery or native-fidelity approval: estimated rich spacing, missing external data/media, dense content and excessive whitespace remain quality work. Historical failures and the old published shared-code baseline are preserved.\n\n## Wrap-up corrections and checks\n\nThe original CI failures were test/integration issues, not spending-limit failures: downstream jobs installed older core APIs; three cross-package assertions still assumed one native shape per text item; the text-corruption checker interpreted binary PPTX/font evidence as UTF-8. The corrected assertions check accepted line anchors, top/height, exact editable words and no-refit behavior. Binary evidence is skipped only for recognized extension/signature pairs; text/JSON/SVG/log checks remain active.\n\nPPTX review corrected clearing a complete tagged heading: it retains its empty role instead of importing an unknown-shape description or promoting body text. All three roles have regression coverage. Scalar placement is explicitly restricted to scalar text/headings, retaining specialized list export. The generated tracked PPTX bundle is synchronized with these changes. Both review findings were resolved.\n\nThe complete local Windows Node 24 coordinated command passes, followed by seven installed-package browser suites: 230 assertions and eight trusted interaction scenarios. Clean candidate checks verify archive/lock integrity, runtime bytes, declarations, export/reimport and actual installed code/editor browser modules. Renderer/editor CI passes Node 20/24; PPTX covers Linux/Windows \xD7 Node 20/24. The final PR checks are authoritative for the latest commit. [Wrap-up evidence](evidence/wrap-up/summary.json) preserves local logs/reports and their checksums. A Windows CLI file-symlink rejection test is explicitly skipped for missing privileges and is covered by Unix CI; no privilege was silently assumed.\n\n## Native PowerPoint remains separate\n\nDo not start another unattended Office retry merely because package CI passes. The [native resume record](evidence/native-resume/README.md) includes the user's Excel-dialog warning and partial success: eight charts opened/saved/reopened, 16 original/saved data imports agree and eight native PNG pairs are identical. The first workbook edit returned; the second `ChartData.Activate()` hung. No edited-deck gate completed. Only owned helper processes were stopped; Office/user documents were not closed and generated-file cleanup completion is unknown.\n\nThe chart harness permits one explicit `-EditSlide` per bounded worker, records progress and does not automatically retry. Dummy-worker controls and temporary registration/removal of all four exact Carlito faces pass. Native text generation passes 24 cases / 144 editable lines per supported Node runtime with identical bytes/geometry; full Office execution remains pending. Fresh metric fixture generation is not native execution. Earlier eight tab deltas above 0.02 pt (maximum about 0.067383 pt) and portrait/right ink at x=497 beyond edge 496.8 remain counterexamples. Keep existing tolerances and raw failures.\n\n## Ownership and continuation\n\n- **Mac owner:** use [this copy/paste prompt](continuation/mac-project.md). Own font/layout product work, bounded repair/Auto arrange, independent review, new dependency-ordered releases, exact registry E2E and all three public applications. Continue the full goal, including selectable/vector PDF and the full Mermaid/general SVG roadmap after font reliability gates are accepted. Those backends are plans, not new implementations in this milestone.\n- **Windows owner:** use [this copy/paste prompt](continuation/windows-powerpoint.md). Own Office readiness, bounded native harnesses, native font/render/edit/save/reopen/reimport evidence and narrow reproducible defect PRs. Preserve user Office work. Coordinate product changes with the Mac owner; avoid competing release/deployment changes.\n\nThe six-skill installer (`npx @openpresentation/cli@latest skills install`), previous website changelog/public-set adoption and older PR triage are already implemented; inspect current state rather than recreating them. Keep security alerts visible, test new dependency upgrades and retain weekly grouping/reduced redundant notifications. The full ecosystem goal is not complete when these source PRs merge.\n"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"slug": "handoff-2026-09-15",
|
|
83
|
+
"file": "docs/handoff-2026-09-15.md",
|
|
84
|
+
"title": "OpenPresentation owner handoff \u2014 September 15, 2026",
|
|
85
|
+
"markdown": "# OpenPresentation owner handoff \u2014 September 15, 2026\n\n## Outcome and boundaries\n\nThe published websites demonstrate editable OPF JSON and live slides. Reusable\npackages provide an open local authoring foundation for scoped developer\nintegrations today. This is not full PowerPoint parity or a finished all-feature\npresentation editor.\n\nThe owner requested committed, remotely preserved work, validated merges or\nexplicit roadmap deferral, and a completed PR cleanup. Eleven dependency PRs\nand four shared-furniture PRs were accepted. One Node26-types update was closed\nto retain Node24. Four remaining shaping PRs conclude as docs/evidence only;\ntheir complete runtime prototypes remain on remote archives. No failed font\nimplementation is promoted, no history is force-pushed, and archives must stay.\n\nUse the original PRs listed below for final merge/check receipts. This document\nis committed in core83 before its final checks/merge and does not invent its\nown future merge SHA. Merging a roadmap does not release its archived feature.\n\n## Repositories and environment\n\n| Repository | Default | Responsibility |\n| --- | --- | --- |\n| [OpenPresentation/opf](https://github.com/OpenPresentation/opf) | main | Schemas, catalogs, composition/edit/lint, CLI, six skills and plans |\n| [OpenPresentation/opf-render](https://github.com/OpenPresentation/opf-render) | main | Font preparation, rendering and image/PDF output |\n| [OpenPresentation/opf-editor](https://github.com/OpenPresentation/opf-editor) | main | Reusable editor controls and source-preserving interaction |\n| [OpenPresentation/opf-pptx](https://github.com/OpenPresentation/opf-pptx) | main | Editable PPTX import/export and provenance |\n| [Data-Advantage/openpresentation-site](https://github.com/Data-Advantage/openpresentation-site) | main | Main website/playground |\n| [Data-Advantage/pptx-gallery](https://github.com/Data-Advantage/pptx-gallery) | main | Gallery and embedded editor demo |\n| [Data-Advantage/pptx-dev](https://github.com/Data-Advantage/pptx-dev) | master | Authoring/inspector/tooling website |\n\nUse Node24. Core/site/gallery pin pnpm10.33.2; pptx-dev pins pnpm11.1.3;\nstandalone libraries use npm lockfiles. Read each AGENTS.md, use codex/ branches\nand focused commits/PRs as work proceeds. Gallery requires Conventional Commits\nand its documented coauthor. Read relevant OPF skills for document operations.\n\nLocal clones live under /Users/michael/Source. This handoff is portable:\nGitHub contains archives and committed evidence. Do not depend on temporary\nworktrees, local dependency symlinks, untracked output or this Mac's credentials.\n\n## Published baseline and accepted source\n\nRegistry inspection confirmed @openpresentation/opf **0.10.0**, opf-render\n**0.8.0**, opf-editor **0.7.0**, opf-pptx **0.8.0**, and cli **0.8.0**.\nHome/playground support JSON editing and preview edits in both directions,\ncontextual catalog choices, indentation, paired quotes and other code-editor\nassistance. Shared controls and contextual lint/design contracts are available.\n\nThe CLI supports create, validate, lint, revision-guarded JSON edits, data\nimport, pagination, schema/catalog lookup and skill installation/update/status.\nDo not invent CLI render/export commands: use documented library/UI APIs.\nSchema-property access is not proof of full WYSIWYG interaction coverage.\n\nCore79 (d0c8841), renderer20 (130a2fa), editor17 (cfdeae6) and PPTX34 (c077b7a)\nadd accepted shared header/footer geometry, editing and provenance. Their main\nCI passed, including coordinated packages and Linux/Windows PPTX checks. These\nnew APIs need a new coordinated release. Do not claim they are in the listed\nnpm versions just because main contains them.\n\nKeep release-plan.json and immutable verification references accurate. Never\noverwrite published versions, change snapshots to conceal regressions or count\nsibling-source imports as installed-package checks. Some older docs/skills\nstill call released APIs unreleased: audit them with the developer quickstart.\n\n## Deployment receipts\n\nLatest retained canonical production checks cover **41 workflows**:\n\n| Website | Verified source commit | Workflows |\n| --- | --- | --- |\n| [openpresentation.org](https://www.openpresentation.org) | bb6b006e5fa18f565779781ad347a839fea4ec83 | 26 |\n| [pptx.gallery](https://www.pptx.gallery) | fe395e4e7187cdb85c2b8a4041ef2801fd81f72d | 5 |\n| [pptx.dev](https://www.pptx.dev) | 3b17ff5366f7a556cf02aae320e6baf87fdf3678 | 10 |\n\nDeployment records and browser logs are in\n[PR consolidation evidence](evidence/pr-consolidation-20260915/README.md).\nThey establish exercised flows, not every capability. The Zod4.6.2 preview\nfailure is fixed/merged in pptx-dev37 using explicit record keys/values and\npublic schema identification.\n\n## Preserved unfinished implementation\n\nEvery library repository retains remote branch codex/archive-shaping-20260915:\n\n| Repository / original PR | Complete immutable prototype |\n| --- | --- |\n| [opf83](https://github.com/OpenPresentation/opf/pull/83) | 36ff66b3d62b39d7d27dcda022b7e79e541bd603 |\n| [renderer21](https://github.com/OpenPresentation/opf-render/pull/21) | 343fb84223f4383ffe546157c6989ccc505c0acb |\n| [editor21](https://github.com/OpenPresentation/opf-editor/pull/21) | ae4cc6426b04c7ca428c1b4acacea2e11d99fa84 |\n| [PPTX35](https://github.com/OpenPresentation/opf-pptx/pull/35) | fbe9a73d012dbd51d65a39251e405e488651a70b |\n\nThese contain HarfBuzz shaping, variable/CFF preparation, prepared SVG glyphs,\nrich-source groups, grapheme/caret/selection/navigation work and native rich/tab\nexport experiments, with tests, licenses and evidence. See\n[the deferred implementation plan](plans/deferred-shaping-20260915.md).\nResume from main and port bounded changes; do not merge an archive wholesale.\n\nRenderer Linux still fails the unchanged 0.1px gate: Source Serif SmText Bold\nmeasures 334.06213682353496px versus Chromium334.193115234375px. Rounding fixes\nfive Linux rows but breaks five macOS rows. Some native platform widths differ\nby more than twice the tolerance. Define an honest supported metric/painting\ncontract; offsets, platform guesses and relaxed assertions do not solve it.\nTrack [renderer24](https://github.com/OpenPresentation/opf-render/issues/24).\n\nArchived editor CI separately has a packed-test mismatch: thirteen rich-input\nworkflows pass but the aggregate expects ten. Repair that assertion and rerun\nthe complete packed command when resuming; the archived run is not green.\n\n[Core87](https://github.com/OpenPresentation/opf/issues/87) and the\n[native plan](plans/powerpoint-acceptance.md) retain image opening, current-content\nprovenance after edit/save/reopen, tab tolerances, notes-master ordering and\nphysical font identity/embedding. Browser, serialization and self-import checks\ndo not establish Office acceptance. Windows host recovery is not authorized:\ndo not retry COM or kill Office processes until recovery is confirmed.\nAptos4.40 is restricted; do not use/distribute it without compatible permission.\n\n## Next milestones\n\nFollow [the developer adoption roadmap](plans/developer-adoption-20260915.md).\nFirst release the accepted increment and provide a clean installed example with\ncurrent API/version docs. Then finish public-site integration in\n[core88](https://github.com/OpenPresentation/opf/issues/88), preserving appearance.\nPackage adoption and feature adoption need separate checks.\n\nBroader work: supported multilingual fonts/fallback/IME/bidi and editing;\nnative Office evidence; bounded deterministic layout repair for dense/nested\ncontent; full visual-editor interaction coverage. Current PDF is raster-backed.\nSelectable vector PDF with legal embedding/Unicode extraction and general SVG/\nsemantic Mermaid follow font reliability. See the linked plans for acceptance.\n\nKeep the foundation provider-neutral and useful offline without an account or\nmodel call. Preserve content, whitespace, formatting, reading order, authored\nintent and undo. Bound layout repair and return actionable failure; never delete\ncontent to fit. AI may be optional application wiring, not a required embedded\ndesign agent. The [broad ecosystem objective](plans/ecosystem-objective-2026-09-09.md)\nremains open. The Codex goal was paused, not completed or replaced by this cleanup.\n\n## Audit record\n\n[Final evidence](evidence/final-handoff-20260915/README.md) records registry\nversions, remote archive checks, all seven repository/worktree inventories and\nlatest archived CI failures. Source audit found no uncommitted source, stashes\nor local-only branch commits. A stale untracked dependency symlink was removed\nwithout changing its target. A legacy temporary directory lacking Git metadata\nwas not treated as an active checkout.\n\nThe four concluding PRs restore runtime/tests/locks/CI to validated main, then\nadd docs/evidence. Verify their final diffs and CI and merge them before reporting\nqueue completion. Do not confuse preserved history with newly accepted code.\n"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"slug": "handoff-mac-owner-2026-09-10",
|
|
89
|
+
"file": "docs/handoff-mac-owner-2026-09-10.md",
|
|
90
|
+
"title": "Mac owner checkpoint \u2014 10 September 2026",
|
|
91
|
+
"markdown": "# Mac owner checkpoint \u2014 10 September 2026\n\nRuntime update (September 10): use **Node 24 only** for new development and verification; see [migration instructions](migrations/node24.md). Historical Node 20/24 results and commands below describe prior checkpoints. Keep distinct browser/OS/native gates and the existing Office recovery prerequisite.\n\nThe active goal covers the full OpenPresentation ecosystem, with font/layout reliability before vector PDF, then SVG/Mermaid, followed by coordinated new releases and public-site verification. This checkpoint does not complete that goal. Read the full [8 September handoff](handoff-2026-09-08.md), [10 September wrap-up](handoff-2026-09-10-wrap-up.md), [ecosystem objective](plans/ecosystem-objective-2026-09-09.md), [font roadmap](plans/font-roadmap.md) and [text placement plan](plans/text-placement.md).\n\n## PR backlog and current state\n\nThe seven-repository audit found only core [PR #60](https://github.com/OpenPresentation/opf/pull/60) open initially. Its TypeScript 7 compatibility changes were reviewed, updated to current main and tested on the exact updated head. Node 20/24 coordinated CI, Mac/Windows portability and Bugbot passed. Local TypeScript 7/core tests and clean packed TypeScript 5.9/7 NodeNext/Bundler consumers passed. Merge: `e882f357cd7860b3e0905fdf0b2fb3ff8c2464d8`; issue #41 is closed.\n\nThe separate Windows agent subsequently opened PPTX [PR #17](https://github.com/OpenPresentation/opf-pptx/pull/17), retaining the owned verifier's process handle so Windows PowerShell 5.1 preserves its exit code. The exact head `95f5b9e0387dabb467a26d0fbbbdbe0171439a55` passed Linux/Windows Node 20/24 and Bugbot. Reviewed and merged as `24e7b2f12462df246e35a8a714a47923ecbd2bfe`. The [GitHub coordination handoff](https://github.com/OpenPresentation/opf-pptx/pull/17#issuecomment-5623170599) requests immutable native findings and preserved failures.\n\nThe initial audit found no open Dependabot security alerts in core, renderer, PPTX, editor or the three sites. Published versions remain core 0.9.0, CLI 0.7.0, renderer/PPTX 0.7.0 and editor 0.6.0. All three public origins returned HTTP 200 with successful production deployment records. That is a state check, not fresh deployed workflow certification. No npm version, release plan or deployment changed in this checkpoint.\n\n## Verified font preparation\n\nRenderer [PR #13](https://github.com/OpenPresentation/opf-render/pull/13), commit `91fe43e25dca9e4f04a2a18b1c6ee74e7e3d2863`, adds `prepareNodeFonts` and an immutable manifest for 33 existing open faces/eight license notices. Exact package versions and file/notice hashes are checked before use. Shared options carry measurement, embedded SVG bytes and raster paths; system fonts are disabled. Visual substitutions remain explicit and authored documents are preserved.\n\nThe old raster default omitted semibold, italic and bold italic from the nine-face base registry. A direct probe preserves the three failing outputs and shows all nine matching after correction. All 143 changed corpus slides were inspected in 18 paired sheets and six at full size. The separate baseline preserves all 662 unchanged hashes and identical source. Complete renderer suites/805 slides pass under Node 20.20.2 and 24.21.0. Nine exact base faces pass actual offline Chromium loading and advance checks; accepted-text and rich-spacing browser checks also pass. [Portable renderer evidence](https://github.com/OpenPresentation/opf-render/tree/91fe43e25dca9e4f04a2a18b1c6ee74e7e3d2863/docs/evidence/font-preparation) includes failures, paired images, hashes and reproduction instructions.\n\nCore's coordinated font harness now passes the same preparation options through pagination, editor composition, SVG/PNG and PPTX. Fresh candidate installations verify source preservation, edit/undo, rendering, editable export and heading reimport. The new declaration consumer checks the shared API and immutable catalog. TypeScript 5.9 and 7 pass. Historical registry harnesses remain version-pinned and do not call unpublished APIs.\n\nBoth Node 20 and 24 Mac installed-browser runs pass seven suites: canvas, rich text, layout, blocks, lists, creation and styled tables, totaling 230 assertions and eight trusted interaction scenarios. The initial Mac styled-table run failed because `Control+End` left all text selected. A direct Chromium control reproduced that behavior; `Meta+ArrowDown` collapses the selection at the end. The harness now uses the native platform shortcut and asserts the selection before typing. The original failure screenshot/log remain in [Mac evidence](evidence/mac-font-preparation/README.md). Product editing behavior was not changed.\n\nFont preparation merged after successful exact-head review and CI: renderer #13 as `e4d0dc0070616bc3b63a10124ce92cb4aff40e21` and core #62 as `028178311dc7f29667086809c83eb09405cefc4a`. No release occurred.\n\n## Merged physical font variants\n\nCore adds optional `FontFaceSelection` metadata to `TextStyle`. Renderer [#14](https://github.com/OpenPresentation/opf-render/pull/14) selects exact static weights through preferred-family grouping and preserves the physical legacy-family style flags. PPTX [#20](https://github.com/OpenPresentation/opf-pptx/pull/20) consumes those flags across measured editable payloads. Previously Roboto 500/600/800 selected neighboring 400/700 files; SemiBold/ExtraBold could receive incorrect synthetic bold flags. All six reproduced selection/style discrepancies are corrected in the new source probes. Explicit custom namespaces, duplicate/ambiguous guards and providers without metadata retain documented behavior.\n\nSource tests cover all nine base faces and seven payload slides on both Node runtimes. Actual offline Chromium advances match within 0.1 pixels; full renderer/converter Node 24 suites pass. The 805-slide base-font checkpoint stays unchanged. Seven complete before/after payload pairs were inspected. Fresh candidate checks repeat the physical-face tests from installed tarballs and verify shared layout, edit/undo, raster output, editable export and reimport. The [candidate evidence](evidence/mac-font-variants/README.md) records package/browser results and the separate native evidence review.\n\nPhysical variant changes merged after exact-head CI and review: core #64 as `a3ad7053e1bd6b7ba7ee8c98cc679caed741c433`, renderer #14 as `44ff76fe19ae9de80d2aaa962aa7e43fabce02bc`, and PPTX #20 as `cb297be6038b4ec6a84761693b6a7c9e4a4f518d`. The current coordinator pins the merged renderer, PPTX `8bf8aab4a69e2f89b489ff64cde2ae6b7c46de7e` (including the quote-role fix), and editor `6e0b7d2f1b4369fc0a228391cf36e913e05188f8`. These source pins remain separate from historical registry verification refs. Versions and `release-plan.json` still describe the published set.\n\n## Remaining work and ownership\n\nThe Windows agent owns bounded native harness work and Office evidence. The user reviewed recovery and resumed Office activity on that computer. PPTX #18 bounds accepted-text workers and guarantees parent-owned temporary font cleanup; #19 bounds the six metric decks and preserves existing fidelity gates. Core [#63](https://github.com/OpenPresentation/opf/pull/63), exact evidence `e862a5f48bbb9e34aa6e5115922848292e23797f`, contains 1,585 byte-verified files. Both Node runtimes pass 24 accepted-text cases, 144 editable lines, 72 exact original/saved/edited imports, 24 equal save/reopen PNG pairs and 96 original-text ink masks. The Mac independently checked those masks and records. The result is scoped to the recorded graph and does not identify every native glyph's font file.\n\nThe original retained baseline on both runtimes reproduces eight metric tab outliers (maximum 0.0673828125 points) and one portrait/right Latency ink overflow at x=497 beyond 496.8. Their 144 imports each pass; character bounds, mask coverage and collisions pass. The Mac independently decoded 96 complete metric slides and 276 isolated masks, checked raw tab arithmetic and import hash bindings, and reproduced the failures. Precise saved DrawingML tab coordinates do not establish why COM/native shaping differs. The Mac owns the shared runtime investigation; avoid duplicate Windows runtime edits.\n\nCore #65/PPTX #21 completed the eight-workbook native chart edit matrix on both runtimes. Exact evidence `a4e7e9b9b5810144b1f116d45a92bc71e1484c78` has 2,289 verified files. Independent Mac review executed 384 imports and 384 separate cache parses, checked live edits, all 128 original/reopened PNG pairs and all sixteen selected-slide raster changes. PowerPoint's loaded pie category getter returns null even in an independently native-created control; this is explicitly unavailable, while live edits and cached XML provide separate exact observations. The original dialog/crash/stale-cache failures remain retained.\n\nCore #66 merged as `626bc8c80495733264a692401e6a8c96663dd62f` after nine checks passed. Its bounded metric layout uses accepted outlines and raster clearance while preserving literal source/tabs, physical font selection and readability floors. Both Node runtimes pass 96 actual offline browser cases; the width-only control also passes and does not reproduce the native Calibri failure. Fresh Windows evidence in core #68, exact `5d39217f0716453bf3762057852006b4787de73b`, independently confirms that the portrait/right Latency ink overflow is gone. The Mac checked 96 full native rasters, 276 isolated masks and 288 actual original/saved/edited imports. Six leading-tab discrepancies remain per runtime (max 0.0226745605469pt against 0.02pt); the full fidelity gate still fails. PPTX #23 corrects only the verifier's accepted-anchor assumption; tolerances and independent ink/source gates are unchanged. Core #68 merged as `fb56cd247091f45a739eb3e752126db9e69fbe4d`.\n\nCore #67/PPTX #22 retain bounded native table/code/quote checks, exact evidence `2024141c116e81608d3c6632b02c7bcbcd2a2bcc` with 2,646 verified files. Tables/code pass their scoped gates. Stronger quote comparison exposed 36 portrait first-body-line-to-subtitle failures. PPTX #24 fixes inference beside complete roles and adds missing tags to default estimated-font headings without changing native geometry. It merged as `8bf8aab4a69e2f89b489ff64cde2ae6b7c46de7e` after all Linux/Windows Node 20/24 and Bugbot checks. Independent Mac runs of 108 table, 48 code and 72 quote imports pass on both Nodes; all 36 prior role failures are retained and now corrected. Six actual browser suites and sixteen loaded/default regression cases pass. Quotes still reimport as generic text lines, not semantic quote payloads.\n\nThe [Akasia assessment](evidence/akasia-assessment/README.md) records exact v0.0.2 open files and public upstream metric agreement across all twelve styles. It retains 14 missing reference codepoints and a Black Italic decomposed-mark Fontkit/Chromium difference of 0.421875px at size 32 on both Nodes. A source/NFC cluster control isolates the difference. Three full slides were inspected with existing sparse layout/contrast limitations explicit. No proprietary reference binary comparison, new mapping or font pack is shipped; Akasia remains experimental.\n\nCore #69 merged the Akasia assessment and metric follow-up. Core #70, exact evidence `28ae661a606d0a70ff39d98aac32e84240dbbb23`, adds fresh native quote runs after PPTX #24 and native-created tab controls from merged PPTX #26. All 182 files were checked against immutable Git blobs; the Mac independently reimported 72 quote slides on each supported Node runtime. Exact current body/footer order, multiplicity and title edits pass. The 0.02pt tab gate still fails in the native-created control; no offset/tolerance workaround is justified by this evidence.\n\nThe natural-rich-text candidate closes the estimated fragment-gap defect, preserves measured origins and adapts editor selection/caret mapping to traced SVG spans. Core harness `0f937d3ee94644ee3df312b7dbbf36b6efe27e70`, renderer product `57be896e761af102961521acd7dd6104273296bf` and editor product `eeaee72f011ccb3d36259236d46fc9a4124a1eed` define the tested source graph. The [portable evidence](evidence/mac-rich-flow/README.md) records the 30-case browser checks, source edit/undo and clean installed-package checks. All 188 raster changes were visually reviewed with six full-size pairs; 617 hashes remain unchanged. The separate rich-flow checkpoint preserves historical baselines. This increment remains unpublished.\n\nRenderer #15 merged as `c92198b0d0acc94892385a8594fe2879461d64b0` and editor #12 as `a0aa911188f8a6364b66c7a19cece64580c1d9f8`, with Node 20/24 CI and independent review passing. The follow-up source graph uses renderer `6520f091a95aa95be5993580adf5df567eb439c8` and editor `f0871842088d2180ed7de606c379d7921e7fbf0e`. It resolves Linux measured SVG advance drift through geometric precision and explicit accepted horizontal advances, keeping raw font metrics distinct from constrained output. Independent review also fixed inherited code-role guards for traced spans; real text-node selection now covers code body/filename/language. Core #71/PPTX #27 retain nine native output family/style matches and blocked image controls. The Mac verified all 389 files, 28 fresh font-slide imports on each Node, and all seven full-size PDF rasters. Native image acceptance remains blocked pending reviewed Office recovery; no further COM retry or cleanup claim.\n\nCore #72 merged the rich-flow coordination and native follow-up as `804c6d362fd175940b8dd3170976ae6ffe87ed8c` after all supported-runtime checks and independent review passed. The subsequent scalar whitespace candidate is described in [its plan](plans/plain-text-whitespace.md) and [portable Mac evidence](evidence/mac-source-whitespace/README.md). It preserves spaces, tab segments and exact hard-break source ranges through fitting, SVG and editable PPTX reimport, fixes blank scalar selection and preserves untouched mixed endings across separate editor input events. A single wholesale replacement keeps the existing replacement-range newline policy. The 805-slide candidate changes 279 hashes, all reviewed in 35 paired sheets plus six full-size pairs; 526 are unchanged. Historical baselines and failures remain retained. The candidate is unpublished and does not close native Office or general visual-quality gates.\n\nContinue the font roadmap: native follow-up for physical variants, real measurement integration in user workflows, text features, bounded repair/readability, diagnostic paths, multilingual shaping/coverage, Akasia/Aptos evaluation and native portability. Estimated rich-run gaps and scalar whitespace loss are corrected by the current candidates; sparse cards, missing marker glyphs and unresolved assets/data remain visible; the 805-slide hashes do not certify quality. Keep optional font packs openly licensed with provenance and bounded downloads. No silent content loss or synthetic compatibility claims.\n\nVector PDF remains gated on font/layout acceptance; sanitized SVG and the complete Mermaid support matrix follow afterward. Publication must use new versions in dependency order, then clean registry workflows, installed-package browser tests and all three deployed sites. The current releases and prior failures must remain distinguishable from source candidates throughout.\n\n## Readability floor source checkpoint\n\nThe preceding whitespace PRs merged: core #73 `c51b02571eab6ee61d03560aa1f539072b2d381b`, renderer #16 `c7a7387f6e27cc21eeeec3015492afe289ec4ce3`, editor #13 `aea29cf6998127fda96a5cbcd6b608db4c4890e3` and PPTX #28 `4c75ff713a19dff072e8f3660c368499973b78ab`. The subsequent audit found no open PRs or Dependabot alerts across all seven repositories. The Windows coordination note is [posted](https://github.com/OpenPresentation/opf/pull/71#issuecomment-5625857758); its request remains conditional on user-reviewed Office recovery.\n\nThe next candidate fixes selected readability floors and bounds fitting to 65 candidate sizes, retaining source, run ratios and the prior relative shrink constraint. Core product is `ade2a4f0a8afa93f546a3b1e18f2ed23b84d0ac7`. [Portable Mac evidence](evidence/mac-readability-floor/README.md) records the reproduced failures, corrections, both runtime suites and fresh installed editing/undo/export checks. The independent 48-case SVG/PPTX size matrix passes from source and installed packages on both runtimes. Renderer #17 retains all 33 reviewed paired sheets for 262 changes, six full-size pairs and the exact predecessor. Editor #14 and PPTX #29 coordinate CI only. CI/review acceptance and merge status must be checked live; no package or site release has occurred.\n\nThe floor checkpoint covers scalar/rich/list/table glyphs and shared heading allocation. It does not close small template footers/page numbers, all chart/timeline internals, missing nested marker coverage, Auto arrange, general visual quality or native Office gates. Continue reliability before vector PDF and then sanitized SVG/Mermaid. The overall goal remains active.\n\n## Shared timeline source checkpoint\n\nReadability merged after all CI/review gates passed: core #74 `2aeb86012c15193dba78ae81be838c9d7e09ac67`, renderer #17 `53b90878b8a9610117ac5191ebfaaa549cc2f3ea`, editor #14 `f71c1cdb3e9e25c9a62e25b0e711792820e6545e` and PPTX #29 `13b2229e3172e48ee489e68cac8432471993d7a9`. Core exact head `82e5a86d597e99c5e3c032d8b3aea717fb0393e3` passed all nine checks, including coordinator run 34535898793; review comments were empty. A fresh seven-repository audit found no open PRs.\n\nThe new timeline implementation fixes core/renderer acceptance disagreement, omitted metadata and synthetic shorthand source paths. Product graph: core `cc4b5245ba1c197746a2c307b78ff58f45df02cc`, renderer `1e5cd95a76e356c09ae5da0c8604809a202b1f40`, editor `78184f161bdb243822f2b21699ee0ab759c4c7bd`, PPTX `6f06406d9615b35a66f39e6424b35b1d32a73052`. [Portable evidence](evidence/mac-shared-timeline/README.md) includes source and installed browser checks on both runtimes, exact current-native-text semantic timeline reimport, bounded search and strict overflow/pagination controls. The independently reproduced predecessor matches all 805 hashes; 83 candidate changes were reviewed in eleven paired sheets and six full-size pairs, with 722 unchanged. New timeline baselines are separate from prior checkpoints.\n\nThis checkpoint is unpublished. Verify live PR/CI status before claiming merge acceptance. Native tab tolerance still fails and image acceptance remains blocked pending Windows Office recovery. The narrow portrait browser control fits but remains heavily wrapped; Auto arrange and overall quality are not complete. Continue font/layout reliability before vector PDF, then SVG/full Mermaid, coordinated new releases and three deployed-site workflow checks.\n\nShared timeline is merged: core #75 `166cebd8d8af4a80cef3e06ece8e0f8f2d1cecb8`, renderer #18 `f863c9c9b234a36720e2500e19b0384e340f1cfb`, editor #15 `6a3b85aecd7ee96bbcd67d60e02a4c3e32ba93bb`, PPTX #30 `9646c0ddf6880dde1d41ecdf21446d347cd88bf4`. Final core head `c2379f870ee0eadabfcda2f738226bf8184451f3` passed all nine checks, including coordinator 34540948071; no core review comments. Final PPTX `d03e2daebaf9fb6c5d01a7461da22695da2bcb9f` passed Linux/Windows Node 20/24 and Bugbot (run 34540943584). Its guard-order review was fixed before merge. The editor blank-field finding was disproven by its existing generic source-text fallback and actual pointer/bounds controls; the [additional blank-when evidence](evidence/timeline-review-follow-up/README.md) is retained. Both runtime editor CI passed and the finding was resolved before merge. A fresh seven-repository audit returned zero open PRs.\n\nThe next [shared header/footer plan](plans/shared-furniture-layout.md) begins on `codex/shared-furniture-20260910`. Read-only Node 20/24 wide/portrait controls reproduce fixed 13px furniture at selected floors 16/32 and missing authored header/footer words in PPTX. They remain in `artifacts/furniture-predecessor` and the source probe/output files in `/private/tmp/opf-furniture-gap-before-node*.json`. No furniture product changes have been made yet. The core branch is based on the merged timeline checkpoint. The exact timeline core raster predecessor archive is retained at `/private/tmp/opf-timeline-predecessor.tgz` (SHA-256 `ad60806239f3aa3d6a9e0993a74d7781225a75998736213f019e34eb7f78a9bd`), with its original candidate manifest; the accepted timeline raster corpus remains available. Published versions, release plans and deployments are unchanged. The overall goal is still active.\n\nThe final [Windows handoff](https://github.com/OpenPresentation/opf/pull/71#issuecomment-5626767382) records the timeline/readability merge graph and keeps new native work conditional on reviewed Office recovery. [Portable header/footer predecessor evidence](evidence/mac-shared-furniture-predecessor/README.md) preserves the next defect before changes. All four active runtime checkouts now use `codex/shared-furniture-20260910` based on their merged timeline checkpoints.\n\n## Shared furniture implementation checkpoint\n\nThe first source implementation is committed: core `864b73e356c45211a28f3ca5afe0702b55868fa4`, renderer `4e11b9557b589e3a9d04c7c97b4a0c66bce83d94`, editor `e0c817fb372a5639f9fd1c829e85bf21fb1ba241`, PPTX `d06bc9c72aef16fdbe345704309f53ed97321417`. The preceding statement that no furniture product changes exist is historical. [Portable draft evidence](evidence/mac-shared-furniture-draft/README.md) records this exact candidate, its failures and current limits.\n\nCore resolves inherited/local/disabled furniture, preserves literal strings and metadata sources, measures accepted parts at the selected floor and reserves body space (`grid-score-v9`, `furniture-flow-v1`). Pagination evaluates final output page numbers and separates optional repeated metadata mappings from its existing body slices. Core's 507 tests and legacy pagination pass on Node 20/24. Thirty-two offline browser cases per runtime pass source editing, empty fields, generated-value selection guards, dates and undo/redo; all four reviewed full-size screenshots match across runtimes. Sixteen PPTX exports per runtime match accepted text boxes, font sizes, source lines and fitted images; all sixteen outputs are byte-identical across runtimes. Existing editor and converter suites pass on both runtimes.\n\nSemantic furniture reimport is **not implemented**. PPTX currently draws accepted parts with stable shape names and preserves blank lines, but has no furniture provenance tags. Continue that work before creating the coordinated PRs or claiming a complete author/edit/export/reimport workflow. The plan identifies standard common-slide customer data as a possible topology carrier for empty/false definitions, to assess and test without stale source words. Missing/duplicate/changed groups, current native text/images, generated metadata disagreement and inheritance/overrides need explicit controls.\n\nRenderer Node 24 non-golden checks pass. Its old timeline baseline correctly reports **657 changed / 148 unchanged** slides with an unchanged source digest. The candidate manifests are in `opf-render/artifacts/furniture-golden-after`; this initial run did not request PNG artifact retention. Regenerate the same candidate with `OPF_GOLDEN_ARTIFACTS=1` or `--update` into a distinct review directory, retain/verify predecessor PNGs, then inspect all changes and full-size pairs before promoting any new baseline. The old timeline baseline remains untouched. Clean candidate package/installed workflows, coordinated CI, PR review and merging remain pending. The large-font portrait browser specimen wraps the organization heavily despite passing bounds.\n\nA fresh seven-repository audit still returned no open PRs. The latest three comments on core #71 contain no new Windows recovery evidence; the existing tab failure and blocked image state remain unchanged. No COM retries occurred. Versions, registry releases, sites and the full-goal acceptance status remain unchanged; continue reliability before vector PDF, then SVG/full Mermaid and coordinated publication.\n\nThe full candidate PNG corpus has now been regenerated into `opf-render/artifacts/furniture-golden-review`: all 805 PNG hashes match its manifest, and that manifest exactly matches the retained first comparison. Paired visual review is still pending. The four source commits and evidence checkpoint `abf3e27563364b4a6e1a095558740be8bd0da85c` are pushed to their matching furniture branches; no furniture PRs exist yet.\n\nConcurrent working-tree edits to `docs/plans/ecosystem-objective-2026-09-09.md` and `docs/plans/font-roadmap.md` add an accepted Node 24-only runtime maintenance milestone after current in-flight checks and before release. These edits were discovered after the source checkpoint and left intact and unstaged. The current Node 20/24 checks are finished; follow the updated roadmap for subsequent work rather than starting more duplicate Node 20 runs. Audit and align the four packages/CLI, three sites, CI/packaging, clean installation, tooling and Windows coordination on Node 24 while retaining distinct browser/OS/native gates. Preserve historical evidence and published artifacts. This newly observed roadmap does not mean the engine declarations or active CI matrices have been migrated yet.\n"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"slug": "handoff-windows-native-2026-09-10",
|
|
95
|
+
"file": "docs/handoff-windows-native-2026-09-10.md",
|
|
96
|
+
"title": "Windows native testing checkpoint",
|
|
97
|
+
"markdown": "# Windows native testing checkpoint\n\nRuntime update (September 10): use **Node 24 only** for new development and verification; see [migration instructions](migrations/node24.md). Historical Node 20/24 results and commands below describe prior checkpoints. Keep distinct browser/OS/native gates and the existing Office recovery prerequisite.\n\nThe [Windows evidence bundle](evidence/windows-native-2026-09-10/README.md) records completed accepted-text native testing on the immutable source baselines in its `sources.json`. Both Node 20.20.2 and 24.20.0 passed all 24 separate bounded cases: 144 editable lines, 72 original/saved/edited imports, 24 unchanged save/reopen PNG pairs and 96 original-text ink masks per runtime. The 0.1-reference-pixel containment rule is unchanged. All four owned temporary Carlito registrations were removed after every case, including separate dummy-worker failure/timeout controls.\n\n[PPTX #17](https://github.com/OpenPresentation/opf-pptx/pull/17), retaining the owned worker handle for Windows PowerShell exit codes, and [PPTX #18](https://github.com/OpenPresentation/opf-pptx/pull/18), adding bounded text workers and parent-owned font cleanup, were reviewed and merged by the Mac owner. [PPTX #19](https://github.com/OpenPresentation/opf-pptx/pull/19) contains the separately bounded metric suite. Native results and exact verifier snapshots are in the evidence bundle. Product runtime and release refs are unchanged.\n\nThe complete chart matrix now passes: eight separately selected workbook edits on each Node runtime, 384 original/saved/edited slide imports, 384 independent chart-cache comparisons and 128 identical original/reopened PNG pairs. Each actual selected edit changes its raster and preserves the other seven. [PPTX #21](https://github.com/OpenPresentation/opf-pptx/pull/21) rebinds the existing source range after cell edits and requires exact live edited series before closing the workbook. A pie created entirely by PowerPoint reproduces null category getters after reopening; these are explicitly unavailable observations, while exact live categories and independent persisted cache data remain required. Initial stale-cache, getter, parser and control-save failures remain raw. The earlier `chart.dll` crash's precise trigger remains unknown and its broader probe was not repeated.\n\nThe user reviewed the AutoRecovered presentations and explicitly resumed after an earlier Escape. Preserve those pre-existing presentations. Never kill PowerPoint or Excel, call `Application.Quit`, discard user work or automatically retry a blocked Office call. The bounded helper may close only verified fixtures it opened; helper termination does not establish Office cleanup. Temporary fonts belong to the surviving parent and must be removed in `finally`.\n\nBoth Node runtimes now completed six separate bounded metric runs / 48 slides each. All 144 original/saved/edited imports per runtime pass, while eight tab errors above 0.02 points (maximum 0.0673828125) and one portrait/right native ink overflow at x=497 beyond 496.8 reproduce exactly. Character bounds, inter-part collisions and isolated-mask coverage pass. Original and saved DrawingML retain the precise tab coordinates; the native shaping/observation cause remains under investigation. The current shared metric layout uses advance positions without the general text model's outline clearance.\n\nBoth runtimes now pass the bounded table suite (six actual cell edits, 72 native cells, 978 character colors and 54 slide imports including two further export/import cycles) and code suite (24 imports, actual body/filename edits, zero tab/character-bound outliers). Stronger quote imports exposed first-body-line promotion to subtitle on all six portrait slides; 18 original/saved/edited counterexamples per runtime retain every word but change its role. Native quote bounds and wide imports pass. Earlier footer-only quote checks missed this problem; both verifier generations and raw results remain in the bundle. [PPTX #22](https://github.com/OpenPresentation/opf-pptx/pull/22) contains the bounded content harness and explicitly preserves this failed gate.\n\nThe [coordinated candidate evidence](evidence/windows-native-candidate-2026-09-10/README.md) now records both complete native metric matrices on core `476fdb2f5547e442d8a270047dfc8557f306bb49` and the physical-font graph. The portrait/right Latency ink overflow is cleared under the unchanged containment rule. Six leading-tab outliers remain per runtime (maximum about 0.02267456 pt). The full metric fidelity gate remains failed. The original baseline remains separate, and changing both outline/font inputs does not isolate their individual effects.\n\nThe [fresh quote and native tab evidence](evidence/windows-native-quote-tab-2026-09-10/README.md) verifies merged PPTX #24 on both Node runtimes: 72 slide imports now preserve exact current body/footer roles and title edits. Quotes remain generic text on import. Nine tab/literal pairs created entirely by PowerPoint independently reproduce the native tab offset discrepancy; DrawingML retains precise coordinates. PDF coordinates also differ but have separate rounding. Preserve the 0.02 pt gate and do not add consumer compensation. The successful control, earlier adapter failure, exact verifiers and portable extracted observations remain; private PDFs/font subsets are excluded.\n\nThe [native font/image checkpoint](evidence/windows-native-font-image-2026-09-10/README.md) now records all nine bundled output family/style combinations in actual PowerPoint character properties and PDF glyph font names on both Node runtimes. Each has seven stable save/reopen PNG pairs, 14 identical current-content imports and all nine temporary registrations removed. Initial PostScript/PDF naming mismatch remains raw. Physical file identity for every glyph is not established. OPF editor atomic image replacement, source preservation, guarded failure and exact document/PPTX undo/redo pass on both runtimes.\n\nNative images are blocked. Both preserve/compatible nine-image decks and minimal OPF/direct-PptxGenJS one-PNG controls were refused immediately despite valid XML, archive relationships and source PNG CRCs. A PowerPoint-created picture control timed out after 45 seconds on 2026-09-10 at 20:03:33 UTC; only helper PID 16992 was terminated. The empty owned checkpoint exists, but cleanup and the exact blocked call are unconfirmed because that scratch control did not persist individual stages. No subsequent Office COM calls were made. UI inspection still showed the three pre-existing chart windows without a visible dialog; that does not establish readiness. The user was asked to save wanted presentations, close PowerPoint normally and reopen it before another native image attempt. Preserve all raw attempts and never kill Office or automatically retry a blocked call.\n\nThe Mac owner owns shared product placement and release work. Neither accepted geometry, temporary font registration nor unchanged save/reopen pixels establishes font-file identity, browser/native equivalence or arbitrary round-trip support. No packages or public sites have been published or deployed by this Windows task. The user has authorized creating and merging focused PRs that pass review and checks.\n"
|
|
74
98
|
},
|
|
75
99
|
{
|
|
76
100
|
"slug": "handoff",
|
|
77
101
|
"file": "docs/handoff.md",
|
|
78
102
|
"title": "Continue the OPF ecosystem work",
|
|
79
|
-
"markdown": "# Continue the OPF ecosystem work\n\nThe coordinated ecosystem PRs were merged on September 8, 2026 UTC. Continue from `main` in these repositories:\n\n| Checkout | Merged PR |\n| --- | --- |\n| opf | https://github.com/OpenPresentation/opf/pull/9 |\n| opf-render | https://github.com/OpenPresentation/opf-render/pull/1 |\n| opf-editor | https://github.com/OpenPresentation/opf-editor/pull/1 |\n| opf-pptx | https://github.com/OpenPresentation/opf-pptx/pull/1 |\n| pptx-gallery | https://github.com/Data-Advantage/pptx-gallery/pull/9 |\n| openpresentation-site | https://github.com/Data-Advantage/openpresentation-site/pull/5 |\n\nClone the six repositories into sibling directories. Use Node.js 24 and pnpm 10.33.2. From the parent directory:\n\n```sh\ngh repo clone OpenPresentation/opf -- --branch main\ngh repo clone OpenPresentation/opf-render -- --branch main\ngh repo clone OpenPresentation/opf-editor -- --branch main\ngh repo clone OpenPresentation/opf-pptx -- --branch main\ngh repo clone Data-Advantage/pptx-gallery -- --branch main\ngh repo clone Data-Advantage/openpresentation-site -- --branch main\n```\n\nInstall dependencies with `pnpm install --frozen-lockfile` in `opf`, `pptx-gallery` and `openpresentation-site`; use `npm ci` in the three library repositories. Then, from `opf`:\n\n```sh\npnpm build\nnode scripts/link-ecosystem.mjs\npnpm test\npnpm test:skills\npnpm test:ecosystem\npnpm test:layout\npnpm test:lists\npnpm demo:editor\npnpm pack:ecosystem\npnpm test:packed-ecosystem\n```\n\nThe link step builds the sibling libraries against the current core. Re-run it after reinstalling dependencies. Core 0.4.0, renderer/editor 0.1.1 and PPTX/CLI 0.1.0 are now published. The source-link workflow remains useful for development. Generated review artifacts, installed dependencies and local server state are excluded from Git and rebuilt by these commands.\n\nStart the editor with `python3 -m http.server 3102 --directory artifacts/editor` from `opf`. In another terminal start the gallery with `OPF_LOCAL_WORKSPACE=1 pnpm dev --port 3101` from `pptx-gallery`. From `openpresentation-site`, run `OPF_LOCAL_SOURCE=../opf pnpm sync:opf`, then `pnpm dev --port 3103`.\n\nFor public-site documentation built from a remote branch instead of the sibling checkout, use `OPF_REPO_REF=codex/opf-ecosystem-20260907 OPF_FORCE_SYNC=1 pnpm sync:opf`.\n\nProduction builds use `OPF_LOCAL_WORKSPACE=1 pnpm build` in `pptx-gallery` after linking, and `OPF_LOCAL_SOURCE=../opf pnpm build` in `openpresentation-site`. The gallery workspace flag lets Turbopack resolve the sibling package. Normal standalone gallery builds now use registry core 0.4.0. Normal site builds default to the source tag matching the installed core version; stale/local snapshots refresh automatically unless OPF_LOCAL_SOURCE explicitly selects local development.\n\n## Current release checkpoint \u2014 September 8 UTC\n\nPR #8 is incorporated into the pushed PR #9 branch through merge 10ed11c. Both test suites, structural package slimming, named schema definitions, catalog/index fixes, governance and Node 20/24 release gates are retained. All six PRs are merged with merge commits; GitHub also marked PR #8 merged through its preserved ancestry. Both sites deployed automatically from the merged main branches.\n\nAll five planned versions are now published and resolve through ordinary npm installation:\n\n| Package | Version | Source and publication |\n| --- | --- | --- |\n| @openpresentation/opf | 0.4.0 | Tag opf-v0.4.0 at 6180096; workflow 34182120112 with provenance |\n| @openpresentation/opf-render | 0.1.1 | Tag opf-render-v0.1.1 at de53df7; workflow 34184779283 with provenance |\n| @openpresentation/opf-editor | 0.1.1 | Tag opf-editor-v0.1.1 at dbbe1a1; workflow 34184868180 with provenance |\n| @openpresentation/opf-pptx | 0.1.0 | Tag opf-pptx-v0.1.0 at 7a385fc; retried workflow 34182814991 with provenance |\n| @openpresentation/cli | 0.1.0 | Reviewed standalone tarball from core 6180096, authenticated first publication; no provenance on this bootstrap release |\n\nThe user completed npm login and browser 2FA. Trusted publishers now exist for editor/PPTX release.yml and core cli-publish.yml. Initial permissions failures were resolved, and exact tagged jobs reran successfully. The CLI public tarball SHA-1 is 0308493d1d85ce18518b69882085419ec3817d73, matching the reviewed artifact. npm metadata took several minutes to expose the new package; it now installs normally. Do not republish an existing version.\n\n`pnpm test:registry-ecosystem` passed for all five exact versions with no local overrides: model operations, fonts, SVG, editable PPTX, TypeScript, browser bundle, CLI create/validate/version. All 60 CLI command checks also pass using the registry-installed executable. `release-plan.json` pins immutable core/editor harness refs for the published release set so unreleased source tests cannot silently change release verification. `test:registry-libraries` is an additional four-library check, not a replacement for the complete gate. All six registry-installed browser suites pass 176 checks (34 canvas, 19 lists, 46 rich text, 19 layout, 18 blocks, 40 creation). Browser evidence lives in `artifacts/npm/registry-browser-verification.json`.\n\nPublished in 0.1.1: renderer 5472483 adds trace-only rich-line geometry; editor a4be429 adds native continuous rich typing with glyph-aligned caret/pointer selection, mixed-style preservation, draft undo/redo, cancellation, conflict protection and composition lifecycle handling. Source browser suites pass 176 checks (34 canvas, 19 lists, 46 rich text, 19 layout, 18 blocks, 40 creation). Actual keystrokes and a measured pointer hit were verified. Renderer/editor 0.1.1 passed standalone Node 20/24 CI (34184700599 and 34184801283), trusted publication, and clean five-package registry verification. Real OS IME, bidi/complex-script and cross-browser behavior remain open. Normal renderer output is unchanged and all 805 raster checks pass.\n\nThe renderer baseline covers 805 slides in 126 installed-core example decks; missing/changed corpora fail and updates create review candidates without replacing the baseline. All 17 overview sheets were inspected and timeline endpoint clipping was fixed. PptxGenJS remains pinned to 4.0.1; its unused image-size advisory remains unresolved, with model/image embedding tested while parser loading is blocked. Neither baseline nor model checks establish native PowerPoint fidelity.\n\nGallery review fix ee01bc5 passes production build and header geometry checks at 320, 640, 1024, 1279, 1280 and 1440 pixels. Phone/laptop screenshots and mobile search were checked. Site review fix fe638e8 removes duplicate sitemap routes, preserves root-relative guide links, omits catalogs without indexes and repairs code-block colors. Its prebuild regression suite covers 592 unique sitemap URLs, link resolution and missing/empty/legacy catalogs. All five confirmed review threads were resolved before merging.\n\nThe gallery editor and site showcase have now been regenerated from the exact npm set above. All 854 gallery documents validate and render using the installed packages; the schema reference exposes 604 fields. Checked-in manifests record package tarball URLs/integrities, example source refs and SHA-256 asset hashes. Normal production builds pass. Served checks pass for nine gallery documents, 583 site source hashes, six skills, seven guides and all refreshed editor/showcase asset hashes.\n\nReproduce registry assets after installing core build tooling and fetching the immutable harness/example refs in release-plan.json:\n\n```sh\npnpm test:registry-ecosystem\npnpm prepare:gallery:registry\npnpm build:showcase:registry\n```\n\nThe gallery command updates its checked-in editor/reference files. Copy the four files in artifacts/site-showcase to openpresentation-site/public/showcase, then build both sites. Registry checks generate their own browser HTML and font files; prior source-demo artifacts are no longer required. Source preparation removes any old registry manifest so it cannot falsely label a development bundle as published.\n\nFinal reviewed core ece9b90 passed core CI 34185231548 and coordinated CI 34185231533 on Node 20/24. The workflow pins renderer/editor release commits. Main now contains the complete ecosystem implementation and the 0.4.0 changelog correction. The user authorized pushes, PR updates, npm publication, and these six merges with their normal site deployment triggers. Preserve unrelated gallery pnpm-workspace.yaml.\n\n## Current scope and remaining work\n\nThe branch includes shared dynamic layout and pagination, loaded-font measurement and substitutes, rich text/lists, CSV/JSON import, an installable agent CLI, six portable skills, schema-driven properties, copy/import/galleries, canvas resizing/moving/creation/deletion, native PPTX improvements, and site/galleries integration. See [ecosystem quality](plans/ecosystem-quality.md) and [coverage](plans/spec-editor-coverage.md) for evidence and remaining fidelity gaps.\n\nThe broader goal is still active. Real OS IME/cross-browser typing, advanced table/media/preset fidelity, and native PowerPoint raster comparison remain work. Local preview tarballs are not evidence of registry publication.\n\n## Merged checkpoint and local follow-ups\n\n| Repository | Main merge commit |\n| --- | --- |\n| opf | c6323d9 |\n| opf-render | 371c6ce |\n| opf-editor | 33cfebc |\n| opf-pptx | e3afb70 |\n| pptx-gallery | 22f1748 |\n| openpresentation-site | b385495 |\n\nBoth production deployments are ready at www.pptx.gallery and www.openpresentation.org, from the exact merge commits above. Releases were already published before merging; no versions were republished.\n\nPost-merge checks passed: core 34186567364, coordinated packages 34186567415, renderer 34186581381, editor 34186583983, PPTX 34186586280 and gallery 34186589351. Live verification passed for 583 source-file hashes, six downloadable skills, seven guides, schema/text endpoints and nine schema-valid gallery documents. All seven gallery manifest hashes and three showcase hashes match production. The manifest's opf-spec.json is served at /api/opf-spec.json; the other editor assets are under /opf-editor/. The live editor renders six starter slides and opens its complete property controls.\n\nThe following local follow-ups remain outside this merged checkpoint. The PPTX table and image branches are now combined in the integration checkpoint below:\n\n- PPTX table fidelity: 7453c33 (c549049 fitting plus ba0ad8a import fixes, reconciled with main) on codex/table-export-fidelity-20260908 in /private/tmp/opf-table-export/opf-pptx. Native editable cells use shared loaded-font fitting, preserve nested minimum font sizes, fill uneven rows, and match the SVG border theme slot. Node 20/24 tests compare 168 cells, including 24 shrinking cases. Quick Look and Keynote can open the exports, but wrapping differs. Keynote's round-trip changes the specimen's 11.25/6.75-point text to 11/6 points; this is viewer-specific evidence, not PowerPoint verification.\n- Site snapshot source links: 2858456 (d5642af reconciled with main) on codex/site-snapshot-links-20260908 in /private/tmp/opf-site-snapshot/openpresentation-site. View-source links serve the exact documentation snapshot bytes instead of GitHub main. Regression tests, production build, 583 raw-file hashes, six skill downloads, seven guides and representative source links pass locally.\n\nNext: review the combined PPTX integration and separate site source-link change, then continue native PowerPoint comparison, real OS typing, and the remaining table/media/preset roadmap. The local commits are not published releases.\n\nThe table follow-up also preserves headerless first rows and empty rows on import using native firstRow flags. Node 20/24 tests and a clean local-tarball consumer pass. Keynote 14.4 recognizes zero headers/three rows versus one header/four rows in a two-slide specimen, with blank rows retained. Native PowerPoint remains untested. Local PR descriptions are ready; approval to open the two new PRs is pending.\n\n## Local image-fidelity follow-up\n\nCommit 0007ff1 on codex/image-fit-fidelity-20260908 in /private/tmp/opf-image-fit/opf-pptx is separate from the table branch. It preserves native picture proportions with fit/crop, honors slide overrides, and maps all eight JPEG EXIF orientations to native rotation/mirroring without recompressing pixels. PNG/JPEG/GIF/WebP dimensions come from the actual embedded bytes. Unsupported/unreadable dimensions produce a path-specific error. Node 20/24 suites pass with image-size loading blocked; 45 geometry cases, eight orientations in fit/crop, clean local-tarball installation and browser bundling pass. Keynote visually shows correct wide/tall PNG fit/crop and all eight JPEG orientations. Native PowerPoint, animated/vector media, non-JPEG orientation and lossless picture import remain open. The change is committed locally and unpublished.\n\n## Combined PPTX integration checkpoint\n\nLocal merge commit 4a41b2b on codex/pptx-fidelity-20260908 in /private/tmp/opf-pptx-fidelity/opf-pptx combines the table and image branches above. The original branches are preserved. An installed-example audit also exposed duplicate native object IDs on 23 slides; the integration repairs only duplicate IDs and adds an eight-slide mixed table/text/image/chart/list regression. Repeated multi-chart exports also exposed ZIP ordering differences when PptxGenJS counters cross digit widths; sorting after part-name normalization fixes them.\n\nNode 20 and 24 pass the integrated suites, syntax checks and package metadata validation. A new structural corpus gate exports/imports all 126 decks / 805 slides, checking slide XML, unique IDs, finite geometry, table grids and imported slide counts. It explicitly uses fallback fonts and 26 synthetic image substitutions. With original asset requests and fallback fonts, 102 decks export/import; the remaining 24 encounter missing local assets or a truncated PNG fixture. With strict available fonts and original assets, only one deck completes. These are different evidence levels: the complete structural gate is not proof of original-asset, typography or native-viewer fidelity.\n\nThe clean consumer in /private/tmp/opf-pptx-fidelity/consumer passes the complete suite against the installed local tarball plus published core 0.4.0 and renderer 0.1.1, including the structural corpus and a browser bundle.\n\nLocal packed artifact: /private/tmp/opf-pptx-fidelity/packed/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 ea3215e9cee82366e131e6b3d3115cd5e19a0b8e. Version 0.1.0 is unchanged for this unpublished development artifact; it must not overwrite the existing npm release. No follow-up branch has been pushed, no new PR opened, and no new package published. The earlier request to open follow-up PRs remains pending; the prepared PPTX description now covers this combined implementation.\n\n## Image media-type and example corrections\n\nPPTX integration now advances to 87f6616. Native raster file extensions and per-part content types are derived from actual embedded PNG/JPEG/GIF/WebP bytes, so transformed host assets and incorrect MIME/path hints cannot label JPEG pixels as PNG. Import detects these formats from bytes as well. Thirty-two cases cover byte results, typed/untyped result objects, data URIs, local paths and host paths/URIs, plus mislabeled older native files. Node 20/24 complete suites and package checks pass. The clean consumer at /private/tmp/opf-pptx-fidelity/consumer-87f6616 passes all tests, the 805-slide structural corpus and browser bundling with published core 0.4.0 / renderer 0.1.1. New local tarball: /private/tmp/opf-pptx-fidelity/packed-87f6616/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 15ce44e1ee1faed81aed711a3e3795a0974d7145. Earlier tarballs remain historical artifacts, and no new version is published.\n\nKeynote 14.4 directly opened the four-format specimen at artifacts/media-types/native-media-types.pptx in the integration worktree. PNG, JPEG and GIF show the expected quadrants and round circle. WebP imports as an empty rectangle, confirmed in both the slide overview and selected slide. That check established the need for compatible PNG fallback; the next checkpoint below implements and verifies it. Correct ZIP metadata alone was insufficient. No native PowerPoint installation is available. The generated specimen was closed without saving.\n\nCore local commit ef25735 replaces the eight-byte PNG signature in examples/technical/asset-source-forms.opf.json with the complete project-authored square PNG from the PPTX test fixtures. All 126 examples validate. The corrected example exports/imports four slides with its exact PNG bytes retained, and its SVG/PNG image slide was visually inspected using explicit fallback fonts. Core/CLI build verification includes checking the generated examples against this source. Other illustrative file/remote references remain host-supplied, not bundled. The correction is unreleased and requires a future core package/site snapshot update.\n\n## Compatible WebP checkpoint\n\nPPTX integration advances to local commit 8197854 on codex/pptx-fidelity-20260908. Default imageFormat: \"compatible\" converts WebP to static PNG after resolving the original asset once; fit/crop uses the decoded PNG dimensions. Pixel comparisons cover alpha, EXIF orientation/mirroring and the first animation frame. imageFormat: \"preserve\" retains unchanged WebP embedding. Conversion errors carry the OPF path, and compatible conversion has a 40-megapixel limit. Original source documents/bytes are unchanged; the exported picture contains PNG pixels, not original WebP metadata or animation.\n\nNode uses lazy Sharp 0.35.4 decoding, raising the package minimum to Node 20.9.0. Browser conditional imports select Blob/image/canvas decoding and exclude Sharp/Node code. Platform dependencies are present in the lockfile; npm's optional native dependencies must be installed normally. The audit still reports only the existing image-size/PptxGenJS advisories. esbuild 0.28.2 is a development-only dependency used to enforce the browser boundary.\n\nNode 20.20.2 and 24.20.0 complete suites, syntax and metadata checks pass. Thirty-six WebP cases match independent Pillow-decoded first-frame RGBA hashes; decoder-unavailable and malformed/oversize cases produce path-specific errors. Existing preservation tests explicitly select preserve mode. The 126-deck / 805-slide structural corpus remains green with its previously documented substitutions. Thirteen browser pixel/geometry/input checks pass, including alpha, EXIF, animation's first frame and DOM canvas output. npm test builds the browser verification page and asserts no native modules enter its bundle; actual browser execution remains a separate UI check.\n\nKeynote 14.4 now displays all six converted WebP specimens in /private/tmp/opf-pptx-fidelity/opf-pptx/artifacts/webp-fallback/compatible-webp.pptx. The earlier empty rectangles are gone; expected quadrants, circles, transparency and orientation are visible. Arial labels avoid the previous missing-font notice. The generated document was closed without saving. Microsoft PowerPoint and other browsers remain unverified, and SVG/vector assets and full animation playback remain separate work.\n\nLocal tarball /private/tmp/opf-pptx-fidelity/packed-8197854/openpresentation-opf-pptx-0.1.0.tgz has SHA-1 6c249cf52d0624c9408bd8abb4e544d444b20c3a. Clean consumer /private/tmp/opf-pptx-fidelity/consumer-8197854 installs published core 0.4.0 / renderer 0.1.1 and this tarball, and passes the complete model/image/corpus suite and browser bundle checks. The packed browser implementation also passes all 13 browser checks. Both decoder files and conditional package imports are packaged. This is unpublished development version 0.1.0; do not overwrite the existing registry release. No follow-up PRs, pushes or publications have been made.\n\n## Renderer WebP raster checkpoint\n\nLocal renderer commit 18c79e4 on codex/renderer-webp-20260908 in /private/tmp/opf-renderer-webp/opf-render fixes WebP images disappearing from PNG/PDF output. The new Node-only raster preparation decodes embedded WebP data URIs to static PNG; it leaves the source SVG/OPF unchanged and adds no external URL/path resolution. href/xlink:href, base64/percent encoding, XML character references, alpha, EXIF and the first animation frame are covered. Malformed input reports its data-opf-path when present or svg.images.N. Input format is checked before decoding and the 40-megapixel Sharp limit applies.\n\nNode 20.20.2 and 24.20.0 full suites, syntax/package checks and all 805 existing golden rasters pass; no baseline changed. Twenty-three focused cases inspect raster pixels, fit/crop, actual PDF image streams and PDF alpha masks. The historical renderer demonstrably fails the first independent pixel reference. Fixtures regenerate byte-for-byte with Pillow 12.3.0; the six-image overview PNG was visually inspected. PNG/PDF conversion uses lazy Sharp 0.35.4 and now requires Node 20.9+. The renderer audit reports zero advisories at this checkpoint. Browser SVG exports exclude the native raster adapter.\n\nThe local renderer tarball /private/tmp/opf-renderer-webp/packed/openpresentation-opf-render-0.1.1.tgz has SHA-1 d19e216a4e8ec0762ed9e912b0708002ec43be64. /private/tmp/opf-renderer-webp/consumer installs it with local PPTX 8197854 and published core 0.4.0, editor 0.1.1 and CLI 0.1.0. Both packages' focused/model/corpus checks pass, browser bundling excludes native decoders, editor import succeeds and CLI reports its expected versions. This is a mixed local/registry development consumer, not evidence of a new registry release.\n\nThe renderer branch and all earlier follow-ups remain local/unpublished. Prepared descriptions now cover four potential follow-up PRs: PPTX fidelity, renderer WebP raster output, the core example correction/handoff, and site snapshot source links. Existing examples/font substitutions and native Microsoft PowerPoint coverage remain separate limits. The JPEG PNG/PDF gap is addressed by the next checkpoint; other media/layout/editor requirements remain open.\n\n\n## Renderer JPEG orientation checkpoint\n\nLocal renderer commit 87663fb extends codex/renderer-webp-20260908 in /private/tmp/opf-renderer-webp/opf-render to honor JPEG EXIF orientations 2\u20138 in PNG/PDF output. It uses the existing lazy Sharp decoder and private rasterization copy. JPEGs with orientation 1 or no orientation retain their exact SVG attribute spelling and compressed bytes. Source OPF/SVG and browser SVG exports remain unchanged. Malformed JPEGs report the image path.\n\nNode 20.20.2 and 24.20.0 verification passes. The final Node 20 suite, syntax and metadata checks are recorded in artifacts/jpeg/node20-verification.log in the renderer worktree; all 805 golden rasters remain unchanged. Twenty-four focused cases cover all eight orientations, fit/crop, independent Pillow pixels (maximum channel difference 2), actual PDF RGB image streams, deterministic PNG output and errors. The historical renderer fails orientation 2 with a maximum channel error of 255. All 16 fixture JPEG/PNG files regenerate byte-for-byte using Pillow 12.3.0. The eight-image PNG overview was visually inspected.\n\nSixteen browser OPF-SVG orientation/fit/crop cases passed before the Mac locked, with an incorrect-orientation control. Maximum mean channel error was 0.6156662326388889, maximum fraction of channels differing by more than 10 was 1.2241753472222223%, and maximum individual channel difference was 49. The incorrect-orientation control had mean error 56.44899848090278. These are geometry/orientation checks with aggregate error bounds, not pixel-identical browser output. The checked-in harness is test/jpeg-browser.js; npm test builds it and asserts native raster code is absent. No additional browser run was performed after the Mac locked.\n\nPacked artifact: /private/tmp/opf-renderer-webp/packed-jpeg/openpresentation-opf-render-0.1.1.tgz, SHA-1 c239043a3230a9d4fb55f8213abde1d1ef12a7e8. A fresh /private/tmp/opf-renderer-webp/consumer-jpeg installs this tarball, local PPTX 8197854, and published core 0.4.0/editor 0.1.1/CLI 0.1.0. All 23 WebP and 24 JPEG focused cases pass against the installed renderer. Editable PPTX, SVG/PNG, editor import and the combined browser dependency boundary pass. The development artifact retains version 0.1.1; it is not a registry publication and must not overwrite that released version.\n\nGitHub was rechecked: all six coordinated PRs remain merged. The four follow-ups remain local, with the earlier request to push/open their draft PRs still pending. The renderer description now covers both WebP and JPEG raster fixes. Native Microsoft PowerPoint, additional browsers and remaining media/editor fidelity remain open.\n\n\n## Native background fill checkpoint\n\nLocal PPTX commit 4c06cf7 advances codex/pptx-fidelity-20260908 in /private/tmp/opf-pptx-fidelity/opf-pptx. Fixed solid and linear-gradient backgrounds now serialize as editable native p:bg fills rather than flattening gradients to a solid fallback. Solid opacity, hex alpha, gradient stop alpha/positions, deck defaults and slide overrides are retained. An inheritance test also exposed and fixed ignored inline theme overrides: theme objects now resolve their base record and then apply the inline properties.\n\nSVG's object-bounding-box gradient and DrawingML's unscaled slide-coordinate gradient need both direction and stop-interval conversion. The new background helper performs that conversion and native RGB solid/linear import without hidden OPF metadata. Native integer angles/positions incur rounding. Uniform alpha returns as background opacity; differing stop alpha returns as eight-bit RGBA, which may round. Unsupported native path gradients, transformed/theme stop colors, non-default tile/flip geometry and unrepresentable stop intervals produce unsupported-background-gradient through the new optional fromPptx onDiagnostic callback. Other background/decorative features remain open.\n\nFinal Node 20.20.2 and 24.20.0 full suites, syntax and metadata checks pass (artifacts/backgrounds/node20-final.log and node24-final.log in the PPTX worktree). Coverage includes 38 principal gradient/solid cases and 990 sample comparisons derived independently from serialized SVG endpoints and native physical gradient properties across landscape, portrait and square canvases. Additional cases cover theme inheritance, alpha, native edits, repeated export/import, empty/single/descending stops, malformed colors and unsupported native fills. The historical implementation fails the first editable-gradient assertion. The structural corpus still passes 126 decks / 805 slides using its documented fallback fonts and 26 synthetic image substitutions; that is not native raster parity evidence.\n\nNative visual verification is unresolved. Four Quick Look thumbnails (0, 30, 45 and 90 degrees) all contain the same flat RGB(106,176,222), rather than the intended gradient. The PNG files and corresponding PPTX/SVG references are under artifacts/backgrounds. Keynote UI inspection was attempted but the desktop tool reported the Mac locked; an unlock request is pending. Microsoft PowerPoint is unavailable. The native XML/mathematical checks must not be treated as proof of native appearance. This discrepancy needs investigation in a native viewer before a release decision.\n\nLocal package: /private/tmp/opf-pptx-fidelity/packed-backgrounds/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 ceacb66d28703b3de866db6847084df59b0dc893. Fresh consumer /private/tmp/opf-pptx-fidelity/consumer-backgrounds installs it with local renderer 87663fb plus published core 0.4.0, editor 0.1.1 and CLI 0.1.0. Installed gradient checks, all 47 JPEG/WebP raster cases, editor import and the combined browser dependency boundary pass. The package still has development version 0.1.0 and must not overwrite the existing registry release. No follow-up pushes, PRs or publications occurred.\n\n\n## JPEG picture import and dimension precision checkpoint\n\nPPTX codex/pptx-fidelity-20260908 now advances through d08fa9e (JPEG picture import) to 4a3a6e3 (dimension precision) in /private/tmp/opf-pptx-fidelity/opf-pptx. A direct audit found that every exported JPEG EXIF orientation imported as orientation 1 because the native rotation/mirror was discarded. The importer now combines existing JPEG EXIF orientation with native quarter-turns/flips and writes the resulting orientation into a copied EXIF record, without decoding/recompressing pixels. Existing metadata is applied before the native transform; that is the importer contract, not a claim about every external viewer. All eight orientations emitted by this exporter recover exact source JPEG bytes through repeated fit-mode round-trips. Alternative text and input PPTX bytes are preserved.\n\nJPEGs without an orientation tag receive a minimal EXIF segment, or a replacement IFD0 appended within the existing bounded APP1 segment. Original metadata entries, referenced offsets and the next-IFD link remain intact. Both byte orders and malformed metadata are covered. Native crop windows are still not represented in the imported asset, and non-quarter-turn/non-JPEG transforms are unsupported. These cases now report unsupported-image-crop or unsupported-image-orientation through fromPptx's optional onDiagnostic callback, using native picture-order paths such as slides.0.pictures.0. Import still recomposes layout and is not a lossless picture/placement/crop/effect/group round trip.\n\nA complete image-slide preview comparison found a separate defect: emuToInches rounded native dimensions to six decimals, changing a 1280-pixel canvas to 1279.999968 pixels and perturbing raster edges. 4a3a6e3 removes that premature rounding. With the local JPEG-aware renderer, all eight complete fit-mode image-slide PNGs now match their source OPF PNG bytes after native export/import. This compares OPF-rendered previews; it does not compare native PowerPoint pixels. One imported orientation-7 PNG was visually inspected.\n\nNode 20.20.2 and 24.20.0 complete suites, syntax and metadata checks pass, including the final precision change (artifacts/image-import/node20-precision.log and node24-precision.log). Forty-two principal image-import cases cover all eight orientations in fit/crop, 16 native quarter-turn/flip combinations, existing EXIF plus native rotation, metadata insertion/link preservation, exact source bytes, independent pixel permutations, malformed EXIF and diagnostics. The old implementation fails the exact-JPEG round-trip assertion; artifacts/image-import/before.json records its eight incorrect orientation results. The 126-deck/805-slide structural corpus remains green with documented font and image substitutions.\n\nLatest local tarball: /private/tmp/opf-pptx-fidelity/packed-import-precision/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 88a32daefda4524161c87cfc5adaa5270b3cf68a. Fresh consumer /private/tmp/opf-pptx-fidelity/consumer-import-precision installs it with local renderer 87663fb and published core 0.4.0/editor 0.1.1/CLI 0.1.0. Installed picture-import and background tests pass. verify-preview.mjs records all eight exact whole-slide PNG comparisons, editor import and the combined browser dependency boundary; results are in preview/report.json and preview-verification.log. No browser UI or native viewer run was performed for this milestone. Historical d08fa9e tarball SHA-1 3af059814d4f22ae2b992228b75b8659d9427756 remains in packed-image-import; it lacks the subsequent precision fix.\n\nBoth changes are local/unpublished, still using development version 0.1.0. The four follow-up draft PR/push request remains pending. The native gradient visual discrepancy and locked-desktop Keynote review remain unresolved; no publication or new native-compatibility claim follows from this checkpoint.\n\n\n## Native Keynote background verification and merge preparation\n\nPPTX commit 821c047 resolves the earlier native gradient verification gap. Keynote 14.4 displays editable Advanced Gradient Fill controls and exports the six landscape angles correctly. Twelve unchanged native PNGs cover those opaque angles and six portrait solid/gradient transparency cases. Eighteen comparisons, including the native Keynote PPTX reimport, pass: opaque maximum channel error 4/255 and mean below 0.38; transparent alpha error at most 1/255. Quick Look remains a thumbnail limitation, not evidence that Keynote renders these gradients flat. Microsoft PowerPoint remains unverified. Generated documents were closed without saving.\n\nThe Keynote round-trip also exposed synthetic titles added to empty/background-only slides. Import now preserves blank content and notes-only slides. Project-authored native fixtures and their hashes are checked in; normal CI does not require Keynote. The historical importer fails the blank-slide assertion. Final Node 20/24 complete suites, syntax, package metadata and browser dependency checks pass, including the 126-deck/805-slide structural corpus with previously documented substitutions. Logs are artifacts/backgrounds/native-node20.log and native-node24.log in the PPTX worktree.\n\nThe user has authorized pushing, PR updates and merging the four prepared follow-ups. Merge preparation covers PPTX 821c047, renderer 87663fb, site 2858456 and this core example/handoff branch. These changes do not publish new npm versions; the existing development version numbers must not overwrite registry releases. Historical pending-approval and locked-desktop notes above describe earlier checkpoints and are superseded here.\n\n## Published fidelity releases and registry verification\n\nThe follow-up implementations are merged and now published through trusted publishing with npm provenance:\n\n| Package | Version | Tagged source | Publish workflow |\n| --- | --- | --- | --- |\n| @openpresentation/opf | 0.4.1 | aed5e5493998a5081fea68bf3bd42c52409e0c15 | 34204122730 |\n| @openpresentation/cli | 0.1.1 | aed5e5493998a5081fea68bf3bd42c52409e0c15 | 34204125018 |\n| @openpresentation/opf-render | 0.2.0 | df7ce5c6915a084f101adf90e6329117c0094a23 | 34204875207 |\n| @openpresentation/opf-pptx | 0.2.0 | 1fef9dcfadeeb8310b3c3b668f7506b52717b695 | 34205556749 |\n| @openpresentation/opf-editor | 0.1.2 | 5819a2ac12ec22f08a348c81bc3c66630682ecfb | 34205593335 |\n\nCore/CLI release PR 18, renderer PR 3, PPTX PR 3 and editor PR 2 were merged after Node 20/24 CI and automated review. Their merge commits passed CI before tags were pushed. GitHub releases contain matching changelog notes. Registry propagation briefly delayed PPTX availability; publication was not rerun, and the subsequent exact-version install passed.\n\nRenderer/PPTX 0.2.0 require Node 20.9 or later and core 0.4.1. Editor 0.1.2 accepts renderer 0.1.1 or 0.2.x through its optional peer; its development dependency explicitly installs renderer 0.2.0 for CI. The renderer release uses the individually reviewed corrected-image baseline and retains the preceding core-0.4.0 manifest for audit. Only the repaired example slide changes; the other 804 raster hashes remain identical.\n\nThe clean registry consumer at artifacts/npm/registry-consumer installs all five exact release-plan versions without local package overrides. Model/API, TypeScript, browser bundling and CLI checks pass. The actual registry CLI reports 0.1.1 with bundled OPF 0.4.1 and passes 60 command checks. Eight complete JPEG image-slide previews are byte-identical before and after PPTX export/import using the installed registry packages.\n\nThe new pnpm test:registry-fidelity command runs immutable test/fixture snapshots against installed npm dist files, checks registry lock records and real paths, and rejects local package overrides. It passes 23 WebP and 24 JPEG raster/PDF cases, all 805 raster baselines, 18 captured Keynote comparisons, table/image/background/import tests and the 126-deck/805-slide structural corpus with its documented fallback fonts and 26 synthetic image substitutions. Coordinated CI now pins the release commits and also runs the exact-version registry integration and fidelity checks on Node 20/24; full core history makes the pinned browser harness source available.\n\nBrowser execution against the registry packages passes 176 editor harness checks plus 13 WebP and 16 JPEG checks. JPEG comparison retains the previously documented aggregate bounds (maximum channel 49, mean below 0.616, at most 1.225% of channels differing by more than 10); it is not pixel-identical browser output. These harnesses do not establish real OS IME, cross-browser behavior or Microsoft PowerPoint fidelity. Core remains free and provider-neutral; normal CI needs no native presentation application.\n\nGallery and site release worktrees are /private/tmp/opf-release-gallery/pptx-gallery and /private/tmp/opf-release-site/openpresentation-site on codex/fidelity-release-20260908. Their locked core is 0.4.1, and editor/showcase assets are regenerated from the five-package registry consumer with version/integrity/hash manifests. All 854 gallery examples validate/render, 106 gallery tests pass, and both production builds pass. The site syncs opf-v0.4.1 and exposes 583 raw files/six skills. Public deployment verification follows these prepared updates; earlier production manifests remain historical until those PRs merge.\n\n## Shared table rows and native rich-table import releases\n\nThe current coordinated package set is core 0.6.0, CLI 0.3.0, renderer 0.4.0, PPTX 0.4.0 and editor 0.3.0. `release-plan.json` pins all five versions and their immutable source commits. Core PR 23, renderer PR 5, PPTX PR 8 and editor PR 4 merged after Node 20/24 CI and automated review. Each merged tree matches the tested head. All five packages were published through trusted publishing with provenance, and registry tarball integrities match the tested release candidates.\n\nCore exports `layoutTable` for shared content-aware row geometry. Rows use spare height before shrinking text; rich cell lines reserve uniform native paragraph advances. Renderer and PPTX consume the same row/cell boxes and fitted text, while editor 0.3.0 aligns dependency minima. PPTX imports supported native rich table character styles, paragraph defaults, theme fonts/colors, external links, run/field/break order and significant whitespace directly from XML. Unstyled body cells remain strings. Cached display text does not reconstruct original scalar types or live fields.\n\nFinal PPTX/editor candidate tarballs with published core/renderer dependencies passed native import and row geometry tests on Node 20/24, 15 browser import/containment checks and 14 browser editor checks. Full standalone tests retained the 126-deck/805-slide structural corpus and all 805 renderer raster baselines. These checks do not establish Microsoft PowerPoint raster parity, complete conditional table styles/merged geometry/cell decoration, cross-engine editing or real OS IME support.\n\nCore publication run 34228179949 published npm successfully but its later GitHub release step failed because a matching release already existed. Preserve existing release notes when the workflow runs again; only create a GitHub release when absent. Do not republish the existing npm version. CLI run 34228594104, renderer run 34229511905, editor run 34230608709 and PPTX run 34231015995 succeeded. PPTX package-index propagation briefly delayed normal clean installation after the exact-version endpoint was available; publication was not repeated.\n\nThe gallery and public-site rollout uses isolated `codex/table-layout-registry-20260908` branches in `/private/tmp/opf-release-gallery/pptx-gallery` and `/private/tmp/opf-release-site/openpresentation-site`. Their core manifests and locks are updated to 0.6.0. Regenerate editor/showcase assets from the verified registry consumer, pin site documentation to the reviewed coordination commit, then verify production deployments and bytes. Earlier public deployment evidence remains historical until those updates land.\n"
|
|
103
|
+
"markdown": "# Continue the OPF ecosystem work\n\nRuntime update (September 10): use **Node 24 only** for new development and verification; see [migration instructions](migrations/node24.md). Historical Node 20/24 results and commands below describe prior checkpoints. Keep distinct browser/OS/native gates and the existing Office recovery prerequisite.\n\nThe coordinated ecosystem PRs were merged on September 8, 2026 UTC. Continue from `main` in these repositories:\n\n| Checkout | Merged PR |\n| --- | --- |\n| opf | https://github.com/OpenPresentation/opf/pull/9 |\n| opf-render | https://github.com/OpenPresentation/opf-render/pull/1 |\n| opf-editor | https://github.com/OpenPresentation/opf-editor/pull/1 |\n| opf-pptx | https://github.com/OpenPresentation/opf-pptx/pull/1 |\n| pptx-gallery | https://github.com/Data-Advantage/pptx-gallery/pull/9 |\n| openpresentation-site | https://github.com/Data-Advantage/openpresentation-site/pull/5 |\n\nClone the six repositories into sibling directories. Use Node.js 24 and pnpm 10.33.2. From the parent directory:\n\n```sh\ngh repo clone OpenPresentation/opf -- --branch main\ngh repo clone OpenPresentation/opf-render -- --branch main\ngh repo clone OpenPresentation/opf-editor -- --branch main\ngh repo clone OpenPresentation/opf-pptx -- --branch main\ngh repo clone Data-Advantage/pptx-gallery -- --branch main\ngh repo clone Data-Advantage/openpresentation-site -- --branch main\n```\n\nInstall dependencies with `pnpm install --frozen-lockfile` in `opf`, `pptx-gallery` and `openpresentation-site`; use `npm ci` in the three library repositories. Then, from `opf`:\n\n```sh\npnpm build\nnode scripts/link-ecosystem.mjs\npnpm test\npnpm test:skills\npnpm test:ecosystem\npnpm test:layout\npnpm test:lists\npnpm demo:editor\npnpm pack:ecosystem\npnpm test:packed-ecosystem\n```\n\nThe link step builds the sibling libraries against the current core. Re-run it after reinstalling dependencies. Core 0.4.0, renderer/editor 0.1.1 and PPTX/CLI 0.1.0 are now published. The source-link workflow remains useful for development. Generated review artifacts, installed dependencies and local server state are excluded from Git and rebuilt by these commands.\n\nStart the editor with `python3 -m http.server 3102 --directory artifacts/editor` from `opf`. In another terminal start the gallery with `OPF_LOCAL_WORKSPACE=1 pnpm dev --port 3101` from `pptx-gallery`. From `openpresentation-site`, run `OPF_LOCAL_SOURCE=../opf pnpm sync:opf`, then `pnpm dev --port 3103`.\n\nFor public-site documentation built from a remote branch instead of the sibling checkout, use `OPF_REPO_REF=codex/opf-ecosystem-20260907 OPF_FORCE_SYNC=1 pnpm sync:opf`.\n\nProduction builds use `OPF_LOCAL_WORKSPACE=1 pnpm build` in `pptx-gallery` after linking, and `OPF_LOCAL_SOURCE=../opf pnpm build` in `openpresentation-site`. The gallery workspace flag lets Turbopack resolve the sibling package. Normal standalone gallery builds now use registry core 0.4.0. Normal site builds default to the source tag matching the installed core version; stale/local snapshots refresh automatically unless OPF_LOCAL_SOURCE explicitly selects local development.\n\n## Current release checkpoint \u2014 September 8 UTC\n\nPR #8 is incorporated into the pushed PR #9 branch through merge 10ed11c. Both test suites, structural package slimming, named schema definitions, catalog/index fixes, governance and Node 20/24 release gates are retained. All six PRs are merged with merge commits; GitHub also marked PR #8 merged through its preserved ancestry. Both sites deployed automatically from the merged main branches.\n\nAll five planned versions are now published and resolve through ordinary npm installation:\n\n| Package | Version | Source and publication |\n| --- | --- | --- |\n| @openpresentation/opf | 0.4.0 | Tag opf-v0.4.0 at 6180096; workflow 34182120112 with provenance |\n| @openpresentation/opf-render | 0.1.1 | Tag opf-render-v0.1.1 at de53df7; workflow 34184779283 with provenance |\n| @openpresentation/opf-editor | 0.1.1 | Tag opf-editor-v0.1.1 at dbbe1a1; workflow 34184868180 with provenance |\n| @openpresentation/opf-pptx | 0.1.0 | Tag opf-pptx-v0.1.0 at 7a385fc; retried workflow 34182814991 with provenance |\n| @openpresentation/cli | 0.1.0 | Reviewed standalone tarball from core 6180096, authenticated first publication; no provenance on this bootstrap release |\n\nThe user completed npm login and browser 2FA. Trusted publishers now exist for editor/PPTX release.yml and core cli-publish.yml. Initial permissions failures were resolved, and exact tagged jobs reran successfully. The CLI public tarball SHA-1 is 0308493d1d85ce18518b69882085419ec3817d73, matching the reviewed artifact. npm metadata took several minutes to expose the new package; it now installs normally. Do not republish an existing version.\n\n`pnpm test:registry-ecosystem` passed for all five exact versions with no local overrides: model operations, fonts, SVG, editable PPTX, TypeScript, browser bundle, CLI create/validate/version. All 60 CLI command checks also pass using the registry-installed executable. `release-plan.json` pins immutable core/editor harness refs for the published release set so unreleased source tests cannot silently change release verification. `test:registry-libraries` is an additional four-library check, not a replacement for the complete gate. All six registry-installed browser suites pass 176 checks (34 canvas, 19 lists, 46 rich text, 19 layout, 18 blocks, 40 creation). Browser evidence lives in `artifacts/npm/registry-browser-verification.json`.\n\nPublished in 0.1.1: renderer 5472483 adds trace-only rich-line geometry; editor a4be429 adds native continuous rich typing with glyph-aligned caret/pointer selection, mixed-style preservation, draft undo/redo, cancellation, conflict protection and composition lifecycle handling. Source browser suites pass 176 checks (34 canvas, 19 lists, 46 rich text, 19 layout, 18 blocks, 40 creation). Actual keystrokes and a measured pointer hit were verified. Renderer/editor 0.1.1 passed standalone Node 20/24 CI (34184700599 and 34184801283), trusted publication, and clean five-package registry verification. Real OS IME, bidi/complex-script and cross-browser behavior remain open. Normal renderer output is unchanged and all 805 raster checks pass.\n\nThe renderer baseline covers 805 slides in 126 installed-core example decks; missing/changed corpora fail and updates create review candidates without replacing the baseline. All 17 overview sheets were inspected and timeline endpoint clipping was fixed. PptxGenJS remains pinned to 4.0.1; its unused image-size advisory remains unresolved, with model/image embedding tested while parser loading is blocked. Neither baseline nor model checks establish native PowerPoint fidelity.\n\nGallery review fix ee01bc5 passes production build and header geometry checks at 320, 640, 1024, 1279, 1280 and 1440 pixels. Phone/laptop screenshots and mobile search were checked. Site review fix fe638e8 removes duplicate sitemap routes, preserves root-relative guide links, omits catalogs without indexes and repairs code-block colors. Its prebuild regression suite covers 592 unique sitemap URLs, link resolution and missing/empty/legacy catalogs. All five confirmed review threads were resolved before merging.\n\nThe gallery editor and site showcase have now been regenerated from the exact npm set above. All 854 gallery documents validate and render using the installed packages; the schema reference exposes 604 fields. Checked-in manifests record package tarball URLs/integrities, example source refs and SHA-256 asset hashes. Normal production builds pass. Served checks pass for nine gallery documents, 583 site source hashes, six skills, seven guides and all refreshed editor/showcase asset hashes.\n\nReproduce registry assets after installing core build tooling and fetching the immutable harness/example refs in release-plan.json:\n\n```sh\npnpm test:registry-ecosystem\npnpm prepare:gallery:registry\npnpm build:showcase:registry\n```\n\nThe gallery command updates its checked-in editor/reference files. Copy the four files in artifacts/site-showcase to openpresentation-site/public/showcase, then build both sites. Registry checks generate their own browser HTML and font files; prior source-demo artifacts are no longer required. Source preparation removes any old registry manifest so it cannot falsely label a development bundle as published.\n\nFinal reviewed core ece9b90 passed core CI 34185231548 and coordinated CI 34185231533 on Node 20/24. The workflow pins renderer/editor release commits. Main now contains the complete ecosystem implementation and the 0.4.0 changelog correction. The user authorized pushes, PR updates, npm publication, and these six merges with their normal site deployment triggers. Preserve unrelated gallery pnpm-workspace.yaml.\n\n## Current scope and remaining work\n\nThe branch includes shared dynamic layout and pagination, loaded-font measurement and substitutes, rich text/lists, CSV/JSON import, an installable agent CLI, six portable skills, schema-driven properties, copy/import/galleries, canvas resizing/moving/creation/deletion, native PPTX improvements, and site/galleries integration. See [ecosystem quality](plans/ecosystem-quality.md) and [coverage](plans/spec-editor-coverage.md) for evidence and remaining fidelity gaps.\n\nThe broader goal is still active. Real OS IME/cross-browser typing, advanced table/media/preset fidelity, and native PowerPoint raster comparison remain work. Local preview tarballs are not evidence of registry publication.\n\n## Merged checkpoint and local follow-ups\n\n| Repository | Main merge commit |\n| --- | --- |\n| opf | c6323d9 |\n| opf-render | 371c6ce |\n| opf-editor | 33cfebc |\n| opf-pptx | e3afb70 |\n| pptx-gallery | 22f1748 |\n| openpresentation-site | b385495 |\n\nBoth production deployments are ready at www.pptx.gallery and www.openpresentation.org, from the exact merge commits above. Releases were already published before merging; no versions were republished.\n\nPost-merge checks passed: core 34186567364, coordinated packages 34186567415, renderer 34186581381, editor 34186583983, PPTX 34186586280 and gallery 34186589351. Live verification passed for 583 source-file hashes, six downloadable skills, seven guides, schema/text endpoints and nine schema-valid gallery documents. All seven gallery manifest hashes and three showcase hashes match production. The manifest's opf-spec.json is served at /api/opf-spec.json; the other editor assets are under /opf-editor/. The live editor renders six starter slides and opens its complete property controls.\n\nThe following local follow-ups remain outside this merged checkpoint. The PPTX table and image branches are now combined in the integration checkpoint below:\n\n- PPTX table fidelity: 7453c33 (c549049 fitting plus ba0ad8a import fixes, reconciled with main) on codex/table-export-fidelity-20260908 in /private/tmp/opf-table-export/opf-pptx. Native editable cells use shared loaded-font fitting, preserve nested minimum font sizes, fill uneven rows, and match the SVG border theme slot. Node 20/24 tests compare 168 cells, including 24 shrinking cases. Quick Look and Keynote can open the exports, but wrapping differs. Keynote's round-trip changes the specimen's 11.25/6.75-point text to 11/6 points; this is viewer-specific evidence, not PowerPoint verification.\n- Site snapshot source links: 2858456 (d5642af reconciled with main) on codex/site-snapshot-links-20260908 in /private/tmp/opf-site-snapshot/openpresentation-site. View-source links serve the exact documentation snapshot bytes instead of GitHub main. Regression tests, production build, 583 raw-file hashes, six skill downloads, seven guides and representative source links pass locally.\n\nNext: review the combined PPTX integration and separate site source-link change, then continue native PowerPoint comparison, real OS typing, and the remaining table/media/preset roadmap. The local commits are not published releases.\n\nThe table follow-up also preserves headerless first rows and empty rows on import using native firstRow flags. Node 20/24 tests and a clean local-tarball consumer pass. Keynote 14.4 recognizes zero headers/three rows versus one header/four rows in a two-slide specimen, with blank rows retained. Native PowerPoint remains untested. Local PR descriptions are ready; approval to open the two new PRs is pending.\n\n## Local image-fidelity follow-up\n\nCommit 0007ff1 on codex/image-fit-fidelity-20260908 in /private/tmp/opf-image-fit/opf-pptx is separate from the table branch. It preserves native picture proportions with fit/crop, honors slide overrides, and maps all eight JPEG EXIF orientations to native rotation/mirroring without recompressing pixels. PNG/JPEG/GIF/WebP dimensions come from the actual embedded bytes. Unsupported/unreadable dimensions produce a path-specific error. Node 20/24 suites pass with image-size loading blocked; 45 geometry cases, eight orientations in fit/crop, clean local-tarball installation and browser bundling pass. Keynote visually shows correct wide/tall PNG fit/crop and all eight JPEG orientations. Native PowerPoint, animated/vector media, non-JPEG orientation and lossless picture import remain open. The change is committed locally and unpublished.\n\n## Combined PPTX integration checkpoint\n\nLocal merge commit 4a41b2b on codex/pptx-fidelity-20260908 in /private/tmp/opf-pptx-fidelity/opf-pptx combines the table and image branches above. The original branches are preserved. An installed-example audit also exposed duplicate native object IDs on 23 slides; the integration repairs only duplicate IDs and adds an eight-slide mixed table/text/image/chart/list regression. Repeated multi-chart exports also exposed ZIP ordering differences when PptxGenJS counters cross digit widths; sorting after part-name normalization fixes them.\n\nNode 20 and 24 pass the integrated suites, syntax checks and package metadata validation. A new structural corpus gate exports/imports all 126 decks / 805 slides, checking slide XML, unique IDs, finite geometry, table grids and imported slide counts. It explicitly uses fallback fonts and 26 synthetic image substitutions. With original asset requests and fallback fonts, 102 decks export/import; the remaining 24 encounter missing local assets or a truncated PNG fixture. With strict available fonts and original assets, only one deck completes. These are different evidence levels: the complete structural gate is not proof of original-asset, typography or native-viewer fidelity.\n\nThe clean consumer in /private/tmp/opf-pptx-fidelity/consumer passes the complete suite against the installed local tarball plus published core 0.4.0 and renderer 0.1.1, including the structural corpus and a browser bundle.\n\nLocal packed artifact: /private/tmp/opf-pptx-fidelity/packed/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 ea3215e9cee82366e131e6b3d3115cd5e19a0b8e. Version 0.1.0 is unchanged for this unpublished development artifact; it must not overwrite the existing npm release. No follow-up branch has been pushed, no new PR opened, and no new package published. The earlier request to open follow-up PRs remains pending; the prepared PPTX description now covers this combined implementation.\n\n## Image media-type and example corrections\n\nPPTX integration now advances to 87f6616. Native raster file extensions and per-part content types are derived from actual embedded PNG/JPEG/GIF/WebP bytes, so transformed host assets and incorrect MIME/path hints cannot label JPEG pixels as PNG. Import detects these formats from bytes as well. Thirty-two cases cover byte results, typed/untyped result objects, data URIs, local paths and host paths/URIs, plus mislabeled older native files. Node 20/24 complete suites and package checks pass. The clean consumer at /private/tmp/opf-pptx-fidelity/consumer-87f6616 passes all tests, the 805-slide structural corpus and browser bundling with published core 0.4.0 / renderer 0.1.1. New local tarball: /private/tmp/opf-pptx-fidelity/packed-87f6616/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 15ce44e1ee1faed81aed711a3e3795a0974d7145. Earlier tarballs remain historical artifacts, and no new version is published.\n\nKeynote 14.4 directly opened the four-format specimen at artifacts/media-types/native-media-types.pptx in the integration worktree. PNG, JPEG and GIF show the expected quadrants and round circle. WebP imports as an empty rectangle, confirmed in both the slide overview and selected slide. That check established the need for compatible PNG fallback; the next checkpoint below implements and verifies it. Correct ZIP metadata alone was insufficient. No native PowerPoint installation is available. The generated specimen was closed without saving.\n\nCore local commit ef25735 replaces the eight-byte PNG signature in examples/technical/asset-source-forms.opf.json with the complete project-authored square PNG from the PPTX test fixtures. All 126 examples validate. The corrected example exports/imports four slides with its exact PNG bytes retained, and its SVG/PNG image slide was visually inspected using explicit fallback fonts. Core/CLI build verification includes checking the generated examples against this source. Other illustrative file/remote references remain host-supplied, not bundled. The correction is unreleased and requires a future core package/site snapshot update.\n\n## Compatible WebP checkpoint\n\nPPTX integration advances to local commit 8197854 on codex/pptx-fidelity-20260908. Default imageFormat: \"compatible\" converts WebP to static PNG after resolving the original asset once; fit/crop uses the decoded PNG dimensions. Pixel comparisons cover alpha, EXIF orientation/mirroring and the first animation frame. imageFormat: \"preserve\" retains unchanged WebP embedding. Conversion errors carry the OPF path, and compatible conversion has a 40-megapixel limit. Original source documents/bytes are unchanged; the exported picture contains PNG pixels, not original WebP metadata or animation.\n\nNode uses lazy Sharp 0.35.4 decoding, raising the package minimum to Node 20.9.0. Browser conditional imports select Blob/image/canvas decoding and exclude Sharp/Node code. Platform dependencies are present in the lockfile; npm's optional native dependencies must be installed normally. The audit still reports only the existing image-size/PptxGenJS advisories. esbuild 0.28.2 is a development-only dependency used to enforce the browser boundary.\n\nNode 20.20.2 and 24.20.0 complete suites, syntax and metadata checks pass. Thirty-six WebP cases match independent Pillow-decoded first-frame RGBA hashes; decoder-unavailable and malformed/oversize cases produce path-specific errors. Existing preservation tests explicitly select preserve mode. The 126-deck / 805-slide structural corpus remains green with its previously documented substitutions. Thirteen browser pixel/geometry/input checks pass, including alpha, EXIF, animation's first frame and DOM canvas output. npm test builds the browser verification page and asserts no native modules enter its bundle; actual browser execution remains a separate UI check.\n\nKeynote 14.4 now displays all six converted WebP specimens in /private/tmp/opf-pptx-fidelity/opf-pptx/artifacts/webp-fallback/compatible-webp.pptx. The earlier empty rectangles are gone; expected quadrants, circles, transparency and orientation are visible. Arial labels avoid the previous missing-font notice. The generated document was closed without saving. Microsoft PowerPoint and other browsers remain unverified, and SVG/vector assets and full animation playback remain separate work.\n\nLocal tarball /private/tmp/opf-pptx-fidelity/packed-8197854/openpresentation-opf-pptx-0.1.0.tgz has SHA-1 6c249cf52d0624c9408bd8abb4e544d444b20c3a. Clean consumer /private/tmp/opf-pptx-fidelity/consumer-8197854 installs published core 0.4.0 / renderer 0.1.1 and this tarball, and passes the complete model/image/corpus suite and browser bundle checks. The packed browser implementation also passes all 13 browser checks. Both decoder files and conditional package imports are packaged. This is unpublished development version 0.1.0; do not overwrite the existing registry release. No follow-up PRs, pushes or publications have been made.\n\n## Renderer WebP raster checkpoint\n\nLocal renderer commit 18c79e4 on codex/renderer-webp-20260908 in /private/tmp/opf-renderer-webp/opf-render fixes WebP images disappearing from PNG/PDF output. The new Node-only raster preparation decodes embedded WebP data URIs to static PNG; it leaves the source SVG/OPF unchanged and adds no external URL/path resolution. href/xlink:href, base64/percent encoding, XML character references, alpha, EXIF and the first animation frame are covered. Malformed input reports its data-opf-path when present or svg.images.N. Input format is checked before decoding and the 40-megapixel Sharp limit applies.\n\nNode 20.20.2 and 24.20.0 full suites, syntax/package checks and all 805 existing golden rasters pass; no baseline changed. Twenty-three focused cases inspect raster pixels, fit/crop, actual PDF image streams and PDF alpha masks. The historical renderer demonstrably fails the first independent pixel reference. Fixtures regenerate byte-for-byte with Pillow 12.3.0; the six-image overview PNG was visually inspected. PNG/PDF conversion uses lazy Sharp 0.35.4 and now requires Node 20.9+. The renderer audit reports zero advisories at this checkpoint. Browser SVG exports exclude the native raster adapter.\n\nThe local renderer tarball /private/tmp/opf-renderer-webp/packed/openpresentation-opf-render-0.1.1.tgz has SHA-1 d19e216a4e8ec0762ed9e912b0708002ec43be64. /private/tmp/opf-renderer-webp/consumer installs it with local PPTX 8197854 and published core 0.4.0, editor 0.1.1 and CLI 0.1.0. Both packages' focused/model/corpus checks pass, browser bundling excludes native decoders, editor import succeeds and CLI reports its expected versions. This is a mixed local/registry development consumer, not evidence of a new registry release.\n\nThe renderer branch and all earlier follow-ups remain local/unpublished. Prepared descriptions now cover four potential follow-up PRs: PPTX fidelity, renderer WebP raster output, the core example correction/handoff, and site snapshot source links. Existing examples/font substitutions and native Microsoft PowerPoint coverage remain separate limits. The JPEG PNG/PDF gap is addressed by the next checkpoint; other media/layout/editor requirements remain open.\n\n\n## Renderer JPEG orientation checkpoint\n\nLocal renderer commit 87663fb extends codex/renderer-webp-20260908 in /private/tmp/opf-renderer-webp/opf-render to honor JPEG EXIF orientations 2\u20138 in PNG/PDF output. It uses the existing lazy Sharp decoder and private rasterization copy. JPEGs with orientation 1 or no orientation retain their exact SVG attribute spelling and compressed bytes. Source OPF/SVG and browser SVG exports remain unchanged. Malformed JPEGs report the image path.\n\nNode 20.20.2 and 24.20.0 verification passes. The final Node 20 suite, syntax and metadata checks are recorded in artifacts/jpeg/node20-verification.log in the renderer worktree; all 805 golden rasters remain unchanged. Twenty-four focused cases cover all eight orientations, fit/crop, independent Pillow pixels (maximum channel difference 2), actual PDF RGB image streams, deterministic PNG output and errors. The historical renderer fails orientation 2 with a maximum channel error of 255. All 16 fixture JPEG/PNG files regenerate byte-for-byte using Pillow 12.3.0. The eight-image PNG overview was visually inspected.\n\nSixteen browser OPF-SVG orientation/fit/crop cases passed before the Mac locked, with an incorrect-orientation control. Maximum mean channel error was 0.6156662326388889, maximum fraction of channels differing by more than 10 was 1.2241753472222223%, and maximum individual channel difference was 49. The incorrect-orientation control had mean error 56.44899848090278. These are geometry/orientation checks with aggregate error bounds, not pixel-identical browser output. The checked-in harness is test/jpeg-browser.js; npm test builds it and asserts native raster code is absent. No additional browser run was performed after the Mac locked.\n\nPacked artifact: /private/tmp/opf-renderer-webp/packed-jpeg/openpresentation-opf-render-0.1.1.tgz, SHA-1 c239043a3230a9d4fb55f8213abde1d1ef12a7e8. A fresh /private/tmp/opf-renderer-webp/consumer-jpeg installs this tarball, local PPTX 8197854, and published core 0.4.0/editor 0.1.1/CLI 0.1.0. All 23 WebP and 24 JPEG focused cases pass against the installed renderer. Editable PPTX, SVG/PNG, editor import and the combined browser dependency boundary pass. The development artifact retains version 0.1.1; it is not a registry publication and must not overwrite that released version.\n\nGitHub was rechecked: all six coordinated PRs remain merged. The four follow-ups remain local, with the earlier request to push/open their draft PRs still pending. The renderer description now covers both WebP and JPEG raster fixes. Native Microsoft PowerPoint, additional browsers and remaining media/editor fidelity remain open.\n\n\n## Native background fill checkpoint\n\nLocal PPTX commit 4c06cf7 advances codex/pptx-fidelity-20260908 in /private/tmp/opf-pptx-fidelity/opf-pptx. Fixed solid and linear-gradient backgrounds now serialize as editable native p:bg fills rather than flattening gradients to a solid fallback. Solid opacity, hex alpha, gradient stop alpha/positions, deck defaults and slide overrides are retained. An inheritance test also exposed and fixed ignored inline theme overrides: theme objects now resolve their base record and then apply the inline properties.\n\nSVG's object-bounding-box gradient and DrawingML's unscaled slide-coordinate gradient need both direction and stop-interval conversion. The new background helper performs that conversion and native RGB solid/linear import without hidden OPF metadata. Native integer angles/positions incur rounding. Uniform alpha returns as background opacity; differing stop alpha returns as eight-bit RGBA, which may round. Unsupported native path gradients, transformed/theme stop colors, non-default tile/flip geometry and unrepresentable stop intervals produce unsupported-background-gradient through the new optional fromPptx onDiagnostic callback. Other background/decorative features remain open.\n\nFinal Node 20.20.2 and 24.20.0 full suites, syntax and metadata checks pass (artifacts/backgrounds/node20-final.log and node24-final.log in the PPTX worktree). Coverage includes 38 principal gradient/solid cases and 990 sample comparisons derived independently from serialized SVG endpoints and native physical gradient properties across landscape, portrait and square canvases. Additional cases cover theme inheritance, alpha, native edits, repeated export/import, empty/single/descending stops, malformed colors and unsupported native fills. The historical implementation fails the first editable-gradient assertion. The structural corpus still passes 126 decks / 805 slides using its documented fallback fonts and 26 synthetic image substitutions; that is not native raster parity evidence.\n\nNative visual verification is unresolved. Four Quick Look thumbnails (0, 30, 45 and 90 degrees) all contain the same flat RGB(106,176,222), rather than the intended gradient. The PNG files and corresponding PPTX/SVG references are under artifacts/backgrounds. Keynote UI inspection was attempted but the desktop tool reported the Mac locked; an unlock request is pending. Microsoft PowerPoint is unavailable. The native XML/mathematical checks must not be treated as proof of native appearance. This discrepancy needs investigation in a native viewer before a release decision.\n\nLocal package: /private/tmp/opf-pptx-fidelity/packed-backgrounds/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 ceacb66d28703b3de866db6847084df59b0dc893. Fresh consumer /private/tmp/opf-pptx-fidelity/consumer-backgrounds installs it with local renderer 87663fb plus published core 0.4.0, editor 0.1.1 and CLI 0.1.0. Installed gradient checks, all 47 JPEG/WebP raster cases, editor import and the combined browser dependency boundary pass. The package still has development version 0.1.0 and must not overwrite the existing registry release. No follow-up pushes, PRs or publications occurred.\n\n\n## JPEG picture import and dimension precision checkpoint\n\nPPTX codex/pptx-fidelity-20260908 now advances through d08fa9e (JPEG picture import) to 4a3a6e3 (dimension precision) in /private/tmp/opf-pptx-fidelity/opf-pptx. A direct audit found that every exported JPEG EXIF orientation imported as orientation 1 because the native rotation/mirror was discarded. The importer now combines existing JPEG EXIF orientation with native quarter-turns/flips and writes the resulting orientation into a copied EXIF record, without decoding/recompressing pixels. Existing metadata is applied before the native transform; that is the importer contract, not a claim about every external viewer. All eight orientations emitted by this exporter recover exact source JPEG bytes through repeated fit-mode round-trips. Alternative text and input PPTX bytes are preserved.\n\nJPEGs without an orientation tag receive a minimal EXIF segment, or a replacement IFD0 appended within the existing bounded APP1 segment. Original metadata entries, referenced offsets and the next-IFD link remain intact. Both byte orders and malformed metadata are covered. Native crop windows are still not represented in the imported asset, and non-quarter-turn/non-JPEG transforms are unsupported. These cases now report unsupported-image-crop or unsupported-image-orientation through fromPptx's optional onDiagnostic callback, using native picture-order paths such as slides.0.pictures.0. Import still recomposes layout and is not a lossless picture/placement/crop/effect/group round trip.\n\nA complete image-slide preview comparison found a separate defect: emuToInches rounded native dimensions to six decimals, changing a 1280-pixel canvas to 1279.999968 pixels and perturbing raster edges. 4a3a6e3 removes that premature rounding. With the local JPEG-aware renderer, all eight complete fit-mode image-slide PNGs now match their source OPF PNG bytes after native export/import. This compares OPF-rendered previews; it does not compare native PowerPoint pixels. One imported orientation-7 PNG was visually inspected.\n\nNode 20.20.2 and 24.20.0 complete suites, syntax and metadata checks pass, including the final precision change (artifacts/image-import/node20-precision.log and node24-precision.log). Forty-two principal image-import cases cover all eight orientations in fit/crop, 16 native quarter-turn/flip combinations, existing EXIF plus native rotation, metadata insertion/link preservation, exact source bytes, independent pixel permutations, malformed EXIF and diagnostics. The old implementation fails the exact-JPEG round-trip assertion; artifacts/image-import/before.json records its eight incorrect orientation results. The 126-deck/805-slide structural corpus remains green with documented font and image substitutions.\n\nLatest local tarball: /private/tmp/opf-pptx-fidelity/packed-import-precision/openpresentation-opf-pptx-0.1.0.tgz, SHA-1 88a32daefda4524161c87cfc5adaa5270b3cf68a. Fresh consumer /private/tmp/opf-pptx-fidelity/consumer-import-precision installs it with local renderer 87663fb and published core 0.4.0/editor 0.1.1/CLI 0.1.0. Installed picture-import and background tests pass. verify-preview.mjs records all eight exact whole-slide PNG comparisons, editor import and the combined browser dependency boundary; results are in preview/report.json and preview-verification.log. No browser UI or native viewer run was performed for this milestone. Historical d08fa9e tarball SHA-1 3af059814d4f22ae2b992228b75b8659d9427756 remains in packed-image-import; it lacks the subsequent precision fix.\n\nBoth changes are local/unpublished, still using development version 0.1.0. The four follow-up draft PR/push request remains pending. The native gradient visual discrepancy and locked-desktop Keynote review remain unresolved; no publication or new native-compatibility claim follows from this checkpoint.\n\n\n## Native Keynote background verification and merge preparation\n\nPPTX commit 821c047 resolves the earlier native gradient verification gap. Keynote 14.4 displays editable Advanced Gradient Fill controls and exports the six landscape angles correctly. Twelve unchanged native PNGs cover those opaque angles and six portrait solid/gradient transparency cases. Eighteen comparisons, including the native Keynote PPTX reimport, pass: opaque maximum channel error 4/255 and mean below 0.38; transparent alpha error at most 1/255. Quick Look remains a thumbnail limitation, not evidence that Keynote renders these gradients flat. Microsoft PowerPoint remains unverified. Generated documents were closed without saving.\n\nThe Keynote round-trip also exposed synthetic titles added to empty/background-only slides. Import now preserves blank content and notes-only slides. Project-authored native fixtures and their hashes are checked in; normal CI does not require Keynote. The historical importer fails the blank-slide assertion. Final Node 20/24 complete suites, syntax, package metadata and browser dependency checks pass, including the 126-deck/805-slide structural corpus with previously documented substitutions. Logs are artifacts/backgrounds/native-node20.log and native-node24.log in the PPTX worktree.\n\nThe user has authorized pushing, PR updates and merging the four prepared follow-ups. Merge preparation covers PPTX 821c047, renderer 87663fb, site 2858456 and this core example/handoff branch. These changes do not publish new npm versions; the existing development version numbers must not overwrite registry releases. Historical pending-approval and locked-desktop notes above describe earlier checkpoints and are superseded here.\n\n## Published fidelity releases and registry verification\n\nThe follow-up implementations are merged and now published through trusted publishing with npm provenance:\n\n| Package | Version | Tagged source | Publish workflow |\n| --- | --- | --- | --- |\n| @openpresentation/opf | 0.4.1 | aed5e5493998a5081fea68bf3bd42c52409e0c15 | 34204122730 |\n| @openpresentation/cli | 0.1.1 | aed5e5493998a5081fea68bf3bd42c52409e0c15 | 34204125018 |\n| @openpresentation/opf-render | 0.2.0 | df7ce5c6915a084f101adf90e6329117c0094a23 | 34204875207 |\n| @openpresentation/opf-pptx | 0.2.0 | 1fef9dcfadeeb8310b3c3b668f7506b52717b695 | 34205556749 |\n| @openpresentation/opf-editor | 0.1.2 | 5819a2ac12ec22f08a348c81bc3c66630682ecfb | 34205593335 |\n\nCore/CLI release PR 18, renderer PR 3, PPTX PR 3 and editor PR 2 were merged after Node 20/24 CI and automated review. Their merge commits passed CI before tags were pushed. GitHub releases contain matching changelog notes. Registry propagation briefly delayed PPTX availability; publication was not rerun, and the subsequent exact-version install passed.\n\nRenderer/PPTX 0.2.0 require Node 20.9 or later and core 0.4.1. Editor 0.1.2 accepts renderer 0.1.1 or 0.2.x through its optional peer; its development dependency explicitly installs renderer 0.2.0 for CI. The renderer release uses the individually reviewed corrected-image baseline and retains the preceding core-0.4.0 manifest for audit. Only the repaired example slide changes; the other 804 raster hashes remain identical.\n\nThe clean registry consumer at artifacts/npm/registry-consumer installs all five exact release-plan versions without local package overrides. Model/API, TypeScript, browser bundling and CLI checks pass. The actual registry CLI reports 0.1.1 with bundled OPF 0.4.1 and passes 60 command checks. Eight complete JPEG image-slide previews are byte-identical before and after PPTX export/import using the installed registry packages.\n\nThe new pnpm test:registry-fidelity command runs immutable test/fixture snapshots against installed npm dist files, checks registry lock records and real paths, and rejects local package overrides. It passes 23 WebP and 24 JPEG raster/PDF cases, all 805 raster baselines, 18 captured Keynote comparisons, table/image/background/import tests and the 126-deck/805-slide structural corpus with its documented fallback fonts and 26 synthetic image substitutions. Coordinated CI now pins the release commits and also runs the exact-version registry integration and fidelity checks on Node 20/24; full core history makes the pinned browser harness source available.\n\nBrowser execution against the registry packages passes 176 editor harness checks plus 13 WebP and 16 JPEG checks. JPEG comparison retains the previously documented aggregate bounds (maximum channel 49, mean below 0.616, at most 1.225% of channels differing by more than 10); it is not pixel-identical browser output. These harnesses do not establish real OS IME, cross-browser behavior or Microsoft PowerPoint fidelity. Core remains free and provider-neutral; normal CI needs no native presentation application.\n\nGallery and site release worktrees are /private/tmp/opf-release-gallery/pptx-gallery and /private/tmp/opf-release-site/openpresentation-site on codex/fidelity-release-20260908. Their locked core is 0.4.1, and editor/showcase assets are regenerated from the five-package registry consumer with version/integrity/hash manifests. All 854 gallery examples validate/render, 106 gallery tests pass, and both production builds pass. The site syncs opf-v0.4.1 and exposes 583 raw files/six skills. Public deployment verification follows these prepared updates; earlier production manifests remain historical until those PRs merge.\n\n## Shared table rows and native rich-table import releases\n\nThe current coordinated package set is core 0.6.0, CLI 0.3.0, renderer 0.4.0, PPTX 0.4.0 and editor 0.3.0. `release-plan.json` pins all five versions and their immutable source commits. Core PR 23, renderer PR 5, PPTX PR 8 and editor PR 4 merged after Node 20/24 CI and automated review. Each merged tree matches the tested head. All five packages were published through trusted publishing with provenance, and registry tarball integrities match the tested release candidates.\n\nCore exports `layoutTable` for shared content-aware row geometry. Rows use spare height before shrinking text; rich cell lines reserve uniform native paragraph advances. Renderer and PPTX consume the same row/cell boxes and fitted text, while editor 0.3.0 aligns dependency minima. PPTX imports supported native rich table character styles, paragraph defaults, theme fonts/colors, external links, run/field/break order and significant whitespace directly from XML. Unstyled body cells remain strings. Cached display text does not reconstruct original scalar types or live fields.\n\nFinal PPTX/editor candidate tarballs with published core/renderer dependencies passed native import and row geometry tests on Node 20/24, 15 browser import/containment checks and 14 browser editor checks. Full standalone tests retained the 126-deck/805-slide structural corpus and all 805 renderer raster baselines. These checks do not establish Microsoft PowerPoint raster parity, complete conditional table styles/merged geometry/cell decoration, cross-engine editing or real OS IME support.\n\nCore publication run 34228179949 published npm successfully but its later GitHub release step failed because a matching release already existed. Preserve existing release notes when the workflow runs again; only create a GitHub release when absent. Do not republish the existing npm version. CLI run 34228594104, renderer run 34229511905, editor run 34230608709 and PPTX run 34231015995 succeeded. PPTX package-index propagation briefly delayed normal clean installation after the exact-version endpoint was available; publication was not repeated.\n\nThe gallery and public-site rollout uses isolated `codex/table-layout-registry-20260908` branches in `/private/tmp/opf-release-gallery/pptx-gallery` and `/private/tmp/opf-release-site/openpresentation-site`. Their core manifests and locks are updated to 0.6.0. Regenerate editor/showcase assets from the verified registry consumer, pin site documentation to the reviewed coordination commit, then verify production deployments and bytes. Earlier public deployment evidence remains historical until those updates land.\n"
|
|
80
104
|
},
|
|
81
105
|
{
|
|
82
106
|
"slug": "how-opf-works",
|
|
@@ -84,6 +108,12 @@ var docsData = Object.freeze([
|
|
|
84
108
|
"title": "How OPF Works",
|
|
85
109
|
"markdown": '# How OPF Works\n\nAn OPF document is one JSON file that answers three questions about a presentation:\n\n- **What does it say?** \u2014 `slides`, with content payloads and assets.\n- **Who is it for and why?** \u2014 `audience`, `purpose`, `tone`, `language`, and `narrative`.\n- **What should it look like?** \u2014 `design`, resolved through themes, color schemes, and font schemes.\n\nThe document records intent; an engine (a renderer, exporter, or editor) turns that intent into pixels or `.pptx` output. OPF deliberately stops at the format boundary: it never embeds OOXML, layout geometry, or renderer-specific state. You \u2014 or your agent \u2014 own the story, the data, and the ask; the format\'s job is to keep all of that readable, diffable, and out of `<p:sp>` tags.\n\n## Anatomy of a document\n\n```\nPresentation\n\u251C\u2500\u2500 identity ...... name, description, organization, speaker, author\n\u251C\u2500\u2500 intent ........ audience, purpose, tone, language, narrative, takeaway, duration\n\u251C\u2500\u2500 content ....... slides[]\n\u2502 \u251C\u2500\u2500 title / subtitle / tag / notes / section / beat / layout\n\u2502 \u2514\u2500\u2500 one content shape:\n\u2502 root payload (a single content kind)\n\u2502 blocks[] (ordered payloads, placement inferred)\n\u2502 region keys (3x3 placement grid)\n\u251C\u2500\u2500 design ........ theme, colorScheme, fontScheme, background, logo, header, footer\n\u251C\u2500\u2500 assets ........ named media sources, referenced as "asset:<id>"\n\u2514\u2500\u2500 catalogs ...... per-kind overrides: inline records and/or custom sources\n```\n\nOnly `slides` is required. The smallest valid document:\n\n```json\n{\n "name": "Minimal OPF Deck",\n "slides": [\n { "title": "Minimal OPF Deck" },\n { "title": "Next Steps", "text": "Use this as a starting point." }\n ]\n}\n```\n\nEverything else in the format is optional and additive.\n\n## Slides and content\n\nA slide carries its content in one of three shapes. Pick the loosest shape that says what you mean \u2014 engines handle placement.\n\n**1. Root payload** \u2014 one content kind directly on the slide. The kind is inferred from the field present (`text`, `items`, `chart`, `table`, `image`, `video`, `code`, `metric`, `quote`, `timeline`); see [`content-payloads.md`](./content-payloads.md) for the full table.\n\n```json\n{\n "title": "Operating Metric",\n "metric": { "value": "42%", "label": "Review cycle reduction", "trend": "up" }\n}\n```\n\nMultiple kinds at the slide root (with no explicit `type`, `blocks`, or regions) are shorthand for the equivalent `blocks`:\n\n```json\n{\n "title": "Habitat",\n "text": "Jaguars are strongly associated with water and dense cover.",\n "items": ["Rainforests and flooded wetlands", "Large defended territories"]\n}\n```\n\n**2. `blocks`** \u2014 an ordered list of payloads when a slide has several pieces of content but placement should stay renderer-inferred:\n\n```json\n{\n "title": "Customer Feedback",\n "blocks": [\n { "table": { "columns": ["Theme", "Mentions"], "rows": [["Speed", 42], ["Ease of use", 31]] } },\n { "quote": { "text": "The new workflow cut review time in half.", "attribution": "Operations Lead" } }\n ]\n}\n```\n\n**3. Promoted region keys** \u2014 a 3\xD73 placement grid when position matters:\n\n```\n left center right\n +--------------------+--------------------+--------------------+\n top | top:left | top:center | top:right |\n +--------------------+--------------------+--------------------+\n middle | middle:left | middle:center | middle:right |\n +--------------------+--------------------+--------------------+\n bottom | bottom:left | bottom:center | bottom:right |\n +--------------------+--------------------+--------------------+\n\n A bare column key ("left") spans all three rows.\n A bare row key ("top") spans all three columns.\n Keys span neighbors with "+" and intersect rows with columns via ":".\n```\n\nThe spans compose into the slide shapes you actually want:\n\n```\n "left" + "center+right" "top" + "middle+bottom"\n (sidebar + main) (headline band + body)\n +----------+------------------+ +-------------------------------+\n | | | | top |\n | | | +-------------------------------+\n | left | center+right | | |\n | | | | middle+bottom |\n | | | | |\n +----------+------------------+ +-------------------------------+\n\n "top" + "middle+bottom:left" + "middle+bottom:center+right"\n (headline band, then sidebar + main)\n +---------------------------------------------+\n | top |\n +---------------+-----------------------------+\n | | |\n | middle+bottom | middle+bottom:center+right |\n | :left | |\n | | |\n +---------------+-----------------------------+\n```\n\nThat last shape in JSON:\n\n```json\n{\n "title": "Adoption Doubled",\n "top": { "text": "Adoption doubled while support load stayed flat." },\n "middle+bottom:left": { "metric": { "value": "2.1x", "label": "Adoption" } },\n "middle+bottom:center+right": {\n "chart": { "type": "line", "data": { "columns": ["Month", "Teams"], "rows": [["Jan", 12], ["Feb", 18]] } }\n }\n}\n```\n\nAnd the two-column shape from the grid above:\n\n```json\n{\n "title": "Operating Snapshot",\n "left": { "table": { "columns": ["Metric", "Value"], "rows": [["Revenue", "$4.2M"]] } },\n "center+right": { "chart": { "type": "line", "data": { "columns": ["Month", "Revenue"], "rows": [["Jan", 3.4]] } } }\n}\n```\n\nRegion keys on one slide must not overlap, and regions cannot be mixed with a root payload. Slide-level strings `title`, `subtitle`, and `tag` sit alongside whichever content shape you use, and render into the matching placeholders of the resolved layout.\n\n## Layouts are hints, not contracts\n\n`Slide.layout` optionally references a record in the `layouts` catalog. The layout\'s placeholders describe what the layout *exposes* (a title slot, chart regions, image treatment) \u2014 they do not constrain what the slide may contain. This loose coupling is intentional:\n\n- A slide may use any region keys or payloads regardless of its declared layout. Validators do not error on a slide/layout mismatch.\n- When `layout` is omitted, engines infer one from the slide\'s payload or region keys.\n- Free-form layout names that don\'t resolve through any catalog fall through to engine-defined layouts.\n\nThe principle, used throughout OPF: **slides are the source of truth**. Layouts, narratives, and design records guide rendering; they never invalidate content.\n\n## Narrative is intent, not structure\n\n`narrative` declares the deck\'s story arc. It resolves to a record in the `narratives` catalog (e.g. `"classic-story"`, `"pitch-deck"`), each of which defines ordered **beats** \u2014 labeled segments of the arc such as `hook`, `problem`, `evidence`, `ask` \u2014 with optional slide-blueprint hints (`slideType`, `layoutHint`, `instructions`, `thoughtCues`).\n\nSlides opt into beats via `Slide.beat`. Nothing forces them to: validators warn on drift (orphan slides, unused beats) but never error.\n\n```json\n{\n "name": "Schema Pitch",\n "narrative": {\n "id": "technical-proof",\n "name": "Technical Proof",\n "beats": [\n { "id": "contract", "name": "Contract", "slideType": "text", "instructions": "State what stays stable." },\n { "id": "evidence", "name": "Evidence", "slideType": "chart" },\n { "id": "adoption", "name": "Adoption", "slideType": "list" }\n ]\n },\n "slides": [\n { "beat": "contract", "title": "The Contract", "text": "Beats describe intent without constraining slides." },\n { "beat": ["evidence", "adoption"], "title": "Proof And Ask", "items": ["One slide may cover several beats."] }\n ]\n}\n```\n\nObject form supports overrides: `{ "id": "classic-story", "beats": [...] }` merges inline beats into the catalog record by beat `id`. An object whose `id` matches no record \u2014 like `technical-proof` above \u2014 is a fully custom inline narrative. Deck-level concerns that aren\'t part of the storyline (`audience`, `tone`, `takeaway`, `duration`) live as siblings on the presentation root, not inside the narrative.\n\n## Catalog references and how they resolve\n\nMost reusable values in OPF are references into **catalogs**: named collections of records, each identified by a kebab-case `id`. The referencing fields are `narrative`, `language`, `tone`, `audience`, `purpose`, `design.theme`, `design.colorScheme`, `design.fontScheme`, `Slide.layout`, `Chart.type`, and the platform keys in `socials`.\n\nEvery reference resolves through the same chain, first match wins:\n\n```\n "design": { "colorScheme": "cool-horizon" }\n |\n v\n 1. catalogs.colorSchemes.records[] inline records in this document\n | miss\n v\n 2. catalogs.colorSchemes.source custom registry declared in this document\n | miss\n v\n 3. default catalog https://www.pptx.gallery/color-schemes\n | miss (bundled in spec/catalogs/ and in\n v the @openpresentation/opf package)\n validation warning \u2014 never an error \u2014 and an engine fallback\n```\n\nWhen a reference is omitted entirely, engines fall back to their own defaults (see [`spec/reference/engine-defaults.json`](../spec/reference/engine-defaults.json) for a reference example \u2014 that file is engine configuration, not part of the document contract).\n\nThree reference forms are accepted wherever a catalog reference is allowed:\n\n- **Bare id** for the common case: `"narrative": "classic-story"`.\n- **Object form** for catalog-backed overrides: `{ "id": "cool-horizon", "accent1": "#0F4C81" }` resolves the record as a base, then inline fields win per key.\n- **URL or `pkg:` reference**, which skips the catalog lookup and resolves directly.\n\nA document can carry its own records or point at a private registry, which also silences unknown-id warnings for that kind:\n\n```json\n{\n "name": "Branded Deck",\n "design": { "colorScheme": "acme-brand" },\n "catalogs": {\n "colorSchemes": {\n "records": [{ "id": "acme-brand", "accent1": "#0F4C81", "light1": "#FFFFFF", "dark1": "#0B1B2B" }]\n },\n "narratives": { "source": "https://catalogs.example.com/narratives" }\n },\n "slides": [{ "title": "Branded Deck" }]\n}\n```\n\n## Design in one paragraph\n\n`design` selects a `theme` (which bundles default color scheme, font scheme, background, and dimensions) and may override any of those directly; `Slide.design` overrides the deck design per slide. More specific always wins, field by field. Color schemes and font schemes each support two mixable models \u2014 OOXML slots/pairs that round-trip to PowerPoint, and abstract roles (`primary`, `heading`, `code`, \u2026) that engines map onto slots. The full precedence chain with worked examples is in [`design-resolution.md`](./design-resolution.md).\n\n## Assets\n\nBinary content lives in the top-level `assets` registry, keyed by id. Content payloads and design fields reference entries with `asset:<id>` strings; asset `src` values accept HTTPS URLs, data URIs, and paths resolved against the OPF file location.\n\n## A complete small deck\n\nEverything above, together \u2014 intent metadata, a catalog-backed narrative with beats, design, an organization and speaker, an asset-backed chart, regions, notes, and sections:\n\n```json\n{\n "$schema": "https://openpresentation.org/schema/opf/v1",\n "name": "Q3 Business Review",\n "description": "Quarterly review for the executive team.",\n "audience": "executives",\n "purpose": "decide",\n "tone": "formal",\n "language": "en-US",\n "narrative": "qbr",\n "takeaway": "Approve the expanded rollout budget.",\n "duration": 20,\n "organization": {\n "id": "acme",\n "name": "Acme Corp",\n "domain": "acme.com",\n "socials": { "linkedin": "acme" }\n },\n "speaker": { "id": "alice", "name": "Alice Chen", "title": "VP Operations", "organizationId": "acme" },\n "design": {\n "theme": "classic",\n "colorScheme": "forest-green",\n "footer": { "left": { "organization": true }, "right": { "slideNumber": true } }\n },\n "assets": {\n "adoption-csv": { "src": "./data/adoption.csv", "alt": "Monthly adoption data" }\n },\n "slides": [\n {\n "layout": "title",\n "beat": "objectives",\n "title": "Q3 Business Review",\n "subtitle": "Operations \u2014 October 2025"\n },\n {\n "beat": "performance-headline",\n "title": "Adoption Doubled",\n "left": { "metric": { "value": "2.1x", "label": "Quarter-over-quarter adoption", "trend": "up" } },\n "center+right": {\n "chart": { "type": "line", "data": { "src": "asset:adoption-csv", "columns": ["Month", "Active Teams"] } }\n },\n "notes": "Pause here; this is the slide the decision hangs on."\n },\n {\n "beat": "risks",\n "section": "Decision",\n "title": "What Could Go Wrong",\n "items": [\n "Capacity: two regions are at 85% utilization.",\n {\n "text": "Churn risk in the legacy tier.",\n "description": "Mitigation: migration incentives ship in November."\n }\n ]\n },\n {\n "beat": "asks",\n "title": "The Ask",\n "text": "Approve $1.2M to expand the rollout to all regions in Q4."\n }\n ]\n}\n```\n\nThe beat ids (`objectives`, `performance-headline`, `risks`, `asks`) come from the `qbr` narrative record; the theme, color scheme, chart type, and layout all resolve through the bundled catalogs. For a fixture that exercises the full surface in one file, see [`examples/technical/full-feature-tour.opf.json`](../examples/technical/full-feature-tour.opf.json).\n\n## Validation philosophy\n\nTwo layers, with a deliberate split:\n\n- **Schema errors** for structural problems: wrong types, overlapping region keys, payloads mixing incompatible content kinds, a region payload missing concrete content.\n- **Warnings** for advisory drift: unknown catalog ids, narrative/slide mismatches. These never make a document invalid.\n\n`validatePresentation` from `@openpresentation/opf` applies both layers locally.\n\n## Where to go next\n\n- [`schema-reference.md`](./schema-reference.md) \u2014 every field of every object in the presentation schema.\n- [`catalog-schema-reference.md`](./catalog-schema-reference.md) \u2014 every field of every catalog record schema.\n- [`content-payloads.md`](./content-payloads.md) \u2014 payload shapes and inference rules with examples.\n- [`design-resolution.md`](./design-resolution.md) \u2014 the design precedence algorithm.\n- [`examples.md`](./examples.md) \u2014 guide to the example decks under `examples/`.\n\nThen write a deck, commit it, revise it, and read the diff. A two-line diff for a two-word change is the whole argument for the format.\n'
|
|
86
110
|
},
|
|
111
|
+
{
|
|
112
|
+
"slug": "lint",
|
|
113
|
+
"file": "docs/lint.md",
|
|
114
|
+
"title": "OPF lint for humans and agents",
|
|
115
|
+
"markdown": '# OPF lint for humans and agents\n\nCore **0.10.0** adds the browser-safe `@openpresentation/opf/lint` entrypoint, and CLI **0.8.0** adds `opf lint`. Earlier versions do not include them; check `opf --help` before asking an installed CLI to lint.\n\n```sh\nnode packages/cli/dist/index.js lint deck.opf.json\nnode packages/cli/dist/index.js lint deck.opf.json --config brand-lint.json --strict\n```\n\nLint is read-only and local. It returns JSON diagnostics with stable rule IDs, severity, JSON Pointer paths, original-source UTF-16 ranges, one-based line/column, explanations, contextual suggestions, and schema/catalog definitions. The CLI includes the original file SHA-256 and the bundled core version. A supplied configuration file has its own path and hash. No AI call, account, remote catalog fetch, source normalization, or automatic fix is involved.\n\n| Check | Behavior |\n| --- | --- |\n| Strict JSON syntax | Reports malformed tokens, comments and trailing commas with source ranges |\n| Duplicate JSON keys | Reports both escaped and literal spellings of the same key; an earlier value cannot silently disappear into `JSON.parse` |\n| OPF schema and semantic constraints | Retains the full validator issue, including all union alternatives, and points to the actual schema |\n| Catalog references | Uses document records over supplied loaded records over built-ins; unknown IDs are advisory, including engine-defined layouts |\n| Catalog definitions | Validates supplied and inline records; rejects duplicate IDs within one catalog and reports invalid overrides |\n| Asset references | Reports missing document registry IDs and cyclic `asset:` references; does not fetch resource bytes |\n| Explicit contracts | Reports existing fields outside the allowed values in a host-supplied policy |\n\nFree-form audience/purpose descriptions and arbitrary extension data do not become catalog references because of their spelling. An inline custom tone/narrative remains distinct from a string catalog reference. External catalog sources remain visible as informational diagnostics; URL and `pkg:` records are not resolved by this local lint pass. Suggestions name records actually present in the supplied context and never silently replace authored values.\n\nLanguage string shorthands with [BCP-47 syntax](https://www.rfc-editor.org/rfc/rfc5646.html#section-2.1), including regional, extended, private-use and grandfathered forms, do not require a language catalog record. Their spelling is preserved. This is syntax recognition, not IANA registry validation; an explicit `language.id` is still a catalog reference, and the existing OPF `en-UK` error remains enforced. Custom inline narrative IDs remain valid with or without a `beats` array.\n\n`valid` means no lint errors. `schemaValid` separately reports structural validation, and is `null` when malformed JSON prevented validation. Exit code 0 means no lint errors; 1 means lint errors, or warnings with `--strict`; 2 means a usage, configuration or I/O failure. The existing `opf validate` command retains its existing report and exit behavior.\n\n## Catalog context and design contracts\n\nAn explicit local JSON file may contain `catalogs` and `contracts`. It is host configuration, separate from the OPF document. Fields under document `extensions` are data and cannot install lint policy.\n\n```json\n{\n "catalogs": {\n "layouts": [\n {"id":"partner-title","name":"Partner title","placeholders":[{"type":"title"}]}\n ]\n },\n "contracts": [\n {\n "path":"/slides/*/layout",\n "allowedValues":["partner-title","text-1x"],\n "message":"Use the brand layouts {{allowed}} at {{path}}. See {{file}}.",\n "documentation":"brand-guide.md#layouts",\n "severity":"error"\n }\n ]\n}\n```\n\nContract paths are JSON Pointer patterns: `~0` escapes `~`, `~1` escapes `/`, and a whole `*` segment matches one property or array index. Contracts check existing fields; they do not require an omitted field or insert defaults. Allowed values are JSON primitives. Optional message placeholders are `{{path}}`, `{{value}}`, `{{allowed}}`, and `{{file}}`. Invalid or misspelled configuration keys fail instead of being ignored. Messages and catalog labels are data, not executable instructions.\n\n## Library use and repair\n\n```js\nimport { lintSource, lintPresentation } from \'@openpresentation/opf/lint\';\nconst report = lintSource(source, {catalogs: loadedCatalogRecords, contracts});\nconst objectReport = lintPresentation(document, {catalogs: loadedCatalogRecords});\n```\n\nThe object API has no source ranges and does not claim to inspect original JSON spelling. `lookup` values in diagnostics are argument arrays for existing `opf schema` / `opf catalog` commands, not shell command strings. Use the same package version when looking up a definition.\n\nInspect a suggested change, preserve unrelated content, then apply a guarded edit with the existing `opf edit --expect-sha256 ... --dry-run` workflow. Rerun lint and render the candidate before saving. Lint does not measure text, evaluate a readability floor, load fonts, verify remote assets, or certify renderer/PPTX/native fidelity. Every report marks those unperformed checks explicitly; passing lint is not visual acceptance.\n'
|
|
116
|
+
},
|
|
87
117
|
{
|
|
88
118
|
"slug": "live-editor",
|
|
89
119
|
"file": "docs/live-editor.md",
|
|
@@ -108,6 +138,12 @@ var docsData = Object.freeze([
|
|
|
108
138
|
"title": "Native PowerPoint feature matrix \u2014 September 9, 2026",
|
|
109
139
|
"markdown": "# Native PowerPoint feature matrix \u2014 September 9, 2026\n\n## Candidate comparison support\n\nThe registry baseline below is preserved. To evaluate an unpublished converter, pass its built `dist/index.js` as a fourth argument to both `generate` and `compare`, using a separate output directory. The report's `candidate` field explicitly labels it as `local-candidate-not-registry-release`, records the declared version and hashes every runtime/vendor file plus package/lock manifests. Its installed core/renderer versions and registry integrities must match the baseline consumer. Comparison rejects a missing or changed candidate; omitting the optional argument remains registry-only. Node 20/24 comparisons and deliberate omission rejection were executed on the native 0.5.2 candidate.\n\nReview found that matching versions and lock integrities alone could allow a linked checkout to masquerade as an installed dependency. Candidate core/renderer paths must now resolve inside the candidate's installed `node_modules`, and their lock records must be non-linked registry URLs. The regression below passes on Node 20/24 and rejects a same-version linked dependency with a matching lock integrity before export:\n\n```powershell\nnode scripts/test-native-candidate-guard.mjs artifacts/npm/registry-consumer artifacts/pptx-native-content\n```\n\nConverter [PR #13](https://github.com/OpenPresentation/opf-pptx/pull/13), candidate `422f1e39e643cbb1c23260f0c9ddef7a3c6ec722`, improves metric/quote/code/timeline layout and chart-label contrast. Its [separate candidate evidence](https://github.com/OpenPresentation/opf-pptx/blob/422f1e39e643cbb1c23260f0c9ddef7a3c6ec722/docs/native-content-candidate.md) records native checks and remaining fidelity/release gates. Review subsequently exposed long quotes overlapping the footer in both renderer and converter. Renderer [PR #8](https://github.com/OpenPresentation/opf-render/pull/8) prepares 0.5.1 with body space reserved before text fitting; the dependent converter fix requires that renderer's publication, a registry lock update and renewed candidate/native evidence. This does not change published PPTX 0.5.1 or the historical observations below.\n\n## Published 0.5.1 observations\n\nReal PowerPoint 16 opens, rasterizes, edits and saves all 19 slides in eight controlled feature cases. Every native edit survives reopen and schema-valid reimport on Node 20/24. PowerPoint exposes three native tables, one editable Office chart and one native picture. The rich text/list, dynamic nested composition, scalar table, code, metric, quote, timeline, chart, grid-span and embedded-image cases come from installed registry core 0.7.0 examples. Renderer 0.5.0 and PPTX 0.5.1 are the actual registry packages, with lockfile integrities recorded in the [machine-readable report](evidence/native-feature-matrix/comparison.json).\n\n**Visual equivalence is not established.** The native rasters reveal substantive differences which file validity, editability and zero converter diagnostics did not detect:\n\n| Case | Observed native difference | Required follow-up |\n| --- | --- | --- |\n| Metric | Value and supporting text are substantially smaller. | Replace exporter hard-coded font sizes/positions with the renderer's measured layout contract. |\n| Quote | Native output changes bold text to italic, moves attribution under the quote and omits its source. | Preserve quote/source content, typography and attribution geometry. |\n| Timeline | Native output is a plain text list instead of the rendered timeline line, markers and alternating labels. | Export editable native timeline shapes using shared geometry. |\n| Code | Background/border, header content and text placement differ. | Align native code panel styling and measured text with preview. |\n| Line chart | Native Office axes use different ticks and nearly invisible dark text against the dark theme. | Preserve native chart editability while fixing axis contrast and reviewing scale/tick geometry. |\n| Dynamic composition | Overall regions remain arranged correctly, but native text wraps and vertical placement differ. | Inspect line box/font conversion against native PowerPoint. |\n\nThe exporter source confirms separate hard-coded paths for metrics, quotes, timelines and code. These findings remain unresolved in published PPTX 0.5.1. They require implementation and renewed native raster checks before a fidelity claim. Do not infer that unrelated rich text, arbitrary imported tables, every chart variant, media playback or non-Latin shaping is covered by this sample.\n\nThe comparison uses the same four locally installed Calibri faces for text measurement and SVG rasterization, and explicit 1280\xD7720 slide dimensions. The authored Aptos run is deliberately normalized to Calibri and recorded. Intermediate requested weights resolve to regular/bold and all seven such substitutions are listed. This isolates native differences but does not prove original-font fidelity. No proprietary font binaries or external assets are distributed. The embedded image comes from the published fixture's data URI.\n\nGlobal RGB mean absolute channel differences range from 0.9763 to 6.0587 on a 0\u2013255 scale; those are observations, not equivalence thresholds. Large blank areas can hide missing features: for example, the visibly different timeline still has mean error 2.1129. Each contact sheet places the renderer on the left and actual PowerPoint on the right; row-to-fixture mappings and hashes are in the report:\n\n- [Rich text, lists and dynamic composition](evidence/native-feature-matrix/contact-1.png)\n- [Nested layout, tables, code and metric](evidence/native-feature-matrix/contact-2.png)\n- [Quote, timeline, chart and grid spans](evidence/native-feature-matrix/contact-3.png)\n- [Embedded raster image](evidence/native-feature-matrix/contact-4.png)\n\nRegenerate from this GitHub checkout and a fresh registry consumer containing the release-plan packages plus the renderer's raster dependencies:\n\n```powershell\nnode scripts/test-native-feature-matrix.mjs artifacts/npm/registry-consumer artifacts/native-feature-matrix generate\n./scripts/test-native-feature-matrix.ps1 -EvidenceDirectory artifacts/native-feature-matrix\nnode scripts/test-native-feature-matrix.mjs artifacts/npm/registry-consumer artifacts/native-feature-matrix compare\n```\n\nThe scripts verify registry resolution, generated input hashes, native raster and saved-file hashes, slide counts, native table/chart/picture counts, every native text edit after reopen, all 24 original/saved/edited deck reimports, and source/native contact sheets. Native slide text and geometry inventories are retained in the report. The COM script closes only its own presentations and leaves PowerPoint and user documents open. The comparison does not assert lossless content/structure round-trip or pixel equivalence. Keep the existing three-slide styled-border regression too; this matrix supplements it.\n"
|
|
110
140
|
},
|
|
141
|
+
{
|
|
142
|
+
"slug": "next-agent-prompt-2026-09-15",
|
|
143
|
+
"file": "docs/next-agent-prompt-2026-09-15.md",
|
|
144
|
+
"title": "Copy/paste prompt for the next project owner",
|
|
145
|
+
"markdown": "# Copy/paste prompt for the next project owner\n\nContinue OpenPresentation as its primary project owner. Build on accepted work,\nkeep changes committed and pushed through focused PRs as you go, and carry the\nnext bounded developer-readiness milestone through validation and release.\nDo not restart the ecosystem or redesign the published websites.\n\nRead OpenPresentation/opf docs/handoff-2026-09-15.md, docs/status-2026-09-15.md,\ndocs/plans/developer-adoption-20260915.md,\ndocs/plans/deferred-shaping-20260915.md and\ndocs/plans/ecosystem-objective-2026-09-09.md. Inspect current defaults, PRs,\nregistry and deployments: these files are dated checkpoints, not assumptions\nthat nothing has changed.\n\nRepositories: OpenPresentation/{opf,opf-render,opf-editor,opf-pptx} and\nData-Advantage/{openpresentation-site,pptx-gallery,pptx-dev}. Default branches\nare main except pptx-dev/master. Local clones are under /Users/michael/Source;\nuse GitHub if those paths do not exist. Use Node24, pinned lockfiles/package\nmanagers (pnpm10.33.2 core/site/gallery, pnpm11.1.3 pptx-dev, npm libraries),\neach AGENTS.md and relevant OPF skills. Schemas/catalogs are authoritative, but\nschema support does not certify editor, renderer or native export fidelity.\n\nAt this checkpoint npm versions are @openpresentation/opf0.10.0,\nopf-render0.8.0, opf-editor0.7.0, opf-pptx0.8.0 and cli0.8.0. Home/playground\nhave editable JSON, live previews, preview edits back to JSON, contextual\ncatalog choices and code-editor assistance. Preserve their appearance. Lint\nand contextual design contracts exist. The CLI supports create, validate,\nlint, revision-guarded JSON edits, data import, pagination, schemas/catalogs and\nsix-skill installation/update/status. Check actual help before promising other\ncommands; rendering/export is available through documented library/UI APIs.\n\nThe cleanup accepted eleven dependency updates and four furniture increments\n(core79, renderer20, editor17, PPTX34), and closed the Node26-types update.\nFour shaping PRs (core83, renderer21, editor21, PPTX35) conclude with docs/\nevidence only. Their prototypes are archived, not released. Check final PR/CI\nstates. Main's new furniture APIs still need coordinated package releases.\nThe public sites passed 41 production browser workflows at the handoff commits;\nretain evidence and rerun affected flows when changing them.\n\nFirst deliver a clear starting path from real published packages: release the\naccepted furniture increment in dependency order, then an independently\ninstallable example that authors JSON, validates/lints, resolves offline fonts,\ncomposes/paginates, edits with undo, previews and exports supported formats.\nCorrect stale API/version guidance in docs/skills, publish a truthful feature\nmatrix, and verify browser/Node boundaries without hidden sibling imports.\nUpdate release-plan and immutable verification refs; never overwrite versions.\nInspect actual tarballs, fresh installs and intended predecessor compatibility.\nAdopt features across the existing sites under core issue88 and verify canonical\nproduction routes, not only dependency manifests.\n\nPreserve each library's remote codex/archive-shaping-20260915 branch. Immutable\ncheckpoints: core 36ff66b3d62b39d7d27dcda022b7e79e541bd603;\nrenderer 343fb84223f4383ffe546157c6989ccc505c0acb;\neditor ae4cc6426b04c7ca428c1b4acacea2e11d99fa84;\nPPTX fbe9a73d012dbd51d65a39251e405e488651a70b.\nThey retain HarfBuzz/prepared glyphs, rich-source groups, variable/CFF work,\ncarets/graphemes/navigation/selection and tab/export experiments with evidence.\nResume from current main and port bounded changes; do not merge archives\nwholesale. Renderer issue24 tracks the Linux native-width contract failure:\n334.06213682353496px measured vs Chromium334.193115234375px at the unchanged\n0.1px gate. Rounding fixes Linux but breaks macOS; some platform widths cannot\nfit a common prediction within that tolerance. Define supported geometry/\npainting behavior and retain failures. No offsets, platform guesses, relaxed\nassertions or golden rewrites. The archived editor separately expects ten packed\nrich-input checks while thirteen pass: repair and rerun that harness on resume.\n\nNative PowerPoint acceptance is split into core issue87 and its plan. Preserve\nimage opening, provenance edit/save/reopen, tabs, notes-master ordering and\nphysical font identity/embedding gaps. Serialization/self-import are not native\nacceptance. Do not retry Windows COM or kill Office processes until host recovery\nis confirmed. Do not use/distribute restricted Aptos4.40 without compatible\nexplicit permission. Broader fonts/IME/bidi/fallback, layout repair and complete\nvisual editor interactions remain planned. Current PDF is raster-backed;\nselectable vector PDF, general SVG and semantic Mermaid follow font reliability.\n\nKeep the ecosystem open, provider-neutral and locally usable without an account\nor model call. No mandatory embedded AI design agent. Preserve text, images,\nUnicode, whitespace, formatting, source mappings, reading order, intent and\nundo. Bound layout repair and emit actionable diagnostics rather than dropping\ncontent. Review complete rendered slides, not only metrics or hashes. Separate\nsource, packed consumer, registry, browser, deployment and native acceptance.\n\nUse accurate progress updates and proceed with authorized reversible work\nwithout repeated permission questions. Preserve existing work, use codex/\nbranches and focused PRs, and merge only validated scope. Store incomplete work\nand failures in durable roadmap issues with evidence. Report what is committed,\nmerged, released, deployed, deferred and next. The broad ecosystem objective is\nnot complete merely because the PR queue is empty. Finish with an updated handoff.\n"
|
|
146
|
+
},
|
|
111
147
|
{
|
|
112
148
|
"slug": "open-ecosystem",
|
|
113
149
|
"file": "docs/open-ecosystem.md",
|
|
@@ -124,7 +160,7 @@ var docsData = Object.freeze([
|
|
|
124
160
|
"slug": "release-process",
|
|
125
161
|
"file": "docs/release-process.md",
|
|
126
162
|
"title": "OPF Release Process",
|
|
127
|
-
"markdown": "# OPF Release Process\n\nThis document is the release runbook for the public JavaScript package,\n[`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf).\n\nThe canonical release path is:\n\n1. Merge the release commit to `main`.\n2. Push a semver tag whose name matches the package version.\n3. Let GitHub Actions publish to npm through npm trusted publishing.\n4. Verify npm and the automatically generated GitHub release notes.\n\n## Release Preconditions\n\nBefore tagging, confirm that the release commit on `main` already contains:\n\n- `packages/javascript/package.json` with the intended version.\n- `CHANGELOG.md` with the matching release section.\n- Passing `OPF CI` on the release commit.\n\nThe publish workflow validates the tag name against\n`packages/javascript/package.json`, so the tag must point at the release commit.\n\n## Tag And Publish\n\nUse the `opf-vX.Y.Z` tag form for the package release:\n\n```sh\ngit checkout main\ngit pull origin main\ngrep '\"version\"' packages/javascript/package.json\ngit tag opf-vX.Y.Z\ngit push origin opf-vX.Y.Z\n```\n\nFor example, version `0.3.0` used:\n\n```sh\ngit tag opf-v0.3.0\ngit push origin opf-v0.3.0\n```\n\nPushing the tag triggers `.github/workflows/npm-publish.yml`. The workflow:\n\n- runs on tags matching `opf-v*` or `@openpresentation/opf@v*`\n- installs dependencies with pnpm on Node 24\n- verifies the tag matches `packages/javascript/package.json`\n- runs typecheck and tests\n- runs the npm package dry-run check\n- publishes from `packages/javascript` with `npm publish --access public`\n\nDo not rerun a successful publish for the same version. npm package versions are\nimmutable; a second publish for an already-published version should fail.\n\n## Trusted Publishing\n\nnpm publishing is configured to use GitHub Actions OIDC trusted publishing, not\na long-lived npm token.\n\nExpected npm package trusted-publisher settings:\n\n| Setting | Value |\n|---|---|\n| Package | `@openpresentation/opf` |\n| Publisher | GitHub Actions |\n| Organization/repository | `OpenPresentation/opf` |\n| Workflow filename | `npm-publish.yml` |\n| Environment | empty, unless the workflow is later moved behind a GitHub Environment |\n| Permission | `npm publish` |\n\nExpected workflow settings:\n\n```yaml\npermissions:\n contents: read\n id-token: write\n```\n\nThe publish step should not set `NODE_AUTH_TOKEN`:\n\n```yaml\n- name: Publish to npm\n working-directory: packages/javascript\n run: npm publish --access public\n```\n\nIf a future release fails with npm authentication errors, check the npm\ntrusted-publisher settings first. Only use an `NPM_TOKEN` repository secret as a\ntemporary fallback, and remove or revoke it once OIDC publishing works again.\n\n## Verify The Release\n\nAfter the workflow completes, verify npm:\n\n```sh\nnpm view @openpresentation/opf version\n```\n\nThe output should equal the package version that was tagged.\n\nSpot-check the validator API from a clean project or temporary directory:\n\n```sh\nnpm install @openpresentation/opf@X.Y.Z\nnode --input-type=module -e \"import {validatePresentation} from '@openpresentation/opf'; console.log(validatePresentation({name:'t', narrative:'not-a-real-id', slides:[{title:'t'}]}).warnings)\"\n```\n\nThe expected result is one warning about an unknown narratives catalog id.\n\n## GitHub Release Notes\n\nThe core tag workflow creates a GitHub Release from the matching changelog section after publishing. Verify that release after npm is verified. If release creation failed, create the missing release for the existing tag:\n\n```sh\ngh release create opf-vX.Y.Z \\\n --repo OpenPresentation/opf \\\n --title '@openpresentation/opf X.Y.Z' \\\n --notes-file /path/to/release-notes.md\n```\n\nUse the matching `## X.Y.Z` section from `CHANGELOG.md` as the release notes.\n\n## Troubleshooting\n\nIf the tag/version check fails, the tag does not point at the release commit or\nthe tag name does not match `packages/javascript/package.json`. Delete the bad\nlocal and remote tag, fetch `main`, and tag the correct commit:\n\n```sh\ngit push origin :refs/tags/opf-vX.Y.Z\ngit tag -d opf-vX.Y.Z\ngit checkout main\ngit pull origin main\ngit tag opf-vX.Y.Z\ngit push origin opf-vX.Y.Z\n```\n\nIf tests fail, fix the code on `main`, create a new release commit, and move the\ntag only if npm has not already published that version.\n\nIf npm publish fails with `ENEEDAUTH`, confirm:\n\n- npm has a trusted publisher for `OpenPresentation/opf`\n- the trusted publisher uses workflow filename `npm-publish.yml`\n- `.github/workflows/npm-publish.yml` has `id-token: write`\n- the publish job is running on a modern Node/npm toolchain\n\nIf npm publish fails after the version is already present on npm, do not retry\nthe same publish. Verify the package and treat the failure as a duplicate\npublish attempt.\n"
|
|
163
|
+
"markdown": "# OPF Release Process\n\nUse Node 24 (`24.x`) for all future source, candidate and registry verification.\nThe next releases must document the [Node 24 migration](migrations/node24.md)\nand use new versions. Historical dual-runtime release records remain unchanged.\n\nThis document is the release runbook for the public JavaScript package,\n[`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf).\n\nThe canonical release path is:\n\n1. Merge the release commit to `main`.\n2. Push a semver tag whose name matches the package version.\n3. Let GitHub Actions publish to npm through npm trusted publishing.\n4. Verify npm and the automatically generated GitHub release notes.\n\n## Release Preconditions\n\nBefore tagging, confirm that the release commit on `main` already contains:\n\n- `packages/javascript/package.json` with the intended version.\n- `CHANGELOG.md` with the matching release section.\n- Passing `OPF CI` on the release commit.\n\nThe publish workflow validates the tag name against\n`packages/javascript/package.json`, so the tag must point at the release commit.\n\n## Tag And Publish\n\nUse the `opf-vX.Y.Z` tag form for the package release:\n\n```sh\ngit checkout main\ngit pull origin main\ngrep '\"version\"' packages/javascript/package.json\ngit tag opf-vX.Y.Z\ngit push origin opf-vX.Y.Z\n```\n\nFor example, version `0.3.0` used:\n\n```sh\ngit tag opf-v0.3.0\ngit push origin opf-v0.3.0\n```\n\nPushing the tag triggers `.github/workflows/npm-publish.yml`. The workflow:\n\n- runs on tags matching `opf-v*` or `@openpresentation/opf@v*`\n- installs dependencies with pnpm on Node 24\n- verifies the tag matches `packages/javascript/package.json`\n- runs typecheck and tests\n- runs the npm package dry-run check\n- publishes from `packages/javascript` with `npm publish --access public`\n\nDo not rerun a successful publish for the same version. npm package versions are\nimmutable; a second publish for an already-published version should fail.\n\n## Trusted Publishing\n\nnpm publishing is configured to use GitHub Actions OIDC trusted publishing, not\na long-lived npm token.\n\nExpected npm package trusted-publisher settings:\n\n| Setting | Value |\n|---|---|\n| Package | `@openpresentation/opf` |\n| Publisher | GitHub Actions |\n| Organization/repository | `OpenPresentation/opf` |\n| Workflow filename | `npm-publish.yml` |\n| Environment | empty, unless the workflow is later moved behind a GitHub Environment |\n| Permission | `npm publish` |\n\nExpected workflow settings:\n\n```yaml\npermissions:\n contents: read\n id-token: write\n```\n\nThe publish step should not set `NODE_AUTH_TOKEN`:\n\n```yaml\n- name: Publish to npm\n working-directory: packages/javascript\n run: npm publish --access public\n```\n\nIf a future release fails with npm authentication errors, check the npm\ntrusted-publisher settings first. Only use an `NPM_TOKEN` repository secret as a\ntemporary fallback, and remove or revoke it once OIDC publishing works again.\n\n## Verify The Release\n\nAfter the workflow completes, verify npm:\n\n```sh\nnpm view @openpresentation/opf version\n```\n\nThe output should equal the package version that was tagged.\n\nSpot-check the validator API from a clean project or temporary directory:\n\n```sh\nnpm install @openpresentation/opf@X.Y.Z\nnode --input-type=module -e \"import {validatePresentation} from '@openpresentation/opf'; console.log(validatePresentation({name:'t', narrative:'not-a-real-id', slides:[{title:'t'}]}).warnings)\"\n```\n\nThe expected result is one warning about an unknown narratives catalog id.\n\n## GitHub Release Notes\n\nThe core tag workflow creates a GitHub Release from the matching changelog section after publishing. Verify that release after npm is verified. If release creation failed, create the missing release for the existing tag:\n\n```sh\ngh release create opf-vX.Y.Z \\\n --repo OpenPresentation/opf \\\n --title '@openpresentation/opf X.Y.Z' \\\n --notes-file /path/to/release-notes.md\n```\n\nUse the matching `## X.Y.Z` section from `CHANGELOG.md` as the release notes.\n\n## Troubleshooting\n\nIf the tag/version check fails, the tag does not point at the release commit or\nthe tag name does not match `packages/javascript/package.json`. Delete the bad\nlocal and remote tag, fetch `main`, and tag the correct commit:\n\n```sh\ngit push origin :refs/tags/opf-vX.Y.Z\ngit tag -d opf-vX.Y.Z\ngit checkout main\ngit pull origin main\ngit tag opf-vX.Y.Z\ngit push origin opf-vX.Y.Z\n```\n\nIf tests fail, fix the code on `main`, create a new release commit, and move the\ntag only if npm has not already published that version.\n\nIf npm publish fails with `ENEEDAUTH`, confirm:\n\n- npm has a trusted publisher for `OpenPresentation/opf`\n- the trusted publisher uses workflow filename `npm-publish.yml`\n- `.github/workflows/npm-publish.yml` has `id-token: write`\n- the publish job is running on a modern Node/npm toolchain\n\nIf npm publish fails after the version is already present on npm, do not retry\nthe same publish. Verify the package and treat the failure as a duplicate\npublish attempt.\n"
|
|
128
164
|
},
|
|
129
165
|
{
|
|
130
166
|
"slug": "rich-text",
|
|
@@ -136,13 +172,25 @@ var docsData = Object.freeze([
|
|
|
136
172
|
"slug": "schema-reference",
|
|
137
173
|
"file": "docs/schema-reference.md",
|
|
138
174
|
"title": "OPF Presentation Schema Reference",
|
|
139
|
-
"markdown": "# OPF Presentation Schema Reference\n\nThis reference documents the author-facing shape of a complete `*.opf.json` presentation document. It summarizes the canonical schema in `spec/schemas/opf.schema.json`; the schema remains the source of truth for validators.\n\n## Document Contract\n\n- Schema id: `https://openpresentation.org/schema/opf/v1`\n- Required top-level fields: `slides`\n- Additional top-level fields: not allowed\n\n## Top-Level Fields\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | no | `const:\"https://openpresentation.org/schema/opf/v1\"` | Optional OPF schema version. When omitted, validators and engines should assume the latest supported OPF schema. |\n| `name` | no | `string` | Display name of the presentation for GUI/TUI lists, library/search indexing, OS-level metadata, and default export filenames. This is deck identity, not slide content. Use slides[].title and slides[].subtitle for text... |\n| `description` | no | `string` | Free-form prose describing what this presentation is about. Used by agents and humans as a deck-level summary; complements purpose (the goal) and narrative (the structured storyline). Round-trips to OOXML 'docProps/co... |\n| `filename` | no | `string` | Optional base filename for exports (without extension). Engine strips a trailing .pptx, .pdf, .png, or .svg (case-insensitive) and appends the target format's extension. When omitted, the engine slugifies name when pr... |\n| `organization` | no | `oneOf:ref:Organization / array<ref:Organization>` | Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (declared via Organization.role or, if no role is set... |\n| `speaker` | no | `oneOf:ref:Speaker / array<ref:Speaker>` | Person presenting the deck. Array form supports panels and multi-speaker decks. Used for cover slides, bio slides, footers, and panel attribution. |\n| `author` | no | `oneOf:string / array<string>` | Optional credit for the person who authored or contributed to the deck, distinct from speaker. Array form supports multiple contributors. Round-trips to OOXML 'docProps/core.xml' as '<dc:creator>' (semicolon-joined wh... |\n| `audience` | no | `oneOf:string / array<oneOf:string / ref:Audience>` | Intended audiences for the presentation. Accepts either: - A single string shorthand: free-form description ('Series B investors'), an audiences catalog id ('executives'), an HTTPS URL, or a 'pkg:' reference. - An arr... |\n| `purpose` | no | `oneOf:string / ref:Purpose` | Primary goal of the presentation. Accepts either: - A string shorthand: free-form goal ('Raise a Series B round of $30M'), a purposes catalog id ('decide', 'align'), an HTTPS URL, or a 'pkg:' reference. - An inline Pu... |\n| `language` | no | `oneOf:string / ref:Language` | Language for the presentation content. Accepts either: - A string shorthand: a BCP-47 language tag ('en-US', 'en-GB', 'ja-JP', 'fr'), a languages catalog id ('english', 'japanese'), an HTTPS URL, or a 'pkg:' reference... |\n| `tone` | no | `oneOf:string / ref:Tone` | Desired tone for the presentation. Accepts either: - A string shorthand: a tones catalog id ('formal'), an HTTPS URL, or a 'pkg:' reference. - An inline Tone object for custom tone metadata or catalog-backed overrides... |\n| `takeaway` | no | `oneOf:string / array<string>` | Audience-facing takeaway the presentation should leave behind. Array form supports multiple takeaways. Deck-level intent used by AI to seed and pressure-test slide content. |\n| `duration` | no | `integer` | Target presentation duration, as an integer number of minutes. Used by AI to set pace and depth, and to compare against the resolved narrative's durationRange. |\n| `tags` | no | `array<string>` | Free-form labels used for categorization, search, and filtering. Lowercase kebab-case is recommended for consistency across a deck library. |\n| `design` | no | `ref:Design` | Optional design system covering theme, color scheme, font scheme, dimensions, background, logo, watermark, header, and footer applied to the deck. When omitted, engines use their default design configuration. |\n| `narrative` | no | `oneOf:string / ref:Narrative` | Structured storyline describing the deck's arc and beats. Resolves to the 'id' of a 'narratives' catalog record. Accepts two forms: - String shorthand for the common case: 'narrative = \"classic-story\"'. Accepts a bare... |\n| `slides` | yes | `array<ref:Slide>` | Ordered array of slides that make up the presentation. |\n| `assets` | no | `ref:Assets` | Optional reusable asset registry for images, data files, videos, documents, fonts, and other resources referenced elsewhere in the deck via 'asset:<id>' strings. |\n| `catalogs` | no | `ref:Catalogs` | Optional per-kind catalog overrides. Each kind may declare a non-default 'source' and/or inline 'records' that override or supplement the default catalog at https://www.pptx.gallery/<kind>. References elsewhere in the... |\n| `extensions` | no | `object` | Custom data passthrough for agent workflows; ignored by the engine but preserved across read/write round-trips. |\n\n## Object And Type Reference\n\n### Composition\n\n- Type: `object`\n- Required fields: none\n- Purpose: Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `mode` | no | `enum:auto \\| grid \\| row \\| column` | auto chooses a grid from available space and content; grid uses columns; row and column use one horizontal or vertical track. |\n| `columns` | no | `integer` | Column count for grid. In auto mode this caps the number of columns. |\n| `gap` | no | `number` | Space between cells as a fraction of the container short edge (canvas at slide root). Default 0.03333333333333333. |\n| `padding` | no | `number` | Inset as a fraction of the container short edge. Default 0.08 on a slide, 0 inside a group. |\n| `weights` | no | `array<number>` | Relative track sizes: columns for row/grid/auto, rows for column. Omitted tracks have weight 1; extra weights are ignored. |\n| `minFontSize` | no | `number` | Minimum readable text size in reference pixels at a 720-pixel canvas short edge. Default 16. Overflow is diagnosed when text cannot fit at this size. |\n| `overflow` | no | `enum:warn \\| error` | warn returns diagnostics for content that does not fit; error rejects layout. Content is never silently removed. Default warn. |\n\n\n### Assets\n\n- Type: `object`\n- Required fields: none\n- Purpose: Reusable asset registry for resources used by slides, charts, metadata, and design. Keys are stable asset ids referenced elsewhere as 'asset:<id>'. Each asset can be a source string or an object with src plus optional metadata.\n\n_No named properties._\n\n\n### Asset\n\n- Type: `oneOf:string / object`\n- Required fields: none\n- Purpose: Reusable or inline resource. A string is shorthand for { \"src\": value }. Source strings accept 'asset:<id>' references, HTTPS URLs, data URIs, relative paths resolved against the OPF file location, or local filesystem paths. Use object form when metadata such as alt text, title, mediaType, or format matters.\n\n_No named properties._\n\n\n### Audience\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline audience metadata for the presentation. Use 'id' to reference an audiences catalog record and override selected fields, or use 'name' for a custom inline audience.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional audiences catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable audience name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the audience. |\n| `description` | no | `string` | Longer prose describing the audience and how to address them. |\n| `seniority` | no | `enum:ic \\| manager \\| director \\| vp \\| c-suite \\| mixed` | Typical seniority level of the audience. |\n| `technicalFluency` | no | `enum:low \\| medium \\| high \\| mixed` | Typical technical fluency of the audience. |\n| `decisionPower` | no | `enum:informational \\| advisory \\| decision-maker` | Whether the audience is expected to be informed, advise, or decide. |\n| `attentionBudgetMinutes` | no | `number` | Realistic upper bound on focused attention for a single presentation, in minutes. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this audience. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this audience. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Purpose\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline purpose metadata for the presentation. Use 'id' to reference a purposes catalog record and override selected fields, or use 'name' for a custom inline purpose.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional purposes catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable purpose name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the purpose. |\n| `description` | no | `string` | Longer prose describing when to use this purpose and how it should shape a deck. |\n| `outcome` | no | `string` | Desired audience outcome after the presentation. |\n| `successCriteria` | no | `array<string>` | Observable signals that the deck accomplished this purpose. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this purpose. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this purpose. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Language\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline language metadata for the presentation. Use 'id' to reference a languages catalog record and override selected fields, or use 'bcp47' for a custom language tag without a catalog record.\n- Conditional requirement: `id` or `bcp47`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional languages catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable language name. |\n| `bcp47` | no | `string` | BCP-47 language tag used for locale-aware rendering, proofing, and accessibility metadata. Use 'en-GB' for UK English; 'en-UK' is not a valid BCP-47 region form. |\n| `code` | no | `string` | ISO 639-3 or 639-2 language code carried for engines that prefer ISO codes. |\n| `direction` | no | `enum:ltr \\| rtl` | Base text direction for the language. |\n| `script` | no | `string` | ISO 15924 script code when the writing system should be explicit. |\n| `fontScheme` | no | `string` | Default font-scheme id for this language when targeting PowerPoint output. |\n| `googleFontScheme` | no | `string` | Default font-scheme id for this language when targeting Google Slides output. |\n| `summary` | no | `string` | One-sentence note about coverage or font defaults. |\n| `description` | no | `string` | Longer prose describing the language record and any font-pairing rationale. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Tone\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline tone metadata for the presentation. Use 'id' to reference a tones catalog record and override selected fields, or use 'name' for a custom inline tone.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional tones catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable tone name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the tone. |\n| `description` | no | `string` | Longer prose describing the tone and the kinds of decks it suits. |\n| `voiceCues` | no | `array<string>` | Short directives that shape AI generation toward this tone. |\n| `avoid` | no | `array<string>` | Anti-patterns that AI generation should not produce when this tone is active. |\n| `samplePhrases` | no | `array<string>` | Short example phrases that exemplify this tone. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids this tone pairs well with. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Organization\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: An organization associated with the presentation typically the presenting company, but also hosts, partners, clients, or sponsors. Surfaced on cover slides, footers, and brand bars; the primary organization's logo is the default deck logo unless overridden by design.logo.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable identifier for the organization, used to reference it from Speaker.organizationId. Must be unique within the deck. |\n| `name` | yes | `string` | Display name shown on slides. |\n| `legalName` | no | `string` | Optional legal entity name when it differs from the display name. |\n| `logo` | no | `ref:Asset` | Source for the organization's logo image. Accepts an HTTPS URL, data URI, relative path (resolved against the OPF file location), local path, or 'asset:<id>' reference. Common formats are SVG (preferred for vector log... |\n| `domain` | no | `string` | Bare internet domain for the organization. Used for footers, contact slides, and engine-driven asset lookups (e.g., favicon-based brand defaults). |\n| `email` | no | `string` | General contact email for the organization. Used on contact slides and footer attribution. |\n| `phone` | no | `string` | Main contact phone number for the organization. E.164 format is recommended. |\n| `tagline` | no | `string` | Short tagline rendered alongside the organization name on cover slides. |\n| `role` | no | `enum:primary \\| partner \\| client \\| sponsor \\| host` | Role of the organization relative to the presentation. When omitted, the single organization or first organization in array form is treated as primary. |\n| `socials` | no | `ref:Socials` | Optional social media handles or URLs for the organization. |\n\n\n### Speaker\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A person presenting the deck. Used for cover slides, bio/intro slides, footer attribution, and panel formats with multiple presenters.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable identifier for the speaker, used for cross-references within the deck. Must be unique within the deck. |\n| `name` | yes | `string` | Display name. |\n| `title` | no | `string` | Role or title. Often paired with the speaker's organization on cover slides. |\n| `photo` | no | `ref:Asset` | Source for the speaker's headshot image. Accepts an HTTPS URL, data URI, relative path (resolved against the OPF file location), local path, or 'asset:<id>' reference. Common formats are JPG or PNG; SVG is not appropr... |\n| `email` | no | `string` | Contact email, used on contact slides or footer attribution when appropriate. |\n| `phone` | no | `string` | Contact phone number for the speaker. E.164 format is recommended. |\n| `bio` | no | `string` | Short biographical paragraph for bio or 'about the speaker' slides. |\n| `organizationId` | no | `string` | Reference to an Organization.id in organization. Lets a speaker be attributed to their org in panel or multi-org decks without repeating organization details. |\n| `socials` | no | `ref:Socials` | Optional social media handles or URLs for the speaker. |\n\n\n### Socials\n\n- Type: `object`\n- Required fields: none\n- Purpose: Social media handles or URLs, keyed by platform id from the 'socialPlatforms' catalog. Each value is a string either a full URL or a platform handle (e.g., '@acme'). The catalog record for each platform carries the URL pattern, handle prefix, brand color, and themed icons used by renderers. Keys resolve to the 'id' of a 'socialPlatforms' catalog record. Resolution order: inline catalogs.socialPlatforms.records[] catalogs.socialPlatforms.source default catalog at https://www.pptx.gallery/socia...\n\n_No named properties._\n\n\n### Narrative\n\n- Type: `object`\n- Required fields: none\n- Purpose: Structured storyline used by AI to shape generated content. Mirrors the OPF Narrative Template record at https://openpresentation.org/schema/opf-narrative/v1 (sans '$schema'), so a library record and an inline narrative are interchangeable. Narrative declares the deck's intended story arc; slides may opt into beats via Slide.beat. The narrative does not constrain slide structure validators warn on drift (orphan slides, unused beats) but never error. Slides are the source of truth; narrative i...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Stable slug identifying this narrative. When it matches a record in the resolved 'narratives' catalog, the catalog record's beats and metadata seed this narrative; inline fields override per-key. When it doesn't match... |\n| `name` | no | `string` | Human-readable narrative name. |\n| `summary` | no | `string` | One-sentence description of when and why to use this narrative. |\n| `description` | no | `string` | Longer prose describing the narrative arc and ideal use cases. Used by AI-driven generation to seed deck-level direction. |\n| `audienceFit` | no | `array<string>` | Audiences this narrative works well for. Free-form strings or 'audiences' catalog ids. |\n| `durationRange` | no | `object` | Typical talk-length window this narrative suits. Compared by validators against duration. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the narrative, used by picker UIs and inline rendering. All sub-fields are optional. |\n| `beats` | no | `array<ref:NarrativeBeat>` | Ordered list of beats that make up the narrative arc. When 'id' matches a catalog record, beats here override or extend matching catalog beats by their own 'id'. Beat IDs must be unique within the narrative. |\n\n\n### NarrativeBeat\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A single narrative beat a labeled segment of the story arc with a specific dramatic purpose (e.g. 'hook', 'problem', 'evidence', 'ask'). Slides reference beats via Slide.beat. Beats may also carry slide-blueprint hints (slideType, layoutHint, thoughtCues, instructions) that guide the assigned slide. Mirrors the Beat definition in narrative.schema.json (https://openpresentation.org/schema/opf-narrative/v1) so library entries and inline OPF beats are interchangeable.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable slug used by Slide.beat to reference this beat. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable beat name. |\n| `description` | no | `string` | Curator-written prose that explains what this beat should accomplish. |\n| `instructions` | no | `string` | Short author-facing instruction for the beat typically one phrase. Complements 'description' with a concise directive. |\n| `slideCount` | no | `integer` | Optional explicit slide count for this beat. Defaults to 1 when omitted; values >1 are reserved for beats that intentionally span multiple slides. Prefer decomposing a heavy beat into multiple beats over setting a hig... |\n| `slideType` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Default content kind for the beat's slide. Mirrors ContentPayload.type and helps engines choose a sensible layout when only the beat is specified. |\n| `layoutHint` | no | `string` | Suggested layout id for the beat's opening slide. Resolves the same way as Slide.layout against catalogs.layouts and the default catalog at https://www.pptx.gallery/layouts. |\n| `thoughtCues` | no | `array<string>` | Optional speaker or thinking cues attached to the beat. Surfaced in presenter notes. |\n\n\n### Design\n\n- Type: `object`\n- Required fields: none\n- Purpose: Visual design system applied to the presentation; individual slides may override fields via Slide.design.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `theme` | no | `oneOf:string / ref:Theme` | Theme for the deck. Accepts two forms: - String shorthand: 'design.theme = \"minimal\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'themes' catalog record. - Object form: a Theme with an optional... |\n| `colorScheme` | no | `oneOf:string / ref:ColorScheme` | Color scheme for the presentation. Accepts two forms: - String shorthand: 'design.colorScheme = \"cool-horizon\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'colorSchemes' catalog record. - Objec... |\n| `fontScheme` | no | `oneOf:string / ref:FontScheme` | Font scheme for heading, body, accent, and code text. Accepts two forms: - String shorthand: 'design.fontScheme = \"aptos\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'fontSchemes' catalog recor... |\n| `dimensions` | no | `oneOf:ref:DimensionPreset / ref:Dimensions` | Slide dimensions and aspect ratio. String shorthand such as 'widescreen' is equivalent to { preset: 'widescreen' }. |\n| `background` | no | `oneOf:ref:BackgroundShortcut / ref:Background` | Default slide background applied across the deck unless overridden on a slide. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors; object forms support theme, solid, gradient, im... |\n| `logo` | no | `oneOf:ref:Asset / ref:LogoSet` | Deck logo assets used by layouts, covers, section dividers, headers, and footers. A string is the default logo source; object form provides light/dark, stacked, icon, and wordmark variants. When omitted, the renderer... |\n| `watermark` | no | `oneOf:const:false / ref:Asset / ref:Watermark` | Optional decorative watermark applied across slides. Use false to suppress an inherited watermark in slide-level design; a string is equivalent to { src: value }. |\n| `header` | no | `oneOf:const:false / ref:HeaderFooter` | Repeated header furniture rendered outside the main slide content. Use false to suppress an inherited header. |\n| `footer` | no | `oneOf:const:false / ref:HeaderFooter` | Repeated footer furniture rendered outside the main slide content. Use false to suppress an inherited footer. |\n| `titleAlignment` | no | `enum:left \\| center \\| right` | Default horizontal alignment for title placeholders in resolved layouts. |\n| `contentAlignment` | no | `enum:left \\| center \\| right` | Default horizontal alignment for body/content regions in resolved layouts. |\n| `contentBox` | no | `boolean` | Whether body/content regions are rendered inside a visible card or surface. |\n| `slideImage` | no | `oneOf:ref:Asset / object` | Optional slide-level image treatment used by layouts that support a decorative or editorial image separate from content images. |\n| `contentDirection` | no | `enum:horizontal \\| vertical` | Axis along which parallel body/content regions are arranged. |\n| `chartPrimary` | no | `enum:none \\| top \\| bottom \\| left \\| right` | For chart layouts, where the primary chart sits relative to supporting content. 'none' means chart regions have equal weight. |\n| `imageFill` | no | `enum:crop \\| fit` | How picture placeholders fill their allocated region. |\n| `listBullet` | no | `enum:character \\| image` | Default bullet rendering style for list layouts. |\n\n\n### Theme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Theme bundle used by the design system. In design.theme, 'id' resolves a themes catalog record as the base; any sibling fields override the resolved theme. The string shorthand on design.theme is equivalent to setting only 'id'.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Theme reference. Resolves to the 'id' of a 'themes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'minimal'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on the surro... |\n| `name` | no | `string` | Human-readable theme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the theme - when to reach for it. |\n| `description` | no | `string` | Longer prose describing what the theme looks and feels like and the kinds of decks it suits. |\n| `colorScheme` | no | `oneOf:string / ref:ColorScheme` | Default color scheme for this theme. A string resolves against catalogs.colorSchemes; an object may provide an 'id' base reference plus overrides. |\n| `fontScheme` | no | `oneOf:string / ref:FontScheme` | Default font scheme for this theme. A string resolves against catalogs.fontSchemes; an object may provide an 'id' base reference plus overrides. |\n| `background` | no | `oneOf:ref:BackgroundShortcut / ref:Background` | Default background for this theme. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors. |\n| `dimensions` | no | `oneOf:ref:DimensionPreset / ref:Dimensions` | Default slide size for this theme. A string preset is equivalent to { preset: value }. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### ColorScheme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Color palette used by the design system. The slot fields (accent1-accent6, dark1, dark2, light1, light2, hyperlink, followedHyperlink) mirror color-scheme.schema.json (https://openpresentation.org/schema/opf-color-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields. Two parallel models are supported and may be mixed: - OOXML slots - the 12-slot PowerPoint theme model that round-trips directly to OOXML. Use these for full control over the palette as Power...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Color scheme reference. Resolves to the 'id' of a 'colorSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'cool-horizon'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Slot and r... |\n| `accent1` | no | `string` | Accent 1 color (hex). Mirrors the OOXML accent1 slot. |\n| `accent2` | no | `string` | Accent 2 color (hex). Mirrors the OOXML accent2 slot. |\n| `accent3` | no | `string` | Accent 3 color (hex). Mirrors the OOXML accent3 slot. |\n| `accent4` | no | `string` | Accent 4 color (hex). Mirrors the OOXML accent4 slot. |\n| `accent5` | no | `string` | Accent 5 color (hex). Mirrors the OOXML accent5 slot. |\n| `accent6` | no | `string` | Accent 6 color (hex). Mirrors the OOXML accent6 slot. |\n| `dark1` | no | `string` | Dark 1 color (hex). Typically the deepest neutral; OOXML dark1. |\n| `dark2` | no | `string` | Dark 2 color (hex). Secondary dark; OOXML dark2. |\n| `light1` | no | `string` | Light 1 color (hex). Typically the slide canvas; OOXML lt1. |\n| `light2` | no | `string` | Light 2 color (hex). Secondary light surface; OOXML lt2. |\n| `hyperlink` | no | `string` | Hyperlink color (hex). OOXML hlink. |\n| `followedHyperlink` | no | `string` | Followed-hyperlink color (hex). OOXML folHlink. |\n| `primary` | no | `string` | Abstract role: primary brand color (hex). The engine maps this onto an OOXML accent slot when serializing. |\n| `secondary` | no | `string` | Abstract role: secondary brand color (hex). |\n| `accent` | no | `string` | Abstract role: accent color used for highlights and emphasis (hex). |\n| `background` | no | `string` | Abstract role: default slide background color (hex). The engine maps this to one of light1 / light2 / dark1 / dark2 when serializing. |\n| `surface` | no | `string` | Abstract role: color for elevated surfaces such as cards and panels (hex). |\n| `text` | no | `string` | Abstract role: primary body text color (hex). |\n| `textSecondary` | no | `string` | Abstract role: secondary or muted text color used for captions and supporting copy (hex). |\n| `custom` | no | `object` | Map of custom named colors for advanced or theme-specific use. |\n\n\n### FontScheme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Typography selections used by the design system. The pair fields (major, minor) and refinement fields (type, app, languageFamily) mirror font-scheme.schema.json (https://openpresentation.org/schema/opf-font-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields. Two parallel models are supported and may be mixed: - OOXML pairs (major, minor) - heading and body family names that round-trip directly to PowerPoint majorFont/minorFont entries. - Abstract roles...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Font scheme reference. Resolves to the 'id' of a 'fontSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'aptos'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on... |\n| `major` | no | `string` | Heading (major) font family mirrors the OOXML majorFont entry. Pairs with 'minor'. |\n| `minor` | no | `string` | Body (minor) font family mirrors the OOXML minorFont entry. Pairs with 'major'. |\n| `type` | no | `enum:sans-serif \\| serif \\| monospace` | High-level typographic class of the scheme. |\n| `app` | no | `enum:PowerPoint \\| Google Slides` | Target application this font pairing is intended for. |\n| `languageFamily` | no | `enum:latin \\| ea \\| cs` | OOXML font-language family this scheme is intended for: 'latin' for Latin-script content, 'ea' for East Asian scripts, 'cs' for Complex Scripts. |\n| `heading` | no | `ref:Font` | Abstract role: font used for slide titles and headings. Maps onto the OOXML major slot when serializing. |\n| `body` | no | `ref:Font` | Abstract role: font used for body copy. Maps onto the OOXML minor slot when serializing. |\n| `accent` | no | `ref:Font` | Abstract role: font used for accent text such as quotes or callouts. No direct OOXML slot. |\n| `code` | no | `ref:Font` | Abstract role: monospaced font used for code blocks. No direct OOXML slot. |\n\n\n### Font\n\n- Type: `object`\n- Required fields: `family`\n- Purpose: Specification for a single font role.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `family` | yes | `string` | Font family name. |\n| `weight` | no | `number` | Numeric font weight (e.g., 400 for regular, 700 for bold). |\n| `style` | no | `enum:normal \\| italic` | Font style. |\n| `letterSpacing` | no | `number` | Letter spacing (tracking) in ems. |\n\n\n### DimensionPreset\n\n- Type: `enum:16:9 | 4:3 | 16:10 | letter | a4 | widescreen | standard`\n- Required fields: none\n- Purpose: Named dimension preset; chooses both aspect ratio and physical size. 'widescreen' is an alias for 16:9 in PowerPoint widescreen size; 'standard' is an alias for 4:3 in PowerPoint standard size.\n\n_No named properties._\n\n\n### Dimensions\n\n- Type: `object`\n- Required fields: none\n- Purpose: Slide dimensions; either pick a preset or specify custom inches.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `preset` | no | `ref:DimensionPreset` | |\n| `widthInches` | no | `number` | Custom slide width in inches; overrides the preset width when provided. |\n| `heightInches` | no | `number` | Custom slide height in inches; overrides the preset height when provided. |\n\n\n### ThemeBackgroundSlot\n\n- Type: `enum:light1 | light2 | dark1 | dark2`\n- Required fields: none\n- Purpose: PowerPoint theme-controlled slide background slot from the active color scheme. These are slots, not assumptions about actual colors: light1 is usually white and dark1 is usually black by convention, but the color scheme controls the real values.\n\n_No named properties._\n\n\n### HexColor\n\n- Type: `string`\n- Required fields: none\n- Purpose: Hex color shorthand accepted by selected string fields.\n\n_No named properties._\n\n\n### BackgroundShortcut\n\n- Type: `oneOf:ref:ThemeBackgroundSlot / ref:HexColor`\n- Required fields: none\n- Purpose: String shorthand for a background. Theme slots ('light1', 'light2', 'dark1', 'dark2') are equivalent to { type: 'theme', slot: value }; hex colors are equivalent to { type: 'solid', color: value }.\n\n_No named properties._\n\n\n### Background\n\n- Type: `oneOf:ref:ThemeBackground / ref:SolidBackground / ref:GradientBackground / ref:ImageBackground / ref:PatternBackground`\n- Required fields: none\n- Purpose: Background fill applied to slides. Theme backgrounds preserve PowerPoint's color-scheme background choice; other variants represent fixed background fills.\n\n_No named properties._\n\n\n### ThemeBackground\n\n- Type: `object`\n- Required fields: `type`, `slot`\n- Purpose: Theme-controlled PowerPoint slide background. The slot is resolved through the active color scheme and remains theme-aware.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"theme\"` | Theme-controlled background fill. |\n| `slot` | yes | `ref:ThemeBackgroundSlot` | |\n\n\n### SolidBackground\n\n- Type: `object`\n- Required fields: `type`, `color`\n- Purpose: Fixed solid slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"solid\"` | Fixed solid background fill. |\n| `color` | yes | `string` | Fixed solid fill color, usually a hex string. Use { type: 'theme', slot: ... } for PowerPoint's four theme-controlled background choices. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### GradientBackground\n\n- Type: `object`\n- Required fields: `type`, `gradient`\n- Purpose: Fixed gradient slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"gradient\"` | Fixed gradient background fill. |\n| `gradient` | yes | `object` | Gradient fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### ImageBackground\n\n- Type: `object`\n- Required fields: `type`, `image`\n- Purpose: Fixed image slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"image\"` | Fixed image background fill. |\n| `image` | yes | `object` | Image fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### PatternBackground\n\n- Type: `object`\n- Required fields: `type`, `pattern`\n- Purpose: Fixed pattern slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"pattern\"` | Fixed pattern background fill. |\n| `pattern` | yes | `object` | Pattern fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### LogoSet\n\n- Type: `object`\n- Required fields: none\n- Purpose: Deck logo variants surfaced by layouts, covers, section dividers, headers, and footers. Organization identity lives in organization; this object only controls visual rendering assets. Renderer convention: on dark backgrounds prefer the 'light' variant, on light backgrounds prefer the 'dark' variant, and in square/vertical slots prefer the stacked family when present.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `default` | no | `ref:Asset` | Default full-lockup logo. Used as fallback when no more specific variant is set. |\n| `light` | no | `ref:Asset` | Light-colored full-lockup logo intended for rendering on dark backgrounds. |\n| `dark` | no | `ref:Asset` | Dark-colored full-lockup logo intended for rendering on light backgrounds. |\n| `stacked` | no | `ref:Asset` | Stacked vertical logo lockup, suited to portrait or square brand-mark slots. |\n| `stackedLight` | no | `ref:Asset` | Light-colored stacked logo variant intended for rendering on dark backgrounds. |\n| `stackedDark` | no | `ref:Asset` | Dark-colored stacked logo variant intended for rendering on light backgrounds. |\n| `icon` | no | `ref:Asset` | Default icon, mark, or symbol without wordmark. Useful for tight spaces such as footers, badges, and slide-corner marks. |\n| `iconLight` | no | `ref:Asset` | Light-colored icon variant intended for rendering on dark backgrounds. |\n| `iconDark` | no | `ref:Asset` | Dark-colored icon variant intended for rendering on light backgrounds. |\n| `wordmark` | no | `ref:Asset` | Default wordmark: the organization name set in branded typography, without icon. |\n| `wordmarkLight` | no | `ref:Asset` | Light-colored wordmark variant intended for rendering on dark backgrounds. |\n| `wordmarkDark` | no | `ref:Asset` | Dark-colored wordmark variant intended for rendering on light backgrounds. |\n\n\n### Watermark\n\n- Type: `object`\n- Required fields: `opacity`\n- Purpose: Decorative watermark image and rendering options. Use design.watermark = false to disable an inherited watermark.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `src` | no | `string` | Source for the watermark image. |\n| `opacity` | yes | `number` | Watermark opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### HeaderFooter\n\n- Type: `object`\n- Required fields: none\n- Purpose: Repeated header or footer content split into left, center, and right zones. Header/footer content is slide furniture, separate from the main slide content payloads.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `left` | no | `ref:HeaderFooterItem` | Left-aligned header/footer content. |\n| `center` | no | `ref:HeaderFooterItem` | Centered header/footer content. |\n| `right` | no | `ref:HeaderFooterItem` | Right-aligned header/footer content. |\n\n\n### HeaderFooterItem\n\n- Type: `object`\n- Required fields: none\n- Purpose: One header/footer zone. Fields may be combined when the renderer supports it; otherwise renderers should prefer image, then text-like generated content.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `text` | no | `string` | Literal text rendered in this zone. |\n| `image` | no | `ref:Asset` | Generic image rendered in this zone, such as a logo, partner mark, certification badge, or icon. |\n| `slideNumber` | no | `boolean` | Whether to render the current slide number in this zone. |\n| `date` | no | `oneOf:boolean / string` | Whether to render the presentation date, or a literal date string to render. |\n| `organization` | no | `boolean` | Whether to render the primary organization name from organization. |\n| `section` | no | `boolean` | Whether to render the current slide section label. |\n\n\n### Slide\n\n- Type: `object`\n- Required fields: none\n- Purpose: A single slide. Content can be authored as a full-slide root payload, or inside promoted named region keys such as 'left', 'center+right', and 'top:left'.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional stable identifier for the slide within the document. Use when another system needs to reference a slide across edits, comments, generation state, exports, or narrative tooling. Slide order is defined by the s... |\n| `type` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Optional full-slide content kind. When omitted, engines infer the kind from root payload fields. |\n| `beat` | no | `oneOf:string / array<string>` | Optional reference to one or more narrative beats (each value matches an id from narrative.beats or the resolved template). A single string declares the slide's primary beat; an array declares that one slide covers mu... |\n| `composition` | no | `ref:Composition` | |\n| `layout` | no | `string` | Optional slide layout reference. Resolves to the 'id' of a 'layouts' catalog record. When omitted, engines infer a layout from the slide's root payload or promoted region keys. Accepts a bare id (lowercase kebab-case,... |\n| `title` | no | `string` | Slide-level title content. When the resolved layout exposes a 'title' placeholder, the engine renders this value there. |\n| `subtitle` | no | `string` | Slide-level subtitle or supporting line. When the resolved layout exposes a 'subtitle' placeholder, the engine renders this value there. |\n| `tag` | no | `string` | Small slide-level label or badge. When the resolved layout exposes a 'tag' placeholder, the engine renders this value there. |\n| `text` | no | `oneOf:string / array<ref:TextRun>` | Full-slide text payload. Use a string for plain text or TextRun[] for inline rich text. TextRun items may be plain strings or formatted run objects. |\n| `items` | no | `array<ref:ListItem>` | Full-slide generic list payload. Presence of this field infers type 'list'. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as shorthand for layout-agnostic blocks. |\n| `bullets` | no | `array<ref:BulletItem>` | Full-slide text-style bullet payload. Presence of this field infers type 'text'. |\n| `image` | no | `ref:Asset` | Full-slide image source. Presence of this field infers type 'image'. |\n| `video` | no | `ref:Asset` | Full-slide video source. Presence of this field infers type 'video'. |\n| `chart` | no | `ref:Chart` | Full-slide chart payload. Presence of this field infers type 'chart'. |\n| `table` | no | `ref:Table` | Full-slide table payload. Presence of this field infers type 'table'. |\n| `code` | no | `oneOf:string / ref:Code` | Full-slide code payload. A string is shorthand for { \"source\": value }; object form carries optional syntax language and filename metadata. |\n| `metric` | no | `oneOf:string / number / ref:Metric` | Full-slide metric payload. A string or number is shorthand for { \"value\": value }; object form carries optional label, description, unit, delta, and trend metadata. Numeric values remain numbers; renderers format them... |\n| `quote` | no | `oneOf:string / ref:Quote` | Full-slide quote payload. A string is shorthand for { \"text\": value }; object form carries optional attribution and source metadata. Presence of this field infers type 'quote'. |\n| `timeline` | no | `ref:Timeline` | Full-slide timeline payload. An array is shorthand for { \"events\": value }; object form carries optional name and description metadata. Presence of this field infers type 'timeline'. |\n| `blocks` | no | `array<ref:ContentPayload>` | Layout-agnostic content blocks rendered together as a composed payload when exact placement is unspecified. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as short... |\n| `design` | no | `ref:Design` | Slide-level design applied on top of the deck-wide design. |\n| `left` | no | `ref:ContentPayload` | |\n| `center` | no | `ref:ContentPayload` | |\n| `right` | no | `ref:ContentPayload` | |\n| `left+center` | no | `ref:ContentPayload` | |\n| `center+right` | no | `ref:ContentPayload` | |\n| `left+center+right` | no | `ref:ContentPayload` | |\n| `top` | no | `ref:ContentPayload` | |\n| `middle` | no | `ref:ContentPayload` | |\n| `bottom` | no | `ref:ContentPayload` | |\n| `top+middle` | no | `ref:ContentPayload` | |\n| `middle+bottom` | no | `ref:ContentPayload` | |\n| `top+middle+bottom` | no | `ref:ContentPayload` | |\n| `top:left` | no | `ref:ContentPayload` | |\n| `top:center` | no | `ref:ContentPayload` | |\n| `top:right` | no | `ref:ContentPayload` | |\n| `top:left+center` | no | `ref:ContentPayload` | |\n| `top:center+right` | no | `ref:ContentPayload` | |\n| `top:left+center+right` | no | `ref:ContentPayload` | |\n| `middle:left` | no | `ref:ContentPayload` | |\n| `middle:center` | no | `ref:ContentPayload` | |\n| `middle:right` | no | `ref:ContentPayload` | |\n| `middle:left+center` | no | `ref:ContentPayload` | |\n| `middle:center+right` | no | `ref:ContentPayload` | |\n| `middle:left+center+right` | no | `ref:ContentPayload` | |\n| `bottom:left` | no | `ref:ContentPayload` | |\n| `bottom:center` | no | `ref:ContentPayload` | |\n| `bottom:right` | no | `ref:ContentPayload` | |\n| `bottom:left+center` | no | `ref:ContentPayload` | |\n| `bottom:center+right` | no | `ref:ContentPayload` | |\n| `bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `top+middle:left` | no | `ref:ContentPayload` | |\n| `top+middle:center` | no | `ref:ContentPayload` | |\n| `top+middle:right` | no | `ref:ContentPayload` | |\n| `top+middle:left+center` | no | `ref:ContentPayload` | |\n| `top+middle:center+right` | no | `ref:ContentPayload` | |\n| `top+middle:left+center+right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left` | no | `ref:ContentPayload` | |\n| `middle+bottom:center` | no | `ref:ContentPayload` | |\n| `middle+bottom:right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left+center` | no | `ref:ContentPayload` | |\n| `middle+bottom:center+right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:center` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left+center` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:center+right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `notes` | no | `string` | Speaker notes shown in presenter view. |\n| `section` | no | `string` | PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports. |\n| `hidden` | no | `boolean` | Whether the slide is hidden from the presented sequence. |\n\n\n### ContentPayload\n\n- Type: `allOf:schema + schema + schema + schema + schema + schema + schema + schema + schema + schema + schema + schema`\n- Required fields: none\n- Purpose: A content leaf or recursively composed group. A group contains blocks and optional composition; it cannot mix blocks with leaf payload fields. Groups may nest up to 32 levels.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline \\| group` | Optional content kind. When omitted, engines infer the kind from the fields present. |\n| `text` | no | `oneOf:string / array<ref:TextRun>` | Text payload. Use a string for plain text or TextRun[] for inline rich text. TextRun items may be plain strings or formatted run objects. |\n| `items` | no | `array<ref:ListItem>` | Generic list payload. Each item is either a plain string, a TextRun[] rich text sequence, or a ListItem object. List nesting uses item.level rather than nested content payloads. |\n| `bullets` | no | `array<ref:BulletItem>` | Text-style bullet payload. Presence of this field infers type 'text'. |\n| `image` | no | `ref:Asset` | Source for an image item. |\n| `video` | no | `ref:Asset` | Source for a video item. |\n| `chart` | no | `ref:Chart` | Chart payload. Presence of this field infers type 'chart'. |\n| `table` | no | `ref:Table` | Table payload. Presence of this field infers type 'table'. |\n| `code` | no | `oneOf:string / ref:Code` | Code payload. A string is shorthand for { \"source\": value }; object form carries optional syntax language and filename metadata. |\n| `metric` | no | `oneOf:string / number / ref:Metric` | Metric payload. A string or number is shorthand for { \"value\": value }; object form carries optional label, description, unit, delta, and trend metadata. Numeric values remain numbers; renderers format them for display. |\n| `quote` | no | `oneOf:string / ref:Quote` | Quote payload. A string is shorthand for { \"text\": value }; object form carries optional attribution and source metadata. |\n| `timeline` | no | `ref:Timeline` | Timeline payload ordered by narrative or chronology. |\n| `blocks` | no | `array<ref:ContentPayload>` | Ordered children of a group. Each child is a leaf or another group. |\n| `composition` | no | `ref:Composition` | Arrangement within this group. Only minFontSize and overflow inherit from the parent; strict overflow cannot be weakened. |\n\n\n### Quote\n\n- Type: `object`\n- Required fields: `text`\n- Purpose: Quote content with optional attribution metadata. Use 'text' for the quoted text, 'attribution' for the credited person or organization, and 'source' for a citation or URL. A string value in a quote field is shorthand for { \"text\": value }.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `text` | yes | `string` | Quoted text. |\n| `attribution` | no | `string` | Person or organization credited for the quote. |\n| `source` | no | `string` | Optional quote source, citation, or URL. |\n\n\n### Code\n\n- Type: `object`\n- Required fields: `source`\n- Purpose: Code content with optional rendering metadata. Use 'source' for the code text, 'language' for syntax highlighting, and 'filename' when the rendered block should show a file label. A string value in a code field is shorthand for { \"source\": value }.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `source` | yes | `string` | Source code text to display. |\n| `language` | no | `string` | Language identifier used for syntax highlighting. |\n| `filename` | no | `string` | Optional file label shown with the code block. |\n\n\n### Metric\n\n- Type: `object`\n- Required fields: `value`\n- Purpose: Metric content with optional display metadata. Use 'value' for the primary value, 'label' for the metric name, 'description' for supporting context, 'unit' for a suffix/currency marker, 'delta' for change, and 'trend' for direction. A string or number value in a metric field is shorthand for { \"value\": value }; numeric values remain numbers and are formatted by renderers.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `value` | yes | `oneOf:string / number` | Primary metric value. |\n| `label` | no | `string` | Metric label. |\n| `description` | no | `string` | Optional supporting context for the metric. |\n| `unit` | no | `string` | Metric unit, suffix, or currency marker. |\n| `delta` | no | `oneOf:string / number` | Metric change value. |\n| `trend` | no | `enum:up \\| down \\| flat` | Metric trend direction. |\n\n\n### Timeline\n\n- Type: `oneOf:array<ref:TimelineEvent> / object`\n- Required fields: none\n- Purpose: Timeline content. An array is shorthand for { \"events\": value }; object form carries optional name and description metadata.\n\n_No named properties._\n\n\n### TimelineEvent\n\n- Type: `object`\n- Required fields: `what`\n- Purpose: A single event inside a timeline content payload.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `when` | no | `string` | Event time, date, or sequence label. Use ISO-like values when possible, but human labels are allowed for quarters, eras, and relative milestones. |\n| `what` | yes | `string` | Short event label. |\n| `description` | no | `string` | Optional event detail. |\n\n\n### ListItem\n\n- Type: `oneOf:string / array<ref:TextRun> / object`\n- Required fields: none\n- Purpose: A flat item inside a list. Strings cover the common case, TextRun[] supports inline rich text without an object wrapper, and object form adds description and nesting depth without creating nested slide content payloads.\n\n_No named properties._\n\n\n### BulletItem\n\n- Type: `oneOf:string / array<ref:TextRun> / object`\n- Required fields: none\n- Purpose: A flat bullet item. Strings cover the common case, TextRun[] supports inline rich text without an object wrapper, and object form adds nesting depth without list-item descriptions.\n\n_No named properties._\n\n\n### TextRun\n\n- Type: `oneOf:string / object`\n- Required fields: none\n- Purpose: A contiguous run of text. Strings cover unformatted spans; object form adds character formatting.\n\n_No named properties._\n\n\n### Chart\n\n- Type: `object`\n- Required fields: `type`, `data`\n- Purpose: Chart content. The chart object keeps chart-specific fields together so slides and regions do not expose loose chart fields.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `string` | Chart type id. Resolves to the id of a chartTypes catalog record; renderers map that record through mappings.openxml and any renderer-specific mapping they understand. |\n| `data` | yes | `oneOf:ref:ChartData / ref:ChartDataSource` | Chart data. Inline data uses a tabular columns/rows shape; renderers convert rows to chart series internally. |\n\n\n### Table\n\n- Type: `object`\n- Required fields: `rows`\n- Purpose: Table content. Columns are optional; rows are the only required field.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `columns` | no | `array<string>` | Optional column labels rendered above table rows. |\n| `rows` | yes | `array<array<ref:TableCell>>` | Two-dimensional table row data; each row aligns by index with columns when columns are supplied. |\n\n\n### ChartData\n\n- Type: `object`\n- Required fields: `columns`, `rows`\n- Purpose: Inline tabular data driving a chart. The first column usually supplies category/x-axis labels; subsequent columns are plotted measures unless a chart type or renderer maps them differently.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `columns` | yes | `array<string>` | Ordered column labels for the chart data table. |\n| `rows` | yes | `array<array<ref:ChartDataCell>>` | Tabular chart rows. Each row aligns by index with columns. |\n\n\n### ChartDataSource\n\n- Type: `object`\n- Required fields: `src`\n- Purpose: Chart data sourced from an asset reference, URL, data URI, relative path, or local path such as CSV, TSV, JSON, or XLSX. The source is interpreted as a table; optional columns select or order fields from that table.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `src` | yes | `string` | Data source. Use 'asset:<id>' to reference the top-level assets registry, or provide an HTTPS URL, data URI, relative path, or local filesystem path. |\n| `sheet` | no | `string` | Optional sheet name or table name for spreadsheet-like assets. |\n| `range` | no | `string` | Optional A1-style range or engine-defined range selector for spreadsheet-like assets. |\n| `columns` | no | `array<string>` | Optional ordered columns or fields to read from the source. When omitted, renderers may use the source's own header row or schema. |\n\n\n### ChartDataCell\n\n- Type: `oneOf:string / number / boolean / null`\n- Required fields: none\n- Purpose: A cell in inline chart data.\n\n_No named properties._\n\n\n### TableCell\n\n- Type: `oneOf:string / number / boolean / null`\n- Required fields: none\n- Purpose: A cell in table content.\n\n_No named properties._\n\n\n### Catalogs\n\n- Type: `object`\n- Required fields: none\n- Purpose: Catalog overrides for the in-document references. Every property is optional. The default catalog for a kind lives at https://www.pptx.gallery/<kind> (e.g. https://www.pptx.gallery/narratives, https://www.pptx.gallery/themes). For each kind, declaring a 'source' replaces the default registry and/or 'records' adds inline records that take precedence over anything fetched from a source. Resolution order for any reference (e.g. narrative, design.theme): inline catalogs.<kind>.records[] catalogs....\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `narratives` | no | `ref:CatalogEntry` | Catalog of narrative templates. Records validate against https://openpresentation.org/schema/opf-narrative/v1. Default source: https://www.pptx.gallery/narratives. |\n| `themes` | no | `ref:CatalogEntry` | Catalog of themes. Records validate against https://openpresentation.org/schema/opf-theme/v1. Default source: https://www.pptx.gallery/themes. |\n| `colorSchemes` | no | `ref:CatalogEntry` | Catalog of color schemes. Records validate against https://openpresentation.org/schema/opf-color-scheme/v1. Default source: https://www.pptx.gallery/color-schemes. |\n| `fontSchemes` | no | `ref:CatalogEntry` | Catalog of font schemes. Records validate against https://openpresentation.org/schema/opf-font-scheme/v1. Default source: https://www.pptx.gallery/font-schemes. |\n| `languages` | no | `ref:CatalogEntry` | Catalog of languages. Records validate against https://openpresentation.org/schema/opf-language/v1. Default source: https://www.pptx.gallery/languages. |\n| `layouts` | no | `ref:CatalogEntry` | Catalog of slide layouts. Records validate against https://openpresentation.org/schema/opf-layout/v1. Default source: https://www.pptx.gallery/layouts. |\n| `chartTypes` | no | `ref:CatalogEntry` | Catalog of chart types. Records validate against https://openpresentation.org/schema/opf-chart-type/v1. Default source: https://www.pptx.gallery/chart-types. |\n| `tones` | no | `ref:CatalogEntry` | Catalog of presentation tones. Records validate against https://openpresentation.org/schema/opf-tone/v1. Default source: https://www.pptx.gallery/tones. Referenced from tone. |\n| `purposes` | no | `ref:CatalogEntry` | Catalog of presentation purposes. Records validate against https://openpresentation.org/schema/opf-purpose/v1. Default source: https://www.pptx.gallery/purposes. Referenced from purpose. |\n| `audiences` | no | `ref:CatalogEntry` | Catalog of presentation audiences. Records validate against https://openpresentation.org/schema/opf-audience/v1. Default source: https://www.pptx.gallery/audiences. Referenced from audience. |\n| `socialPlatforms` | no | `ref:CatalogEntry` | Catalog of social-media platforms. Records validate against https://openpresentation.org/schema/opf-social-platform/v1. Default source: https://www.pptx.gallery/social-platforms. Referenced via the property keys of an... |\n\n\n### CatalogEntry\n\n- Type: `object`\n- Required fields: none\n- Purpose: A catalog override for one record kind. 'source' replaces the default registry; 'records' adds inline records that take precedence over anything fetched from a source. Either or both may be provided; both omitted means the kind uses its default catalog.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `source` | no | `oneOf:ref:CatalogSource / array<ref:CatalogSource>` | Single source or an ordered search path of sources. When omitted, the engine falls back to https://www.pptx.gallery/<kind>. |\n| `records` | no | `array<object>` | Inline catalog records embedded in this OPF document. Each record validates against the kind's companion schema (e.g. https://openpresentation.org/schema/opf-narrative/v1 for narratives). Inline records win over anyth... |\n\n\n### CatalogSource\n\n- Type: `string`\n- Required fields: none\n- Purpose: Catalog source location. Accepts: - A bare URL pointing at a catalog directory (e.g. 'https://acme.com/decks/narratives'); record ids resolve to '<base>/<id>.json'. - A URL pointing at an index file (e.g. 'https://acme.com/decks/narratives/index.json'); records are resolved relative to the index file's directory and the index entries describe what's available. - A package reference of the form 'pkg:<package>[/<subpath>]'; resolved through a locally-installed package on the engine's package path.\n\n_No named properties._\n"
|
|
175
|
+
"markdown": "# OPF Presentation Schema Reference\n\nThis reference documents the author-facing shape of a complete `*.opf.json` presentation document. It summarizes the canonical schema in `spec/schemas/opf.schema.json`; the schema remains the source of truth for validators.\n\n## Document Contract\n\n- Schema id: `https://openpresentation.org/schema/opf/v1`\n- Required top-level fields: `slides`\n- Additional top-level fields: not allowed\n\n## Top-Level Fields\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `$schema` | no | `const:\"https://openpresentation.org/schema/opf/v1\"` | Optional OPF schema version. When omitted, validators and engines should assume the latest supported OPF schema. |\n| `name` | no | `string` | Display name of the presentation for GUI/TUI lists, library/search indexing, OS-level metadata, and default export filenames. This is deck identity, not slide content. Use slides[].title and slides[].subtitle for text... |\n| `description` | no | `string` | Free-form prose describing what this presentation is about. Used by agents and humans as a deck-level summary; complements purpose (the goal) and narrative (the structured storyline). Round-trips to OOXML 'docProps/co... |\n| `filename` | no | `string` | Optional base filename for exports (without extension). Engine strips a trailing .pptx, .pdf, .png, or .svg (case-insensitive) and appends the target format's extension. When omitted, the engine slugifies name when pr... |\n| `organization` | no | `oneOf:ref:Organization / array<ref:Organization>` | Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (declared via Organization.role or, if no role is set... |\n| `speaker` | no | `oneOf:ref:Speaker / array<ref:Speaker>` | Person presenting the deck. Array form supports panels and multi-speaker decks. Used for cover slides, bio slides, footers, and panel attribution. |\n| `author` | no | `oneOf:string / array<string>` | Optional credit for the person who authored or contributed to the deck, distinct from speaker. Array form supports multiple contributors. Round-trips to OOXML 'docProps/core.xml' as '<dc:creator>' (semicolon-joined wh... |\n| `audience` | no | `oneOf:string / array<oneOf:string / ref:Audience>` | Intended audiences for the presentation. Accepts either: - A single string shorthand: free-form description ('Series B investors'), an audiences catalog id ('executives'), an HTTPS URL, or a 'pkg:' reference. - An arr... |\n| `purpose` | no | `oneOf:string / ref:Purpose` | Primary goal of the presentation. Accepts either: - A string shorthand: free-form goal ('Raise a Series B round of $30M'), a purposes catalog id ('decide', 'align'), an HTTPS URL, or a 'pkg:' reference. - An inline Pu... |\n| `language` | no | `oneOf:string / ref:Language` | Language for the presentation content. Accepts either: - A string shorthand: a BCP-47 language tag ('en-US', 'en-GB', 'ja-JP', 'fr'), a languages catalog id ('english', 'japanese'), an HTTPS URL, or a 'pkg:' reference... |\n| `tone` | no | `oneOf:string / ref:Tone` | Desired tone for the presentation. Accepts either: - A string shorthand: a tones catalog id ('formal'), an HTTPS URL, or a 'pkg:' reference. - An inline Tone object for custom tone metadata or catalog-backed overrides... |\n| `takeaway` | no | `oneOf:string / array<string>` | Audience-facing takeaway the presentation should leave behind. Array form supports multiple takeaways. Deck-level intent used by AI to seed and pressure-test slide content. |\n| `duration` | no | `integer` | Target presentation duration, as an integer number of minutes. Used by AI to set pace and depth, and to compare against the resolved narrative's durationRange. |\n| `tags` | no | `array<string>` | Free-form labels used for categorization, search, and filtering. Lowercase kebab-case is recommended for consistency across a deck library. |\n| `design` | no | `ref:Design` | Optional design system covering theme, color scheme, font scheme, dimensions, background, logo, watermark, header, and footer applied to the deck. When omitted, engines use their default design configuration. |\n| `narrative` | no | `oneOf:string / ref:Narrative` | Structured storyline describing the deck's arc and beats. Resolves to the 'id' of a 'narratives' catalog record. Accepts two forms: - String shorthand for the common case: 'narrative = \"classic-story\"'. Accepts a bare... |\n| `slides` | yes | `array<ref:Slide>` | Ordered array of slides that make up the presentation. |\n| `assets` | no | `ref:Assets` | Optional reusable asset registry for images, data files, videos, documents, fonts, and other resources referenced elsewhere in the deck via 'asset:<id>' strings. |\n| `catalogs` | no | `ref:Catalogs` | Optional per-kind catalog overrides. Each kind may declare a non-default 'source' and/or inline 'records' that override or supplement the default catalog at https://www.pptx.gallery/<kind>. References elsewhere in the... |\n| `extensions` | no | `object` | Custom data passthrough for agent workflows; ignored by the engine but preserved across read/write round-trips. |\n\n## Object And Type Reference\n\n### Assets\n\n- Type: `object`\n- Required fields: none\n- Purpose: Reusable asset registry for resources used by slides, charts, metadata, and design. Keys are stable asset ids referenced elsewhere as 'asset:<id>'. Each asset can be a source string or an object with src plus optional metadata.\n\n_No named properties._\n\n\n### Asset\n\n- Type: `oneOf:string / object`\n- Required fields: none\n- Purpose: Reusable or inline resource. A string is shorthand for { \"src\": value }. Source strings accept 'asset:<id>' references, HTTPS URLs, data URIs, relative paths resolved against the OPF file location, or local filesystem paths. Use object form when metadata such as alt text, title, mediaType, or format matters.\n\n_No named properties._\n\n\n### Audience\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline audience metadata for the presentation. Use 'id' to reference an audiences catalog record and override selected fields, or use 'name' for a custom inline audience.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional audiences catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable audience name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the audience. |\n| `description` | no | `string` | Longer prose describing the audience and how to address them. |\n| `seniority` | no | `enum:ic \\| manager \\| director \\| vp \\| c-suite \\| mixed` | Typical seniority level of the audience. |\n| `technicalFluency` | no | `enum:low \\| medium \\| high \\| mixed` | Typical technical fluency of the audience. |\n| `decisionPower` | no | `enum:informational \\| advisory \\| decision-maker` | Whether the audience is expected to be informed, advise, or decide. |\n| `attentionBudgetMinutes` | no | `number` | Realistic upper bound on focused attention for a single presentation, in minutes. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this audience. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this audience. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Purpose\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline purpose metadata for the presentation. Use 'id' to reference a purposes catalog record and override selected fields, or use 'name' for a custom inline purpose.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional purposes catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable purpose name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the purpose. |\n| `description` | no | `string` | Longer prose describing when to use this purpose and how it should shape a deck. |\n| `outcome` | no | `string` | Desired audience outcome after the presentation. |\n| `successCriteria` | no | `array<string>` | Observable signals that the deck accomplished this purpose. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids that work well for this purpose. |\n| `recommendedTones` | no | `array<string>` | Soft cross-link: tone-catalog ids that work well for this purpose. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Language\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline language metadata for the presentation. Use 'id' to reference a languages catalog record and override selected fields, or use 'bcp47' for a custom language tag without a catalog record.\n- Conditional requirement: `id` or `bcp47`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional languages catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable language name. |\n| `bcp47` | no | `string` | BCP-47 language tag used for locale-aware rendering, proofing, and accessibility metadata. Use 'en-GB' for UK English; 'en-UK' is not a valid BCP-47 region form. |\n| `code` | no | `string` | ISO 639-3 or 639-2 language code carried for engines that prefer ISO codes. |\n| `direction` | no | `enum:ltr \\| rtl` | Base text direction for the language. |\n| `script` | no | `string` | ISO 15924 script code when the writing system should be explicit. |\n| `fontScheme` | no | `string` | Default font-scheme id for this language when targeting PowerPoint output. |\n| `googleFontScheme` | no | `string` | Default font-scheme id for this language when targeting Google Slides output. |\n| `summary` | no | `string` | One-sentence note about coverage or font defaults. |\n| `description` | no | `string` | Longer prose describing the language record and any font-pairing rationale. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Tone\n\n- Type: `anyOf:schema / schema`\n- Required fields: none\n- Purpose: Inline tone metadata for the presentation. Use 'id' to reference a tones catalog record and override selected fields, or use 'name' for a custom inline tone.\n- Conditional requirement: `id` or `name`\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional tones catalog id to resolve before applying inline overrides. |\n| `name` | no | `string` | Human-readable tone name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the tone. |\n| `description` | no | `string` | Longer prose describing the tone and the kinds of decks it suits. |\n| `voiceCues` | no | `array<string>` | Short directives that shape AI generation toward this tone. |\n| `avoid` | no | `array<string>` | Anti-patterns that AI generation should not produce when this tone is active. |\n| `samplePhrases` | no | `array<string>` | Short example phrases that exemplify this tone. |\n| `recommendedNarratives` | no | `array<string>` | Soft cross-link: narrative-catalog ids this tone pairs well with. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### Organization\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: An organization associated with the presentation typically the presenting company, but also hosts, partners, clients, or sponsors. Surfaced on cover slides, footers, and brand bars; the primary organization's logo is the default deck logo unless overridden by design.logo.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable identifier for the organization, used to reference it from Speaker.organizationId. Must be unique within the deck. |\n| `name` | yes | `string` | Display name shown on slides. |\n| `legalName` | no | `string` | Optional legal entity name when it differs from the display name. |\n| `logo` | no | `ref:Asset` | Source for the organization's logo image. Accepts an HTTPS URL, data URI, relative path (resolved against the OPF file location), local path, or 'asset:<id>' reference. Common formats are SVG (preferred for vector log... |\n| `domain` | no | `string` | Bare internet domain for the organization. Used for footers, contact slides, and engine-driven asset lookups (e.g., favicon-based brand defaults). |\n| `email` | no | `string` | General contact email for the organization. Used on contact slides and footer attribution. |\n| `phone` | no | `string` | Main contact phone number for the organization. E.164 format is recommended. |\n| `tagline` | no | `string` | Short tagline rendered alongside the organization name on cover slides. |\n| `role` | no | `enum:primary \\| partner \\| client \\| sponsor \\| host` | Role of the organization relative to the presentation. When omitted, the single organization or first organization in array form is treated as primary. |\n| `socials` | no | `ref:Socials` | Optional social media handles or URLs for the organization. |\n\n\n### Speaker\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A person presenting the deck. Used for cover slides, bio/intro slides, footer attribution, and panel formats with multiple presenters.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable identifier for the speaker, used for cross-references within the deck. Must be unique within the deck. |\n| `name` | yes | `string` | Display name. |\n| `title` | no | `string` | Role or title. Often paired with the speaker's organization on cover slides. |\n| `photo` | no | `ref:Asset` | Source for the speaker's headshot image. Accepts an HTTPS URL, data URI, relative path (resolved against the OPF file location), local path, or 'asset:<id>' reference. Common formats are JPG or PNG; SVG is not appropr... |\n| `email` | no | `string` | Contact email, used on contact slides or footer attribution when appropriate. |\n| `phone` | no | `string` | Contact phone number for the speaker. E.164 format is recommended. |\n| `bio` | no | `string` | Short biographical paragraph for bio or 'about the speaker' slides. |\n| `organizationId` | no | `string` | Reference to an Organization.id in organization. Lets a speaker be attributed to their org in panel or multi-org decks without repeating organization details. |\n| `socials` | no | `ref:Socials` | Optional social media handles or URLs for the speaker. |\n\n\n### Socials\n\n- Type: `object`\n- Required fields: none\n- Purpose: Social media handles or URLs, keyed by platform id from the 'socialPlatforms' catalog. Each value is a string either a full URL or a platform handle (e.g., '@acme'). The catalog record for each platform carries the URL pattern, handle prefix, brand color, and themed icons used by renderers. Keys resolve to the 'id' of a 'socialPlatforms' catalog record. Resolution order: inline catalogs.socialPlatforms.records[] catalogs.socialPlatforms.source default catalog at https://www.pptx.gallery/socia...\n\n_No named properties._\n\n\n### Narrative\n\n- Type: `object`\n- Required fields: none\n- Purpose: Structured storyline used by AI to shape generated content. Mirrors the OPF Narrative Template record at https://openpresentation.org/schema/opf-narrative/v1 (sans '$schema'), so a library record and an inline narrative are interchangeable. Narrative declares the deck's intended story arc; slides may opt into beats via Slide.beat. The narrative does not constrain slide structure validators warn on drift (orphan slides, unused beats) but never error. Slides are the source of truth; narrative i...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Stable slug identifying this narrative. When it matches a record in the resolved 'narratives' catalog, the catalog record's beats and metadata seed this narrative; inline fields override per-key. When it doesn't match... |\n| `name` | no | `string` | Human-readable narrative name. |\n| `summary` | no | `string` | One-sentence description of when and why to use this narrative. |\n| `description` | no | `string` | Longer prose describing the narrative arc and ideal use cases. Used by AI-driven generation to seed deck-level direction. |\n| `audienceFit` | no | `array<string>` | Audiences this narrative works well for. Free-form strings or 'audiences' catalog ids. |\n| `durationRange` | no | `object` | Typical talk-length window this narrative suits. Compared by validators against duration. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n| `preview` | no | `object` | Visual previews of the narrative, used by picker UIs and inline rendering. All sub-fields are optional. |\n| `beats` | no | `array<ref:NarrativeBeat>` | Ordered list of beats that make up the narrative arc. When 'id' matches a catalog record, beats here override or extend matching catalog beats by their own 'id'. Beat IDs must be unique within the narrative. |\n\n\n### NarrativeBeat\n\n- Type: `object`\n- Required fields: `id`, `name`\n- Purpose: A single narrative beat a labeled segment of the story arc with a specific dramatic purpose (e.g. 'hook', 'problem', 'evidence', 'ask'). Slides reference beats via Slide.beat. Beats may also carry slide-blueprint hints (slideType, layoutHint, thoughtCues, instructions) that guide the assigned slide. Mirrors the Beat definition in narrative.schema.json (https://openpresentation.org/schema/opf-narrative/v1) so library entries and inline OPF beats are interchangeable.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | yes | `string` | Stable slug used by Slide.beat to reference this beat. Lowercase kebab-case. |\n| `name` | yes | `string` | Human-readable beat name. |\n| `description` | no | `string` | Curator-written prose that explains what this beat should accomplish. |\n| `instructions` | no | `string` | Short author-facing instruction for the beat typically one phrase. Complements 'description' with a concise directive. |\n| `slideCount` | no | `integer` | Optional explicit slide count for this beat. Defaults to 1 when omitted; values >1 are reserved for beats that intentionally span multiple slides. Prefer decomposing a heavy beat into multiple beats over setting a hig... |\n| `slideType` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Default content kind for the beat's slide. Mirrors ContentPayload.type and helps engines choose a sensible layout when only the beat is specified. |\n| `layoutHint` | no | `string` | Suggested layout id for the beat's opening slide. Resolves the same way as Slide.layout against catalogs.layouts and the default catalog at https://www.pptx.gallery/layouts. |\n| `thoughtCues` | no | `array<string>` | Optional speaker or thinking cues attached to the beat. Surfaced in presenter notes. |\n\n\n### Design\n\n- Type: `object`\n- Required fields: none\n- Purpose: Visual design system applied to the presentation; individual slides may override fields via Slide.design.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `theme` | no | `oneOf:string / ref:Theme` | Theme for the deck. Accepts two forms: - String shorthand: 'design.theme = \"minimal\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'themes' catalog record. - Object form: a Theme with an optional... |\n| `colorScheme` | no | `oneOf:string / ref:ColorScheme` | Color scheme for the presentation. Accepts two forms: - String shorthand: 'design.colorScheme = \"cool-horizon\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'colorSchemes' catalog record. - Objec... |\n| `fontScheme` | no | `oneOf:string / ref:FontScheme` | Font scheme for heading, body, accent, and code text. Accepts two forms: - String shorthand: 'design.fontScheme = \"aptos\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'fontSchemes' catalog recor... |\n| `dimensions` | no | `oneOf:ref:DimensionPreset / ref:Dimensions` | Slide dimensions and aspect ratio. String shorthand such as 'widescreen' is equivalent to { preset: 'widescreen' }. |\n| `background` | no | `oneOf:ref:BackgroundShortcut / ref:Background` | Default slide background applied across the deck unless overridden on a slide. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors; object forms support theme, solid, gradient, im... |\n| `logo` | no | `oneOf:ref:Asset / ref:LogoSet` | Deck logo assets used by layouts, covers, section dividers, headers, and footers. A string is the default logo source; object form provides light/dark, stacked, icon, and wordmark variants. When omitted, the renderer... |\n| `watermark` | no | `oneOf:const:false / ref:Asset / ref:Watermark` | Optional decorative watermark applied across slides. Use false to suppress an inherited watermark in slide-level design; a string is equivalent to { src: value }. |\n| `header` | no | `oneOf:const:false / ref:HeaderFooter` | Repeated header furniture rendered outside the main slide content. Use false to suppress an inherited header. |\n| `footer` | no | `oneOf:const:false / ref:HeaderFooter` | Repeated footer furniture rendered outside the main slide content. Use false to suppress an inherited footer. |\n| `titleAlignment` | no | `enum:left \\| center \\| right` | Default horizontal alignment for title placeholders in resolved layouts. |\n| `contentAlignment` | no | `enum:left \\| center \\| right` | Default horizontal alignment for body/content regions in resolved layouts. |\n| `contentBox` | no | `boolean` | Whether body/content regions are rendered inside a visible card or surface. |\n| `slideImage` | no | `oneOf:ref:Asset / object` | Optional slide-level image treatment used by layouts that support a decorative or editorial image separate from content images. |\n| `contentDirection` | no | `enum:horizontal \\| vertical` | Axis along which parallel body/content regions are arranged. |\n| `chartPrimary` | no | `enum:none \\| top \\| bottom \\| left \\| right` | For chart layouts, where the primary chart sits relative to supporting content. 'none' means chart regions have equal weight. |\n| `imageFill` | no | `enum:crop \\| fit` | How picture placeholders fill their allocated region. |\n| `listBullet` | no | `enum:character \\| image` | Default bullet rendering style for list layouts. |\n\n\n### Theme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Theme bundle used by the design system. In design.theme, 'id' resolves a themes catalog record as the base; any sibling fields override the resolved theme. The string shorthand on design.theme is equivalent to setting only 'id'.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Theme reference. Resolves to the 'id' of a 'themes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'minimal'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on the surro... |\n| `name` | no | `string` | Human-readable theme name shown in pickers. |\n| `summary` | no | `string` | One-sentence positioning of the theme - when to reach for it. |\n| `description` | no | `string` | Longer prose describing what the theme looks and feels like and the kinds of decks it suits. |\n| `colorScheme` | no | `oneOf:string / ref:ColorScheme` | Default color scheme for this theme. A string resolves against catalogs.colorSchemes; an object may provide an 'id' base reference plus overrides. |\n| `fontScheme` | no | `oneOf:string / ref:FontScheme` | Default font scheme for this theme. A string resolves against catalogs.fontSchemes; an object may provide an 'id' base reference plus overrides. |\n| `background` | no | `oneOf:ref:BackgroundShortcut / ref:Background` | Default background for this theme. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors. |\n| `dimensions` | no | `oneOf:ref:DimensionPreset / ref:Dimensions` | Default slide size for this theme. A string preset is equivalent to { preset: value }. |\n| `tags` | no | `array<string>` | Free-form labels for filtering and search. |\n\n\n### ColorScheme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Color palette used by the design system. The slot fields (accent1-accent6, dark1, dark2, light1, light2, hyperlink, followedHyperlink) mirror color-scheme.schema.json (https://openpresentation.org/schema/opf-color-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields. Two parallel models are supported and may be mixed: - OOXML slots - the 12-slot PowerPoint theme model that round-trips directly to OOXML. Use these for full control over the palette as Power...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Color scheme reference. Resolves to the 'id' of a 'colorSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'cool-horizon'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Slot and r... |\n| `accent1` | no | `string` | Accent 1 color (hex). Mirrors the OOXML accent1 slot. |\n| `accent2` | no | `string` | Accent 2 color (hex). Mirrors the OOXML accent2 slot. |\n| `accent3` | no | `string` | Accent 3 color (hex). Mirrors the OOXML accent3 slot. |\n| `accent4` | no | `string` | Accent 4 color (hex). Mirrors the OOXML accent4 slot. |\n| `accent5` | no | `string` | Accent 5 color (hex). Mirrors the OOXML accent5 slot. |\n| `accent6` | no | `string` | Accent 6 color (hex). Mirrors the OOXML accent6 slot. |\n| `dark1` | no | `string` | Dark 1 color (hex). Typically the deepest neutral; OOXML dark1. |\n| `dark2` | no | `string` | Dark 2 color (hex). Secondary dark; OOXML dark2. |\n| `light1` | no | `string` | Light 1 color (hex). Typically the slide canvas; OOXML lt1. |\n| `light2` | no | `string` | Light 2 color (hex). Secondary light surface; OOXML lt2. |\n| `hyperlink` | no | `string` | Hyperlink color (hex). OOXML hlink. |\n| `followedHyperlink` | no | `string` | Followed-hyperlink color (hex). OOXML folHlink. |\n| `primary` | no | `string` | Abstract role: primary brand color (hex). The engine maps this onto an OOXML accent slot when serializing. |\n| `secondary` | no | `string` | Abstract role: secondary brand color (hex). |\n| `accent` | no | `string` | Abstract role: accent color used for highlights and emphasis (hex). |\n| `background` | no | `string` | Abstract role: default slide background color (hex). The engine maps this to one of light1 / light2 / dark1 / dark2 when serializing. |\n| `surface` | no | `string` | Abstract role: color for elevated surfaces such as cards and panels (hex). |\n| `text` | no | `string` | Abstract role: primary body text color (hex). |\n| `textSecondary` | no | `string` | Abstract role: secondary or muted text color used for captions and supporting copy (hex). |\n| `custom` | no | `object` | Map of custom named colors for advanced or theme-specific use. |\n\n\n### FontScheme\n\n- Type: `object`\n- Required fields: none\n- Purpose: Typography selections used by the design system. The pair fields (major, minor) and refinement fields (type, app, languageFamily) mirror font-scheme.schema.json (https://openpresentation.org/schema/opf-font-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields. Two parallel models are supported and may be mixed: - OOXML pairs (major, minor) - heading and body family names that round-trip directly to PowerPoint majorFont/minorFont entries. - Abstract roles...\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Font scheme reference. Resolves to the 'id' of a 'fontSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'aptos'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on... |\n| `major` | no | `string` | Heading (major) font family mirrors the OOXML majorFont entry. Pairs with 'minor'. |\n| `minor` | no | `string` | Body (minor) font family mirrors the OOXML minorFont entry. Pairs with 'major'. |\n| `type` | no | `enum:sans-serif \\| serif \\| monospace` | High-level typographic class of the scheme. |\n| `app` | no | `enum:PowerPoint \\| Google Slides` | Target application this font pairing is intended for. |\n| `languageFamily` | no | `enum:latin \\| ea \\| cs` | OOXML font-language family this scheme is intended for: 'latin' for Latin-script content, 'ea' for East Asian scripts, 'cs' for Complex Scripts. |\n| `heading` | no | `ref:Font` | Abstract role: font used for slide titles and headings. Maps onto the OOXML major slot when serializing. |\n| `body` | no | `ref:Font` | Abstract role: font used for body copy. Maps onto the OOXML minor slot when serializing. |\n| `accent` | no | `ref:Font` | Abstract role: font used for accent text such as quotes or callouts. No direct OOXML slot. |\n| `code` | no | `ref:Font` | Abstract role: monospaced font used for code blocks. No direct OOXML slot. |\n\n\n### Font\n\n- Type: `object`\n- Required fields: `family`\n- Purpose: Specification for a single font role.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `family` | yes | `string` | Font family name. |\n| `weight` | no | `number` | Numeric font weight (e.g., 400 for regular, 700 for bold). |\n| `style` | no | `enum:normal \\| italic` | Font style. |\n| `letterSpacing` | no | `number` | Letter spacing (tracking) in ems. |\n\n\n### DimensionPreset\n\n- Type: `enum:16:9 | 4:3 | 16:10 | letter | a4 | widescreen | standard`\n- Required fields: none\n- Purpose: Named dimension preset; chooses both aspect ratio and physical size. 'widescreen' is an alias for 16:9 in PowerPoint widescreen size; 'standard' is an alias for 4:3 in PowerPoint standard size.\n\n_No named properties._\n\n\n### Dimensions\n\n- Type: `object`\n- Required fields: none\n- Purpose: Slide dimensions; either pick a preset or specify custom inches.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `preset` | no | `ref:DimensionPreset` | |\n| `widthInches` | no | `number` | Custom slide width in inches; overrides the preset width when provided. |\n| `heightInches` | no | `number` | Custom slide height in inches; overrides the preset height when provided. |\n\n\n### ThemeBackgroundSlot\n\n- Type: `enum:light1 | light2 | dark1 | dark2`\n- Required fields: none\n- Purpose: PowerPoint theme-controlled slide background slot from the active color scheme. These are slots, not assumptions about actual colors: light1 is usually white and dark1 is usually black by convention, but the color scheme controls the real values.\n\n_No named properties._\n\n\n### HexColor\n\n- Type: `string`\n- Required fields: none\n- Purpose: Hex color shorthand accepted by selected string fields.\n\n_No named properties._\n\n\n### BackgroundShortcut\n\n- Type: `oneOf:ref:ThemeBackgroundSlot / ref:HexColor`\n- Required fields: none\n- Purpose: String shorthand for a background. Theme slots ('light1', 'light2', 'dark1', 'dark2') are equivalent to { type: 'theme', slot: value }; hex colors are equivalent to { type: 'solid', color: value }.\n\n_No named properties._\n\n\n### Background\n\n- Type: `oneOf:ref:ThemeBackground / ref:SolidBackground / ref:GradientBackground / ref:ImageBackground / ref:PatternBackground`\n- Required fields: none\n- Purpose: Background fill applied to slides. Theme backgrounds preserve PowerPoint's color-scheme background choice; other variants represent fixed background fills.\n\n_No named properties._\n\n\n### ThemeBackground\n\n- Type: `object`\n- Required fields: `type`, `slot`\n- Purpose: Theme-controlled PowerPoint slide background. The slot is resolved through the active color scheme and remains theme-aware.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"theme\"` | Theme-controlled background fill. |\n| `slot` | yes | `ref:ThemeBackgroundSlot` | |\n\n\n### SolidBackground\n\n- Type: `object`\n- Required fields: `type`, `color`\n- Purpose: Fixed solid slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"solid\"` | Fixed solid background fill. |\n| `color` | yes | `string` | Fixed solid fill color, usually a hex string. Use { type: 'theme', slot: ... } for PowerPoint's four theme-controlled background choices. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### GradientBackground\n\n- Type: `object`\n- Required fields: `type`, `gradient`\n- Purpose: Fixed gradient slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"gradient\"` | Fixed gradient background fill. |\n| `gradient` | yes | `object` | Gradient fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### ImageBackground\n\n- Type: `object`\n- Required fields: `type`, `image`\n- Purpose: Fixed image slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"image\"` | Fixed image background fill. |\n| `image` | yes | `object` | Image fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### PatternBackground\n\n- Type: `object`\n- Required fields: `type`, `pattern`\n- Purpose: Fixed pattern slide background fill.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `const:\"pattern\"` | Fixed pattern background fill. |\n| `pattern` | yes | `object` | Pattern fill definition. |\n| `opacity` | no | `number` | Background opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### LogoSet\n\n- Type: `object`\n- Required fields: none\n- Purpose: Deck logo variants surfaced by layouts, covers, section dividers, headers, and footers. Organization identity lives in organization; this object only controls visual rendering assets. Renderer convention: on dark backgrounds prefer the 'light' variant, on light backgrounds prefer the 'dark' variant, and in square/vertical slots prefer the stacked family when present.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `default` | no | `ref:Asset` | Default full-lockup logo. Used as fallback when no more specific variant is set. |\n| `light` | no | `ref:Asset` | Light-colored full-lockup logo intended for rendering on dark backgrounds. |\n| `dark` | no | `ref:Asset` | Dark-colored full-lockup logo intended for rendering on light backgrounds. |\n| `stacked` | no | `ref:Asset` | Stacked vertical logo lockup, suited to portrait or square brand-mark slots. |\n| `stackedLight` | no | `ref:Asset` | Light-colored stacked logo variant intended for rendering on dark backgrounds. |\n| `stackedDark` | no | `ref:Asset` | Dark-colored stacked logo variant intended for rendering on light backgrounds. |\n| `icon` | no | `ref:Asset` | Default icon, mark, or symbol without wordmark. Useful for tight spaces such as footers, badges, and slide-corner marks. |\n| `iconLight` | no | `ref:Asset` | Light-colored icon variant intended for rendering on dark backgrounds. |\n| `iconDark` | no | `ref:Asset` | Dark-colored icon variant intended for rendering on light backgrounds. |\n| `wordmark` | no | `ref:Asset` | Default wordmark: the organization name set in branded typography, without icon. |\n| `wordmarkLight` | no | `ref:Asset` | Light-colored wordmark variant intended for rendering on dark backgrounds. |\n| `wordmarkDark` | no | `ref:Asset` | Dark-colored wordmark variant intended for rendering on light backgrounds. |\n\n\n### Watermark\n\n- Type: `object`\n- Required fields: `opacity`\n- Purpose: Decorative watermark image and rendering options. Use design.watermark = false to disable an inherited watermark.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `src` | no | `string` | Source for the watermark image. |\n| `opacity` | yes | `number` | Watermark opacity from 0 (fully transparent) to 1 (fully opaque). |\n\n\n### HeaderFooter\n\n- Type: `object`\n- Required fields: none\n- Purpose: Repeated header or footer content split into left, center, and right zones. Header/footer content is slide furniture, separate from the main slide content payloads.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `left` | no | `ref:HeaderFooterItem` | Left-aligned header/footer content. |\n| `center` | no | `ref:HeaderFooterItem` | Centered header/footer content. |\n| `right` | no | `ref:HeaderFooterItem` | Right-aligned header/footer content. |\n\n\n### HeaderFooterItem\n\n- Type: `object`\n- Required fields: none\n- Purpose: One header/footer zone. Fields may be combined when the renderer supports it; otherwise renderers should prefer image, then text-like generated content.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `text` | no | `string` | Literal text rendered in this zone. |\n| `image` | no | `ref:Asset` | Generic image rendered in this zone, such as a logo, partner mark, certification badge, or icon. |\n| `slideNumber` | no | `boolean` | Whether to render the current slide number in this zone. |\n| `date` | no | `oneOf:boolean / string` | Whether to render the presentation date, or a literal date string to render. |\n| `organization` | no | `boolean` | Whether to render the primary organization name from organization. |\n| `section` | no | `boolean` | Whether to render the current slide section label. |\n\n\n### Slide\n\n- Type: `object`\n- Required fields: none\n- Purpose: A single slide. Content can be authored as a full-slide root payload, or inside promoted named region keys such as 'left', 'center+right', and 'top:left'.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `id` | no | `string` | Optional stable identifier for the slide within the document. Use when another system needs to reference a slide across edits, comments, generation state, exports, or narrative tooling. Slide order is defined by the s... |\n| `type` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline` | Optional full-slide content kind. When omitted, engines infer the kind from root payload fields. |\n| `beat` | no | `oneOf:string / array<string>` | Optional reference to one or more narrative beats (each value matches an id from narrative.beats or the resolved template). A single string declares the slide's primary beat; an array declares that one slide covers mu... |\n| `layout` | no | `string` | Optional slide layout reference. Resolves to the 'id' of a 'layouts' catalog record. When omitted, engines infer a layout from the slide's root payload or promoted region keys. Accepts a bare id (lowercase kebab-case,... |\n| `title` | no | `string` | Slide-level title content. When the resolved layout exposes a 'title' placeholder, the engine renders this value there. |\n| `subtitle` | no | `string` | Slide-level subtitle or supporting line. When the resolved layout exposes a 'subtitle' placeholder, the engine renders this value there. |\n| `tag` | no | `string` | Small slide-level label or badge. When the resolved layout exposes a 'tag' placeholder, the engine renders this value there. |\n| `text` | no | `oneOf:string / array<ref:TextRun>` | Full-slide text payload. Use a string for plain text or TextRun[] for inline rich text. TextRun items may be plain strings or formatted run objects. |\n| `items` | no | `array<ref:ListItem>` | Full-slide generic list payload. Presence of this field infers type 'list'. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as shorthand for layout-agnostic blocks. |\n| `bullets` | no | `array<ref:BulletItem>` | Full-slide text-style bullet payload. Presence of this field infers type 'text'. |\n| `image` | no | `ref:Asset` | Full-slide image source. Presence of this field infers type 'image'. |\n| `video` | no | `ref:Asset` | Full-slide video source. Presence of this field infers type 'video'. |\n| `chart` | no | `ref:Chart` | Full-slide chart payload. Presence of this field infers type 'chart'. |\n| `table` | no | `ref:Table` | Full-slide table payload. Presence of this field infers type 'table'. |\n| `code` | no | `oneOf:string / ref:Code` | Full-slide code payload. A string is shorthand for { \"source\": value }; object form carries optional syntax language and filename metadata. |\n| `metric` | no | `oneOf:string / number / ref:Metric` | Full-slide metric payload. A string or number is shorthand for { \"value\": value }; object form carries optional label, description, unit, delta, and trend metadata. Numeric values remain numbers; renderers format them... |\n| `quote` | no | `oneOf:string / ref:Quote` | Full-slide quote payload. A string is shorthand for { \"text\": value }; object form carries optional attribution and source metadata. Presence of this field infers type 'quote'. |\n| `timeline` | no | `ref:Timeline` | Full-slide timeline payload. An array is shorthand for { \"events\": value }; object form carries optional name and description metadata. Presence of this field infers type 'timeline'. |\n| `blocks` | no | `array<ref:ContentPayload>` | Layout-agnostic content blocks rendered together as a composed payload when exact placement is unspecified. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as short... |\n| `design` | no | `ref:Design` | Slide-level design applied on top of the deck-wide design. |\n| `left` | no | `ref:ContentPayload` | |\n| `center` | no | `ref:ContentPayload` | |\n| `right` | no | `ref:ContentPayload` | |\n| `left+center` | no | `ref:ContentPayload` | |\n| `center+right` | no | `ref:ContentPayload` | |\n| `left+center+right` | no | `ref:ContentPayload` | |\n| `top` | no | `ref:ContentPayload` | |\n| `middle` | no | `ref:ContentPayload` | |\n| `bottom` | no | `ref:ContentPayload` | |\n| `top+middle` | no | `ref:ContentPayload` | |\n| `middle+bottom` | no | `ref:ContentPayload` | |\n| `top+middle+bottom` | no | `ref:ContentPayload` | |\n| `top:left` | no | `ref:ContentPayload` | |\n| `top:center` | no | `ref:ContentPayload` | |\n| `top:right` | no | `ref:ContentPayload` | |\n| `top:left+center` | no | `ref:ContentPayload` | |\n| `top:center+right` | no | `ref:ContentPayload` | |\n| `top:left+center+right` | no | `ref:ContentPayload` | |\n| `middle:left` | no | `ref:ContentPayload` | |\n| `middle:center` | no | `ref:ContentPayload` | |\n| `middle:right` | no | `ref:ContentPayload` | |\n| `middle:left+center` | no | `ref:ContentPayload` | |\n| `middle:center+right` | no | `ref:ContentPayload` | |\n| `middle:left+center+right` | no | `ref:ContentPayload` | |\n| `bottom:left` | no | `ref:ContentPayload` | |\n| `bottom:center` | no | `ref:ContentPayload` | |\n| `bottom:right` | no | `ref:ContentPayload` | |\n| `bottom:left+center` | no | `ref:ContentPayload` | |\n| `bottom:center+right` | no | `ref:ContentPayload` | |\n| `bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `top+middle:left` | no | `ref:ContentPayload` | |\n| `top+middle:center` | no | `ref:ContentPayload` | |\n| `top+middle:right` | no | `ref:ContentPayload` | |\n| `top+middle:left+center` | no | `ref:ContentPayload` | |\n| `top+middle:center+right` | no | `ref:ContentPayload` | |\n| `top+middle:left+center+right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left` | no | `ref:ContentPayload` | |\n| `middle+bottom:center` | no | `ref:ContentPayload` | |\n| `middle+bottom:right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left+center` | no | `ref:ContentPayload` | |\n| `middle+bottom:center+right` | no | `ref:ContentPayload` | |\n| `middle+bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:center` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left+center` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:center+right` | no | `ref:ContentPayload` | |\n| `top+middle+bottom:left+center+right` | no | `ref:ContentPayload` | |\n| `notes` | no | `string` | Speaker notes shown in presenter view. |\n| `section` | no | `string` | PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports. |\n| `hidden` | no | `boolean` | Whether the slide is hidden from the presented sequence. |\n| `composition` | no | `ref:Composition` | |\n\n\n### ContentPayload\n\n- Type: `allOf:schema + schema + schema + schema + schema + schema + schema + schema + schema + schema + schema + schema`\n- Required fields: none\n- Purpose: A content leaf or recursively composed group. A group contains blocks and optional composition; it cannot mix blocks with leaf payload fields. Groups may nest up to 32 levels.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | no | `enum:text \\| list \\| image \\| chart \\| table \\| video \\| code \\| metric \\| quote \\| timeline \\| group` | Optional content kind. When omitted, engines infer the kind from the fields present. |\n| `text` | no | `oneOf:string / array<ref:TextRun>` | Text payload. Use a string for plain text or TextRun[] for inline rich text. TextRun items may be plain strings or formatted run objects. |\n| `items` | no | `array<ref:ListItem>` | Generic list payload. Each item is either a plain string, a TextRun[] rich text sequence, or a ListItem object. List nesting uses item.level rather than nested content payloads. |\n| `bullets` | no | `array<ref:BulletItem>` | Text-style bullet payload. Presence of this field infers type 'text'. |\n| `image` | no | `ref:Asset` | Source for an image item. |\n| `video` | no | `ref:Asset` | Source for a video item. |\n| `chart` | no | `ref:Chart` | Chart payload. Presence of this field infers type 'chart'. |\n| `table` | no | `ref:Table` | Table payload. Presence of this field infers type 'table'. |\n| `code` | no | `oneOf:string / ref:Code` | Code payload. A string is shorthand for { \"source\": value }; object form carries optional syntax language and filename metadata. |\n| `metric` | no | `oneOf:string / number / ref:Metric` | Metric payload. A string or number is shorthand for { \"value\": value }; object form carries optional label, description, unit, delta, and trend metadata. Numeric values remain numbers; renderers format them for display. |\n| `quote` | no | `oneOf:string / ref:Quote` | Quote payload. A string is shorthand for { \"text\": value }; object form carries optional attribution and source metadata. |\n| `timeline` | no | `ref:Timeline` | Timeline payload ordered by narrative or chronology. |\n| `blocks` | no | `array<ref:ContentPayload>` | Ordered children of a group. Each child is a leaf or another group. |\n| `composition` | no | `ref:Composition` | Arrangement within this group. Only minFontSize and overflow inherit from the parent; strict overflow cannot be weakened. |\n\n\n### Quote\n\n- Type: `object`\n- Required fields: `text`\n- Purpose: Quote content with optional attribution metadata. Use 'text' for the quoted text, 'attribution' for the credited person or organization, and 'source' for a citation or URL. A string value in a quote field is shorthand for { \"text\": value }.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `text` | yes | `string` | Quoted text. |\n| `attribution` | no | `string` | Person or organization credited for the quote. |\n| `source` | no | `string` | Optional quote source, citation, or URL. |\n\n\n### Code\n\n- Type: `object`\n- Required fields: `source`\n- Purpose: Code content with optional rendering metadata. Use 'source' for the code text, 'language' for syntax highlighting, and 'filename' when the rendered block should show a file label. A string value in a code field is shorthand for { \"source\": value }.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `source` | yes | `string` | Source code text to display. |\n| `language` | no | `string` | Language identifier used for syntax highlighting. |\n| `filename` | no | `string` | Optional file label shown with the code block. |\n\n\n### Metric\n\n- Type: `object`\n- Required fields: `value`\n- Purpose: Metric content with optional display metadata. Use 'value' for the primary value, 'label' for the metric name, 'description' for supporting context, 'unit' for a suffix/currency marker, 'delta' for change, and 'trend' for direction. A string or number value in a metric field is shorthand for { \"value\": value }; numeric values remain numbers and are formatted by renderers.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `value` | yes | `oneOf:string / number` | Primary metric value. |\n| `label` | no | `string` | Metric label. |\n| `description` | no | `string` | Optional supporting context for the metric. |\n| `unit` | no | `string` | Metric unit, suffix, or currency marker. |\n| `delta` | no | `oneOf:string / number` | Metric change value. |\n| `trend` | no | `enum:up \\| down \\| flat` | Metric trend direction. |\n\n\n### Timeline\n\n- Type: `oneOf:array<ref:TimelineEvent> / object`\n- Required fields: none\n- Purpose: Timeline content. An array is shorthand for { \"events\": value }; object form carries optional name and description metadata.\n\n_No named properties._\n\n\n### TimelineEvent\n\n- Type: `object`\n- Required fields: `what`\n- Purpose: A single event inside a timeline content payload.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `when` | no | `string` | Event time, date, or sequence label. Use ISO-like values when possible, but human labels are allowed for quarters, eras, and relative milestones. |\n| `what` | yes | `string` | Short event label. |\n| `description` | no | `string` | Optional event detail. |\n\n\n### ListItem\n\n- Type: `oneOf:string / array<ref:TextRun> / object`\n- Required fields: none\n- Purpose: A flat item inside a list. Strings cover the common case, TextRun[] supports inline rich text without an object wrapper, and object form adds description and nesting depth without creating nested slide content payloads.\n\n_No named properties._\n\n\n### BulletItem\n\n- Type: `oneOf:string / array<ref:TextRun> / object`\n- Required fields: none\n- Purpose: A flat bullet item. Strings cover the common case, TextRun[] supports inline rich text without an object wrapper, and object form adds nesting depth without list-item descriptions.\n\n_No named properties._\n\n\n### TextRun\n\n- Type: `oneOf:string / object`\n- Required fields: none\n- Purpose: A contiguous run of text. Strings cover unformatted spans; object form adds character formatting.\n\n_No named properties._\n\n\n### Chart\n\n- Type: `object`\n- Required fields: `type`, `data`\n- Purpose: Chart content. The chart object keeps chart-specific fields together so slides and regions do not expose loose chart fields.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `type` | yes | `string` | Chart type id. Resolves to the id of a chartTypes catalog record; renderers map that record through mappings.openxml and any renderer-specific mapping they understand. |\n| `data` | yes | `oneOf:ref:ChartData / ref:ChartDataSource` | Chart data. Inline data uses a tabular columns/rows shape; renderers convert rows to chart series internally. |\n\n\n### Table\n\n- Type: `object`\n- Required fields: `rows`\n- Purpose: Table content. Columns are optional; rows are the only required field.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `columns` | no | `array<oneOf:string / array<ref:TextRun> / ref:StyledTableCell / null>` | Optional column labels. Labels may be strings, rich runs or styled cell objects. Null is an empty label or a placeholder covered by a preceding column span. |\n| `rows` | yes | `array<array<ref:TableCell>>` | Two-dimensional table row data; each row aligns by index with columns when columns are supplied. |\n\n\n### ChartData\n\n- Type: `object`\n- Required fields: `columns`, `rows`\n- Purpose: Inline tabular data driving a chart. The first column usually supplies category/x-axis labels; subsequent columns are plotted measures unless a chart type or renderer maps them differently.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `columns` | yes | `array<string>` | Ordered column labels for the chart data table. |\n| `rows` | yes | `array<array<ref:ChartDataCell>>` | Tabular chart rows. Each row aligns by index with columns. |\n\n\n### ChartDataSource\n\n- Type: `object`\n- Required fields: `src`\n- Purpose: Chart data sourced from an asset reference, URL, data URI, relative path, or local path such as CSV, TSV, JSON, or XLSX. The source is interpreted as a table; optional columns select or order fields from that table.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `src` | yes | `string` | Data source. Use 'asset:<id>' to reference the top-level assets registry, or provide an HTTPS URL, data URI, relative path, or local filesystem path. |\n| `sheet` | no | `string` | Optional sheet name or table name for spreadsheet-like assets. |\n| `range` | no | `string` | Optional A1-style range or engine-defined range selector for spreadsheet-like assets. |\n| `columns` | no | `array<string>` | Optional ordered columns or fields to read from the source. When omitted, renderers may use the source's own header row or schema. |\n\n\n### ChartDataCell\n\n- Type: `oneOf:string / number / boolean / null`\n- Required fields: none\n- Purpose: A cell in inline chart data.\n\n_No named properties._\n\n\n### TableCell\n\n- Type: `oneOf:ref:TableCellValue / ref:StyledTableCell`\n- Required fields: none\n- Purpose: A scalar, rich-run array, or styled/spanning cell object. Existing scalar and rich forms remain valid.\n\n_No named properties._\n\n\n### TableCellValue\n\n- Type: `oneOf:string / number / boolean / null / array<ref:TextRun>`\n- Required fields: none\n- Purpose: A scalar table value or canonical rich text runs, without cell decoration or geometry.\n\n_No named properties._\n\n\n### StyledTableCell\n\n- Type: `object`\n- Required fields: `value`\n- Purpose: A cell with explicit visual style or merged geometry. Its position remains its array column index; use null placeholders for every covered grid position.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `value` | yes | `ref:TableCellValue` | Editable cell content; styling and spans do not change its scalar type or rich runs. |\n| `style` | no | `ref:TableCellStyle` | |\n| `colSpan` | no | `integer` | Number of grid columns covered, starting at this cell. Covered positions must contain null. Default 1. |\n| `rowSpan` | no | `integer` | Number of grid rows covered, starting at this cell. Covered positions must contain null. Header cells cannot span into body rows. Default 1. |\n\n\n### TableCellStyle\n\n- Type: `object`\n- Required fields: none\n- Purpose: Cell appearance. Sizes use reference pixels at a 720-pixel canvas short edge and scale with the slide.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `fill` | no | `string` | Explicit RGB or RGBA color. Eight-digit colors include alpha; #00000000 is transparent. |\n| `color` | no | `string` | Default text color, overridden by individual rich run colors. |\n| `align` | no | `enum:left \\| center \\| right` | Horizontal text alignment inside the cell. |\n| `verticalAlign` | no | `enum:top \\| middle \\| bottom` | Vertical alignment inside the padded cell box. |\n| `padding` | no | `ref:TableCellPadding` | |\n| `borders` | no | `object` | Independent cell edges. Omitted edges retain the table theme border; width 0 removes an edge. |\n\n\n### TableCellPadding\n\n- Type: `object`\n- Required fields: none\n- Purpose: Text insets in reference pixels. Defaults: top 8, right 10, bottom 4, left 10.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `top` | no | `number` | |\n| `right` | no | `number` | |\n| `bottom` | no | `number` | |\n| `left` | no | `number` | |\n\n\n### TableCellBorder\n\n- Type: `object`\n- Required fields: `color`, `width`\n- Purpose: One explicit cell border.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `color` | yes | `string` | Explicit RGB or RGBA color. Eight-digit colors include alpha; #00000000 is transparent. |\n| `width` | yes | `number` | Border width in reference pixels; 0 removes this edge. |\n| `dash` | no | `enum:solid \\| dash \\| dot` | Default solid. |\n\n\n### Catalogs\n\n- Type: `object`\n- Required fields: none\n- Purpose: Catalog overrides for the in-document references. Every property is optional. The default catalog for a kind lives at https://www.pptx.gallery/<kind> (e.g. https://www.pptx.gallery/narratives, https://www.pptx.gallery/themes). For each kind, declaring a 'source' replaces the default registry and/or 'records' adds inline records that take precedence over anything fetched from a source. Resolution order for any reference (e.g. narrative, design.theme): inline catalogs.<kind>.records[] catalogs....\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `narratives` | no | `ref:CatalogEntry` | Catalog of narrative templates. Records validate against https://openpresentation.org/schema/opf-narrative/v1. Default source: https://www.pptx.gallery/narratives. |\n| `themes` | no | `ref:CatalogEntry` | Catalog of themes. Records validate against https://openpresentation.org/schema/opf-theme/v1. Default source: https://www.pptx.gallery/themes. |\n| `colorSchemes` | no | `ref:CatalogEntry` | Catalog of color schemes. Records validate against https://openpresentation.org/schema/opf-color-scheme/v1. Default source: https://www.pptx.gallery/color-schemes. |\n| `fontSchemes` | no | `ref:CatalogEntry` | Catalog of font schemes. Records validate against https://openpresentation.org/schema/opf-font-scheme/v1. Default source: https://www.pptx.gallery/font-schemes. |\n| `languages` | no | `ref:CatalogEntry` | Catalog of languages. Records validate against https://openpresentation.org/schema/opf-language/v1. Default source: https://www.pptx.gallery/languages. |\n| `layouts` | no | `ref:CatalogEntry` | Catalog of slide layouts. Records validate against https://openpresentation.org/schema/opf-layout/v1. Default source: https://www.pptx.gallery/layouts. |\n| `chartTypes` | no | `ref:CatalogEntry` | Catalog of chart types. Records validate against https://openpresentation.org/schema/opf-chart-type/v1. Default source: https://www.pptx.gallery/chart-types. |\n| `tones` | no | `ref:CatalogEntry` | Catalog of presentation tones. Records validate against https://openpresentation.org/schema/opf-tone/v1. Default source: https://www.pptx.gallery/tones. Referenced from tone. |\n| `purposes` | no | `ref:CatalogEntry` | Catalog of presentation purposes. Records validate against https://openpresentation.org/schema/opf-purpose/v1. Default source: https://www.pptx.gallery/purposes. Referenced from purpose. |\n| `audiences` | no | `ref:CatalogEntry` | Catalog of presentation audiences. Records validate against https://openpresentation.org/schema/opf-audience/v1. Default source: https://www.pptx.gallery/audiences. Referenced from audience. |\n| `socialPlatforms` | no | `ref:CatalogEntry` | Catalog of social-media platforms. Records validate against https://openpresentation.org/schema/opf-social-platform/v1. Default source: https://www.pptx.gallery/social-platforms. Referenced via the property keys of an... |\n\n\n### CatalogEntry\n\n- Type: `object`\n- Required fields: none\n- Purpose: A catalog override for one record kind. 'source' replaces the default registry; 'records' adds inline records that take precedence over anything fetched from a source. Either or both may be provided; both omitted means the kind uses its default catalog.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `source` | no | `oneOf:ref:CatalogSource / array<ref:CatalogSource>` | Single source or an ordered search path of sources. When omitted, the engine falls back to https://www.pptx.gallery/<kind>. |\n| `records` | no | `array<object>` | Inline catalog records embedded in this OPF document. Each record validates against the kind's companion schema (e.g. https://openpresentation.org/schema/opf-narrative/v1 for narratives). Inline records win over anyth... |\n\n\n### CatalogSource\n\n- Type: `string`\n- Required fields: none\n- Purpose: Catalog source location. Accepts: - A bare URL pointing at a catalog directory (e.g. 'https://acme.com/decks/narratives'); record ids resolve to '<base>/<id>.json'. - A URL pointing at an index file (e.g. 'https://acme.com/decks/narratives/index.json'); records are resolved relative to the index file's directory and the index entries describe what's available. - A package reference of the form 'pkg:<package>[/<subpath>]'; resolved through a locally-installed package on the engine's package path.\n\n_No named properties._\n\n\n### Composition\n\n- Type: `object`\n- Required fields: none\n- Purpose: Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.\n\n| Field | Required | Type | Notes |\n| --- | --- | --- | --- |\n| `mode` | no | `enum:auto \\| grid \\| row \\| column` | auto chooses a grid from available space and content; grid uses columns; row and column use one horizontal or vertical track. |\n| `columns` | no | `integer` | Column count for grid. In auto mode this caps the number of columns. |\n| `gap` | no | `number` | Space between cells as a fraction of the container short edge (canvas at slide root). Default 0.03333333333333333. |\n| `padding` | no | `number` | Inset as a fraction of the container short edge. Default 0.08 on a slide, 0 inside a group. |\n| `weights` | no | `array<number>` | Relative track sizes: columns for row/grid/auto, rows for column. Omitted tracks have weight 1; extra weights are ignored. |\n| `minFontSize` | no | `number` | Minimum readable text size in reference pixels at a 720-pixel canvas short edge. Default 16. Overflow is diagnosed when text cannot fit at this size. |\n| `overflow` | no | `enum:warn \\| error` | warn returns diagnostics for content that does not fit; error rejects layout. Content is never silently removed. Default warn. |\n"
|
|
140
176
|
},
|
|
141
177
|
{
|
|
142
178
|
"slug": "security-2026-09-09",
|
|
143
179
|
"file": "docs/security-2026-09-09.md",
|
|
144
180
|
"title": "Security and dependency review \u2014 September 9, 2026 UTC",
|
|
145
181
|
"markdown": "# Security and dependency review \u2014 September 9, 2026 UTC\n\n## Follow-up action and parser maintenance\n\nA fresh GitHub audit across all seven repositories finds zero open Dependabot security alerts, without dismissals. Routine grouping/scheduling and separate security updates remain enabled.\n\npptx.dev PR #23 merged as `5c862d23c39f330e4fccdaa5a45bd053ae86a1dc`, tree-identical to reviewed `52a51d49f2d01ebc048d2b365d412f3bce9a0cca`. It pairs immutable upload-artifact 7.0.1/download-artifact 8.0.1 refs with normal multi-file ZIP behavior and fatal digest mismatch checks. CI `34315591982` builds real Python wheel/source distributions, uploads/downloads them, verifies complete names and SHA-256 hashes and runs Twine checks on Linux/Windows. Both transport jobs, full application CI `34315591938` and Bugbot pass. The absent `sdk/mcp` publisher scaffold is retired; hosted HTTP MCP remains. Dependabot PRs #16/#17 are closed as superseded. No publishing workflow was dispatched or package released.\n\nPPTX PR #12 merged as `9c0abf1d6f296a62322fac7c4ef5c91d025a3705`, tree-identical to reviewed `5016051b45bb35a5d02591cc720a82dda95eae6e`. It synchronizes only the lockfile to fast-xml-parser 5.11.1 and its declared helpers, including entities 3.0.0. The existing semver range already permits this graph, which the fresh published 0.5.1 consumer used for registry/native checks also resolves. All four Linux/Windows Node 20/24 CI jobs `34307685202` pass clean install/audit, full converter, packed-consumer and real Chromium tests. Published package versions and immutable release verification refs remain unchanged; do not republish 0.5.1.\n\npptx.dev browser PR #22's initial review found missing active-draft commits in source export/copy/save and send actions. The follow-up uses the current editor snapshot and commits before canvas unmount; real browser tests activate exports, copy and a local metadata request without relying on pointer blur. The claimed SVG script/data-link injection is not reproduced: the pinned renderer restricts link/image protocols, escapes text/attributes and validates embedded font CSS. A real-browser regression verifies hostile shared Inspector, Author import-preview and mounted-canvas documents stay inert, with safe HTTPS links retained. All four local and exact-preview tests pass on candidate `c18b1fdd5d5e5e2e10b259957ba678def598a2ac`. Renewed Linux/Windows CI `34316394032` and Bugbot pass; all review threads are resolved. Merge `fa94477f8fceb8bb1a0d62fa23d7e0d05423e94a` is deployed as `dpl_4bQ6pSkG7kiCw8FNAPuEx9RtumTS`. All four public tests pass, all 33 deployed font files/licenses verify against the registry package, and the actual production download passes native PowerPoint edit/save/reopen/reimport. See the current handoff and portable `docs/evidence/pptx-dev-browser/` reports.\n\nMonaco, Commander, js-yaml and core schema-generator/TypeScript majors remain explicit separate compatibility reviews, as described below. Unrelated site PR #4 and pptx.dev PR #6 are preserved. Vercel redundant-comment settings still require the previously requested browser passkey sign-in; no protection or notification setting has been changed.\n\n## Current production and compatibility checkpoint\n\nCore PR #33 merged as `188c32333a903fed9058d781caaaae4cd10b3d28` after package CI `34309217317`, coordinated Node 20/24 CI `34309217315` and Bugbot. Published PPTX 0.5.1 is now pinned in the release plan and immutable verification refs. The local preview-packer correction also passed renewed coordinated checks.\n\nAll three production deployments now adopt 0.5.1 and have real Edge verification. Website merge `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f` / `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm` passes four public tests. Gallery PR #21 merge `2ea8ccb75b9a6d9b64a93e6ec36d78100c044f8a` / `dpl_5cooy8gD6MrZXu5vDDXNNxkBpFjN` passes deployed asset hashes and both browser tests after CI `34309168015` and Bugbot. pptx.dev PR #21 merge `f1f9e700ae2648467b36baf22b3393a216b78780` / `dpl_wkf6fiWCeyW1E562zHFU9RXwM92X` passes both public inspector/toolkit browser tests after Linux/Windows CI `34309892749` and Bugbot. Its clean frozen install, audit, 591 tests, typecheck and full build pass. The application retains the narrowly scoped image-size removal override for its separate legacy PptxGenJS generator. OPF 0.5.1 itself no longer needs that override.\n\nPending pptx.dev upgrades were inspected individually and left unmerged with evidence: [Monaco #18](https://github.com/Data-Advantage/pptx-dev/pull/18#issuecomment-5595709296) fails worker resolution following changed public exports; [Commander #19](https://github.com/Data-Advantage/pptx-dev/pull/19#issuecomment-5595673135) requires Node >=22.12 while the CLI supports Node 20; [js-yaml #20](https://github.com/Data-Advantage/pptx-dev/pull/20#issuecomment-5595709414) fails codec/API tests after the version 5 export change. These require migrations and relevant consumer/browser checks. Current patched dependencies audit clean. Remaining action upgrades and the obsolete MCP publishing workflow need separate maintenance. Vercel comment configuration still awaits browser passkey sign-in; no security alert was dismissed or hidden.\n\nThe deployment checks establish package adoption and the documented OPF flows. They do not establish complete browser PPTX transfer controls or broad native PowerPoint raster equivalence. The main pptx.dev renderer/exporter integration remains open. Historical checkpoints below preserve the earlier evidence.\n\nLatest verified production checkpoint: pptx.dev PR #15 merged as `06ebef116608110fa88ac98cbcd6fe8ea6ad76f1`, from reviewed `aad6b5ce29dc4ed5b03a7982121ff4a7ea4543bc`. Linux/Windows CI `34304827786` and Bugbot pass; the standalone/adapter finding is fixed and resolved. Preview E2E passes. Production `dpl_638zt5oC7grWNTYEXL3XM4cFMbGE` is READY on the merge and aliases www.pptx.dev, pptx.dev, api.pptx.dev and mcp.pptx.dev. The same real Edge inspector author/preview/edit/undo/redo/OPF-download/shared-reimport test passes against https://www.pptx.dev. GitHub open Dependabot alerts now total zero without dismissals. SDK/CLI consolidation is complete for this baseline; main custom renderer/exporter adoption remains open.\n\nCore security PR #30 merged as `6967b037c934c665e312086e232545cb71753bcf` after successful package `34304887858`, portability `34304887838`, coordinated `34304887865` and Bugbot checks. Renderer PR #7 merged as `ad59248ad8dbf11e519c1ba75e95d6d3fa4a39ed` (CI `34305311878`); editor PR #6 merged as `aeb2871ba381bf97656e58418b5271ec764ed0d5` (CI `34305316921`), both with renewed Bugbot review and clean audit. Their new weekly groups and unfiltered audit gates do not change published versions. Historical PPTX 0.5.0 has two high audit findings via image-size; the compatible 0.5.1 removal is verified below. The suggested downgrade to PptxGenJS 1.1.5 was not applied.\n\nThe September 8 audits are historical. Newly indexed advisories require a refreshed audit of each actual lockfile; no advisory has been ignored or dismissed.\n\n## PPTX 0.5.1 and refreshed alert state\n\nWebsite PR #16 merged as `680be53dd69d99701f8b3f21e7e1c0f9b5f9390f`; CI `34308522871`, Bugbot and all four production Edge tests pass. Deployment `dpl_9aR19f8JG7GHDukBnTLQv4b2hhTm` serves the new changelog and verified showcase manifest. Gallery PR #21 and pptx.dev PR #21 hold their follow-up 0.5.1 adoption candidates. The latter passes a clean frozen workspace installation, audit, all 591 tests and typecheck while retaining its legacy-generator removal override.\n\nThe core coordinated CI found that the local preview staging builder excluded vendor files. Its fix copies all declared literal payloads, checks contained staging paths and invokes npm portably on Windows. Fresh preview tarball consumers pass on Node 20/24; these local previews remain distinct from published registry evidence. The registry package itself includes the required code and license and was unaffected by this staging omission.\n\nPPTX PR #11 merged as `f7f30082da3568a4f911d42493ffc75c77dd4e14` after Linux/Windows Node 20/24 CI `34307186304` and Bugbot pass. It removes unused image-size from ordinary npm consumers by shipping the exact licensed and hash-verified PptxGenJS 4.0.1 ESM runtime, with JSZip declared directly. Fresh packed installations audit clean. npm does not audit vendored source as an installed upstream package; provenance and upstream advisory review are explicit maintenance requirements. All 126 corpus PPTX files match the actual 0.5.0 registry release with controlled images/fonts; real Edge checks and three-slide native PowerPoint edit/save/reopen/raster checks pass. [Portable evidence](https://github.com/OpenPresentation/opf-pptx/blob/f7f30082da3568a4f911d42493ffc75c77dd4e14/docs/security-0.5.1.md).\n\nTrusted publication `34307645895` succeeded for tag `opf-pptx-v0.5.1`, published at `2026-09-09T03:37:39.613Z`. Fresh Node 20/24 coordinated installations and full pinned fidelity suites pass. The fresh consumer has zero npm vulnerabilities; `npm audit signatures` verifies 64 registry signatures and 15 attestations. Actual registry native PowerPoint edit/save/reopen and raster checks pass. Do not republish. A fresh GitHub audit of core, renderer, PPTX, editor, website, gallery and pptx.dev finds zero open Dependabot alerts without dismissals. Existing registry version 0.5.0 retains its historical dependency graph.\n\nCore PR #31 updates supported Node 20 declarations to 20.19.43 and merged as `47190652f436e80fa5dd0a947bc1ceeb6db709ff` after package, coordinated and Windows/macOS CI. Website action PRs #12/#13 passed renewed combined checks and merged. Gallery PR #20 merged as `d01cbfc24855d5e41adc6e092841554196a3e9cb` after full CI `34307438488`, consolidating and closing PRs #16/#17/#18. Its sole review finding incorrectly claimed the pnpm pin did not exist; the live official annotated tag and successful exact-head run establish otherwise, and the thread is resolved.\n\n## Core build dependencies and portability\n\nScoped overrides select js-yaml 4.3.2 for the [merge-key CPU advisory](https://github.com/advisories/GHSA-2883-xcg3-v3hh) and esbuild 0.28.2 for the [Windows development-server file-read advisory](https://github.com/advisories/GHSA-g7r4-m6w7-qqqr). Core CI now runs unfiltered `pnpm audit`. These are build dependencies; published core 0.7.0 and CLI 0.5.0 remain immutable and are not republished.\n\nThe CLI portability workflow uses the same reviewed immutable checkout 7.0.1, setup-node 7.0.0 and pnpm/action-setup 6.1.0 refs as package CI. `.gitattributes` preserves LF for text on Windows: CRLF checkout conversion changed indexed preview byte counts and prevented Markdown fenced-example discovery. Existing source text has no semantic changes. A fresh checkout applies this policy automatically.\n\nWindows Node 20 and 24 both pass core/CLI typechecks and complete tests: 406 core tests, composition/pagination/data/rich-text/list checks, 11 installer tests and 69 CLI command checks. Text/spec integrity and all 126 examples pass. Lint exits successfully with pre-existing warnings. The unfiltered workspace audit reports no known vulnerabilities. Full core tests now also run in the existing Windows/macOS portability matrix, making preview-byte and documentation-example checks repeatable on clean checkouts. A file-symlink case still requires Unix CI because this Windows account lacks that optional privilege; junction and other installer safety cases run locally.\n\nNode type declarations stay on the minimum supported runtime, Node 20. Dependabot PR #15 proposed Node 26 types and was closed with that rationale. Only routine major version updates for `@types/node` are limited, using `version-update:semver-major`; no dependency version or security advisory is ignored. Weekly minor/patch groups and separate security groups remain enabled. TypeScript 7 PR #16 is deferred because tsup's declaration bundler depends on removed legacy TypeScript APIs; the reproducible failure is recorded on the PR.\n\n## Schema generator major review\n\nPR #13 (`beb1e56f3755349cd03b5e78491e6f3eaac0a858`) changes json-schema-to-typescript 15 to 16. A direct comparison of all twelve generated type files finds eleven byte-identical files. `presentation.ts` removes the unrestricted string index signature from `ContentPayload` and adds a gradient-stop comment. The stricter content type agrees with the schema's existing `additionalProperties: false`, but may reject consumers that relied on the older declaration. Candidate core/CLI typechecks pass. Keep this major separate from the security patch; integration and consumer declaration compatibility must be reviewed before merging it into the next release. The current YAML override resolves the advisory without requiring that type API change.\n\n## Public application security deployments\n\n- Website PR #15: reviewed `592092d51ac9e7d1724c87851176d649add531dc`, merged `2f1b5428a06079e70f3ad67653768fa55a8c463c`. CI `34303539609` and Bugbot pass. Production `dpl_Bdxr6u3j6rdEjp9fJP9RbLp4f2pS` is READY on that merge and aliases both public domains. Four real Edge tests pass against `https://www.openpresentation.org`: complete skill files and copied installer command, published changelog, mobile layout and exact showcase downloads.\n- Gallery PR #19: reviewed `afec055b1f8361fd1b1d10fb5a0ec3e1a929f504`, merged `7d661c074a73dc81487a713a2af040246e62a097`. CI `34303548885` and Bugbot pass. Production `dpl_3GbDE7grPv3zCyCzfzhgAKuCuTsg` is READY on that merge. Two real Edge tests pass against `https://pptx.gallery`: deployed editor bundle hashes and JSON authoring, styled-table preview, inline edit/undo/redo, OPF download and reimport.\n\nBoth applications use Next.js 16.3.4 and have clean isolated audits. Gallery also uses patched Vitest 4.1.11 and js-yaml 3.15.2. For either checkout nested inside another pnpm workspace, use `pnpm audit --ignore-workspace` to audit its own lockfile. Do not use that flag in pptx.dev: its app, TypeScript SDK and CLI share a real root workspace.\n\npptx.dev PR #15 is merged and its production baseline is verified as recorded above. Its 591 unit tests and anonymous inspector browser flow pass on Linux and Windows, with SDK lockfile consolidation and the Next.js standalone/adapter fix included. The main preview/export still use custom implementations. Existing OPF browser tests, registry rendering tests and three-slide native PowerPoint evidence do not establish full browser PPTX coverage or broad native raster equivalence.\n\nPPTX 0.5.1 integrity: `sha512-iXUW3ex9fMunbTuk0L+3BCU32g5oHkuZ7JLXyeteRrW3BaVtK4xagN0/4AAh0htXOgRj1NT+412u5jCwQCHS8w==`. Fresh registry reports: [Node 20 fidelity](evidence/pptx-0.5.1/fidelity-node20.json), [Node 24 fidelity](evidence/pptx-0.5.1/fidelity-node24.json), [native source provenance](evidence/pptx-0.5.1/generation.json), [PowerPoint edit/reopen](evidence/pptx-0.5.1/native.json), [measured comparisons and reimports](evidence/pptx-0.5.1/comparison.json). Release verification now includes the installed vendor directory, and clean npm tests revalidate cached metadata so a just-published version is visible.\n"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"slug": "status-2026-09-15",
|
|
185
|
+
"file": "docs/status-2026-09-15.md",
|
|
186
|
+
"title": "OpenPresentation status \u2014 September 15, 2026",
|
|
187
|
+
"markdown": "# OpenPresentation status \u2014 September 15, 2026\n\nThe public JSON/slide demo and reusable authoring foundation are available.\nShared headers/footers are validated on main. Four unfinished shaping prototypes\nare preserved on remote archive branches and tracked in the roadmap; their\noriginal PRs conclude with documentation/evidence changes only.\n\nRead the [current handoff](handoff-2026-09-15.md),\n[next-agent prompt](next-agent-prompt-2026-09-15.md) and\n[developer adoption roadmap](plans/developer-adoption-20260915.md).\nEarlier dated checkpoints are historical evidence, not current release claims.\n\n| Area | Current state |\n| --- | --- |\n| Public demo | Home/playground support editable OPF JSON, live preview, preview edits back to JSON, contextual catalog choices and normal code-editor assistance. Appearance is preserved. |\n| Published packages | Core0.10.0, renderer0.8.0, editor0.7.0, PPTX0.8.0 and CLI0.8.0 were confirmed in the registry. This final cleanup publishes no additional versions. |\n| Developer foundation | Schemas/catalogs, six agent skills, contextual lint/contracts, source-preserving edits/undo, composition/pagination, preview and supported exports exist. Feature and platform limits apply. |\n| Shared headers/footers | Core79, renderer20, editor17 and PPTX34 are merged with passing main CI. This increment needs new coordinated versions and consumer adoption. |\n| Font shaping/prepared editing | Core83, renderer21, editor21 and PPTX35 retain complete prototypes on archive branches. Final PR diffs contain roadmap/evidence only. Linux native-width failures and an editor packed-test assertion remain recorded, not waived. |\n| Native PowerPoint | Acceptance is separately tracked in core issue87. Serialization and self-import do not certify Office. |\n| Production checks | Latest retained deployed checks passed 26 main-site, five gallery and ten pptx.dev workflows. See the handoff for commits/evidence. |\n\nThe original twenty-PR queue comprises eleven accepted dependency updates,\nfour accepted furniture increments, four roadmap-only conclusions and one\nclosed Node26-types update because the ecosystem targets Node24. Check the\nlinked PR states for final merge/check receipts; merging a roadmap does not\nrelease its archived prototype.\n\nNext: release the accepted increment, provide one independently installable\ndeveloper example with current API/version docs, and adopt shared behavior\nacross the public sites. Broader font/IME/bidi coverage, native Office evidence,\nlayout repair and full visual-editor coverage remain roadmap work. Selectable\nvector PDF and general SVG/Mermaid follow font reliability.\n"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"slug": "table-text-colors",
|
|
191
|
+
"file": "docs/table-text-colors.md",
|
|
192
|
+
"title": "Inherited table text colors",
|
|
193
|
+
"markdown": "# Inherited table text colors\n\nThe unpublished shared-metric integration branches use one core rule for inherited table text colors in SVG and editable PowerPoint cells. After resolving the cell fill, keep the inherited text color when its unrounded contrast is at least 4.5:1. Otherwise choose the higher-contrast black or white. This covers pale headers and dark body-cell fills without changing the source document.\n\nAn explicit cell `style.color` or rich-text run `color` remains authoritative, including a deliberately low-contrast color. Translucent fills and unresolved colors keep the inherited preference: their actual backdrop must be known before assessing contrast. This rule does not alter fills, borders, fonts, layout or metadata.\n\nCore exports `colorContrast(foreground, background)` and `textColorForFill(fill, preferred)` from its root and `/composition` entrypoints. They accept opaque hexadecimal `#RGB`, `#RRGGBB` and `#RRGGBBFF` colors. `colorContrast` returns `undefined` for unsupported or translucent colors. Callers must apply explicit text-color overrides before invoking the fallback.\n\nThe ratio uses [W3C's sRGB relative luminance definition](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html). Passing this narrow color check is not a WCAG certification, a readability guarantee, a browser/native raster equivalence result or an arbitrary PowerPoint round-trip claim. Source tests check actual SVG attributes and native OOXML text colors, including inherited and explicit rich-text colors. A separate six-slide real PowerPoint test passes on Node 20.20.2 and 24.20.0: all 48 original/reopened cell observations and 624 character-color observations match per runtime. Native rasters remain distinct evidence from browser rendering.\n"
|
|
146
194
|
}
|
|
147
195
|
]);
|
|
148
196
|
var docsRaw = docsData;
|