结构化模板执行分支深度解析:PPT Master 集成 —— ppt-master 的 Mirror / Layout 复用机制
本文聚焦 ppt-master(一个将文档或主题转化为原生 PowerPoint 演示文稿的开源项目)中 Executor 的 Structured Template Branch(结构化模板分支)。它服务于
template_reuse_scope: mirror|layout且pptx_structure.mode: structured的项目场景:当用户希望复用已有模板的母版(Master)、版式(Layout)、占位符(Placeholder)与原型拓扑时,该分支负责把锁定的模板契约落地为每个页面的 SVG 结构元数据,再由导出器编译成真正的 PowerPoint Master / Layout / Slide 图。读完本文,你将掌握镜像复用(mirror)与换肤复用(layout)两条执行路径的完整规则、结构化页面的根身份属性与槽位(slot)声明规范,以及与之配套的源码级校验与导出机制。
1. 分支定位:它执行的是"包结构",不是"信息结构"
executor-structured.md(位于 skills/ppt-master/references/executor-structured.md)是 Executor 的条件分支之一,由 executor-base.md 的触发表在 pptx_structure.mode: structured 时装载。
触发条件:锁(spec_lock.md)选择结构化模板复用,即 template_reuse_scope 为 mirror 或 layout,且 pptx_structure.mode 为 structured。
首要硬规则 —— 包结构,而非信息结构:该分支拥有可复用的 Master/Layout 原子、占位符、槽位与原型拓扑;而 executor-structure.md(Slide 局部定性构图语法)独立拥有页面局部的关系几何。两者互不蕴含:页面局部画了几个关系图形,绝不意味着项目就是 structured 模式;反之,结构化模式也不产生任何构图配额。
这一分工在 executor-structure.md 开篇再次强调:"不是结构化 PPTX:本分支拥有 Slide 局部几何;executor-structured.md 在 pptx_structure.mode: structured 下独立拥有可复用的 Master/Layout/占位符。" 因此阅读本分支时必须与 Slide 局部构图(拓扑决策、原生形状选择)区分开。
2. 模板复用规则总览(§1.0):上下文加载策略
在绘制任何一页之前,Executor 需要先加载模板上下文。原文档给出如下加载策略:
| 上下文 | 加载策略 |
|---|---|
templates/design_spec.md |
在有效上下文中复用;失效后与规划产物一起重读一次 |
| 当前页面映射 | 保留的 spec_lock.md page_layouts 行;页面变更无需重新加载文件 |
| 选定的原型 SVG | 每个有效上下文读取完整的 templates/<basename>.svg 一次,直到已知变更前一直复用 |
硬规则 —— 完整原型 SVG 是唯一权威:完整的 Slide 原型 SVG 已自行解析其 Master + Layout;独立的 Master/Layout 定义 SVG 无效;绝不允许基于花名册(roster)、清单(manifest)、旁车文件(sidecar)、文件名或摘要来创作。清单/文本槽文件只是工具元数据——它们的缺失既不使旧工作区失效,也不允许文本拓扑变更。
每页的原型直接从其 page_layouts 行解析:
mirror→ 进入 §1.1(要求工作区支持replication_mode: mirror);layout→ 解析P<NN>: <basename>,保留结构体系,应用下述换肤/重排规则;- 缺少行 → 停止(自适应模式仍需要一个选定的输入原型,且没有文件名/页面类型回退)。
映射变更:一旦映射发生变化,停止并返回 Strategist 更新计划,读回并校验,然后加载新原型。
默认 —— 对 layout 换肤(当应用计划保留模板视觉且锁反映该视觉时允许覆盖):继承几何、标签/图例位置与系列编码;从当前样式/锁重新绘制渐变、阴影、填充与描边。mirror 则按 §1.1 保留视觉。
硬规则 —— 字号是皮肤,不是几何(非 mirror):模板中硬编码的 font-size 一律不继承。必须根据 §IX 与当前备注构建每页的文本清单,将每个结构角色与可复用槽位(title、subtitle/lead、body、annotation、footnote/page_number、可复用的 hero 或强调槽位)映射到 spec_lock.typography 中声明的角色——缺少角色则返回上游,绝不使用数值相近的近似角色。放置文本前,选择锚点值或 ±2 px 范围内的一个值;只有 Slide 局部的非槽位 Hero/Display 元素才能使用 executor-base.md 的稀疏例外,可复用槽位永远不行。随后基于这些字号布局——行高、换行数、子元素 y/dy、卡片内边距与高度、列间距、图片/图表区域——并用有界的字号回流容器与局部几何,而不是从模板字号出发。不得重新分页、拆分或丢弃内容;值仍超出带宽则按 executor-base.md §2.1 返回上游。
从实现侧看,这一"字号是皮肤"规则与 svg-pipeline.md 中记录的导出行为互相印证:结构化导出中 Master 文本样式由 spec_lock.md 的 title/body 锚点生成——title 锚点映射到 Master p:titleStyle 的每个 a:defRPr@sz,body 锚点用于 p:bodyStyle 和 p:otherStyle 的 Level 1,层级 2–9 从 15/16 递减到 8/16 确定性推导。也就是说,结构化页面的文本大小在生成阶段就由锁驱动,模板自身的硬编码字号不会进入最终 Master 文本样式。
3. Mirror 复用 —— 字面页面替换(§1.1)
当锁记录 template_reuse_scope: mirror 时(工作区的 replication_mode: mirror 是前提,但不是触发器,也绝不会在锁说 layout 或 style 时强制镜像):
1. 每页引用:Strategist 已从 design_spec.md §V 描述中为每个项目页在 page_layouts 选择了一个镜像页(如 P04: 015_content)。
2. 复制,而非填充:从保留的完整镜像 SVG 出发,原地编辑幻灯片特定文本,逐字保留每个普通非文本元素和每个 data-pptx-* 结构属性;唯一例外是 JSON 优先的 Chart/Table——其标记 id/kind/authority 与元数据保留,而其派生预览可由该 JSON 重新生成。不要因另一页选择了同一路径而重新打开同一 path + SHA。
3. 可编辑范围:语义槽位映射与可见字符串值已由 <text>/<tspan> 节点承载(标题、正文、题注、KPI 标签、日期、页码)。保持每个文本节点的数量、顺序、嵌套与全部属性;绝不合并、拆分、在节点间移动字符串、添加 tspan 或删除空载体——检查器与导出会校验拓扑与原型哈希。
4. 不可触碰范围:位置、尺寸、字体、颜色、填充、描边、渐变、每个普通 <image> 指向哪张图、分组、精灵图 <svg viewBox> 包装器、装饰、<use data-icon> 标记、权威 Chart/Table JSON。href 路径不是图片本身:在 Step 3 迁移字节后,将裸的 href="cover_bg.png" 规范化为精确的 href="../images/<name>"——这是传输重写,不是视觉编辑。
5. 内容适配:当替换需要不同数量的分段或条目时,不要合并、拆分、丢弃或重构——报告 warning: P<NN> content does not fit mirror reference <basename>; choose another prototype or change template_reuse_scope to layout/style 并返回 Strategist。
6. 可见文本:镜像 SVG 可能携带字面源文本而非 {{...}} 标记;原地编辑,保留导入的 data-pptx-placeholder 身份与精确拓扑。
7. 输出文件名:标准的 <index>_<page_name>.svg,使用项目页索引;镜像文件名只是参考,不是输出名。
Chart/Table 与定性拓扑:镜像 SVG 内的图表、表格与定性拓扑已创作完成——只替换允许的文本,绝不从目录或语法重新绘制;JSON 优先对象可在 JSON 未变的情况下刷新其近似预览,不产生元数据、边界、标记、槽位或视觉漂移;镜像模板通常省略 page_visualizations,遗留的 page_charts 永不覆盖保真度。
遗留模板边界:pptx-structure-interface.md §3 定义的遗留契约(baseline/template/preserve 模式、layout_strategy、data-pptx-layout-kind、distilled/utility、直接原子占位符、不完整的根 Master 身份等)永远不是回退输入——停止;新工作区必须通过 create-template.md 创建。
每页绘制前的必选输出:
📝 **Template mapping**: `templates/03a_content_image_text.svg`(自由设计路由可用 "None")
🎯 **Adherence rules / application plan**: [具体描述]
内容页:模板只定义页眉/页脚,内容区自由。只有自由设计或品牌专属路由才允许无模板。
从源码侧看,镜像创建由 mirror_template_materialize.py 支撑,其产物为 ppt-master.template-execution-manifest.v1 与每个原型一份 ppt-master.template-text-slots.v2-min 旁车;svg-pipeline.md 明确指出"清单/文本槽文件是工具元数据",这正与 §1.0 的硬规则一致——缺失这些文件既不会使旧工作区失效,也不构成文本拓扑变更的依据。
4. PowerPoint Master / Layout 映射(§1.2)
仅在锁记录 template_reuse_scope: mirror|layout 时应用:page_layouts 选择输入原型,pptx_masters/pptx_layouts 声明唯一可复用的输出定义,page_pptx_layouts 在绘制第一页之前为每一页分配。style、自由设计与品牌专属路由使用 mode: flat,省略全部四个 section,所有对象保持 Slide 局部。
每个结构化页面必须满足的元数据契约(根身份属性、原子固定层、绘制顺序、槽位形式及其 object+proxy 复合、背景归属、文本载体)定义在 pptx-structure-interface.md §2;遗留契约按该文件 §3 拒绝。本分支决定每页声明什么:
硬规则 —— 根身份(root identity):一条 page_pptx_layouts 行将页面绑定到一个 pptx_layouts 键,该键提供其 Master 键、Layout 选择器名称与原型来源;在根 <svg> 上写出 Master 键/名称与 Layout 键/名称。该 Master 的每一页重复相同的有序 Master 原子契约,共享 (master, layout) 的每一页重复相同的 Layout 原子契约。
必选 —— 每页槽位覆盖:为页面实际拥有的每个标准角色声明槽位——标题 title、封面标语 subtitle、页码 slide-number、运行页脚 footer、hero/内容图片 picture、一个合并正文框 body;零槽位仅对真正固定的构图有效,绝不能作为默认;共享同一键的页面输出相同槽位集合。
硬规则 —— 可变内容:页面变化的文本或图片必须由槽位承载或保持 Slide 局部,绝不做成固定 Layout 原子。
必选 —— 层覆盖(layer coverage):将全册背景与每页 chrome(页脚条、运行 logo)标记为 master;将定义该键构图的静态框架(页眉规则、分隔带、区域面板、内容页重复但封面缺失的 chrome)标记为 layout;零标记的页面导出为裸 Master 与空 Layout。
Layout 身份与遵守:键仅在固定原子或槽位拓扑/默认边界/绑定模式上不同——措辞、图像、裁剪或 Slide 局部几何的差异不构成新键;相同契约共享一个键。strict 保留原子与槽位 id/类型/索引/边界/绑定(layout 仍可在这些边界内更改当前文本/tspan、行高、裁剪与载体局部几何;mirror 拓扑冻结);adaptive 保留原型 Master,仅实现锁中已声明的 Layout 定义与分配。需要改变原子或槽位拓扑时停止页面,返回 Strategist 声明新键、更新定义与分配并校验;仅内容变化永不算新 Layout。只把真正可复用的固定框架标记为原子——标题、正文、指标、图表标记、图片与页面专属组留在槽位或 Slide 局部组中;导出器永不推断结构。
源码实现侧,template_structure.py 定义了这些数据模型的形态:PptxLayoutDefinition(layout_key/master_key/layout_name)、PptxMasterReference、PptxPageLayoutAssignment(page 到 layout_key 的分配),以及 TEMPLATE_REUSE_SCOPES = {"mirror", "layout", "style"} 与 PPTX_STRUCTURE_MODES = {"structured", "preserve", "flat"} 两个枚举常量——structured 之外的值都会被拒绝,这与"mode 必须是 structured(其他任何值都被拒绝——创建新工作区,绝不迁移)"的规则一一对应。
5. 每页结构化查找(§2):page_layouts 与 page_pptx_layouts
page_layouts(仅 mirror/layout):绘制前读取页面行(如 P04: 03a_content_image_text),在选定模板目录中解析完整 SVG(§1.0 决定是读取还是复用;reference_set 指纹可诊断不确定路径,但非必需)。basename 必须匹配真实文件——否则停止并报告无效映射;strict 与 adaptive 都不回退到自由设计。行缺失或 mirror|layout 下 section 缺失会以上游契约错误停止;style 下该 section 必须缺席。绝不因 templates/ 存在而发明条目或假设结构。
page_pptx_layouts(仅 mirror|layout):flat(包括 style)下跳过本项与脚手架,pptx_masters、pptx_layouts、page_layouts 与元数据全部缺席,每个根声明 data-pptx-page-role。否则 mode 必须是 structured;读取 P<NN>: <layout_key>,在 pptx_layouts 中解析该键、在 pptx_masters 中解析其 Master(缺失或不完整映射停止),写出匹配的根键与选择器名称,不写 data-pptx-layout-kind 或 data-pptx-page-role。strict 精确匹配原型;adaptive 保留 Master 并实现已声明的 Layout,原子或槽位必须变化时停止并返回上游。一个键只有在原子与槽位完全相同时才可在非相邻页面重复。
5.1 结构化页面 SVG 骨架示例
原文档给出的完整示例是理解该契约的最佳入口:
<svg viewBox="…"
data-pptx-master="<master-key>" data-pptx-master-name="<master-name>"
data-pptx-layout="<layout-key>" data-pptx-layout-name="<layout-name>">
<rect id="master-bg" data-pptx-layer="master" …/> <!-- 一个原子 Master 对象 -->
<text id="master-footer" data-pptx-layer="master" …>…</text> <!-- 无 Master/Layout g -->
<path id="layout-rule" data-pptx-layer="layout" …/> <!-- 一个原子 Layout 对象 -->
<g id="title-slot" data-pptx-placeholder="title" data-pptx-bounds="60 36 1160 64">
<text id="title-carrier" data-pptx-carrier="true" …>…</text>
</g>
<g id="body-slot" data-pptx-placeholder="body" data-pptx-idx="1" data-pptx-bounds="60 120 470 500">
<text id="body-carrier" data-pptx-carrier="true" …>…</text>
</g>
<g id="picture-slot" data-pptx-placeholder="picture" data-pptx-idx="2" data-pptx-bounds="570 120 650 500">
<image id="picture-carrier" data-pptx-carrier="true" …/>
</g>
<g id="content-block-1" data-pptx-bounds="60 120 470 500">…</g> <!-- 每个逻辑内容单元一个组 -->
<g id="content-block-2" data-pptx-bounds="570 120 650 500">…</g>
</svg>
关键结构约束:Master/Layout 原子与槽位组是根的直接子元素,位于普通内容组之前;嵌套在内容组内的结构元数据会导致导出失败。Flat 页面只使用普通顶层语义组。
5.2 元数据属性速查
结合 pptx-structure-interface.md §2 的完整属性表,结构化页面可用的核心元数据包括:
| 属性 | 位置 | 行为 |
|---|---|---|
data-pptx-master="master-default" |
根 <svg> |
将幻灯片绑定到一个生成的 Slide Master 键 |
data-pptx-master-name="Default Master" |
根 <svg> |
Master 选择器/显示名 |
data-pptx-layout="content" |
根 <svg> |
绑定到一个生成的可复用 Layout 键 |
data-pptx-layout-name="Title and Content" |
根 <svg> |
Layout 选择器名;默认取自 Layout 键 |
data-pptx-show-master-shapes="false" |
根 <svg> |
可选,必须小写 true/false;共享该键的每个 SVG 重复相同值;省略视为 true |
data-pptx-show-inherited-shapes="false" |
根 <svg> |
可选;此 Slide 的 showMasterSp——false 隐藏继承形状而不移除背景、占位符、部件或父级;省略视为 true |
data-pptx-layer="master"/"layout" |
直接语义原子 | 将一个重复静态对象/背景移入 Master 或选定 Layout;普通 <g> 被禁止,校验过的紧凑作者预设 <g> 是唯一原子例外 |
data-pptx-layer="slide" |
直接全画布实心 <rect> 仅 |
一页背景覆盖,写成 Slide p:bg |
data-pptx-placeholder="..." |
直接槽位 <g id> |
可复用 Layout 槽位,其可见内容保持 Slide 局部 |
data-pptx-bounds="x y width height" |
槽位 <g> |
必选的正设计区框架,SVG 用户单位,每值最多两位小数 |
data-pptx-idx="1" |
槽位 <g> |
保留导入的源占位符索引;重建布局时可选 |
data-pptx-carrier="true" |
普通槽位的一个兼容直接子元素 | 将该可见子元素绑定为真正的 Slide 占位符载体 |
data-pptx-binding="proxy" |
复合 object 槽位 <g> 仅 |
保持可见组普通,并创建一个隐藏透明绑定代理 |
data-pptx-editable="false" |
master/layout 元素或幻灯片背景 | 声明在普通幻灯片内容之外的有意编辑 |
占位符值与 PowerPoint 占位符的对应关系:title/subtitle/body → 一个 <text data-pptx-carrier="true"> → title/subTitle/body;date/footer/slide-number → dt/ftr/sldNum;picture/media → 标记为载体的 <image> 或受支持的导入裁剪 <svg> → pic/media;chart/table → 标记为载体的匹配 data-pptx-replace-with 标记组(需要 --native-charts-and-tables)→ chart/tbl;object → 标记为载体的文本、图片、基础 SVG 形状或校验过的紧凑作者预设 <g>,或声明 binding="proxy" → obj。
显式仅限(explicit only)硬规则:结构化路由下每个 SVG 都携带四个根身份属性;每个 Master/Layout 原子与槽位都是带唯一稳定 id 的根直接子元素;data-pptx-layout-kind、distilled、utility 是遗留物,直接失败。id 标识元素;data-pptx-layer(而非 id)决定归属;同一 Master/Layout 契约下不同页面可重复同一固定原子 id。未标记的内容是 Slide 局部的。
层序(layer order):按 PowerPoint 绘制顺序创作——Master 背景、Layout 背景、可选 Slide 背景、其余 Master 原子、其余 Layout 原子、然后是槽位组与 Slide 局部内容。背景是每个形状下方的继承面;保持此顺序使 SVG 预览与 PowerPoint 渲染一致。
实心背景归属:只有直接全画布实心 <rect> 才能拥有有作用域的背景——layer="master" 为全册默认、layer="layout" 为同一设计语言下的页型变体、layer="slide" 为单页覆盖;Layout 覆盖 Master,Slide 覆盖两者。渐变/图案矩形、纹理、变换矩形与可见描边矩形保持为已声明层上的普通形状或 Slide 局部;图片保持为图片。
槽位边界:data-pptx-bounds 从设计区、列、面板内边距、安全区或图片框推导——绝不从文本长度、字形宽度、行数或紧凑内容框推导。同一 Layout 的每张幻灯片重复相同的槽位 id/类型/有效索引/默认边界/绑定模式;Slide 内容与局部载体几何可不同于默认框。
6. 检查器与导出器如何强制执行结构化契约
结构化契约不只是文档约定——svg_quality_checker.py 在模板模式下逐条校验作者形态(validate_structured_svg_shape 路径):
- 根身份完整:结构化 SVG 根必须携带全部根结构属性,缺失任何一个即报
structured SVG root is missing ...; - 根可见性属性:
data-pptx-show-master-shapes等必须是精确的true/false; - 根级独占:根结构/可见性元数据只允许出现在根元素上,嵌套元素携带即报错;
- 遗留属性拒绝:
data-pptx-layout-kind直接报legacy distillation attribute; restore the page to the structured contract; - 原子层约束:
data-pptx-layer="master|layout"元素必须是根的直接子元素;<g>标记为 master/layout 但非作者预设原子时报错;同一元素不能既是固定层又是占位符槽位; - 槽位约束:占位符槽位必须是根级
<g>、必须有稳定id、只能携带id与data-pptx-*属性(其他包装属性报错)、必须有合法正边界data-pptx-bounds、载体必须是直接子元素; - 载体与绑定:proxy 槽位不得声明可见载体,普通槽位必须恰有一个兼容载体。
这与原文档"Master/Layout 原子和槽位组是根的直接子元素"、"普通 <g> 被禁止"的规则完全一致——检查器是这些规则的机器化执行者。
导出侧,svg-pipeline.md 记录:结构化导出创建一个可复用 Layout 键,并重新打开包验证完整的 Presentation → Master → Layout → Slide 图、固定对象顺序、占位符身份/边界、载体绑定、隐藏代理与零槽位 Layout;图或注册不匹配则中止发布。命令示例:
python3 skills/ppt-master/scripts/svg_to_pptx.py <project_path> --pptx-structure structured
默认导出(省略 --pptx-structure)则读取 spec_lock.md:自由设计、品牌专属与 template_reuse_scope: style 声明 mode: flat,省略 Master/Layout 映射与 SVG 结构元数据,从当前锁物化一个干净的项目自有 Master 加一个 Blank Layout。
7. 与 Flat 模式的边界及工作区创建前提
结构化与 flat 是互斥的确定路由:pptx-structure-interface.md §1 的路由表规定——自由设计、品牌专属、template_reuse_scope: style 项目使用 mode: flat,不写 pptx_masters/pptx_layouts/page_pptx_layouts/page_layouts,导出物化一个干净的项目自有 Master 加一个 Blank Layout,所有对象保持 Slide 局部;Layout/Deck 模板且 template_reuse_scope: mirror|layout 时使用 structured。
无结构推断硬规则:flat 导出不提升、不去重任何内容;结构化导出只编译声明的根身份、原子固定层与槽位组——绝不指派 Layout 族、聚类页面、推断占位符、修复缺失元数据或迁移遗留契约。遗留模式项目(携带 analysis/native_structure.json/sources/source.pptx、pptx_structure.mode: baseline|template|preserve、layout_strategy、data-pptx-layout-kind、distilled/utility、直接原子占位符或不完整根 Master 身份)不是生成/导出输入,也不会就地升级——必须通过 create-template.md 创建新的当前工作区(standard/fidelity/mirror 三种策略按输入证据选择),再让 Generate Step 6 在新的 svg_output/ 中创作结构化页面,由导出器只编译那些声明。
对于想落地一套"以自己 .pptx 为模板、保留母版版式、让每页内容可编辑"流程的读者,推荐路径是:pptx_template_import.py 导入 → create-template 工作流创建 mirror/layout 工作区 → 生成结构化 SVG 页面(根身份 + 层 + 槽位)→ svg_quality_checker.py --template-mode 校验 → svg_to_pptx.py --pptx-structure structured 导出并重开包验证图。这条链路中,本分支(executor-structured.md)是每页元数据声明的行为规范,检查器与导出器是其机器化执行者,二者共同保证最终 .pptx 中的 Master/Layout/Slide 结构与 SVG 源完全对应。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00