| 1 | # Execution Lock Structure |
| 2 | |
| 3 | `spec_lock.md` projects cross-page anchors/routes from audited `design_spec.md` and context; it excludes local paint/type. This file owns structure; [`schemas/spec_lock.schema.json`](./schemas/spec_lock.schema.json) owns grammar. |
| 4 | |
| 5 | ## 1. Author the complete artifact |
| 6 | |
| 7 | After Generate Step 4 Gate 1, read the completed Design Spec and current page/resource/template context, compose the entire lock in active context, then create `<project_path>/spec_lock.md` once. |
| 8 | |
| 9 | **Mandatory — new-project write**: The first non-empty line is exactly `<!-- ppt-master-schema: spec-lock/v1 -->`, followed by `# Execution Lock`. Write only final sections and values; do not create a blank lock, copy inactive optional sections, or patch scaffold placeholders. Do not reopen final confirmation or interpret it independently. |
| 10 | |
| 11 | `project_manager.py scaffold-lock` remains an optional manual convenience and overwrite-safe troubleshooting tool. It is not part of normal Generate authoring. When a credible completed Design Spec/lock pair needs correction, repair only the affected projection after auditing the Design Spec. When the Design Spec was missing and an orphan lock survived, discard that lock as authority and re-author the complete lock from the recovered, audited Design Spec plus current context. |
| 12 | |
| 13 | **Hard rule**: A project lock contains only `##` sections and `- key: value` data lines, except `## forbidden`, whose list items are literal rules. Do not copy guidance paragraphs into the lock. |
| 14 | |
| 15 | --- |
| 16 | |
| 17 | ## 2. Base sections |
| 18 | |
| 19 | | Section | Required keys | Notes | |
| 20 | | --- | --- | --- | |
| 21 | | `canvas` | `viewBox`, `format` | `format` is the canonical display name (for example `PPT 16:9`); `viewBox` is the matching exact geometry | |
| 22 | | `communication` | `primary_language`, `audience`, `objective`, `core_message` | New lock: canonical BCP-47; old lock may omit it. Reject `und` and Chinese without script/region. `objective` merges intent/outcome; `consumption_mode` is optional off PPT | |
| 23 | | `mode` | `mode` | Preset or `custom` | |
| 24 | | `visual_style` | `visual_style` | Preset or `custom` | |
| 25 | | `colors` | Stable semantic color roles | Core identity and recurring roles only; contextual SVG paints need no row; `image_rendering` appears only for AI images | |
| 26 | | `typography` | `font_family`, `body`, `title` | Core family/size anchors; new locks also write explicit `title_family` and `body_family`; size anchors are unitless px numbers | |
| 27 | | `icons` | `library`, `inventory` | `library` is the Strategist's primary bundled style choice or `none`; content-driven `simple-icons/*` may be prepared alone or accompany it; `inventory` indexes the curated synced SVG pool rather than page usage or all usable project-local icons; `stroke_width` is conditional | |
| 28 | | `page_rhythm` | One `P<NN>` row per page | Values: `anchor`, `dense`, `breathing` | |
| 29 | | `pptx_structure` | `mode` | Values: `flat`, `structured` | |
| 30 | | `forbidden` | Literal list items | General standards stay in their owning reference | |
| 31 | |
| 32 | Optional data sections: `images`, `page_visualizations` (Chart/Table only). New locks never write |
| 33 | legacy `page_charts`; existing locks may retain it for read-only compatibility. |
| 34 | Never declare the same page in both sections. |
| 35 | |
| 36 | The required universal block is: |
| 37 | |
| 38 | ```markdown |
| 39 | ## forbidden |
| 40 | - `mask`, `<style>`, `class`, external CSS, `<foreignObject>`, `textPath`, `@font-face`, `<animate*>`, `<set>`, `<script>` / event attributes, `<iframe>` |
| 41 | - HTML named entities in text; write typography as raw Unicode and escape XML reserved characters |
| 42 | ``` |
| 43 | |
| 44 | --- |
| 45 | |
| 46 | ## 3. Conditional sections and fields |
| 47 | |
| 48 | | Trigger | Required addition | |
| 49 | | --- | --- | |
| 50 | | `mode.mode: custom` | `mode_behavior` in `mode`; optional `mode_references` only when catalog modes are actually used | |
| 51 | | `visual_style.visual_style: custom` | `visual_style_behavior` in `visual_style`; optional `visual_style_references` only when catalog styles are actually used | |
| 52 | | `colors.image_rendering: custom` | `image_rendering_behavior` in `colors`; optional `image_rendering_references` only when catalog renderings are actually used | |
| 53 | | `icons.library: tabler-outline` | `stroke_width: 1.5`, `2`, or `3` | |
| 54 | | `pptx_structure.mode: structured` | `template_reuse_scope: layout\|mirror`, `template_adherence`, plus `pptx_masters`, `pptx_layouts`, `page_pptx_layouts`, and `page_layouts` | |
| 55 | | `pptx_structure.template_reuse_scope: mirror` | `mode: structured` and `template_adherence: strict` | |
| 56 | | `pptx_structure.template_reuse_scope: style` | `mode: flat`; omit structured mapping sections | |
| 57 | | `pptx_structure.mode: flat` | Omit all four structured mapping sections | |
| 58 | |
| 59 | Structured section value shapes: |
| 60 | |
| 61 | ```markdown |
| 62 | ## pptx_masters |
| 63 | - master-default: Default Master |
| 64 | |
| 65 | ## pptx_layouts |
| 66 | - content-two-column: master-default | Two Column | template:03_content |
| 67 | |
| 68 | ## page_pptx_layouts |
| 69 | - P01: content-two-column |
| 70 | |
| 71 | ## page_layouts |
| 72 | - P01: 03_content |
| 73 | ``` |
| 74 | |
| 75 | Project each §VII Page/Family/Template into at most one |
| 76 | `page_visualizations` `<chart|table>/<key>` row per page; Usage, children, |
| 77 | no-match, and qualitative relationships stay in §IX. Resolve the reference to |
| 78 | one live SVG. It locks neither type, geometry, nor native output. |
| 79 | |
| 80 | ```markdown |
| 81 | ## page_visualizations |
| 82 | - P03: chart/line_chart |
| 83 | - P09: table/record_table |
| 84 | ``` |
| 85 | |
| 86 | **Legacy compatibility**: keep existing `page_charts` bare keys. Live |
| 87 | Chart/Table keys resolve unambiguously through two registries; retired Structure |
| 88 | keys are semantic-only, have no SVG, and rely on §IX (repair upstream when |
| 89 | insufficient). New locks write `page_visualizations`; dual page declarations |
| 90 | conflict even when they resolve alike. |
| 91 | |
| 92 | Typography projection excludes Character/upgrade References: |
| 93 | |
| 94 | | Design Spec §IV declaration | `spec_lock.md` field | |
| 95 | | --- | --- | |
| 96 | | Title font stack | `title_family` | |
| 97 | | Body font stack | `body_family` and compatibility/default `font_family` | |
| 98 | | Any additional recurring font role `<role>` | `<role>_family` | |
| 99 | | Every Font Size Hierarchy role `<role>` | lowercase `<role>` with its numeric anchor | |
| 100 | |
| 101 | New locks always write `title_family` and `body_family`, even when their values happen to match. Every additional recurring family row and every size-anchor row in the Design Spec must appear under the same lowercase snake_case role; omit only family roles that inherit without an explicit override. Existing locks without family-role fields remain readable through `font_family` fallback. Executor may choose the anchor or a value within that role's `±2px` band; the lock does not enumerate intermediate values. A short non-structural Hero/Display size may remain absent only while the same undeclared value appears at most twice across the deck; its third occurrence requires a named role. |
| 102 | |
| 103 | --- |
| 104 | |
| 105 | ## 4. Field Grammar Index |
| 106 | |
| 107 | - `font_family`, `title_family`, `body_family`, and every optional `<role>_family` use one non-empty PPT-safe exported family stack. `font_family` is the body/default compatibility stack, not permission to erase role differences. |
| 108 | - Every non-family `typography` value is a positive finite unitless px anchor. Intermediate values need no lock row when they stay within the mapped role's anchor `±2px`. At most two occurrences of one undeclared short non-structural Hero/Display size may remain sparse; a third occurrence or any structural use requires Design Spec repair and a named anchor. |
| 109 | - `icons.library` records the primary stylistic library selected from `chunk-filled`, `tabler-filled`, `tabler-outline`, or `phosphor-duotone`, or `none` when no generic bundled icons are selected. Content-driven `simple-icons/*` brand marks may appear alone or alongside it in `inventory` without becoming a stylistic library or a separate confirmation choice. The inventory indexes the curated synced SVG pool without assigning page usage; every SVG already under `<project_path>/icons/` remains valid prepared execution material. Illustrated-icon slices create no icon-lock field: their exact paths belong under `images`, and the unplaced parent sheet stays out of the lock. |
| 110 | - `objective` grammar: one concise sentence preserving the deck goal and audience success condition. |
| 111 | - `image_rendering` grammar: one catalog id, or `custom` with `image_rendering_behavior`. |
| 112 | - `images`: `- <key>: <path> | source=<via> | pattern=<layout> | crop=<adaptive|no-crop>`; e.g. `- p04: images/a.png | source=user | pattern=full-height image beside the evidence | crop=no-crop`. Use the canonical `images/<filename>` path; `source` and `crop` exactly project §VIII, while `pattern` preserves its non-empty normalized free-form suggestion and any optional hierarchical catalog ids. The pattern remains a recommendation for Executor recall that may be adopted, adapted, or declined, not a geometry or realization lock. Omit unplaced sheets. |
| 113 | - Custom reference grammar: comma-separated exact catalog ids with no duplicates. Reference fields are valid only for `custom`; omit them for a genuinely novel direction. |
| 114 | - `stroke_width` grammar: `1.5`, `2`, or `3`; present only for `tabler-outline`. |
| 115 | - `page_rhythm` grammar: `P` + at least two digits (`P01`, `P100`) followed by `anchor|dense|breathing`. |
| 116 | - `page_visualizations` grammar: `P` + at least two digits followed by |
| 117 | `chart|table`, `/`, and one canonical visualization key; the family/key must |
| 118 | resolve to one SVG through the matching live index. |
| 119 | - Legacy `page_charts` grammar: `P` + at least two digits followed by one bare |
| 120 | key. Chart/Table resolves uniquely across two registries; retired Structure |
| 121 | is semantic-only. Never add this section to a new lock. |
| 122 | - `pptx_masters` grammar: `<master_key>: <PowerPoint picker name>`. |
| 123 | - `pptx_layouts` grammar: `<layout_key>: <master_key> | <PowerPoint layout name> | <prototype source>`. |
| 124 | - `page_pptx_layouts` grammar: `P` + at least two digits followed by a declared Layout key. |
| 125 | - `page_layouts` grammar: `P` + at least two digits followed by a template SVG basename. |
| 126 | |
| 127 | Catalog-based custom example: |
| 128 | |
| 129 | ```markdown |
| 130 | ## mode |
| 131 | - mode: custom |
| 132 | - mode_references: pyramid, narrative, instructional |
| 133 | - mode_behavior: Open conclusion-first with pyramid, develop the risk through a narrative tension-and-resolution act, then close with an instructional action sequence. |
| 134 | ``` |
| 135 | |
| 136 | --- |
| 137 | |
| 138 | ## 5. Machine Validation |
| 139 | |
| 140 | ```bash |
| 141 | python3 skills/ppt-master/scripts/project_manager.py validate <project_path> |
| 142 | ``` |
| 143 | |
| 144 | Validation reports unresolved `[fill...]` placeholders, wrong casing, unknown sections or fields, illegal enums, malformed page keys, missing catalog assets, broken structured-layout references, and unmet conditions. It neither rewrites the lock nor checks semantic projection; Generate Step 4 Gate 2 owns that check. |
| 145 | |
| 146 | Field meaning and selection logic stay in the owning Strategist modules. Executor branch references own consumption behavior. The schema owns only artifact grammar and structural conditions. |
| 147 | |
| 148 | ## 6. Anchor and extension semantics |
| 149 | |
| 150 | - Confirmed core palette roles and every declared typography family/size role remain stable cross-page anchors. |
| 151 | - Page-local tints, gradient stops, shadow/glow paints, transparency composites, and one-off export-safe display families may be authored from context without adding a lock row. |
| 152 | - Executor may adjust one occurrence within its declared size role's anchor `±2px` while preserving hierarchy and readability; intermediate values are realization choices, not new lock rows. |
| 153 | - When a contextual value becomes a recurring semantic role, or one undeclared display size reaches its third occurrence, add the descriptive role, read back and validate affected planning fragments, then reuse it. Structural typography outside its applicable anchor band returns upstream immediately. |
| 154 | - Do not expand the lock merely to make an informational checker comparison empty. A lock edit should express reuse or identity, not enumerate incidental literals. |
| 155 |